AymarData

How To Backtest Trading Strategy With Order Book: Backtest a Strategy With Order Book Data

How to backtest a trading strategy with order book data: reconstruct the historical book, model fills and latency, report honest metrics, and avoid false edges.

How To Backtest Trading Strategy With Order Book: Backtest a Strategy With Order Book Data

Backtesting a strategy with order book data means replaying historical bids, asks, trades, and market events to estimate whether a trading rule could actually have been executed — not merely whether a candle-based signal would have pointed the right way. That distinction is the whole point. Learning how to backtest a trading strategy with order book data starts with one question: does your edge depend on liquidity, spread, queue position, available size, or execution timing? If it does, candles quietly flatter your results, and you need a reconstructed book plus an execution model that answers harder questions — was there enough size at the quoted price, would the order have crossed the spread, did the market move before the fill, was the book one-sided, and what did the position settle at?

This guide is the hub for that work. It covers what order-book backtesting measures, the data it requires, how to reconstruct a historical book safely, how to pick an execution model, the metrics worth reporting, and where backtests usually break. The deeper mechanics of bids, asks, spread, and depth live in our dedicated primers, so here we concentrate on turning a book into a defensible backtest.

Table of contents

What order book backtesting actually measures

A limit order book records resting buy and sell interest at different price levels. Bids are prices at which participants are willing to buy; asks are prices at which they are willing to sell. The best bid is the highest visible bid, the best ask the lowest visible ask, and the spread the gap between them. Depth is the quantity available at one or more levels, and imbalance compares buying and selling quantity across the levels you select.

The cleanest way to frame the exercise is to separate two very different tests. A signal backtest asks whether the strategy's indicator would have predicted a profitable price move. An execution backtest asks whether the strategy could have entered and exited at prices and quantities that were actually available. The first can run on candles. The second cannot — it needs a historical book, because the question is no longer where did price go but what could you have traded, and at what cost.

That framing decides everything downstream. If you only care about direction over hours or days, you may not need a book at all. If your edge is spread capture, imbalance signals, passive market making, or prediction-market entries priced off an outcome token, every assumption you make about fills changes the result. For a plain-language refresher on the components themselves, see our explainer on reading bids, asks, spread, and depth, and for the prediction-market specifics our Polymarket order book primer covers the outcome-token model.

The data an order-book backtest requires

A useful backtest normally combines several historical data types, and each answers a different question.

Book snapshots show the visible state of the book at a point in time, across multiple bid and ask levels. They let you reconstruct the market at a decision time, estimate executable prices, and measure spread and depth. Their limit is that two snapshots say nothing about what happened between them — a strategy reacting to rapid cancellations or replenishment needs more.

Incremental book updates describe changes to price levels after a snapshot. A replay engine applies them in sequence to maintain a local copy of the book. This is where integrity matters most: a stale or badly reconstructed book can invent impossible liquidity, drop cancellations, duplicate quantity, or report fills at prices that never existed. Binance's own documentation illustrates the discipline required — buffer depth events, fetch a REST depth snapshot, compare update identifiers, discard events already covered by the snapshot, and then apply later updates in order, rebuilding the book if the first usable event does not bridge the snapshot's update ID. The principle generalizes beyond any single venue: a replay should detect gaps rather than silently continue. You can read the integrity rules in the Binance WebSocket streams documentation.

Trades and transaction events help you tell displayed liquidity apart from executed liquidity. They confirm that activity occurred near a quoted level, support trade-driven signals, and let you compare displayed depth against actual turnover. What they do not do is prove your order would have filled — a trade at your price is evidence about the market, not about your position in the queue.

Settlement or terminal-value data matters for markets that resolve to a defined outcome. A prediction-market position may not be exited through a conventional sale; it pays a final value when the event resolves. Our Polymarket backtest workflow uses a settlement endpoint, excludes unresolved windows from profit-and-loss calculations, and treats the two outcome books separately by requiring an explicit outcome. If you are specifically after that market, our guide on getting Polymarket historical data walks through the sources and the checks to run first.

Reconstructing the historical book safely

Replay has four conceptual layers, and skipping any one of them is how false edges get born.

First, establish the instrument and time window. Identify the exact market or contract, its trading interval, and the historical period under test. Do not assume a market name maps to one continuous instrument. Prediction-market products often create multiple short-lived windows, and crypto venues carry spot, perpetual, futures, and options instruments with different contract rules. Our Polymarket example lists concrete market windows first, then passes the resolved slug into book, trade, and settlement requests.

Second, load the initial state from the earliest valid snapshot covering the test period. Record the snapshot timestamp, instrument identifier, sequence or update ID where available, price and quantity precision, the bid and ask levels, and the source and timezone. If the snapshot is dated after your strategy's intended start, you are feeding it information it did not have — move the start forward or obtain an earlier snapshot.

