Monte Carlo Greeks for discontinuous payoffs, done correctly and benchmarked against closed-form references.
When an option's payoff is discontinuous (a digital that pays a fixed amount if
the underlying finishes above a strike, a barrier that knocks out on touch), the
textbook pathwise (infinitesimal perturbation) estimator for its sensitivities
quietly breaks: the derivative of the payoff is zero almost everywhere, so the
estimate collapses toward zero. radonlab implements the established remedies,
tests each one against a known analytic answer, and benchmarks them side by side
so you can see which method to use and what it costs.
Pure NumPy/SciPy. Apache-2.0. No copyleft dependencies.
A header-only C++20 port lives at github.com/quantsingularity/radonlab-cpp. The two libraries share the same methods and the same closed-form references, and the C++ analytics are cross-checked against this library's values (which are verified to machine precision by complex-step differentiation), so the two agree to 1e-9 across languages.
Python (radonlab) |
C++ (radonlab-cpp) |
|
|---|---|---|
| Role | Reference implementation; carries the research extensions | Header-only production port |
| Validated by | Complex-step differentiation, to machine precision | Cross-checked against this library, to 1e-9 |
| Extras | Merton jump-diffusion, path-dependent Malliavin delta | Adjoint algorithmic differentiation, exact second-order Greeks, threaded estimator |
All estimators return a value together with its per-path standard error.
| Estimator | Differentiates | Notes |
|---|---|---|
| Likelihood-ratio (LRM) | the density, never the payoff | Unbiased for digitals and other discontinuous payoffs. Covers delta, vega, gamma. |
| Smoothing | a |
A tunable bias/variance trade-off. |
| Conditional Monte Carlo | integrates out the barrier-crossing event with the Brownian-bridge non-crossing probability | Unbiased for the continuously-monitored price at any number of steps, and Lipschitz in spot, so its delta comes out by the pathwise method. |
| Pathwise / finite-difference | baselines | Kept so their failure modes on discontinuous payoffs are visible and measurable. |
Closed-form Black-Scholes analytics (the ground truth) are provided for European calls/puts, cash-or-nothing and asset-or-nothing digitals, and continuously-monitored down-and-out / down-and-in calls. Every explicit Greek formula is checked against complex-step differentiation of the price to machine precision.
pip install -e ".[benchmark,test]"| Package | Needed for |
|---|---|
numpy |
core (required) |
scipy |
core (required) |
pandas |
benchmark table |
matplotlib |
benchmark plots |
from radonlab import GeometricBrownianMotion, CashOrNothingCall, Greek
from radonlab import likelihood_ratio, pathwise, analytics
model = GeometricBrownianMotion(S0=100, r=0.03, sigma=0.20, T=1.0)
payoff = CashOrNothingCall(strike=100)
# Ground truth
ref = analytics.cash_or_nothing_call(100, 100, 0.03, 0.20, 1.0, greek="delta")
# Likelihood ratio: unbiased for the digital
lrm = likelihood_ratio(model, payoff, Greek.DELTA, n_paths=1_000_000)
print(lrm) # delta=... +/- ... [likelihood-ratio]
print(lrm.confidence_interval(0.95))
# Naive pathwise: collapses to ~0, badly biased
pw = pathwise(model, payoff, Greek.DELTA, n_paths=1_000_000)
print(pw.value, "vs analytic", ref)Under geometric Brownian motion, the terminal spot is
and a price is
| Method | Identity | Behaviour on a jump in |
|---|---|---|
| Likelihood ratio | Unbiased: |
|
| Pathwise | Degenerate: |
|
| Conditional MC (barrier) | multiplies the terminal payoff by |
Exact bridge probability of not breaching |
Writing
| Greek | Score function |
|---|---|
| Delta | |
| Vega | |
| Gamma |
Full references are in each module's docstring: Broadie and Glasserman (1996), Glasserman (2003), Reiner and Rubinstein (1991), and the smoothed-perturbation and Malliavin literature.
Reproduce with python examples/benchmark_digital_delta.py (1,000,000 paths,
seed 0). Delta of an at-the-money cash-or-nothing call,
| Method | Value | Std. error | Abs. error vs analytic | Biased? |
|---|---|---|---|---|
| Likelihood-ratio | 0.01939 | 2.84e-05 | 5.9e-05 | No |
| Smoothing (h = default) | 0.01921 | 4.56e-05 | 1.2e-04 | No |
| Finite-difference (1% bump) | 0.01934 | 9.49e-05 | 8.5e-06 | No |
| Pathwise | 0.00000 | 0.00e+00 | 1.9e-02 | Yes |
Two things to read off it. First, pathwise is 100% wrong: it returns exactly zero, because the digital's derivative is zero almost everywhere. Second, among the unbiased methods the likelihood-ratio estimator has the lowest variance (about 3.3 times smaller standard error than the 1% finite difference) and needs no bump to tune.
Finite difference forces a bad choice: sweeping the bump size in the same run shows the standard error exploding as the bump shrinks, while a large bump introduces its own bias:
| Relative bump | Value | Std. error | Abs. error |
|---|---|---|---|
| 1e-01 | 0.018620 | 2.36e-05 | 7.1e-04 (bias) |
| 1e-02 | 0.019311 | 9.49e-05 | 2.2e-05 |
| 1e-03 | 0.019161 | 3.04e-04 | 1.7e-04 |
| 1e-04 | 0.017274 | 9.15e-04 | 2.1e-03 |
The likelihood-ratio method sidesteps that trade-off entirely. This is the whole reason the library exists.
pytestThe suite validates the analytics by complex-step differentiation, confirms each Monte Carlo estimator agrees with the analytic Greek within a few standard errors, and documents the pathwise failure on digitals as an explicit test.
This release covers the Black-Scholes / GBM world and, in radonlab.merton, the
Merton jump-diffusion model with a closed-form digital reference: it shows the
likelihood-ratio delta weight is unchanged by jumps and validates the estimator
against the closed form. It is a rigorous, tested core rather than a kitchen
sink: the estimators and their validation are real, and where a method is
expected to be biased (pathwise on a digital), the library shows it rather than
hiding it. It also includes a genuinely path-dependent frontier estimator in
radonlab.asian: the likelihood-ratio / Malliavin delta of a geometric
Asian digital, validated against the closed form, with a weight built from
the whole path. Stochastic volatility, arithmetic-Asian and lookback
payoffs, and a JIT/vectorized backend are natural next steps.
Apache-2.0. See LICENSE.