November 7, 2026 · microstructure

The Backtest Read the Right Price from the Wrong Market

The Backtest Read the Right Price from the Wrong Market

At 10:14 UTC, a simple breakout strategy bought a crypto perpetual after the price crossed its 20-minute high. The backtest showed a fill at $64,210. That number appeared in the data, the signal was timestamped correctly, and the simulated order arrived on the next bar. We almost called it a clean result.

Then we lined up the instrument IDs. The signal came from the BTCUSDT perpetual. The fill came from a BTCUSD inverse contract. Both traded near $64,210, and both were liquid markets. They were still different order books, with different prices, tick sizes, depth, and fee schedules. The backtest had stitched together a market no trader could access.

The strategy itself was unremarkable: enter on a close above the rolling high, exit on a close below the rolling low, size each position to a fixed dollar risk. The trouble surfaced only when we asked a more precise question than “what was BTC worth?” We asked, “what could this order have bought in this exact contract at that time?”

The chart was a composite before the strategy ever ran

Our research feed made it easy to compare venues. It normalized symbols and displayed a consolidated price series. That was handy for looking at the market; it was a poor execution reference. A composite can show the best price across exchanges, even though the strategy can send an order to only one venue.

At the breakout, the consolidated bar high was $64,205. The selected contract’s own last trade had already moved to $64,218. Meanwhile, a cached quote for the inverse contract still showed an ask at $64,210. The simulator used the breakout from one series and the attractive ask from another. Each value was real. Their combination was fictional.

InputWhat the backtest usedWhat the order needed
Breakout highConsolidated BTC priceSelected contract’s price history
Entry referenceCached inverse-contract askFresh ask for the traded instrument
Fill quantityRequested position sizeQuantity available at each price level

One row in a market-data table can look complete while its fields describe different markets. A symbol alias is not proof that two instruments share a book. The contract ID, venue, quote currency, and timestamp need to travel together through signal generation and execution.

We replayed the order against the book

We reran the entry using the selected perpetual’s own best ask and the order-book updates available at decision time. The quote was fresh, but only 0.18 BTC sat at the top level. Our simulated order was 0.50 BTC. The remaining 0.32 BTC would have crossed into higher asks.

$64,218best ask when the order arrived
0.18 BTCavailable at that ask
$64,231volume-weighted replay price

The adjusted entry was $21 worse per BTC than the printed fill, before fees. That’s a small difference on a single trade. Across the test, though, the strategy made most of its gross profit on a handful of quick breakouts. Replaying those entries against the correct books cut the gross result by 31%; taker fees and impact reduced it further.

We also found two cases where the top-of-book quote arrived after the signal’s decision time. A backtest that joins on the nearest timestamp can quietly pick a future update. We now join backward: the quote must have been observed by the time the order was sent, and we record its age. If the latest usable quote is too old, the simulator marks the order unfillable or applies an explicit stale-data rule.

What a tradable price requires

A bar close is useful for calculating a signal. It doesn’t establish that a particular order could fill there. For that, the price must belong to the exact instrument and venue, be available at the order’s arrival time, and have enough opposing quantity for the requested size. When the data can’t answer those questions, the honest output is a range or a missing fill, not an invented exact price.

We kept the consolidated series for market context and moved it out of the execution path. Signals now reference the chosen contract’s own history; orders replay against that contract’s book, with fees and size applied after the fill is calculated. A little more plumbing, and a much less flattering equity curve.

That breakout did happen. The backtest simply gave it a better market than the one the strategy had selected.

crypto futuresorder booksmarket databacktestingexecution
← All posts