Third, apply updates in sequence. A positive quantity generally sets the size at that price, a zero quantity removes the level, and order matters. Sequence gaps should invalidate or rebuild the local book, and already-consumed updates must not be applied twice. Between applications, verify continuously that the best bid sits below the best ask unless the venue permits a special state, that no quantity is negative, that timestamps stay monotonic after normalization, that sequence numbers do not skip, and that no impossible duplicate levels appear.

Fourth, produce decision-time book states. For each evaluation time, generate a state containing the best bid and ask, spread, size at each level, cumulative depth, recent trades, recent book changes, the event timestamp, and any venue status or settlement flag. That state is the only thing your strategy sees. Never compute a feature from future updates and apply it to an earlier decision.

The granularity of your source data caps how precisely you can model queues. CME distinguishes Market by Order (MBO), which exposes individual orders, queue position, and full depth, from Market by Price (MBP), which aggregates quantity at each level and tells you far less about where a specific order sits in line. If you only have MBP data, your passive-fill modeling is inherently an assumption, not a measurement — a point that drives the next decision.

Diagram showing four stages of historical order book reconstruction feeding a decision-time state into the strategy, with a gap-detection loop.
Four layers of a safe book replay

Choosing an execution model that will not lie to you

The execution model is usually what decides whether a backtest is useful or self-deception.

For marketable orders, the conservative baseline is simple: execute an aggressive buy against the ask and an aggressive sell against the bid. Our Polymarket backtest guidance follows exactly this — buy at the ask, sell at the bid, cap size by top-of-book liquidity, and skip one-sided books. For larger orders, consume multiple levels so the fill reflects real depth:

def estimate_buy_cost(asks, quantity):
    remaining = quantity
    cost = 0
    for level in asks:
        fill = min(remaining, level["size"])
        cost += fill * level["price"]
        remaining -= fill
        if remaining <= 0:
            break
    filled = quantity - remaining
    return cost / filled if filled else None, filled

This returns a volume-weighted execution price instead of pretending the whole order fills at the best ask.

Passive limit orders are where optimism creeps in. An order should not count as filled just because the market traded at its price. A realistic model weighs whether the order was posted before the relevant trade, how much quantity rested ahead of it, which trades and cancellations consumed the level, partial fills, order lifetime, and whether the strategy could even have submitted the order within observed latency. With MBP data you cannot see exact queue position, so state an explicit assumption: immediate fill when the price is touched (optimistic), fill only after displayed quantity is consumed (conservative), a probabilistic fill from observed volume and cancellations, or no passive-fill modeling at all — which limits you to signal research, not execution claims. If you cannot observe queue position, label the result as an estimate rather than a confirmed historical fill.

Latency deserves its own assumption because a single timestamp can mean many things: exchange event time, transaction time, feed publication, receipt, decision, submission, or matching-engine acceptance. A strategy reacting to an update at time t cannot usually trade the same state once feed, computation, and routing have passed. Rather than guessing one correct latency, replay under several — a zero-latency research baseline, a typical application latency, and a stress case during volatile periods — and check whether the edge survives all of them.

A book-based loop then reads cleanly in the abstract:

for event in historical_events:
    book.apply(event)
    if not book.is_valid():
        mark_data_gap()
        rebuild_or_skip_window()
        continue
    if strategy.should_trade(book, portfolio):
        order = strategy.create_order(book, portfolio)
        fill = execution_model.simulate(order, book, event.timestamp)
        portfolio.apply(fill)
    portfolio.mark_to_market(book)

The strategy sees only the reconstructed state; the execution model decides independently whether the order fills, at what price, and in what size. Any profit, win rate, or edge produced from demonstration snippets is illustrative, not verified performance, and should be labeled that way in every notebook or report built on sample data.

Metrics that separate a real result from a mirage

Total return is the least informative number in an execution backtest. Report execution quality alongside strategy quality and data quality, because weakness in any one invalidates the others.

Category What to report
Execution Fill rate, partial-fill rate, average execution price, slippage vs mid, slippage vs decision-time quote, spread paid or captured, time to fill, market impact by size
Strategy Net and gross P&L after fees, return on deployed capital, max drawdown, profit factor, risk-adjusted return, trade count, exposure time, win rate by regime
Prediction markets Results by outcome, by market window, by time to resolution, unresolved-window count, settlement contribution, capital locked until resolution
Data quality Sequence gaps, invalid books, missing timestamps, duplicate events, one-sided-book frequency, coverage by instrument and date

The data-quality row is the one most studies omit and the one that most often explains a surprising result. A strategy that only looks profitable after invalid intervals are quietly removed has not been validated — it has been edited. Track how many orders were evaluated with complete depth, and treat that percentage as a confidence ceiling on the whole backtest.

Where order-book backtests quietly fail

The failure modes repeat across venues and asset classes. Treating the midpoint as an executable price is the most common: the midpoint is an analytical reference, not a tradable level, and buying there overstates performance unless the strategy genuinely posts passively and the fill model supports it. Ignoring available quantity is close behind — a quoted price may hold only a sliver of size, so applying it to the full order manufactures capacity that never existed. Use the size at each level and walk the book for larger orders.

