Each TradingView strategy implicitly uses a certain number of price bars to base its calculations on. Almost always, TradingView can figure out itself how many price bars a strategy needs for its computations. But what if that value cannot be determined automatically?

#### In this article:

## Setting the number of bars a TradingView strategy calculates on

We configure a TradingView strategy’s settings either by hand or with the `strategy()`

function. This function needs to be added to every strategy (*Pine Script Language Tutorial*, n.d.) and its `title`

argument, which specifies the strategy’s name, always needs to be set (TradingView, n.d.).

Another argument of the `strategy()`

function is `max_bars_back`

. This sparsely documented argument sets the maximum number of historical bars that the strategy can reference (TradingView, n.d.). TradingView automatically calculates how many price bars a strategy needs for its calculations (TradingView, n.d.), but in rare circumstances TradingView has trouble determining this value (Vitvlkv, 2016). In that case, TradingView generates the ‘out of depth at index’ error and we fix that error by setting the `max_bars_back`

argument to the number of bars our strategy uses with its calculations.

To understand what this ‘number of historical bars’ means, let’s say we create a trading strategy that uses a 12-bar RSI (Relative Strength Index). Now before this script can plot and use that RSI value, it needs to have 12 price bars to calculate with. So if we would scroll our chart all the way back to the first few price bars, we’ll see our script ‘waiting’ till there are 12 bars before plotting the RSI.

We set the number of historical bars a script uses with its calculations with `max_bars_back`

like this:

```
strategy(title="My example strategy", max_bars_back=12)
```

**only**need to set

`max_bars_back`

when TradingView cannot figure out that number of bars itself. This happens with less than 5 percent of scripts (estimation), and so we don’t use the `max_bars_back`

argument with the large majority of TradingView strategies. Now let’s look at a script example to see how a strategy’s code affects the number of historical bars a strategy bases its calculations on. After that we’ll continue our discussion of `max_bars_back`

with some insights and considerations.

## Example: seeing how many historical bars a strategy needs

The value we give the `max_bars_back`

argument is closely related to how far ago we reference historical price bars (see Vitvlkv, 2016). This referencing of historical price bars is done with functions that calculate on a series of values (like `ema()`

and `lowest()`

) or with the history referencing operator (`[]`

). That operator returns a previous value from some number of bars ago (*Pine Script Language Tutorial*, n.d.).

For example, `close`

returns the closing price of the current bar but `close[12]`

uses the history referencing operator to get the close price of 12 bars ago. Likewise, `volume[7]`

returns the volume of 7 bars ago. Now before our script can get *both* of these values, it needs to have access to at least 12 historical price bars.

For a more visual explanation, let’s consider the following example:

```
strategy(title="Strategy example - max_bars_back", overlay=true)
plot(series=highest(high, 20), color=green, linewidth=2)
plot(series=lowest(low, 20), color=red, linewidth=2)
```

We start here with the `strategy()`

function to configure the strategy’s properties. With the `title`

argument we specify the script’s name and with `overlay`

we display the strategy on the chart’s instrument. Since we don’t set the `max_bars_back`

argument, we let TradingView automatically calculate how many bars the script needs.

Then we plot a series of data on the chart with `plot()`

, and this function plots a line by default (TradingView, n.d.). By setting the `linewidth`

argument of both `plot()`

statements to 2, we create plots that are one step bigger than normal (TradingView, n.d.).

The first `plot()`

function call plots a 20-bar highest high with the `green`

basic TradingView colour. We use the `highest()`

function to get that extreme price. That function accepts two arguments: a series of values and the number of bars to get the highest value of (TradingView, n.d.). Here we set those arguments to the bar’s high prices (`high`

) and 20. This also means there need to be 20 price bars before the script can calculate that value.

With the second `plot()`

statement we display the 20-bar lowest low in `red`

. We retrieve that value with `lowest()`

, a function that also accepts two arguments: a series of values alongside an integer that sets the number of bars to calculate on (TradingView, n.d.). We set those arguments to `low`

and 20, and so here we also require 20 price bars to compute on (which are the same bars that we calculate the highest high value on).

When we add this strategy to the chart and scroll all the way back to the first bars (or use the ‘Go To…’ option that’s placed just below the chart), we see the following:

Because our strategy needs price data of 20 price bars, its holds off plotting till the 20th bar. On any bar before that, the `highest()`

and `lowest()`

function can’t calculate their extreme prices. And so the number of historical bars that our script references is 20. Here we let TradingView determine that value, but to set it ourselves we would add `max_bars_back=20`

to the `strategy()`

function.

