TradingView Backtesting

Is the TradingView Strategy Tester Accurate?

TradingView Strategy Tester simulates orders under specified data and execution assumptions. Its results can help evaluate a strategy, but there is no universal accuracy percentage or guarantee that simulated fills match a broker. Check costs, intrabar order sequencing, calculation settings, future-data leaks, and chart type before interpreting the returns. A high win rate measures the simulated trades, not the accuracy of the simulation.

Analyze Exported Trades

What the broker emulator assumes

TradingView fills simulated orders from available price data. With default bar-close calculation, a market order created at the close normally fills on the next available tick, typically the next bar open in historical testing. Pending stop and limit orders can fill within a later bar. They do not all wait for its close.

  • Without finer historical detail, an open nearer the high gives an open → high → low → close path; an open nearer the low gives open → low → high → close. Candle color does not choose the path.
  • If a price-based order level is crossed in the gap between bars, the emulator can fill at the new open instead of the requested level.
  • When both bracket levels lie inside one candle, inspect which orders were active and the inferred sequence. Same-bar entry and exit alone do not prove an error.

Bar Magnifier adds detail, not a broker execution record

Bar Magnifier uses lower-interval OHLC data to refine historical fills. The interval depends on the chart interval; it is not always one minute. On time-based charts it does not reconstruct every historical tick, queue position, or available liquidity. Compare the affected trades with the setting enabled and disabled, keeping all other inputs fixed.

  • Lower-timeframe coverage is limited. TradingView documents a maximum of 200,000 requested lower-timeframe bars, so older chart bars may have no magnified coverage.
  • An unchanged result may mean the orders were unaffected or that finer data was unavailable. It does not certify accuracy.
  • Record whether the account and dataset allow the setting. If unavailable, mark intrabar sequencing as an unresolved limitation.

Separate calculation timing from fill timing

Changing when the script runs can change its orders. Historical bars do not preserve the same sequence of updates seen while a realtime bar is open. Reloading converts those elapsed bars into historical calculations, which can change results for strategies that depend on intrabar updates.

SettingEffect to audit
calc_on_every_tickRecalculates on realtime updates. It does not supply missing historical tick data; compare recorded forward signals with the same bars after reload.
calc_on_order_fillsRuns another calculation after a fill. Inspect repeated same-bar orders and whether the strategy relies on information or fill prices unavailable in live execution.
process_orders_on_closeAllows an additional fill attempt on the closing tick. An alert sent after a session closes may reach the broker only after that execution opportunity has passed.

Model costs and chart prices explicitly

Use the fee schedule for the actual instrument, broker, order size, and account tier. Commission applies on entries and exits. Slippage is a fixed number of ticks added adversely to market and stop fills; it is a scenario assumption, not a measured spread or a variable market-impact model. No single tick allowance fits every instrument.

  • Record commission type and value, tick size, quantity, margin, and currency. Keep spread assumptions separate from fees to avoid counting the same cost twice.
  • For limit entries, review backtest_fill_limits_assumption. Requiring price to move beyond a limit changes the fill test but does not reproduce queue priority.
  • Use standard candles or bars for the baseline. Renko, Kagi, and other non-standard charts can use synthetic prices.
  • Heikin Ashi has a specific fill_orders_on_standard_ohlc option for standard-price fills. Signals can still depend on synthetic Heikin Ashi values; this option is not a general fix for every non-standard chart.

Check higher-timeframe data for future leaks and repainting

A higher-timeframe request using an unoffset expression with lookahead_on can expose future values on historical bars. For the previous confirmed higher-timeframe value, use an expression offset by one bar together with lookahead_on, and require the requested timeframe to be higher than the chart. The two parts work together. Merely switching to lookahead_off does not prevent a current higher-timeframe value from changing while that bar remains open.

A complete Pine Script baseline for controlled comparisons

This educational strategy uses a confirmed higher-timeframe EMA and a bracket measured in ticks from the simulated entry fill. Its 0.05% commission and two-tick slippage are illustrative inputs, not broker benchmarks. Use a standard time-based chart below the filter timeframe. Check affordability and tradable quantity for the chosen symbol. This page reports no measured returns or live-fill comparison.

