Consecutive Bar Count

korygill

korygill

Member
VIP
Warehouse
Like roulette in Vegas, the longer the ball keeps landing on Red, the more likely it is to land on Black the next turn, right? Well, in roulette, the odds are the same each turn, but perhaps in the stock market, all trends change at some point. [side note on roulette]

This is also an example of how to count things in thinkscript. If you are new to thinkscript, remember that your code runs on each bar and calculates everything based on that bar and any forward or backward looking values (like close[1] being the close 1 bar in the past). You can also reference the values of your own variables!

CompoundValue is a powerful function, and one you can use to in a couple ways. One way is counting things. That is what I will show here. Search other articles and the documentation for other usages like how to carry a previous value/condition forward until it changes.

For this example, we will count the number of consecutive up and down bars (based on close) on a chart. This image should give you a clear idea of what we're doing. Perhaps this technique can be applied to other studies and strategies.



Code for ConsecutiveBarCount

Code:
#
# ConsecutiveBarCount
#
# Study to indicate count consecutive up/down bars.
#
# Author: Kory Gill, @korygill
#
# VERSION HISTORY (sortable date and time (your local time is fine), and your initials
# 20190709-1200-KG    - created
# ...
# ...
#
# Comment out unnecessary portions to preserve TOS memory and enhance speed
#

declare lower;
declare once_per_bar;

#
# Common variables. Using variables reduces calls to TOS iData server.
#

# iData Definitions
#def vHigh = high;
#def initHigh =  CompoundValue(1, high, high);  # creates an initialized variable for high
#def vLow = low;
#def initLow = CompoundValue(1, low, low);
#def vOpen = open;
#def initOpen = CompoundValue(1, open, open);
def vClose = close;
#def initClose = CompoundValue(1, close, close);
#def vVolume = volume;
#def initVolume = CompoundValue(1, volume, volume);
def nan = Double.NaN;

# Bar Time & Date
#def bn = BarNumber();
#def currentBar = HighestAll(if !IsNaN(vHigh) then bn else nan);
#def Today = GetDay() ==GetLastDay();
#def time = GetTime();
#def GlobeX = GetTime() < RegularTradingStart(GetYYYYMMDD());
#def globeX_v2 = if time crosses below RegularTradingEnd(GetYYYYMMDD()) then bn else GlobeX[1];
#def RTS  = RegularTradingStart(GetYYYYMMDD());
#def RTE  = RegularTradingEnd(GetYYYYMMDD());
#def RTH = GetTime() > RegularTradingStart(GetYYYYMMDD());
#def RTH_v2 = if time crosses above RegularTradingStart(GetYYYYMMDD()) then bn else RTH[1];

# Bars that start and end the sessions
#def rthStartBar    = CompoundValue(1,
#                         if   !IsNaN(vClose)
#                         &&   time crosses above RegularTradingStart(GetYYYYMMDD())
#                         then bn
#                         else rthStartBar[1], 0);
#def rthEndBar      = CompoundValue(1,
#                         if   !IsNaN(vClose)
#                         &&   time crosses above RegularTradingEnd(GetYYYYMMDD())
#                         then bn
#                         else rthEndBar[1], 1);
#def globexStartBar = CompoundValue(1,
#                         if   !IsNaN(vClose)
#                         &&   time crosses below RegularTradingEnd(GetYYYYMMDD())
#                         then bn
#                         else globexStartBar[1], 1);
#def rthSession = if bn crosses above rthStartBar #+ barsExtendedBeyondSession
#                    then 1
#                    else if   bn crosses above rthEndBar #+ barsExtendedBeyondSession
#                         then 0
#                    else rthSession[1];

def zeroLine = 0;
plot pZeroLine = zeroLine;
pZeroLine.SetDefaultColor(Color.WHITE);
def upLine = 5;
plot pUpLine = upLine;
pUpLine.SetDefaultColor(Color.GREEN);
def downLine = -5;
plot pDownLine = downLine;
pDownLine.SetDefaultColor(Color.RED);

def barUp = vClose > vClose[1];
def barDown = vClose < vClose[1];

def barUpCount = CompoundValue(1, if barUp then barUpCount[1] + 1 else 0, 0);
plot pBarUpCount = if barUpCount > 0 then barUpCount else nan;
pBarUpCount.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
pBarUpCount.AssignValueColor(Color.GREEN);

def barDownCount = CompoundValue(1, if barDown then barDownCount[1] - 1 else 0, 0);
plot pBarDownCount = if barDownCount < 0 then barDownCount else nan;
pBarDownCount.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
pBarDownCount.AssignValueColor(Color.RED);

AddLabel(yes, "Consecutive Bar Count", Color.GRAY);
The secret sauce
def barUpCount = CompoundValue(1, if barUp then barUpCount[1] + 1 else 0, 0);

This statement says...
if the current bar is up
then set barUpCount to the "barUpCount of the previous bar" plus 1
else set barUpCount to zero

For now, don't worry about the first "1," and the last ",0" parts. You will just about always keep those like that and just change the middle part...

So the first UP bar we see is 1. If the next bar is also UP, then we take the previous barUpCount (1) and add 1 to it for 2. If we get a third UP bar, then we take the previous barUpCount (2) and add 1 to it for 3. Once you get this (and don't worry if it takes you a while; I struggled for a bit at first too), you will get an aha moment and this will become a great tool in your thinkscript arsenal.

Shareable link to the image and code
http://tos.mx/eY58Fy
 
Last edited:
markos

markos

Well-known member
VIP
Warehouse
Hey Kory, that is a very nice little touch that you put in; placing a version history at the top of the script. Quite professional.
 
korygill

korygill

Member
VIP
Warehouse
Hey Kory, that is a very nice little touch that you put in; placing a version history at the top of the script. Quite professional.
Thanks. I get paid to code for a living, and I try to use best practices everywhere. I saw other scripts that have a version scheme that did not sort well. It should be real easy to see if your version is newer/older than something else you are looking at. Also I am experimenting/exploring the right amount of boilerplate at the top. I expect many scripts here get modified by everyone a little. Want to encourage sharing/extending and attribution.
 

Top