Now let’s change the lookback of our script to 35:

```
strategy(title="Strategy example - max_bars_back", overlay=true)
plot(series=highest(high, 35), color=green, linewidth=2)
plot(series=lowest(low, 35), color=red, linewidth=2)
```

The only change here is that the `highest()`

and `lowest()`

functions now calculate on 35 bars. After saving the code, we see the script delaying an additional 15 bars:

While we see the script wait with plotting until there are enough bars, this also affects other aspects of the strategy. For example, if we submit orders based on the 35-bar highest high and lowest low, then those orders cannot be generated before the 35th bar.

While that’s only a small delay here, if we would reference a lot of bars (like when calculating a 200-bar moving average or the weekly high from a 1-minute chart), then some historical data is ‘lost’ when backtesting since the strategy has to ‘wait’ till there are enough price bars to calculate on.

## Tips for setting a strategy’s max_bars_back argument

Some insights for setting the `max_bars_back`

argument of the `strategy()`

function are:

- First, we need to set
`max_bars_back`

when TradingView cannot figure out the number of historical bars a strategy references. Unfortunately, this is a black box operation since we neither know how TradingView estimates this value nor can we see it somewhere. So currently the only way to know that we need to set`max_bars_back`

is with the*‘out of depth at index’*error message: that error appears when TradingView cannot determine how many historical bars our script uses.

- There are two functions that, when we compute them on a series of values, make it impossible for TradingView to figure out how many bars our strategy references:
`pivothigh()`

and`pivotlow()`

(TradingView, n.d.). But besides this, there is no way to know in advance (before the error message appears) whether we need to set the`max_bars_back`

argument or not. Generally speaking, scripts that repeatedly use values from previous bars with calculations (that is, use the history referencing operator) are harder for TradingView to get right. - As preparation, we can set
`max_bars_back`

before the ‘out of depth at index’ error happens. If we do, this argument’s value has to be high enough for the script’s calculations – even when we change the values our script calculates with through the input options. Because when the manually specified value of`max_bars_back`

is too low, TradingView still attempts to calculate this value automatically (TradingView, n.d.). And then the script can still run into the error message even though we’ve set the`max_bars_back`

argument.

Now which value do we need to set the `max_bars_back`

argument to? Some tips and considerations for that are:

- First, we don’t want to set
`max_bars_back`

too low. Otherwise the strategy still runs into the ‘out of depth at index’ error message when we change an input option, for example. And so the value of`max_bars_back`

needs to be generous enough to allow us to change the script’s inputs to double or triple their length. - However, there are two reasons why we don’t want to set
`max_bars_back`

too high. First, if we set this argument to higher than the number of bars on the chart, TradingView generates the*‘too large lookback’*error message:

- The second reason why a high
`max_bars_back`

value isn’t helpful is because it makes the script ‘wait’ before calculating, and that artificially shortens our backtest period. For example, if we set the argument to 1000, then the strategy won’t generate any orders or take other actions during the first thousand bars on the chart. And so we’ll be wasting a lot of historical data instead of using that data in our backtest. - As a rule of thumb, an approximate
`max_bars_back`

value for short-term strategies is 50. A value of 100 is more suitable for medium-term strategies, whereas a long-term strategy can require 200 bars back or more.

`max_bars_back`

argument of the `strategy()`

function. To learn more about working with the `max_bars_back`

argument, let’s look at a programming example.

## Example: setting the number of bars a strategy uses

The example strategy that’s shown below only works when we set the `max_bars_back`

argument of the `strategy()`

function. Because TradingView is quite good in determining how many historical bars a strategy calculates on, we have to employ some ‘tricks’ in our code to prevent TradingView from determining how many historical bars our strategy references. As a consequence, this strategy isn’t a good example of a clear, well-written TradingView script.

The example strategy plots and trades the swing pivot high (see next image). We go long on the first bar of the day, provided the bar’s close is below the swing pivot. Once we’re long, we submit a limit sell order for the then-current pivot swing high. How we calculate the pivot depends on the strategy’s market position. This way we require a ‘stronger’ pivot high to open a position, but once we’re in a position, we use a less pronounced swing pivot to exit the position. That way our take profit order is executed sooner. After discussing the code, we’ll look at how the strategy behaves and the impact of the `max_bars_back`

argument.

