Caps and Floors
Instruments
let cap = MakeCapFloor::default()
.with_identifier("USD_SOFR_CAP_2Y".to_string())
.with_start_date(rd)
.with_maturity_date(rd + Period::from_str("2Y")?)
.with_notional(10_000_000.0)
.with_strike(0.045)
.with_cap_floor_type(CapFloorType::Cap)
.with_currency(Currency::USD)
.with_market_index(MarketIndex::SOFR)
.with_frequency(Frequency::Quarterly) // default
.build()?;
let trade = CapFloorTrade::new(cap, rd, 10_000_000.0, Side::LongReceive);
Required: notional, start_date, maturity_date, strike, currency, market_index, identifier, cap_floor_type. Defaults: side LongReceive, frequency Quarterly. CapFloorType::{Cap, Floor}; a single period is a CapletFloorlet (CapletFloorletType::{Caplet, Floorlet}) with trade CapletFloorletTrade::new(..).
Black-76 pricers
ClosedFormBlackCapletPricer::new() and ClosedFormBlackCapPricer::new() handle Request::Value and Request::Sensitivities. For each caplet with fixing \(T\), accrual \([T,S]\), \(\tau=S-T\):
\[ F = \frac{1}{\tau}\left(\frac{P(T)}{P(S)}-1\right),\qquad \text{Caplet} = N\,\tau\,Pd(S)\,[F\,\Phi(d_1) - K\,\Phi(d_2)],\quad d{1,2}=\frac{\ln(F/K)\pm\tfrac12\sigma^2 T}{\sigma\sqrt T}. \]
- The forward comes from the curve of
market_index; the discount factor from the discount policy (dual-curve when aSingleCurveCSADiscountPolicyis set). - The strike is a
Strike(Absolute,Atm,Relative) resolved against \(F\). - \(\sigma\) is read from the
VolatilitySurfaceElementformarket_indexat(fixing_date, strike)throughvolatility_from_date;VolatilityType::Normalsurfaces switch to the Bachelier formula. - A cap is the sum of its caplets; floors use the put formula.
Market data requested: the discount curve(s) and the volatility surface of the index. Sensitivities are labelled with the OIS quotes and the CapletFloorlet_* quotes that define the surface.
Hull-White pricers
ClosedFormHullWhiteCapletPricer::new(alpha, sigma) and ClosedFormHullWhiteCapPricer::new(alpha, sigma) price the same trades without a surface, using the one-factor Hull-White model with constant \(\sigma\):
\[ \text{Caplet} = N\,(1+\tau K)\;\text{BondPut}\bigl(T, S, X\bigr),\qquad X=\frac{1}{1+\tau K}, \]
where the zero-coupon bond option uses the volatility
\[ \sigma_P = \sigma\,B(T,S)\sqrt{\frac{1-e^{-2\alpha T}}{2\alpha}},\qquad B(t,T)=\frac{1-e^{-\alpha(T-t)}}{\alpha}. \]
They are useful to cross-check a calibrated model (HullWhite::calibrate_with_configuration, see Hull-White) against the Black surface it was fitted to.
Sensitivities
Both pricer families run the reverse sweep from the option value; results.sensitivities() therefore contains curve pillars (OIS_USD_SOFR_*) and, for Black pricers, one row per volatility quote (CapletFloorlet_USD_SOFR_3M_1Y_Absolute_0.045_Straddle_Black), i.e. a vega ladder on the quoted grid.