Skip to content

Commit d4fc399

Browse files
authored
Merge pull request #69 from tyrneh/svi_slice
refactored 'iv smoothing' into 'surface fitting', added SVI
2 parents 8aaa16a + a576c33 commit d4fc399

16 files changed

Lines changed: 1357 additions & 390 deletions

TECHNICAL_README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,15 @@ ModelParams(
7373
pricing_engine = "black76" | "bs", # default forward-based Black-76. Use Black-Scholes only when puts data are unavailable
7474
price_method = "last" | "mid", # defaults to 'mid'; mid-price calculated as `(bid + ask) / 2`
7575
max_staleness_days = 3, # filter options older than N calendar days from valuation_date. Defaults to 3 to accomodate weekends. Set to None to disable filtering
76+
surface_method = "svi", # "svi" (default) or "bspline"
77+
surface_options = {"max_iter": 400}, # optional dict of method-specific kwargs
7678
)
7779
```
7880

7981
Note that mid prices are preferred over last, due to lower noise from stale quotes. However, Yahoo Finance often doesn't have bid/ask data, so the from_ticker() method for yfinance uses last prices by default.
8082

83+
`surface_method` selects between the arbitrage-aware SVI fitter and the legacy cubic B-spline smoother. Supply `surface_options` as a plain dictionary (for example via `oipd.core.svi.svi_options(max_iter=800, tol=1e-9)`) to override calibration defaults. If calibration fails (e.g., too few strikes or a hard butterfly violation) the code raises `CalculationError("Failed to smooth implied volatility data: ...")`. In those cases either clean the input quotes or retry with the legacy cubic spline via `ModelParams(surface_method="bspline")`.
84+
8185
### 2.4 RND estimator
8286

8387
Main class that fits risk-neutral density models from options data and provides probability distribution results.
@@ -152,7 +156,7 @@ The process of generating the PDFs and CDFs is as follows:
152156
2. Apply put–call parity preprocessing: estimate the forward from near‑ATM call–put pairs
153157
3. Based on the forward price, restrict to OTM options. Keep calls above the forward and replace in‑the‑money calls with synthetic calls constructed from OTM puts via parity, to reduce noise from illiquid ITM quotes[^2].
154158
4. Using the chosen pricing model (Black‑76 as it works with forward prices[^3]) we convert strike prices into implied volatilities (IV)[^4]. IV are solved using either Newton's Method or Brent's root‑finding algorithm, as specified by the `solver_method` argument
155-
5. Using B‑spline, we fit a curve‑of‑best‑fit onto the resulting IVs over the full range of strike prices[^5]. Thus, we have extracted a continuous model from discrete IV observations — this is called the volatility smile
159+
5. Fit the implied-volatility smile using the configured surface model. By default we calibrate a raw SVI slice. During optimisation we constrain the raw parameters (`b ≥ 0`, `|ρ| ≤ ρ_bound < 1`, `σ ≥ σ_min`) and enforce the Gatheral–Jacquier minimum-variance condition `a + b σ √(1 − ρ²) ≥ 0`. After calibration we evaluate the butterfly diagnostic `g(k)` on an extended log-moneyness grid; if `min_g < 0` a `CalculationError` is raised. Users can opt into the historical cubic B-spline smoother with `surface_method="bspline"`.
156160
6. From the volatility smile, we use the same pricing model to convert IVs back to prices. Thus, we arrive at a continuous curve of options prices along the full range of strike prices
157161
7. From the continuous price curve, we use numerical differentiation to get the first derivative of prices. Then we numerically differentiate again to get the second derivative of prices. The second derivative of prices multiplied by a discount factor $\exp^{r*\uptau}$, results in the probability density function [^6]
158162
8. Once we have the PDF, we can calculate the CDF
@@ -161,7 +165,7 @@ The process of generating the PDFs and CDFs is as follows:
161165
[^2]: Parity-based OTM‑only preprocessing follows Aït‑Sahalia and Lo, ["Nonparametric Estimation of State‑Price Densities Implicit in Financial Asset Prices"](https://www.princeton.edu/~yacine/aslo.pdf)
162166
[^3]: Derivation of Black-76 is explained well by [this article](https://benjaminwhiteside.com/2021/01/15/black-76/)
163167
[^4]: We convert from price-space to IV-space, and then back to price-space in step 6. See this [blog post](https://reasonabledeviations.com/2020/10/10/option-implied-pdfs-2/) for a breakdown of why we do this double conversion
164-
[^5]: See [this paper](https://edoc.hu-berlin.de/bitstream/handle/18452/14708/zeng.pdf?sequence=1&isAllowed=y) for more details. In summary, options markets contains noise. Therefore, generating a volatility smile through simple interpolation will result in a noisy smile function. Then converting back to price-space will result in a noisy price curve. And finally when we numerically twice differentiate the price curve, noise will be amplified and the resulting PDF will be meaningless. Thus, we need either a parametric or non-parametric model to try to extract the true relationship between IV and strike price from the noisy observations. The paper suggests a 3rd order B-spline as a possible model choice
168+
[^5]: Options markets contain noise. Simple interpolation would yield erratic smiles, which in turn produce unstable price curves and PDFs. We therefore fit a model to the smile: by default the raw SVI parametrisation of Gatheral & Jacquier (see ["Arbitrage-Free SVI Volatility Surfaces"](https://arxiv.org/abs/1204.0646)), with a legacy cubic B-spline fallback available for diagnostics. The original B-spline motivation is discussed in [Zeng (2014)](https://edoc.hu-berlin.de/bitstream/handle/18452/14708/zeng.pdf?sequence=1&isAllowed=y)
165169
[^6]: For a proof of this derivation, see this [blog post](https://reasonabledeviations.com/2020/10/10/option-implied-pdfs-2/)
166170

167171
---

0 commit comments

Comments
 (0)