Why your backtest disagrees with your broker
Every trader eventually has the same argument with a backtest: the report says the strategy made money, the broker statement says otherwise. The gap is almost never mysterious. It is made of three boring things, and each one is measurable.
1. The price you traded was not the price in the file
Candle files carry one price series. Your broker trades two: bid and ask. A long entry fills at ask, a long exit at bid, so a round trip costs the spread before the market moves at all — and a backtest that trades the candle price silently skips that cost.
Two ways to fix it, in increasing order of honesty:
- A fixed spread in pips. Better than nothing, and useful when you deliberately want a stable assumption across years. Wrong in exactly one way: real spread is not fixed. It widens at rollover, before news, and during thin sessions.
- A tick dataset with recorded bid and ask. Now spread is a measurement instead of a setting. Rollover widening is there because it happened.
If your strategy holds for hours, spread noise rarely matters. If it targets a few pips, spread is a large part of the strategy, and a constant is a guess about your own results.
2. Same-bar collisions
Price touches your stop-loss and your take-profit inside one candle. Only one can be paid. Candle data does not record which came first, so the engine must apply a documented convention — and a strategy whose edge depends on that coin flip did not have an edge.
With a tick dataset, there is no coin flip: the recorded tick sequence says which level traded first. This is the single most valuable thing tick data gives you, and it is also the cheapest way to discover that a strategy was never profitable.
3. Where the fill actually happened
A limit order does not fill because price crossed it; it filled because price traded through it. A stop fills at the next available price, not at the trigger. Slippage is not a decoration on the report, it is the mechanism by which orders get filled.
Our synthetic tick path per base candle is deterministic (bullish candles O→L→H→C, bearish O→H→L→C) and real tick data overrides it. That is enough to resolve SL/TP collisions and pending-order triggers consistently, and it makes runs reproducible: same data version plus same rules equals same fills, which is what makes a comparison meaningful at all.
Shrinking the gap, in order
- Import the finest data you can obtain and keep it as the dataset base.
- Use recorded spread when your data has it; state the assumption when it does not.
- Charge commission and swap — including triple swap on Wednesday — instead of pretending they are zero.
- Re-run the same strategy on a window you did not tune on, and accept the difference as the estimate.
- Only then argue with the broker statement.
None of this makes backtests predictive. It makes them falsifiable: a simulation you can trust enough to disqualify a bad idea with.
Related
- Importing Data — what a tick archive must contain.
- Creating a Replay — spread and dataset choices when you start a session.
- Troubleshooting — the same-bar collision answer in one line.