Limit Order Book Dynamics: Price-Time Priority and Queue Position
The order book is not a static list. It's a queue. How the matching engine ranks orders, and where you stand in line, decides who gets filled, who pays the spread, and who stares at a screen waiting.
Most trading articles describe the order book as a static list with bids on one side, asks on the other, spread in the middle. That’s fine for beginners. It misses everything that matters.
The order book is a queue. Every resting limit order is standing in line at some price, and whether your order fills depends on three things: where you stand, what everyone else does while you wait, and whether the matching engine thinks anyone crossed with you. Those three things run through this whole article — and by the end they combine into something uncomfortable: “post or take” becomes an expected-value calculation, and the expected value is often not on your side.
The Two Rules That Run Every Exchange
Every modern exchange (NYSE, Nasdaq, Cboe, CME, Binance, Coinbase, EBS, even the dark pools that pretend they have no book) runs on the same two rules. Price priority: the best price fills first — a buy at $100.02 jumps ahead of every buy at $100.01. Time priority: among orders at the same price, first in, first out. (NYSE is the historical exception, with floor brokers doing discretionary allocation, but the consolidated tape still looks FIFO.)
Harris calls these the trading rules of an exchange (Harris, Trading and Exchanges, Ch. 4). They sound obvious. They aren’t — because some exchanges really do break one of them. Pro-rata markets (some futures exchanges, historically CME on certain products) allocate fills at a price level proportionally to size, not by time: post 10 contracts next to someone’s 30 and you get 25% of every incoming market order. There’s also the rare size priority (bigger orders win ties) and mixed hybrids (pro-rata at the top of book, FIFO behind it).
If you trade a pro-rata product, your whole mental model flips: you don’t want the front of the queue, you want a big order at the touch. We won’t chase that branch here, because the dominant equity and crypto venues are pure price-time. But remember that “the order book works this way everywhere” is a lie.
Anatomy of a Resting Order
A resting limit order has five attributes that determine its fate: side (buy or sell), price (the worst price the holder will accept), quantity, time of arrival (the FIFO timestamp), and an exchange-assigned order ID (used to break ties and trace the order through its life).
When a marketable order arrives — a buy at or above the best ask, or a sell at or below the best bid — the matching engine walks the opposite side of the book from the best price outward, draining size level by level, and within each level in time order. That is the matching algorithm in one sentence. Harris spends all of Chapter 4 spelling it out.
The Queue Position Math
Suppose you submit a buy limit at $100.00 and join the queue there. Ahead of you sit shares from earlier arrivals; your own size is . Marketable sell orders hit the bid at a rate of events per second, each draining some size from the queue.
Your expected time to fill is:
where is the probability that $100.00 remains the best bid throughout your wait. That probability is the tricky part. While you stand in line, the price can leave: somebody lifts the offer, the new best bid becomes $100.01, and now you’re behind the new level even though you arrived early.
For a back-of-envelope version of that probability, model the midprice as a random walk with volatility . Over a horizon , the probability that the mid moves by more than half the spread in either direction is roughly:
where is the spread in price units and is the standard normal CDF (the factor of 2 is “count both directions”). Why do both directions count as bad news? Up, and you never fill while the move runs away from you. Down, and you do fill — catching a falling knife, which is adverse selection, covered properly in article 4. The envelope math says: wide spread and low vol, you wait forever; tight spread and high vol, you either pull the order or get run over.
Practical takeaway: in fast markets, queue position is a decaying asset. Every second you wait, the conditional probability of a clean fill drops.
What Happens When Orders Cross
Now a concrete case. A buy limit arrives at $100.02. The book shows:
ASK $100.02 | 500 shares
ASK $100.03 | 800 shares
BID $100.01 | 200 shares
BID $100.00 | 1200 shares
Your $100.02 buy is marketable — at or above the best ask. The matching engine immediately executes it against the 500 shares resting at $100.02. You pay $100.02 for 500 shares (and if you sent more than 500, the rest fills at $100.03).
The 200 shares resting at $100.01 on the bid side don’t trade with your order. They’re on the wrong side. The matching engine doesn’t care that $100.01 < $100.02 in a logical sense; it cares that a bid is a bid and an ask is an ask, and they only meet when the bid price reaches the ask price.
But suppose someone sends a marketable limit sell at $100.01. That order crosses with the $100.01 bid (100.01 ≤ 100.01) and fills 200 shares there. The remainder? Its limit is $100.01, which can’t reach the next bid level at $100.00 — so the residual rests at $100.01 on the ask side and becomes the new best ask. This is sweeping: a marketable order walks through price levels until it hits the level its own limit can’t reach, and any unfilled residual becomes a resting limit at the limit price. Mechanically, a marketable limit is a market order plus a residual limit order — which is why instructions like fill-or-kill have to declare all-or-nothing on entry. (Harris, Ch. 4, on the lifecycle of orders.)
The Self-Trade Prevention Edge Case
Modern exchanges track your own resting orders and refuse to match you against yourself. If you have a buy resting at $100.00 and you send another buy at $100.01, the engine will either cancel the old order and place the new one (replace behavior), or refuse the self-match and queue the new order, or reject the new order outright. Different exchanges pick differently.
This is a real source of spooky behavior in execution algos. If you’ve ever watched a TWAP “skip” a child order, it’s often because the algo sent a marketable buy while a resting sell from the same parent was still on the book.
Queue Position Is a Tradable Asset
Here’s the part most retail traders never think about. Your position in the queue is an asset. It’s not on your balance sheet, but it has economic value: the difference between the price you’ll get and the price the person behind you will get. If you’re 10th in line at the bid with a $0.01 spread, then relative to the 1000th-in-line trader you effectively hold about one tick of “queue-jump compensation” — when the best bid gets taken out and your order becomes the new best bid, you capture one tick of price improvement.
This is why maker-taker fee schedules exist. The exchange rebates the maker (the resting limit order) and charges the taker (the marketable order that removes liquidity); the maker rebate is partial compensation for queue risk. On equities the rebates are tiny — fractions of a cent per share. On crypto they’re much larger: Binance has historically paid 0.01–0.02% to makers, which is real money for high-frequency strategies.
If you run a market-making strategy, you should know your expected queue position at every tick and your expected fill rate per second. The math for this line of thinking is in Harris Ch. 13 and the academic queue literature (see Parlour, “Price Dynamics in Limit Order Markets,” 1998; Handa, Schwartz, and Tiwari, 2003).
Estimating Fill Probability in Practice
Put the two quantities from earlier — queue-drain speed and price-drift risk — together and you get a serviceable fill estimator:
import numpy as np
from scipy.stats import norm
def fill_probability(queue_ahead, my_size, events_per_sec, vol_per_sec,
spread, horizon_sec):
"""
Probability that a limit order at the touch fills before
the spread narrows or the price moves against us.
"""
# Expected time for the queue ahead to clear
eta = (queue_ahead + my_size) / max(events_per_sec, 1e-9)
# Probability the midprice drifts up by half a tick in `eta` seconds
# (assuming the spread stays constant and the touch becomes stale)
drift_std = vol_per_sec * np.sqrt(eta)
prob_uptick = norm.cdf(spread / 2 / max(drift_std, 1e-9))
return float(np.clip(1.0 - prob_uptick, 0.0, 1.0))
# Toy example: 500 shares ahead, we post 100, 4 marketable orders/sec,
# vol = 0.005 $/sqrt(s), spread = 0.02, horizon = 60s
print(fill_probability(500, 100, 4, 0.005, 0.02, 60))
Run it and you’ll see fill probabilities in the 30–80% range for typical short-horizon parameters. This is not a research-grade model — for that you want a Hawkes process for event arrivals and a jump-diffusion for the mid — but it captures the main intuition.
Why Queue Position Determines Strategy Choice
The same quantity matters wildly differently at different horizons. If you’re a long-term investor, queue position is noise: you send a market order, pay a few basis points of spread, and move on. If you’re a high-frequency market maker, queue position is the entire game: colocation, faster cancel-replace, sniping the front of book — enormous engineering effort spent moving up the line, because every microsecond of queue position is expected P&L.
In between sit retail and institutional execution algos, which must choose: post passively (rest a limit, capture the spread, risk non-fill) or take aggressively (market order, pay the spread, guarantee the fill)? The answer depends on the urgency of the parent order, the depth of the book, the volatility, and the time of day. This is the entire reason execution algos exist — the later articles on Almgren-Chriss, VWAP, and implementation shortfall can all be read as expansions of one sentence: every execution decision is a queue-position decision.
The Hidden Cost of Pulling
Cancel a resting limit before it fills and nobody charges you a fee. But you pay something: information. Cancel quickly and the market may infer you lost your edge (or that your fill never came). High-frequency market makers watch cancellation rates as a toxicity signal. Harris Ch. 13, on dealer behavior, covers this — it’s part of why pure “post and pray” strategies get adversely selected.
Real Numbers From a Real Book
Now realistic magnitudes. You post a 200-share buy at the bid. Bid $100.00, ask $100.01. Queue ahead of you: 800 shares. Over the next 60 seconds you see 12 marketable sell orders hit the bid (each draining some queue) and 4 small cancels. A realistic queue-drain event rate is per second.
Ignoring price drift, the expected wait:
That’s an hour, and the price will not sit still for an hour. With $0.02 daily vol and 6.5 trading hours, per-second vol is about dollars; the typical drift over an hour is dollars, against a half-spread of just $0.005. The probability the mid moves more than half the spread in either direction within the hour:
And either direction is bad: up means you waited for nothing, down means you caught the knife. You have roughly a 48% chance of a clean fill before the price leaves. A coin flip. Is a maker rebate of $0.0002 per share (typical for equities) or 0.002% (typical for crypto) worth those odds? Almost never on a single shot. The expected payoff of posting:
where “adverse” is the half-tick or more you lose when the price runs. That expected value routinely rounds to zero or slightly negative — this is exactly how naive market making bleeds. Making it positive, by skewing quotes to manage inventory and adverse selection, is the subject of the Avellaneda-Stoikov article (article 4).
What Arithmion SDK Does With the Book
If you backtest execution algos with Arithmion, the simulator has to model queue position or the fills are fiction. The OrderBookSimulator in arithmion.microstructure keeps a per-order-ID timestamp on each resting order and matches marketable orders FIFO within each price level — that’s the baseline. For more realism you can enable the cancel-replace race (an incoming cancel can arrive “too late” if a marketable order already started matching at that price), priority preservation through partial sweeps (when a marketable order drains part of a level, the surviving resting orders keep their time priority), and per-order latency (each order carries its own timestamp and matches in arrival order).
That is the difference between an academic backtest and a realistic one. Most retail backtests assume you get filled whenever you want to. After this article you know why that’s fiction: the book is a queue, queue position is the asset, and most backtests price that asset at zero.
References
- Harris, L. Trading and Exchanges: Market Microstructure for Practitioners. Oxford University Press, 2003. Ch. 4 (trading rules, order types, and matching), Ch. 13 (dealer behavior). ISBN: 978-0-19-514470-3.
- Parlour, C. “Price Dynamics in Limit Order Markets.” Journal of Financial Economics, 1998.
- Handa, P., Schwartz, R., Tiwari, S. “Quote Setting and Price Formation in an Order Driven Market.” Journal of Financial Markets, 2003.