```
strategy(title="Example - max_bars_back", overlay=true)
// Input options
pivOffsetLong = input(title="Pivot Offset (Long)", type=integer, defval=7)
pivOffsetFlat = input(title="Pivot Offset (Flat)", type=integer, defval=15)
// Determine pivot
pivHighValue = (strategy.position_size == 0) ? pivOffsetFlat :
pivOffsetLong
pivHigh = pivothigh(pivHighValue, pivHighValue[1])
// Plot pivot on the chart
plot(series=strategy.position_size == 0 ? pivHigh : na,
style=circles, linewidth=5, color=green, offset=-pivOffsetFlat)
plot(series=strategy.position_size == 0 ? na : pivHigh,
style=circles, linewidth=5, color=green, offset=-pivOffsetLong)
// Determine trading conditions
recentPivot = fixnan(pivHigh)
enterLong = (close < recentPivot) and (dayofmonth != dayofmonth[1])
// Submit orders
strategy.entry(id="Enter Long", long=true, when=enterLong)
strategy.exit(id="Exit Long", from_entry="Enter Long", limit=recentPivot)
```

We first specify the strategy’s settings with `strategy()`

. With this function’s `title`

argument we name the strategy and with `overlay`

set to `true`

the strategy displays on the chart’s instrument (TradingView, n.d.).

Then we add two input options:

```
pivOffsetLong = input(title="Pivot Offset (Long)", type=integer, defval=7)
pivOffsetFlat = input(title="Pivot Offset (Flat)", type=integer, defval=15)
```

User-configurable input options are made with `input()`

, and this function also returns the input’s current value (TradingView, n.d.). We store those values in variables with the assignment operator (`=`

). That way we can refer to the input’s value later on in the code by using the variable.

Both inputs are numerical integer inputs. These accept whole numbers only and are made by setting the `type`

argument of the `input()`

function to `integer`

(*Pine Script Language Tutorial*, n.d.).

The first input is named “Pivot Offset (Long)” and we use its value when calculating the pivot high values that are used to open a position. We give it a default value of 7 (`defval=7`

) and store its current value in the `pivOffsetLong`

variable. We use that variable later on when computing the swing high pivot.

The second input is called “Pivot Offset (Flat)” and this one specifies the strength of the swing pivots high that we use with the strategy’s exit orders. The input starts with a value of 15 and has its current value tracked in the `pivOffsetFlat`

variable.

Next we use the inputs to calculate the swing pivot high:

```
pivHighValue = (strategy.position_size == 0) ? pivOffsetFlat :
pivOffsetLong
pivHigh = pivothigh(pivHighValue, pivHighValue[1])
```

Since we want to calculate the swing pivot highs differently depending on the strategy’s market position, we first need to figure out whether the script is long or flat. We do that with `strategy.position_size`

, a built-in variable that returns the size and direction of the current market position: when the strategy is long, this variable returns the number of open long contracts; when the script is flat, it returns 0 (TradingView, n.d.).

We use `strategy.position_size`

to conditionally set the value of `pivHighValue`

, our variable that holds the swing pivot length. This makes it possible to calculate the swing pivots later on with a different length depending on whether the strategy is long or flat. To implement this, we use the conditional (ternary) operator (`?:`

).

That operator works on three values: a true/false expression and two other values, of which one is returned based on the true/false expression (*Pine Script Language Tutorial*, n.d.). Now when that expression is `true`

, the conditional operator returns its second value. And when the expression evaluates to `false`

, the operator returns its third and last value. This makes the conditional operator work like an if/else statement: ‘if this expression is true, then return the second value; otherwise, return the third’.

The expression that we evaluate is whether `strategy.position_size`

equals (`==`

) 0, which it does when the strategy is flat (TradingView, n.d.). When that’s the case, the conditional operator returns the value of the `pivOffsetFlat`

input variable (which has a standard value of 15). That value is then assigned to the `pivHighValue`

variable.

Now when the strategy isn’t flat, our conditional operator returns the `pivOffsetLong`

variable (which has a standard value of 7). That value is then stored in the `pivHighValue`

variable. So depending on whether the strategy is flat or not, the `pivHighValue`

variable either holds a value of 7 or 15. Now since we use this variable to calculate the swing pivot highs, the length of those pivots in effect depend on whether the strategy has a position on or not.

We calculate that swing pivot high with `pivothigh()`

. That function returns the price of the swing pivot (if there’s currently one) or ‘NaN’ (a “not a number” value) for when there’s no new pivot price point (TradingView, n.d.). With the `pivHighValue`

variable inside this function’s parentheses we specify the pivot’s left and right strength. These ‘strength’ values indicate how many bars there need to be to the left and to the right of a high before TradingView considers that point to be a ‘swing pivot high’.

We offset the second `pivHighValue`

variable inside the `pivothigh()`

function’s parentheses with the history referencing operator (`[]`

). With help of this operator we don’t use this variable’s current bar value but work with the previous bar value of `pivHighValue`

