Use case · Pricing
Solve IV, forward, and Greeks in one call
When a workload needs solved implied volatility AND the explicit forward AND the full Greek set on the same contract, contract_analytics fuses them on one internal evaluation path — the Greeks reuse the solved price rather than recomputing a base point.
When to use it
- You have an observed market price and contract terms (no volatility) and need solved IV, the forward, and the Greeks computed together.
- High-throughput per-contract analytics — option-chain rows, spread legs — where reusing the solved price for the Greek base point matters.
- The IV solve is driven by Jaeckel's Let's-Be-Rational rational-cubic solver to machine precision (bisection fallback on the European Black paths).
Example
use ferro_risk::{contract_analytics, ExerciseStyle, IvSolveInputs, OptionType, PricingModel};
// Contract terms WITHOUT volatility — volatility is what we solve for.
let inputs = IvSolveInputs {
option_type: OptionType::Call,
exercise_style: ExerciseStyle::European,
spot: 100.0,
strike: 100.0,
time_to_expiry: 0.5,
rate: 0.03,
dividend_yield: 0.01,
};
let market_price = 6.10; // observed option price
let analytics = contract_analytics(&inputs, market_price, PricingModel::BlackScholesMerton)?;
let implied_vol = analytics.iv.iv; // solved sigma
let forward = analytics.forward; // undiscounted forward / futures
let model_price = analytics.greeks.price; // price at the solved IV
let delta = analytics.greeks.delta;
let converged = !analytics.iv.used_fallback;
# Ok::<(), ferro_risk::FerroRiskError>(())The result
ContractAnalyticsResult bundles three things:
| Field | Description |
|---|---|
| forward | Undiscounted forward / futures price implied by the contract; collapses to spot at exact expiry. |
| iv | An IvResult: iv (solved sigma), iterations, used_fallback, price_residual, price_residual_unit. |
| greeks | The full Greeks set evaluated at the solved IV; greeks.price differs from the market price by the IV residual. |
Notes
IvSolveInputshas novolatilityfield — that is the unknown. Usewith_volatility(σ)to convert it to aPricingInputs.used_fallbackistrueonly when the rational solver falls back to bisection. For Bachelier it is alwaysfalse(bisection over normal vol is canonical); for American Bjerksund-Stensland it istrueon every live non-exact solve.- Residual units differ by model family — check
iv.price_residual_unit(ForwardNormalisedPricevsModelPrice) before comparing residuals across models.
Batch
contract_analytics_batch(&[(IvSolveInputs, f64, PricingModel)]) -> Vec<Result<ContractAnalyticsResult, FerroRiskError>> runs each contract in parallel via Rayon, preserves order, and isolates per-contract failures.