Skip to content

kshitijbhandari/Market-Making-Simulator

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Market Making Simulator — Equity & Options

A simulation of an automated market maker operating on SPY shares and SPY call options, built on the Avellaneda-Stoikov (2008) optimal quoting framework. Parameters are calibrated from real SPY market data. The project covers the full pipeline: data download → parameter calibration → simulation → analysis.


What Is a Market Maker?

A market maker continuously posts a bid (price to buy) and an ask (price to sell). Every time a counterparty trades against one of these quotes, the MM earns the spread i.e. the difference between the bid/ask and the fair value of the instrument. The MM does not take directional bets; it profits purely from facilitating trades.

The risk is inventory accumulation: if the MM buys more than it sells, it is left holding a position that loses money if the price falls. The Avellaneda-Stoikov model solves for quotes that optimally balance spread income against this inventory risk.


Project Structure

├── src/
│   ├── mm_core.py              # Avellaneda-Stoikov core: reservation price, optimal spread,
│   │                           # arrival intensity, inventory control (shared by both MMs)
│   ├── option_pricing.py       # Black-Scholes pricing, Greeks, SABR implied vol
│   └── option_mm_engine.py     # Option MM simulation engine (delta hedging, P&L decomposition)
│
├── notebooks/
│   ├── equity_mm/
│   │   ├── data_calibration.ipynb         # Data download + parameter calibration (equity)
│   │   └── simulation.ipynb               # Multi-day equity MM simulation + analysis
│   └── option_mm/
│       ├── arrival_rate_calibration.ipynb # Arrival intensity calibration from real options volume
│       ├── data_setup.ipynb               # Data download + SABR calibration (options)
│       ├── simulation.ipynb               # Multi-day option MM simulation
│       └── analysis.ipynb                 # Greeks exposure, sensitivity, equity vs option comparison
│
├── outputs/
│   ├── equity_mm/              # Charts and logs from equity MM
│   └── option_mm/              # Charts, simulation pickle, and logs from option MM
│
└── requirements.txt

The Model

Reservation Price

The MM does not quote at the fair value mid. It adjusts by its inventory and risk aversion:

$$r = S - q \cdot \gamma \cdot \sigma_d^2 \cdot \left(1 - \frac{t}{T}\right)$$

  • $q$ — current inventory (positive = long, negative = short)
  • $\gamma$ — risk aversion coefficient
  • $\sigma_d$ — dollar volatility per unit per day
  • $t/T$ — fraction of trading session elapsed

As inventory grows long, $r$ falls below mid → the MM quotes a lower bid and ask to encourage selling. The adjustment shrinks to zero at close, eliminating end-of-day liquidation pressure.

Optimal Spread

$$\delta^* = \underbrace{\gamma \sigma_d^2 \left(1 - \frac{t}{T}\right)}_{\text{inventory risk}} + \underbrace{\frac{2}{\gamma} \ln!\left(1 + \frac{\gamma}{\kappa}\right)}_{\text{adverse selection}}$$

The first term compensates for holding inventory overnight; the second compensates for the possibility that the counterparty knows something you don't.

Order Arrival

Order arrivals follow a Poisson process with intensity decaying exponentially from mid:

$$\lambda(\delta) = A \cdot e^{-\kappa \delta}$$

$A$ is the base arrival rate, $\kappa$ controls how quickly flow dries up as the quote moves away from fair value. Both are calibrated from data.

Inventory Control

Three modes are implemented:

Mode Description
0 No control — quotes unchanged
1 Hard limits — suppress the quote on the side that would worsen inventory when |q| ≥ Q_max
2 Hard limits + soft skew — beyond 50% of Q_max, gradually push the undesired quote further away

Part 1 — Equity Market Making

Instrument: SPY shares
Data: 1-minute OHLCV bars, ~20 trading days
Calibrated parameters:

Parameter Value Meaning
σ_d $7.58 / share / day Dollar volatility per share
κ 8.68 / $ Order book resilience
A 2.394 fills/min Base arrival rate
γ 0.0040 Risk aversion
Q_max 3 (normalized) Max inventory

Results (20-day backtest):

  • Mean daily P&L: ~$0.069
  • Annualised Sharpe: ~136
  • Win rate: ~88%
  • P&L breakdown: ~94% spread income, ~6% inventory P&L

The lot size is normalized to $1 notional per unit, so absolute P&L is small by design. The Sharpe and win rate are the meaningful metrics.

