In this article we repeat some of the most important points when configuring a TradingView strategy programmatically. Follow the links to the full articles for more information.

In this article:

Configuring the settings of a TradingView strategy programmatically

After the chapter’s introduction we discussed configuring a TradingView strategy with code. This is done with strategy(), a function that needs to be added to every TradingView strategy (Pine Script Language Tutorial, n.d.). And this function’s title argument, which specifies the strategy’s name, always needs to be set too (TradingView, n.d.).

Configuring the strategy’s options by hand is possible too. Because the manual options override the settings specified with strategy(), multiple instances of the same strategy can be configured differently. Furthermore, the manual options make it possible to quickly change a setting without having to edit the script’s code. However, configuring a strategy’s settings programmatically has benefits too: it saves time otherwise spend configuring the strategy, prevents forgetting to configure something, and makes sharing the script with the right settings easier.

Besides that title argument, all other arguments of the strategy() function are optional. The different arguments that this function has are (TradingView, n.d.):

strategy(title, shorttitle, overlay, precision, scale, max_bars_back,
     pyramiding, calc_on_order_fills, calc_on_every_tick,
     backtest_fill_limits_assumption, default_qty_type, default_qty_value,
     initial_capital, currency)

These arguments mean the following (Pine Script Language Tutorial, n.d.; TradingView, n.d.):

  • title: required string argument that sets the name of the trading strategy. This name is used in several TradingView windows, and can be different from the filename that the script is saved under in the Pine Editor. For more on title, see setting the name of a TradingView strategy.
  • shorttitle: optional string argument that also names the strategy. This argument overrides the value set by title and, as we discuss in naming a TradingView strategy, doesn’t provide capabilities beyond what title already does.
  • overlay: optional true/false argument that, when set to true, displays the strategy in the chart area of the chart’s instrument. With overlay=false the strategy instead appears in a separate chart panel below the chart’s instrument. For more, see overlaying a strategy on the chart’s instrument.
  • precision: optional integer argument that specifies how many digits to show after the decimal point of the plotted strategy values. This argument defaults to 4 and has a minimum of 0. With that latter large numbers are formatted with the ‘K’ (for thousands) and ’M’ (for millions) suffixes. See setting the displayed precision of a trading strategy for more.
  • scale: optional argument that defines which price scale the strategy attaches to. Possible values are scale.right (the default value when we don’t set the scale argument), scale.left, and scale.none. With that latter the strategy uses the full chart area when plotting, and this requires that the overlay argument is set to true. For more on the scale argument, see configuring the scale of a TradingView strategy programmatically.
  • pyramiding: optional integer argument that specifies how many entries are allowed in the same direction. This argument defaults to 0, and with that value only one long or short entry order can be filled while additional entries will be rejected. We take a closer look at this argument in setting pyramiding settings programmatically in TradingView.
  • calc_on_order_fills: optional Boolean argument that, when set to true, makes the strategy perform an additional intra-bar order calculation immediately after an order fills. That extra calculation happens on both historical and real-time price bars. When omitted, calc_on_order_fills defaults to false and the strategy then calculates on the close of each bar. See calculating a TradingView strategy immediately after an order fills for more.
  • calc_on_every_tick: optional true/false value that, when set to true, makes the strategy calculate with every real-time tick rather than only on bar close. On historical bars the strategy keeps calculating at the close of each price bar. The default value of calc_on_every_tick is false. We examine this argument closely in calculating a TradingView strategy with every real-time price update.
  • max_bars_back: optional integer argument that specifies the maximum number of historical bars that the strategy references to perform its calculations. That number of bars is automatically calculated by TradingView, but can be changed with this argument. For more on max_bars_back see setting the number of historical bars a strategy uses programmatically.
  • backtest_fill_limits_assumption: optional integer argument that configures how strict TradingView deals with limit orders when backtesting. Before a limit order fills, the bar’s price has to exceed the limit order price with the number of ticks set by backtest_fill_limits_assumption. We take a closer look at this argument in specifying TradingView’s backtest assumptions of limit orders.
  • default_qty_type: optional argument that specifies the default order size (that is, the order size used when we submit an order without specifying its quantity). This argument can be set to three values: strategy.fixed (order sizing with a fixed quantity; the default setting), strategy.cash (sizing orders based on a cash amount), and strategy.percent_of_equity (sizing orders based on an equity percentage).
  • default_qty_value: optional float argument that specifies the quantity of the default order size. Whereas the default_qty_type argument specifies how the default order size is calculated, default_qty_value sets the standard order size. And so default_qty_value specifies the number of contracts or shares, the cash amount of each order, or the equity percentage to invest with each order depending on the default_qty_type setting.
  • initial_capital: optional argument that sets the strategy’s starting funds, and this value defaults to 100,000. See setting a strategy’s initial capital programmatically for more.
  • currency: optional argument that specifies the account currency. Whenever the strategy’s currency differs from the currency used by the chart’s instrument, TradingView performs currency conversion of things like the strategy’s net profit and equity. This argument defaults to currency.NONE, and with that no currency conversion takes place. Other values for currency are currency.AUD (Australian dollar), currency.CAD (Canadian dollar), currency.CHF (Swiss franc), currency.EUR (euro), currency.GBP (pound sterling), currency.HKD (Hong Kong dollar), currency.JPY (Japanese yen), currency.NOK (Norwegian krone), currency.NZD (New Zealand dollar), currency.RUB (Russian ruble), currency.SEK (Swedish krona), currency.SGD (Singapore dollar), currency.TRY (Turkish lira), currency.USD (US dollar), and currency.ZAR (South African rand). See setting the currency of a TradingView strategy programmatically for more.

