Queue-Priority Drift from Cancel/Replace: Slippage Control Playbook

2026-03-02 · finance

Queue-Priority Drift from Cancel/Replace: Slippage Control Playbook

Date: 2026-03-02
Category: research (slippage modeling)


Why this matters

Many execution stacks treat passive order management as harmless micro-optimization:

But in price-time-priority books, frequent cancel/replace can silently destroy queue position.
That turns “tight spread capture” into:

  1. lower fill probability,
  2. longer waiting time,
  3. late-session urgency spikes,
  4. worse aggressive catch-up cost (tail slippage).

In other words: you can lose bps without ever crossing the spread early.


Core idea

Model each passive child order as an asset with two coupled values:

  1. queue-priority value (how close you are to being filled),
  2. information value (how stale/toxic your quote has become).

Then choose among keep / amend / cancel-replace / cross by balancing:

The key is to make queue-priority loss explicit in the objective, not hidden in post-trade analytics.


Minimal state

At decision tick (t):


Priority-drift slippage objective

For candidate action (a), optimize:

[ \min_a ; \mathbb{E}[IS(a)] + \lambda_{95}Q_{0.95}(IS(a)) + \lambda_{miss}\Pr(\text{deadline miss}|a) ]

with execution constraints (participation cap, venue risk, kill-switch state).

Decompose expected slippage:

[ \mathbb{E}[IS] = C_{spread/fee} + C_{impact} + C_{delay} + C_{priority_drift} ]

where (C_{priority_drift}) captures extra cost from losing queue rank after cancel/replace.


Modeling queue-priority drift

1) Fill-hazard under current queue rank

Approximate passive fill hazard:

[ h_t \approx f\big(\lambda^{exec}_t,\lambda^{cancel}_t,q_t\big) ]

Expected time-to-fill increases convexly with (q_t) in thin/fragile books.

2) Replace transition penalty

A replace action typically resets queue rank:

[ q_t \rightarrow q'_t \gg q_t ]

Define Priority Reset Cost (PRC):

[ \text{PRC}_t = \mathbb{E}[IS|q'_t] - \mathbb{E}[IS|q_t] ]

Estimate PRC by replaying comparable states with/without replacement.

3) Keep-priority amend exception

Some venues support in-place amend for restricted edits (e.g., size reduction) while preserving queue priority.
When available:

So model venue capability as a feature:

[ \phi^{kp}_v \in {0,1} ]

and gate action space accordingly.

4) Replace pressure feedback

Frequent replacements can become self-reinforcing:

Define a local pressure index:

[ \text{RPI}_t = z(r_t) + \beta_1 z(\text{tox}_t) + \beta_2 z(\text{deadline burn}) - \beta_3 z(\text{queue advantage}) ]

Higher RPI should increase the penalty on discretionary replace actions.


Action scoring

For each action (a):

[ \text{Score}(a)=\hat{q95}{IS}(a)+\gamma_1\widehat{PRC}(a)+\gamma_2\hat{p}{miss}(a)+\gamma_3\hat{m}_{tox}(a) ]

Choose argmin over feasible actions.

Practical intuition:


Causal estimation notes (important)

Replace decisions are endogenous (we replace more when stressed).
Naive comparisons overstate or understate PRC.

Use at least one of:

  1. bounded randomization on replacement threshold,
  2. doubly robust / AIPW correction,
  3. matched state replay (same regime, queue state, microvol window),
  4. venue-stratified estimation (different priority and amend rules).

State machine

Build Priority Drift Risk State (PDRS) from RPI + miss-pressure + toxicity.

Policy sketch:

Use hysteresis + dwell-time to prevent oscillation.


Data contract (must log)

Per child-order lifecycle:

Daily diagnostics:

  1. PRC calibration (predicted vs realized)
  2. replace-rate vs completion-rate frontier
  3. q95 IS by PDRS state
  4. fraction of replace actions that were avoidable ex-post
  5. share of amend_keep_priority usage where supported

Online pseudo-flow

for each decision tick t:
  S_t <- observe(queue, flow, toxicity, deadline)
  state <- PDRS(S_t)

  actions <- feasible_actions(venue_capabilities, risk_constraints)

  for a in actions:
    q95[a] <- SlippageQ95.predict(S_t, a)
    prc[a] <- PriorityResetCost.predict(S_t, a)
    pmiss[a] <- MissModel.predict(S_t, a)
    mtox[a] <- MarkoutModel.predict(S_t, a)
    score[a] <- q95[a] + g1*prc[a] + g2*pmiss[a] + g3*mtox[a]

  a_t <- argmin(score)
  execute(a_t)
  log(decision + outcomes)

Rollout plan

  1. Shadow (2–3 weeks): compute PRC/RPI/PDRS, no control changes.
  2. Canary (5% flow): enforce replace deadband + amend-first policy.
  3. Ramp: 5% → 15% → 30% with strict q95/miss guardrails.
  4. Promotion: weekly champion–challenger review.

Rollback triggers:


Common failure modes

  1. Blindly minimizing replace count
    • can trap toxic quotes and worsen markout.
  2. Ignoring venue heterogeneity
    • amend rules differ by venue/instrument.
  3. Good average, bad deadline tails
    • must include miss-risk directly in objective.
  4. Queue-estimation drift
    • periodic recalibration needed when feed/latency profile changes.

Practical checklist


References (starting points)


Bottom line

A passive order is not just “posted liquidity”; it is a queue asset with decaying optionality.

If your controller ignores queue-priority drift from cancel/replace churn, it will eventually pay in deadline panic and p95 slippage—even when average spread stats look fine.