Queue Priority Reset Tax in Dynamic Repricing
Date: 2026-03-06
Category: research (execution / slippage modeling)
Why this playbook exists
Many desks "improve" passive execution by repricing child limits every tiny quote move. In live books, that can backfire:
- each replace often loses queue priority,
- you spend more time at the back than near the front,
- fills arrive later (or never),
- urgency later forces aggressive catch-up.
That hidden drag is the Queue Priority Reset Tax (QPRT).
Core mechanism
For a buy child order:
- You post at best bid and start aging in queue.
- Microprice tilts up by 1 tick; controller sends replace.
- Venue applies replace as cancel+new (priority reset).
- You move from near-front to back-of-queue.
- Either:
- you miss prints that would have filled old queue position, or
- you fill later at worse levels after urgency escalation.
Symmetric for sells.
The error is not "too passive" or "too aggressive" alone. It is over-churn without valuing queue age.
Data contract (minimum)
Child-order event tape:
parent_id,child_id,symbol,side,venuesubmit_ts,ack_ts,replace_send_ts,replace_ack_ts,cancel_tslimit_px_before,limit_px_after,reason_codevisible_size,remaining_qty- L2/L3 snapshots (or best-effort queue estimates)
- trade prints with aggressor side
- benchmark refs: arrival mid, decision mid, microprice
- fees/rebates and odd-lot flags
Without replace and queue-state timestamps, QPRT is mostly invisible.
Metrics that expose QPRT
1) Replace Churn Intensity (RCI)
[ RCI = \frac{#(replaces)}{\text{child active seconds}} ]
Track p50/p90 by symbol and regime.
2) Queue Age at Fill (QAF)
[ QAF_i = t_{fill,i} - t_{last_priority_reset,i} ]
Falling QAF with rising RCI is a red flag.
3) Missed Queue Opportunity (MQO)
Estimated shares that would likely have filled without the last reset:
[ MQO = \sum \max(0, \hat q^{no-reset}{fill} - q^{actual}{fill}) ]
Use conservative queue-depletion simulator.
4) Queue Priority Reset Tax (QPRT, bps)
[ QPRT = 10^4 \cdot \frac{C_{actual} - C_{counterfactual,no-reset}}{\text{notional}} ]
Counterfactual must replay real prints/quotes with reset removed, not a static spread model.
5) Churn-to-Catchup Ratio (CCR)
[ CCR = \frac{\text{cost from urgency catch-up}}{\text{cost from passive fills}} ]
When CCR rises with RCI, controller is borrowing pain from the future.
Modeling blueprint
Model expected incremental cost of sending a replace at time t:
[ \Delta C_{replace}(t) = \underbrace{\Delta C_{adverse,selection,avoided}}_{benefit}
- \underbrace{\Delta C_{queue,age,loss}}_{QPRT}
- \underbrace{\Delta C_{deadline,risk}}_{urgency,interaction} ]
Only replace when \Delta C_replace(t) < -\epsilon.
Component models
Adverse-selection component (benefit of moving quote)
- Inputs: microprice drift, imbalance, cancel/trade intensity, short-horizon volatility.
- Output: expected bps saved if price moved now.
Queue-age loss component (QPRT term)
- Survival/hazard model for fill conditional on queue age and depth ahead.
- Output: expected additional delay + expected missed-fill notional from reset.
Deadline-risk component
- Remaining time, residual size, participation caps.
- Output: expected future catch-up cost if current passive path under-fills.
State machine for live control
STABLE_QUEUE
- RCI low, QAF healthy
- normal repricing allowed
CHURNING
- RCI rising, QAF dropping
- widen no-replace band, enforce min dwell
QUEUE_DAMAGE
- QPRT burn-rate breach or MQO spike
- freeze non-essential reprices, split child into layered levels
DEADLINE_RISK
- underfill risk high near cutoff
- controlled aggression with cap; avoid panic sweep
Use hysteresis (harder exit than entry) to avoid oscillation.
Practical controls
Control 1: No-replace micro band
Do not replace for tiny reference moves unless move persists:
- e.g., require
|microprice shift| >= θforτms.
Control 2: Minimum dwell timer
After any replace, require dwell before next replace unless risk override triggers.
Control 3: Queue-age-aware sizing
If queue age is high (good position), prefer size reduction over full-price reset.
Control 4: Layered child structure
Use two layers:
- anchor layer: protects queue age (low churn)
- reactive layer: handles short-term micro alpha
Control 5: Deadline guardrail
If projected completion probability drops below threshold, pre-emptively shift a bounded slice aggressive (instead of late full chase).
Backtest and promotion protocol
- Build event-level replay with queue reset semantics per venue.
- Run A/B policies:
- baseline (naive frequent replace)
- QPRT-aware gating policy
- Evaluate by regime: open, lunch, close, news windows.
- Track tails (q90/q95/q99), not only mean slippage.
Promotion gates (example)
- q95 slippage improvement >= 5 bps
- MQO reduction >= 15%
- completion ratio not worse by > 1.0 pp
- aggression cost at deadline not worse by > 2 bps
Rollback if two consecutive windows breach q95 or completion floor.
Common mistakes
"More responsive quoting is always better"
False when priority resets dominate micro-alpha gains."Replace cost is just exchange fee"
Bigger cost is queue age destruction, often uncaptured in fee analytics."Average slippage improved, so done"
Tail and deadline blow-ups can worsen while mean improves."One policy fits all venues"
Priority/replace semantics differ materially by venue.
Minimal pseudo-policy
score = benefit_adverse_selection - cost_queue_reset + cost_deadline
if state == STABLE_QUEUE and score < -eps:
replace()
elif state == CHURNING:
replace_only_if(score < -eps_strict and dwell_passed)
elif state == QUEUE_DAMAGE:
freeze_nonessential_replaces()
maintain_anchor_layer()
elif state == DEADLINE_RISK:
bounded_aggressive_slice()
if QPRT_burn_rate > limit:
widen_no_replace_band()
Desk-level takeaway
Repricing logic must optimize price + priority + time, not price alone.
If your controller ignores queue age, frequent replaces can turn into a steady hidden tax that only appears when urgency arrives.