Quant Memo
Core

The Execution Report State Machine

Every order lives its whole life as a sequence of states — new, partially filled, filled, cancelled, rejected — and an execution report is the message that tells you which state it just moved to.

Prerequisites: How An Order Entry Gateway Works

An order isn't a single event — it's a small object that lives through a sequence of states from the moment it's submitted until it's finished, one way or another. An execution report is the message an exchange (or broker) sends every time an order's state changes, and the full set of possible states and the transitions allowed between them form a state machine that every trading system, on both sides of an order, has to track correctly.

The core states

StateMeaning
NewOrder accepted by the exchange, resting in the book, no fills yet
Partially FilledSome, but not all, of the order's quantity has traded
FilledThe entire order quantity has traded
CancelledOrder removed from the book before fully trading, no more quantity can fill
RejectedOrder never made it into the book at all — failed a validation check
Pending Cancel / Pending ReplaceA cancel or amend request has been sent but not yet confirmed by the exchange
ExpiredOrder's time-in-force ran out (end of day, IOC's instant, etc.) without fully filling

Each of these is signalled by its own execution report, tagged with an order status field, so any system consuming the message stream can always tell exactly what just happened to a specific order without having to infer it.

Walking an order through its states

You send a limit buy for 1,000 shares at $25.00.

  1. New. The exchange accepts it and sends an execution report confirming the order is now live in the book at $25.00.
  2. Partially Filled. A seller crosses in for 400 shares. You get an execution report: 400 filled at $25.00, 600 remaining, status "partially filled."
  3. Partially Filled again. Another 300 shares trade. A second execution report: 700 filled cumulative, 300 remaining.
  4. Filled. The last 300 shares trade. Final execution report: 1,000 filled cumulative, 0 remaining, status "filled" — the order is now finished and can never receive another execution report.

If instead, after step 2, you'd sent a cancel request for the remaining 600 shares, you'd receive a Pending Cancel report followed by a Cancelled report confirming the remaining 600 were pulled from the book — and no further fills are possible on that order ever again.

An execution report is not the order itself — it's a notification that the order's state just changed, and a correct trading system must track cumulative filled quantity and current status from the sequence of these messages, not assume the order sent is the order that resulted.

Why this matters more than it sounds

A single order can legitimately generate many execution reports over its lifetime — a big order that fills across dozens of small trades produces dozens of "partially filled" reports before ever reaching "filled." A trading system that misses one, processes them out of order, or double-counts a report can badly miscalculate its actual position and remaining exposure, which is a serious operational risk rather than a cosmetic bug. This is exactly why the ClOrdID, OrigClOrdID And Order Identity scheme exists — every execution report is tied to a specific client order ID so a system can unambiguously match each report back to the order it belongs to, even across amendments handled by Cancel/Replace: What Actually Happens and rejections categorized under Why Orders Get Rejected.

In an interview, if you're asked to design or debug an order management system, the state machine is the right mental model to reach for first: list the valid states, then ask which transitions between them are actually legal — a "filled" order can never go back to "new," and that kind of constraint is usually where the interesting bugs live.

Cumulative versus incremental quantity

One subtlety trips up a lot of first-time order management system builders: does a fill report describe the quantity filled in this specific execution, or the cumulative quantity filled so far across the order's whole life? Real protocols like FIX report both fields on every execution report precisely so a receiving system doesn't have to choose — it can validate its own running total against the exchange's cumulative figure on every single message, catching a dropped or duplicated report immediately rather than discovering the discrepancy only once the order is fully done. A system that tracks only the incremental number and simply adds each new report to its own running total has no independent way to notice if it missed one along the way; a system that also checks the cumulative field catches that kind of gap the instant it happens.

This is also why exchanges assign every execution report its own unique, strictly increasing identifier separate from the order's own ID — so a receiving system can detect gaps in the report sequence itself (a possible sign of a dropped network message) independently of whatever the fill quantities say.

Related concepts

Practice in interviews

Further reading

  • FIX Trading Community, FIX 4.4 Specification
  • Harris, Trading and Exchanges (ch. 3)
ShareTwitterLinkedIn