(*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);