Finite Difference Solver

Policy iteration solver for HJB equations discretized on a grid.

Approach

The HJB PDE is discretized on a grid over the state variables. The solver then iterates:

  1. Policy evaluation: for the current control policy (bid/ask quotes), solve the linear system for the value function at each grid point. Uses SOR for the inner solve.
  2. Policy improvement: at each grid point, find the control that maximizes the HJB residual using the current value function.
  3. Repeat until the policy converges.

Example

#![allow(unused)]
fn main() {
use solver::core::grid::Grid;
use solver::models::avellaneda::AvellanedaModel;
use solver::numeric::finite_difference::solver::PolicyIterationSolver;

// 1D grid over inventory q = [-10, 10], 21 points
let grid = Grid::<1>::new([21], [-10.0], [10.0]);

// Avellaneda-Stoikov model with constant intensity
let model = AvellanedaModel::new(
    0.01,   // gamma: risk aversion
    0.2,    // sigma: volatility
    100.0,  // k: order arrival intensity
    1.0,    // T: terminal time
);

let solver = PolicyIterationSolver::new(0.01); // dt = 0.01
let v = solver.solve(&grid, &model, 100); // 100 time steps
// v[i] = value function at grid point i at t=0
}

Configuration

Grid parameters, boundary conditions, convergence tolerance, and SOR relaxation parameters are configurable. See solver/src/numeric/.

When to use

Finite difference is preferred when:

  • The state space is low-dimensional (1-3 dimensions).
  • You need high accuracy on a fixed grid.
  • The dynamics have simple boundary behavior.

It becomes infeasible above 3-4 dimensions due to the curse of dimensionality (grid points grow exponentially).