Where the gap comes from
"Backtests are optimistic" is true and useless. The gap has specific causes, each of which you can check on your own script, and they sit in three different places in the documentation.
Bar-level execution assumptions
The tester fills orders against bar data. Live, you fill against a book.
| Assumption | What it hides [1] |
|---|---|
process_orders_on_close off | orders fill at the next bar's open, not where your signal fired |
process_orders_on_close on | orders fill at the close of the signal bar — better aligned, but only reachable if you can actually trade the close |
calc_on_order_fills off | the script does not re-evaluate on a fill, so intrabar sequences the live market would produce are not modelled |
pyramiding default of 1 | a second signal is ignored, in the test and live alike |
None of these is wrong. They are modelling choices, and the point is to know which one you made.
The historical/realtime asymmetry
A finished bar holds four numbers. A forming bar's high, low and close are still moving [2]. The tester runs on finished bars; live runs on a bar that is not finished yet.
That single fact produces most of the ordinary divergence. A condition that
compares against high is comparing against a final value in the test and a
provisional one live. A strategy with calc_on_every_tick executes every tick
live and only at bar close historically [2] — the same script, two execution
models.
Costs, which are the largest single factor
Commission and slippage are declaration parameters, and a tester with neither is modelling a market that does not charge you. Slippage is set in ticks [1], so getting the unit wrong scales the error by the instrument's tick size.
This is covered properly in commission, slippage and capital; the short version is that cost settings usually explain more of the gap than execution timing does.
Two that surprise people
Non-standard chart types. TradingView states plainly that they produce unrealistic results by default and that standard charts should be used for realistic backtesting [1]. A Heikin Ashi or Renko backtest cannot be reproduced with real fills — the bars themselves are derived, not traded.
The 9,000-order cap. Beyond it, v6 silently trims the oldest orders rather
than raising an error [3], and trimmed trades return na from
strategy.closedtrades.*. A long high-frequency backtest can therefore be
reporting on a subset of its own trades.
Shrinking the gap, in order of effect
Ordered by how much each step typically moves the result, largest first.
1. Put real costs in. Commission and slippage from your own account, not a number from an article. This usually accounts for more of the gap than everything below it combined.
2. Test on a standard chart. If the backtest was run on Heikin Ashi or Renko, the result is not comparable to live trading at all [1] and nothing else on this list will fix that.
3. Decide the fill model deliberately. Choose process_orders_on_close
knowingly rather than by default, and be honest about whether you can trade the
close of a bar on the timeframe you are testing. On a daily chart, you often
cannot.
4. Check for lookahead. If the script uses request.security(), confirm
there is no future leak — see
repainting and lookahead.
This is a binary: either the historical run had information the live run cannot
have, or it did not.
5. Look at the trade count, not only the return. Costs and execution assumptions scale with frequency, so a high-frequency result is far more sensitive to every item above. A strategy with 40 trades has not been tested, whatever its return says.
6. Re-run at double your cost estimate. A strategy that survives that is interesting. One that does not is telling you its result is the cost assumption.
Then paper trade, and expect it to still differ
Paper trading removes the historical/realtime asymmetry [2] because it runs forward on forming bars, the way live does. What it does not remove is your fill — a paper fill is still a modelled fill, not a queue position.
So the sequence that actually works is: backtest to reject bad ideas cheaply, paper trade to catch the execution assumptions the backtest hid, then live small to find out what your fills really cost.
The honest limit of all of this
None of these steps makes a backtest predictive. A tester with correct costs, standard bars, a deliberate fill model and no lookahead is still a model, and the market is not obliged to resemble it.
What the work buys you is different and worth more: a test that fails honestly. Most strategies that look good with default settings stop looking good once costs are real — and finding that out in the tester costs nothing, while finding it out live costs the account.
Tactix AI on this workflow
AlfaTactix includes Tactix AI: use Tactix Studio to describe your idea in plain language and draft timeframes, signals, filters, and risk into the same six-step Strategy Builder form — or open Tactix Guide on any step when you only need a field explained. Review every value, then export MQL5 or Pine Script from Code Generator (form-first — not untested prompt-to-code).

