Order-Book Entropy + Cancel-Shock Slippage Early-Warning Playbook

2026-02-26 · finance

Order-Book Entropy + Cancel-Shock Slippage Early-Warning Playbook

Date: 2026-02-26
Category: Research (Execution / Slippage Modeling)
Scope: Intraday equity execution (KR-focused, but portable)


Why this model exists

Most slippage controllers react too late.

They usually wait for one of these to happen:

By then, the order is often already paying the tax.

This playbook builds an early-warning layer for slippage using two leading signals:

  1. Order-book entropy collapse (depth becomes concentrated/fragile),
  2. Cancel shock bursts (visible liquidity evaporates faster than normal replenishment).

Core idea: treat displayed liquidity as perishable inventory. When structure fragility appears before price moves, execution mode should de-risk preemptively.


Conceptual model

We define a latent state variable:

[ S_t \in {\text{Stable}, \text{Fragile}, \text{Toxic}} ]

State transitions are driven by:

The controller maps state to execution policy:


Signal design

1) Order-book entropy

For each side (bid/ask), take top (L) levels with normalized depth weights:

[ p_{i,t}^{(side)} = \frac{q_{i,t}^{(side)}}{\sum_{j=1}^{L} q_{j,t}^{(side)}} ]

Shannon entropy:

[ H_t^{(side)} = -\sum_{i=1}^{L} p_{i,t}^{(side)} \log p_{i,t}^{(side)} ]

Interpretation:

Use an intraday z-score by symbol-time bucket:

[ Z^H_t = \frac{H_t - \mu_{H, bucket}}{\sigma_{H, bucket}} ]

Focus on entropy drop velocity as an early warning:

[ \Delta H_t^{(k)} = H_t - H_{t-k} ]

Large negative (\Delta H) often precedes slippage bursts.


2) Cancel shock index (CSI)

Define per-window cancel and add flow (message-level or L2 diff based):

A robust shock statistic:

[ CSI_t = \frac{C_t - \lambda A_t}{\epsilon + T_t + \eta A_t} ]

with tuned (\lambda, \eta) to discount healthy replenishment.

Then standardize by bucketed history:

[ Z^{CSI}t = \frac{CSI_t - \mu{CSI,bucket}}{\sigma_{CSI,bucket}} ]

A high positive (Z^{CSI}) means liquidity is being withdrawn disproportionately fast.


3) Coupled fragility score

Construct a composite score:

[ F_t = w_1(-Z^H_t) + w_2 Z^{CSI}t + w_3 |\Delta I_t| + w_4 \Delta s_t + w_5 \hat{\sigma}{short,t} ]

where:

This score is a feature (not final decision). Final state should be produced by a probabilistic model.


Modeling stack

A. State classifier (fast path)

Train a 3-class model for (S_t):

Output:

[ P_t = \big(P(Stable), P(Fragile), P(Toxic)\big) ]

B. Tail slippage model (risk path)

Separately model conditional tail cost (e.g., next 30-120s expected IS quantiles):

This path gives the controller risk budget updates.

C. Transition smoothing

Avoid mode flapping with a sticky transition filter:

Example:


Labeling strategy

Define slippage target relative to decision/arrival benchmark:

[ Y_{t,h} = \text{IS}_{t \to t+h} \quad (h \in {30s, 60s, 180s}) ]

Label regimes from forward outcomes + local microstructure context:

Important: use purged temporal splits to avoid leakage from overlapping horizons.


Online controller

Let (B_t) be remaining slippage budget (bps) for the parent order.

Policy template

  1. Infer state probabilities and tail forecasts every (\Delta) seconds.
  2. Update expected budget burn:

[ \hat{b}t = f\big(P_t, \hat{q95}{slip,t}, participation_t\big) ]

  1. Map to action mode:
  1. If projected (B_t) breach risk > limit, force defensive completion protocol.

Feature table (production minimum)


Evaluation framework

Offline

Use block bootstrap by day and symbol cohort.

Shadow/live

Hard stop triggers:


Drift & reliability guards

If entropy input is delayed or malformed, do not keep using stale fragility scores.


Practical implementation notes


Pseudocode

for each decision_tick t:
    x_t = build_features(book, trades, cancels, adds, own_exec)
    p_state = clf.predict_proba(x_t)  # stable/fragile/toxic
    q95 = tail_model.predict_quantile(x_t, q=0.95)

    state = hysteresis_filter.update(p_state)
    burn = burn_model(state, q95, participation, remain_qty)

    if breach_prob(slippage_budget, burn) > TH_BREACH:
        mode = "TOXIC_DEFENSIVE"
    else:
        mode = policy_map(state)

    action = execution_policy(mode, market_state, remain_qty)
    send(action)

What this improves (if done right)

This is not a magic predictor. It is a risk-aware timing layer that moves decisions earlier, when adaptation is still cheap.


Next experiments

  1. Venue-local CSI decomposition to isolate one-venue liquidity failures.
  2. Cross-impact extension for portfolio baskets (fragility contagion across names).
  3. Conformal risk envelope around toxic probability for stronger online coverage guarantees.
  4. Joint optimization of slippage tail + underfill penalty via constrained MPC.

One-line takeaway

If your slippage model only reacts after spread and markout already blow out, you are paying tuition; entropy collapse + cancel shocks let you switch regimes before the bill arrives.