0bps

Learn / Track VII / lesson 2 of 4

Market making: the Avellaneda–Stoikov model

Quoting both sides and earning the spread — and the inventory risk and adverse selection that try to take it back.

12 min read

A market maker posts a bid and an ask, buys from sellers and sells to buyers, and aims to earn the spread many times a day. Two forces fight that income:

  • Inventory risk: after a run of fills on one side, you hold a position exposed to price moves.
  • Adverse selection: the counterparties most eager to trade with you are often the ones who know where the price is going.

The Avellaneda–Stoikov model

Avellaneda and Stoikov (2008) derived optimal quotes for a market maker with inventory qq, risk aversion γ\gamma, mid price ss following Brownian motion with volatility σ\sigma, and time T−tT - t remaining in the session.

First, the reservation price — the price at which the market maker is indifferent to holding one more unit:

r=s−q γ σ2 (T−t)r = s - q\,\gamma\,\sigma^2\,(T - t)

If you are long (q>0q > 0), your reservation price sits below the mid, so you quote lower: more eager to sell, less eager to buy. If short, it sits above. This is inventory skew.

Second, the optimal total spread around rr:

δa+δb=γ σ2 (T−t)+2γln⁡ ⁣(1+γk)\delta^a + \delta^b = \gamma\,\sigma^2\,(T - t) + \frac{2}{\gamma}\ln\!\Big(1 + \frac{\gamma}{k}\Big)

where kk describes how quickly fill probability falls as you quote further from the mid (order arrival intensity decays like Ae−kδA e^{-k\delta}). The bid is placed at r−spread/2r - \text{spread}/2 and the ask at r+spread/2r + \text{spread}/2.

Reading the formulas

  • Higher volatility → wider spread and stronger skew: inventory is riskier.
  • Higher risk aversion γ\gamma → stronger skew, faster inventory mean reversion.
  • Larger kk (fill probability falls off quickly) → tighter spread, because quoting wide means you rarely trade.
  • As T−tT - t shrinks, the inventory terms fade: near the end of the horizon you mainly want to get flat.
In crypto perps

There is no session end, so practitioners usually replace (T−t)(T - t) with a fixed horizon parameter, estimate σ\sigma from recent short-horizon returns, and estimate kk from how often quotes at different distances get filled. Funding rates add a carry term to the reservation price.

Adverse selection and protection

The model assumes fills are random. In reality, fills cluster just before the price moves against you. Practical defences:

  • widen or pull quotes when volatility or order-book imbalance spikes,
  • skew quotes using short-term signals (micro-price, trade flow),
  • cap inventory hard and flatten with a market order if breached,
  • cancel quickly; stale quotes are free options for faster traders.
Common mistake

Backtesting a market maker on candles. Fills depend on queue position, cancels and latency, none of which exist in OHLC data. Use tick or order-book data, and assume you are at the back of the queue unless you can show otherwise.

Put it to work

Build this idea

A spec is not a trading system. Paste this into your coding agent and AgenKit runs a specialist team — architecture, test-first build, risk gates, review — with paper trading on by default.

in Claude Code, Cursor, Codex & 4 more
/agenkit build an Avellaneda-Stoikov market making bot for perps from strategies/Dynamic-Spread-Market-Making-Strategy.md with inventory skew management, order deduplication, a max-inventory kill switch, and paper trading by default
  1. npx agenkit install engineering-kit in your project
  2. Paste the command into your agent and approve each phase
  3. Get tests, backtest, risk controls and a paper-trading switch
esc

Try , , or .

↑↓ move↵ open