Order-Book Convexity + Liquidity Elasticity Slippage Playbook

2026-02-28 · finance

Order-Book Convexity + Liquidity Elasticity Slippage Playbook

Date: 2026-02-28
Category: research (execution / slippage modeling)

Why this exists

Most slippage models treat visible depth as a single scalar (top-of-book depth or spread). In production, that misses two structural realities:

  1. Depth shape matters: same total depth can have very different near-touch curvature.
  2. Refill behavior matters: some books refill quickly after a sweep, others stay hollow.

This playbook models slippage with two coupled state variables:

The goal is not prettier TCA charts. The goal is better online action selection (post, improve, take, split, or pause).


1) Core modeling idea

Represent expected child-order slippage as:

[ S_t(q) = S^{\text{instant}}_t(q; C_t) + S^{\text{persistence}}_t(q; E_t, H_t) ]

Interpretation:


2) Convexity state ((C_t))

2.1 Depth-shape fit

For each side of the book, fit cumulative depth curve:

[ D_t(\Delta p) = a_t (\Delta p)^{\gamma_t} ]

Practical reading:

2.2 Size-to-price mapping

Given target size (q), implied walk distance from inverse curve:

[ \Delta p_t(q) \approx \left(\frac{q}{a_t}\right)^{1/\gamma_t} ]

Instant expected impact scales with this walk distance, adjusted for queue priority and spread regime.


3) Elasticity state ((E_t))

3.1 Refill ratio

After consuming book volume, track refill over horizon (\tau):

[ R_{t,\tau} = \frac{\text{added depth over }[t,t+\tau]}{\text{consumed depth at }t + \epsilon} ]

Define elasticity proxy (bounded):

[ E_t = \text{clip}(\log(1+R_{t,\tau}), 0, E_{\max}) ]

Higher (E_t) means faster replenishment and lower persistent impact.

3.2 Cancel-adjusted elasticity

Raw refill can be fake if cancel bursts dominate. Use net refill:

[ R^{net}_{t,\tau} = \frac{\text{adds} - \text{cancels}}{\text{consumed} + \epsilon} ]

In fragile regimes, always prefer net elasticity over gross.


4) Persistence / markout term

Model short-horizon markout penalty with (E_t) and pressure (H_t):

[ S^{\text{persistence}}_t(q) = \beta_0 + \beta_1 q + \beta_2 (1-E_t) + \beta_3 H_t + \beta_4 q(1-E_t) ]

Where (H_t) may include:

This captures the operational truth:

Same sweep size hurts more when refill is weak and tape pressure is one-sided.


5) Data contract (minimum viable)

Unit: child-order decision + realized outcome.

Required fields:

Guardrails:


6) Regime map for control

Build a simple 2D regime map:

Four practical regimes:

  1. Flat+Elastic (low (\gamma), high (E))

    • book tolerant, refill strong
    • allow larger passive clips, occasional controlled take
  2. Flat+Inelastic (low (\gamma), low (E))

    • initial fill easy, residual impact sticky
    • reduce repeat aggression; stagger slices
  3. Convex+Elastic (high (\gamma), high (E))

    • near-touch thin but recovery decent
    • smaller clips, higher cadence acceptable
  4. Convex+Inelastic (high (\gamma), low (E))

    • worst tail-risk state
    • hard POV cap, wider cooldown, SAFE mode candidate

7) Controller coupling (action layer)

For each action candidate (a):

[ J_t(a)=\mathbb{E}[S_t|a] + \lambda_{opp},\text{OppCost}(a) + \lambda_{tail},\text{CVaR}_{95}(S_t|a) ]

Pick action with minimal (J_t(a)) under constraints:

Action set example:


8) Calibration protocol

Offline

Online

Suggested defaults:


9) Failure modes

  1. Using gross refill only

    • hides cancel storms; overestimates resilience.
  2. Single-horizon elasticity

    • 1s refill may look healthy while 10s persistence remains toxic.
  3. Ignoring tick-size regime

    • convexity interpretation differs across tick/price buckets.
  4. Fill-only training set

    • systematically underprices real implementation shortfall.
  5. No action integration

    • accurate forecasts without policy coupling yield no PnL benefit.

10) Minimal implementation sketch

for each decision time t:
  snapshot = get_lob_snapshot(t)
  flow     = get_recent_flow_features(t)

  C_t = fit_convexity(snapshot)            # gamma_t, a_t
  E_t = estimate_net_elasticity(t, tau)    # refill-adjusted
  H_t = pressure_state(flow, microprice, spreads)

  for action a in ACTIONS:
    q_a = proposed_child_size(a)
    S_inst[a] = instant_cost_from_inverse_depth(q_a, C_t)
    S_pers[a] = persistence_model(q_a, E_t, H_t)
    S_total[a]= S_inst[a] + S_pers[a]
    J[a]      = E[S_total[a]] + opp_penalty(a) + tail_penalty(a)

  action = argmin_feasible(J)
  execute(action)
  log(t, C_t, E_t, H_t, action, realized_slippage, markouts)

11) What “good” looks like

If those hold, convexity+elasticity is doing what static depth metrics cannot: it explains not only where liquidity is, but how it behaves after you touch it.