Consecutive Bar Count Indicator for ThinkorSwim

I have a question about this code.

What does "[1]" & what does " Double.NaN" mean? I'm trying to intregate this into another study/indicator to display a label if there are 3 bearish bars in a row.



Code:
def vClose = close;

def nan = Double.NaN;


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);
 
[1] 1 bar ago, ]2] 2 bars ago. The docs are pretty good for thinksctipt. Great way to learn with them and reading code.
 
Code:
AddLabel(yes, IF BardownCount [+2]  then "TAKE PROFIT!TAKE PROFIT!TAKE PROFIT!" else "stand by", Color.white);

Oh wow, look at that.

Hnuik0c.png
 
How would you edit it so it gives you the average up to down ratio? Upbarcount/Downbarcount?

Thanks for the sharing the indicator!
 
How would you edit it so it gives you the average up to down ratio? Upbarcount/Downbarcount?

Thanks for the sharing the indicator!

You could add something like this after the #barUp and #barDown get defined.)
Let me know if this is what you're after.

Reference: https://tlc.thinkorswim.com/center/reference/thinkScript/Functions/Math---Trig/TotalSum


Code:
def totalUp = TOTALSUM(barUp);
def totalDown = TOTALSUM(barDown);
def avgUpDownRatio = totalUp/totalDown;

AddLabel(yes, "Ratio: " +  avgUpDownRatio, Color.Gray);
AddLabel(yes, " Up: " +  totalUp, Color.GREEN);
AddLabel(yes, " Down: " + totalDown, Color.RED);


MGgoAmu.png
 
Last edited by a moderator:
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.

8tG1NTF.png


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
Korygill

Thanks for the info on CompoundValue!!!! I'm new to TOS & ThinkScript and you saved me a lot of headaches with your excellent explanation of CompoundValue. It was exactly what I needed to solve my problem.

Have a very Happy Thanksgiving!
G.
 
Is there anyway to add a label to show number of up or down bars in a row, statically based on your lookback on the chart?
 
Is there anyway to add a label to show number of up or down bars in a row, statically based on your lookback on the chart?
input price = Close;
input Period = aggregationPeriod.min;

def barUp = close > close;
def barDn = Close < Close;

def barUpCount = CompoundValue(1, if barUp then barUpCount[1] + 1 else 0, 0);

def barDownCount = CompoundValue(1, if barDn then barDownCount[1] - 1 else 0, 0);

AddLabel(yes,("Bars "+(Round(barDownCount + barUpCount, 1))), if barUpCount > 1 then color.Green else if barDownCount <= 0 then color.Red else color.Gray);
 
@korygill - Thanks for the CompoundValue illustration. I'm trying to get it to work by showing a total number on a label using variables I've constructed:

Code:
def openOverCLOSE = open > close[1];
def totalCount = CompoundValue(1,if openoverclose then openoverclose[1] + 1 else 0,0);
AddLabel(yes,"Opened over Close[1] "+totalCount+" Times",color.yellow);

I have another counting method that I found some time ago that seems to be less than trustworthy and I'm not sure why.

However, when I run this criteria on an SPY daily chart using my "old" methodology I get a count of 1,636 while using the code above, I get a result of 0.

