Note

Partial fills are a state machine, not a cost adjustment

Most backtesters model an order as filled or not filled. Live, an order is a small state machine, and the branches a backtest never visits are the ones that fail first in production.

Execution

An order in a backtest is usually a boolean. It filled, or it did not. An order in a market is a state machine with at least seven states and a set of transitions that the venue, not the strategy, controls. Research conducted against the boolean version validates a system that does not exist, and the gap shows up on the first difficult session rather than in the research.

The states that actually exist

An order that has been submitted is not yet an order that exists. Between submission and acknowledgement it is in an indeterminate state where it may be working, may be rejected, and cannot be safely cancelled because there is nothing yet to cancel. That window is short and is where a surprising share of production incidents live.

Once acknowledged, an order can be working, partially filled, filled, cancelled, expired, or rejected. Partial fill is not a terminal state: it is a working order with a reduced remaining quantity and an average price that now needs tracking. A cancel request against a partially filled order races the venue, and the outcome of that race is not knowable in advance, only reported afterwards. The order may fill completely before the cancel lands, in which case the cancel is rejected and the position is larger than the strategy believed it would be for the duration of the round trip.

None of these transitions are optional in production. A strategy that has no representation for "cancel requested but not yet confirmed, and a fill may still arrive" will do something arbitrary when it encounters that state, and arbitrary behaviour with live orders is the definition of an operational risk.

Why this is a research problem and not only an engineering one

The obvious objection is that this is plumbing, and that research can safely model fills as binary and let the engineers handle the rest. That objection fails on three points.

A partial fill is evidence. If an order for a given size fills only in part, the market has just reported that the liquidity assumed by the strategy was not there. A research model that assumes full fill has assumed away the measurement. Worse, it has assumed it away exactly in the conditions where it matters, since partial fills cluster in fast markets and thin books, which is where most strategies do their worst.

The remainder poses a decision the backtest never asks. Half the intended size is filled and the price has moved. Does the signal still justify the remaining half at the new price? Three answers are defensible: complete at any price, re-evaluate and possibly cancel, or work the remainder passively and accept the risk of never completing. They produce materially different return distributions. A binary-fill backtest silently chooses the first and never tests the others, which means the decision was made by the engine rather than by the researcher.

Position sizing stops being deterministic. With partial fills the realised position is a random variable, not a parameter. Risk limits, hedge ratios and portfolio weights all become approximate. A strategy whose result depends on precise position sizing is more fragile than its backtest suggests, and there is no way to see that fragility without modelling the partial.

Modelling the fill, in ascending order of honesty

Fill everything at the touch. The default in most simple engines. Defensible only when order size is genuinely negligible against displayed depth and holding periods are long enough that entry precision is immaterial. Both conditions should be stated and checked rather than assumed.

Cap by available depth. Fill up to the displayed size at each level, walking the book for the remainder. Cheap to implement given depth data and removes the worst error, which is filling arbitrary size at the top-of-book price. Still optimistic, because it assumes every resting order at those levels is available to trade and none of it cancels.

Allocate by volume participation. Over each interval, allow the order to receive some fraction of the volume that actually printed, capped by a participation ceiling. This is the most useful model for scheduled execution because it produces partial fills naturally, and because participation rate is the quantity the strategy actually controls.

Model queue position. Track the resting volume ahead of the order and decrement it with observed trades, filling only once it is exhausted. This is the only approach that captures adverse selection on passive orders correctly, and it requires order-by-order data to do properly. Where a strategy's edge is passive capture, nothing weaker than this is a test of it.

The right choice depends on what the strategy claims. A strategy whose edge comes from providing liquidity cannot be evaluated with a model that grants fills for free, because the model has assumed the thing being tested. This is the same failure mode described in what a backtest gets wrong about fills: the fills a naive model grants most generously are the ones a real book would have declined.

One order model, two consumers

The structural recommendation is to build the order state machine once and have both the backtester and the live system consume it. Not similar implementations. The same code.

When the research engine and the production engine maintain separate order models, they diverge, and the divergence is silent because nothing compares them. The backtest continues to report a number, the live system continues to trade, and the difference between them is attributed to market conditions rather than to the two systems disagreeing about what an order does.

Sharing the model has a second benefit that is easy to underrate. It forces the research code to handle rejection, expiry and the cancel race, which means those paths are exercised thousands of times in simulation before they are ever exercised with capital. The cheapest place to find out that a strategy has no sensible behaviour on a rejected order is a backtest, and the most expensive place is a live session.

Verification

The check that matters is a comparison against reality. Once any live or paper trading exists, replay the same decisions through the backtester and compare fill by fill: quantity, price, and the sequence of state transitions. Aggregate agreement is not sufficient, because compensating errors are common and a model that is too generous on entries and too harsh on exits can produce a plausible total while being wrong in both directions.

Per-order comparison is what surfaces the specific assumption that is wrong. It is also the only measurement that turns the fill model from an assumption into a fitted component with an error that can be tracked, which is the difference between a number the research produced and a number anyone should act on.