[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: _SMA3: A steep roll-off lowpass filter



PureBytes Links

Trading Reference Links

Bob:

>>I've come up with a simple lowpass filter that has a significantly
>>sharper and steeper roll-off than the T3 Average while maintaining
>>the size of the main lobe in the frequency response.
>
>Interesting.

I was hoping you'd see it.  Ever since you posted the T3 average
code here, it has intrigued me, yet its overshoot problem bothered
me at the same time.  Last night while falling asleep I got this
idea to make something better.  Using the nulls in one SMA to cancel
out sidelobes in another SMA seems so simple that I'm sure someone
must have thought of it before me, but I can't recall seeing an
example of anyone doing it.

>You can greatly speed up the computation by expanding the coefficients.

I know, but doing so for 3 cascading SMAs would have complicated the
EL code to the point of incomprehensibility, for the purposes of my
article.

>The Simple Moving Average is a simple FIR (Finite Impulse Response)
>filter so that if you cascade them, the final filter is also a FIR
>filter. Thus you can calculate the coefficients of the final filter
>once at CurrentBar = 1 then use them on each following bar.
>
>Here is a simple example for Average(P1, 3) cascaded with Average(P2, 2);
>
>f0 = a*c0 + a*c1 + a*c2   (where a = .33333)
>f1 = a*c1 + a*c2 + a*c3   (where a = .33333)
>g0 = b*f0 + b*f1          (where b = .50000)
>   = a*b*c0 + a*b*c1 + a*b*c2 + a*b*c1 + a*b*c2 + a*b*c3
>   = a*b*c0 + 2*a*b*c1 + 2*a*b*c2 + a*b*c3
>
>You get the idea.

Yes, but I got a headache from figuring out how to calculate the
coefficients of three cascaded SMAs of different lengths!

I think it's computationally even more efficient (and easier to
figure out) to maintain each SMA as a running sum rather than an
average, and then divide each sum by its respective length to get
the average.  You only need a loop just once at the beginning to
initialize each sum, and after that you simply drop off the old
value and add the new value -- no looping required.  This will
accumulate error eventually, however, so every thousand bars or so
one should re-initialize the sums.

The code would be something like this:

 --------------------------------------------------------------------
{Function: _SMA3
 A lowpass filter having a sharper cut-off and steeper fall-off
 than the T3 Average.
 by Alex Matulich, Unicorn Research Corporation, June 2004
}

Inputs: price(NumericSeries), length(NumericSimple);

Vars: N1(0),N2(0),N3(0), sum1(0),sum2(0),sum3(0), av1(0),av2(0);

if mod(currentbar, 1000) = 1 then begin
    N1 = MaxList(1, IntPortion(0.75*length+0.5));
    N2 = MaxList(1, IntPortion(N1/1.25));
    N3 = MaxList(1, IntPortion(N1/1.5));
    sum1 = summation(price, N1);
    av1 = sum1 / N1;
    sum2 = summation(av1, N2);
    av2 = sum2 / N2;
    sum3 = summation(av2, N3);
end else begin
    sum1 = sum1 + price - price[N1];
    av1 = sum1 / N1;
    sum2 = sum2 + av1 - av1[N2];
    av2 = sum2 / N2;
    sum3 = sum3 + av2 - av2[N3];
end;

_SMA3 = sum3 / N3;
 --------------------------------------------------------------------

That way on 999 out of 1000 bars, only 10 mathematical operations
are needed: three additions, three subtractions, and three
divisions, and one modulo -- no loops required.  Calculating the
_SMA3 filter from the cascaded coefficients, on the other hand,
would have an operation count proportional to the length.

-- 
  ,|___    Alex Matulich -- alex@xxxxxxxxxxxxxx
 // +__>   Director of Research and Development
 //  \ 
 // __)    Unicorn Research Corporation -- http://unicorn.us.com