Struct Scenario
pub struct Scenario {
pub label: String,
pub legs: Vec<ScenarioLeg>,
pub fx_mode: FxMode,
}Expand description
A named perturbation of the market, written in the units its quotes are made in.
Passive data, and applied by building a market rather than mutating one: the stored curves are reference-counted and untouched, and the shocked market wraps them in their family’s shock transform. Two scenarios can be applied to one market independently, and neither is visible to the other or to anything else holding the base.
The shock owns no free parameters — a transform’s parts are the curves it reads — so a shocked market lifts to a vector of the same length in the same order as its base. That is what lets a risk pass, a report and a P&L attribution run under a scenario and line up with the base row for row.
Fields§
§label: StringWhat a report keys this scenario’s row by, and the label the shock transforms carry.
legs: Vec<ScenarioLeg>The legs, applied in order, so two legs on one input compose.
fx_mode: FxModeWhat an FX spot leg holds fixed on an FX-implied curve.
Implementations§
§impl Scenario
impl Scenario
pub fn new(label: impl Into<String>) -> Self
pub fn new(label: impl Into<String>) -> Self
A scenario with no legs — the identity, until one is added.
pub fn shift(self, selector: Selector, amount: f64) -> Self
pub fn shift(self, selector: Selector, amount: f64) -> Self
This scenario with a parallel leg: every input selector admits moved
by amount, in the units it is quoted in.
pub fn slope(
self,
selector: Selector,
level: f64,
per_year: f64,
pivot_years: f64,
) -> Self
pub fn slope( self, selector: Selector, level: f64, per_year: f64, pivot_years: f64, ) -> Self
This scenario with a slope leg: level + per_year·(τ − pivot_years),
τ in years from the curve’s own reference date.
pub fn bucket(
self,
selector: Selector,
start: NaiveDate,
end: NaiveDate,
amount: f64,
) -> Self
pub fn bucket( self, selector: Selector, start: NaiveDate, end: NaiveDate, amount: f64, ) -> Self
This scenario with a bucket leg: amount at the pillars between
start and end, nothing elsewhere.
pub fn tent(
self,
selector: Selector,
left: Option<NaiveDate>,
peak: NaiveDate,
right: Option<NaiveDate>,
amount: f64,
) -> Self
pub fn tent( self, selector: Selector, left: Option<NaiveDate>, peak: NaiveDate, right: Option<NaiveDate>, amount: f64, ) -> Self
This scenario with a tent leg: amount at peak, linear to nothing at
left and right; a missing corner holds amount flat on its side.
pub fn holding_outrights(self) -> Self
pub fn holding_outrights(self) -> Self
This scenario moving FX-implied curves’ spots with every FX leg and
holding their outrights (FxMode::OutrightsHeld), so an FX shock’s
P&L is the one the AD FX delta predicts.
pub fn with_shift_type(
self,
selector: Selector,
shift: Shift,
shift_type: ShiftType,
) -> Self
pub fn with_shift_type( self, selector: Selector, shift: Shift, shift_type: ShiftType, ) -> Self
This scenario with one more leg, moving its inputs as shift_type
says — a vol leg in vol points under ShiftType::Absolute.
pub fn parallel(label: impl Into<String>, shift: f64) -> Self
pub fn parallel(label: impl Into<String>, shift: f64) -> Self
Every rate curve’s zero rate moved by shift, reported under label.
Discount and projection curves: a rates scenario that moved only what a book discounts on would report a basis move as a rates move.
fn apply(&self, market: &MarketContext) -> Result<MarketContext, ScenarioError>
fn apply(&self, market: &MarketContext) -> Result<MarketContext, ScenarioError>
market under this scenario: every admitted input wrapped in its
family’s shock transform, everything else carried through.
§Errors
ScenarioError if a leg names an input kind that has no shock, asks
a family for a shape it cannot carry, or if a shock curve is malformed.
fn shocked_inflation(
&self,
curve: &Inflation,
shift: Shift,
) -> Result<ShockedInflation, ScenarioError>
fn shocked_inflation( &self, curve: &Inflation, shift: Shift, ) -> Result<ShockedInflation, ScenarioError>
curve under shift, a move in its zero inflation rate: parallel as
one level, a dated shape evaluated at the curve’s nodes after its base
date and interpolated between them — the rate side’s rule.
fn shocked_curve(
&self,
curve: &Curve,
shift: Shift,
) -> Result<Curve, ScenarioError>
fn shocked_curve( &self, curve: &Curve, shift: Shift, ) -> Result<Curve, ScenarioError>
curve under shift, as a shock composed onto it.
A parallel move is a FlatSpread, whose log discount is −Δ·τ, so
composing it moves the zero rate by exactly Δ at every tenor. A dated
shape is a PiecewiseSpread over the base’s own pillar dates — or a
tenor grid when it has none — interpolating the spread linearly between them.