There are several ways to configure how TradingView backtests our trading strategy. One of them involves setting how strict TradingView fills limit orders on historical data. How to do that and why would we want to?

In this article:

Specifying how strict limit orders fill during backtesting

We configure TradingView strategies either manually or with the strategy() function. We need to add that function to every strategy (Pine Script Language Tutorial, n.d.) and its title argument, which names the strategy, always need to be set too (TradingView, n.d.). The benefit of configuring a strategy’s settings programmatically is that our script is always added with the right settings to the chart.

One argument of strategy() is backtest_fill_limits_assumption. This argument configures how strict TradingView fills the strategy’s limit orders during backtesting: limit orders only fill when the market price exceeds the limit price by the number of ticks set by this argument (TradingView, n.d.). So with this argument our limit orders only fill when the bar’s range goes beyond the limit price with a certain number of ticks.

The default value of backtest_fill_limits_assumption is 0. That means that when we don’t set this argument, limit orders fill during backtesting as soon as their price is touched. And when we set this argument to a value that’s greater than 0, then limit orders only fill when the bar’s price surpasses the limit order price (Pine Script Language Tutorial, n.d.).

We can use the backtest_fill_limits_assumption argument of the strategy() function like this:

strategy(title="Example - backtest_fill_limits_assumption", 
     backtest_fill_limits_assumption=1)

When we set backtest_fill_limits_assumption higher than 0, we simulate the situation in which our order wasn’t filled even though the historical price bar reached the limit price or better (Pine Script Language Tutorial, n.d.). This makes backtest results more robust. Since in real-time trading, not all limit orders fill at their limit price or better (that is, higher for sell orders and lower for buy orders) depending on our position in the order queue and the volume traded at the limit price or better.

A couple of noteworthy features of backtest_fill_limits_assumption are:

  • First, backtest_fill_limits_assumption only influences when TradingView considers our limit order filled during a backtest; this argument has no effect on the actual order fill price (Pine Script Language Tutorial, n.d.).
  • Furthermore, backtest_fill_limits_assumption only affects when limit orders fill during backtesting; when trading in real-time, orders fill against real-time prices (Pine Script Language Tutorial, n.d.).
  • When a historical price bar reaches the price that triggers the limit order (that is, the limit order’s price plus or minus the number of ticks set by backtest_fill_limits_assumption), then the limit order fills on that bar. This happens regardless of that bar’s range. This can give the surprising situation in which we see limit orders fill on price bars that didn’t reach the limit price itself. (We discuss this further down below with an example chart.)
  • During backtesting, TradingView assumes that there are no price gaps inside a bar. This means a limit order can fill at any price inside a bar (Pine Script Language Tutorial, n.d.), even though in reality the price might have ‘jumped’ which makes filling the limit order impossible.
  • We cannot set backtest_fill_limits_assumption to an integer variable nor a numerical input variable (like backtest_fill_limits_assumption=myInputOption). This argument only accepts literal values, and those values need to be 0 or greater. Giving it a negative value triggers the ‘cannot call ‘strategy’ with arguments’ error message:
TradingView error message: 'cannot call strategy with arguments'

Before looking at the manual equivalent option of backtest_fill_limits_assumption, let’s walk through an example.

Example: filling limit orders on the E-mini S&P 500

To better understand how backtest_fill_limits_assumption affects when limit orders fill, let’s say we’re trading the E-mini S&P 500 future. This instrument has a tick size (minimum price movement) of 0.25 points. So when we set the backtest_fill_limits_assumption argument of the strategy() function to 1, prices need to exceed the limit order with 0.25 points before that order fills during backtesting.

Say the E-mini S&P 500’s current price is 1510.25 and our strategy places a buy limit order at 1510. That makes our limit order one tick away from the market price. But when the E-mini S&P 500 drops to 1510, our limit order isn’t filled. After all, with backtest_fill_limits_assumption=1 our limit order doesn’t trigger at its fill price but when the market price is one tick beyond the limit price.

And so when the next price bar touches 1509.75 – which is one tick beyond our limit price – TradingView fills the strategy’s buy limit order at 1510. What can lead to confusion is that this order even fills when this bar’s range doesn’t touch 1510 (Pine Script Language Tutorial, n.d.). In other words, when the range of this bar is for example 1509.75 till 1508.75, then the limit order displays on the chart as filled at 1510 simply because it was triggered on this bar during backtesting.

A couple more examples of how backtest_fill_limits_assumption works when trading the E-mini S&P 500 future are:

