An interactive, high-fidelity implementation of the seminal Avellaneda-Stoikov (2008) model for algorithmic market making. This simulator explores the stochastic control problem of managing inventory risk while providing liquidity in a limit order book.
In-depth essay: here
The simulator models a market maker (MM) who provides liquidity by simultaneously posting bid and ask quotes. The MM's goal is to capture the spread while managing Inventory Risk (the risk of price movement against a held position) and Adverse Selection (the risk of trading against informed participants).
The system runs a real-time loop (160ms ticks) simulating a continuous market environment using Geometric Brownian Motion for price action and Poisson processes for trade arrivals.
The simulator is built on three core mathematical pillars:
Unlike a naive trader who quotes around the mid-price
-
$s$ : Current Mid-Price. -
$q$ : Inventory position (positive for long, negative for short). -
$\gamma$ : Risk aversion parameter. -
$\sigma$ : Market volatility. -
$(T-t)$ : Remaining time horizon.
Logic: If the MM is "Long" (
The model calculates the optimal distance from the reservation price to place the bid and ask quotes:
The total spread is comprised of an Inventory Risk Premium and an Adverse Selection Premium. As volatility (
The probability of a quote being "hit" (a fill) is modeled as a decaying exponential function of the distance from the mid-price:
-
$A$ : Intensity of overall market trades (frequency). -
$k$ : Market "depth" or price sensitivity. High$k$ means the market is very sensitive; if your price is too far from the mid, you will never get filled.
The application is a single-file web tool (index.html) using Chart.js for visualization and vanilla JavaScript for the simulation engine.
-
Price Engine (
randnfunction): Uses the Box-Muller Transform to generate Gaussian noise for the Geometric Brownian Motion (GBM) update. -
Quote Engine (
asQuotesfunction): The mathematical "brain" that calculates$r$ and$\delta$ based on current state and slider inputs. -
Fill Engine (
poissonProbfunction): Determines fills by comparing a random float against the calculated Poisson intensity for both the bid and ask sides. - State Management: Tracks PnL (Mark-to-Market), Cash, Inventory, and Fills in a centralized loop.
| Parameter | Symbol | Impact on Behavior |
|---|---|---|
| Risk Aversion | Higher values lead to wider spreads and more aggressive "skewing" to keep inventory at zero. | |
| Volatility | Increases the "drift" of the price and widens spreads to account for larger potential price swings. | |
| Order Depth | Represents how "thick" the order book is. Higher |
|
| Order Frequency | Controls the total volume of trades in the market. | |
| Manual Skew | — | A heuristic override to force the MM to lean long or short regardless of the model's math. |
Based on the research provided in the accompanying essay:
- The Inventory Leash: Pure spread-capture is impossible without an inventory limit. The reservation price acts as a "leash" that pulls the MM back to a neutral position.
-
Regime Awareness: In high-volatility regimes, the MM must increase
$\gamma$ to survive. In low-volatility, "mean-reverting" regimes, the MM can lower$\gamma$ to capture more volume. -
Adverse Selection: When
$k$ is high, the MM is effectively competing in a "winner-take-all" price environment, requiring tighter spreads and faster reaction times.
- Download the
index.htmlfile or open this link: here - Open it in any modern web browser (Chrome, Firefox, or Edge recommended).
- Adjust the sliders to set your market conditions.
- Avellaneda, M., & Stoikov, S. (2008). High-frequency trading in a limit order book.
- Implementation and documentation by Handiko Gesang.