Model caveat: The Sharpe of ~136 and near-perfect win rate are significantly inflated by the assumption that all order flow is uninformed as counterparties arrive randomly with no knowledge of future price moves. In reality a portion of flow comes from informed traders who systematically trade against the MM on adverse fills, compressing spreads and introducing losing days. These figures should be read as an upper bound on strategy performance under ideal conditions.


Part 2 — Options Market Making

Instrument: SPY front-month call option (~40 DTE, near-ATM strike)
Data: 5-minute OHLCV bars, 40 trading days
Pricing model: Black-Scholes with SABR implied vol smile
Lot size: 100 shares per contract (standard US options)

What changes for options

  1. Dollar volatility is scaled by delta:
    $\sigma_d^{opt} = |\Delta| \cdot S \cdot \sigma_{annual} / \sqrt{252}$
    This gives the daily P&L volatility of holding one option contract — the direct analogue of $\sigma_d$ in the equity MM.

  2. Delta hedging: On every fill, the MM immediately buys or sells SPY shares equal to $-\Delta \times \text{lot}$ to neutralise directional exposure. The hedge is rebalanced every bar.

  3. P&L decomposition:

    • Spread income — half-spread captured on each fill
    • Theta P&L — time value that decays each minute in the seller's favour
    • Gamma P&L$\frac{1}{2} \Gamma \cdot \Delta S^2$ profit from delta rebalancing on underlying moves

Arrival rate calibration

$A$ was calibrated from real SPY options volume data (2021–2022, 30–60 DTE, near-ATM strikes):

  • Median per-strike ATM call volume: 871 contracts/day
  • Assuming 5% market share: $A = 2.44$ fills/minute
  • Assuming 10% market share: $A = 4.88$ fills/minute

Calibrated parameters

Parameter Value Meaning
σ_iv SABR-fitted Implied vol (smile-adjusted per bar)
κ calibrated Arrival decay rate
A 2.44 Base arrival rate (5% market share)
γ 0.004 Risk aversion
Q_max 10 contracts Max inventory

Results (40-day backtest)

Metric Value
Mean daily P&L $890.32
Std daily P&L $57.99
Annualised Sharpe 243.7
Win rate 100% ⚠
Total P&L (40 days) $35,613
Avg fills per day 80.6
Avg spread income/day $885.99
Avg theta P&L/day −$0.67
Avg gamma P&L/day +$0.32

Nearly all P&L originates from spread income. Theta and gamma are small and roughly offsetting — consistent with implied volatility ≈ realised volatility over the sample period.

⚠ Model caveat: The Sharpe of 243.7 and 100% win rate are severely inflated by the assumption that all order flow is uninformed. Every counterparty in the model arrives randomly i.e. no one knows the price is about to move. In practice, a real options desk faces informed traders who pick off quotes just before large moves, adverse selection on the delta hedge (hedging into a trending market), and transaction costs on every hedge rebalance. These factors would materially reduce both mean P&L and the Sharpe ratio. The figures above represent a theoretical upper bound under the uninformed-flow assumption.

Greeks exposure

  • Net delta after hedge: stays within ±0.2 shares around zero across all days which confirms the hedge eliminates directional risk effectively.
  • Option delta: ~0.50 at open (ATM by construction), drifts slightly with intraday SPY moves.
  • Gamma and vega: nearly flat intraday which is expected at 40+ DTE where a single day's time decay is negligible (~0.4% of remaining theta).

Inventory behaviour

Maximum inventory reached across all 40 days: ~3 contracts (Q_max = 10). The symmetric Poisson fill model means buyers and sellers arrive in roughly equal numbers, so inventory mean-reverts naturally. The hard inventory limits were never binding.


Running the Project

# Install dependencies
pip install -r requirements.txt

# Run notebooks in order:
# Equity MM
notebooks/equity_mm/data_calibration.ipynb
notebooks/equity_mm/simulation.ipynb

# Options MM
notebooks/option_mm/arrival_rate_calibration.ipynb   # optional, A already set
notebooks/option_mm/data_setup.ipynb
notebooks/option_mm/simulation.ipynb
notebooks/option_mm/analysis.ipynb

References

  • Avellaneda, M. & Stoikov, S. (2008). High-frequency trading in a limit order book. Quantitative Finance, 8(3), 217–224.

About

Avellaneda-Stoikov market making framework applied to SPY equity and options. Covers parameter calibration from real market data, Black-Scholes/SABR pricing, delta hedging, and P&L decomposition across 40 simulated trading days.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors