Keltner Channel Scan


Category:
0
0

Hey Pete,  I’m trying to construct a scan that returns stocks that have pierced through the lower keltner channel intraday and closed abover the lower channel on a daily chart.  I would also like to have a scan that does the same on an hourly chart where at least 1 hourly bar’s range was outside of the lower channel within the last 2 days (or 14 bars).

I think was able to successfully create the daily scan, but the hourly scan I am having some trouble with.  Here’s what I used for the daily scan:

declare weak_volume_dependency;

input factor = 1.5;
input length = 20;
input price = close;

def shift = factor * Average(TrueRange(high, close, low), length);
def average = Average(price, length);

def Avg = average;
def Upper_Band = average + shift;
def Lower_Band = average – shift;

plot scan = low < Lower_Band and close > Lower_Band ;

 

Also, I would like the middle band to be specified as a 20 period exponential MA.

Marked as spam
Posted by (Questions: 1, Answers: 1)
Asked on May 8, 2018 9:35 am
1784 views
0
Private answer

This is a great question. Very well explained and you provided your own code. Love this.

Convert to Exponential Average

Let’s begin with your very last request. The middle band should be a 20 period Exponential Moving Average. As your code exists, that middle band is a Simple Moving Average:

def average = Average(price, length);

So we first need to change that to get you the Exponential Moving Average you require:

def average = ExpAverage(price, length);

There, that was simple wasn’t it?

Does it work?

The bad news is that your code is missing an important piece. See attached screenshot. I have added your code as a lower study on the chart. I have marked the various signals on the chart generated by your code. I see only one valid signal.

At this point I can either wait for you to provide more details or I can make some assumptions and proceed with the solution. I choose the later. I will assume that when you say:

“stocks that have pierced through the lower keltner channel”

What you mean is that prices should be above the lower band leading up to the pierce. While at the same time the bar that pierces should have opened above the lower band.

The Fix

So we will revise your code to fit that:

input factor = 1.5;
input length = 20;
input price = close;
def shift = factor * Average(TrueRange(high, close, low), length);
def average = ExpAverage(price, length);
def Avg = average;
def Upper_Band = average + shift;
def Lower_Band = average – shift;
def previousBarAbove = low[1] > Lower_Band;
def piercingBar = open > Lower_Band and low < Lower_Band and close > Lower_Band;
plot scan = previousBarAbove and piercingBar;

Second screenshot shows the improved version. Also note in this second screenshot I am using a modified version of the Keltner Channel that comes with Thinkorswim. The standard version uses a simple moving average so I modified one to use the exponential moving average. This ensures we can see on the chart exactly what is taking place in the scan.

Code Review

Notice the modifications I made to your code. I break out the price pattern into the smallest individual pieces. We have previousBarAbove as the first piece and piercingBar as the second. This makes the code much easier to read and debug. You can plot those pieces individually to see what each one is doing. Just change the def to plot to display them on the chart.

This also makes it much easier to modify the specifications. Let’s say you need to have two bars above the lower band before the pierce, instead of just one:

plot scan = previousBarAbove and previousBarAbove[1] and piercingBar;

The Hourly Scan

Now, how about that hourly scan?

“at least 1 hourly bar’s range was outside of the lower channel within the last 2 days (or 14 bars)”

Once again I have to make an assumption here. You used the term “outside the lower channel”, while the only options are to be above or below. We cannot be outside a single line. So I will interpret this to mean you want the range of one hourly bar in the past 14 to be “outside” the Keltner channel. More specifically, below the lower band (because outside the channel could also mean above the upper band).

Ok, so we do the same as we have for the daily, with the added condition that the high of any of the previous 14 bars (excluding the previous) should be below the lower band. Why do we exclude the previous? Because that is the first condition we have for the daily scan (previousBarAbove).

Modified Code for Hourly

So now we have this for the hourly scan:

