1. Trading at the price that told you to trade
This is lookahead bias in its most common form. A strategy calculates a signal from a bar’s closing price, then the backtest fills the trade at that same close.
The trouble is that you only know the close once the bar has finished. By then that price is history. In real trading, the earliest you can act is the next bar.
Fix: enter at the open of the bar after the signal. It sounds like a tiny change, but for short-term strategies it can be the difference between a winning and losing system.
2. The bar that hits your stop and your target
Say you’re testing on hourly candles. One hour’s high reaches your profit target and its low reaches your stop loss. Which happened first?
An hourly candle can’t tell you. Many backtesters quietly assume the good outcome, or pick whichever check happens to come first in the code. Across thousands of trades, that small optimism compounds.
Fix: look inside the bar using finer data, such as 1-minute candles, to see what really came first. Where even that can’t settle it, assume the stop was hit, and report how many trades were decided that way. If it’s a large share, the result is inside the noise.
3. Limit orders that fill a little too kindly
Limit orders are where simulations are most generous, in three ways:
- Profits from before you were in. If a limit fills halfway through a bar, the part of the bar before the fill can’t count towards your target. Some engines use the whole bar anyway.
- Prices that never traded. If the market gaps straight through your resting price, you’d be filled at the gap price, not your order price. Recording the order price books a trade at a price nobody could have got.
- Orders that never fill disappear. If a limit order expires unfilled, some engines simply drop that setup. But the ones that don’t fill are often the ones that would have been winners, which biases results upwards.
Fix: only count price action after the fill, record fills at prices the market actually printed, and keep a count of expired orders alongside the results.
4. The costs you forgot to include
Fees look small per trade. Over hundreds of trades, they’re often the single biggest thing standing between a strategy and profit. On crypto perpetual futures there are also funding payments, charged or paid periodically while a position is open, which a price-only backtest ignores completely.
Fix: model fees, funding and a sensible allowance for slippage on every trade, inside the simulation, not as a rough deduction at the end.
5. Testing a hundred ideas and keeping the best one
Try enough variations of a strategy on the same data and one of them will look brilliant by pure chance. That doesn’t mean it has found anything real. It means you searched until the noise lined up.
Fix: keep a record of how many variations you tried, hold back data the strategy has never seen for a final test, and be deeply suspicious of results that depend on very precise settings.
6. Trades still open when the data runs out
When a backtest reaches the end of its data, some positions are still open. Ignore them and you’ve quietly removed trades that might have been losers. Close them at their best price and you’ve flattered the result.
Fix: mark open positions to the last price, report them separately, and count them in the totals.
A quick honesty checklist
- Do trades enter on the bar after the signal?
- When a bar hits both stop and target, what does the engine assume, and how often?
- Are limit fills recorded at prices the market actually traded?
- Are unfilled orders counted, not dropped?
- Are fees, funding and slippage modelled on every trade?
- How many variations were tested before this one?
- What happened to positions still open at the end?
If a backtest can’t answer these, its results aren’t wrong yet. They’re just unverified. We applied every point on this list when building our algorithmic trading engine.
This article is general, educational information about software design. It is not financial or investment advice, and nothing here is a recommendation to trade. Trading involves the risk of losing money.