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: CrossCurrencyLegThe leg paid.
recv: CrossCurrencyLegThe leg received.
fx_spot: f64The inception spot, in receive units per one pay unit:
N_recv = N_pay · fx_spot. The resetting baseline.
spread_leg: DirectionWhich 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
impl CrossCurrencySwap
pub fn new(pay: CrossCurrencyLeg, recv: CrossCurrencyLeg, fx_spot: f64) -> Self
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
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>
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>
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>
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>
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
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
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
pub fn leg(&self, side: Direction) -> &CrossCurrencyLeg
The leg on side.
§impl CrossCurrencySwap
impl CrossCurrencySwap
pub(crate) fn check_agreed_rate<R: Scalar>(
&self,
view: &PricingView<'_, R>,
) -> Result<(), PricingError>
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>
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>
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>
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>
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>
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
impl CrossCurrencySwap
fn non_deliverable_npv<R: Scalar>(
&self,
side: Direction,
view: &PricingView<'_, R>,
) -> Result<R, PricingError>
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>
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
impl CrossCurrencySwap
fn npv_in_pay<R: Scalar>(
&self,
view: &PricingView<'_, R>,
) -> Result<R, PricingError>
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>
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
impl Clone for CrossCurrencySwap
§fn clone(&self) -> CrossCurrencySwap
fn clone(&self) -> CrossCurrencySwap
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more§impl Debug for CrossCurrencySwap
impl Debug for CrossCurrencySwap
§impl PartialEq for CrossCurrencySwap
impl PartialEq for CrossCurrencySwap
§fn eq(&self, other: &CrossCurrencySwap) -> bool
fn eq(&self, other: &CrossCurrencySwap) -> bool
self and other values to be equal, and is used by ==.§impl<R: Scalar> Priceable<R> for CrossCurrencySwap
impl<R: Scalar> Priceable<R> for CrossCurrencySwap
§fn npv(&self, view: &PricingView<'_, R>) -> Result<R, PricingError>
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>
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>
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
impl PricingRiskFactors for CrossCurrencySwap
§fn risk_factors(&self) -> Result<RiskFactors<'_>, PricingError>
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
impl Product for CrossCurrencySwap
§fn restruck_at_spread(&self, spread: f64) -> Option<AnyInstrument>
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>
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
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)>
fn contract_dates(&self) -> Vec<(&'static str, NaiveDate)>
(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>>
fn legs(&self) -> Option<Vec<&Leg>>
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>
fn final_payment_date(&self) -> Option<NaiveDate>
None for a product no ladder is built from.