N-Dimensional Models
The solver crate supports models with arbitrary state dimension through Rust const generics.
ControlProblem<N> trait
The generic contract is [solver::models::control::ControlProblem]. It is
the solver-agnostic abstraction consumed by both the BSDE regression solver
and explicit finite-difference steps:
#![allow(unused)] fn main() { pub trait ControlProblem<const N: usize> { type Control; fn optimize(&self, t, state, derivs) -> Self::Control; fn running_reward(&self, t, state, control) -> f64; fn generator(&self, t, state, control, derivs) -> f64; fn driver(&self, t, state, control, derivs) -> f64; fn terminal(&self, state) -> f64; fn apply_constraint(&self, state, value) -> f64; fn discount_rate(&self, state) -> f64; fn constant_discount_rate(&self) -> Option<f64>; fn next_step(&self, t, state, dt, noise) -> [f64; N]; fn is_diffusion_dimension(&self, dim) -> bool; fn gradient_step(&self, dim) -> f64; } }
StateDerivatives<N> carries first and diagonal second derivatives plus
forward/backward directional differences. Continuous controls consume
grad/hessian; jump controls consume fwd/bwd. For correlated diffusions
it also carries the full symmetric Hessian hessian_full, whose off-diagonal
entries are the mixed second derivatives d^2 V / dx_i dx_j.
Correlated diffusions and the Heston rho term
The generator of a correlated diffusion is
\(\tfrac12\,\mathrm{tr}(D\, \mathrm{Hess}\, V)\) with covariance
\(D = \sigma\sigma^{\top}\), so the off-diagonal entries of hessian_full are
weighted by the off-diagonal covariance. The Heston model does not use this
general path: its value is reduced to the coordinates \([q, v]\) by the CARA
ansatz, so the spot \(S\) is not a grid dimension. The spot-variance correlation
therefore appears as a closed-form drift correction
\[ \rho\,\xi\,v\,\partial_{v}\partial_{S}V = -\gamma\,q\,\rho\,\xi\,v\,\partial_{v}V, \]
folded into the variance drift. This is exact for the reduced model, not an ad
hoc substitution, and it does not need hessian_full because the correlated
coordinate is collapsed. The general cross term is exercised instead by models
with two (or more) diffusive grid coordinates, such as
[solver::models::lq_regulator::LqRegulator] with a full diffusion matrix.
The FD-specific transport contract for implicit and ADI schemes is documented
in PDE Solving Methods. It is a separate trait, not part
of ControlProblem.
Dimension kinds
The generic trait currently exposes two per-dimension signals:
is_diffusion_dimension(dim): the coordinate is driven by Brownian diffusion.gradient_step(dim): physical finite-difference step for mesh-free stencils.
This is not sufficient to select a stable FD stencil. The PDE contract adds
a declarative dimension_kind(dim) with three values: DiscreteJump,
Diffusion, and DeterministicDrift. See PDE Solving Methods
for the stencils.
Conventions
- Dimension 0 is always inventory for market-making models.
- The generic result carries the model's associated
Controltype directly; there is no inventory-specificto_spreadson the generic result. - Spread conversion for market-making lives in
solver::models::market_making::{MarketMakingControl, SpreadResult}.
Proven: N=3 Heston-Hawkes
HestonHawkes implements ControlProblem<3> with state [q, v, lambda]:
- dim 0 (inventory): discrete jump-controlled dimension.
- dim 1 (variance): CIR diffusion,
is_diffusion_dimension(1) = true. - dim 2 (intensity): deterministic mean-reverting drift.
Run the example: cargo run --release --example heston_hawkes_n3.