Let’s take a closer look at these different arguments of the strategy() function.

title: setting a TradingView strategy’s name with code

The title argument of the strategy() function specifies the strategy’s name (TradingView, n.d.). This argument always needs to be set and we use it like this:

strategy(title="Moving average crossover")

title accepts a literal string (like we see here); it doesn’t accept a built-in or user-defined string variable nor does it accept a concatenated TradingView string. Furthermore, we also cannot set the strategy’s name manually. That means the title argument is the only way to set a strategy’s name.

The name that we give a strategy with title appears in the chart’s legend:

Example of the strategy's name displayed on the TradingView chart

And displays in the ‘Data Window’:

Example of the strategy's name appearing the 'Data Window'

And appears in the ‘Strategy Tester’ window too:

Strategy name appearing in the TradingView 'Strategy Tester' window

Besides title, the shorttitle argument sets the strategy’s abbreviated name (TradingView, n.d.). However, this latter argument does the same thing title does. And since title is required whereas shorttitle is not (TradingView, n.d.), it’s more convenient to just use title for naming our strategy.

A thing to keep in mind is that title doesn’t specify how the strategy is named in the list of indicators and strategies. Instead, the script’s filename is used in that window.

Strategy filename appearing in TradingView's list of indicators and strategies

We set that filename in the Pine Editor, the window where we edit the script’s code:

Example of the filename showing in the TradingView Pine Editor

This means title sets the strategy’s name we see 95% of the time, but when we want to add the strategy to the chart then we need to look for its filename (and not the strategy name displayed on the chart, which title sets). To prevent confusion and not being able to find the strategy, set the strategy’s filename to something that closely resembles its displayed name on the chart.

overlay: showing a strategy on the instrument’s price bars or not

When the optional overlay argument of the strategy() function is set to true, the strategy displays on the chart’s instrument. With overlay=false or not set, the strategy displays in a separate chart panel below the instrument (TradingView, n.d.).

We use overlay like so:

strategy(title="My example strategy", overlay=true)

The overlay argument only accepts literal true/false values; we cannot set it to a built-in or user-defined variable, nor can overlay work with a Boolean true/false input option.

