Volatility surface
Module: Shoals.VolSurface.
This module parameterizes a volatility smile with the five-parameter SVI total-variance form, converts total variance to implied volatility, applies structured shifts to a surface, and solves for an implied volatility from a call price by bisection over Black-Scholes.
The SVI type
Section titled “The SVI type”type SVI = | SVI { a: f32, b: f32, rho: f32, m: f32, sigma: f32 }The SVI parameters are a (the vertical level), b (the slope of the
wings), rho (the rotation, or skew), m (the horizontal translation),
and sigma (the smoothness of the curvature near the money). From
tests/volsurface.ch, a flat surface and a downward-skewed smile:
def flat_svi() -> SVI = SVI { a: cast(0.04, f32), b: cast(0.0, f32), rho: cast(0.0, f32), m: cast(0.0, f32), sigma: cast(0.1, f32) }def smile_svi() -> SVI = SVI { a: cast(0.04, f32), b: cast(0.2, f32), rho: cast(-0.3, f32), m: cast(0.0, f32), sigma: cast(0.1, f32) }Total variance and implied volatility
Section titled “Total variance and implied volatility”def vs_total_variance(p: SVI, k: f32) -> f32def vs_implied_vol(p: SVI, k: f32, t: f32) -> f32vs_total_variance evaluates the SVI total variance w(k) at log-moneyness
k. vs_implied_vol converts total variance to an implied volatility by
sqrt(max(w, 0) / t), clamping negative variance to zero.
From tests/volsurface.ch, a flat surface has total variance equal to a
at the money and constant across strikes, and its implied vol at one year
is sqrt(a / t):
p = flat_svi()w = vs_total_variance(p, cast(0.0, f32)) // w == 0.04iv = vs_implied_vol(p, cast(0.0, f32), cast(1.0, f32)) // iv == 0.2A smile has higher total variance out of the money than at the money.
Surface shifts
Section titled “Surface shifts”def vs_shift_atm(p: SVI, delta_a: f32) -> SVIdef vs_shift_skew(p: SVI, delta_rho: f32) -> SVIdef smile_shift_skew_wing(p: SVI, delta_b: f32) -> SVIdef parallel_shift_atm_iv(p: SVI, delta_iv: f32, t: f32) -> SVIvs_shift_atm adds delta_a to the level parameter, which adds the same
amount to total variance. vs_shift_skew adds to rho. smile_shift_skew_wing
adds to b. parallel_shift_atm_iv is the structured shift that lifts the
at-the-money implied volatility by exactly delta_iv, recomputing the level
parameter so the change to total variance is consistent at maturity t.
From tests/volsurface.ch:
p = smile_svi()shifted = parallel_shift_atm_iv(p, cast(0.01, f32), cast(1.0, f32))// the ATM implied vol of shifted is 0.01 above that of pImplied-vol solver
Section titled “Implied-vol solver”def implied_vol_from_call(spot: f32, strike: f32, r: f32, t: f32, target_price: f32) -> f32def implied_vol_bisect(spot: f32, strike: f32, r: f32, t: f32, target: f32, vol_lo: f32, vol_hi: f32, max_iters: int64, tol: f32) -> f32def bracket_brackets_root(spot: f32, strike: f32, r: f32, t: f32, target: f32, vol_lo: f32, vol_hi: f32) -> booldef is_iv_solver_failed(iv: f32) -> boolimplied_vol_from_call inverts the Black-Scholes call to find the
volatility that reproduces target_price. It calls implied_vol_bisect
with a search bracket of 0.0001 to 5.0, sixty iterations, and a price
tolerance of 0.000001. From tests/volsurface.ch, the solver round-trips
a Black-Scholes price back to its volatility:
price = bs_call_scalar(cast(100.0, f32), cast(100.0, f32), cast(0.05, f32), cast(0.2, f32), cast(1.0, f32))iv = implied_vol_from_call(cast(100.0, f32), cast(100.0, f32), cast(0.05, f32), cast(1.0, f32), price)// iv == 0.2implied_vol_bisect exposes the full bisection with an explicit bracket,
iteration cap, and tolerance. If the bracket does not contain a sign change,
it returns a NaN sentinel rather than pinning silently at the bracket edge.
bracket_brackets_root reports whether a [vol_lo, vol_hi] pair brackets
the target, and is_iv_solver_failed tests the returned value for the NaN
sentinel:
iv = implied_vol_bisect(cast(100.0, f32), cast(100.0, f32), cast(0.05, f32), cast(1.0, f32), cast(200.0, f32), cast(0.0001, f32), cast(5.0, f32), cast(60, int64), cast(0.000001, f32))failed = is_iv_solver_failed(iv) // true: 200.0 is not a reachable call price here