Skip to main content

CrossCurrencySwap

Struct CrossCurrencySwap 

pub struct CrossCurrencySwap {
    pub pay: CrossCurrencyLeg,
    pub recv: CrossCurrencyLeg,
    pub fx_spot: f64,
    pub spread_leg: Direction,
    pub resetting_leg: Option<Direction>,
}
Expand description

A cross-currency swap: pay one leg, receive another, principal exchanged at both ends, valued in the pay currency.

With no basis — each currency projecting off its own discount curve — the swap is worth exactly zero at any rate levels: each side is a par floater plus its principal, worth par, and the two par amounts net at spot. What the swap prices is the gap between a currency’s discount and projection curves, and the quoted basis spread that closes it.

A resetting leg has its notional marked to the forward FX rate at every boundary (covered interest parity off the two discount curves), so the principal exposure never drifts from spot; its coupons accrue on the prior boundary’s notional and the notional steps are exchanged at each reset.

Fields§

§pay: CrossCurrencyLeg

The leg paid.

§recv: CrossCurrencyLeg

The leg received.

§fx_spot: f64

The inception spot, in receive units per one pay unit: N_recv = N_pay · fx_spot. The resetting baseline.

§spread_leg: Direction

Which leg quotes the basis spread (Direction::Receive by default).

§resetting_leg: Option<Direction>

Which leg’s notional resets to the forward each period, if any.

Implementations§

§

impl CrossCurrencySwap

pub fn new(pay: CrossCurrencyLeg, recv: CrossCurrencyLeg, fx_spot: f64) -> Self

A constant-notional swap quoting its spread on the receive leg.

pub fn with_mtm_resetting(self, leg: Direction) -> Self

Marks leg’s notional to the forward at every boundary. Its principal becomes the schedule the resets set, so its exchanges come out of the compiled leg.

pub fn from_template( template: &XccySwapTemplate, effective: NaiveDate, termination: NaiveDate, notional: f64, fx_rate: f64, quote: f64, ) -> Result<Self, CrossCurrencyError>

A swap on a registry template: receives the template’s quoted-spread leg on notional carrying spread, pays the other leg on notional × fx_rate, where fx_rate is units of the other leg’s currency per one unit of the quoted leg’s currency — whatever way the template’s FX pair is quoted. A KRW NDCCS quotes its KRW leg, so its fx_rate is USD per KRW: 1.0 / 1385.0 at a market of 1,385 KRW per USD, not 1385.0. A rate inverted that way is refused when the swap is valued.

Each leg follows its own conventions: its schedule from its frequency, calendar, business-day convention, end-of-month flag and generation rule; its payment delay on its calendar; an overnight leg compounded daily on that calendar (the index’s own day count when the registry knows the index); a term leg projected over its registered index window, or the accrual period for a code the registry does not know. Both legs discount under the template’s CSA by CollateralSpec::under_csa. On an MTM template the leg in the FX index’s variable-notional currency resets.

A zero-coupon template builds each leg as one coupon over the whole life paying at termination: a fixed leg accruing simply, or compounded on a BUS/252 day count; an overnight leg compounding its index daily. A final-only template exchanges principal at the end alone.

On a non-deliverable template the leg in the FX source’s reference currency settles in the settlement currency: each coupon converts at a fixing dated by the template’s anchor, each exchange at a fixing the lag before it pays, and an initial exchange at the deal rate — this fx_rate, oriented as the fixing series quotes.

§Errors

CrossCurrencyError for an inclusive accretion mode, an MTM template without an FX index, a currency code that does not parse, a non-deliverable template that resets a notional or has no leg in its settlement currency, or conversions the reference leg refuses.

fn settled_non_deliverably( self, template: &XccySwapTemplate, settlement: &str, anchor: FixingAnchor, quoted_fx: f64, (recv_fx, pay_fx): (Option<&LegFx>, Option<&LegFx>), ) -> Result<Self, CrossCurrencyError>

This swap with every leg not in settlement converting into it, the leg in settlement paying deliverably. quoted_fx is the trade’s fx_rate — other-leg units per quoted-leg unit — the deal rate an initial exchange converts at; (recv_fx, pay_fx) are the receive (quoted) and pay legs’ FX sources.

