Scan for stocks trending downward


Category:
0
0

Hello forum and Happy Fathers Day,

Please help me generate a scan which will return results of stocks decaying intraday.
The following characteristics would be:

  • The current 5 day SMA close is less than the previous 5 day SMA close 3 periods ago in 5 minute intraday – (5 SMA close is trending downward)
  • The current high is less than the previous high 3 periods ago by n percent in 5 minute intraday – (3 consecutive red candle conditions must be met)

The screenshot below shows the results I am trying to achieve

The current scan I have is a bit inefficient and at times returned undesired results.

input n = 5;
input nn = 5;
def a = if open = nn then 1 else 0;

Thank you so much for any help you’re willing to provide

Marked as spam
Posted by (Questions: 7, Answers: 13)
Asked on June 17, 2018 8:22 am
218 views
0

Need to clear up some things. When you say: “5 day SMA”, are you actually intending to say “5 period SMA”? Reason I ask is because later in that sentence you state this should be a 5 min time frame. Are you using both daily and 5 min time frames or just a 5 min time frame?

For your second statement I see two elements. One is that the current high should be x percent less than the high from 3 bars ago. The second is that you require the last three bars to be red. Is that correct?

The code you provided performs no action at all.

( at June 17, 2018 9:16 am)
0
Hi Pete, Thank you for responding. My apologies for not being clear. The 5 day SMA is technically `SimpleMovingAvg(close, 5)` For some reason I am unable to edit my original post. Somehow the original code I posted got cut off. But here is the full in code: input n = 5; input nn = 5; def a = if open = nn then 1 else 0; Please keep in mind that this is bit inefficient and at times returns undesired results.
( at June 18, 2018 6:22 am)
0

In case you may want to see how the code is formatted properly: http://dpaste.com/33J1W8C

( at June 18, 2018 6:39 am)
0
Private answer

I am going to take a bit more time on this post. I want to review the code presented by the author to explain exactly what the code does. This will enable us to compare that to requested specifications. This is not intended to point out flaws, this is intended to provide education.

Here is the author’s original code:

input n = 5;
input nn = 5;
def a = if open < open[1] then 1 else 0;
plot b = if sum(a,n) >= nn then 1 else 0;

User Inputs

There are two user inputs, (n and nn). Their default values are set to 5. I am not a fan of excessive abbreviations in code. Those variable names should describe exactly what they are. Abbreviations make code less readable. Use them sparingly.

Check for Lower Open

After the two user inputs we have another variable, (a). We don’t have the slightest clue what is intended here because it’s just a single letter. This is not even an abbreviation. But we can read the code and we find this variable named “a” is set to a value of 1 if the open of the current bar is less than the open of the previous bar. If not, this variable is set to 0. This is how the line of code should be written:

def lowerOpen = open < open[1];

In place of a single letter we have a variable name which describes exactly what that variable contains. And if you are setting value of 1 or 0, there is no need for the if-then-else statement. In this case the expression that compares the current open to the previous open evaluates to true or false. In Thinkorswim the true/false values are actually numeric. True is always 1 and false is always 0. So we don’t need to assign them using the if-then-else.

Series of Consecutive Lower Opens

Ok, this brings us to the final line of code. Once again we have a single letter variable name. We don’t have the slightest clue what was intended here. So we have to read the code. The code is using the Sum() method and is calculating the sum of the “a” variable over the last “n” bars. It then takes this value and checks if it is greater than or equal to the “nn” input. Using the default inputs, this code basically says this: “check if the current bar’s open is less than the previous bar’s open for every one of the previous 5 or more bars.”

Properly Structured Code

So this is what this the entire code should look like, when written properly:

input lookBackBars = 5;
input minimumSeries = 5;
def lowerOpen = open < open[1];
plot seriesOfLowerOpens = Sum(lowerOpen, lookBackBars) >= minimumSeries;

Much easier to read. Still doesn’t even come close to meeting the specifications. But at least this code can be read and understood very quickly. This code is not “a bit inefficient”. And it does not “at times returned undesirable results”. This code always misses the mark, 100% of the time. Because it does not contain any of the elements from the stated specification. Not a single element. It’s very important you understand this, if you have a desire to learn how to do this.

The Solution

The way the specifications are structured leaves room for more than one interpretation. So we have to make some assumptions. The first specification is for the 5 period sma trending down.

One way to interpret that statement is to simply compare the current value of the 5 period sma to its value from 3 bars ago. Another way to interpret this is to say the 5 period sma must be lower than it’s previous value for 3 consecutive bars. We’ll be applying the first interpretation here.

Likewise, we can interpret the second specification in one of these two ways. Once again, we’ll be applying the first interpretation, because it’s easier.

The Final Code

input length = 5;
input percent = 5.0;
def sma = Average(close, length);
def smaTrendingDown = sma < sma[3];
def lowerHighByPercent = high < (high[3] * (1 - percent * 0.01));
def downBar = close < open;
def threeConsecutiveDownBars = Lowest(downBar, 3) > 0;
plot scan = smaTrendingDown and lowerHighByPercent and threeConsecutiveDownBars;

Review

Notice the final line of the code is the scan plot. You will see it contains our three specifications, spelled out clearly because we didn’t use excessive abbreviations when naming our variables.

Using the default inputs here I would expect this to be exceptionally rare. This is due to the percent being applied to the high from 3 bars ago. When are you going to find a case where you to see a 5% decline in price within 15 minutes? Which is 3 bars on a 5 minute time frame. Only on the opening bar, during a severe gap down from the previous close.

So you should start with a very, very small percent value. Perhaps something like 0.1. Or take some time to examine these patterns you are trying to pick up and calculate the average percent move that actually occurs in 3 bars.

Screenshot

Attached is a screenshot showing what this looks like using a percent value of 0.1, as applied to a Study Alert. You can see the spikes in the lower subgraph indicating when the conditions are true.

Attachments:
Marked as spam
Posted by (Questions: 37, Answers: 4091)
Answered on June 18, 2018 9:36 am
0

You’re amazing!
Thank you soo much for providing crisp details; very educational.
Now I have a much clearer understanding what’s going on.

I will backtest with the solution you have provided and will report back with my findings.
Again, thank you Pete.

( at June 20, 2018 5:53 am)
0
Hi Pete, I am revisiting this code and noticed that the `input length = 5;` is defined but doesn't appear to be used anywhere in your code. My apologies if I have been mistaken. Thank you
( at December 7, 2019 11:41 am)
0
yes, you are correct. Great catch. I'll update my answer to correct that. For now, you can modify the following line: def sma = Average(close, 5); With this: def sma = Average(close, length);
( at December 7, 2019 1:01 pm)