Overview
Pricing models
Seven models dispatch through one PricingModel enum — European to American, lognormal to normal, deterministic to stochastic vol, with jumps. The model is always named explicitly at the call site.
The seven models
| PricingModel | Description |
|---|---|
| BlackScholesMerton | European — equity-style spot options with continuous carry/dividend yield. The default workhorse. |
| Black76 | European — options on forwards and futures. Set dividend_yield = 0.0; spot is the forward. |
| Bachelier | European — normal-vol options on forwards/futures. Admits zero and negative spot/strike (rates, spreads). |
| DisplacedBlack { displacement } | European — shifted-lognormal pricing for shifted forward markets. |
| Heston { parameters } | European — stochastic-volatility pricing via the Fang-Oosterlee COS method. volatility is sqrt(v0). |
| JumpDiffusion { parameters } | European — Merton (1976) lognormal jump-diffusion with explicit Poisson intensity, jump-mean, and jump-std parameters. |
| BjerksundStensland | American — the Bjerksund-Stensland 2002 two-stage exercise boundary. The production American path. |
Naming a model
Unit-variant models are named directly; parameterized models carry their configuration in the variant (with const constructors for convenience):
use ferro_risk::{price, PricingInputs, PricingModel};
// unit variants
price(&inputs, PricingModel::BlackScholesMerton)?;
price(&inputs, PricingModel::Black76)?;
price(&inputs, PricingModel::BjerksundStensland)?;
// parameterized variants
price(&inputs, PricingModel::displaced_black(0.03))?;
// PricingModel::heston(...), PricingModel::jump_diffusion(...)
# Ok::<(), ferro_risk::FerroRiskError>(())Discrete cash dividends
The PricingModel variants all take carry as a continuous dividend_yield. For listed equity options, where the underlying pays discrete cash amounts on known ex-dates, the American path accepts a DividendSchedule instead: it prices the escrowed spot S − Σ Dᵢ·e^(−r·tᵢ) through the unchanged Bjerksund-Stensland kernel.
use ferro_risk::{american_price_with_dividends, DividendEvent, DividendSchedule};
let schedule = DividendSchedule::new(vec![
DividendEvent::new(38.0 / 365.0, 0.96)?,
])?;
let premium = american_price_with_dividends(&pricing, &schedule)?;
// The empty schedule is the exact no-dividend identity.
assert_eq!(
american_price_with_dividends(&pricing, &DividendSchedule::empty())?.to_bits(),
ferro_risk::american_price(&pricing)?.to_bits(),
);
# Ok::<(), ferro_risk::FerroRiskError>(())The same schedule rides on IvSolveInputs.dividends, so implied_vol, contract_analytics, and de_americanize_quote all invert on the escrowed process. See dividends & de-Americanization.
A non-empty schedule off the BS2002 American path fails loud with UnsupportedModelExerciseCombination — the dividends are never silently dropped.
American CRR reference
Alongside the production BjerksundStensland path, an opt-in high-fidelity Cox-Ross-Rubinstein binomial reference is available for validation workflows via american_reference_price / american_reference_report. It is intentionally slower and is not a PricingModel variant — use it to check the fast approximation, not to price in production.
The Bjerksund-Stensland 2002 boundary used in production is a higher-fidelity approximation than common single-boundary engines; the CRR reference (run to a high step count) is the oracle it is validated against.
Dupire local volatility
Beyond the parametric models, FerroRisk extracts a Dupire local-vol surface from any calibrated surface and reprices over it with backward Crank-Nicolson PDE, forward Dupire-strip PDE, and Monte-Carlo kernels. See surface calibration.