Deviation Squared Moving Average (DSMA) troubleshooting

I'm using the fantastic code provided by Tomasz in John Ehler's Technical Analysis of Stocks and Commodities (TASC) article regarding the Deviation Squared Moving Average (DSMA), which can be found here.

The code works fine on daily data. But on my 1-minute database from IBKR, there are a number of symbols where the DSMA suddenly returns geometrically increasing numbers, eventually reaching inf or -inf, and never recovers to "normal" values. See screenshot, below, where DSMA10 is the 10-day moving average. This also happens on DSMA30 later down the exploration (not pictured).

image

Here's the code, which I adapted from the article by putting it in a function and renamed "Close" to "Array", but it's otherwise the same:

// Deviation Scaled Moving Average (DSMA)
// TASC Traders Tips July 2018
// http://traders.com/Documentation/FEEDbk_docs/2018/07/TradersTips.html#item7
function DSMA( Array, Period )
{
    PI = 3.1415926;
    a1 = exp( -1.414 * PI / ( 0.5 * Period ) );
    b1 = 2 * a1 * cos( 1.414 * PI / ( 0.5 * Period ) );
    c2 = b1;
    c3 = -a1 * a1;
    c1 = 1 - c2 - c3;
    Zeros = Array - Ref( Array, -2 );

	// SuperSmoother Filter
    Filt = IIR( Zeros, c1 * 0.5, c2, c1 * 0.5, c3 );

	// Compute Standard Deviation
    RMS = Sum( Filt * Filt, Period );
    RMS = sqrt( RMS / Period );

	// Rescale Filt in terms of Standard Deviations
    ScaledFilt = Filt / RMS;
    alpha1 = abs( ScaledFilt ) * 5 / Period;

    return AMA( Array, alpha1 );
}

// Exploration

SetOption( "NoDefaultColumns", True );
Filter = 1;
AddTextColumn( Name(), "Symbol" );
AddColumn( DateTime(), "Date", formatDateTime );
AddColumn( O, "Open", 1.2 );
AddColumn( H, "High", 1.2 );
AddColumn( L, "Low", 1.2 );
AddColumn( C, "Close", 1.2 );
AddColumn( V, "Volume", 1.0 );
AddColumn( DSMA(C,10), "DSMA10" );
AddColumn( DSMA(C,30), "DSMA30" );
AddColumn( DSMA(C,90), "DSMA90" );
AddColumn( DSMA(C,270), "DSMA270" );

Before I debug each step of the calculation, does anyone have any advice on what could be causing this? :thinking:

Any help is appreciated!

... does anyone have any advice on what could be causing this?

At first glance it looks like you have checked Pad and align... setting of Analysis settings - General tab.

Uncheck that option and then re-run exploration.

Also now you can find out status of that option via code level using new field "PadAndAlignToReference" of GetOption() function.

http://www.amibroker.com/devlog/2019/11/28/amibroker-6-35-0-beta-released/

1 Like

Thanks for the idea! "Pad and align" wasn't checked, and I got the same result with it checked and unchecked, unfortunately.

And thanks for letting me know about checking the status of that option in code. It had escaped my notice when I read the docs.

Still Pad and Align being enabled can be one cause too as you can see here
9

In your case the cause is that array elements are equal for longer period of time (see your OHLC columns). Same applies when pad and align is enabled and symbol has missing data compared to other one (so holes are filled -> equal elements for certain period).

RMS may become negative and square root of negative number results in...

To avoid RMS becoming negative you could do like this:

RMS = sqrt( Max(1e-7, RMS) / Period ); 
6 Likes

You got it! I was wondering if it was something like that and you saved me so much time troubleshooting! :sunglasses:

I'm truly grateful for your help on this.

This kind of community support is one reason why I chose AmiBroker and I am constantly reminded of what a good decision that was!

Yours truly,
Peter Deal

1 Like

The article follows original formulation of DSMA exactly as described by Ehlers. The problem with that formulation is that it assumes that prices are changing. You have

Zeros = Array - Ref( Array, -2 );

This calculates difference between given bar and 2 bars before. Later on this is smoothed and used to calculate RMS. And contrary to what @fxshrat RMS will NEVER become negative. It can not be negative because:

RMS = Sum( Filt * Filt, Period ); // sum of SQUARED numbers can NEVER be negative
RMS = sqrt( RMS / Period ); // this is ALWAYS correct

What it can be come is ZERO. It will be come zero IF you input data is flag (changes are zero). And when RMS approaches zero this division:

ScaledFilt = Filt / RMS;

would approach infinity. You can prevent it by adding small constant to denominator.

1 Like

@Tomasz,

in my tests
RMS = Sum( Filt * Filt, Period );
became very very small negative at some cases (tested with Pad&align checked).

I suppose because of https://www.amibroker.com/kb/2010/07/20/about-floating-point-arithmetic/

So because of those very small negative occurrences then sqrt of RMS became inf.
So just because of those tests I mentioned that it may become negative.

11


12

1 Like

It is zero. IEEE standard has two zeros +0 and -0. What you see is -0. And yes it is due to rounding in running sum.

Wow, I learned a lot on this one. Although I understood there was a sign bit, I never made the connection that there could be a negative or positive zero. Thanks for the reference to IEEE, which is another step forward in my computing knowledge!