Implementation Matrix

This page catalogues every configurable option across the three crates and shows which combinations are compatible. Use it to determine what model, solver, and engine setup fits your use case.

Models

The solver crate provides 9 pre-built optimal control models. Each implements Model<N> for a specific state dimension and set of dynamics.

ModelNState variablesLiquidation costInventory boundsDriftImpactUnique feature
AvellanedaStoikov2q, SNo (hardcoded zero)NoNoNoBase AS: constant intensity A
AvellanedaDrift2q, SNoNoYes (mu)NoDrifting mid-price
AvellanedaImpact2q, SHardcoded quadraticNoNoYes (xi)Permanent market impact
AvellanedaHawkes2q, lambdaYesYesNoNoSelf-exciting intensity
BilateralHawkes3q, lambda+, lambda-YesYesNoNoSeparate buy/sell intensities
BilateralHawkesOFI3q, lambda+, lambda-YesYesNoYes (eta_ofi)OFI adverse selection
Heston2q, vYesYesNoNoStochastic volatility (CIR)
HestonHawkes3q, v, lambdaNo (hardcoded zero)NoNoNoCombined Heston + Hawkes
AmericanPut1SHardcoded (K-S)+NoYes (mu)NoNon-market-making benchmark

Terminal conditions

ConditionValue at expirySupported by
ZeroV(T) = 0 for all statesAll 9 models
LiquidationCost`V(T) = -q

Models that do not expose with_terminal_condition have hardcoded terminal values (usually zero, or a model-specific expression like -0.5*xi*q^2 for AvellanedaImpact). To apply uniform terminal liquidation at the backtest level, use run_backtest_with_liquidation from the engine.

Price behaviours captured

BehaviourModels
Constant volatilityAvellanedaStoikov, AvellanedaDrift, AvellanedaImpact
Stochastic volatilityHeston, HestonHawkes
Mean-reverting intensityAvellanedaHawkes, BilateralHawkes, BilateralHawkesOFI, HestonHawkes
Jump diffusion on price(via market_model processes fed to engine, not via solver models)
Permanent market impactAvellanedaImpact, BilateralHawkesOFI
Order flow imbalanceBilateralHawkesOFI (eta_ofi > 0)
Drifting mid-priceAvellanedaDrift

Solvers

Both numerical solvers accept any Model<N> implementation.

SolverMethodBest forTime discretisation
PolicyIterationSolverFinite difference on a gridN <= 3, high accuracyImplicit, Explicit, Crank-Nicolson, Strang ADI
BsdeSolverLeast-squares Monte Carlo regressionN >= 3, scales better with dimensionForward-backward with basis functions
SolverScheme optionsLinear solver
PolicyIterationSolverImplicit (default: Crank-Nicolson), Explicit, StrangAdiSOR, Thomas (tridiagonal), LAPACK dgtsv
BsdeSolverPolynomial basis (Power, Hermite, Chebyshev, Laguerre), degree 1-6, scaling wrapperCustom regression (SVD via faer)

Engine strategies

All strategies implement Strategy and consume Observation (filtered by ObservationFilter) to emit OrderRequests.

StrategyTable dimsTable axesMaturitySource of optimal spreads
AvellanedaStoikovStrategy(none)ProductionAnalytical formula, optional vol estimation
AvellanedaStoikovExactStrategy2D[q, tau]ProductionExact GBM matrix ODE solution
AvellanedaStoikovHestonStrategy3D[q, v, tau]ProductionPrecomputed FDM Heston tables
AvellanedaStoikovHawkesStrategy3D[q, lambda, tau]ProductionPrecomputed FDM Hawkes tables
AvellanedaStoikovBilateralHawkesStrategy4D[q, lambda+, lambda-, tau]ProductionPrecomputed FDM BilateralHawkes tables
AvellanedaStoikovBilateralHawkesOFIStrategy4D[q, lambda+, lambda-, tau]ProductionPrecomputed FDM BilateralHawkesOFI tables
ConstantSymmetricStrategy(none)ProductionFixed half-spread
ZeroIntelligenceStrategy(none)ProductionUniform random half-spread
RandomStrategy(none)ProductionRandom side with small price jitter
ExternalStrategy(none)ProductionExternally injected via set_pending_requests

Strategy to model mapping

StrategyCompatible solver model
AvellanedaStoikovStrategyAvellanedaStoikov, AvellanedaDrift
AvellanedaStoikovExactStrategyAvellanedaStoikov
AvellanedaStoikovHestonStrategyHeston
AvellanedaStoikovHawkesStrategyAvellanedaHawkes
AvellanedaStoikovBilateralHawkesStrategyBilateralHawkes
AvellanedaStoikovBilateralHawkesOFIStrategyBilateralHawkesOFI
ConstantSymmetricStrategy / ZI / RandomAny (model-agnostic)

Matchers

Two matcher implementations determine how limit orders get filled.

MatcherFill mechanismsHawkes supportFeatures
SimpleMatcherAggressive crossing at BBONoDeterministic, zero configuration
StochasticMatcherAggressive + sweep + Poisson arrivalUnilateral or bilateralConfigurable k, a, alpha, beta

StochasticMatcher Hawkes modes

ModeBuildera_eff(t)Parameters exposed
No Hawkesdefaulta (constant)
Unilateral.with_hawkes(alpha, beta)a + excitation(t)hawkes_intensity
Bilateral.with_bilateral_hawkes(alpha, beta)Separate per sidehawkes_buy_intensity, hawkes_sell_intensity

Data sources

SourceProcessesOutputGround truth
SimulatedDataSource<P>GBM, Heston, BatesBBO + vol + drift + paramsOptional (filtered by ObservationFilter)
ParquetDataSourceFile replayBBO onlyNone

Backtesting

FunctionTerminal liquidationCustom lookbackUse case
run_backtestNoNo (default 10)Default path
run_backtest_with_liquidationYes (q* half_spread)
run_backtest_lookbackNoYes (custom steps)Custom adverse selection window

BacktestResult metrics

Return, annualised return, volatility, Sharpe, Sortino, max drawdown, total trades, final equity, mean/max/min inventory, adverse selection (bps), realised edge (bps), inventory variance, PnL spread, PnL directional, fill buy/sell counts, mean hold time, terminal liquidation cost.


Observation filtering

ModeConstructorVisible to strategy
Transparenttransparent()BBO, portfolio, volatility, drift, all parameters
Opaqueopaque()BBO, portfolio only
PartialStruct fieldsBBO, portfolio, selected parameters via whitelist

VecEnv

FieldPurpose
ModelHeston process (fixed, not configurable per env)
MatcherStochasticMatcher with bilateral Hawkes when hawkes_alpha > 0
StrategyExternalStrategy (actions injected per step)
State (6D)[mid, inventory, variance, lambda_buy, lambda_sell, time_remaining]
Action (2D)[bid_distance, ask_distance] from mid
RewardPnL or DiffSharpe, minus inventory penalty
Parallelismrayon across N independent envs