The visual difference between overlay set to true or false is:

Visual example of the different overlay options for TradingView strategies

A couple of insights when working with this argument are:

  • When the strategy is added to the chart before we set or change the overlay argument, the strategy needs to be removed from the chart and re-added to see the effect of the updated code.
  • We cannot specify in which subchart the strategy displays – with overlay=false the strategy simply appears in a new chart panel below the instrument’s price chart.
  • Each strategy can be overlaid on the chart’s instrument, even when its values are much higher or lower than the instrument’s prices. In that case, we’ll need to adjust the strategy’s scaling to prevent skewing the instrument’s price axis.
  • A strategy’s trades always appear in the chart area of the instrument, even when the strategy itself plots in a subchart.
  • Most TradingView functions follow the overlay argument setting, but some (like barcolor() that colours the instrument’s price bars) always work in the instrument’s chart area regardless of the overlay setting.

precision: setting the number of displayed decimals programmatically

The optional precision argument of the strategy() function specifies the number of digits after the floating point of the strategy’s values (TradingView, n.d.). We use precision as follows:

strategy(name="My example strategy", precision=3)

The precision argument can only be set to a literal integer that has a value of 0 or greater; it doesn’t accept a variable nor does it work with a numerical input option.

The default value of this argument is 4, and when we set it to 0 large values display with special formatting (TradingView, n.d.). That is, thousands show with the ‘K’ and millions with the ’M’ suffix. With that large strategy values don’t take up a lot of screen space.

With precision=3, a strategy displays like this:

Example of a strategy's number of decimals set programmatically

The value of the precision argument also affect how the values appear in the ‘Data Window’:

Example of the 'Data Window' with the strategy's values

Noteworthy features of precision are:

  • precision only affects how the strategy’s plotted values display; it doesn’t affect the script’s calculations nor does it influence at which price orders are submitted.
  • All values that the strategy plots are affected by precision. It’s not possible to, for example, have one plot display with 2 decimals while another uses 4 digits after the floating point.
  • A strategy that’s overlaid on the price chart uses the same precision as the chart’s instrument. In that case, TradingView doesn’t respect our precision setting. We take a closer look at this and the workarounds in a TradingView strategy that displays with a different precision than configured.

scale: setting a TradingView strategy’s price scale with code

The optional scale argument of the strategy() function sets which price scale the strategy’s plotted values attach to (TradingView, n.d.). When we don’t specify this argument, the strategy uses the chart’s right price scale.

The scale argument is useful when a strategy plots values much higher or lower than the chart’s prices. By attaching the strategy to a different price scale than the instrument uses, we prevent the strategy’s values from distorting the instrument’s price scale.

We use scale like this:

strategy(title="My example strategy", scale=scale.left)

The different values that the scale argument can be set to are (TradingView, n.d.):

Value Meaning
scale.right Attaches the strategy to the chart’s right price scale. This is the standard option when we don’t set scale.
scale.left Attaches the strategy to the left price scale. This value is typically used to prevent skewing the right price axis when more than one script plots in the same window or when we overlay the strategy on the chart’s instrument.
scale.none Doesn’t attach the strategy to any price scale. This way the plotted values cannot be read from a price scale, but it does allow the strategy to use the full chart area when plotting – and sometimes even plots beyond the chart’s margins. This scaling option requires that the strategy displays on the chart’s instrument.

For a visual idea of the different scaling options, on the following chart the Bollinger Bands use the right price scale:

Plotting values in TradingView that are attached to the right price scale

When we change the script’s scaling to the left axis (scale=scale.left), the chart looks as follows:

Example of plotting values in TradingView that are attached to the left price scale

Now the Bollinger Bands display as a horizontal line. This happens because the left scale, which is already used by the volume indicator, has a strongly different range of values.

When we plot the script with scale.none, it doesn’t attach to any price scale but uses the full chart area instead:

Plotting values in TradingView that aren't attached to a price scale

The Bollinger Bands look the same here as when they were attached to the right price scale. However, the Euro Bund price action is better visible now since the right price scale doesn’t need to accommodate the Bollinger Band values anymore.

Features of the scale argument include:

initial_capital: setting the strategy’s starting funds programmatically

The optional initial_capital argument of the strategy() function sets the strategy’s initial capital (TradingView, n.d.). This argument’s default value is 100,000 and to start the strategy with initial funds of 25k we use it like:

strategy(title="Example - initial_capital", initial_capital=25000)

We can set initial_capital only to a literal integer; it doesn’t accept a variable nor works with a numerical input option.

Because initial_capital specifies the strategy’s starting funds, it also influences the default order size when sizing orders based on an equity percentage. The initial capital setting is also reflected in built-in variables like strategy.equity (which returns the sum of initial capital, net profit, and open profit) and strategy.initial_capital that returns the strategy’s initial capital (TradingView, n.d.). A strategy’s initial capital and currency setting together affect its equity, as we discussed in initial capital, currency conversion, and a strategy’s equity.

currency: setting a TradingView strategy’s currency with code

The optional currency argument of the strategy() function configures the strategy’s currency setting (TradingView, n.d.). This way a strategy can calculate with a different currency than used by the instrument it trades (Pine Script Language Tutorial, n.d.). A consequence is that the strategy’s profit, equity, initial capital, drawdowns, and other performance metrics are reported in the strategy’s currency (and not in the currency of the traded instrument).

To have our strategy behave like it’s trading a Japanese Yen broker account, we use strategy() like:

strategy(title="Example - strategy currency", currency=currency.JPY)

The values that we can set the currency argument to are (TradingView, n.d.):

currency argument value Currency used by the strategy
currency.AUD Australian dollar
currency.CAD Canadian dollar
currency.CHF Swiss franc
currency.EUR Euro
currency.GBP Pound sterling
currency.HKD Hong Kong dollar
currency.JPY Japanese yen
currency.NOK Norwegian krone
currency.NONE Unspecified currency. With this setting, the strategy always uses the same currency as the instrument it trades and no currency conversion happens.
currency.NZD New Zealand dollar
currency.RUB Russian ruble
currency.SEK Swedish krona
currency.SGD Singapore dollar
currency.TRY Turkish lira
currency.USD United States dollar
currency.ZAR South African rand

There are three different situations in TradingView when it comes to currency conversion:

  • When we don’t set the currency argument, it defaults to currency.NONE and then no current conversion takes place. Instead, the strategy implicitly uses (and reports in) the same currency as the instrument it trades.
  • With currency set to the same currency as the instrument uses, then currency conversion also doesn’t happen.
  • When currency is set to a different currency than used by the instrument, then currency conversion does happen. Since the strategy then reports its results in the currency we specified, we get a more accurate estimate of how the strategy would perform in the currency of our trading capital.
Tip: TradingView performs currency conversion with the closing price of the previous trading day (Pine Script Language Tutorial, n.d.). That means the same conversion rate is used for the whole trading day instead of the (almost) real-time forex price that brokers would use. This creates a small difference in results due to currency conversion.

Besides influencing the values in the strategy’s performance report, the currency argument affects other features too:

pyramiding: limiting a TradingView strategy’s entries in the same direction

The pyramiding argument of the strategy() function specifies how many entries in the same direction are allowed (TradingView, n.d.). This argument’s default value is 0, and with that only one entry order in the same direction is possible while the strategy will reject additional entries (TradingView, n.d.).

To allow multiple entries in the same direction, we can use pyramiding like this:

strategy(title="My example strategy", pyramiding=4)

The pyramiding argument can only be set to a literal integer (like we do above); it doesn’t accept a variable nor a numerical input option.

