Edgoro
Strategy

How to backtest on TradingView: the Strategy Tester settings that change your results

Every TradingView Strategy Tester property that changes a backtest: order size, commission, slippage, margin, bar magnifier and fills, with the strategy() code.

Two people run the same Pine Script strategy on the same chart and get very different reports. Nine times out of ten the code isn't the difference: the settings are. Commission, slippage, order size, margin and the way fills are simulated inside a bar can turn a smooth equity curve into a flat one, or the other way round.

This guide goes through the Strategy Tester's properties in the order you'll meet them, explains what each one does to fills and profit, and shows how to put them in the strategy() declaration so the report doesn't depend on someone remembering to click. Then it gives a routine for a backtest you can actually learn from. It's about testing honestly, not about finding a strategy that wins.

Where the settings live

Every setting exists in two places:

  • In the code, as parameters of strategy(). These are the defaults anyone gets when they add the script.
  • In the Properties tab of the strategy's settings on the chart. Changing a value there overrides the code for that chart only.

That split causes a lot of confusion. You tweak commission in the Properties tab, the report improves, and the code you share still carries the old default. Treat the declaration as the record of your assumptions, and use the Properties tab for quick experiments only.

The properties, one by one

Propertystrategy() parameterWhat it changesSensible starting point
Initial capitalinitial_capitalThe base for percentage sizing and returnsThe account size you'd really trade
Base currencycurrencyThe currency the report is inYour account currency
Order sizedefault_qty_value + default_qty_typeSize when strategy.entry() has no qty: contracts, cash or % of equityA modest % of equity, or risk-based qty in code
PyramidingpyramidingHow many entries in the same direction can stackThe default (a single position) unless you scale in on purpose
Commissioncommission_type + commission_valueCost per order: a percentage, cash per contract or cash per orderYour broker's real cost, charged on entry and exit
Verify price for limit ordersbacktest_fill_limits_assumptionA limit order only fills if price trades through it by this many ticks1–2 ticks on liquid markets
SlippageslippageTicks added against you on market and stop fillsA few ticks; more on thin markets and around news
Margin for long / short positionsmargin_long, margin_shortShare of position value that equity must cover; below it, simulated margin calls100 without leverage; 100 ÷ leverage otherwise
Recalculate: after order is filledcalc_on_order_fillsRuns the script again inside the bar after each fillOff, unless your logic needs it
Recalculate: on every tickcalc_on_every_tickRecalculates on live ticks; history only has closed barsOff for backtests
Fill orders: using bar magnifieruse_bar_magnifierUses lower-timeframe data to decide what filled first inside a barOn, where your plan includes it
Fill orders: on bar closeprocess_orders_on_closeMarket orders fill at the signal bar's close instead of the next openOff, unless you can really trade the close
Fill orders: using standard OHLCfill_orders_on_standard_ohlcOn Heikin Ashi and similar charts, fills use real pricesOn whenever the chart type isn't standard candles

Labels in the Properties tab change from time to time; the parameter names in the reference manual are the stable reference.

How TradingView decides what filled inside a bar

On historical bars the simulated broker only knows each bar's open, high, low and close, not the path in between. It assumes one: if the high is closer to the open than the low is, price went open → high → low → close; otherwise open → low → high → close.

That assumption matters whenever a stop and a target both sit inside the same bar's range. The report shows one of them filled, but the real market might have hit the other first. The bar magnifier replaces the guess with data from a lower timeframe, which makes those bars much closer to reality.

A useful test: run the strategy with the magnifier on and off. If the results change a lot, many of your trades are decided inside a single bar, which usually means stops and targets that are tight relative to the bar size. Either accept the magnifier's version or test on a lower timeframe.

The other default rules are worth knowing too:

  • Market orders placed when a bar closes fill at the next bar's open.
  • Limit orders fill at the limit price or better; if price gaps through, at the open.
  • Stop orders fill at the stop price or worse; if price gaps through, at the open, plus slippage.
  • Slippage applies to market and stop fills, not to limit fills.

Putting the settings in code

Here's a declaration with every assumption written down, plus a simple strategy so the script runs. The strategy is a placeholder for testing the settings, not a recommendation:

//@version=6
strategy("Backtest settings demo", overlay = true,
  initial_capital = 10000,
  currency = currency.USD,
  default_qty_type = strategy.percent_of_equity,
  default_qty_value = 10,
  pyramiding = 0,
  commission_type = strategy.commission.percent,
  commission_value = 0.05,
  slippage = 2,
  backtest_fill_limits_assumption = 1,
  margin_long = 100,
  margin_short = 100,
  process_orders_on_close = false,
  calc_on_every_tick = false,
  calc_on_order_fills = false,
  use_bar_magnifier = true,
  fill_orders_on_standard_ohlc = true)