Argument setting Order Trigger price Fill price
backtest_fill_limits_assumption=1 Sell @ 1487.50 1487.75 1487.50
backtest_fill_limits_assumption=2 Buy @ 1300 1299.50 1300
backtest_fill_limits_assumption=2 Sell @ 1300 1300.50 1300
backtest_fill_limits_assumption=5 Buy @ 1502.25 1501 1502.25
backtest_fill_limits_assumption=5 Sell @ 1508.75 1510 1508.75
Tip: The backtest_fill_limits_assumption argument affects the price at which the order is considered filled during backtesting; it doesn’t influence the order fill price.

Tips for the backtest limit assumptions setting

Now which value should we use with the backtest_fill_limits_assumption argument? Like other strategy settings, this depends on your personal preference. Some considerations when choosing a value are:

  • The type of strategy. A script that’s specifically designed to trade breakouts after economic news releases will have a harder time getting limit orders filled than a strategy that trades during more quiet moments.
  • The instrument traded. The more liquid and less erratic the price movement of an instrument (like the E-mini S&P 500 future), the better the chances that limit orders fill. Instruments with less liquidity (like small caps stocks) and/or more volatile price movements (like crude oil and alternative currencies like Bitcoin) will have more trouble getting orders filled (and thus require a higher backtest_fill_limits_assumption value to adjust the backtest results for that).
  • The liquidity when the strategy trades. During regular trading hours, limit orders are more likely to fill than before or after these hours when relatively few contracts are traded at each price.

Choosing a value for the backtest_fill_limits_assumption argument also depends on your trading experience with the instrument and how tough you want to be with the backtest results. Generally speaking, setting backtest_fill_limits_assumption to 1 is a good starting point to adjust for the fact that not all limit orders will be filled during real-time trading.

Configuring a strategy’s limit orders assumption by hand

Besides the backtest_fill_limits_assumption argument of the strategy() function to specify how the strategy should fill limit orders on historical bars, we can also configure this setting with the manual ‘Verify Price For Limit Orders’ option.

This means we can use backtest_fill_limits_assumption to configure the strategy so that, whenever we add the script to the chart, it’s added with the right settings. And with the related manual option, we have the flexibility to give multiple instances of the same strategy different settings.

To manually change a strategy’s backtest fill assumptions, we first click on the gear icon ( ) that’s displayed to the right of the strategy’s name on the chart:

Opening the strategy settings window in TradingView

This brings up a window with different strategy settings. Here we select the ‘Properties’ tab and there we configure set the backtest fill assumption with the ‘Verify Price For Limit Orders’ setting:

Manually changing a TradingView strategy's limit orders setting
Note: The manual setting overrides the value we set to the backtest_fill_limits_assumption argument. This makes it possible to configure the same script differently by hand, regardless of the setting we’ve predefined with the strategy() function.

Programming example: conservative limit orders in TradingView

In the programming example below we plot a 20-bar Donchian Channel. This version of that popular technical indicator uses the 20-period highest high and lowest low, and plots the average value of these two as well. We open a long position whenever the bar closes above the highest high and short the market with a close below the lowest low. The strategy exits the position when the close crosses the middle line or when the profit target is hit. With the backtest_fill_limits_assumption argument we configure how strict TradingView should backtest those take profit limit orders.

The image below shows how the finished strategy behaves. After discussing the code, we look at charts showing how the strategy behaves and then examine how changing the backtest_fill_limits_assumption argument influences the strategy.

Example of the TradingView script that trades the Donchian Channel
//@version=2
strategy(title="Example - backtest_fill_limits_assumption", 
     backtest_fill_limits_assumption=1, overlay=true)

// Inputs
donLength = input(title="Donchian Length", type=integer, defval=20)
ptOffset  = input(title="Profit Target Offset (in ticks)", 
     type=integer, defval=30) * syminfo.mintick

// Compute data
donHigh   = highest(high, donLength)[1]
donLow    = lowest(low, donLength)[1]
donMiddle = (donHigh + donLow) / 2

