Empirical Results

Measured results for the neural methods. The theory behind these methods is in the theory section. All numbers below are CPU measurements with JAX 0.11.x, recorded on 2026-08-23; they are indicative of correctness, not of GPU throughput.

Deep BSDE validation

The deep BSDE Z-process method is validated against closed forms. In all runs the network is an Mlp((2, 32, 32, 1)) and training uses Adam with learning rate \(10^{-2}\) and a fixed Monte Carlo dataset.

Black-Scholes European call

Parameters: \(S_0 = 100\), \(K = 100\), \(r = 0.05\), \(\sigma = 0.2\), \(T = 1\). Exact price \(10.4506\). 512 paths, 25 steps, 3000 iterations.

SeedRecovered \(Y_0\)Relative error
010.68992.29%
110.37750.70%
210.47050.19%

Merton log-utility portfolio

Parameters: \(\mu = 0.08\), \(r = 0.03\), \(\sigma = 0.2\), \(X_0 = 100\), \(T = 1\). The known optimal fraction is \(\pi^* = 1.25\); the exact initial value is \(\log(100) + 0.06125 = 4.66642\). The deep BSDE recovers this within the 10% test tolerance.

Architecture comparison

The activation choice was compared on the Black-Scholes problem above (seed 0, same hyperparameters). Reproduced by neural_solver/benchmarks/architecture_study.py.

ActivationRecovered \(Y_0\)Relative errorFinal loss
softplus10.43660.13%2.285
relu10.49420.42%6.291
tanh10.68992.29%60.031

softplus wins for this smooth problem, consistent with its role as the standard DGM activation. The ordering is not universal: kinked value functions (which jump and control-boundary problems produce) are expected to favor relu or an adaptive activation, as discussed in the jump theory.

Deep HJB (DGM) validation

Black-Scholes European call

The DGM value network minimizes the Black-Scholes PDE residual plus a terminal-condition term. Parameters: \(S_0 = 100\), \(K = 100\), \(r = 0.05\), \(\sigma = 0.2\), \(T = 1\). Exact price \(10.4506\). 1024 interior and 256 terminal collocation points, Mlp((2, 32, 32, 1)) with softplus, 3000 iterations, learning rate \(10^{-3}\).

MethodExactRecoveredRelative error
DGM10.450610.56591.10%

Jump linear-quadratic regulator

The jump-LQ problem is the minimal benchmark for the Gamma path: the state and control are scalar, a single Poisson jump source drives the jump term, and the value has a closed-form Riccati/affine solution. Parameters: \(a = -0.5\), \(b = 1\), \(\sigma = 0.2\), \(q = 1\), \(r = 1\), \(q_T = 1\), \(\lambda = 1\), \(\xi = 0.25\), \(x_0 = 0.5\), \(T = 1\). 512 paths, 25 steps, 3000 iterations.

MethodQuantityExactRecoveredRelative error
Deep BSDEInitial value \(V(0, x_0)\)-0.37630-0.378940.70%
DGMInitial value \(V(0, x_0)\)-0.37630-0.371291.33%

The recovered values are negative as required, and the relative errors are comparable to the diffusion deep BSDE on a smooth problem. The exact value -0.37630 comes from the Riccati solution P = 0.65345, m = 0.21258, n = 0.10664 at tau = 1; the asymmetric jump (xi = 0.25) is what makes the linear coefficient m non-zero and therefore exercises the affine correction in the control.

Integrand and correction validation

Matching the scalar initial value alone cannot detect a network that learns the no-jump -P x^2 part and drops the jump correction, because the affine m x + n term is small relative to the total value. Two stronger checks isolate the jump path directly:

CheckQuantityMeasured mean relative error
Z integrand\(Z = \sigma V_x\) at \(x_0\), over \(t\)~4%
Gamma integrand\(\Gamma = V(x_0+\xi) - V(x_0)\), over \(t\)~2%
Correction presence\(V_{\text{jump}} - V_{\text{no-jump}} = m x + n\)\(-0.1825\) (exact), recovered value tracks it

The learned Gamma is strictly negative and non-zero, so the jump correction is not silently absorbed into the value. These are evaluated on the reachable region (near \(x_0\), where the Monte Carlo paths concentrate); off-manifold points degrade as expected because the network never saw them. The checks live in neural_solver/tests/test_bsde_jump.py and use a documented 10% mean relative-error band (the terminal-matching loss does not supervise Z or Gamma directly).

Merton jump portfolio

The Merton log-utility portfolio with a deterministic multiplicative jump is the first jump target where the optimal control itself depends on the jump. Parameters: \(\mu = 0.08\), \(r = 0.03\), \(\sigma = 0.3\), \(\lambda = 1\), \(y = 1.1\), \(X_0 = 100\), \(T = 1\). The optimal fraction rises from the no-jump value \(0.5556\) to \(u^* = 1.5201\) because the upward jump makes the risky asset more attractive. The exact initial value is \(4.74870\).

MethodQuantityExactRecoveredRelative error
Deep BSDEInitial value \(V(0, x_0)\)4.748704.747670.022%

Because Z and Gamma are constants for this problem (\(Z = \sigma u^*\) and \(\Gamma = \ln(1 + u^*(y-1))\)), the method converges far more tightly than on the jump-LQ problem. The learned Gamma is positive and tracks the exact constant to within 10%, confirming the jump correction is captured rather than absorbed. See neural_solver/tests/test_merton_jump.py.

For the log-normal jump size (\(\ln Y \sim \mathcal{N}(m, \delta^2)\) with \(m = -0.02\), \(\delta = 0.05\)), the optimal fraction is a numerical root, \(u^* = 0.3386\) (below the no-jump \(0.5556\), since the jumps are downward on average), and the exact initial value is \(4.64049\). This is a reference-only model: it is validated against the Rust reference (neural_solver/tests/test_merton_jump_lognormal.py) but is not trained by the deep BSDE loop, which does not yet sample random jump sizes.

Reference agreement (no training)

The JAX closed forms reproduce the Rust solver reference values within 1e-6 (float32) for Merton policy and value, and Black-Scholes positivity. See neural_solver/tests/test_reference_match.py.