LC StudioDissertation (PDF)

A sequential walkthrough of an options-pricing pipeline: from a raw option chain to forward recovery, implied vol, an SVI smile per expiry, static arbitrage guardrails, a global SSVI surface, and a Dupire local-vol surface — each stage computed live in the browser from the same bundled sample chain.

54 clean quotes3 expiriesNelder–Mead
01 / 08

Forward & discount via put–call parity

C − P = DF·(F − K)

lib/forward.ts → recoverForward()

Pairs each expiry's call and put quotes at matching strikes and regresses (C − P) against strike; the slope recovers the discount factor DF and the intercept recovers the forward F, in one weighted least-squares pass. The forward isn't assumed from spot and a rate — it's observed directly from market prices via put–call parity.

Assumptions / limitations — European-style, cash-settled options with matched call/put strikes; dividends and financing costs are absorbed into the implied (F, DF) pair rather than modelled separately.

02 / 08

Black-76 & implied vol (Newton)

C = DF·[F·N(d₁) − K·N(d₂)]

lib/bs.ts → black76Call(); lib/impliedVol.ts → impliedVol()

Every OTM quote is priced under Black-76 (lognormal forward, so no separate drift assumption is needed once F and DF are known), then inverted for the implied volatility that reproduces its market mid, using Newton's method seeded from a Brenner–Subrahmanyam ATM estimate, falling back to bisection if Newton stalls or vega is too small.

Assumptions / limitations — Black-76 is used purely as an inversion device, not a claim of constant vol; prices outside the model's no-arbitrage bounds are rejected rather than forced to a volatility.

03 / 08

Coordinates

k = ln(K/F), w = σ²τ

lib/volSurface.ts → impliedVolPoints()

Converts each expiry's (strike, implied vol) pairs into the coordinates the rest of the pipeline fits in: log-moneyness k, which normalises strikes across expiries and spot levels, and total variance w = σ²τ, the additive quantity across time that SVI and SSVI are parameterised in.

Assumptions / limitations — Only the OTM leg (calls above the forward, puts below) is used per strike, since OTM quotes carry the least discretisation/pinning noise; wide or crossed quotes were already dropped upstream during cleaning.

04 / 08

SVI slice fit

w(k) = a + b[ρ(k−m) + √((k−m)² + σ²)]

lib/svi.ts → fitSVISlice()

Fits the five-parameter raw SVI curve to one expiry's (k, w) points at a time by weighted least squares (Nelder–Mead over an unconstrained reparameterisation, with random restarts), giving a smooth, closed-form smile with analytic derivatives that the arbitrage checks and Dupire formula later depend on.

Assumptions / limitations — A per-expiry fit only constrains that one slice — nothing stops adjacent expiries from crossing in time until the calendar check (or the global SSVI fit) is applied.

a = 0.01551b = 0.02418ρ = -0.58419m = 0.06748σ = 0.00364rmse 1.044e-39 points
05 / 08

Butterfly & implied density

g(k) = (1 − kw′/2w)² − (w′²/4)(1/w + 1/4) + w″/2, p(k) = g/√(2πw)·e^(−d₋²/2)

lib/arbitrage.ts → butterflyG(), riskNeutralDensity()

g(k) is the Gatheral–Jacquier butterfly-arbitrage indicator, built from the SVI slice's analytic first and second derivatives; g(k) < 0 anywhere implies a negative implied density there — a butterfly-spread arbitrage. p(k) is that implied risk-neutral density itself.

Assumptions / limitations — Evaluated on the strikes actually spanned by the fit — extrapolating g(k) or p(k) far outside the calibrated k-range isn't a claim the fit is making.

showing 2026-08-21
butterfly okmin g(k) = 6.458e-1
06 / 08

Calendar / no-crossing

∂w/∂τ ≥ 0

lib/arbitrage.ts → checkCalendar()

Total variance must be non-decreasing in time at fixed log-moneyness, or a shorter-dated option would be arbitrageable against a longer-dated one at the same strike. checkCalendar scans every pair of adjacent-tau slices across a shared k-grid and flags any point where a longer expiry's w dips below a shorter one's.

Assumptions / limitations — Checked over each pair's shared, data-supported k-range for independent per-expiry slices, since raw extrapolation there isn't trustworthy; the global SSVI surface instead satisfies this by construction via its penalised fit.

no crossings detected
07 / 08

SSVI global surface

w(k,θ) = (θ/2){1 + ρφk + √((φk+ρ)² + (1−ρ²))}, φ(θ) = ηθ^(−γ)

lib/ssvi.ts → fitSSVI()

Instead of one SVI curve per expiry, SSVI fits a single global (ρ, η, γ) across every expiry's points at once, driven by the ATM total-variance term structure θ(τ) built from the per-slice fits. The no-butterfly-arbitrage bound θ·φ(θ)·(1+|ρ|) < 4 is penalised directly inside the fit, so the surface is arbitrage-free by construction rather than by checking after the fact.

Assumptions / limitations — One skew/curvature shape is shared across the whole surface; if the true smile shape changes materially by tenor, a single (ρ, η, γ) fits some expiries less tightly than an independent per-slice SVI would.

ρ = -0.3202η = 0.5702γ = 0.5000rmse 1.274e-3converged
butterfly ok (all expiries)worst min g(k) = 3.226e-1calendar ok

Per-expiry: independent SVI vs. SSVI slice

08 / 08

Dupire local vol

σ_loc²(k,τ) = (∂w/∂τ) / g(k)

lib/dupire.ts → localVolSurface()

Dupire's formula recovers the instantaneous local volatility consistent with the entire fitted implied-vol surface, expressed here in (k, τ) coordinates via the same pieces used above: ∂w/∂τ by finite differences along θ(τ), and g(k) analytically from the SSVI-equivalent slice at that τ.

Assumptions / limitations — Local vol reproduces every vanilla price the surface implies, but it flattens the forward smile going forward in time — it is not the same object as the market's future implied-vol smile — and is only reliable strictly inside the calibrated tau range, since θ(τ) is clamped flat outside it.

min local variance = 1.261e-2local vol >= 0 everywhere

Glossary

k
Log-moneyness: k = ln(K/F).
w
Total variance: w = σ²τ; additive across time, the coordinate SVI/SSVI fit in.
θ(τ)
ATM total-variance term structure, θ(τ) = w(0, τ); the backbone SSVI's slices are anchored to.
φ(θ)
SSVI's power-law curvature, φ(θ) = ηθ^(−γ); controls how sharply the smile bends at each maturity.
g(k)
The Gatheral–Jacquier butterfly indicator; g(k) < 0 signals a negative (arbitrageable) implied density.
F
The forward price of the underlying for a given expiry, recovered from put–call parity.
DF
The discount factor to a given expiry, recovered alongside F from the same regression.
ρ
The correlation/skew parameter controlling the smile's tilt; |ρ| < 1.
SVI
The five-parameter (a, b, ρ, m, σ) raw parametrisation of one expiry's total-variance smile.
SSVI
"Surface SVI": one global (ρ, η, γ) plus a term structure θ(τ), giving one consistent surface across all expiries.
Local vol
The Dupire instantaneous volatility σ_loc(k, τ) consistent with the whole fitted implied-vol surface.