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
https://tos.mx/eY58Fy