Post-Only Reject Cascade + Maker-Fallback Slippage Playbook
Date: 2026-03-05
Category: research
Domain: execution microstructure / slippage modeling
Why this matters
Many desks treat post-only as “free spread capture.” In live markets, that assumption breaks when books move during gateway/venue latency:
- your post-only order becomes marketable,
- venue rejects (or reprices),
- you retry,
- queue priority resets,
- and the trade ends up crossing anyway at worse prices.
This reject → retry → queue reset → panic take loop creates hidden slippage that standard maker/taker fee models miss.
Core idea
Model post-only execution as a branching process rather than a single passive fill path.
At each child-order decision, expected cost should include:
- Accept branch (post-only accepted and resting)
- Reject branch (would-cross protection, price moved, or venue rule mismatch)
- Fallback branch (switch to taker, midpoint, or pause)
Optimize across branches under a tail-risk budget (p95/CVaR), not average bps alone.
Slippage decomposition
For one child order at decision time (t):
[ EC_t = P(A)\cdot C_A + P(R)\cdot C_R + P(F|R)\cdot C_F ]
Where:
- (A): post-only accepted
- (R): post-only rejected
- (F): fallback action after reject
- (C_A): accepted-path cost (spread capture, rebate, markout, non-fill risk)
- (C_R): reject-path cost (latency drift + retry overhead + queue-reset tax)
- (C_F): fallback-path cost (cross spread + impact + urgency penalty)
Key hidden term:
[ C_R \approx \Delta p_{latency} + QueueResetTax + RetryControlCost ]
Most implementations underestimate (\Delta p_{latency}) and ignore queue reset tax.
Practical state variables
Use a compact feature set that can be maintained in real time:
Market microstructure
- Spread in ticks
- Microprice drift (50ms/200ms)
- Top-of-book depletion hazard
- Cancel/trade ratio near touch
- Quote age / stale depth ratio
Execution path
- Venue round-trip latency (p50/p90/p99)
- Post-only reject reason distribution
- Retry count in rolling window
- Queue position loss estimate per retry
Cost + risk
- Net maker edge (spread + rebate - expected markout)
- Fallback expected taker cost
- Remaining parent urgency / deadline slack
- Tail-budget burn (today/session strategy)
New desk-level metrics
PORS (Post-Only Reject Score)
Weighted reject intensity: [ PORS = w_1\cdot RejectRate + w_2\cdot RejectBurst + w_3\cdot DriftDuringRetry ]QRT (Queue Reset Tax)
bps loss attributable to lost queue priority after retries.MII (Maker Illusion Index)
Difference between naive maker edge and branch-aware expected edge: [ MII = Edge_{naive\ maker} - Edge_{branch\ aware} ]FCR (Forced Cross Ratio)
Fraction of initially passive intents that ended as taker fills after reject cascades.
Regime state machine
1) MAKER_OK
- Low reject rate
- Stable touch
- Positive branch-aware maker edge
Action:
- Use post-only baseline sizing
- Normal retry policy
2) FRICTION
- Reject rate rising
- Mild drift during retries
- Queue reset costs visible
Action:
- Reduce child size
- Increase price buffer logic
- Cap retries aggressively
3) REJECT_STORM
- Reject bursts + fast drift
- Forced-cross ratio elevated
- Tail budget burning
Action:
- Disable post-only on affected venue/symbol cluster
- Route to midpoint/taker with explicit risk cap
- Increase urgency only within budget guardrails
4) SAFE
- Severe instability or model-confidence drop
Action:
- Minimal-risk completion mode
- Tight notional caps
- Human alert + incident logging
Use hysteresis to avoid state flapping.
Control policy (production sketch)
At each decision step:
- Estimate (P(A), P(R), P(F|R))
- Estimate branch costs (C_A, C_R, C_F)
- Compute branch-aware expected cost + risk penalty
- Pick action from
{post_only, post_only_buffered, midpoint, taker, pause} - Enforce hard guards:
- max retries/order
- max reject burst/window
- max tail-budget burn rate
- max forced-cross ratio
Calibration workflow
Data contract
Per attempt (not just per fill):
- decision timestamp (source + exchange clock)
- intended limit, side, size
- venue / order type / post-only flag
- ack/reject timestamps and reason codes
- retry linkage key (attempt chain)
- eventual fill path and markouts
Modeling sequence
- Reject probability model (classification, calibrated)
- Retry-drift model (quantile regression)
- Queue reset tax model (survival/fill-hazard delta)
- Fallback cost model (impact + spread + markout)
- Joint branch simulator for policy evaluation
Prefer quantile loss + calibration checks over MSE-only reporting.
Backtest and replay safeguards
- Include rejected/canceled attempts (avoid fills-only survivorship bias)
- Replay with venue-specific post-only rules
- Simulate latency jitter bursts, not fixed latency
- Use p95/CVaR targets as promotion gates
Promotion criteria example:
- p95 implementation shortfall improvement >= 8%
- forced-cross ratio reduction >= 15%
- completion rate degradation <= 2%
- no guardrail breach in stress replay pack
Failure modes to watch
- Fee illusion: rebate-focused routing that ignores reject cascades
- Over-retry loop: retries increase urgency cost faster than expected
- Venue drift mismatch: one venue enters reject storm earlier than others
- Clock integrity issues: bad timestamps hide retry latency cost
- Policy thrash: no hysteresis between maker and taker modes
2-week implementation plan
Week 1
- Add attempt-chain telemetry
- Compute PORS/QRT/MII/FCR dashboards
- Build reject + retry-drift baseline models
Week 2
- Add state machine controller in shadow mode
- Run historical + live shadow comparisons
- Roll out with 5% traffic canary and kill switch
Bottom line
Post-only is not a binary “maker good” switch; it is a conditional strategy with path-dependent failure costs.
A branch-aware slippage model that explicitly prices reject cascades turns passive execution from fee theater into controllable risk-adjusted edge.