Look-ahead is subtler. Computing a feature from a completed interval and pretending it was known at the interval's start is the classic error; decisions must be made only after the relevant information arrives, driven by event timestamps. Equally dangerous is assuming every touched price fills a passive order, which ignores queue position entirely. Ignoring data gaps lets a single missing update distort the reconstructed book, so detect gaps with sequence numbers where available and fall back on timestamp continuity and plausibility checks otherwise.

Two failures are specific to how results are framed. Ignoring settlement rules can turn a profitable-looking prediction-market entry into a loss once resolution and payout rules apply — use the venue's settlement data and exclude unresolved markets from final figures. And testing only one market regime hides fragility: order-book strategies behave differently across high and low volatility, wide and narrow spreads, news events, open and close, and thin versus deep liquidity. Split those regimes rather than reporting one blended number.

Choosing a data delivery method

The right delivery surface follows the research workload, not the other way around. Use a REST API for targeted historical queries, specific book states, market metadata, settlement lookups, and moderate samples; our Polymarket example lists market windows, retrieves a book at a given time, and pulls settlement over REST, and the API Quickstart is the fastest way to build a repeatable query loop.

Use bulk Parquet and CSV files for large historical scans, local columnar analytics, repeated backtests without repeated API calls, and reproducible datasets. Parquet suits analytical workflows with column selection and efficient scans; CSV remains handy for inspection and general-purpose tooling. Our Polymarket backtest page provides free CSV and Parquet samples for schema inspection and local smoke tests.

Use live streams when the same book-reconstruction logic must later support live monitoring or execution research. The architecture that pays off is keeping the strategy independent of the source:

historical files/API ─┐
                      ├─> normalized book state ─> strategy ─> execution model
live WebSocket stream ┘

This reduces the risk that your historical and live implementations interpret the same updates differently. For research assistants and tool-using systems, our MCP server exposes a machine-accessible interface to these workflows — with the same rules enforced, since an agent should never infer fills from a midpoint, drop missing events, or treat illustrative output as verified performance.

When candle data is enough

Order books are not always necessary, and insisting on them when they add nothing wastes compute and storage. Candles can be adequate when the strategy holds positions over relatively long periods, trades on daily or hourly signals, does not depend on precise entry prices, moves small size in highly liquid markets, makes no realistic-execution claim, or is simply screening signals before any execution modeling.

Order-book data earns its cost when the strategy trades at short horizons, uses spread, depth, or imbalance, places passive limit orders, operates in thin or fragmented markets, claims realistic slippage or fill rates, uses large orders relative to displayed liquidity, or exploits microstructure and event timing. So the real decision is not "books beat candles." It is whether your research question concerns execution and market microstructure rather than only directional price movement.

How to work with our data surfaces

A developer can assemble the pieces by required scale. Begin at the backtest hub to find backtesting-oriented workflows, then use the Polymarket backtest example for a concrete L2 reconstruction and settlement walkthrough. From there, our REST API handles targeted historical states, bulk files handle larger local replays, live streams extend the same logic to real time, and the dataset catalog helps you confirm the venue and instrument before you commit to a design.

The one design principle worth internalizing: normalize historical and live events into the same internal book representation. When the research code and the live code share that representation, your paper-trading and monitoring behavior stays comparable to the assumptions you tested — which is exactly what a backtest is supposed to guarantee. If you want help matching a venue, instrument, and delivery format to your strategy's latency and size requirements, send us the specifics and we will point you to the right surface.

Frequently asked questions

How do I backtest a trading strategy with order book data?

Reconstruct the historical book from snapshots and incremental updates, generate only the market state available at each decision time, apply an execution model for marketable and passive orders, include fees and a latency assumption, and score the position using realized exits or settlement values.

Can I backtest an order-book strategy with snapshots only?

Yes, for simple decision-time analysis and conservative marketable-order estimates. Snapshots are usually insufficient for accurate queue-position modeling, cancellation analysis, or high-frequency replay, where incremental updates become necessary.

Should I use the bid, ask, or midpoint?

Use the ask for an aggressive buy, the bid for an aggressive sell, and the midpoint only as a reference — never as an executable price unless your execution model explicitly supports midpoint or passive fills.

How should I model a large order?

Consume available quantity across successive price levels and compute the volume-weighted execution price. Do not assume the entire order fills at the best bid or ask, because that invents liquidity the market never showed.

What if the historical book has missing updates?

Detect the gap using sequence numbers where available, rebuild from a valid snapshot if possible, or exclude the affected interval. Continuing with an uncertain book can create false liquidity and invalid fills.

Is order-book data necessary for every strategy?

No. It matters most when the strategy depends on short-horizon execution, spread, depth, queue position, liquidity, or market impact. For longer-horizon directional research, candles are often enough for an initial screen.