Almost every strategy performs worse live than it did in simulation, and the gap is usually attributed to bad luck or changed conditions. Both explanations are available and both are usually wrong: the gap has mechanical sources, and they can be listed.
When a tested strategy underperforms live, the first hypothesis offered is that the market changed. That hypothesis is unfalsifiable in the short run and therefore useless, and it is also usually unnecessary, because the difference between a simulation and an account statement has causes that do not require the market to have changed at all.
The useful framing is that a backtest is a model, and every model differs from reality in specific ways. The question is not whether the model was wrong but where, and that question has answers you can go and check rather than speculate about.
There are six recurring sources, and in practice most of the gap on any given strategy comes from one or two of them. Identifying which is a diagnostic exercise, and it is worth doing before concluding anything about whether the underlying idea works.
The market did not necessarily change. A backtest is a model, and models differ from reality in specific places you can go and check.
The most common and the largest. A simulation typically assumes that a resting order at a price is filled when the market touches that price. In reality, touching a price means someone traded there, not that you did: your order sits in a queue behind everybody who placed at that level earlier, and the market can touch, fill the front of the queue, and leave without reaching you.
This affects strategies asymmetrically and in the worst possible direction. Your winning trades, where price touched your level and continued away, are exactly the ones where the queue may not have cleared. Your losing trades, where price touched and continued through, are the ones that certainly filled. The simulation gives you both; reality gives you the second reliably and the first sometimes.
The diagnostic is straightforward: count the proportion of your simulated fills that occurred at a level the market only touched rather than traded through. If it is high, this is your main gap, and the honest correction is to require the market to trade through your level by some margin before counting a fill.
Many simulations run on a single price series, typically the closing price of each interval, and enter and exit at that price. But there is no single price: there is a bid and an ask, and you buy at one and sell at the other. Using a mid or a close for both sides removes an entire cost from every round trip.
The magnitude of that omission is proportional to how often the strategy trades, which is why it destroys high-frequency strategies and barely touches long-horizon ones. A strategy taking one position a month can absorb the omission; a strategy taking twenty a day cannot, and the difference in outcome between the two is entirely an artefact of the modelling choice.
The correction is to model both sides explicitly: buy at the ask, sell at the bid, using the actual spread that existed at the time rather than a typical value. Where historical spread data is unavailable, using a conservative constant is far better than using none, because none is an assumption of zero and zero is the one value that is certainly wrong.
Fee modelling errors are common and they are almost always in the same direction. The frequent version is applying a single fee rate to every trade when the real structure distinguishes between orders that add liquidity and orders that take it, and assuming your orders behave like the cheaper category more often than they do.
There is also the funding cost of leveraged positions, which is not a trading fee and does not appear in a fee schedule. A simulation of a strategy holding contracts overnight without accounting for periodic funding payments is measuring something other than what the account would have done, and the omission compounds with holding time.
The correction is arithmetic and worth doing precisely: apply the correct rate per order type based on what each order actually was, and add the periodic costs of any position held across the intervals at which they are charged. This is the least interesting source of the gap and one of the easiest to eliminate.
Lookahead bias is the subtle one and it hides in ordinary code. Any calculation that uses information from a bar to make a decision within that bar is using the future, and the classic version is deciding at the open of a period based on a value computed from its close.
It also enters through data revision. Some data series are corrected after publication, and a series downloaded today contains those corrections; a strategy tested on the corrected series had knowledge that nobody had at the time. This affects fundamental and macro inputs far more than price, but price series are not immune where a venue has republished data.
The test for lookahead is to run the strategy in a way that structurally cannot see the future: process the data one observation at a time, making each decision with only what preceded it. If results collapse, you had lookahead, and the amount they collapse by is exactly how much of your result was made of information you did not have.
Deciding at the open of a period using a value computed from its close is the classic lookahead. It is invisible in a spreadsheet and fatal in a result.
A strategy tested on the assets that exist today has been tested on a set selected for having survived. Assets that were listed, traded and then disappeared are absent from your data, and the strategy never had to handle them, which flatters the result by exactly the amount those failures would have cost.
In digital assets this effect is unusually large, because the failure rate of listed assets is high and the disappearances are not gradual. A strategy that trades a broad universe and was tested only on the current universe has an optimism built into it that is not visible anywhere in its statistics.
The correction requires historical data that includes delisted and dead assets, which is harder to obtain and worth obtaining if your strategy trades a broad set. For a strategy trading a small number of large, long-lived assets, the effect is smaller, and knowing which situation you are in is more useful than assuming either.
The last source is not a modelling error but a statistical one, and it is the hardest to see. Every parameter you tried and rejected, every variant you tested and abandoned, every date range you looked at, is a test, and the best result out of many tests is better than the truth by an amount that grows with the number of tests.
The mechanism is the same one that manufactures calendar patterns, and it does not require any dishonesty. Someone who tries a hundred variants and keeps the best has not cheated; they have simply produced a number that reflects the search as much as the strategy, and the live result reverts toward what the strategy alone produces.
The defence is to hold data back and to count. Reserve a period the strategy has never touched, test the final version on it once, and treat that single number as the estimate. And keep a count of how many variants were tried, because that count is the measure of how much optimism to expect and it is a number nobody records.
A useful diagnostic sequence, in order of typical magnitude. First check the fills: what proportion depended on a level being touched rather than traded through. Then check whether both sides of the spread were modelled. Then verify the fee arithmetic, which is quick. Those three account for most of the gap on most active strategies.
Then the harder three. Test for lookahead by processing sequentially. Ask whether your asset universe was selected on survival. And count the variants you tried, honestly, including the ones you abandoned in the first minute.
The sequence matters because the first three are correctable and the last three are mostly not. A strategy whose gap comes from fee arithmetic can be fixed; a strategy whose result came from trying two hundred variants cannot be fixed, only re-estimated, and the re-estimate is the number that was always true.
The purpose of removing these six sources is not to produce a number that matches live performance, because it will not. The purpose is to produce a number that is not systematically optimistic, so that comparisons between strategies are meaningful and so that the decision to allocate capital is made on something other than an artefact.
A corrected backtest also changes what you learn from a live divergence. If the simulation was honest about fills, spread and fees, and live results still differ substantially, that is genuine information about conditions having changed, which is exactly the signal the uncorrected version could never give you because it was always going to diverge anyway.
That is the real cost of an optimistic backtest. It does not just overstate the result; it destroys your ability to detect when something has actually gone wrong, because a permanent unexplained gap makes every new gap unremarkable.
Run the strategy live at a size small enough that the outcome does not matter, for long enough to accumulate a meaningful number of trades, and compare each individual trade to what the simulation said that trade would have been. Not the aggregate, the individual trades.
The comparison is far more informative than the aggregate because it localises the difference. If entries match and exits do not, that is one problem. If fills match and the cost per trade is consistently higher, that is another. The aggregate tells you a gap exists; the trade-by-trade comparison tells you where it lives.
Most people skip this step because it is unexciting and it delays deployment. It is also the only step that distinguishes between a modelling error you can fix and an idea that does not work, and confusing those two is expensive in both directions: abandoning a sound idea, or scaling a broken one.
Usually not luck and usually not the market changing. Six mechanical sources produce the gap: fills you would not have received, an unmodelled spread, incomplete fee arithmetic, lookahead bias, a survivor-selected asset universe, and the number of variants you tried before keeping the best.
Assumed fills. Simulations typically fill a resting order when the market touches its price, but touching means someone traded there, not that you did. Your winning trades are exactly the ones where the queue may not have cleared; your losing ones certainly filled.
Many simulations use one price series and enter and exit at that price, removing an entire cost from every round trip. The magnitude is proportional to trading frequency, which is why the omission destroys high-frequency strategies and barely touches long-horizon ones.
Using information that was not available when a decision was made. The classic version is deciding at the open of a period based on a value computed from its close. It also enters through revised data series that contain corrections nobody had at the time.
Run the strategy so it structurally cannot see the future: process one observation at a time, making each decision with only what preceded it. If results collapse, you had lookahead, and the size of the collapse is how much of the result was made of unavailable information.
Testing on the assets that exist today means testing on a set selected for having survived. Assets that were listed, traded and disappeared are absent, so the strategy never had to handle them. The effect is unusually large here because the failure rate is high and the disappearances abrupt.
Yes, and it is the hardest source to see. The best result out of many tests exceeds the truth by an amount growing with the number of tests, with no dishonesty required. The defence is a reserved period tested once, and an honest count of how many variants were tried.
Trade live at a size that does not matter and compare each individual trade to what the simulation said it would be. The aggregate tells you a gap exists; the trade-by-trade comparison localises it, distinguishing a modelling error you can fix from an idea that does not work.