Adverse-Selection Markout Gating Playbook (Production-First)
Date: 2026-02-23
Category: research
Context: Practical execution control for live trading where spread capture often gets erased by toxic fills.
Why this matters
A lot of passive execution looks good at fill time and bad 5–60 seconds later.
That gap is adverse selection. If we don’t measure and gate on it, “good fill ratio” becomes false comfort.
Core idea
Use short-horizon markout as a live toxicity signal and tie it directly to execution aggressiveness.
- If markout stays healthy: keep passive participation.
- If markout degrades: reduce passive exposure, widen quote selectivity, or shift temporary aggression to finish safely.
Minimal data contract
For each child order / fill, store:
ts_decision(order decision time)ts_fillside(buy/sell)px_fillmid_t+5s,mid_t+30s,mid_t+60sspread_at_fill,volatility_regime,imbalance_statevenue,order_type,participation_rate
Derived:
markout_5s_bps(signed)markout_30s_bps(signed)markout_60s_bps(signed)
Signed convention: positive = favorable after fill; negative = toxic fill.
Live toxicity score
Build a simple score first (no overfitting):
toxicity_score = w1*EMA(markout_5s) + w2*EMA(markout_30s) + w3*fill_to_cancel_ratio_z + w4*short_term_vol_z
Suggested defaults:
w1=0.5, w2=0.3, w3=0.1, w4=0.1- EMA half-life 5–15 minutes intraday
Focus on stability over cleverness.
3-state gating policy
State A — Normal
Condition:
toxicity_score > -0.5
Actions:
- Baseline passive POV
- Normal quote width / replenishment
State B — Caution
Condition:
-1.5 < toxicity_score <= -0.5
Actions:
- Reduce passive POV by 25–40%
- Increase min edge threshold (don’t join every queue)
- Increase slice interval slightly
State C — Defensive
Condition:
toxicity_score <= -1.5
Actions:
- Cut passive POV by 60–80%
- Use selective liquidity-taking for time-risk control
- Tighten max participation caps by venue
- Trigger short cool-down timer before re-entering Normal
Add hysteresis so states don’t flap every minute.
Calibration loop (weekly)
- Bucket fills by state (Normal/Caution/Defensive).
- Compare p50/p90/p95 implementation shortfall and completion risk.
- Check if Defensive actually reduces tail loss without excessive underfill.
- Retune thresholds first; only then retune weights.
Rule: optimize for tail protection, not best average bps on calm days.
Guardrails
- Hard max participation ceiling per symbol liquidity tier
- News-window override (earnings/FOMC/CPI): start from Caution
- Kill-switch if markout collapses beyond extreme quantile threshold
- Venue quarantine if venue-specific toxicity spikes persist
Failure modes to avoid
- Overreacting to tiny sample windows
- Ignoring underfill/opportunity-cost while optimizing markout
- Using one universal threshold across all symbols/regimes
- No hysteresis (constant state churning)
Practical rollout plan
Phase 1 (shadow): compute score + hypothetical states only.
Phase 2 (limited capital): apply gating on small notional universe.
Phase 3 (full): enable across book with dashboard + alerting.
Success criteria
- Lower p95 shortfall in stress windows
- Stable completion ratio (or explicitly controlled trade-off)
- Fewer sudden “fill looked fine then instantly went bad” episodes
Execution quality is not just spread capture; it’s post-fill path quality.
Markout gating makes that explicit and actionable.