instead. (The only reason for this part of the code example is to prevent TradingView from correctly guessing the number of historical bars that the script calculates on.)

The value that’s returned by `pivothigh()`

– which is either the swing pivot high or ‘NaN’ – is assigned to the `pivHigh`

variable. Then we plot that value on the chart:

```
plot(series=strategy.position_size == 0 ? pivHigh : na,
style=circles, linewidth=5, color=green, offset=-pivOffsetFlat)
plot(series=strategy.position_size == 0 ? na : pivHigh,
style=circles, linewidth=5, color=green, offset=-pivOffsetLong)
```

Even though we have a single value to plot (the swing pivot high), we call the `plot()`

function twice. We need to do that because the `pivothigh()`

function determines a swing pivot high *after* it occurred. To display that value correctly on the chart, we need to shift the pivot high value a certain number of bars to the left. Since we cannot set the `offset`

argument of the `plot()`

function conditionally (TradingView, n.d.), we use two `plot()`

statements with different offset values for our swing pivot strengths of 7 and 15 bars.

The first `plot()`

statement displays the swing pivot values for when our strategy is flat. To plot those values conditionally (based on whether there’s a market position), we use the conditional (ternary) operator (`?:`

) again. With this operator we set the `series`

argument of the `plot()`

function either to the pivot high value (which we stored in the `pivHigh`

variable) or `na`

. That built-in variable represents a “not a number” value (TradingView, n.d.) which, when used with plotting, has the effect of turning off the plot (see *Pine Script Language Tutorial*, n.d.). The true/false expression of the conditional operator is whether the strategy’s market position (`strategy.position_size`

) equals (`==`

) 0. When the strategy is indeed flat, we set the `series`

argument of the `plot()`

function to the `pivHigh`

variable.

With the other arguments of this first `plot()`

statement we display the swing pivot values as a small circle (`style=circles`

) in the `green`

basic TradingView colour. And the `linewidth`

argument set to 5 makes our circles appear with a large size. Now to plot this swing pivot value on the correct bar, we set the `offset`

argument of the `plot()`

function to `-pivOffsetFlat`

(the input variable that holds the pivot strength for when the strategy is flat).

The second `plot()`

function call is similar. But now we plot the `pivHigh`

value on the chart whenever the strategy *is not* flat. We offset those plotted values to the left with the `pivOffsetLong`

input variable that has a standard value of 15. Since both `plot()`

statements cancel each other out with our use of the conditional operator, the swing pivot high value either displays with 7 or 15 bars to the left depending on whether the strategy currently has an open position or not.

Then we determine the trading conditions:

```
recentPivot = fixnan(pivHigh)
enterLong = (close < recentPivot) and (dayofmonth != dayofmonth[1])
```

As discussed above, the `pivothigh()`

function either returns the swing pivot high price or NaN when there isn’t a new pivot high. The problem with those non-numerical NaN values is that we cannot use them with comparisons. And so we first need to convert them to actual numbers. We do that here with the `fixnan()`

function, which replaces any NaN value with the nearest non-NaN value (TradingView, n.d.).

The `fixnan()`

function works here with the `pivHigh`

variable that holds the value returned by `pivothigh()`

. This way we replace any NaN value with the nearest swing pivot price, and we assign those corrected values to the `recentPivot`

variable. This makes the `recentPivot`

variable hold the recent pivot swing price on every bar (without NaN values).

Then we create the true/false `enterLong`

variable. We set this variable’s value with two expressions that are combined with the `and`

logical operator. This operator only returns `true`

when the value on its left *and* the value on its right are `true`

too (*Pine Script Language Tutorial*, n.d.). When one or both values are `false`

, then combing them with `and`

returns `false`

too.

The first expression checks whether the bar’s closing price (`close`

) is less than (`<`

) the recent swing pivot high (`recentPivot`

). Since we’re going to use the `recentPivot`

value as our profit target, we want to make sure we don’t open a position above our profit target (since that position will then be immediately closed by the strategy).

The second expression evaluates if the current bar is the first of the trading day. We use `dayofmonth`

here, a built-in variable that returns the bar’s day of month (TradingView, n.d.). The evaluation checks whether this variable’s current value is unequal to (`!=`

) its value on the previous bar (`dayofmonth[1]`

). This makes our strategy only open positions at the start of the trading day.

In the last part of the script we submit the strategy’s orders:

```
strategy.entry(id="Enter Long", long=true, when=enterLong)
strategy.exit(id="Exit Long", from_entry="Enter Long", limit=recentPivot)
```