pub fn on_own_curves(self) -> Result<Self, CrossCurrencyError>

This swap with no CSA: each leg discounted on its own currency’s curve rather than collateralised under the template’s.

§Errors

CrossCurrencyError::OwnCurvesNonDeliverable for a non-deliverable swap, whose legs settle in one currency on its curve.

pub fn non_deliverable_side(&self) -> Option<Direction>

The side whose leg settles non-deliverably, if one does.

fn template_currency( template: &XccySwapTemplate, code: &str, ) -> Result<Currency, CrossCurrencyError>

fn leg_schedule( leg: &XccyLegTemplate, effective: NaiveDate, termination: NaiveDate, ) -> Schedule

A template leg’s accrual schedule from effective to termination: one period for a leg paying once, which has no step to generate by; otherwise generated on the leg’s own conventions, the stub where its generation direction leaves it.

fn leg_from_template( template: &XccySwapTemplate, leg: &XccyLegTemplate, effective: NaiveDate, termination: NaiveDate, notional: f64, quote: f64, csa: Currency, ) -> Result<CrossCurrencyLeg, CrossCurrencyError>

pub fn reversed(self) -> Self

The same trade from the other side: pays what was received and receives what was paid, the spread staying on the leg that quotes it and the resetting leg staying the leg that resets.

pub fn leg(&self, side: Direction) -> &CrossCurrencyLeg

The leg on side.

§

impl CrossCurrencySwap

