Skip to main content

MarketContext

Struct MarketContext 

pub struct MarketContext {
    as_of: Option<NaiveDate>,
    state: MarketState,
    build: BuildRecord,
    misdated: BTreeMap<(&'static str, String), ReferenceDateMismatch>,
    layout: OnceLock<Arc<[Span]>>,
    history: FixingHistory,
    others: BTreeMap<NaiveDate, Snapshot>,
    fetched: Option<Arc<MarketData>>,
    source_recipes: BTreeMap<CollateralSpec, Option<CurveRecipe>>,
}
Expand description

The stored market: passive, immutable, shareable.

Three things by type, not by comment: the state a lift reads and equality compares, the build record of how the market was or would be built, and two caches derived from the state. Curves are held behind Arc, so pinning one curve under two roles shares one allocation while keeping two risk axes — a discount move and a projection move are different facts even when one curve answers both, and a ladder that merged them could not tell them apart.

Fields§

§as_of: Option<NaiveDate>

The date this is a market as of.

Declared at construction rather than derived from whichever curve happened to be bound first: bind order would otherwise decide which input a mismatch is blamed on, and an empty market would have no date to state. Every curve bound is checked against it.

Part of equality, where the build record is not. It is not a record of how the market was built — it is state a valuation reads, and two markets as of different dates are different markets.

§state: MarketState

What a lift reads: the four families. Part of equality — all of it, by derivation, so a family or input added here is compared without a line being written.

§build: BuildRecord

How the market was, or would be, built. Not part of equality: two markets holding identical state are the same market whether one was calibrated and the other pinned by hand, and whether or not one also carries the recipes that would rebuild it.

§misdated: BTreeMap<(&'static str, String), ReferenceDateMismatch>

The curves bound through an infallible binder as of another date than as_of, keyed by store and key. Recorded where they are bound and refused by view — in every profile, where a debug assertion would leave a release build to value against them — and cleared when the key is bound again with a curve as of as_of. Derived from the dated stores against as_of, so not part of equality.

§layout: OnceLock<Arc<[Span]>>

The span layout, computed once per stored state and shared with every lift. Every builder method clears it, so it can never describe a market other than this one. Not part of equality: it is derived.

§history: FixingHistory

Every print the market has seen, with the date each version was known on: the market’s one fixing history. The observations family of the current snapshot holds it as known on the current date — what a market as of that date had seen — and the lift reads only that. Part of equality, every version.

§others: BTreeMap<NaiveDate, Snapshot>

The snapshots held at dates other than the current one: each the state, ladders and refits the market had at that date, set aside by on and brought back when the market moves there again. Their states are part of equality. An empty snapshot is never set aside.

§fetched: Option<Arc<MarketData>>

The market data the current snapshot was fetched from, where it was. Not part of equality.

§source_recipes: BTreeMap<CollateralSpec, Option<CurveRecipe>>

The recipes a source returned for the current date, by key — None for a key asked of the source that it had no recipe for. How the date’s curves were built, under the caller’s own overlay and over the shipped base; not part of equality.

Implementations§

§

impl MarketContext

pub fn demand(&self, book: &Book) -> Result<Demand, PricingError>

What book needs from outside to price on this market — see the module notes.

A curve this market already holds is not demanded; a spot or fixing it already holds is not either. A curve no recipe builds is listed under Demand::unresolved rather than refused, so a snapshot names it with every other gap.

§Errors

PricingError where a trade cannot state its risk factors, or the book spans currencies without declaring one to report in.

fn demand_key( &self, key: &CollateralSpec, keys: &mut BTreeSet<CollateralSpec>, strips: &mut BTreeSet<StripKey>, unresolved: &mut BTreeSet<Unresolved>, want_fx: &mut impl FnMut(Currency, Currency), )

Demands the strips key’s recipe names, and — for a cross key — the pair and the own keys its segments read.

fn demand_projection( &self, index: &str, keys: &mut BTreeSet<CollateralSpec>, strips: &mut BTreeSet<StripKey>, unresolved: &mut BTreeSet<Unresolved>, )

Demands the strip that marks projection index: the own-collateral recipe whose swap template — a par-swap segment or an own strip — floats on the index. A curve is pinned under the index its rungs’ instruments carry, so that, and not a recipe’s label for the index, is what identifies the strip. The recipe’s discount is demanded with it: a projection solves over its currency’s discount.

pub fn with_market_data( &self, demand: &Demand, data: &MarketData, ) -> Result<MarketContext, SnapshotError>

This market with what data carries of demand built in: spots, then fixings, then every own-collateral curve, then every cross curve — or, where anything demanded is missing, no market and every gap named.

The receiver is unchanged. Spots and fixings join those it already holds. A strip that arrived but does not solve is a SnapshotError::Calibration, not a gap: the source answered.

§Errors

SnapshotError as above, or for a strip or spot stamped after as_of.

pub fn with_market_data_using( &self, demand: &Demand, data: &MarketData, options: &CalibrationOptions, ) -> Result<MarketContext, SnapshotError>

with_market_data solving every curve under options.

§Errors

As with_market_data.

pub fn recipe_ask( &self, book: &Book, ) -> Result<Option<RecipeAsk>, SnapshotError>

What a recipe source must be asked for book at this market’s date: the collateral keys the book reads that the caller’s own overlay does not set and that were not already asked at this date — or None where no key is left to ask.

§Errors

SnapshotError::Pricing where a trade cannot state its keys.

pub fn with_source_recipes_answered( &self, ask: &RecipeAsk, specs: &[RecipeSpec], ) -> Result<MarketContext, SnapshotError>

This market with specs — a source’s answer to ask — kept as the current date’s source recipes: each validated through the builder, a key the caller’s overlay sets left to the caller, and every asked key the answer leaves out recorded as asked. The caller’s overlay is not touched.

§Errors

SnapshotError::Recipe naming a recipe the builder refuses.

pub fn with_recipes_from( &self, book: &Book, source: &dyn RecipeSource, ) -> Result<MarketContext, SnapshotError>

This market with the recipes source holds for book’s keys, kept as the current date’s source recipes: the caller’s own recipes win, a source’s beat the shipped base, and a key already asked at this date is not asked again. recipe_ask, the source’s answer, then with_source_recipes_answered.

§Errors

SnapshotError::Source where the source failed; SnapshotError::Recipe naming a recipe the builder refuses; SnapshotError::Pricing where a trade cannot state its keys.

§

impl MarketContext

fn with_observed( &self, data: &MarketData, ) -> Result<MarketContext, SnapshotError>

This market with data’s spots and fixings joined to those it holds — a fetched spot replacing a held one on the same pair, either way round.

§

impl MarketContext

pub fn as_of(as_of: NaiveDate) -> Self

An empty market as of as_of.

There is no date-less constructor. A market’s inputs are all quoted as of some date, and one that did not say which could hold two curves that disagree about what day it is — which priced, silently, until this existed.

pub fn undated() -> Self

An empty market with no date: reference data — recipes, counterparties, meeting schedules, the data source — and a fixing history, but no snapshot. A dated input is refused until the market is moved to a date with on, and it does not value.

The process default data source, if one is set, is copied in here; a later set_data_source does not reach a market built before it.

pub fn date(&self) -> Option<NaiveDate>

The date this market is as of, or None for an undated market.

pub fn on(self, date: NaiveDate) -> Self

This market at date: the same reference data and fixing history, with the snapshot held at date current — an empty one where none is held. The snapshot current until now is set aside, not dropped, and comes back when the market is moved to its date again. Curves are shared, not copied.

pub fn dates(&self) -> Vec<NaiveDate>

The dates this market holds a snapshot for, the current one included.

pub fn without(self, date: NaiveDate) -> Self

This market without the snapshot held at date. Dropping the current date’s snapshot leaves the market at that date with an empty one.

pub(crate) fn emptied(self) -> Self

This market at its own date with an empty snapshot, keeping the recipes a source answered for the date: what a rebuild of the date from other quotes starts from.

pub(crate) fn carrying_unfetched(self, held: &MarketContext) -> Self

This market with every term structure, vol surface and mark that held carries and the current snapshot lacks pinned back, with the carried curves’ ladders and refits: what a re-fetch of the same date leaves behind because its source does not serve it. What the fetch did bring is kept as fetched.

pub fn fetched(&self) -> Option<&MarketData>

The market data the current snapshot was fetched from, where it was.

pub(crate) fn with_fetched_merged(self, data: &MarketData) -> Self

Records data beside what the current snapshot was already fetched from: a top-up adds to the record rather than replacing it.

pub fn data_source(&self) -> Option<&DataSource>

The data source this market fetches from, or None where it is offline or none was ever set.

pub fn with_data_source(self, source: Option<DataSource>) -> Self

This market fetching from source, or — with None — offline: it never fetches, even where a process default is set.

pub fn reference_date(&self) -> NaiveDate

The date this is a market as of.

Spelled as every curve spells it, because it is the same fact: a market and the curves it holds agree on their reference date, which is what the bind-time check enforces.

fn note_reference_date( &mut self, store: &'static str, key: &str, reference: NaiveDate, )

Records whether the curve bound under store’s key agrees with this market’s date.

The infallible half of the reference-date invariant. The mid-builder binders stay infallible for the call sites that have the curves in front of them; a disagreeing date is recorded here and refused by view, the gate every valuation passes, with the same typed error the checked form (check_reference_date) returns at bind. A matching bind clears the key’s record.

Every store a dated curve is bound into calls it — discount, projection, repo, security spread, credit and inflation. reference_date_guard in the tests derives that set from this struct’s fields rather than listing it.

pub fn missing_curve(&self, id: &CurveId) -> PricingError

The refusal for a curve this market does not hold under id: the key, the keys it holds of the same kind, those it holds of every other kind, and the recipe that would build it where one is carried.

The one constructor every lookup builds the refusal through — a valuation’s resolution and the binding’s lookups alike — so the text is the same wherever the curve was missed. Read only once a lookup has failed, so its allocations are off the pricing path.

fn missing_curve_ref(&self, key: CurveIdRef<'_>) -> PricingError

missing_curve by borrowed key.

fn recipe_like(&self, key: CurveIdRef<'_>) -> Option<String>

How a curve under key would be built, where this market carries an effective recipe for it.

Only a discount key can have one: recipes are keyed by the collateral spec, which is what a discount key is. A projection, repo, spread, credit or inflation key names no recipe, and says so.

Read only when a resolution has already failed, so the formatting is off the pricing path — the same ground held_like is read on.

fn held_like(&self, key: CurveIdRef<'_>) -> Vec<String>

The keys of the same kind as key that this market does hold.

Read only when a resolution has already failed, so the allocation is off the pricing path. It is what turns “no curve under projection(USD-SOFR)” into a message a caller can act on: the mismatch is usually a spelling, and the spelling that is held is the correction.

pub fn check_reference_date( &self, key: &str, reference: NaiveDate, ) -> Result<(), ReferenceDateMismatch>

Refuses reference where it is not this market’s as_of.

The typed half of the reference-date invariant, for the data-driven paths — the binding, and any caller assembling a market from a feed — where a disagreeing date is a fact about the data rather than a mistake visible in the source. The infallible builders record the same check and view refuses it, so the refusal holds in every profile either way.

§Errors

ReferenceDateMismatch naming the key and both dates.

fn record_provenance(&mut self, id: CurveId, pinned: &PinnedCurve)

Records pinned’s ladder under id, if it brought one.

A curve pinned without a ladder clears whatever ladder the key held: re-pinning is a replacement, and a stale ladder describing the previous curve is worse than none. That is what makes a scenario’s shocked curve drop its provenance without the scenario code saying anything.

The rung count is not re-checked here — PinnedCurve::with_provenance refuses a mismatch before one can be built, and From<Calibrated> cannot produce one — so the invariant holds by construction and the assertion below only guards a future third constructor.

fn record_ladder( &mut self, id: CurveId, provenance: Option<&Arc<CurveProvenance>>, parameter_count: usize, )

The same, for any pin that knows its ladder and its parameter count.

pub fn with_recipes(self, recipes: CurveRecipes) -> Self

This market with recipes as its effective curve recipes.

The layout is not cleared: a recipe contributes no lifted parameter, so the span layout this market may already have computed still describes it. Clearing it would force a recomputation inside a pinned allocation budget for a change that moves nothing the lift reads.

pub fn with_counterparties(self, counterparties: Counterparties) -> Self

This market carrying counterparties as the master a draft’s counterparty is resolved from. The layout and the compared state are untouched: a master is reference data, not a market input.

pub fn with_meetings(self, schedule: MeetingSchedule) -> Self

This market carrying schedule as the bank’s calendar of decisions. The layout and the compared state are untouched: a schedule is reference data, not a market input, and a window on a step curve is named from it without a number moving.

pub fn meetings(&self, bank: &CentralBank) -> Option<MeetingSchedule>

The schedule pinned for bank, or the seed where none is pinned, or None for a bank with neither.

pub fn counterparty(&self, acronym: &str) -> Option<&Counterparty>

The counterparty under acronym, or None on a market given no master or an acronym it does not hold.

pub fn recipe(&self, key: &CollateralSpec) -> Option<CurveRecipe>

The effective recipe for key — how a curve under that key would be built — or None where this market carries none.

Resolution is CurveRecipes::resolve’s: overlay ▸ base ▸ absence, so the precedence is decided in one place rather than restated here.

This answers how a curve is built, never whether one is held: a key this returns a recipe for may or may not resolve to a stored curve, and the two questions are asked of the same CollateralSpec.

pub fn curve( &self, id: &CurveId, ) -> Option<(Arc<Curve>, Option<Arc<CurveProvenance>>)>

The curve pinned under id, with the provenance it was pinned with.

The pair is the point: a curve read out and pinned into another market keeps the ladder par risk reads, so a read-back is lossless rather than a copy that has forgotten how it was built. A curve pinned bare answers Some((curve, None)) — held, with no ladder — which is a different answer from None, not held.

Serves the four rate-curve roles. Credit and Inflation are stored in their own maps under their own types, and are read through credit_curve and inflation_curve.

pub(crate) fn rate_curve(&self, id: &CurveId) -> Option<&Arc<Curve>>

The rate curve pinned under id, borrowed and without its ladder: the read a hot path takes when curve’s provenance lookup would go unused.

pub fn credit_curve( &self, credit: &CreditCurveId, ) -> Result<(Arc<Survival>, Option<f64>), PricingError>

The survival curve and stated recovery pinned for entity.

The recovery rides with the curve because it is the assumption the quote carries: reading one without the other would hand back a curve whose units are unrecoverable.

§Errors

The market’s missing-curve refusal naming credit(<id>) where no survival curve is pinned for it.

pub fn inflation_curve(&self, index: &str) -> Option<Arc<Inflation>>

The inflation curve pinned under index.

fn term<T>( &self, id: CurveIdRef<'_>, pick: impl FnOnce(&Term) -> Option<&T>, ) -> Option<&T>

The term under id, as the arm pick names — the terms’ twin of vol and mark, with the same reading of a mismatch: the identity’s role decides the arm, so another arm under it is a defect in this store.

pub fn base_correlation( &self, index: &CreditIndexId, ) -> Option<Arc<BaseCorrelation>>

The base correlation pinned under credit_index.

The five readers below complete the read-back obligation: until they existed a caller could pin a correlation, a rate or a surface and read none of them, so a market holding vols could not be rebuilt from its own contents.

fn mark<T>( &self, id: MarkIdRef<'_>, pick: impl FnOnce(&Mark) -> Option<&T>, ) -> Option<&T>

The mark under id, as the arm pick names — the marks’ twin of vol, with the same reading of a mismatch.

pub fn vol_surface_ids(&self) -> Vec<VolSurfaceId>

Every vol surface the market holds, by identity, in the identity’s order — the order the lift reads them.

pub fn base_correlations(&self) -> Vec<(CreditIndexId, Arc<BaseCorrelation>)>

Every base-correlation curve, with the credit index it is pinned under, in store order.

pub fn fx_rate(&self, pair: CurrencyPair) -> Option<f64>

The FX rate pinned for pair, as stored.

What was pinned, not what can be derived. A cross reachable only through a pivot is a valuation-time derivation and belongs to the lift, where FxView::rate triangulates; this states the input, so a market can be rebuilt from its own contents without inventing quotes it never held. The inverse is not reported either: a pinned EURUSD does not make USDEUR a pinned input.

fn vol<T>( &self, id: VolSurfaceIdRef<'_>, pick: impl FnOnce(&VolSurface) -> Option<&T>, ) -> Option<&T>

The surface under id, as the arm pick names.

The verbs insert each identity with its own arm, so an identity found under another arm is a defect in this store rather than a caller’s mistake, and is treated as one.

fn smile_of(&self, id: VolSurfaceIdRef<'_>) -> Option<RateSmileRef<'_>>

The rate smile pinned under id, grid or SABR.

pub fn fx_vols(&self, pair: CurrencyPair) -> Result<&FxVolSurface, PricingError>

The FX volatility surface pinned for pair.

§Errors

PricingError::MissingVolSurface naming the pair where the market pins no surface.

pub fn swaption_vols( &self, currency: Currency, ) -> Result<&RateVolSurface, PricingError>

The swaption volatility surface pinned for currency.

§Errors

PricingError::MissingSwaptionVols naming the currency where the market pins no surface.

pub fn swaption_smile( &self, currency: Currency, ) -> Result<RateSmileRef<'_>, PricingError>

The swaption smile pinned for currency, grid or SABR.

§Errors

PricingError::MissingSwaptionVols naming the currency where the market pins none.

pub fn cap_smile( &self, currency: Currency, ) -> Result<RateSmileRef<'_>, PricingError>

The caplet smile pinned for currency, grid or SABR.

§Errors

PricingError::MissingCapVols naming the currency where the market pins none.

pub fn bond_yield_vols( &self, key: &str, ) -> Result<&RateVolSurface, PricingError>

The bond-yield volatility surface pinned under key: a currency code, or the security an option names.

§Errors

PricingError::MissingBondYieldVols naming the key where the market pins no surface.

pub fn cap_vols( &self, currency: Currency, ) -> Result<&RateVolSurface, PricingError>

The cap volatility surface pinned for currency.

§Errors

PricingError::MissingCapVols naming the currency where the market pins no surface.

pub fn yoy_vols(&self, index: &str) -> Result<&YoyVolSurface, PricingError>

The year-on-year inflation optionlet vol surface pinned for the price index index.

§Errors

PricingError::MissingYoyInflationVols naming the index where the market pins no surface.

pub fn cpi_vols(&self, index: &str) -> Result<&CpiVolSurface, PricingError>

The zero-coupon CPI option vol surface pinned for the price index index.

§Errors

PricingError::MissingCpiInflationVols naming the index where the market pins no surface.

pub fn equity_vols( &self, name: &str, ) -> Result<&FutureOptionVolSurface, PricingError>

The option vol surface pinned for the equity name.

§Errors

PricingError::MissingEquityVols naming the equity where the market pins no surface.

pub fn future_option_vols( &self, contract: &ListedFutureId, ) -> Result<&FutureOptionVolSurface, PricingError>

The option vol surface pinned for the listed future contract.

§Errors

PricingError::MissingFutureOptionVols naming the contract where the market pins no surface.

pub fn future_price(&self, contract: &ListedFutureId) -> Option<f64>

The quoted price of the listed future contract, per 100 face, if the market carries one.

pub fn equity_spot(&self, name: &str) -> Option<f64>

The quoted spot of the equity name, if the market carries one.

pub fn future_prices(&self) -> impl Iterator<Item = (&ListedFutureId, f64)> + '_

Every quoted futures price, as (contract, price) in key order.

pub fn credit_vols( &self, credit: &CreditCurveId, ) -> Result<&CreditVolSurface, PricingError>

The credit volatility surface pinned for credit.

§Errors

PricingError::MissingCreditVols naming the identity where the market pins no surface.

pub fn contents(&self) -> Vec<(&'static str, String)>

Every stored input’s identifier, as (kind, key) rows in lift order.

The listing is produced from the same walk the lift reads, so a store cannot be filled by a builder and stay invisible here: adding one without giving Input::contents an arm is a compile error, not a silent omission. The kinds name the builder verbs, so a row reads as the call that would put it back — except recovery, which with_credit_curve pins beside the entity’s credit row: it is a lifted parameter of its own, and no parameter is held unlisted.

Stored inputs only. Curve recipes are not contents: they are construction instructions for curves this market does not hold, they contribute no lifted parameter, and they are read through recipe and recipe_keys. Nor is reference_date a row — every context has one, so it is a property of the listing rather than an entry in it.

pub fn watched_labels(&self) -> Vec<&str>

Every exogenous label this market watches, in store order.

pinned_input answers a label already known; this is how a caller learns which labels there are. Also reachable through contents under the pinned_input kind — this is the typed form for a caller who wants only those.

pub(crate) fn watched_label_iter(&self) -> impl Iterator<Item = &str>

watched_labels without collecting them.

pub fn recipe_keys(&self) -> Vec<CollateralSpec>

The effective recipe keys this market carries.

pub(crate) fn caller_overrides(&self, key: &CollateralSpec) -> bool

Whether the caller’s own overlay sets a recipe for key.

pub(crate) fn asked_of_source(&self, key: &CollateralSpec) -> bool

Whether key was already asked of a source at the current date.

pub(crate) fn with_source_recipes( self, recipes: impl IntoIterator<Item = (CollateralSpec, Option<CurveRecipe>)>, ) -> Self

This market with recipes as what a source answered for the current date, by key — None for a key asked and not answered.

pub fn recipes(&self) -> Records

The effective recipes as one table — one row per pillar, plus one per telescoping projection, which has no pillar of its own.

Columns are (key, curve, kind, curve_id, tenor_or_date). The key column carries the canonical CollateralSpec spelling, so every listed row is addressable through recipe rather than merely readable.

A telescoping projection is listed because it is a topology fact a pillar-only listing would hide: the index resolves onto the discount curve rather than onto a forward curve of its own, and a reader who saw no row could not tell that from the index being absent.

pub fn with_discount( self, collateral: CollateralSpec, curve: impl Into<PinnedCurve>, ) -> Self

This market with curve pinned as the discount curve for collateral.

§Panics

If curve is a Curve::RepoSpread: a spread is pinned over its base with with_repo_spread, and as a rate curve it would discount off the spread alone.

pub fn with_discount_via( self, currency: Currency, via: Currency, collateral: Currency, ) -> Result<Self, DegenerateHub>

This market with cash flows in currency under a collateral CSA discounted through hub currency via: the key CollateralSpec::under_csa reads D(collateral) · D(currency under via) / D(collateral under via), the three keys a triangulated recipe names, composed at resolution. Nothing is copied, so a later pin of a source moves the key, and its risk lands on the sources.

§Errors

DegenerateHub where via is currency or collateral.

pub fn with_flat_swaption_vol( self, currency: Currency, expiry: NaiveDate, end: NaiveDate, normal_vol: f64, ) -> Self

This market carrying normal_vol as the ATM normal volatility of the currency swaption expiring on expiry into a swap ending on end, under its canonical exogenous label.

pub fn with_projection( self, index: impl Into<String>, curve: impl Into<PinnedCurve>, ) -> Self

This market with curve pinned as the projection curve for index.

§Panics

If curve is a Curve::RepoSpread, as with_discount does.

pub fn with_projection_checked( self, index: impl Into<ProjectionKey>, curve: impl Into<PinnedCurve>, ) -> Result<Self, CurveError>

This market with curve pinned as the projection curve for index, refusing an index the registry does not carry.

The checked form of with_projection. A projection key is drawn from the rate-index registry — the same namespace product construction already validates — so binding a curve under "SOFR", or under a template code such as "USD-SOFR-OIS" where an index name belongs, stores a key no valuation will ever read and fails much later, elsewhere, as a missing curve.

A caller who holds an index value rather than a typed string passes it instead, and no registry lookup happens: see ProjectionKey. Nothing must be registered to pin a curve.

with_projection stays infallible because it sits mid-builder in eighty-five call sites that have the type system and the registry in front of them; this is the form the binding uses, where the caller is naming the index in a string and a refusal is the only way to say so.

It checks the curve’s date as well as its key. A form that validated the index and delegated the date to with_projection would rest the date on an assertion the release profile compiles out, and the caller who reaches this form is exactly the data-driven one the typed refusal exists for.

§Errors

CurveError::UnknownIndex if index is not a registered rate index, naming the registered ones; CurveError::ReferenceDateMismatch if the curve is as of another date than this market.

pub fn with_repo_curve( self, key: impl Into<String>, curve: impl Into<PinnedCurve>, ) -> Self

This market with curve pinned as the repo curve for key.

§Panics

If curve is a Curve::RepoSpread, as with_discount does.

pub fn with_repo_spread( self, key: impl Into<String>, spread: impl Into<PinnedCurve>, over: CurveId, ) -> Self

This market with spread pinned under repo(KEY) as a spread over over — a discount key, or another repo key, so a special can sit over GC and GC over the overnight curve.

Resolving the key composes the chain additively in simple-rate space, 1/P = 1/P_base + Σ s·τ: the base’s parameters report on the base’s own axis and each spread’s on repo(KEY). Replaces whatever the key held, a whole curve included.

§Panics

If spread is not a Curve::RepoSpread or over is neither a discount nor a repo key — a construction error in the caller, refused the way every writer here refuses a misplaced curve.

pub fn repo_discount( &self, key: &str, date: NaiveDate, ) -> Result<f64, PricingError>

The discount factor a trade financed on repo(KEY) reads on date: a spread chain composed additively onto its base, 1/P = 1/P_base + Σ s·τ, exactly as resolution composes it; a whole repo curve as it was pinned. curve reads back what was pinned, which for a spread is the spread over a unit base.

§Errors

Whatever resolution refuses: an absent key, a cycle, a basis mismatch, an undated market, a date before the curve’s reference.

pub fn discount_factor( &self, currency: Currency, collateral: Currency, date: NaiveDate, ) -> Result<f64, PricingError>

The discount factor cash flows in currency under a collateral CSA read on date, exactly as pricing reads it: a triangulated key composed from its three sources, any other key as pinned.

§Errors

Whatever resolution refuses: an absent key or source, a chained triangulation, an undated market, a date before the curve’s reference.

pub fn discount_via( &self, currency: Currency, collateral: Currency, ) -> Option<Currency>

The hub cash flows in currency under a collateral CSA were declared triangulated through, or None for a key held any other way — what a listing needs, beside its discount row, to declare the key again.

pub fn discount_ratio_sources(&self, id: &CurveId) -> Option<[&CurveId; 3]>

The base, numerator and denominator keys id is composed from, where it was declared a triangulated discount.

fn discount_ratio(&self, key: CurveIdRef<'_>) -> Option<[&CurveId; 3]>

The base, numerator and denominator keys key reads, where it was declared a triangulated discount.

pub fn repo_base(&self, key: &str) -> Option<&CurveId>

The base repo(KEY) is declared over, when it holds a spread; None for a whole curve or an absent key.

pub fn with_security_spread( self, key: impl Into<String>, curve: impl Into<PinnedCurve>, ) -> Self

This market with curve pinned as the spread curve for security key.

pub fn curve_refit(&self, id: &CurveId) -> Option<&Arc<CurveRefit>>

What the rate curve pinned under id was calibrated from, when it was pinned from a calibration rather than as a bare curve.

pub fn curve_refits(&self) -> Vec<(CurveId, Arc<CurveRefit>)>

Every rate curve role pinned with a refit, and the refit.

pub fn provenance(&self, id: &CurveId) -> Option<&Arc<CurveProvenance>>

The ladder the curve pinned under id was calibrated from, where it was pinned with one.

pub fn ladder_row( &self, id: &MarketInputId, ) -> Result<(&Arc<CurveProvenance>, usize), RiskError>

The ladder a risk entry’s pillar belongs to, and the row of ∂z/∂q that pillar occupies.

The join is an index, not a search. A CurveNode already carries the CurveId it belongs to and its position in that curve’s flat parameter vector, and a ladder’s rows are in exactly that order — so the row is node_index, and nothing here matches on dates.

Nor does anything fold one role’s pillars onto another’s rows. A Jacobian keyed by (role, date) would need one, because a self-discounting curve read back on a projection axis would have no projection rows to land on. Here CurveId::Discount and CurveId::Projection are distinct identities from the start and a curve serving both is registered under both, sharing one ladder — so each role’s pillars find rows under their own name, and the two roles’ contributions meet in the shared ladder’s columns rather than needing to be routed there.

§Errors

RiskError::NoLadder for a curve pinned without one, RiskError::NoLadderRow for an input that occupies no row — a meeting or turn the pinned step curve does not carry, or an input naming no curve — and RiskError::LadderTooShort if a ladder and its curve came apart after pinning.

pub fn sabr_par_row( &self, id: &MarketInputId, ) -> Result<Vec<(MarketInputId, f64)>, RiskError>

A SABR node’s par row: the grid quotes the fit that built its surface read, each with the node parameter’s derivative in it — the quote Jacobian’s column for that parameter, keyed as the grid would key the quote had it been pinned (RateVolNode / CapVolNode at the quote’s node and strike coordinate; none for an ATM matrix quote).

§Errors

RiskError::NoSabrFit for a surface pinned from parameters, RiskError::NoLadderRow for an input that is not a SABR node of a pinned SABR surface, and RiskError::Pricing for a surface the market does not hold.

fn step_knot_index(&self, curve: &CurveId, knot: &KnotKind) -> Option<usize>

The position of knot among the pillars of the step curve pinned under curve, where it is one and carries it.

pub fn with_credit_curve( self, credit: CreditCurveId, curve: impl Into<PinnedSurvival>, recovery: Option<f64>, ) -> Self

This market with curve pinned as entity’s survival curve, quoted against recovery.

pub fn survival_refit( &self, credit: &CreditCurveId, ) -> Option<&Arc<SurvivalRefit>>

What entity’s survival curve was calibrated from, when it was pinned from a calibration rather than as a bare curve.

pub fn with_base_correlation( self, index: CreditIndexId, curve: Arc<BaseCorrelation>, ) -> Self

This market with curve as the base-correlation curve of index. Each quoted point is a lifted parameter on the Correlation axis, keyed by index and detachment.

pub fn with_inflation_curve( self, key: impl Into<String>, curve: impl Into<PinnedInflation>, ) -> Self

This market with curve pinned as the term structure for price index key.

pub fn has_inflation(&self, key: &str) -> bool

Whether an inflation curve is pinned under key.

The fixings binder asks this. An index print is published into the fixing store under the caller’s own inflation key — the same string with_inflation_curve took, drawn from no registry — and the linker and both inflation swaps read it back under that key. So when a fixing key is validated at publish time, a spelling this market already pins an inflation curve under is the caller’s own namespace, and the market is the only authority on which spellings exist in it.

pub fn has_projection(&self, key: &str) -> bool

Whether this market pins a projection curve under key.

The rate-index sibling of has_inflation: an index bound as a value pins its projection under the name a leg on it carries, drawn from no registry, and a fixing published under that name is what such a leg reads. So a fixing key this market already projects under is the caller’s own namespace, and the market is the authority on which spellings exist in it.

pub fn with_fixings(self, fixings: FixingStore) -> Self

This market with fixings as the prints it was given by hand, each known from this market’s date (or its own, where later) and read over any fetched version: they replace the prints pinned before, and every version a fetch returned is kept.

pub(crate) fn with_fixings_added(self, fixings: &FixingStore) -> Self

This market with fixings added to the prints given by hand, a print already pinned replaced — what a reset step publishes, leaving every other print and every fetched version as it was.

pub fn without_fixings_fetched_on(self, date: NaiveDate) -> Self

This market without the fixing versions a fetch on date learnt, so a fetch at date asks for those prints again — the same-day re-fetch an explain makes, which must see a print restated during the day.

pub(crate) fn with_fixings_fetched( self, prints: &[(String, NaiveDate, f64)], on: NaiveDate, ) -> Self

This market with prints learnt by a fetch on on.

fn refresh_fixings(self) -> Self

The current view re-read from the history.

pub fn with_recipe_quotes( &self, key: &CollateralSpec, sheet: &QuoteSheet, ) -> Result<Self, CalibrationError>

This market with the curves its recipe for key describes solved from sheet and pinned — one statement from a desk’s quote sheet to a market that prices. The recipe says which templates build the curve; the sheet is the grid.

calibrate_recipe under default CalibrationOptions with the solves dropped; a caller who wants the solves, or other options, calls the function.

§Errors

As calibrate_recipe.

pub fn recipe_rungs( &self, key: &CollateralSpec, sheet: &QuoteSheet, ) -> Result<Vec<Rung>, RecipeQuoteError>

The helpers sheet binds to under this market’s recipe for key, in sheet order and unsolved — what with_recipe_quotes solves, for a caller who checks every quote reprices on the market it marked. with_recipe_quotes(key, sheet) is with_curve_helpers(&recipe_rungs(key, sheet)?).

Each rung is built on a notional of one, the default the solve reads; recipe_rungs_at takes another.

§Errors

RecipeQuoteError::NoRecipe where the market carries no recipe under key; otherwise as rungs_for.

pub fn with_curve_helpers( &self, rungs: &[Rung], ) -> Result<Self, CalibrationError>

This market with every curve rungs solve pinned under the roles their instruments declare.

calibrate_curve_helpers under default CalibrationOptions with the solves dropped.

§Errors

As calibrate_curve_helpers.

pub fn with_hull_white( self, currency: Currency, mean_reversion: f64, sigma: impl Into<SigmaPin>, ) -> Self

This market watching the Hull-White parameters for currency: the mean reversion and the volatility the lattice and the analytic engines read, under the canonical labels — a flat volatility under HW-{CCY}-SIGMA, a term under one HW-{CCY}-SIGMA-{date} label per piece. Pinning either spelling removes every label of the other for the currency, so a re-pin never leaves the two side by side. What the Python with_hull_white pins.

pub fn with_credit_crisis( self, credit: &CreditCurveId, rate: f64, jump_mean: f64, default_probability: f64, ) -> Self

This market watching credit’s crises — the rate κ, the mean spread jump m and the probability p a crisis defaults at once — under the canonical labels the repack gap simulation reads. What the Python with_credit_crisis pins.

pub fn with_credit_intensity( self, credit: &CreditCurveId, currency: Currency, mean_reversion: f64, vol: f64, correlation: f64, ) -> Self

This market watching credit’s Gaussian intensity — its mean reversion b, volatility η and correlation ρ with currency’s Hull-White factor — under the canonical labels a correlated repack gap reads. What the Python with_credit_intensity pins.

pub fn with_fx_rate_correlation( self, pair: CurrencyPair, currency: Currency, correlation: f64, ) -> Self

This market with the correlation between the FX pair pair and currency’s Hull-White factor, which a cross-currency repack simulation reads on the correlation axis.

pub fn with_fx_credit_correlation( self, pair: CurrencyPair, credit: &CreditCurveId, correlation: f64, ) -> Self

This market with the correlation between the FX pair pair and the credit entity credit’s intensity.

pub fn with_rate_correlation( self, first: Currency, second: Currency, correlation: f64, ) -> Self

This market with the correlation between two currencies’ Hull-White factors.

pub fn with_fx_rates(self, fx: FxRates) -> Self

This market with fx as its quoted spot rates.

pub fn with_fx_vols(self, surface: FxVolSurface) -> Self

This market carrying surface as the vol surface for its pair.

pub fn with_swaption_vols( self, currency: Currency, surface: impl Into<RateSmile>, ) -> Self

This market carrying surface as the swaption vol surface for currency.

pub fn with_bond_yield_vols( self, key: impl Into<String>, surface: RateVolSurface, ) -> Self

This market carrying surface as the bond yield vol surface under key — a currency code, or the security an option names: expiry × forward-modified-duration, in years.

pub fn with_cap_vols( self, currency: Currency, surface: impl Into<RateSmile>, ) -> Self

This market carrying surface as the cap vol surface for currency: expiry × index tenor, in years, at the money — what a cap or floor reads for each caplet at its fixing.

pub fn with_yoy_vols(self, index: &str, surface: YoyVolSurface) -> Self

This market carrying surface as the year-on-year inflation optionlet vol surface for the price index index (its registry code, as the inflation curve is keyed): expiry × absolute YoY strike — what a YoY caplet, floorlet or collared YoY coupon reads.

pub fn with_cpi_vols(self, index: &str, surface: CpiVolSurface) -> Self

This market carrying surface as the zero-coupon CPI option vol surface for the price index index (its registry code): expiry × annualised zero-coupon strike — what a zero-coupon inflation cap or floor, or a collared CPI notional, reads.

pub fn with_equity_vols( self, name: &str, surface: FutureOptionVolSurface, ) -> Self

This market carrying surface as the option vol surface of the equity name: listed expiry × absolute strike, sticky strike, what every option on the equity reads.

pub fn with_future_option_vols( self, contract: ListedFutureId, surface: FutureOptionVolSurface, ) -> Self

This market carrying surface as the option vol surface of the listed future contract: listed expiry × strike, what every option exercising into that contract reads.

pub fn with_future_price( self, contract: ListedFutureId, price: f64, ) -> Result<Self, MarketDataError>

This market carrying price, per 100 face, as the quoted price of the listed future contract — one lifted parameter on the futures-price axis, what an option on the future reads as its underlying.

§Errors

MarketDataError::Malformed for a price that is not finite and positive.

pub fn with_equity_spot( self, name: impl Into<String>, price: f64, ) -> Result<Self, MarketDataError>

This market carrying price as the quoted spot of the equity name — one lifted parameter on the equity axis.

§Errors

MarketDataError::Malformed for a price that is not finite and positive.

pub fn with_credit_vols( self, credit: CreditCurveId, surface: CreditVolSurface, ) -> Self

This market carrying surface as the credit vol surface for name — a single name’s entity or an index’s code: the Black vol of the forward spread by expiry, what a CDS option on it reads.

pub fn with_basket_correlation( self, key: impl Into<String>, correlation: f64, ) -> Result<Self, CurveError>

This market carrying a basket’s asset correlation under key — the correlation an nth-to-default basket on on_market_correlation reads — as one lifted parameter on the correlation axis.

§Errors

CurveError::Malformed for a correlation outside [0, 1).

pub fn basket_correlation(&self, key: &str) -> Option<f64>

The basket correlation pinned under key, if any.

pub fn with_cms_spread_correlation( self, index: &str, other: &str, correlation: impl Into<CmsSpreadCorrelationCurve>, ) -> Result<Self, CurveError>

This market carrying the correlation between two swap indices’ rates — what a CMS spread coupon on CmsSpreadCorrelation::Market on those indices reads — as lifted parameters on the correlation axis. index and other are swap-index codes (SwapIndex::code, e.g. EUR-EURIBOR-6M-IRS-10Y), in either order: a correlation is symmetric, so the pair is one mark. correlation is one number (an f64 converts to the flat mark, one parameter) or a CmsSpreadCorrelationCurve by option expiry, one parameter per pillar, which a coupon reads at its fixing’s expiry.

§Errors

CurveError::Malformed for a correlation outside [-1, 1].

pub fn cms_spread_correlation( &self, index: &str, other: &str, ) -> Option<&CmsSpreadCorrelationCurve>

The CMS spread correlation pinned for the swap indices index and other, in either order, if any — the flat mark or the term structure.

pub fn cms_spread_correlations( &self, ) -> impl Iterator<Item = ((&str, &str), &CmsSpreadCorrelationCurve)> + '_

Every CMS spread correlation pinned, as ((first, second), curve) in the market’s pair order.

pub fn with_recovery_floor( self, index: CreditIndexId, floor: f64, ) -> Result<Self, CreditError>

This market carrying a credit index’s Amraoui–Hitier recovery floor — what a tranche on on_market_recovery_floor reads — as one lifted parameter on the recovery axis. key is the index id the index’s base correlation is keyed by (CdoTranche::index, e.g. CDX.NA.IG.46). A tranche refuses a floor above its mean recovery when it prices.

§Errors

CreditError::RecoveryFloor for a floor outside [0, 1).

pub fn recovery_floor(&self, index: &CreditIndexId) -> Option<f64>

The recovery floor pinned for the credit index key, if any.

pub fn with_copula_dof( self, index: CreditIndexId, factor_dof: f64, idiosyncratic_dof: f64, ) -> Result<Self, CreditError>

This market carrying a credit index’s double-t degrees of freedom — what a tranche on on_market_copula_dof reads — as two lifted parameters on the correlation axis, the factor’s and each name’s. key is the index id, as for with_recovery_floor.

§Errors

CreditError::DegreesOfFreedom naming the first value not in (2, ∞).

pub fn copula_dof(&self, index: &CreditIndexId) -> Option<(f64, f64)>

The degrees of freedom (factor, idiosyncratic) pinned for the credit index key, if any.

pub fn pin_input(self, label: impl Into<String>, value: f64) -> Self

This market watching a named scalar as a differentiable input.

The generalisation of a scenario-shock magnitude: anything a caller wants a derivative with respect to that is not a curve parameter, a fixing or a spot. It has no natural bump unit, so it belongs to no delta axis and reports on its own.

pub fn fixings(&self) -> &FixingStore

The published observations as known on this market’s date: for each print dated on or before it, the latest version known on or before it. What a valuation, a calibration and a refit read.

pub fn fixing_history(&self) -> &FixingHistory

Every print the market has seen, every version with the date it was known on.

pub fn fixing( &self, index: &str, date: NaiveDate, ) -> Result<f64, MarketDataError>

The rate index fixed at on date.

§Errors

The fixing store’s refusal naming the index and the date where no print was published.

pub fn try_fixing(&self, index: &str, date: NaiveDate) -> Option<f64>

The rate index fixed at on date, or None if it was never published — for deciding whether a reset has been observed, where absence is an ordinary answer rather than a failure.

pub fn fx(&self) -> &FxRates

The quoted spot rates.

pub fn curves(&self) -> Vec<(CurveId, Arc<Curve>)>

Every curve-shaped input this market holds, by identifier.

What a scenario walks to decide what it shocks. The credit store is reported separately by credit_curves, since a survival curve is a different closed set with a different shock.

pub fn credit_curves(&self) -> Vec<(CreditCurveId, Arc<Survival>, Option<f64>)>

Every credit curve, with the entity it belongs to and the recovery its quote assumes — what re-pinning a shocked one needs.

pub fn inflation_curves(&self) -> Vec<(String, Arc<Inflation>)>

Every inflation curve, with the price-index key it is pinned under — what a scenario walks to shock one.

pub fn pinned_input(&self, label: &str) -> Option<f64>

A watched scalar’s stored value.

fn inputs(&self) -> impl Iterator<Item = Input<'_>>

The lift order. Every stored input, as the lift reads it, in the one sequence the layout, the flattened vector, the input identifiers and the differentiability check are all produced from.

This is the only place the order is written down. The two storeless inputs — fixings and FX spots — are always yielded, even when empty, so a market that later gains a fixing does not move any other input; the marks come last, so a market that gains one moves none either.

fn spans(&self) -> &Arc<[Span]>

Where each input’s parameters sit in the lifted vector, in inputs order.

Computed once per stored state and shared: every lift clones the Arc, and a view checks its layout by pointer before it compares by value.

fn compute_spans(&self) -> Vec<Span>

fn stored_parameters(&self) -> Vec<f64>

Every stored parameter, end to end, in inputs order.

pub fn parameter_count(&self) -> usize

How many free parameters this market holds in total.

pub fn lift<R: Scalar>(&self) -> LiftedMarket<R>

The lift. This market’s parameters in mode R, plus the layout the read-back walks.

Takes &self and returns owned values: the stored market is neither mutated nor copied — only its f64 parameters are converted, which is the one thing an active mode genuinely needs its own copy of. The curves themselves stay where they are and are borrowed by the view.

pub fn lift_seeded<R: Scalar + Seedable>( &self, index: usize, ) -> Result<LiftedMarket<R>, CurveError>

The forward-mode lift. This market’s parameters in mode R, with the parameter at flat index carrying a unit tangent and every other a zero one.

The market is addressed as one flat vector, in input_ids order, so a caller names an input once rather than naming a curve and then an offset into it. That is the shape a one-input, one-output derivative wants: seed, one forward pass, read the tangent off the result. No tape, no recording, no reverse sweep — which is the whole reason a sequential solve does not belong in reverse mode.

§Errors

CurveError::NoSuchParameter if index is past the last lifted parameter.

pub fn lift_directional<R: Scalar + Seedable>( &self, direction: &[f64], ) -> Result<LiftedMarket<R>, CurveError>

The directional forward-mode lift. This market’s parameters in mode R, each carrying the tangent direction gives it.

The generalisation of lift_seeded, and the shape a second-order measure along a direction wants: one forward pass returns the value, the directional first derivative and the directional second derivative together. It is also the only way to differentiate with respect to a curve pinned under two roles, where one stored pillar is two lifted parameters and moving “the pillar” means moving both.

The tangent is set with arithmetic in the mode itself — value + seed(0)·tangent — so no mode needs a second constructor for it.

§Errors

CurveError::ParameterCountMismatch if direction is not exactly as long as this market’s parameter vector.

fn lift_stored_along<R: Scalar + Seedable>( &self, stored: Vec<f64>, direction: &[f64], ) -> Result<LiftedMarket<R>, CurveError>

The directional lift over an already-flattened parameter vector, so the seeded entry point flattens once rather than twice.

pub fn priced<T>( &self, factors: &RiskFactors<'_>, read: impl FnOnce(&PricingView<'_, f64>) -> Result<T, PricingError>, ) -> Result<T, PricingError>

read applied to this market’s resolved view of factors: the lift, the view and the resolution a market-bound read needs, in one call — market.priced(&option.risk_factors()?, |v| option.diagnostics(v)).

§Errors

Whatever the view or the resolution refuses — an undated market, a misdated or missing curve — and whatever read returns.

pub fn view<'a, R: Scalar>( &'a self, lifted: &'a LiftedMarket<R>, ) -> Result<MarketView<'a, R>, PricingError>

A view over this market at lifted’s parameters.

§Errors

PricingError::Curve if lifted was produced from a different market and its layout no longer matches, or — carrying CurveError::ReferenceDateMismatch — if a curve as of another date was bound through an infallible binder and not bound again since.

§

impl MarketContext

pub fn under(&self, scenario: &Scenario) -> Result<MarketContext, ScenarioError>

This market under scenario: every admitted input wrapped in its family’s shock transform, everything else carried through. The receiver is untouched, and the result is a market like any other — value, risk, report and attribution all run against it.

§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.

Trait Implementations§

§

impl Clone for MarketContext

§

fn clone(&self) -> MarketContext

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
§

impl Debug for MarketContext

§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
§

impl PartialEq for MarketContext

The date and the state, and nothing else: the build record and the caches are not what a lift reads. Written once here; the state’s own equality is derived, so a family or input added there is compared without a line.

§

fn eq(&self, other: &Self) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.