Pine Script v6: fixed assumptions for an audit runpinescript
//@version=6
strategy("Backtest assumption audit", overlay=true,
     initial_capital=10000,
     default_qty_type=strategy.percent_of_equity, default_qty_value=10,
     margin_long=100, pyramiding=0,
     commission_type=strategy.commission.percent, commission_value=0.05,
     slippage=2, process_orders_on_close=false,
     calc_on_every_tick=false, calc_on_order_fills=false,
     use_bar_magnifier=false)

string filterTf = input.timeframe("1D", "Higher timeframe")
int fastLen = input.int(10, "Fast EMA", minval=1)
int slowLen = input.int(30, "Slow EMA", minval=1)
int stopTicks = input.int(100, "Stop distance in ticks", minval=1)
int targetTicks = input.int(150, "Target distance in ticks", minval=1)

if timeframe.in_seconds() >= timeframe.in_seconds(filterTf)
    runtime.error("Choose a filter timeframe higher than the chart timeframe.")

float confirmedEma = request.security(syminfo.tickerid, filterTf,
     ta.ema(close, 50)[1], lookahead=barmerge.lookahead_on)
float fastEma = ta.ema(close, fastLen)
float slowEma = ta.ema(close, slowLen)
bool crossedUp = ta.crossover(fastEma, slowEma)

if barstate.isconfirmed and crossedUp and close > confirmedEma and strategy.position_size == 0
    strategy.entry("Long", strategy.long)
    strategy.exit("Bracket", "Long", loss=stopTicks, profit=targetTicks)

plot(fastEma, "Fast EMA", color=color.teal)
plot(slowEma, "Slow EMA", color=color.orange)
plot(confirmedEma, "Confirmed higher-timeframe EMA", color=color.purple)

Repeatable comparison checklist

Use this proposed audit procedure on your own strategy. Freeze the script and dataset first, then save each run under a distinct name. Do not tune entry rules between runs. The aim is to explain sensitivity to assumptions, not to select the most attractive equity curve.

  • Treat unexplained discrepancies as unresolved. A matching headline metric is insufficient if the individual trades differ.
  • Separate market-data or session differences from delivery latency, rejected orders, partial fills, and liquidity effects when comparing with broker records.
  • Retain screenshots or exports of the settings alongside the trade file. A CSV alone cannot establish whether the source code leaked future information.
RunChange only thisSave and investigate
A: baselineUse standard bars and documented settings.Script, properties, data range, trade export, open positions, net profit, drawdown, and trade count.
B: costsReplace illustrative costs with documented fees and a stated slippage scenario.Entry/exit prices, commissions, and results. Reconcile cost changes on several individual trades.
C: intrabar detailEnable Bar Magnifier when available.Trades whose entry or exit changed, lower-timeframe coverage, and any unresolved stop/target ordering.
D: sensitivityIncrease one cost assumption at a time using values justified for your instrument.Where results become dependent on a small fill-price change; retain losing runs too.
E: unseen periodUse a date range excluded from parameter selection.Apply the frozen rules and costs. Report the sample and any deterioration without retuning it away.
F: forward observationRecord new signals as they occur, then reload later.Signal timestamps and subsequent historical signals. For broker records, reconcile order submission, acceptance, fill time, price, and size separately.
Where Pineify fits

Backtest Deep Report

Analyze exported TradingView trade records after checking the simulation settings. The report cannot recover missing intrabar data or detect source-code lookahead from a trade CSV.

Also useful: Pine Script AI Coding Agent. Use the coding agent to help review strategy code and revise cost, data-request, or execution settings. Validate the revised script and rerun the comparison.

Analyze Exported Trades

Frequently asked questions

Educational information, not investment advice. Simulated results do not guarantee live fills or future returns. The example and checklist are methods to investigate assumptions, not evidence of a profitable trading system.

Sources and verification

Published by Pineify. Pineify is an independent product and is not affiliated with TradingView. Sources support the technical explanations; examples do not establish trading performance.