There is a specific way a backtest lies to you that has nothing to do with overfitting, and it is much easier to commit by accident. The rule reads a piece of information from the bar it fires on, and then fills at a price that happened earlier in that same bar. The equity curve that comes out is not optimistic. It is impossible.
The reason it slips past people is that the rule sounds completely reasonable when you say it out loud. "Buy when the close crosses above the 50-day average." Fine. Fill it at the open of that day, and you have just bought at nine thirty in the morning based on something you could not know until four in the afternoon.
The rule that buys at a price it could not have known
Work a single trade through it. A stock opens at 40.00, trades down to 39.10, and closes at 41.20, which is the day it crosses above its average. A backtest that evaluates the condition on that day's close but records the fill at that day's open books an entry at 40.00. You made 1.20 a share before the position even started, on every single signal, in a direction that is always favourable, because the condition only triggers on days that closed strong.
That is the part people miss. The leak is not random noise that averages out. It is systematically biased towards the outcome the rule is looking for. If your entry condition requires a strong close, then the sample of days where it triggers is exactly the sample of days where the open was well below the close. On volatile names the average gap between the open and the close on trigger days can be a meaningful percentage, and across a few hundred trades it becomes most of the reported edge.
Run that number for yourself before you argue with it. Take twenty signals from your own strategy, note the open and the close on each trigger day, and average the difference as a percentage. Whatever that number is, it is the per-trade head start your backtest is quietly awarding you, and it is the first thing to subtract from any result you are proud of.
Three shapes of the same mistake
Once you know what you are looking for, the leak shows up in more places than entries.
- The indicator itself. Any average, band, or oscillator computed over a window that includes the current unfinished bar changes value as the bar develops. A condition on it is a condition on a number that will not settle until the bar closes.
- The fill timestamp. Signal at the close, fill at the same close, is defensible only if you can genuinely trade the close. Signal at the close, fill at that day's open or at that day's low, is not.
- Exit ordering within the bar. If both your stop and your target sit inside one bar's range, the backtest has to pick one, and the cheerful choice is to assume the target filled first. On a bar that touched both, that assumption is a coin flip you are always winning.

The third one is worth a moment because it is the least discussed. Say your strategy has a 2 percent stop and a 4 percent target. On a day the stock trades down 2.5 percent and up 4.5 percent from your entry, both levels were touched. Intraday sequence decides which one actually happened, and daily bars do not record sequence. The conservative convention is to assume the stop filled first every time. It will understate your results slightly, and that is the correct direction to be wrong in.
The one-bar shift test
You do not need to audit the internals to find out whether you have a leak. You need one comparison run.
Build a second copy of the strategy where every condition reads the previous completed bar, and the entry fills at the next bar's open. Same thresholds, same symbols, same period. Then compare the two on three numbers rather than one.
- Trade count. It should be close to unchanged. If the shifted version takes far fewer trades, your conditions were referencing something that only exists intrabar.
- Average trade return. This is where the leak size shows up. The gap between the two versions, per trade, is your head start expressed in the units you care about.
- Hit rate. A leak inflates this too, and often more visibly than the average return, because it turns marginal losers into small winners.
The reading is blunt. If the shifted version keeps most of the edge, the original was probably fine and you now have a version you can defend. If the shifted version gives back a large slice, the edge lived in the leak. And if the shifted version goes to roughly zero, you did not have a strategy, you had a data alignment bug with a nice chart attached.
Do this test on the strategy you like most, not the one you are unsure about. The ones that look best are the ones most likely to be leaking, precisely because leaking makes results look good.
Writing conditions that cannot leak in the first place
The whole class of problem disappears if you adopt three habits when you write the rule.
First, decide out loud which bar each condition is reading, and prefer the last completed one. When you write "close above the average", finish the sentence with "as of yesterday's close, evaluated before today opens". If the condition cannot be stated that way, it is not ready.
Second, put a gap between the decision and the fill. Signal on a completed bar, fill on the next bar's open. You lose a little on the entry price and you gain a result that survives contact with reality. On a strategy that trades a few times a month this costs you very little. On one that trades daily it can cost a lot, which is itself information about how fragile the idea is.
Third, only allow intrabar evaluation for things that can hurt you. A stop that triggers intraday is fine, because assuming you got stopped is the pessimistic assumption. A target that fills intraday is the optimistic one, so if you use it, pair it with the convention that the stop always wins on ambiguous bars.
What the honest version feels like
Expect the corrected strategy to look worse, and expect to dislike it. Entries land a bit later and a bit higher, some trades that used to be flagged never trigger at all, and the curve gets choppier. That is not the correction failing, that is the correction working. The version you had before was measuring your rule plus a subsidy, and the subsidy is not available when you go to trade it.
The practical decision this week is small. Take whichever strategy you were closest to putting real money behind, build the shifted copy, and run them side by side on the same window. If the two are within touching distance, keep the shifted one and delete the original so you are never tempted to quote its numbers. If they are far apart, you have saved yourself the tuition, and the specific condition responsible is usually obvious once you know the gap is there.
The reason to sort this out before anything else is that every other test you run downstream inherits the answer. Filters, exits, position sizing, all of it gets evaluated against a baseline, and if the baseline is leaking then every comparison you make afterwards is measured against a number that cannot happen.