Use case · Volatility
Take the variance risk premium and split it into legs
variance_risk_premium turns implied and realized volatility on a shared tenor into a typed VrpRead; a JumpDiffusionFit then decomposes the premium into diffusive and jump/tail legs, and vrp_zscore normalizes it against a rolling baseline.
When to use it
- You need the premium between implied and realized variance as a typed read, in both vol-point and variance units.
- You want to know how much of the premium is diffusive carry versus compensation for jump/tail risk.
- You want a normalized, tradable signal — a z-score against a baseline mean and standard deviation.
Example
use ferro_risk::{
variance_risk_premium, vrp_decomposition, vrp_zscore,
JumpDiffusionFit, JumpDiffusionParameters, RvMethod, SurfaceTenor,
};
let tenor = SurfaceTenor::new(30.0 / 365.0)?; // 30-day tenor, in years
// implied 22 vol, realized 18 vol, both on the same tenor and estimator.
let vrp = variance_risk_premium(0.22, 0.18, tenor, RvMethod::YangZhang)?;
println!("premium (vol pts) = {}", vrp.premium_vol_pts());
println!("premium (variance) = {}", vrp.premium_variance());
// Decompose using a Merton jump-diffusion fit of the implied dynamics.
let params = JumpDiffusionParameters::new(0.9, -0.02, 0.08); // intensity, jump-mean, jump-std
let fit = JumpDiffusionFit::new(0.18, params)?;
let split = vrp_decomposition(fit, vrp);
println!("diffusive VRP = {} jump VRP = {}", split.diffusive_vrp(), split.jump_vrp());
println!("jump variance share = {}", split.jump_variance_share());
// Normalize against a rolling baseline (mean, std of the premium).
let z = vrp_zscore(vrp.premium_variance(), 0.010, 0.004)?;
println!("z-score = {}", z);
# Ok::<(), ferro_risk::FerroRiskError>(())The reads
| VrpRead | Description |
|---|---|
| premium_vol_pts() | Premium expressed in volatility points (implied − realized vol). |
| premium_variance() | Premium expressed in variance units (implied − realized variance). |
| implied_vol() | The implied volatility input. |
| realized_vol() | The realized volatility input. |
| tenor() | The SurfaceTenor the premium is quoted on. |
| method() | The RvMethod used for the realized leg. |
| VrpSplit | Description |
|---|---|
| diffusive_vrp() | The diffusive component of the premium. |
| jump_vrp() | The jump/tail component of the premium. |
| jump_variance_share() | Jump share of implied variance from the fit, in [0, 1]. |
| jump_share_of_premium() | Option<f64> — literal jump fraction of the premium; None when realized ≥ implied. |
| premium_variance() | The premium in variance units (carried from the read). |
Notes
- The realized leg must be measured with the same
RvMethodand tenor the premium is quoted against — see realized volatility. jump_variance_share()comes from the fit and is always in[0, 1];jump_share_of_premium()is the literal premium fraction and can exceed 1 (or beNone) when the diffusive leg is negative or realized exceeds implied.- The fit reuses
JumpDiffusionParameters— the same Merton (1976) intensity / jump-mean / jump-std bundle the pricing engine exposes. - Non-finite or degenerate inputs (a zero baseline std, an overflowed jump moment) fail loud with a typed
FerroRiskErrorin thevrp.*namespace.
Signal
vrp_zscore(premium, baseline_mean, baseline_std) is a plain standardization — pair it with your own rolling baseline to turn the premium level into a comparable signal across regimes.