TESTING · 8 MIN READ
How to backtest a strategy without fooling yourself
Every backtest is a simulation with assumptions baked in, and those assumptions determine the result at least as much as the strategy does.
The five assumptions that inflate results
- Fixed [spread](/learn/glossary/spread). Live spread widens at rollover, at session transitions and around news — exactly when signals cluster. A test using a constant narrow spread is testing a market that does not exist.
- No [slippage](/learn/glossary/slippage). Replay fills at the modelled price; reality does not. Every entry and exit is slightly worse live, and it compounds across hundreds of trades.
- Favourable intrabar sequence. On bars where both stop and target were touched, the tester must assume which came first. Optimistic assumptions inflate results substantially, and the effect is largest on tight stops.
- Lookahead. Using information not available at the time. A swing point is not confirmed until several bars after it forms, so a test treating it as known at formation is measuring a strategy nobody can trade.
- Position-sizing fantasy. Fractional lots, no broker minimum, no margin constraint. Real accounts have all three.
What makes a backtest trustworthy
Hold data back and test on it once. Fit and refine on one period, then run a single test on a period never used during development. Testing on the held-out data more than once destroys its value — each look leaks information until the out-of-sample period is quietly part of the training set.
Prefer fewer parameters. Every additional tunable is another dimension along which noise can be fitted, and the number of combinations tried should raise the evidence bar rather than lower it.
Test with the code that trades. Reimplementing a strategy for backtesting introduces divergence that is invisible until live results disagree. Our replay runs real broker bars through the live signal path with the real tracker driving selection, so no separate implementation exists.
The numbers to publish
Maximum drawdown, the length of the test period, whether an out-of-sample period was used, and the number of trades. A win rate without an average win and average loss beside it is the flattering half of the picture, and a precise figure from a small sample is noise — see sample size.
Our own, measured two ways. One continuous six-month run at $1,000 with live percentage sizing returned +3.5% in total across 42 trades, 7.2% drawdown, 38% win rate. Seven separate monthly windows restarting from a blank slate at a fixed trade size returned more, at a 21.2% drawdown and 44.8% win rate in-sample (Jan–Jul 2026) and a 20.5% drawdown and 36.5% win rate out-of-sample (Aug–Dec 2025). The windowed figures validate the edge; the continuous one is what an installed bot does. Neither sample is large enough to treat as precise.
How the same strategy produced two different results
Those two sets of figures are the same rules on the same instrument over overlapping dates. They differ by roughly seven times on total return. Nothing was changed between them except how the position size was calculated, and that is worth walking through, because it is the most expensive backtesting mistake we have made and it does not appear on any list of the usual five.
| Windowed runs | Continuous run | |
|---|---|---|
| Position size | Fixed 0.01 lot every trade | Percentage of live equity |
| Learning state | Reset to blank each month | Carried forward throughout |
| Balance effect | None — size never changes | Wins and losses compound into the next size |
| Answers | Do these rules have an edge? | What happens to an installed bot? |
At a fixed lot, every trade carries identical weight, so the result is a clean measure of whether the rules win more than they lose. Under percentage risk the weights differ, and a losing trade that happened to be sized larger can outweigh several smaller winners. One month in our own data flips sign on exactly that: +$10.18 at a flat 0.01 lot, and −$0.17 at $1,000 with real percentage sizing. Same trades, same order, opposite conclusion.
The error is not in either measurement. It is in dividing dollar totals earned at a fixed lot by an account balance that was never sized that way, and then publishing the percentage as an expectation. We did that, and it is how a genuine +3.5% became an advertised +25.3%. See what our figures actually say.
What our replay does differently
Three properties, because each one closes a specific way a backtest lies:
- It runs the live signal engine. Real broker bars are replayed through the same code path that trades, with the real tracker driving strategy selection. There is no second implementation to drift from the first.
- It cannot write anything. The replay is state-isolated and snapshot-restored, so a run cannot leave learned state behind. Before that was enforced, a second identical run in the same process returned a different result, because the first had already updated the tracker it was about to read.
- It applies the full live gate chain. Session hours, spread guard, news shield, regime detection, concurrency cap and the daily lockdown all evaluate exactly as they do live. A backtest that skips the gates is measuring a strategy the bot would never have been allowed to trade.
The learning mode matters too. A walk-forward run starts from a blank slate with every operator override cleared, which reproduces a fresh install rather than this machine's accumulated tuning — the difference between testing the product and testing your own copy of it.
Keep reading
- Walk-forward analysis explainedWalk-forward testing repeatedly fits on one window and tests on the next, producing an equit…
- Curve fitting, and how to recognise itOverfitting is the largest single cause of trading bot failure. Here is how it happens throu…
- Reading a verified track record properlyA verified badge proves the trades happened. It does not prove the account is live, the only…
- Walk-forward analysis
- Curve fitting explained
Educational information only, not financial advice. Trading leveraged products carries substantial risk of loss. Last updated 2026-08-11.