pub(crate) fn check_agreed_rate<R: Scalar>( &self, view: &PricingView<'_, R>, ) -> Result<(), PricingError>

Refuses an agreed rate that is not positive and finite, or that reads as the market’s inverted: more than ten times away from the spot in its own orientation while its reciprocal is within ten times. Both conditions, so a seasoned trade in a pair that has moved a long way still values.

fn unsupported(entry_point: &'static str) -> PricingError

pub(crate) fn sides<'v, 'a, R: Scalar>( &self, view: &'v PricingView<'a, R>, entry_point: &'static str, ) -> Result<(SideCurves<'v, 'a, R>, SideCurves<'v, 'a, R>), PricingError>

The pay side’s and the receive side’s curves off the view.

pub(crate) fn fx_recv_to_pay<R: Scalar>( &self, view: &PricingView<'_, R>, ) -> Result<R, PricingError>

Pay units per one receive unit, off the FX store.

pub fn reset_notionals<R: Scalar>( &self, view: &PricingView<'_, R>, ) -> Result<Option<Vec<R>>, PricingError>

A resetting leg’s notionals at its boundaries, for every boundary but the last. The first is struck off the deal’s rate: N_base · fx_spot once the swap has started, and before that the deal’s rate carried to the start, N_base · fx_spot · DF_base(t_0)/DF_var(t_0), as every later one is carried to its own reset. Each later one is N_base · S · DF_base(t_i)/DF_var(t_i) — covered interest parity off the market’s spot S and the two discount curves. None when no leg resets.

§Errors

Whatever the discount curves or the spot report, the product error if the view lacks the receive side’s curves, or PricingError::SeasonedReset for a reset after the first that is on or before the valuation date: its rate is a fixing the swap names none for.

fn side_value<R: Scalar>( &self, side: Direction, curves: &SideCurves<'_, '_, R>, resets: Option<&[R]>, view: &PricingView<'_, R>, ) -> Result<R, PricingError>

One side’s value in its own currency, receive-oriented: coupons plus principal, constant or resetting.

fn quoted_leg_marginal<R: Scalar>( &self, resets: Option<&[R]>, fx: R, view: &PricingView<'_, R>, ) -> Result<R, PricingError>

The change in pay-currency value per unit of the quoted leg’s quote — its spread where it floats, its fixed rate where it is fixed: that leg’s annuity — reset-weighted when it resets — converted to the pay currency and signed by the side.

§

impl CrossCurrencySwap

fn non_deliverable_npv<R: Scalar>( &self, side: Direction, view: &PricingView<'_, R>, ) -> Result<R, PricingError>

A non-deliverable swap’s value in its settlement currency: the settlement leg on its own curve, the reference leg converted payment by payment — both under the leg’s rule that a payment due today is settled — received less paid.

fn non_deliverable_par_rate<R: Scalar>( &self, side: Direction, rate: f64, view: &PricingView<'_, R>, ) -> Result<R, PricingError>

The fair fixed rate on a non-deliverable swap’s quoted leg: the value is affine in it, so K − npv / marginal, the marginal the quoted leg’s annuity — converted payment by payment where it is the reference leg. A quoted leg compounding its rate into one payment is not affine in it and is refused by name.

§

impl CrossCurrencySwap

fn npv_in_pay<R: Scalar>( &self, view: &PricingView<'_, R>, ) -> Result<R, PricingError>

A deliverable swap’s recv_side · fx − pay_side, in the pay currency: what the par rate and spread divide by a pay-currency marginal.

pub fn leg_values<R: Scalar>( &self, view: &PricingView<'_, R>, ) -> Result<[(Direction, Currency, R, Currency); 2], PricingError>

Each leg’s value as the holder sees it, pay leg first: its side, its currency, the value and the currency the value is in. A deliverable leg values in its own currency, resets and exchanges included; a non-deliverable swap’s legs both value in the settlement currency. The two convert into npv’s currency and sum to it.

§Errors

As npv.

Trait Implementations§

§

impl Clone for CrossCurrencySwap

§

fn clone(&self) -> CrossCurrencySwap

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 CrossCurrencySwap

§

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

Formats the value using the given formatter. Read more
§

impl PartialEq for CrossCurrencySwap

§

fn eq(&self, other: &CrossCurrencySwap) -> 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.
§

impl<R: Scalar> Priceable<R> for CrossCurrencySwap

§

fn npv(&self, view: &PricingView<'_, R>) -> Result<R, PricingError>

In currency: a deliverable swap’s recv_side · fx − pay_side in the pay currency, converted at spot into the quoted leg’s; a non-deliverable swap’s in its settlement currency.

§

fn par_rate(&self, view: &PricingView<'_, R>) -> Result<R, PricingError>

The fair fixed rate on a fixed quoted leg, K − npv(K) / marginal: the value is exactly affine in the rate, so this is a division. Refused by name where the quoted leg floats and quotes a spread.

§

fn par_spread(&self, view: &PricingView<'_, R>) -> Result<R, PricingError>

The fair basis on the quoted leg, s − npv(s) / marginal: the value is exactly affine in the spread, so this is a division. Refused by name where the quoted leg is fixed and quotes a rate.

§

impl PricingRiskFactors for CrossCurrencySwap

§

fn risk_factors(&self) -> Result<RiskFactors<'_>, PricingError>

The pay leg’s curves are the view’s primary pair, the receive leg’s the second discount and second projection; the spot comes from the FX store.

§

impl Product for CrossCurrencySwap

§

fn restruck_at_spread(&self, spread: f64) -> Option<AnyInstrument>

The quoted leg at spread; None where the quoted leg is fixed and quotes a rate instead.

§

fn restruck_at_rate(&self, rate: f64) -> Option<AnyInstrument>

The quoted leg at the fixed rate rate; None where the quoted leg floats and quotes a spread instead.

§

fn currency(&self) -> Currency

The quoted leg’s currency, whichever side the holder pays — so a trade and its reversed report alike — or the settlement currency a non-deliverable swap values and reports in whichever side its reference leg is on.

§

fn contract_dates(&self) -> Vec<(&'static str, NaiveDate)>

The contract dates the product resolved to, as (name, date) pairs — exactly the dates its stated constructor takes, so a product built through a derived form can be read back and rebuilt through the stated one. Empty for a product with no stated form. No default: every product states which it is — see AnyInstrument::contract_dates.
§

fn legs(&self) -> Option<Vec<&Leg>>

The legs the product itself holds, in a declared order, or None for a product that holds none — see AnyInstrument::legs. No default: every product states which it is.
§

fn final_payment_date(&self) -> Option<NaiveDate>

The date of the product’s final payment, where a calibration rung can be built on it; None for a product no ladder is built from.
§

impl StructuralPartialEq for CrossCurrencySwap

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.