Noteworthy features of pyramiding are:

  • pyramiding specifies the number of entries in the same direction, but doesn’t set the total position size. This latter consists out of the sum of each individual order’s size. We can set a strategy’s default order size to a fixed quantity, a cash amount, or an equity percentage.
  • TradingView evaluates an order’s conditions when it generates, not when the order executes (Pine Script Language Tutorial, n.d.). This has an important consequence for the strategy’s pyramiding setting. When we generate several orders at the same time (or quickly after each other), then all of them are approved when the strategy’s current position hasn’t reached the pyramiding limit yet. But when all of those orders execute, we can easily end up with a position that’s bigger than allowed by pyramiding. For an analysis and possible workarounds, see the impact of multiple entry orders on a strategy’s pyramiding setting.
  • A strategy that doesn’t respect its pyramiding setting can also be caused by how we submit entry orders. While the strategy.entry() function respects the pyramiding option, the strategy.order() function submits orders without checking the strategy’s pyramiding setting (Pine Script Language Tutorial, n.d.; TradingView, n.d.). See the impact of strategy.order() on a strategy’s pyramiding setting for more (including a workaround).

default_qty_type and default_qty_value: setting default order size

Configuring the default order size with the strategy() function is possible too. This order size is used by the strategy when we don’t set the qty argument of the strategy.entry(), strategy.exit(), or strategy.order() functions when submitting an order.

The default order size is set with the default_qty_type and default_qty_value arguments of strategy(), and these can be combined in three ways (TradingView, n.d.):

So to have a strategy trade with a default order size of 10 contracts, we use strategy() like:

strategy(title="Example - fixed number of contracts", 
     default_qty_type=strategy.fixed, default_qty_value=10)

And sizing orders based on 2,000 cash is done like:

strategy(title="Example - fixed cash amount", 
     default_qty_type=strategy.cash, default_qty_value=2000)

Noteworthy features of he default_qty_type and default_qty_value arguments are:

max_bars_back: the number of bars a strategy calculates on

The max_bars_back argument of the strategy() function sets the number of historical bars the strategy references in its calculations (TradingView, n.d.). By default, TradingView automatically calculates how many price bars a strategy needs for its calculations (TradingView, n.d.). But in rare circumstances, the code is so complex that TradingView cannot correctly estimate that required amount of price bars.

When TradingView cannot determine the bar amount programmatically, the script generates the ‘out of depth at index’ error message. We fix that error message by setting max_bars_back to the number of bars that we think the strategy should use for its calculations.

Setting max_bars_back goes like:

strategy(title="My example strategy", max_bars_back=50)

The max_bars_back argument needs to be set to a literal integer; it doesn’t accept numerical variables nor numerical input options.

A visual explanation of the max_bars_back argument is the following:

Visual example of the max_bars_back argument of TradingView strategies

Here the strategy plots the highest high and lowest low of the last 20 bars. Because these extreme prices need at least 20 price bars (including the current bar) to calculate successfully, we see the script ‘waiting’ until there are enough price bars on the chart.

Having to set the max_bars_back argument ourselves is quite rare; currently, there are only two functions that can require that max_bars_back is set: pivothigh() and pivotlow() (TradingView, n.d.). It’s also possible that in other cases we set the max_bars_back argument, but that only happens when the code logic is so complex that TradingView cannot ‘read’ from the code how many historical bars the script’s calculations use.

And even then we only need to set the max_bars_back argument when TradingView generates the ‘out of depth’ at index error message. The exact value that we set to this argument depends on how many bars the strategy references in its calculations, and that differs with every script.

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. Note that if we do set max_bars_back but give it a too low value, then TradingView still attempts to calculate this value automatically (TradingView, n.d.). In that case the script can still trigger an error even though we’ve set max_bars_back.

backtest_fill_limits_assumption: specifying how strict limit orders fill