// Plot data
plot(series=donHigh, color=teal)
plot(series=donLow, color=teal)
plot(series=donMiddle, color=#FF7F50)

// Order conditions
enterLong  = crossover(close, donHigh) and (strategy.position_size == 0)
enterShort = crossunder(close, donLow) and (strategy.position_size == 0)

// Submit enter position orders
if (enterLong)
    strategy.entry(id="Enter Long", long=true)
    
if (enterShort)
    strategy.entry(id="Enter Short", long=false)

// Submit exit position order
if (crossunder(close, donMiddle) or crossover(close, donMiddle))
    strategy.close_all()

// Determine and plot the take profit orders
takeProfitPrice = 
     (strategy.position_size > 0) ? strategy.position_avg_price + ptOffset :
     (strategy.position_size < 0) ? strategy.position_avg_price - ptOffset :
     na
    
plot(series=takeProfitPrice, color=#DC143C, style=circles, linewidth=3)

// Submit the sell long and cover short orders
if (strategy.position_size > 0)
    strategy.exit(id="Exit Long TP", limit=takeProfitPrice)

if (strategy.position_size < 0)
    strategy.exit(id="Exit Short TP", limit=takeProfitPrice)

We start the @version=2 comment. This makes the script use the second version of Pine Script which, among other things, makes using if statements possible (Pine Script Language Tutorial, n.d.).

Then we specify the strategy settings with strategy(). With this function’s title argument we name the strategy and with the overlay argument set to true we display the strategy on the chart’s instrument (TradingView, n.d.). We set backtest_fill_limits_assumption to 1. This way the strategy’s limit orders only fill on historical bars when the bar’s range is one tick beyond the limit price.

Next we add two input options:

donLength = input(title="Donchian Length", type=integer, defval=20)
ptOffset  = input(title="Profit Target Offset (in ticks)", 
     type=integer, defval=30) * syminfo.mintick

The input() function adds a manual option to the script’s settings and also returns that input’s current value (TradingView, n.d.). Those returned values are stored here in variables with the assignment operator (=). That way we can refer to the input’s value later on in the script 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.).

We name the first input “Donchian Length” with the title argument, and this name appears before the input option in the script’s settings (see image further down below). The input’s default value (defval) is 20 and we track its current value with the donLength variable. We use that variable later on as the lookback period for the highest high and lowest low.

The name of the other input is “Profit Target Offset (in ticks)”, and this one starts with a value of 30 (defval=30). Before we assign its value to the ptOffset variable, we first multiply it with syminfo.mintick. That built-in variable returns the minimum tick value (that is, smallest price change) of the symbol that the script calculates on (TradingView, n.d.).

That converts the input to the instrument’s price scale, which makes the “Profit Target Offset” option set a number of ticks – regardless of whether we add the script to the E-mini S&P 500 future (which has a tick size of 0.25) or the EUR/USD currency pair (whose minimum price change is 0.00001). We store this profit target offset (converted to the instrument’s number of ticks) in the ptOffset variable, which we use later when submitting the take profit orders.

Then we compute the Donchian Channel values:

donHigh   = highest(high, donLength)[1]
donLow    = lowest(low, donLength)[1]
donMiddle = (donHigh + donLow) / 2

We first calculate the highest high with highest(). That function returns the extreme high and accepts two arguments: a series of values to process and the length of the lookback period (TradingView, n.d.). Here it calculates on the instrument’s high prices (high) for the number of bars set by the donLength input variable, which we gave a standard value of 20.

However, computing the highest high in this way also includes the current bar. That makes trading breakouts impossible. After all, when the extreme high includes the current bar’s data, then the current bar can never cross above that 20-bar highest high.

And so we place the history referencing operator ([]) with a value of 1 just after highest(). This way the function doesn’t return the current bar’s value, but the previous bar value (Pine Script Language Tutorial, n.d.). That way we end up with the highest high up until, but not including, the current bar. We store that value in the donHigh variable to use later.

We determine the lowest low likewise. With the lowest() function processing low data for a length of donLength bars we get the 20-bar lowest low (TradingView, n.d.). Then, with the history referencing operator, we offset that lowest low value one bar to the left. We store the extreme low of the preceding 20 bars in the donLow variable.

Then we compute the Donchian Channel’s middle line. For that we add the donHigh and donLow variables together before dividing them by 2. That average value is assigned to the donMiddle variable, which we use later on to close our positions whenever the bar’s close crossed this middle line.

Next we plot the strategy’s data:

plot(series=donHigh, color=teal)
plot(series=donLow, color=teal)
plot(series=donMiddle, color=#FF7F50)

The plot() function displays the data of its series argument on the chart as a consecutive line by default (TradingView, n.d.). Our first two plot() function calls have that argument set to the donHigh and donLow variables to plot the 20-bar highest high and lowest low. With the function’s color argument we have both lines display in the teal basic TradingView colour.

The third and last plot() function call displays the average of the highest high and lowest low (series=donMiddle). This plot’s colour is set to #FF7F50, the hexadecimal colour value of coral.

Then we determine the conditions for opening a position:

enterLong  = crossover(close, donHigh) and (strategy.position_size == 0)
enterShort = crossunder(close, donLow) and (strategy.position_size == 0)

We create two true/false variables here: enterLong and enterShort. Both are assigned a value that’s the combination of two true/false expressions, which each check for a certain situation. We combine those expressions with the and logical operator. This operator only returns true when the value on its left and the value on its right are also true. Otherwise, when one or both values are false, then and returns false too (Pine Script Language Tutorial, n.d.).

And so before enterLong is true, its two expressions have to be true as well. The first expression checks if the closing price crossed above the 20-bar highest high. We implement this programmatically with crossover(). That function works on two series of values, and returns true when the value of the first argument is greater than the second argument’s value on the current bar, while on the previous bar the first argument’s value was below that of the second (TradingView, n.d.).

Since we have the crossover() function calculate with the close and donHigh variables, it returns true whenever the closing price crossed above the 20-bar highest high and returns false when the closing price didn’t do that on the current bar.

The second expression that affects the enterLong variable requires the strategy to be flat. We check that by evaluating whether strategy.position_size returns a value equal to (==) 0. That variable returns different values depending on the strategy’s position: a positive value with the number of open long contracts, a negative value for the short position size, and 0 when there’s no open position (TradingView, n.d.). By checking this variable as part of our enter long condition, we prevent the strategy from pyramiding into an open position as well as reversing open short positions.

Similarly, the value of the enterShort variable is also set with two expressions. The first evaluates with the crossunder() function whether the bar’s closing price (close) dropped below the 20-bar lowest low (donLow) while, on the previous bar, the close was still above that bar’s lowest low. With the second expression, strategy.position_size == 0, we evaluate whether the strategy is flat. Now when both expressions are true, then enterShort is true too; otherwise, this variable’s value is false.

Next we submit the market orders to open our positions:

if (enterLong)
    strategy.entry(id="Enter Long", long=true)
    
if (enterShort)
    strategy.entry(id="Enter Short", long=false)

These two if statements execute strategy.entry() conditionally. That function opens a position with a market order by default (TradingView, n.d.). We set two of its arguments. The first, id, specifies the order identifier, a name that displays on the chart and in the ‘Strategy Tester’ window. The other argument, long, makes strategy.entry() open a long position when set to true whereas long=false has the function initiate a short position (TradingView, n.d.).

The first if statement checks whether the enterLong variable returns true, which it does when the closing price crossed above the 20-bar highest high and the strategy is flat. We then submit the “Enter Long” order with strategy.entry(). The second if statement processes the value of enterShort, which is true whenever the bar’s close dropped below the 20-bar lowest low while the strategy is flat. When that happens, we submit the “Enter Short” order with strategy.entry().

Then we code our first exit order:

if (crossunder(close, donMiddle) or crossover(close, donMiddle))
    strategy.close_all()

This if statement’s condition has two true/false expressions. We combine them with the or logical operator, which returns true when the value on its left, the value on its right, or both values are true (Pine Script Language Tutorial, n.d.). Only when the two expressions that or joins are together false, then this operator returns false too.

Our first expression uses the crossunder() function to evaluate whether the bar’s closing price dropped below the average of the highest high and lowest low (which we stored in the donMiddle variable). The other expression checks with crossover() whether the bar’s closing price crossed the Donchian Channel middle line.

When one of these expressions is true, we call strategy.close_all(). That function exits the strategy’s open market position (regardless of whether the strategy is currently long or short), and doesn’t do anything when the strategy is already flat (TradingView, n.d.). This way we exit any open position whenever the bar crossed above or below the middle Donchian line.

Our strategy’s other exits are take profit orders. For those we first need to calculate the limit price:

takeProfitPrice = 
     (strategy.position_size > 0) ? strategy.position_avg_price + ptOffset :
     (strategy.position_size < 0) ? strategy.position_avg_price - ptOffset :
     na

The takeProfitPrice variable is assigned a value with two conditional (ternary) operators (?:). That operator works on three values. The first is a true/false expression that, when true, makes this operator return its second value. When the true/false expression is false, the conditional operator returns its third and last value (Pine Script Language Tutorial, n.d.).

That makes the operator work like an if/else statement: ‘when this is true, return A; otherwise, return B’. We use the conditional operators here so that the takeProfitPrice variable holds the profit target of long orders, the take profit level for shorts, or a non-numerical value when the strategy is flat.

The first conditional operator checks if the strategy is long, which is the case when the strategy.position_size variable returns a value that’s greater than (>) 0 (TradingView, n.d.). When that true/false expression is true, the first conditional operator calculates the long profit target.

We do that by adding the “Profit Target Offset” input option (whose value we stored in the ptOffset variable) to the entry price of the current position. That latter is retrieved with strategy.position_avg_price, a built-in variable that returns the average entry price of the open position (TradingView, n.d.). Since our strategy only opens positions when flat (and thus doesn’t have multiple entries in the same direction), that variable in effect returns the position’s initial entry price. And so by adding the ptOffset input variable (which has a default value of 30), our profit target is always 30 ticks away from the entry price. That long profit target is then returned by the first conditional operator and subsequently assigned to the takeProfitPrice variable.

Now when the strategy isn’t long, the true/false expression of the first conditional operator evaluates to false and TradingView continues with processing the second conditional operator. That operator’s true/false expression checks whether the strategy is short, which is the case when strategy.position_size returns a value less than (<) 0. Now when that evaluates to true, we calculate the take profit limit price for shorts by subtracting the “Profit Target Offset” value from the position’s entry price (strategy.position_avg_price). That calculated value is then returned by this second conditional operator and stored in the takeProfitPrice variable for use later on in the script.

When the strategy is neither long nor short, both conditional operators have their true/false expressions evaluate to false. In that case, the second conditional operator returns na. That built-in variable represents a “not a number” value (TradingView, n.d.), and acts as the default fallback value here. Such a value also ‘turns off’ a plot (Pine Script Language Tutorial, n.d.) as we’ll see below.

To visually confirm and track our profit target, we plot it on the chart:

plot(series=takeProfitPrice, color=#DC143C, style=circles, linewidth=3)

We display the takeProfitPrice variable on the chart with the plot() function. That variable holds, depending on the conditional operators discussed above, the profit target for long and short positions, or na. Now when we set the series argument of the plot() function to na, then the plot doesn’t display on the chart (Pine Script Language Tutorial, n.d.). That feature of na makes it possible to only plot the profit target when there’s an open long or short position, and don’t plot when the strategy is flat.

The plot type that we make are small dots on the chart (style=circles). The linewidth argument of the plot() function sets the plot’s size starting from 1 as the default size (TradingView, n.d.), and here we set that argument to 3 to make those dots relatively big. We set the color argument to #DC143C, the hexadecimal colour value of crimson red.

After plotting the profit targets, we submit these limit orders:

if (strategy.position_size > 0)
    strategy.exit(id="Exit Long TP", limit=takeProfitPrice)

if (strategy.position_size < 0)
    strategy.exit(id="Exit Short TP", limit=takeProfitPrice)

These two if statements submit two exit orders: one to close a long positions whereas the other exits a short trade. The first if statement evaluates whether the strategy is long, which the script is when the strategy.position_size variable returns a value that’s greater than (>) 0 (TradingView, n.d.).

We call strategy.exit() when the strategy is indeed long. That function exits open market positions and has several arguments to configure the exit order (TradingView, n.d.). We use two arguments here. With id we specify the order identifier, a name that’s displayed on the chart and in the ‘Strategy Tester’ window. We set the take profit limit price with limit, and this argument requires a specified price (which we computed above) as opposed to a certain tick offset (TradingView, n.d.). We set id to “Exit Long TP” and set the take profit’s price with the takeProfitPrice variable.

The second if statement is similar. With it we check if the strategy is short, which it is when the strategy.position_size variable returns a value that’s less than (<) 0 (TradingView, n.d.). In that situation we use the strategy.exit() function to submit the “Exit Short TP” order with a limit price of takeProfitPrice.

This ends our discussion of the programming example. Now let’s see how the strategy behaves on the chart and which role the backtest_fill_limits_assumption argument of the strategy() function plays.

Example charts: trading Donchian Channels in TradingView

The above programming example has the following input options:

Example of the input options of our TradingView example strategy

When we add the strategy to the EuroStoxx 50 Index CFD chart, it behaves like:

Example of the TradingView strategy trading the Donchian Channel

Here the strategy opens a long position after the bar closed above the upper Donchian Channel. The strategy then computes the exit long profit target and uses red dots to plot this value on the chart.

When we change the ‘Profit Target Offset’ input option to 15 (instead of 30), the script opens the same long position but now closes it much sooner. This makes it even possible to open a second long position during the uptrend:

Example of the TradingView strategy with the input options changed

Let’s set the ‘Profit Target Offset’ input option back to its default of 30 and change the chart to a S&P 500 Index CFD. On this instrument, the strategy is much more active:

Trading the Donchian Channel in a downtrend

The script opens several short positions during this downtrend, which are closed with a profit target that’s near the entry price. This happens because we calculate the profit target based on a number of ticks, and prices of the S&P 500 CFD move in increments of 0.1 whereas the previous EuroStoxx 50 CFD has a minimum price movement of 1. And so a profit target of 30 ticks is 3 points with the first instrument but 30 points with the second.

When we change the ‘Profit Target Offset’ input option to 150 (meaning, 15 full S&P 500 CFD points), the previous chart changes to:

The behaviour of our TradingView strategy during a downtrend

This places the profit target further away from the entry price and the strategy becomes less active as a result. Let’s examine how the backtest_fill_limits_assumption argument affects how the strategy’s limit orders are filled on historical bars.

Visual example: changing the fill assumption of limit orders

To change how strict the strategy’s limit orders fill on historical bars, we can change the manual option (see above) or adjust the backtest_fill_limits_assumption argument of the strategy() function. In the above example, we initially set that argument to 1:

strategy(title="Example - backtest_fill_limits_assumption", 
     backtest_fill_limits_assumption=1, overlay=true)

Before giving this argument another value, let’s first examine how the strategy behaves on a EuroStoxx 50 CFD chart with backtest_fill_limits_assumption=1:

Example of filling TradingView orders with a limit assumption of 1

Here we see a sell limit order of 3012 points and, with backtest_fill_limits_assumption=1, TradingView considers this order filled on the historical bar that touches the 3013 price.

But let’s say our TradingView strategy should fill historical limit orders when the bar’s price goes 4 ticks beyond the limit price. For that we change the strategy() function to:

strategy(title="Example - backtest_fill_limits_assumption", 
     backtest_fill_limits_assumption=4, overlay=true)

We now save the script and, after it reloads on the chart, it exits the same long order as follows:

Example of the TradingView strategy with limit orders assumption set to 4

Our take profit order still exits the long position at 3012, but now fills a bar later. This happens because the historical bar now needs to reach 3016 points: the limit price of 3012 plus the backtest_fill_limits_assumption value of 4. The bar before the one on which the order fills did reach 3012, but it’s high was only 3014 – not high enough to have TradingView consider our limit order filled.

One consequence of backtest_fill_limits_assumption is that, when this argument is set to a high value, limit orders can fill on bars that don’t even come close to reaching the actual limit price. We see that when we set the backtest_fill_limits_assumption argument to a high value of 12:

strategy(title="Example - backtest_fill_limits_assumption", 
     backtest_fill_limits_assumption=12, overlay=true)

Now when we save the strategy, the script reloads and looks like:

Example of the TradingView strategy with backtest_fill_limits_assumption set to 12

Our take profit order still fills at 3012 here. But with backtest_fill_limits_assumption set to 12, the historical bar has to reach 3024 before TradingView considers our limit order filled. In this case, it takes several bars before reaching that price. And when the order fills, it does so at the limit price of our take profit order and not at a price that’s inside that historical bar’s range.

In this way, backtest_fill_limits_assumption pessimistically adjusts our backtest results in two ways. First, this argument makes it harder for a limit order to fill during backtesting (in other words, backtest_fill_limits_assumption makes it more likely that our order does not fill). Second, when a limit order fills during backtesting, it executes at its limit price even though the bar’s price range is likely much more favourable.

Summary

We need to add the strategy() function to the code of every TradingView strategy. This function has several arguments to configure the strategy’s settings, including backtest_fill_limits_assumption. This argument specifies the limit order execution on historical price bars. That is, TradingView only considers limit orders filled when, during backtesting, the bar’s price reaches the limit order plus or minus the value we’ve set with backtest_fill_limits_assumption. During real-time trading, however, limit orders always fill against real-time prices. The default value of backtest_fill_limits_assumption is 0, and so when we don’t set this argument, limit orders execute as soon as their limit price is touched during backtesting. By setting this argument to a higher value we can simulate the situation wherein our limit order won’t be filled due to our position in the order queue and/or the liquidity around the limit price level. Note that with a high backtest_fill_limits_assumption value, limit orders can fill on price bars whose range didn’t touch the limit price.

Learn more:


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 April 14, 2016, from https://www.tradingview.com/study-script-reference/