3Y3C Option Lab Pricing · Volatility · Trading Engineering
option.3y3c.club
02

Fitting the Volatility Curve: SVI, Splines, and No-Arbitrage

1. Why volatility is a curve

The previous note established that of BSM’s five inputs, the only invisible one is volatility $\sigma$. The market quotes in reverse — each listed option, at each strike and expiry, backs out its own implied volatility. If BSM’s assumptions held exactly, all these IVs would be a single number. Plot IV against strike for a fixed expiry and reality looks like:

The causes are fat tails in the return distribution, the negative price–volatility correlation (leverage effect), and the plainest supply-and-demand fact: everyone wants crash insurance.

The problem thus becomes: given a sparse, noisy set of $(K_i, \mathrm{IV}_i)$ quotes, fit a smooth curve defined on the whole strike axis that also survives scrutiny. That is volatility curve fitting.

2. Three hard constraints on any fit

  1. Fit the data: keep the weighted sum of squared residuals small — weights usually proportional to vega or to the inverse bid–ask spread.
  2. Smoothness: the curve must be differentiable, because every Greek and every local volatility is a derivative of it.
  3. No arbitrage — the lifeline, with two clauses:
    • Butterfly: for a fixed expiry, call prices as a function of strike must satisfy $\partial^2 C/\partial K^2 \geq 0$ (equivalently, a non-negative risk-neutral density). Violate it and the market offers a free lunch of buying and selling the same risk at different prices.
    • Calendar: if $T_1 < T_2$ then total variance $W(T_2,k) \geq W(T_1,k)$.

A standard trick: fit total variance $W(k) = \sigma^2(k),T$ rather than IV, where $k = \ln(K/F)$ is log-moneyness and $F$ is the forward. Only in total-variance terms does the calendar condition take a clean form.

3. Lee’s moments: the grammar of the wings

As strikes run to infinity, implied volatility cannot do as it pleases. Lee (2004) proved that as $|k| \to \infty$, total variance must grow linearly, with asymptotic slopes inside a determined band. In plain words:

The wings of the smile may only rise roughly linearly, with bounded slopes — no exponential blow-up, no flattening into negative slopes.

This boundary is the ceiling on extrapolation for every fitting method. Spline-type methods die here most often: the data cover only the middle segment, the wings are extrapolated, and one careless step breaks the no-arbitrage boundary — or swings wildly with a day’s quotes, leaving the Greeks of deep-OTM options unrecognizable.

4. Method 1: splines / interpolation

Idea: fit a cubic spline to $W(k)$ (or IV) with knots at the quotes.

Suitable for quick internal interpolation (valuing between existing quotes); not suitable as the full curve you quote externally.

5. Method 2: SVI — the de facto industry standard

Stochastic Volatility Inspired (Gatheral, 2004). Parameterize total variance:

$$W(k) = a + b\left[\rho,(k - m) + \sqrt{(k-m)^2 + \sigma^2}\right]$$

The five parameters each have a clean geometric meaning:

ParameterMeaningHow to guess an initial value
$a$Overall level of total varianceATM total variance minus half the tilt contribution
$b \geq 0$Tilt magnitude (how wide the smile opens)Half the sum of the two wing slopes
$\rho \in (-1,1)$Tilt direction (negative = left-high skew)From the difference/sum of wing slopes
$m$Horizontal shift of the smile centerThe ATM $k$ (near 0)
$\sigma > 0$Roundedness near the ATM pointInverted from local curvature at ATM

Sufficient conditions for no-arbitrage (Gatheral–Jacquier, 2014) reduce to simple constraints on the parameters:

$$0 \leq b \leq \frac{4}{T}, \qquad |\rho| < 1, \qquad a \geq -b,\sigma\sqrt{1-\rho^2}, \qquad \sigma > 0$$

The beauty of this set: “the whole curve is arbitrage-free” collapses into box constraints on five scalars — hand them straight to a constrained solver.

SVI also ships with the jump-wing parameterization: re-express in market language — ATM total variance $\nu$, left/right asymptotic slopes, ATM skew — convenient for time-series smoothing of parameters across expiries.

6. Method 3: SABR

The king of interest-rate markets (Hagan et al., 2002). The model is stochastic volatility: the volatility itself has a volatility (vol-of-vol $\nu$), correlated with the underlying via $\rho$, with CEV elasticity $\beta$ controlling smile symmetry. The IV approximation is explicit, and the four parameters $(\alpha, \beta, \nu, \rho)$ map directly onto shape language.

Two cautions: in low-rate environments the Hagan approximation can introduce arbitrage (arbitrage-free SABR is the patched version); and equity markets generally favor SVI, while rates (especially caps/swaptions) default to SABR.

7. A production pipeline (SVI example)

1. Clean      Drop: no two-sided quotes, time-to-expiry < 3–5 trading days,
              |k| outside the data band, outliers far from neighbors
2. Transform  F = S·e^{rT} (or the futures price directly), k = ln(K/F), W = IV²·T
3. Weights    w_i ∝ Vega(K_i) or 1/(ask−bid)
4. Objective  min Σ w_i · [W(k_i; θ) − W_i]²
5. Constraints Gatheral–Jacquier domain (the box constraints above)
6. Initial    values by the geometric guesses in the table; ρ = −0.3, σ = 0.1
              are robust starting points
7. Verify     pointwise butterfly (∂²C/∂K² > 0, finite differences) + calendar
              against neighboring expiries
8. Smooth     parameters across expiries and across days to avoid jumpy Greeks

A minimal working skeleton:

import numpy as np
from scipy.optimize import minimize

def svi_w(k, a, b, rho, m, sig):
    """Total variance W(k)."""
    return a + b * (rho * (k - m) + np.sqrt((k - m)**2 + sig**2))

def fit_svi(k, iv, T, w=None):
    W = iv**2 * T                      # work in total variance
    if w is None:
        w = np.ones_like(W)
    def obj(p):                        # weighted sum of squared residuals
        return np.sum(w * (svi_w(k, *p) - W)**2)
    cons = [                            # Gatheral–Jacquier box constraints
        dict(type='ineq', fun=lambda p: p[1]),              # b >= 0
        dict(type='ineq', fun=lambda p: 4/T - p[1]),        # b <= 4/T
        dict(type='ineq', fun=lambda p: 1 - abs(p[2])),     # |rho| < 1
        dict(type='ineq', fun=lambda p: p[4]),              # sig > 0
        dict(type='ineq', fun=lambda p: p[0] + p[1]*p[4]),  # a + b·sig >= 0 (simplified)
    ]
    x0 = [np.median(W), 0.1, -0.3, 0.0, 0.1]   # geometric initial guess
    return minimize(obj, x0, constraints=cons, method='SLSQP').x

# After fitting, always check d²C/dK² > 0 pointwise (butterfly no-arbitrage)

8. Common pitfalls

9. Summary

When fitting a volatility curve, “does it look like the data” is secondary; “is it arbitrage-free, and is it stable” is the lifeline — only a curve that breathes without crossing the boundaries can carry portfolio pricing, hedging, and risk. SVI, with five parameters and one box of constraints, hits the engineering sweet spot.

The next note: once single curves are assembled into a full surface, how to price and hedge options at arbitrary strikes and dates.

Written by Ezra Options trader and systems builder since 2008 — Korea, Japan, Taiwan, Hong Kong, and mainland China. About the author →