The backtest_fill_limits_assumption argument of the strategy() function specifies how strict TradingView fills limit orders during backtesting. On historical bars, limit orders are only considered filled when the bar’s range exceeds the limit price by the number of ticks set by this argument (Pine Script Language Tutorial, n.d.; TradingView, n.d.).

This backtest_fill_limits_assumption feature makes our backtesting 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.

We use backtest_fill_limits_assumption like this:

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

The backtest_fill_limits_assumption argument can only be set to literal integers; it doesn’t accept variables nor numerical input options. It has a default value of 0, and so without setting this argument, a strategy’s limit orders fill at their limit price during backtesting.

Noteworthy features of the backtest_fill_limits_assumption argument are:

  • The value set by backtest_fill_limits_assumption only influences when TradingView considers our limit order filled during backtesting; it has no influence on the actual order fill price (Pine Script Language Tutorial, n.d.).
  • backtest_fill_limits_assumption only affects backtesting; when the strategy runs on real-time data, orders are triggered and filled with real-time prices (Pine Script Language Tutorial, n.d.).
  • During backtesting, limit orders fill at their limit price – even though they might be triggered at a much higher or lower price due to backtest_fill_limits_assumption. This can give the surprising situation that limit orders fill on price bars that did not reach the limit price (see example image below).
  • When TradingView calculates a strategy on historical data, it assumes there are no price gaps inside a bar and that each price inside the bar’s range is traded with sufficient volume. This means that a limit order can fill at any price inside a bar (Pine Script Language Tutorial, n.d.).

To see how backtest_fill_limits_assumption influences when a limit order fills, let’s examine the same order multiple times:

Example of a TradingView strategy with backtest_fill_limits_assumption=1

Here we used backtest_fill_limits_assumption=1. This means that our sell limit order at 3012 is considered filled by TradingView when the range of the historical bar reaches 3013. We see that happening in the annotated bar, which has a range of 3008-3014.

Here we have the same order but this time backtest_fill_limits_assumption is set to 4:

Example of a TradingView strategy with backtest_fill_limits_assumption=4

Now the same sell limit order of 3012 requires that the 3016 price is touched before this order is considered filled. That limit order price plus 4 ticks is now reached a bar later than in the previous chart.

A more extreme example is when we set backtest_fill_limits_assumption to 12. The order then fills like this:

Example of a TradingView strategy with backtest_fill_limits_assumption=12

Here our sell limit order at 3012 only fills when the bar reaches 3024. Now it takes several more price bars before this order is fills during backtesting, and if it weren’t for the uptrend then the sell limit order wouldn’t been filled at all. Note that, when this order fills, it does so at the limit price of 3012 even though the bar on which it fills doesn’t even reach that price.

calc_on_order_fills: an intra-bar calculation when an order fills

The calc_on_order_fills argument of the strategy() function makes the strategy perform, when set to true, an additional intra-bar calculation after an order fills (Pine Script Language Tutorial, n.d.; TradingView, n.d.). This argument’s default value is false, and in that case the strategy doesn’t perform an extra intra-bar calculation after an order fills during backtesting or real-time trading (TradingView, n.d.).

The calc_on_order_fills argument is used like this:

strategy(title="Example - calc_on_order_fills", calc_on_order_fills=true)

This argument can only be set to literal true/false values; it doesn’t accept variables nor can work with a true/false input option.

The default behaviour of TradingView strategies on real-time and historical data is to only calculate when the price bar closes (Pine Script Language Tutorial, n.d.). During that script calculation, the strategy can generate an order to submit at the open of the next bar and which can fill sometime during that price bar. But our script then also has to wait till that next bar closes before calculating again and performing additional actions based on whether the order filled or not. Depending on the chart’s time frame, there can be a long ‘waiting period’ between when an order fills and the bar closes.

Now with the calc_on_order_fills argument set to true, the strategy still calculates when the real-time and historical bars close (Pine Script Language Tutorial, n.d.). But the script then also calculates one additional time after an order fills during backtesting or real-time trading. This way our strategy can perform an extra action immediately after the order fills, like placing another order or updating the profit target based on the order fill price.

