A replication and extension of Vähämaa (2004) and Hull & White (2017) using recent SPY options data.
The Black-Scholes model prices options under the assumption of constant volatility, yet equity option markets display a persistent implied volatility skew. Practitioners routinely override the flat-vol assumption by computing delta at the smile-consistent implied volatility for each strike — a heuristic known as practitioner Black-Scholes delta. This project replicates the empirical hedging experiments of Vähämaa (2004) and Hull & White (2017) on SPY options to quantify the hedging P&L cost of flat-vol delta relative to two smile-aware alternatives: practitioner BS delta and smile-adjusted delta derived from the full local-volatility surface. We decompose the hedging error across moneyness buckets (deep ITM, ATM, OTM), time-to-expiration regimes (< 30 days, 30–60 days, > 60 days), and realized-volatility regimes (low / medium / high VIX terciles). The primary metric is daily delta-hedged P&L variance; a smaller variance indicates a better hedge.
How much does using flat-vol Black-Scholes delta cost a delta hedger, relative to practitioner BS delta and smile-adjusted delta, and where does the gap come from — moneyness, time to expiration, or volatility regime?
We use the continuous-dividend Black-Scholes formula (Merton 1973) for both pricing and Greek computation. The spot price of SPY serves as S, Treasury yields as r, and the SPY trailing dividend yield as q.
For each option in the cross-section, we invert Black-Scholes numerically (Brent's method) to obtain the implied volatility σ(K, T). The resulting function of strike and expiration is the implied volatility surface.
| Label | Definition |
|---|---|
| Flat-vol delta | ∂C/∂S evaluated at a single ATM implied volatility; ignores the skew entirely. |
| Practitioner BS delta | ∂C/∂S evaluated at the option's own implied volatility σ(K, T). Standard industry practice. |
| Smile-adjusted delta | ∂C/∂S + ∂C/∂σ · ∂σ/∂S, where ∂σ/∂S is the slope of the smile with respect to the underlying (the "sticky-strike" vs "sticky-delta" correction). Following Hull & White (2017). |
We fit a parametric surface to the implied volatility grid using the SVI (Stochastic Volatility Inspired) parameterization of Gatheral (2004), which is arbitrage-free by construction in the time-slice dimension. The surface provides smooth ∂σ/∂K and, combined with the chain rule, ∂σ/∂S.
For each option we construct a daily delta-hedged portfolio (short one option, long Δ shares of SPY, residual in a money-market account financed at the risk-free rate), rebalance daily, and record the per-rebalance P&L. We then compare the variance of daily hedging P&L across the three delta variants. No transaction costs or microstructure, following Vähämaa (2004).
Reproducible Monte Carlo (implemented). A full longitudinal experiment on
real chains needs daily historical option data (OptionMetrics/WRDS), which
yfinance cannot provide. So the runnable experiment in src/hedging_sim.py
simulates the underlying as GBM and gives each option a floating implied-vol
smile in log-moneyness, σ(k) = σ_atm + b·k + c·k² with b < 0 (sticky
moneyness). In this controlled world the smile-adjusted delta is the exact
total spot derivative — hence the minimum-variance hedge — so the experiment
cleanly isolates the value of each correction term. The real-data path is wired
but not executed: src.data_loader.load_historical_chains documents the WRDS
swap-in, and the analysis/plotting layers run unchanged on either P&L source.
Hedging error variance is regressed on indicator variables for moneyness quintile, DTE bucket, and VIX tercile, following the decomposition framework in Hull & White (2017) Section 4.
Current implementation: CBOE-listed SPY options sourced via yfinance
(point-in-time snapshot, no historical chains). This is sufficient for
surface-fitting and methodology validation but not for the full longitudinal
hedging experiment.
Target dataset: OptionMetrics (via WRDS) or ORATS, covering 2018–2024 to
span multiple vol regimes. See src/data_loader.py for the swap-in TODO.
Filters applied:
- Volume ≥ 10 contracts per day
- Bid-ask spread ≤ 10% of mid-price
- 7 ≤ DTE ≤ 180
- Strike within ±30% of spot (log-moneyness |ln(K/S)| ≤ 0.30)
.
├── src/
│ ├── greeks.py # Black-Scholes pricing and Greeks
│ ├── iv_solver.py # Implied volatility inversion
│ ├── surface.py # Volatility surface fitting (SVI / splines)
│ ├── hedging_sim.py # Daily delta-hedge simulation
│ ├── data_loader.py # Data ingestion and cleaning
│ ├── analysis.py # Decomposition regressions and summary stats
│ └── plots.py # Publication-quality figures
├── notebooks/
│ ├── 01_explore_data.ipynb # Data pull + IV smile smoke test
│ ├── 02_build_surface.ipynb # Surface fitting and diagnostics
│ ├── 03_run_hedging.ipynb # Monte Carlo hedging experiment
│ └── 04_results.ipynb # Decomposition, significance, final figures
├── tests/
│ └── test_greeks.py # Unit tests for pricing and IV inversion
├── data/
│ ├── raw/ # Parquet snapshots from data_loader (gitignored)
│ └── processed/ # Cleaned option chains (gitignored)
└── results/
├── figures/ # PNG / PDF outputs
└── tables/ # CSV / LaTeX tables
pip install -r requirements.txt
pytest tests/ # 87 tests, all green
# Reproducible hedging experiment (no market data needed):
python -c "from src.hedging_sim import run_experiment; \
s, _ = run_experiment(); \
print(s.groupby('method')['var_pnl'].mean())"
# Or run the notebooks end-to-end (writes results/figures and results/tables):
jupyter notebook notebooks/03_run_hedging.ipynb # hedging experiment
jupyter notebook notebooks/04_results.ipynb # decomposition + figuresNotebooks 03–04 are generated from notebooks/_build_notebooks.py and can be
re-rendered headless with
python -m nbconvert --to notebook --execute --inplace notebooks/0[34]_*.ipynb.
On the reproducible floating-smile Monte Carlo (4,000 paths per cell across three vol regimes × three maturities × five strikes; daily rebalancing):
| Delta variant | Mean daily P&L variance | Reduction vs flat-vol |
|---|---|---|
| Flat-vol delta | 0.00509 | — (baseline) |
| Practitioner delta | 0.00555 | −8.8% (worse) |
| Smile-adjusted delta | 0.00455 | +10.8% |
The smile-adjusted delta is the minimum-variance hedge. The reduction is highly significant (Levene test p ≪ 0.01; bootstrap 95% CI on the variance reduction excludes zero). Two findings worth flagging:
- Practitioner delta alone does not beat the naive flat-vol hedge in this world. Marking the option at its own implied vol captures the level of the smile but not its spot dynamics; it is the vega·∂σ/∂S correction — not the smile level — that reduces variance. This is the central message of Hull & White (2017).
- Hedging risk is dominated by the volatility regime, then moneyness (per the OLS decomposition in Notebook 04), and the smile-adjusted advantage grows with rebalancing frequency, converging to a perfect hedge as the total-derivative argument predicts.
Figures (results/figures/) and tables (results/tables/) are regenerated by
the notebooks and are gitignored.
Black, F., & Scholes, M. (1973). The pricing of options and corporate liabilities. Journal of Political Economy, 81(3), 637–654.
Derman, E., & Kani, I. (1994). Riding on a smile. Risk, 7(2), 32–39.
Dumas, B., Fleming, J., & Whaley, R. E. (1998). Implied volatility functions: Empirical tests. Journal of Finance, 53(6), 2059–2106.
Gatheral, J. (2004). A parsimonious arbitrage-free implied volatility parameterization with application to the valuation of volatility derivatives. Presentation at Global Derivatives & Risk Management, Madrid.
Hull, J., & White, A. (2017). Optimal delta hedging for options. Journal of Banking & Finance, 82, 180–190.
Merton, R. C. (1973). Theory of rational option pricing. Bell Journal of Economics and Management Science, 4(1), 141–183.
Vähämaa, S. (2004). Delta hedging with the smile. Financial Markets and Portfolio Management, 18(3), 241–255.