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.
| Seed | Recovered \(Y_0\) | Relative error |
|---|---|---|
| 0 | 10.6899 | 2.29% |
| 1 | 10.3775 | 0.70% |
| 2 | 10.4705 | 0.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.
| Activation | Recovered \(Y_0\) | Relative error | Final loss |
|---|---|---|---|
softplus | 10.4366 | 0.13% | 2.285 |
relu | 10.4942 | 0.42% | 6.291 |
tanh | 10.6899 | 2.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}\).
| Method | Exact | Recovered | Relative error |
|---|---|---|---|
| DGM | 10.4506 | 10.5659 | 1.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.
| Method | Quantity | Exact | Recovered | Relative error |
|---|---|---|---|---|
| Deep BSDE | Initial value \(V(0, x_0)\) | -0.37630 | -0.37894 | 0.70% |
| DGM | Initial value \(V(0, x_0)\) | -0.37630 | -0.37129 | 1.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:
| Check | Quantity | Measured 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\).
| Method | Quantity | Exact | Recovered | Relative error |
|---|---|---|---|---|
| Deep BSDE | Initial value \(V(0, x_0)\) | 4.74870 | 4.74767 | 0.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.