Inventory Risk in Market Making

Inventory risk is the directional exposure a market maker accumulates when fills are one-sided — you keep buying as price falls, or selling as price rises, and the spread you earned does not cover the mark-to-market loss. Every market making strategy is a tradeoff between spread capture (good) and inventory accumulation (bad). This article decomposes market-making P&L, introduces the Avellaneda-Stoikov framework, and covers the practical controls that keep inventory from becoming a directional bet you did not intend.

P&L decomposition

A market maker's daily P&L splits into four components:

P&L = spread_capture + inventory_pnl + fees_rebates + adverse_selection_cost
ComponentSourceSign
Spread captureBuy bid, sell ask, repeatPositive (intended edge)
Inventory P&LMark-to-market on net positionPositive or negative
Fees/rebatesExchange maker rebates, taker feesUsually positive for makers
Adverse selectionInformed traders pick you offNegative

The failure mode: spread capture looks steady at +$500/day while inventory P&L bleeds -$2000 on a trend day. Net loss. The maker was providing liquidity to informed flow without adjusting quotes — classic adverse selection.

Why inventory accumulates

Fills are not independent. In a downtrend:

  1. Your bid gets hit (you buy) repeatedly
  2. Your ask does not get lifted (you do not sell)
  3. Net inventory grows long as price falls
  4. Spread earned per round-trip < loss per unit of inventory

This is passive exposure to informed order flow. The market is telling you something through which side fills, and if you ignore it, you are running a losing directional strategy disguised as market making.

Correlation between fill side and subsequent return is the empirical test:

import pandas as pd
import numpy as np

def adverse_selection_cost(fills: pd.DataFrame) -> float:
    """Avg return after fill × fill direction. Positive = you are being picked off."""
    # fill_side: +1 for buy, -1 for sell
    # ret_1m: return in next 1 minute after fill
    picked_off = (fills['fill_side'] * fills['ret_1m']).mean()
    return picked_off  # positive → adverse selection against you

If this metric is consistently positive, your quotes are too tight or too slow to adjust.

Avellaneda-Stoikov framework

The standard model (Avellaneda & Stoikov, 2008) optimizes quotes around a reservation price that skews away from accumulated inventory:

reservation_price = mid - q × γ × σ² × (T - t)
SymbolMeaning
qCurrent inventory (positive = long)
γRisk aversion parameter
σVolatility
T - tTime remaining in session

Quotes are placed around the reservation price, not the mid:

bid = reservation_price - δ/2
ask = reservation_price + δ/2

When long (q > 0), reservation price drops below mid → bid moves down, ask moves down → harder to buy more, easier to sell. This is inventory skew.

def avellaneda_quotes(mid: float, inventory: float, gamma: float,
                      sigma: float, time_left: float,
                      k: float = 1.5) -> tuple[float, float]:
    """Simplified AS optimal quotes."""
    reservation = mid - inventory * gamma * sigma**2 * time_left
    # Optimal half-spread (simplified)
    delta = gamma * sigma**2 * time_left + (2 / gamma) * np.log(1 + gamma / k)
    return reservation - delta / 2, reservation + delta / 2

# Long inventory → lower quotes → encourage selling
bid, ask = avellaneda_quotes(mid=100, inventory=500, gamma=0.1,
                             sigma=0.02, time_left=0.5)

γ controls aggressiveness of skew: high γ → flatten inventory fast (wider spread, more skew); low γ → tolerate inventory for more spread capture.

Practical inventory controls

Beyond AS, production market makers use layered controls:

Hard limits

if |inventory| > max_inv: pull all quotes on accumulating side

Simple, effective, stops the bleeding. Cost: you earn no spread while flat on one side.

Soft skew (linear)

Shift quotes proportionally to inventory without full AS optimization:

bid -= skew_factor × inventory
ask -= skew_factor × inventory

Easier to tune than γ, σ, k. Start here before full AS.

Time-based flattening

As session end approaches, increase γ (or skew_factor) to reach zero inventory. Overnight inventory carries gap risk — most equity MMs flatten into close.

Vol-adjusted spreads

Widen spread when σ rises; inventory losses scale with σ² in the AS model. Connect to GARCH or realized vol estimates.

Toxicity detection

If order flow imbalance is strongly negative, pull bids before they fill. This is adverse-selection-aware quoting — halfway between market making and HFT alpha.

Inventory in crypto market making

Crypto adds:

  • 24/7 exposure — no session end to flatten; inventory can accumulate for days
  • Funding payments — perp inventory earns/pays funding,

changing the carry of holding inventory

  • Fragmented liquidity — inventory on one exchange is not fungible instantly;

transfer risk during rebalancing

  • Liquidation cascades — inventory accumulates into a squeeze; gap risk is extreme

Crypto MMs often hedge inventory with perp positions on another venue — converting inventory risk into basis/funding risk, which may be cheaper to manage.

Measuring market-making edge

Track daily:

MetricHealthy rangeRed flag
Spread capture / volumeStable bps per shareDeclining trend
Inventory P&L / spread capture< 0.5x> 1x (inventory dominates)
Adverse selection (post-fill return)Near 0Consistently positive
Fill rate imbalance~50/50 buy/sell> 60/40 one side
Inventory half-life< 30 min (intraday MM)> 2 hours

If inventory half-life exceeds your horizon, you are not market making — you are directional with extra steps.

Connection to capacity and execution

Inventory risk scales with strategy capacity: larger quotes → more inventory per fill → more skew needed → wider effective spread → less competitive. The optimal size balances spread revenue against inventory variance.

For execution (not pure MM), Almgren-Chriss is the analogous framework: trade off speed (inventory reduction) against impact.

Key takeaways

  • Market-making P&L = spread + inventory + rebates - adverse selection
  • Inventory accumulates one-sided in trends; skew quotes to flatten
  • Avellaneda-Stoikov: reservation price shifts with inventory × γ × σ²
  • Hard limits, soft skew, and toxicity detection are production essentials
  • Track inventory half-life — if it is too long, you are running a directional book
#inventory risk #market making #Avellaneda-Stoikov #bid-ask spread #adverse selection