Characteristics of calc_on_order_fills are:

  • The backtest results of a strategy that uses calc_on_order_fills=true do not indicate how the script would perform in real-time trading. The cause for this difference is that, during backtesting, at most 4 calculations happen per bar; but during real-time trading, there can be as many intra-bar calculations as there are real-time price updates (Pine Script Language Tutorial, n.d.). Depending on the strategy’s code, this can have a minor to big effect on its behaviour. For more, see inaccurate backtest results with calc_on_order_fills.
  • We can quickly build up a position with calc_on_order_fills since each filled order triggers an intra-bar script calculation, which we can then use to submit yet another order. And when that order fills, the script performs yet another extra calculation. This does, however, require that the order’s entry or exit conditions are still valid when the strategy performs those extra intra-bar calculations. See why an order doesn’t fill during an intra-bar calculation for more.

calc_on_every_tick: calculating a strategy with every real-time price update

The calc_on_every_tick argument of the strategy() function makes the strategy process every real-time price update when set to true (TradingView, n.d.). This argument defaults to false, and in that case the script only calculates on the close of each price bar.

To calculate with every real-time tick, we set calc_on_every_tick like this:

strategy(title="My example strategy", calc_on_every_tick=true)

The calc_on_every_tick argument only accepts literal true/false values; it doesn’t work with variables nor with a true/false input option.

The advantage of processing every real-time tick is a greater speed. Let’s say we want to submit 5 entry orders, one with each script calculation. Since a strategy by default calculates on the close of each price bar (Pine Script Language Tutorial, n.d.), it takes 5 bars to submit those orders. But with calc_on_every_tick=true, it can take 10 seconds (depending on how many real-time price updates there are for the traded instrument).

Depending on the price data that the strategy runs on, calc_on_every_tick has a different influence on the strategy’s calculations (Pine Script Language Tutorial, n.d.; TradingView, n.d.):

  • On historical data, the strategy calculates on the close of each price bar, regardless of whether calc_on_every_tick is enabled or not.
  • On real-time data, the strategy calculates with every price update (when calc_on_every_tick=true) or only on bar close (when calc_on_every_tick=false or missing from the strategy() function).

This different behaviour on historical and real-time data has several consequences:

  • The backtest results of a script that uses calc_on_every_tick=true do not indicate how the strategy performs during real-time trading. Due to the extra calculations on real-time data, it can seem were trading two different strategies when comparing backtest results with real-time performance. We examined this in inaccurate backtest results when backtesting calc_on_every_tick.
  • Since a strategy with calc_on_every_tick=true can perform dozens to hundreds of calculations per bar, its speed is much higher than we’d normally see. This also means that a small error or misconfiguration becomes a problem quickly. For instance, the strategy’s pyramiding limit can easily be violated by submitting orders quickly after each other. Things like this make it even more important that calc_on_every_tick=true strategies are extensively tested on real-time data.

Besides calculating a strategy with every real-time tick (calc_on_every_tick), a strategy can also calculate after an order fills (calc_on_order_fills). The difference between these two related arguments is (Pine Script Language Tutorial, n.d.; TradingView, n.d.):

  • With calc_on_every_tick=true, the strategy calculates on every real-time price update. This feature only affects the strategy’s behaviour on real-time data but doesn’t change its backtest performance.
  • With calc_on_order_fills=true, the strategy performs an additional intra-bar calculation when an order fills. This extra calculation happens on real-time and historical price bars. But while on historical bars the strategy can calculate on the bar’s open, high, low, and close; on real-time data that extra intra-bar calculation can happen with every tick. This means there are a lot more calculation opportunities in real time than there are on historical bars.

This ends our overview of the different ways to programmatically configure a trading strategy in TradingView and the different caveats when doing so. See all TradingView programming articles to learn more about other topics.

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