(*Description...
The Moving Average Contest
This script demonstrates usage, performance and differences of some moving averages.
When smoothing data here is always a trade-off between lag and removal of noise. This scripts shows several moving averages, all adjusted to produce the same lag.
The upper pane shows price info along with all moveing averages. The respective period used is printed after the moving average's name. The periods are adjusted to produce the same lag.
The lower pane shows the "speed" of the price-movement calculated from the respective moving average. The speed is also known as "momentum" which is a great misnomer. In any case it is the first derivative with respect to time, calculated as difference between adjacent values.
The speed calculation amplifies the higher frequency components (by 6 dB per Octave) and is thus very sensitive to the filter properties of the moving averages. A smooth speed curve is clearly preferable.
Results
While the three pole butterworth shows the smoothest speed curve and thus the best attenuation of unwanted higher frequencies it also shows some additional lag in cases of fast price movement.
The favorite seems to be the gaussian filter with 4 poles. He has a consistently low lag and a very
smooth speed curve.
Please note: Most Trading System use SMA, WMA or EMA moving averages to smooth out any high frequency noise. This script clearly demonstrates that these are not the best choices at all.
These averages often come in disguise. A ROC(41) for example is equivalent to Momentum(SMA(41)) (plus some scaling) which is shown in the lower pane. If you look at the "speed of SMA" curve you will certainly want to switch to something better.
References
Description of Code Library Item "Butterworth"
Description of Code Library Item "Gaussian"
John F. Ehlers: "Rocket Science For Traders, Digital Signal Processing Applications"
*)
{$I 'Gaussian'}
{$I 'Butterworth'}
var ema_s, bw2_s, bw3_s: integer; // series
var ema_m_s, bw2_m_s, bw3_m_s: integer; // series
var sma_s, wma_s: integer; // series
var sma_m_s, wma_m_s: integer; // series
var gs1_s, gs2_s, gs3_s, gs4_s: integer; // series
var gs1_m_s, gs2_m_s, gs3_m_s, gs4_m_s: integer; // series
var Lag: Float;
var per_gs1, per_gs2, per_gs3, per_gs4, per_bw2, per_bw3: float;
var per_sma, per_ema, per_wma: integer;
Lag := 20; // Test for 10 Bars Lag
// Smoothed Prices
// Gaussian: Lag = N * P / (2 * Pi^2)
// --> P := Lag * 2 * Pi^2 / N
per_gs1 := Lag * 2 * Pi * Pi / 1;
gs1_s := GaussianSeries(#Open, per_gs1, 1);
per_gs2 := Lag * 2 * Pi * Pi / 2;
gs2_s := GaussianSeries(#Open, per_gs2, 2);
per_gs3 := Lag * 2 * Pi * Pi / 3;
gs3_s := GaussianSeries(#Open, per_gs3, 3);
per_gs4 := Lag * 2 * Pi * Pi / 4;
gs4_s := GaussianSeries(#Open, per_gs4, 4);
// Butterworth: Lag = N * P / Pi^2
// --> P := Lag * Pi^2 / N
per_bw2 := Lag * Pi * Pi / 2;
bw2_s := Butterworth2Series(#Open, per_bw2);
per_bw3 := Lag * Pi * Pi / 3;
bw3_s := Butterworth3Series(#Open, per_bw3);
// SMA Lag := (p-1)/2
// --> P := 2*Lag + 1
per_sma := Round(2 * Lag + 1);
sma_s := SMASeries(#Open, per_sma);
// WMA Lag := (p-1)/3
// --> P := 3*Lag + 1
per_wma := Round(3 * Lag + 1);
wma_s := WMASeries(#Open, per_wma);
// EMA:
// P := (-2.0 * Pi) / LN(1 - (1 / (Lag +1)))
per_ema := Round(-2.0 * Pi / LN(1.0 - 1.0 / (Lag + 1)));
ema_s := EMASeries(#Open, Round(per_ema));
// Speed
bw2_m_s := MomentumSeries(bw2_s, 1);
bw3_m_s := MomentumSeries(bw3_s, 1);
gs1_m_s := MomentumSeries(gs1_s, 1);
gs2_m_s := MomentumSeries(gs2_s, 1);
gs3_m_s := MomentumSeries(gs3_s, 1);
gs4_m_s := MomentumSeries(gs4_s, 1);
sma_m_s := MomentumSeries(sma_s, 1);
wma_m_s := MomentumSeries(wma_s, 1);
ema_m_s := MomentumSeries(ema_s, 1);
// Graphics
var SpeedPane: integer; // pane
HideVolume;
// Title
DrawText( 'Fixed Lag = ' + FormatFloat('#', Lag),
0, 300, 4, #Black, 20 );
SpeedPane := CreatePane( 100, false, true );
DrawText( 'Butterworth, 2 poles P=' + FormatFloat('###.#', per_bw2),
0, 4, 4, 060, 12 );
PlotSeries( bw2_s, 0, 060, #Thin );
DrawText( 'Butterworth, 3 poles P=' + FormatFloat('###.#', per_bw3),
0, 4, 20, #Green, 12 );
PlotSeries( bw3_s, 0, #Green, #Thin );
DrawText( 'Gaussian, 1 pole P=' + FormatFloat('###.#', per_gs1),
0, 4, 36, 099, 12 );
PlotSeries( gs1_s, 0, 099, #Thin );
DrawText( 'Gaussian, 2 poles P=' + FormatFloat('###.#', per_gs2),
0, 4, 52, 059, 12 );
PlotSeries( gs2_s, 0, 059, #Thin );
DrawText( 'Gaussian, 3 poles P=' + FormatFloat('###.#', per_gs3),
0, 4, 68, 005, 12 );
PlotSeries( gs3_s, 0, 005, #Thin );
DrawText( 'Gaussian, 4 poles P=' + FormatFloat('###.#', per_gs4),
0, 4, 84, #Black, 12 );
PlotSeries( gs4_s, 0, #Black, #Thick );
DrawText( 'SMA P=' + FormatFloat('###.#', per_sma),
0, 4, 100, 933, 12 );
PlotSeries( sma_s, 0, 933, #Thin );
DrawText( 'WMA P=' + FormatFloat('###.#', per_wma),
0, 4, 116, #Red, 12 );
PlotSeries( wma_s, 0, #Red, #Thin );
DrawText( 'EMA P=' + FormatFloat('###.#', per_ema),
0, 4, 132, 500, 12 );
PlotSeries( ema_s, 0, 500, #Thick);
// Speed
DrawText( 'Speed',
SpeedPane, 300, 4, #Black, 20 );
DrawText( 'Butterworth, 2 poles', SpeedPane, 4, 4, 060, 12 );
PlotSeries( bw2_m_s, SpeedPane, 060, #Thin );
DrawText( 'Butterworth, 3 poles', SpeedPane, 4, 20, #Green, 12 );
PlotSeries( bw3_m_s, SpeedPane, #Green, #Thin );
DrawText( 'Gaussian, 1 pole', SpeedPane, 4, 36, 099, 12 );
PlotSeries( gs1_m_s, SpeedPane, 099, #Thin );
DrawText( 'Gaussian, 2 poles', SpeedPane, 4, 52, 059, 12 );
PlotSeries( gs2_m_s, SpeedPane, 059, #Thin );
DrawText( 'Gaussian, 3 poles', SpeedPane, 4, 68, 005, 12 );
PlotSeries( gs3_m_s, SpeedPane, 005, #Thin );
DrawText( 'Gaussian, 4 poles', SpeedPane, 4, 84, #Black, 12 );
PlotSeries( gs4_m_s, SpeedPane, #Black, #Thick );
DrawText( 'SMA', SpeedPane, 4, 100, 933, 12 );
PlotSeries( sma_m_s, SpeedPane, 933, #Thin );
DrawText( 'WMA', SpeedPane, 4, 116, #Red, 12 );
PlotSeries( wma_m_s, SpeedPane, #Red, #Thin );
DrawText( 'EMA', SpeedPane, 4, 132, 500, 12 );
PlotSeries( ema_m_s, SpeedPane, 500, #Thick);