(Not a pro coder by any stretch....can't say I'm really clear on CompoundValue() yet but it seems like I'm not getting a similar result..)

Ideas?
 
@autolox I have no idea what your "old" code is meant to do, but I am guessing it is either method 1 or 2 in this code below. I used 2 plots to also visualize what the code is calculating.

Code:
def openoverclose = open > close[1];
def totalCount1 = CompoundValue(1,if openoverclose then totalCount1[1] + 1 else 0,0);
plot p1 = totalCount1;
AddLabel(yes,"1-Opened over Close[1] "+totalCount1+" Times",color.yellow);

def totalCount2 = CompoundValue(1,if openoverclose then totalCount2[1] + 1 else totalCount2[1],0);
plot p2 = totalCount2;
AddLabel(yes,"2-Opened over Close[1] "+totalCount2+" Times",color.yellow);
 
Thanks for the sharing @korygill ! I've been looking at this more and testing more since my post and this definitely seems better.

Here is what I had been using. I had recently adapted it to use the TotalSum() function shortly before finding this thread. Matter of fact I need to update this one to the CompoundValue() usage which reduces the number of lines.

Code:
def stage1Scenario = or2;
def stage1inarow = if stage1scenario == 1 then 1 else 0;
def stage1inarowcount = if stage1inarow == 1 then (stage1scenario[1] + 1) else (stage1scenario + 0);
def stage1inarowtotalcount = TotalSum(stage1inarowcount);
 
I like this one on the daily/weekly chart. I added this code in for a quick assessment of price difference since last down bar.
Code:
def close_diffpositive = if barUp then close - close[1] else 0;
def totalpositive = compoundvalue ( 1,if barupcount then close_diffpositive + totalpositive[1] else 0,0);
def close_diffnegative = if barDown then (close[1] - close) * -1 else 0;
def totalnegative = CompoundValue(1, if bardowncount then close_diffnegative + totalnegative[1] else 0, 0);
AddChartBubble(1, pBarUpCount,totalpositive, Color.GREEN);
AddChartBubble(1, pBarDownCount, totalnegative, Color.RED);

cmPbp5G.png
What do the numbers mean on the Bar Count?
 
What do the numbers mean on the Bar Count?
Hi Solaris, What does this code do? Mike
I don't know trying to figure that out
If your question, is what is this thread:
This is a tutorial contains a code snippet that explains for how to count bars between two points.
The code itself doesn't "DO" anything.

If your question is: Why would anyone want to count bars:
Here are the top 50 threads where members felt the need to count bars (sorted by popularity):
https://usethinkscript.com/search/1071664/?q=count&t=post&c[title_only]=1&o=date
 
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.

View attachment 4802

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
HI KORY: @korygill A+ for sharing this and your discussion of the code. It also works on a tick chart , which I particularly find interesting. I am in the process of trying to add it to separate studies on intraday indicators such as the as Fisher Transform plus the Recursive Median Filter. It makes for some non-Gaussian filters which I find unique and edifying. Thanks for much for your generosity. MagicQuotes
 

Join useThinkScript to post your question to a community of 21,000+ developers and traders.

Similar threads

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
350 Online
Create Post

Similar threads

Similar threads

The Market Trading Game Changer

Join 2,500+ subscribers inside the useThinkScript VIP Membership Club
  • Exclusive indicators
  • Proven strategies & setups
  • Private Discord community
  • ‘Buy The Dip’ signal alerts
  • Exclusive members-only content
  • Add-ons and resources
  • 1 full year of unlimited support

Frequently Asked Questions

What is useThinkScript?

useThinkScript is the #1 community of stock market investors using indicators and other tools to power their trading strategies. Traders of all skill levels use our forums to learn about scripting and indicators, help each other, and discover new ways to gain an edge in the markets.

How do I get started?

We get it. Our forum can be intimidating, if not overwhelming. With thousands of topics, tens of thousands of posts, our community has created an incredibly deep knowledge base for stock traders. No one can ever exhaust every resource provided on our site.

If you are new, or just looking for guidance, here are some helpful links to get you started.

What are the benefits of VIP Membership?
VIP members get exclusive access to these proven and tested premium indicators: Buy the Dip, Advanced Market Moves 2.0, Take Profit, and Volatility Trading Range. In addition, VIP members get access to over 50 VIP-only custom indicators, add-ons, and strategies, private VIP-only forums, private Discord channel to discuss trades and strategies in real-time, customer support, trade alerts, and much more. Learn all about VIP membership here.
How can I access the premium indicators?
To access the premium indicators, which are plug and play ready, sign up for VIP membership here.
Back
Top