The `strategy.entry()`

function opens a position with a market order by default (TradingView, n.d.). We use three of this function’s arguments: with `id`

we set the order identifier to “Enter Long”. That name displays on the chart and in the ‘Strategy Tester’ window, and other order functions use this name to reference this order. The `long`

argument, when set to `true`

, makes `strategy.entry()`

submit an enter long order (TradingView, n.d.). And the `when`

argument requires a true/false expression to specify when the order should be submitted. This argument is set to the `enterLong`

variable we declared a moment ago.

We end the example with `strategy.exit()`

, a function that closes an open position (TradingView, n.d.). We configure this exit order with several arguments. The order identifier is set with `id`

and `from_entry`

specifies which entry order our exit order should apply to. With the `limit`

argument we set the profit target of this exit order to a specific price (TradingView, n.d.). That argument is set here to the `recentPivot`

variable , which holds the 7-bar and 15-bar swing pivot high.

There are three noteworthy features of our exit order. First, we only use `strategy.exit()`

to submit a take profit order but not a stop-loss order. This means there’s no limit on the maximum loss that each position can occur. Second, we submit the take profit order based on a variable’s value, and that variable updates each time a new swing high happens. That means our profit target isn’t fixed but can change while the position is open.

The third observation is that we call `strategy.exit()`

unconditionally; this function even executes when there’s no open position. This isn’t a problem because, when the entry order isn’t filled but we still execute `strategy.exit()`

, our exit order waits till the entry order places before being submitted (TradingView, n.d.). This means we don’t need to worry that our profit target acts as a limit order that opens a short position.

## Example charts: trading pivot high prices with a strategy

Now let’s see how our example strategy behaves. First, the script’s input options are:

When we add our strategy to the chart, it doesn’t do anything except triggering the *‘out of depth at index’* error message:

This error message happens when TradingView cannot automatically determine how many historical price bars the strategy bases its calculations on. Luckily, we can fix this error with the `max_bars_back`

argument. We initially used the `strategy()`

function in the above example like this:

```
strategy(title="Example - max_bars_back", overlay=true)
```

But since we didn’t specify the `max_bars_back`

argument, TradingView automatically guessed the number of bars our strategy calculates with (TradingView, n.d.). But as the error message shows, that estimation didn’t went well.

So let’s help TradingView and set the number of bars our strategy references ourselves. To do so, we change the `strategy()`

function to:

```
strategy(title="Example - max_bars_back", overlay=true, max_bars_back=50)
```

Here we add the `max_bars_back`

argument with a value of 50. This makes our strategy wait with calculating its values until there are at least 50 price bars to work with. With our input options set to 7 and 15, this value is high enough to prevent running into the ‘out of depth at index’ error message again.

After making that change, we save the script. The strategy then reloads on the chart and works correctly:

Now our strategy opens long positions when the first bar of the day closes below the swing pivot high, and exits that position at the pivot high with a limit order.

### Summary

Each TradingView strategy needs to include `strategy()`

, a function that uses several arguments to configure a strategy’s settings. One of those arguments is `max_bars_back`

which sets the number of bars a strategy uses with its calculations. By default, TradingView estimates this number of bars automatically. But in rare cases (especially when we use the `pivothigh()`

or `pivotlow()`

functions), TradingView cannot figure out how many bars a strategy needs for its calculations. In that case, TradingView generates the *‘out of depth at index’* error message when we add the strategy to the chart. To fix that error, we need to set the `max_bars_back`

argument to a manual value that’s high enough that the script has enough price bars to calculate on. Typical values for this argument range from 50 for short-term strategies to over 200 for long-term strategies that reference a lot of historical price bars.

#### Learn more:

- With the
`strategy()`

function we can also configure other settings that affect how TradingView calculates the script, like calculating a TradingView strategy with every real-time tick and recalculating a strategy each time an order fills. - Besides specifying how many bars a strategy references, we can also configure the number how many bars an indicator uses with the
`max_bars_back`

argument of the`study()`

function.

**References**

*Pine Script Language Tutorial* (n.d.). Retrieved on February 24, 2016, from https://docs.google.com/document/d/1sCfC873xJEMV7MGzt1L70JTStTE9kcG2q-LDuWWkBeY/

TradingView (n.d.). *Script Language Reference Manual*. Retrieved on May 9, 2016, from https://www.tradingview.com/study-script-reference/

Vitvlkv (2016, February 25). *Pine script documentation issue - forum discussion*. Retrieved on March 11, 2016, from https://getsatisfaction.com/tradingview/topics/pine-script-documentation-issue#reply_16650071