input factor = 1.5;
input length = 20;
input price = close;
def shift = factor * Average(TrueRange(high, close, low), length);
def average = ExpAverage(price, length);
def Avg = average;
def Upper_Band = average + shift;
def Lower_Band = average – shift;
def previousBarAbove = low[1] > Lower_Band;
def piercingBar = open > Lower_Band and low < Lower_Band and close > Lower_Band;
def belowLowerBand = high < Lower_Band;
plot scan = previousBarAbove and piercingBar and Highest(belowLowerBand[1], 14) > 0;

What the Heck is That?

I will take some time to explain. I have only added one line of code. It evaluates to True when the high of a bar is below the lower band. Which means it is completely outside of the Keltner channel, below the lower band. This true/false variable, converts to a numeric value of 1/0 automatically. So we only need to check of that variable has been true (value == 1) within the last 14 bars (excluding the current bar). We do this using a method named Highest(). This checks for the highest value of the variable within the last 14 bars. We just need to have one of those bars to be true (value == 1) in order to tigger that condition.

Third screenshot shows the result. I left the chart set to daily because it makes it easier for folks to go back and check their own charts. This pattern will be detected on any time frame you apply it to.

Have fun!

Attachments:
Marked as spam
Posted by (Questions: 37, Answers: 4087)
Answered on May 8, 2018 11:43 am
0
Private answer

Pete,

You’re a legend man.  Thank you for explaining everything in depth.  I’m in the beginning stages of learning how to use thinkscript, and I’ve found this website to be my best guide.

The daily scan is exactly what I was looking for.  The hourly scan isn’t quite giving me the type of results I had in my head.  I tried to edit the code a little bit to scan for charts that meet this criteria: 1 bar closes below lower band, next bar closes above the lower band (which would be better described as a breakout bar rather than a piercing bar), and then I added 2 more bars.  The first closes above the lower band and the second has a low above the lower band.  I defined them as-

def followingBarAbove = high[1] > Lower_Band and close[1] > Lower_Band;
def followingBarHolds = low > Lower_Band;

I’m pretty sure the scan is giving me what I am looking for, but I was hoping you could take a look and let me know what you think or anything you would change.

Here’s the code:

input factor = 1.5;
input length = 20;
input price = close;
def shift = factor * Average(TrueRange(high, close, low), length);
def average = ExpAverage(price, length);
def Avg = average;
def Upper_Band = average + shift;
def Lower_Band = average – shift;
def previousBarBelow = close[3] < Lower_Band;
def piercingBar = high[2] > Lower_Band and low[2] < Lower_Band and close[2] > Lower_Band;
def followingBarAbove = high[1] > Lower_Band and close[1] > Lower_Band;
def followingBarHolds = low > Lower_Band;
def belowLowerBand = high < Lower_Band;
plot scan = previousBarBelow and piercingBar and followingBarAbove and followingBarHolds and Highest(belowLowerBand[1], 14) > 0;

 

Thanks again Pete.

Attachments:
Marked as spam
Posted by (Questions: 1, Answers: 1)
Answered on May 8, 2018 3:53 pm
0

We don’t usually permit additional questions be posted using the “Post your Answer” box at the bottom of the thread. It is usually best to respond to previous questions by entering a comment, as I have done here. However the question you added here is sort of another answer to your original question. Sort of.

I see you included a screenshot but I don’t see the full chart. So I don’t have the ticker symbol and cannot replicate the chart on my side. Your screenshot is also lacking any indication of the exact bar on the chart that contains the signal you are trying to get your code to pick up. So I really can’t do anything with this.

Since you are interested in learning. I suggest you try plotting this code as a lower study, as I did for my screenshots. Then work through each piece of your code, changing the def to plot, so you can see exactly what each one is doing. This is a very important skill in software development (debugging). Programmers spend far more time debugging code then they do writing it.

If you get through all that and still can’t get things nailed down I suggest you post a new question for this hourly scan. Be sure the title of question explains what you are trying to achieve, (such as including the phrase: Keltner breakout bar).

Good luck, and have fun!

( at May 8, 2018 4:31 pm)