Is the implied volatility surface arbitrage-free?#
Topics
SVI · SSVI · Durrleman condition · risk-neutral density · butterfly arbitrage · calendar spread
When we calibrate an implied volatility surface from market quotes, we get a smooth, good-looking surface. But does it make sense mathematically? Concretely: could a trader build a portfolio of vanilla options from this surface and lock in a guaranteed profit at zero cost? If yes, the surface is not arbitrage-free, it is internally inconsistent, regardless of how well it fits the data.
This note works through two classical notions of arbitrage on a vol surface, derives the
conditions for each, and shows how to check them on a surface calibrated with hestonpy.
Setup: total implied variance#
Let \(F_T = S_0 e^{r T}\) denote the forward price at maturity \(T\) and spot \(S_0\), and let \(k = \ln(K / F_T)\) denote the log-moneyness. Instead of working with implied volatility \(\sigma_{imp}(k,T)\) directly, it is more convenient to work with the total implied variance:
This removes the trivial \(\sqrt{T}\) scaling and makes the arbitrage conditions cleaner.
Two types of arbitrage#
Calendar spread arbitrage#
A calendar spread is a position long one call at maturity \(T_2\) and short one call at maturity \(T_1 < T_2\), at the same strike. Under any risk-neutral measure, holding an option to \(T_2\) is worth at least as much as holding it to \(T_1\) (early exercise aside), so the forward calendar spread price must be non-negative.
Translating this into the language of total variance, The total variance must be non-decreasing in maturity at every strike. Intuitively: more time means more uncertainty, so a wider distribution of terminal prices. Thus, one can show that a vol surface is free of calendar spread arbitrage if and only if, for every log-moneyness \(k\):
Butterfly arbitrage and the Durrleman condition#
A butterfly centered at strike \(K_0\) is long calls at \(K_0 - \delta\) and \(K_0 + \delta\) and short two calls at \(K_0\). Its payoff is always non-negative (it’s a tent function), so its price must be non-negative too. A violation implies a negative risk-neutral density, the model assigns negative probability to some region of the spot, which is absurd.
For a single maturity slice \(w(\cdot) = w(\cdot, T)\), define Durrleman’s function:
where primes denote derivatives with respect to \(k\). One can show that the risk-neutral density of the log-moneyness \(k\) satisfies:
Since \(e^{-d_2^2/2} / \sqrt{2\pi w} > 0\) always, the density is non-negative if and only if \(g(k) \geq 0\). Therefore:
Conditions for SVI#
The raw SVI parameterisation (Gatheral, 2004) reads:
hestonpy calibrates this with the constraint \(a + b\sigma\sqrt{1-\rho^2} \geq 0\), which
ensures the minimum total variance is non-negative. But is this sufficient for no
butterfly arbitrage?
No, in general. The constraint is necessary (negative total variance immediately implies \(g < 0\)) but not sufficient. The full butterfly-free characterisation for SVI requires checking \(g(k) \geq 0\) everywhere. However, in practice a well-calibrated SVI slice almost never violates it. The dangerous regime is when the wings are too steep (\(b\) large, \(\sigma\) small).
Necessary conditions for SVI (no butterfly)
\(b \geq 0\)
\(|\rho| < 1\)
\(a + b\sigma\sqrt{1-\rho^2} \geq 0\)
These are enforced automatically by the StochasticVolatilityInspired.calibration() method.
Checking the Durrleman condition numerically#
For an SVI slice, \(g(k)\) can be evaluated analytically by computing \(w'\) and \(w''\):
Note that \(w'' > 0\) always (SVI is convex in \(k\)), which is a good sign. We plug these into \(g(k)\) and check the sign over a grid of log-moneyness values.
import numpy as np
from hestonpy.models.calibration.svi import StochasticVolatilityInspired
# --- Calibrate SVI on a single smile ---
T = 0.5
svi = StochasticVolatilityInspired(time_to_maturity=T)
# (assume strikes, market_ivs, forward are available)
params, model_ivs = svi.calibration(strikes, market_ivs, forward)
a, b, rho, m, sigma = params["a"], params["b"], params["rho"], params["m"], params["sigma"]
# --- Durrleman condition on a fine grid ---
k_grid = np.linspace(-0.5, 0.5, 500)
sqrt_term = np.sqrt((k_grid - m)**2 + sigma**2)
w = a + b * (rho * (k_grid - m) + sqrt_term)
w_p = b * (rho + (k_grid - m) / sqrt_term)
w_pp = b * sigma**2 / sqrt_term**3
g = (1 - k_grid * w_p / (2 * w))**2 \
- (w_p**2 / 4) * (1/w + 0.25) \
+ w_pp / 2
is_butterfly_free = np.all(g >= 0)
print(f"Butterfly-free: {is_butterfly_free}")
print(f"Min g(k) = {g.min():.6f}")
Conditions for SSVI#
The SSVI parameterisation (Gatheral & Jacquier, 2014) writes the total variance surface as:
where \(\theta_T = \sigma_{ATM}(T)^2 \cdot T\) is the ATM total variance and \(\varphi_T \geq 0\) is the wing (curvature) parameter.
The strength of SSVI is that Gatheral & Jacquier derived analytical no-arbitrage conditions:
No-arbitrage theorem for SSVI (Gatheral & Jacquier, 2014)
No butterfly arbitrage iff, for every maturity \(T\):
No calendar spread arbitrage iff, for every pair of maturities \(T_1 < T_2\) and every \(k\):
In practice, since \(\theta_T = \sigma_{ATM}^2\cdot T\) is set directly from market ATM vols, calendar-spread arbitrage reduces to checking that the total ATM variance \(T \mapsto \theta_T\) is non-decreasing — which the market almost always satisfies.
In hestonpy, the calibration of each slice already enforces \(\varphi_T \leq 2/\theta_T\),
which implies \(\theta_T \varphi_T \leq 2\). Combined with \((1 + |\rho|) \leq 2\), this gives
\(\theta_T \varphi_T (1 + |\rho_T|) \leq 4\) — exactly the no-butterfly condition.
Key insight
The bound constraint phi <= 2/theta_T in the calibrate_single_maturity optimisation
is not just a numerical trick — it is a direct encoding of the no-butterfly condition
(up to the \(\rho\) factor, which is bounded by \(2\)).
Checking analytically with hestonpy#
import numpy as np
from hestonpy.models.calibration.ssvi import SurfaceStochasticVolatilityInspired
maturities = np.array([0.25, 0.5, 1.0, 2.0])
ssvi = SurfaceStochasticVolatilityInspired(maturities=maturities)
# (assume strikes, iv_surface, forwards are available)
params = ssvi.calibrate_surface(strikes, iv_surface, forwards)
print("Maturity | theta | phi | rho | theta*phi*(1+|rho|) | OK?")
print("-" * 70)
for T in maturities:
theta = ssvi.theta[T]
rho = params[T]["rho"]
phi = params[T]["phi"]
cond = theta * phi * (1 + abs(rho))
ok = "✓" if cond <= 4 else "✗ ARBITRAGE"
print(f" T={T:.2f} | {theta:.4f} | {phi:.4f} | {rho:+.4f} | {cond:.4f} | {ok}")
Calendar spread check#
# Check that total ATM variance is non-decreasing in T
thetas = np.array([ssvi.theta[T] for T in maturities])
diffs = np.diff(thetas)
if np.all(diffs >= 0):
print("✓ No calendar spread arbitrage (theta is non-decreasing)")
else:
bad = np.where(diffs < 0)[0]
for i in bad:
print(f"✗ Calendar spread arbitrage between T={maturities[i]:.2f} and T={maturities[i+1]:.2f}")
Discussion#
SVI |
SSVI |
|
|---|---|---|
Butterfly-free |
Check \(g(k) \geq 0\) numerically |
Analytical: \(\theta\varphi(1+\vert\rho\vert)\leq 4\) |
Calendar-spread-free |
Must compare slices |
\(\theta_T\) non-decreasing |
Enforced in |
Necessary conditions only |
✓ via bound on \(\varphi\) |
The practical takeaway: SSVI is strictly safer than slice-by-slice SVI for building a full surface, because its no-arbitrage conditions can be encoded as simple box constraints in the optimiser. SVI is more flexible on a single smile but offers no cross-maturity guarantee.
For a production calibration pipeline, one should:
Use SSVI (or parametric SSVI with \(\varphi(\theta) = \eta/\theta^\gamma\)) for the full surface, with the bound \(\varphi \leq 2/\theta\).
After calibration, run a quick check: compute \(g(k)\) on a fine grid for each slice.
Verify that \(T \mapsto \theta_T\) is non-decreasing.
If any check fails, tighten the optimisation constraints or review the input data for outlier quotes.
References#
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.
Gatheral, J. & Jacquier, A. (2014). Arbitrage-free SVI volatility surfaces. Quantitative Finance, 14(1), 59–71.
Durrleman, V. (2005). From implied to spot volatilities. PhD thesis, Princeton University.
Lee, R. (2004). The moment formula for implied volatility at extreme strikes. Mathematical Finance, 14(3), 469–480.