thinkScript BarNumber() Function Usage and Examples

markos

Well-known member
VIP
Trying to learn BarNumber() function in thinkscript? Take a look at some of the notes below—credit to the folks over at the ThinkScript Lounge.

BarNumber Usage

First you must remember that thinkscript runs your script once for each and every bar on your chart, regardless of the aggregation period. So for instance, for daily charts I usually run a 9m D (9 month daily) with 5 expansion bars. TOS counts around 195 bars for this chart, the number varies slightly based on the mix of months on the chart. Typically you'll want to suspend a study's calculation for data in the expansion bars.

So looking at the two subject lines the first is simple enough we create a variable, barNum, that contains the number assigned each individual bar on the chart, 1 thru N. This is done because we want to use barNum in several places in the script without incurring the processing expense of calling the barNumber() function each time.

Code:
******************************************************
def barNum = if(barNumber() * (close > 0)<=barnumber(),barnumber(),double.nan);
************************************************************

# define period to plot
declare lower;
input candlestart = 28;        
input candlestop = 14;

# Test if the barnumber has a closing value, if there is, the barnumber is good
# If there is no close value, the candle has not formed yet,

def barNum = if(barNumber() * (close > 0)<=barnumber(),barnumber(),double.nan);
def numBars = HighestAll(barNum);

plot barsWanted = if(  (numBars - barNum >= candlestop)
                   AND (numBars - barNum < candlestart),
                   high, double.NaN);
barsWanted.SetLineWeight(3);
barsWanted.SetPaintingStrategy(curve.POINTS);

*************** Plot barnumber **********************
def barNumber = barNumber();
#def barCount = HighestAll(if(IsNaN(price), 0, barNumber));
plot bn = barNumber;
bn.setPaintingStrategy(PaintingStrategy.VALUES_BELOW);
If the strategy is omitted a straight line is plotted. With the strategy included
the number of each bar is printed instead of the plot.
##################################

BarNumber() will never be 0

Simplify, simplify, simplify. Here's what is going is going wrong. Labels show the current value of a variable.

Code:
def FormingBar = !IsNaN(open) and IsNaN(open [-1] ) ;  # This is 1 if true and 0 is false.
def FormingBarNumber = if barnumber() == [1 or 0] then barNumber() else double.nan ; # BarNumber() will never be 0 and in order for it to be 1 you would need a chart with only 1 bar on the screen.

But more importantly those aren't doing anything at all in the script, why have them? What are you trying to do?

Barnumber() and bn - a function and a variable are different things

Also remember when using both Barnumber() and bn that a function and a variable are different things. Here is something that should show that difference

Code:
declare lower;

def random = Random();

plot
"Function/Function" = Random() / Random();
plot
"Variable/Variable" = random / random;
"Variable/Variable".SetStyle(Curve.Points);

9-21-19 17:22 JohnnyQs_IRA: If anyone is interested.. I put together a little Education Script to assist myself in understanding the Script Function and some general line drawing logic. It is included below..

Code:
## Education: The Script Function Exercise #1 JQ
## OneNote Name:Edu_Script_Ex1_JQ

#Mobius:  Scripts must end in a plot as their output. That plot can then be referenced as a global variable.
The objective of ALL ThinkScript is to plot something on a chart. ThinkScript is a chart painting program.

# Drawing a line from Point_A with and without a Script{} sub-routine
# Mobius
# Data Needed: Bar at Condition (bC), Value at Condition (vC), Length of Line (LL)

# User Inputs
input n = 20;             #hint n: Length for calculations.
input SdMulti = 2.0;      #hint SdMulti: Multiplier for St Dev.
input AtrMulti = 1.5;     #hint AtrMulti: Multiplier for ATR.

# Chart Data
def o = open;
def h = high;
def l = low;
def c = close;
def bar = BarNumber();

# Internal Script Reference
script LinePlot
        {
    input LL = 0; #Line Length
    input vC = close; #Value at Condition
    input bC = 0; #Bar at Condition
    plot line = if HighestAll(bC) - LL <= bC
                 and bC == highestAll(bC)
                then vC
                else Double.NaN;
        }
#                if the highest bar meeting the condition - LineLength is less than Bar at Condition
#                  and bC == highest bar meeting the condition
#                then value at condition
#                else double.nan

#> End Script (JQ)

#> BarNumber Plot
    plot barNumBelow = bar;
        barNumBelow.setpaintingStrategy(paintingStrategy.VALUES_BELOW);



