← Writing archive

Writing / Market structure

One Order, Several Trades: Partial Fills and Walking the Book

Calculate partial fills, execution prices, average cost, and unfilled remainders as a buy order consumes several orders and price levels.

Laptop displaying a trading chart and buy and sell controls beside a notebook and coffee.

You submit one buy order. The trade history shows three executions at two prices.

That is an ordinary outcome when the order needs more quantity than one seller offers. The engine works through eligible resting orders, reducing the incoming quantity after each match. Your app may combine those executions into one average, but the underlying trades still have separate quantities and prices.

The arithmetic explains both the final cost and the exposure that remains.

Freeze the book before calculating

Our fictional Harbor exchange trades a fictional instrument, BAG, in whole units with one-dollar price ticks. Its order book records unfilled buy and sell instructions. Resting orders are already waiting in that book; an incoming order can trade with them. Each completed match is a fill, which may execute only part of the incoming order’s requested quantity.

Harbor uses price-time priority: choose the best eligible price, then the earliest resting order at that price. Trades use the resting order’s price. Every order is fully displayed and belongs to a different owner. Ignore fees, routing, auctions, and settlement. The example assumes no intervening command while one incoming order is being processed.

Use this initial book for each explicitly reset comparison below:

Side Order Price Available units
Buy B1 $99 6
Sell S1, first at this price $100 4
Sell S2, second at this price $100 3
Sell S3 $101 5

Coinbase Exchange documents resting-price execution. That is the real venue comparison behind our price rule; the numbers and order IDs here are invented. Coinbase execution pricing

A ten-unit order with a $100 limit

M1 is a buy for ten units with a $100 limit, good till canceled. The limit allows payment of $100 or less per unit. Good till canceled allows an unfilled remainder to stay available for future trades under Harbor’s rules.

Step Resting seller Fill units Price M1 units left
1 S1 4 $100 6
2 S2 3 $100 3
Stop S3 asks more than the limit 0 — 3

M1 has bought seven units for $700. Its three-unit remainder rests as a bid at $100. It cannot consume S3 at $101 because that would break the limit instruction.

A bid is an offer to buy; an ask is an offer to sell. Here the best ask after those fills is $101, while M1’s remaining bid stays at $100. Those prices do not meet, so the remainder waits.

At this point, the average execution price is $100 across the seven units already bought. Dividing $700 by the original ten-unit request would produce $70, a meaningless number that mixes executed and unexecuted quantity.

For this unchanged active order:

Requested quantity = executed quantity + working remainder
10 = 7 + 3

Later cancellation can remove the remainder without adding another fill. We need to retain that separate outcome rather than stretch this active-order equation into a universal rule for every terminal state, when the order can no longer trade.

Now allow the order to reach $101

Reset the book. This is an alternative order, X1, not a continuation of M1.

X1 buys ten with a $101 limit. The engine selects the cheaper sell level first, then uses the next level to finish the order.

Execution Seller Units Price Value X1 units left
1 S1 4 $100 $400 6
2 S2 3 $100 $300 3
3 S3 3 $101 $303 0
Total 10 $1,003 0

The weighted average is $1,003 divided by ten: $100.30. S3 still has two units offered at $101. X1 has no resting remainder.

Moving through the $100 sell level and into the $101 level is walking the book. The engine has exhausted cheaper eligible quantity and used the next price level to finish the order.

Execution price by cumulative units: first seven at 100 dollars, final three at 101 dollars; average 100.30.

Figure 3.1. Starting from the initial book, X1 buys four from S1 at $100, three from S2 at $100, and three from S3 at $101. Gross cost is $1,003 and the volume-weighted average is $100.30. The horizontal axis is quantity, not time.

The $101 limit did not require every execution to occur at $101. It allowed Harbor to pay up to that price. A buyer willing to pay more can still trade with cheaper resting sellers.

Relative to the initial $100 best ask, X1 spent $3 more across ten units. That is 0.30% above that reference price, before fees. This is the cost implied by consuming the stated depth. We have not modeled the market’s later response or claimed a prediction about lasting price impact.

Illustrative Harbor system diagram showing the request, matching, and reporting paths

At every step, the fill size is the smaller of the incoming remainder and the selected resting order’s remaining quantity. Harbor repeats until the incoming order is filled or there is no eligible resting interest.

The remainder instruction changes the result

Reset again. X2 requests fourteen units with a $101 limit. Only twelve units are available at eligible prices: seven at $100 and five at $101.

Harbor defines these outcomes:

Instruction Executed now Unfilled outcome
Good till canceled, GTC 12 Two units rest as a bid at $101
Immediate or cancel, IOC 12 Two units are canceled; nothing rests
Fill or kill, FOK 0 Entire fourteen-unit request ends unfilled

The GTC and IOC versions both spend $1,205 on twelve units, averaging about $100.4167. The FOK version requires the whole fourteen to be executable immediately, so Harbor checks that condition before committing any trades.

GTC fills twelve and rests two; IOC fills twelve and cancels two; FOK fills zero and leaves fourteen unfilled.

Figure 3.2. Each policy is a reset to the initial Harbor book. GTC buys twelve for $1,205 and rests two at $101. IOC buys twelve for $1,205 and cancels two. FOK executes zero because all fourteen cannot be filled immediately.

These definitions align with Coinbase’s documented GTC, IOC, and FOK behavior. FOK requires the full quantity; it does not require one counterparty or one execution price. Coinbase time-in-force documentation

A market order adds different instructions. It usually lacks the customer’s limit-price boundary, while venue protections and available liquidity can still restrict its outcome. Coinbase states that market orders never rest on its open book. Do not take the best displayed ask as a promise for the whole order. Coinbase order types

One order ID cannot replace a fill ledger

Suppose the app receives X1’s first two executions and then disconnects. It knows seven units traded at $100. When it reconnects, it receives the third execution plus a repeated copy of the second.

If it adds every received message, it counts thirteen units. If it stores only the last fill, it loses the earlier seven. If it uses the order ID as the deduplication key, it may discard valid later fills because all three belong to X1.

Harbor’s client design retains execution identifiers separately from order identifiers. It records each unique trade once and reconciles the sum against the venue’s cumulative quantities. That is a requirement of our design; a real integration must use that venue’s documented execution identity and correction rules.

FIX, a standard for electronic trading messages, distinguishes individual trade reporting from cumulative order quantities. Its specification also allows trade cancellations and corrections, so a complete ledger must be able to revise a previously recorded execution when the venue sends a valid correction. FIX Trade specification, section 3.1.2

Depth is an input with a timestamp

Our calculations freeze the book. A real app sees a delayed view while orders continue arriving and canceling.

If S1 disappears before X1 reaches matching, X1’s result changes. The displayed seven units at $100 were available when that feed state was produced; they are not reserved for whoever next clicks Buy.

For an execution review, reconstruct the book and rules at the order’s processing point, then compare each fill’s units and price. For the user, show the executed quantity, its actual average price, and any quantity still capable of trading. An average alone hides too much.

Educational research. Not financial advice.