C++ options pricing engine implementing the Heston stochastic volatility model with both Quasi-Monte Carlo and semi-analytical characteristic-function pricing, stress-tested using regime-aware non-parametric bootstraps, with Python bindings via pybind11.
- Heston dynamics with full-truncation Euler scheme.
- Quasi-Monte Carlo path generation (Halton + random shift) with antithetic variates.
- Optional Sobol sequence engine (Joe-Kuo direction numbers) for high-dimensional QMC runs.
- Semi-analytical vanilla pricing via COS (primary) and Carr-Madan FFT (benchmark/surface grid).
- Deterministic calibration objective using COS pricing with
scipydifferential evolution. - Automated market ingestion with
yfinance, UTC-normalized timestamps, and data-contract validation. - Automated data-quality reporting (missing/stale/outlier diagnostics) on downloaded regimes.
- Multiple bootstrap engines:
iid,moving_block,circular_block,stationary(+ automatic block-length inference). - Higher-order sensitivity scorecards:
Delta,Gamma,Vega,Vanna,Volga,Charm. - Portfolio-level risk aggregation with book Greeks and VaR/CVaR (95%/99%).
- Statistical validation report for bootstrap realism (ACF and tail-preservation diagnostics).
- Quantitative validation benchmarks: confidence error bands, path-count convergence checks, and Black-Scholes baseline comparison.
- Greek-based PnL attribution and markdown risk memo generation.
- Stress framework that reprices vanilla Europeans across spot/volume perturbation grids under historical bootstrap regimes (COS or QMC backend).
- Implied-volatility surface construction from Carr-Madan prices plus SVI slice fitting utilities.
- Optional OpenMP acceleration for C++ loops with graceful non-OpenMP fallback.
- Optional CUDA accelerator path for Monte Carlo pricing (when CUDA toolkit/compiler is available).
- Native C++ implementation with Python access through
pybind11.
src/heston.hpp,src/heston.cpp: core engine.src/bindings.cpp: Python module interface (heston_qmc).src/main.cpp: C++ CLI sample.python/stress_test.py: full stress-test pipeline.python/download_data.py: automatic market data downloader.python/data_pipeline.py: yfinance ingestion and regime extraction utilities.python/data_quality.py: data quality scorecard generation.python/bootstrap.py: advanced bootstrap engines and block-length estimation.python/higher_order_greeks.py: finite-difference higher-order Greek calculators.python/stat_validation.py: bootstrap statistical validation report.python/pnl_attribution.py: Greek-factor PnL explain.python/portfolio_risk.py: portfolio aggregation and VaR/CVaR computation.python/var_cvar.py: standalone VaR/CVaR estimators.python/iv_surface.py: Carr-Madan-based IV surface builder and SVI fitter.python/risk_memo.py: markdown risk memo synthesis.python/benchmark_suite.py: runtime benchmark presets.python/example_usage.py: minimal Python pricing example.data/: expected historical return inputs.
python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -r requirements.txt
cmake -S . -B build -DBUILD_PYTHON_BINDINGS=ON
cmake --build build --config ReleaseIf pybind11 CMake config is not auto-discovered, set pybind11_DIR:
$pybind = python -c "import pybind11; print(pybind11.get_cmake_dir())"
cmake -S . -B build -Dpybind11_DIR=$pybind -DBUILD_PYTHON_BINDINGS=ON
cmake --build build --config Releasepython python/make_report.py --data-dir data --out-dir output --ticker SPY --bootstrap-method stationary --price-mode adj_closeRuntime-controlled profiles:
python python/make_report.py --data-dir data --out-dir output --quality-profile fast --heartbeat-secs 10
python python/make_report.py --data-dir data --out-dir output --quality-profile balanced --heartbeat-secs 20
python python/make_report.py --data-dir data --out-dir output --quality-profile high --heartbeat-secs 20
python python/make_report.py --data-dir data --out-dir output --quality-profile extreme --heartbeat-secs 20Profiles trade runtime vs fidelity (fast < balanced < high < extreme).
make_report.py prints heartbeat progress during long steps and applies a calibration time cap for non-extreme profiles.
Fast dev/laptop run:
python python/make_report.py --data-dir data --out-dir output --fast --skip-calibration--fast uses reduced scenarios, compact stress grids, and smaller simulation settings for quick smoke runs.
Offline/local-data smoke run:
python python/make_report.py --data-dir data --out-dir output --quality-profile fast --skip-calibration --skip-download-data--skip-download-data uses existing CSV files in data/ and skips yfinance downloads.
This runs:
- C++/pybind module auto-build (if
heston_qmcis not yet available), - data download,
- Heston calibration,
- stress-test generation,
- statistical validation,
- PnL attribution,
- markdown risk memo,
- and prepares files for the notebook report.
Optional runtime benchmark suite:
python python/make_report.py --data-dir data --out-dir output --include-benchmark --fast --skip-calibration.\build\Release\heston_cli.exeEnsure the built heston_qmc module is in PYTHONPATH (or copied next to script), then:
python python/example_usage.pypython python/calibrate_heston.py --ticker SPY --risk-free-rate 0.02 --max-expiries 3 --max-strikes 8 --out-dir outputCalibration outputs:
output/heston_calibration_params.jsonoutput/heston_calibration_points.csvoutput/heston_calibration_summary.csv
- Download regime return data via yfinance:
python python/download_data.py --data-dir dataOptions:
python python/download_data.py --data-dir data --price-mode adj_close
python python/download_data.py --data-dir data --price-mode close --skip-raw-mirrordownload_data.py now writes all configured historical regimes (2008, 2011, 2020, 2022) and a quality report.
- Run stress tests (auto-download can also run inline):
python python/stress_test.py --data-dir data --out-dir output --scenarios 200 --horizon-days 10 --bootstrap-method stationary --auto-block-length --auto-download-data --price-mode adj_closeCOS-first (recommended) stress repricing is now default. To force legacy Monte Carlo repricing:
python python/stress_test.py --data-dir data --out-dir output --pricing-engine qmc --scenarios 200 --horizon-days 10 --bootstrap-method stationary --auto-block-lengthEnable Sobol QMC in direct engine calls by setting SimulationConfig.use_sobol = True.
If heston_qmc.has_cuda() is true for your build, you can call:
heston_qmc.price_option_qmc_cuda(option, model, num_paths, seed)
When CUDA is not available, CPU code paths remain fully functional.
Faster run controls:
python python/stress_test.py --data-dir data --out-dir output --scenarios 20 --horizon-days 5 --num-paths 1500 --num-steps 24 --num-batches 3 --bootstrap-method stationary --auto-block-length --auto-download-data --price-mode adj_close --fast-modeOutputs:
output/surface_gfc_2008.csvoutput/surface_covid_march_2020.csvoutput/instability_pathwise_gfc_2008.csvoutput/instability_pathwise_covid_march_2020.csvoutput/gamma_instability_gfc_2008.csvoutput/gamma_instability_covid_march_2020.csvoutput/near_expiry_scorecard_gfc_2008.csvoutput/near_expiry_scorecard_covid_march_2020.csvoutput/gamma_instability_summary.csvoutput/run_metadata.csvoutput/data_quality_report.csvoutput/statistical_validation.csvoutput/quantitative_validation.csvoutput/quantitative_validation_summary.csvoutput/pnl_attribution.csvoutput/portfolio_risk.csvoutput/portfolio_risk_summary.csvoutput/risk_memo.mdoutput/benchmark_runtime.csv(when--include-benchmarkis enabled)
python python/iv_surface.py --out-file output/iv_surface.csv --svi-file output/iv_surface_svi_params.csv --spot 100 --rate 0.02 --maturities 0.05,0.1,0.25,0.5,1.0Outputs:
output/iv_surface.csvwith(K, T) -> implied_voloutput/iv_surface_svi_params.csvwith one SVI parameter set per maturity
Open and run:
notebooks/risk_report.ipynb
The notebook builds:
- calibration diagnostics (market vs model fit),
- interactive 3D near-expiry surfaces (
Gamma,Vanna,Volga,Charm), - instability heatmaps for 2008 vs 2020 regimes.
- The stress module maps volume shocks to variance parameters (
v0,theta,sigma) to surface Greek sensitivity under volatility/flow stress. - COS stress repricing is substantially faster and deterministic for vanilla instruments; QMC remains available for pathwise/noise-aware comparisons.
- Data pipeline writes adjusted return series and optionally mirrors raw price history for auditability.
- Stationary and circular block bootstrap preserve serial dependence better than i.i.d. resampling.
- Increase
num_pathsandnum_stepsfor production-grade stability checks.
GitHub Actions workflow in .github/workflows/ci.yml runs build and tests on:
- Ubuntu with Python 3.10/3.11/3.12 matrix
- Windows with Python 3.11