SVI¶
This guide shows how to calibrate and use analytic SVI smiles.
In this library, SVI is used in raw parameterization:
abrhomsigma
and models total variance as a function of log-moneyness.
The coordinate system¶
SVI works with:
- log-moneyness
y = ln(K / F(T)) - total variance
w = T * iv^2
If your market data starts as (T, K, iv), you usually convert each expiry slice into y and w first.
Evaluate the raw SVI formula directly¶
import numpy as np
from option_pricing.vol.svi import SVIParams, svi_total_variance
params = SVIParams(a=0.02, b=0.50, rho=-0.20, m=0.10, sigma=0.30)
y = np.linspace(-1.0, 1.0, 51)
w = svi_total_variance(y, params)
Calibrate a single SVI slice¶
import numpy as np
from option_pricing.vol.svi import DomainCheckConfig, calibrate_svi
y = np.linspace(-0.8, 0.8, 41)
w_obs = 0.04 + 0.18 * np.sqrt((y + 0.05) ** 2 + 0.08**2) - 0.02 * (y + 0.05)
fit = calibrate_svi(
y=y,
w_obs=w_obs,
loss="linear",
domain_check=DomainCheckConfig(
mode="fixed_logmoneyness",
y_min=-1.0,
y_max=1.0,
n_grid=101,
),
)
print(fit.params)
print(fit.diag.ok)
print(fit.diag.summary)
The return value is SVIFitResult with:
params: calibratedSVIParamsdiag: rich fit diagnostics
Wrap calibrated parameters as a smile object¶
from option_pricing.vol.svi import SVISmile
smile = SVISmile(T=1.0, params=fit.params)
print(smile.iv_at(0.0))
print(smile.dw_dy(0.0))
print(smile.d2w_dy2(0.0))
Those derivative methods are one reason SVI is useful as an intermediate representation for local-vol work.
Diagnostics you will usually inspect¶
checks = fit.diag.checks
print(checks.rmse_unw)
print(checks.butterfly_ok)
print(checks.min_g)
print(checks.sL, checks.sR)
Common signals:
fit.diag.okis the top-level pass/fail summarychecks.butterfly_oktells you whether the slice passed the butterfly testchecks.rmse_unwgives you an unweighted fit error summarychecks.sLandchecks.sRare the fitted wing slopes
Build a whole SVI surface from quotes¶
If you already have (T, K, iv) market quotes, the easiest route is usually:
surface_svi = VolSurface.from_svi(rows, forward=forward)
That calibrates a slice per expiry and stores the result as analytic SVI smiles.
Repair during calibration¶
If you want the calibration routine to repair butterfly-arbitrage violations automatically, pass repair options directly into calibrate_svi(...) or VolSurface.from_svi(...):
fit = calibrate_svi(
y=y,
w_obs=w_obs,
repair_butterfly=True,
repair_method="line_search",
butterfly_min_g_tol=None,
butterfly_min_g_tol_scale=1.0,
)
When butterfly_min_g_tol is None, the effective tolerance becomes
\(-k * \max(10^{-6}, \mathrm{median}(|w_{obs}|))\) with \(k = \texttt{butterfly_min_g_tol_scale}\).
The repair workflow is described in SVI repair.