Skip to content

Numerical validation

jaxfolio's optimizers are validated against independent reference solvers — the two code paths share nothing but the mathematics, so agreement is meaningful. This page is the "does it compute the right answer?" evidence: which method is checked against which reference, on what kind of problem, and how close they agree.

How it works

  • References. SciPy SLSQP (a general-purpose constrained optimizer), a CVXPY linear program for CVaR, and PyPortfolioOpt for HRP. Where a method targets an exact mathematical property (e.g. equal risk contributions), we assert that property directly — it is a stronger reference than a second iterative solver.
  • Problem conditions. Each method is exercised on well-conditioned inputs, ill-conditioned inputs (near-singular / collinear covariance, condition number ≳ 10⁴), and degenerate inputs (single asset, zero-variance asset, infeasible bounds). The contract on hard inputs is robustness: stay finite and feasible, and match the reference objective where the optimum is defined.
  • Executable. Every row is backed by a test in tests/validation/ and runs in CI (the validation job). The table below is regenerated by examples/validation/run_matrix.py.

Reproduce it yourself:

uv sync --all-extras
uv run pytest tests/validation -v
uv run python examples/validation/run_matrix.py   # regenerates the table below

Validation matrix

Method Reference Condition Metric jaxfolio Reference value Agreement
Minimum variance SciPy SLSQP well-conditioned variance 4.8074e-05 4.8074e-05 PASS
Maximum Sharpe SciPy SLSQP well-conditioned Sharpe 0.042967 0.042967 PASS
Maximum diversification SciPy SLSQP well-conditioned div. ratio 2.5347 2.5347 PASS
Kelly (log-growth) SciPy SLSQP well-conditioned E[log-growth] 0.00044781 0.00044781 PASS
Risk parity (ERC) Analytic ERC property well-conditioned max|rcᵢ − 1/N| 8.12e-09 0 (exact) PASS
Minimum CVaR CVXPY LP (exact) well-conditioned CVaR₉₅ 0.01729 0.01353 ⚠️ +27.84% (see notes)
HRP PyPortfolioOpt well-conditioned L1 weight dist. PASS (L1=1.11e-07)
Multi-period MV (linear cost) CVXPY QP (exact) well-conditioned path objective -0.0045116 -0.0045114 PASS
Multi-period MV (impact) CVXPY QP (exact) well-conditioned path objective -0.0042534 -0.0042533 PASS
Minimum variance SciPy SLSQP ill-conditioned (κ≈6.0e+04) variance 1.029e-04 1.029e-04 PASS
Risk parity (ERC) finite / feasible ill-conditioned (κ≈6.0e+04) Σw, finite feasible PASS
Minimum variance exact (trivial) degenerate: single asset w = [1] 1.0 1.0 PASS
Minimum variance finite / feasible degenerate: zero-variance asset finite w finite PASS

Known limitations

  • Minimum CVaR. The smooth, Adam-based projected-gradient solver min_cvar defaults to — an explicitly configured optax optimizer is honored instead — converges to a point that is systematically ~26–33% above the exact CVaR optimum found by the CVXPY LP on multi-asset panels, and additional iterations do not close the gap. The direction is correct (it is never below the true optimum) and single-asset / tiny problems are fine, but the multi-asset CVaR result should be treated as approximate. This is tracked by a strict-xfail test (tests/validation/test_reference_solvers.py::test_min_cvar_matches_cvxpy_lp) that will flip to a failure the moment the solver is improved to match the LP — a built-in reminder to remove the caveat. Contributions welcome.

Scope

This matrix covers the classical/convex optimizers and HRP, where an external ground truth exists. Learning-based (deep_sharpe, online_gradient) and LLM-driven strategies are validated by property and integration tests rather than reference-solver equivalence — there is no canonical "correct" allocation to compare against. LLM strategies are additionally experimental.