Class AvellanedaStoikov
java.lang.Object
com.quantfinlib.trading.AvellanedaStoikov
Avellaneda-Stoikov (2008) optimal market-making quotes — the principled
version of the inventory skew
HftQuoter applies heuristically.
Two closed-form answers from one utility-maximization problem:
- Where is MY mid? The reservation price shades the market
mid against your inventory:
r = mid − q·γ·σ²·τ. Long inventory (q > 0) pushes both quotes down — you want to sell, so you make selling attractive and buying not. The shade grows with risk aversion (γ), variance (σ²) and remaining horizon (τ): a big position in a wild market you must carry for hours is worth shading hard; - How wide? The optimal total spread
δ = γ·σ²·τ + (2/γ)·ln(1 + γ/κ)balances the volatility cost of holding inventory against the fill-rate cost of quoting wide, where κ is the order-arrival decay (how fast fill intensity drops as you quote away from the touch — bigger κ = thicker flow near the mid = quote tighter). As γ → 0 the spread collapses to the pure liquidity floor 2/κ.
Units contract (same discipline as
execution.BenchmarkExecutor.MarketState):
priceVariancePerSecond— variance of the PRICE per second, not the return: from the signal engine,Math.pow(mid * sig.volPerSqrtSecond(sym), 2). NaN or negative reads as 0 (the inventory term disables; the liquidity floor keeps quoting sane);horizonSeconds— time to the moment inventory must be flat (the close, the fixing). Continuous 24/5 FX has no terminal time: use a fixed risk horizon (how long you are willing to sit on a position) — the standard practitioner reading of τ;inventory— signed position in UNITS OF THE INSTRUMENT the mid prices (shares of the stock, base-currency units of the pair). This is dimensional, not stylistic: the shadeq·γ·σ²·τis in price units only when q counts the same thing σ² is quoted per — pass round lots instead of shares and the shade silently shrinks 100× while the spread term (which never sees q) is unchanged, gutting the skew that is the model's point. Calibrate γ with the inventory unit fixed first.
Wiring into the fast lane: compute reservationPrice − mid as
the inventory skew and optimalHalfSpread(double, double) as the half-spread,
and feed both to HftQuoter's skew/spread inputs — the model
decides, the quoter executes. Pure static-shape math on primitives:
zero allocation, safe on any thread. Like every model here, γ and κ
deserve calibration against your own fill data before the output is
trusted with size.
-
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptiondoubleaskQuote(double mid, double inventory, double priceVariancePerSecond, double horizonSeconds) The ask to quote: reservation price plus the optimal half-spread.doublebidQuote(double mid, double inventory, double priceVariancePerSecond, double horizonSeconds) The bid to quote: reservation price minus the optimal half-spread.doublegamma()doublekappa()doubleoptimalHalfSpread(double priceVariancePerSecond, double horizonSeconds) Half of the optimal total spread:(γ·σ²·τ)/2 + (1/γ)·ln(1 + γ/κ).doublereservationPrice(double mid, double inventory, double priceVariancePerSecond, double horizonSeconds) The inventory-shaded fair value:mid − inventory·γ·σ²·τ.
-
Constructor Details
-
AvellanedaStoikov
public AvellanedaStoikov(double gamma, double kappa) - Parameters:
gamma- risk aversion, e.g. 0.1 (bigger = shade and widen more)kappa- fill-intensity decay per unit distance from the touch, e.g. 1.5 (bigger = flow concentrates at the mid)
-
-
Method Details
-
reservationPrice
public double reservationPrice(double mid, double inventory, double priceVariancePerSecond, double horizonSeconds) The inventory-shaded fair value:mid − inventory·γ·σ²·τ. Flat inventory or a dead/garbage variance returns the mid itself. -
optimalHalfSpread
public double optimalHalfSpread(double priceVariancePerSecond, double horizonSeconds) Half of the optimal total spread:(γ·σ²·τ)/2 + (1/γ)·ln(1 + γ/κ). Never below the liquidity floor — even a becalmed market pays for immediacy. -
bidQuote
public double bidQuote(double mid, double inventory, double priceVariancePerSecond, double horizonSeconds) The bid to quote: reservation price minus the optimal half-spread. -
askQuote
public double askQuote(double mid, double inventory, double priceVariancePerSecond, double horizonSeconds) The ask to quote: reservation price plus the optimal half-spread. -
gamma
public double gamma() -
kappa
public double kappa()
-