A Python and experimental C++20 toolkit for comparing closed-form, lattice, Monte Carlo, and stochastic-volatility pricing methods.
The repository is organized around method selection and numerical validation: Black-Scholes provides a reference where its assumptions apply, binomial trees extend the exercise treatment, and simulation supports path-dependent payoffs. An interactive Streamlit app exposes the verified Python layer and, when locally built, the broader C++ engine.
This is the broad numerical-derivatives project in the portfolio. The separate Differential ML Option Pricer focuses specifically on a neural surrogate trained with price and Greek labels.
| Method | Instruments / purpose | Interface |
|---|---|---|
| Black-Scholes | No-dividend European calls and puts; analytic Greeks | Python and C++ |
| CRR binomial tree | European or American vanilla calls and puts | Python |
| Monte Carlo | European and discrete arithmetic-average Asian payoffs | Python |
| Discrete barrier Monte Carlo | Up/down, knock-in/knock-out calls and puts | Python |
| Variance-reduced Monte Carlo | European, Asian, and barrier payoffs | C++ |
| Heston characteristic function and COS pricing | Experimental stochastic-volatility pricing | C++ |
| SVI and Heston calibration routines | Experimental synthetic calibration exercises | C++ |
| Pathwise / likelihood-ratio Greeks | Experimental Monte Carlo sensitivities | C++ |
The Python dashboard works without compiling C++. Advanced tabs clearly require the optional C++ extension.
- Black-Scholes is the reference for European options under constant volatility, continuous trading, lognormal dynamics, and no dividends.
- Binomial trees are useful when early exercise matters or a discrete lattice is easier to inspect. European tree values can be checked against Black-Scholes.
- Monte Carlo is useful for path-dependent payoffs and produces sampling uncertainty that should be reported with the estimate.
- Barrier simulation in the Python layer uses discrete monitoring. It will not reproduce continuously monitored barrier prices.
- Heston/COS and calibration are research implementations in the optional C++ layer, not calibrated trading or risk systems.
Python 3.10-3.12 is checked in CI.
python -m venv .venv
# Activate .venv using your shell's activation command.
python -m pip install -r requirements.txt
streamlit run streamlit_app.pyProgrammatic comparison:
from binomial_tree import binomial_tree_option
from black_scholes import black_scholes_price
from monte_carlo import monte_carlo_option_price
inputs = dict(S=100, K=100, T=1.0, r=0.05, sigma=0.20)
closed_form = black_scholes_price(**inputs, option_type="call")
lattice = binomial_tree_option(**inputs, N=500, option_type="call")
simulation, confidence_interval = monte_carlo_option_price(
**inputs,
simulations=100_000,
option_type="call",
)The Monte Carlo default seed is fixed for reproducible examples. Supply a NumPy
Generator through rng to control independent experiments.
For a no-dividend European call:
d1 = [ln(S/K) + (r + 0.5 sigma^2)T] / (sigma sqrt(T))
d2 = d1 - sigma sqrt(T)
C = S N(d1) - K exp(-rT) N(d2)
Rates and volatilities are annualized decimals and maturity is measured in years. Python theta is annual time decay. Vega and rho are reported per 1.00 change in volatility and rate, respectively; divide by 100 for a one-percentage-point move.
The CRR tree checks that its risk-neutral probability lies in [0, 1].
Antithetic Monte Carlo confidence intervals use paired-payoff averages so the
reported standard error reflects dependence within each pair.
python -m pip install -r requirements-dev.txt
python -m ruff check *.py tests
python -m ruff format --check *.py tests
python -m pytest -qDeterministic Python tests cover put-call parity, finite-difference delta, binomial convergence, the American put inequality, seeded Monte Carlo, barrier in/out reconciliation on identical paths, wrapper seed propagation, and invalid inputs.
The C++20 code, pybind11 bindings, Catch2 tests, and build details live under
quantlib/.
cmake -S quantlib -B quantlib/build -DCMAKE_BUILD_TYPE=Release
cmake --build quantlib/build --config Release
ctest --test-dir quantlib/build -C Release --output-on-failureCMake fetches pybind11 and Catch2 if they are not installed. A C++20 compiler and, by default, OpenMP are required. Disable optional components with the documented CMake flags if a smaller build is needed.
streamlit_app.py
-> quant_wrapper.py
-> verified Python reference modules
-> optional quantcpp_py binding
-> quantlib/include/quant public interfaces
-> quantlib/src numerical implementations
The wrapper provides one dashboard-facing interface and reports whether the extension is available. The Python numerical modules do not import Streamlit.
black_scholes.py closed-form prices and Greeks
binomial_tree.py CRR European/American lattice
monte_carlo.py European/Asian simulation and GBM paths
barrier_option.py discrete barrier simulation
quant_wrapper.py Python/C++ interface selection
streamlit_app.py interactive comparison dashboard
tests/ Python numerical sanity checks
quantlib/ optional C++20 engine, bindings, and Catch2 tests
- Models assume idealized frictionless markets; dividends, funding spreads, transaction costs, discrete hedging, and counterparty risk are omitted.
- The Python Asian pricer uses a discrete arithmetic average and no control variate.
- The Python barrier pricer monitors only simulated dates and does not apply a Brownian-bridge correction.
- Monte Carlo confidence intervals quantify sampling error, not model or parameter uncertainty.
- C++ Heston, COS, SVI, calibration, and Greek components are experimental and have not been validated against market data or an independent production library.
- The repository contains no supported cross-language performance benchmark, so no speedup claim is made.
MIT licensed. This software is for education and numerical-method comparison. It is not investment advice and must not be used as an independent source of trading, valuation, or risk numbers.