Use case · Surfaces
Run the canonical smile-panel in one call
surface_smile_risk_metrics returns the standard morning skew panel from one calibrated smile — ATM IV at the effective forward, the 25Δ and 10Δ risk reversals, and the 25Δ / 10Δ butterfly flies — replacing the handful of hand-rolled delta-to-strike lookups a desk would otherwise wire up.
When to use it
- You have one calibrated parametric smile (SVI / SSVI / SABR) at one expiry and want the full skew panel — ATM IV, RR25, RR10, fly25, fly10 — in one round trip.
- You want both delta pairs computed against the same effective forward and market context, so the two ATM IVs agree by construction.
- You need per-wing snap-to-listed-strike output plus bracket-quality diagnostics for readiness / degradation signals.
Example
use ferro_risk::{
surface_smile_risk_metrics, PricingModel, SurfaceDeltaConvention,
SurfaceSmileDeltaSelectionPolicy,
};
// `smile` is a calibrated SviSmile / SsviSlice / SabrSmile; `market` is the
// SurfaceMarketContext used to calibrate it. `listed_strikes` is the venue grid.
let metrics = surface_smile_risk_metrics(
&smile,
&market,
SurfaceDeltaConvention::Forward,
PricingModel::BlackScholesMerton,
SurfaceSmileDeltaSelectionPolicy::default(),
&listed_strikes,
)?;
let atm_iv = metrics.atm_iv(); // ATM IV at the effective forward
let rr_25 = metrics.rr_25().risk_reversal(); // call_iv - put_iv at 25Δ
let rr_10 = metrics.rr_10().risk_reversal(); // call_iv - put_iv at 10Δ
let fly_25 = metrics.fly_25(); // 25Δ butterfly fly
let fly_10 = metrics.fly_10(); // 10Δ butterfly fly
// Per-wing bracket diagnostics on the 25Δ put wing.
let put = metrics.rr_25().put_wing();
let snap_distance = put.bracket_delta_distance(); // delta-space snap-to-target gap
let lever_arm = put.bracket_spread(); // Option<f64>: interpolation width
# Ok::<(), ferro_risk::FerroRiskError>(())The readout
| Accessor | Description |
|---|---|
| metrics.atm_iv() | Smile IV at the effective forward. |
| metrics.rr_25() / rr_10() | The 25Δ / 10Δ risk reversal (each with its own wings, butterfly, and ATM IV). |
| metrics.fly_25() / fly_10() | 25Δ / 10Δ butterfly fly. |
| .risk_reversal() | On a risk reversal: call-wing IV minus put-wing IV, in decimal vol. |
| .put_wing() / .call_wing() | The two wings of a risk reversal. |
| wing.theoretical_strike() | Strike from the continuous delta inversion — where IV is read. |
| wing.selected_strike() | Nearest eligible listed strike (for order routing). |
| wing.bracket_delta_distance() | Snap-to-target distance: |Δ|-space gap between the requested target and the selected strike. Zero on an exact listed-strike hit. |
| wing.bracket_spread() | Interpolation lever-arm: the |Δ|-space width of the bracket. None on the continuous parametric path. |
Notes
SurfaceDeltaConventionhas two variants:Forward(undiscounted forward delta — the typical desk choice) andSpot(PV-sensitivity delta, scaled by the discount factor).- IVs, RR, and flies are computed at the theoretical strikes, so the numbers track the requested delta rather than the snapped grid;
selected_strike()is for routing. - The two bracket diagnostics are orthogonal — two wings can both read
Interpolatedyet differ in trustworthiness. Threshold on bothbracket_delta_distance()andbracket_spread()instead of trusting the binary quality flag. - The 25Δ RR is computed first and short-circuits on failure — a chain whose 25Δ wings are uninvertible yields no result. Call
surface_smile_risk_reversalat|Δ| = 0.10directly if you need independent tail metrics.
Note
The bundle is a single source of truth: atm_iv(), fly_25(), and fly_10() are accessors over the two risk reversals, not separately stored fields.