Queue Position Modeling for Passive Orders
Queue position is the difference between posting a limit order and actually getting filled. A bid can be the best price for seconds yet receive nothing because older orders stand ahead of it. Conversely, a fill is not automatically good news: it may arrive because informed sellers know the fair value is lower. A useful model therefore estimates both fill probability and the conditional cost of a fill.
Price-time priority is common but not universal. Pro-rata matching, retail priority, hidden liquidity, and venue-specific allocation rules alter the economics. Confirm the matching rule before fitting parameters. The reconstructed order-level state in order book replay is ideal; without IDs, queue position is a latent variable rather than an observed fact.
The basic queue calculation
For a newly posted buy at price \(p\), initial queue ahead is displayed bid size at \(p\):
def initial_queue_ahead(book, price, own_size):
displayed = book.bid_size(price)
return max(0, displayed - own_size) # if book already includes our order
Thereafter, executions at the price reduce queue ahead, cancellations may reduce it, and new same-price orders join behind under price-time priority. The hard part is allocating cancelled size: with aggregated data we do not know whether cancellation came ahead of us. A naive assumption that every cancellation improves our rank systematically overstates fills.
| Model | Cancellation allocation | Typical use |
|---|---|---|
| Conservative | None helps our order | Upper bound on wait |
| Uniform | Cancelled size allocated by rank | Fast baseline |
| Probabilistic | Estimate ahead-cancel share from IDs | Production approximation |
| Order-level | Exact ID ordering | Best available benchmark |
A probabilistic queue model
Let \(Q0\) be displayed quantity ahead, \(Et\) executed quantity at our price, and \(C_t\) cancellations. With an estimated fraction \(\rho\) of cancellations ahead:
\[ Qt = \max(0, Q0 - Et - \rho Ct) \]
The order fills when cumulative consumption after priority reaches its size. Estimate \(\rho\) by instrument, time of day, side, spread regime, and volatility bucket from order-ID data. It is often lower than a uniform model implies because traders cancel young quotes after their signals change.
def queue_remaining(q0, executions, cancels, rho):
return max(0.0, q0 - executions - rho * cancels)
def fill_fraction(q_remaining, own_qty, consumed_after):
return min(1.0, max(0.0, (consumed_after - q_remaining) / own_qty))
The model must update in event time. A one-second bucket can hide a cancel-then-trade ordering that changes a simulated fill from zero to full.
Fill probability is only half the objective
Estimate a conditional response such as:
\[ E[r{t\rightarrow t+h} \mid \text{passive fill}, Xt] \]
where the sign is measured against the maker. A bid fill followed by a negative return is adverse selection. Combine this with fees, rebates, and opportunity cost:
| Component | Buy-limit interpretation |
|---|---|
| Fill probability | Chance to acquire exposure |
| Spread capture | Value if price subsequently mean reverts |
| Rebate/fee | Venue-dependent fixed bps |
| Adverse selection | Expected post-fill loss |
| Non-fill cost | Missed alpha or forced crossing later |
This is why high fill rate can be a warning. Orders at the touch during a toxic sell program fill reliably and then lose. Link the queue estimate to imbalance, volatility, trade sign, and the features discussed in adverse selection.
Backtest and calibration traps
Never fill every resting order whenever a trade print reaches its price. Prints may reflect hidden execution, another venue, or liquidity ahead. Calibrate simulated fills against actual child-order outcomes, partitioned by queue percentile. Report predicted versus realized fill rates and post-fill returns, not one aggregate metric.
Queue behavior is nonstationary. Opening, closing, and event windows have different cancellation and displayed-depth patterns. Treat the close as its own regime, especially when auction liquidity takes over; auction mechanics explains why continuous-book assumptions then fail.
Key takeaways
- Displayed depth is not queue position; priority and cancellation attribution matter.
- Use order-level data to calibrate, then apply conservative models where IDs are absent.
- Update queues in exchange event order, not coarse time buckets.
- Optimize expected passive value: fills, fees, adverse selection, and non-fill cost.
- Validate fill predictions by regime and queue percentile against live outcomes.
