After a recent video blog post where I discussed squeeze breakout trading with George Lea an observant viewer asked why the weekly squeeze shown in the stock ‘BEAT’ appeared to end at a different time to the weekly squeeze shown on the ThinkOrSwim platform.

A squeeze occurs in a stock when the Bollinger Bands move inside the Keltner Channel.

It turns out that if you place standard Bollinger Bands and a Keltner Channel on a ToS chart the bands might cross the Keltner Channel at slightly different places than in EdgeRater and other platforms. I spentĀ  some time diving into this problem to see if there was a data or formula issue in EdgeRater and I came across something interesting.

Here are the two charts for comparison:

EdgeRater Weekly Squeeze ending (Bollinger Bands move outside of Keltner Channel)


ToS Weekly Squeeze ending (Bollinger Bands move outside of Keltner Channel)


So, What could be going wrong?

The good news was that the Bollinger Bands values in ToS completely agreed with the Bollinger Bands values in EdgeRater, the less good news was that in some cases the Keltner Channel values were off by a little bit.

Why would that be the case? After all the calculation for Keltner Channel is quite straightforward – it’s just a displacement about a moving average, in our case equal to 1.5 times the 20 period Average True Range (ATR).

The calculation for TrueRange is simple enough:


And on further investigation the TrueRange values in both EdgeRater and ThinkOrSwim agree.

So then the other part is the 20 period average of TrueRange.

It turns out that the KeltnerChannel thinkScript uses a simple moving average for this part of the calculation and EdgeRater uses a Wilder’s Moving Average. Which one is correct? Welles Wilder developed the Average True Range indicator and used his own moving average calculation (Known as the Wilder’s Moving Average) and so the official calculation is the Wilder’s Moving Average.

Just to confirm that I had found the reason for the discrepancy I added a new thinkScript for the Keltner Channel which uses the WildersATR (in thinkScript there is function called ATRWilder).

Here’s the result:


And here’s the script. Note that the values of 1.5 and 20 have been hardcoded into this script and not added as input parameters:

def ATR = ATRWilder(20);
def shift = 1.5*ATR;

def avg20 = Average(Close, 20);
plot KCU = avg20 + shift;
plot KCL = avg20 – shift;

And also…

Along the way I also discovered that the Wilder’s Moving Average with period N is actually identical to an EMA with a period equal to 2*N -1. So for this example the 20 period Wilder’s Moving Average is actually identical to a 39 period EMA.