# Variables for example
    # Example: First bar of mean value in a squeeze
    def Avg = Average(c, n); # c = close    n = length
    def SD = StDev(c, n); # c = close  n = length
    def ATR = Average(TrueRange(h, c, l), n);  # h = high   c = close   l = low   n = length
    plot upperSD = Avg + (SdMulti * SD);
        upperSD.setdefaultcolor(color.BLUE);
        upperSD.setlineweight(2);
    addlabel(1,"upperSD", uppersd.takeValueColor());
#    addchartbubble(1, lowestall(low), "SD\n" + upperSD, color.white, no);
    plot upperATR = Avg + (AtrMulti * ATR);
        upperATR.setdefaultcolor(color.plum);
#    addchartbubble(1, lowestall(low), "ATR\n" + upperATR, color.white, no);
        upperATR.setlineweight(2);
    addlabel(1," upperATR", upperATR.takeValueColor());
    addlabel(1," Condition: upperSD crosses below upperATR ", Color.violet);



# Variables for plotting line segment
    # bC is the Bar at Condition input to the Script
    def bC = if upperSD crosses below upperATR
             then bar
             else bC[1];  # barnumber where the condition is met
    #!        assigns bC an initial value of n/a
    #!        bC retains its bC[1] value until the condition is met
    #!        if upperSD crosses below upperATR bC takes the current barnumber as its value
    #!        bC retains that barnumber until the condition is met again if ever
#>    addchartbubble(1, lowestall(low), "bC\n" + bC, color.white, no);



    # vC is the Value at Condition input to the Script
    def vC = if upperSD crosses below upperATR
             then Round(Avg / TickSize(), 0) * TickSize()
             else vC[1];   # value (y-axis) where the condition is met
    #!        assigns vC an initial value of n/a
    #!        vC retains its vC[1] value until the condition is met
    #!        if upperSD crosses below upperATR vC takes the current Avg rounded to the nearest tick as its value
    #!        vC retains that value until the condition is met again if ever
#>    addchartbubble(1, lowestall(low), "vC\n" + vC, color.white, no);



    # LL is then LineLength input to the sctipt
    def LL = if bar != bC
             then bar - bC
             else if bar == bC
                  then Double.NaN
                  else LL[1];  #  Line Length
input Display_LL_Debug = {default "Hide", "Display"};
    addchartbubble(Display_LL_Debug, lowestall(low), "bar\n" + bar, color.white, no);
    addchartbubble(Display_LL_Debug, lowestall(low), "bC\n" + bC, color.white, no);
    addchartbubble(Display_LL_Debug, lowestall(low), "bar\n!=bC\n" + (bar != bC), color.white, no);
    addchartbubble(Display_LL_Debug, lowestall(low), "bar\n-bC\n" + (bar - bC), color.white, no);
    addchartbubble(Display_LL_Debug, lowestall(low), "bar\n==bC\n" + (bar == bC), color.white, no);
    addchartbubble(Display_LL_Debug, lowestall(low), "LL\n" + LL, color.white, no);
    addchartbubble(Display_LL_Debug, lowestall(low), "LL[1]\n" + LL[1], color.white, no);

# Plots
    # Method without Script{} for plotting just one line
    plot Squeeze_Pivot_1 = if HighestAll(bC) - LL <= bC
                           and bC == highestAll(bC)
                           then vC
                           else Double.NaN;
         Squeeze_Pivot_1.SetStyle(Curve.Points);
         Squeeze_Pivot_1.setDefaultColor(color.orange);
         Squeeze_Pivot_1.setLineWeight(5);
        AddLabel(1,"Squeeze_Pivot_1", Squeeze_Pivot_1.takeValueColor());
input Display_SP1_Debug = { default "Hide", "Display"};
    addchartbubble(Display_SP1_Debug, lowestall(low), "HAbC\n" + highestall(bC), color.white, no);
    addchartbubble(Display_SP1_Debug, lowestall(low), "LL\n" + LL, color.white, no);
    addchartbubble(Display_SP1_Debug, lowestall(low), "HAbC\n-LL\n" + (highestall(bC) - ll), color.white, no);
    addchartbubble(Display_SP1_Debug, lowestall(low), "bC\n" + bC, color.white, no);
    addchartbubble(Display_SP1_Debug, lowestall(low), "bC==\nHAbC\n" + (bC == highestall(bC)), color.white, no);
    # Method with Script{} for plotting multiple lines with different conditions
    #Note: Since there's only one plot statement in the Script() a plot extension name is not needed.

    plot Squeeze_Pivot_2 = LinePlot(vC = vC, LL = LL, bC = bC);
         Squeeze_Pivot_2.setDefaultColor(color.cyan);
         Squeeze_Pivot_2.SetLineWeight(3);
        AddLabel(1,"Squeeze_Pivot_2: script", Squeeze_Pivot_2.takeValueColor());