// Test window: entries are only allowed between these dates
startTime = input.time(timestamp("2020-01-01T00:00:00"), "Start", group = "Test window")
endTime   = input.time(timestamp("2025-12-31T23:59:59"), "End", group = "Test window")
inWindow  = time >= startTime and time <= endTime

fast      = ta.ema(close, 20)
slow      = ta.ema(close, 50)
atr       = ta.atr(14)
crossUp   = ta.crossover(fast, slow)
crossDown = ta.crossunder(fast, slow)

var float stopPrice = na
if inWindow and crossUp and strategy.position_size == 0
    stopPrice := close - 2 * atr
    strategy.entry("Long", strategy.long)
if crossDown
    strategy.close("Long")
strategy.exit("Stop", "Long", stop = stopPrice)

// Close anything still open once the window ends, so the report covers the window only
if not inWindow and strategy.position_size != 0
    strategy.close_all()

plot(fast, "Fast EMA", color.teal)
plot(slow, "Slow EMA", color.orange)

A few notes:

  • commission_value = 0.05 with strategy.commission.percent charges 0.05% of the order value on every order, so a round trip costs about 0.1%. For futures, strategy.commission.cash_per_contract is usually closer to how you're billed.
  • slippage = 2 is in ticks, so its money value depends on the symbol's tick size.
  • TradingView's forex and CFD data is a single price stream, so the spread isn't modelled. Add it through slippage or commission, or the backtest trades at prices you'd never get.
  • use_bar_magnifier = true only has an effect on plans that include the feature; elsewhere it's ignored.

Why a test window in code helps

The Strategy Tester lets you pick a date range, and that's fine for a quick look. The inWindow filter above does something extra: the indicators still calculate on all the bars before startTime, so a 200-period average is fully warmed up when the first trade can happen. It also lets you run the same code on two separate periods by changing two inputs, which is the basis of an out-of-sample test.

Reading the report

Start with these, roughly in this order:

  • Total trades. With fewer than a few dozen, the other numbers are mostly noise.
  • Net profit after costs, compared with buy-and-hold over the same window.
  • Maximum drawdown. Ask whether you'd have kept trading through it. The drawdown calculator shows what it takes to recover.
  • Average trade versus costs. If the average trade is barely larger than commission plus slippage, a small change in costs flips the result.
  • Win rate together with average win and loss. Either alone says little. Put them into the expectancy calculator.
  • Longs versus shorts, and results over time in the list of trades: one great year can carry a weak strategy.
  • Margin calls in the list of trades. If you see them, the position sizes don't fit the margin setting.

A backtesting routine that holds up

  1. Write costs, size and margin into the declaration, as above.
  2. Compare with the bar magnifier on and off, and keep the more realistic result.
  3. Split the history. Choose settings on an older window, then run them unchanged on a recent one.
  4. Check for repainting. Signals that move after the bar closes make every number meaningless; see Pine Script repainting explained.
  5. Look at neighbouring settings. If a 20-period length works and 18 and 22 don't, you've found noise.
  6. Try other symbols in the same asset class.
  7. Forward-test on paper trading or a demo account before any real money is involved.

The traps this routine guards against are explained in more depth in 8 backtesting mistakes that make a strategy look better than it is.

What the Strategy Tester can't tell you

It can't see liquidity, partial fills or spreads that widen at the open and around news. Its data can differ slightly from your broker's. And it can't tell you whether the market will behave next year the way it did in the test. A careful backtest narrows the guesswork; it doesn't remove it.

Sources and further reading

Try it with Edgoro

When you ask Edgoro for a TradingView strategy, the declaration comes with initial capital, position size and commission already set, ready for the Strategy Tester. For crypto, the Backtest Lab runs strategies on real exchange data with fees and slippage you choose. Either way, a backtest describes the past, so forward-test before you trust it.

Backtested results are hypothetical and don't account for every real-world cost or condition. Nothing here is investment advice, and trading involves substantial risk of loss.

Build it with Edgoro

Describe your strategy in plain English and get a TradingView indicator in Pine Script v6 or a MetaTrader 5 Expert Advisor in minutes. Every first purchase is covered by a 7-day money-back guarantee.

Build your indicator with Edgoro