Rough Heston
Vol Surface Lab
Calibrate a full implied volatility surface from live SPY options in seconds. Price derivatives and hedge Greeks β all running in Rust.
Request Early AccessBeyond Black-Scholes β capturing the true roughness of volatility
Classical Heston assumes volatility follows a standard SDE. Empirical evidence (Gatheral et al., 2018) shows SPX volatility is rough β its realised sample paths have Hurst exponent $H \approx 0.1$, much less than Brownian motion's $H = 0.5$.
The Rough Heston model drives variance $V_t$ by a fractional Brownian motion $W^H$:
where $\alpha = H + \tfrac{1}{2} \in (0.5, 1)$ is the roughness index. Key consequence: the ATM implied vol scales as a power law:
Calibrated on live SPY data: $H = 0.19$, $\nu = 0.36$, $\rho = -0.60$. The calibration takes <100ms via fractional Riccati numerical integration.
The variance swap and leverage swap rates are available analytically via the characteristic function:
Live SPY calibration (March 2026):
| Expiry Ο (yr) | ATMIV | Var Swap | Lev Swap | Skew |
|---|---|---|---|---|
| 0.003 | 12.3% | 0.000056 | β0.000012 | β0.0034 |
| 0.005 | 14.0% | 0.000113 | β0.000024 | β0.0052 |
| 0.008 | 15.2% | 0.000169 | β0.000036 | β0.0076 |
| 0.011 | 15.9% | 0.000226 | β0.000049 | β0.0098 |
| 0.083 (1m) | 23.4% | 0.000612 | β0.000134 | β0.0211 |
3-D smile across strikes Γ maturities β RH Hurst scaling extrapolated from live data
Calibrate, price, and hedge β live SPY data in under 2 minutes
# advanced_portfolio_optimization.ipynb β Options / Derivatives section
from python.data.fetchers.options_fetcher import (
RoughHestonPricer, RoughHestonParams, RoughHestonCharFunc,
atm_skew, skew_stickiness_ratio, fetch_options_full
)
# ββ 1. Fetch live SPY options ββββββββββββββββββββββββββββββββββββββββββββββ
spy_opts = fetch_options_full('SPY', n_expiries=4)
spot = spy_opts['spot'] # β $560
# ββ 2. Calibrate H from ATM IV term structure ββββββββββββββββββββββββββββββ
taus = np.array([spy_opts['expiry_taus'][e] for e in spy_opts['expiry_dates']])
ivs = np.array([spy_opts['atm_iv'][e] for e in spy_opts['expiry_dates']])
H = np.polyfit(np.log(taus), np.log(ivs), 1)[0] # = 0.19
params = RoughHestonParams(H=H, nu=0.36, rho=-0.60, lambda_=0.0,
theta=float(np.mean(ivs)**2), v0=float(np.mean(ivs)**2))
cf = RoughHestonCharFunc(params)
# ββ 3. Price a 1-month ATM put β analytically fast via characteristic function
pricer = RoughHestonPricer(params)
K_put = spot * 0.98 # 2% OTM protective put
put_price = pricer.price_single(spot, K_put, 1/12, 'put')
print(ff"Put price: ${put_price:.4f} ({put_price/spot*100:.2f}% of spot)")
# ββ 4. Compute variance and leverage swap rates ββββββββββββββββββββββββββββ
for tau in [1/52, 1/12, 3/12]:
vs = cf.variance_swap(tau)
sk = atm_skew(cf, tau)
ssr = skew_stickiness_ratio(cf, tau)
print(ff"Ο={tau:.3f}yr VarSwap={vs:.6f} ATMSkew={sk:.4f} SSR={ssr:.3f}")
5 strategies Β· 5% AUM / monthly roll Β· analytical BS pricing with RH smile vol
π§ Key Insights
- β¦ The HMM Regime Selector rotates between Bull Spreads, Iron Condors, and Bear Spreads based on the real-time regime state β achieving the best risk-adjusted return.
- β¦ Iron Condors excel in Sideways regime (44% of 2024-2026 sample), harvesting theta with low directional risk.
- β¦ Variance Swap short profits from the variance risk premium β implied vol persistently exceeds realised vol by ~2-4 vol-points.
- β¦ All strategies use only 5% AUM. With a 25% allocation the Regime Selector P&L scales linearly, reaching ~SR=2.5+.
- [1] Gatheral, Jaisson & Rosenbaum (2018) β Volatility is rough. Quantitative Finance 18(6).
- [2] El Euch & Rosenbaum (2019) β The characteristic function of rough Heston models. Mathematical Finance 29(1).
- [3] Carr & Madan (1999) β Option valuation using the fast Fourier transform. Journal of Computational Finance 2(4).
- [4] Heston (1993) β A closed-form solution for options with stochastic volatility. Review of Financial Studies 6(2).
- [5] Fukasawa (2021) β Volatility has to be rough. Quantitative Finance 21(1).