# End of Code
 
Last edited by a moderator:

paramay

New member
Greetings,

Has anyone had any success plotting a numeric value to a defined/specified date?

Each Friday, I generate a report and I would like that value (0 to 100) to be displayed on the plot. I suppose the value could be assigned to the open of that date. I have been informed by the kind folks here that I cannot tie to an external data set, so I am comfortable inputting a new value each week.

I do not have the foggiest just yet how to make that work. Has anyone on the forum had any success with this strange request?
 

tomsk

Well-known member
VIP
@paramay @BenTen Sure you can plot whatever value you wish so long as you can identify a bar number to do so against. Here is a simple example. Let's say you want to plot the value 280 on January 3, 2020 forward in time. This snippet does it. Load this on a daily aggregation of AAPL

Code:
# Plot Specific Date
# tomsk
# 1.21.2020

declare hide_on_intraday;

input date = 20200103;
input myLevel = 280;

def bar = if getYYYYMMDD() == date then barNumber() else Double.NaN;
plot data = if barNumber() >= HighestAll(bar) then myLevel else Double.NaN;
# End Plot Specific Date
 

tomsk

Well-known member
VIP
@BenTen ThinkScript is like a painting program. Important thing is to identify bars, then pretty much you can do whatever you want.

@paramay Over time all those levels are going to be a real challenge to manage. You might be better served to use a spreadsheet of some kind. That said if you really want to achieve this sort of thing by Thinkscript, you literally have to manage dates, barNumbers as well as input levels. Suggest you rethink about this a bit and maybe have a different approach
 

paramay

New member
@tomsk Thank you for the assistance with this. It does appear to be a lot of work. Generating the code and managing the dates I have a handle on (My report only maintains 1 year, and 6 months of visible data, anything more is shaved off). I'm certain I could generate a template from my data-set/spreadsheet, filling in the dynamic variables.

Thinking about the 40+ /futures contracts of data that I generate a report for, I can foresee, with this approach, could be a lengthy Study (or more like 40!).

I do have a wonderful report that I look at and have cultivated over the last several months, and I thought, "Man, this would be nice to have these levels right on the charts since it is a part of my strategy.

I'm not yet ready to give up on it. I am open to different approaches. Even if I was managing less data (dates, barNumbers, input levels), say 2 months worth - it would be beneficial to have that on a chart. I do like the idea of having this juxtaposed to candles and other indicators (minimal I mind you - I run a clean ship), as I find myself manually drawing things on the many charts everyday for reference. This could potentially save me 10's of hours a week of fiddling and managing my charts.

The data I am looking for, from what I can tell, is available on other platforms, just not TS yet - I wish it was.

"Nothing ventured, nothing gained" - Thanks for the help thus far, as I yet do not know much about the limitations/capabilities of thinkScript.

I was able to get some assistance with some simple code that does what I need it to do.

Ap3v6Wx.png


My report takes about 30 seconds to update, and the indicator another 30 seconds. I use a spreadsheet based off my report spreadsheet to generate the code. The code itself is a bit lengthy, nothing epic, but it delivers what I need while only adding a second or two to the load. I can absolutely live with this.

The folks at thinkScript lounge assisted and in it's simplest form looks like this:

Code:
plot line6MonthRTY = if GetSymbol() == "/RTY:XCME" OR  GetSymbol() == "/M2K:XCME" then                                 
if GetYYYYMMDD() >     20200121    then    0.00    else                 
if GetYYYYMMDD() >     20200114    then    2.81    else                 
if GetYYYYMMDD() >     20200107    then    5.72    else                 
if GetYYYYMMDD() >     20191231    then    0.28    else
if GetYYYYMMDD() >     20190730    then    94.92    else    94.92
else double.nan;

Thanks for all the assistance. If anyone wants to know more, please ask.
 

che2tango

New member
I grabbed the code and tried it. It will keep be busy figuring everything out and the first thing that I noticed is that the LinePlot Script is only called once. I was thinking that i want to plot a series of coefficients that have identical code except for the number. Thanks for sending this. I'm open for suggestions to learn this scripting language.
 

Similar threads

Top