Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Netting Sets and CSA

NettingSet

NettingSet::new(claims: Vec<ContingentClaim>, policy: Box<dyn DiscountPolicy>)
NettingSet::with_csa_terms(claims: Vec<ContingentClaim>, csa: CsaTerms)

ns.claims() -> &[ContingentClaim]
ns.csa_terms() -> Option<&CsaTerms>
ns.discount_policy() -> &dyn DiscountPolicy

All claims in a netting set are summed per path and date before taking positive/negative parts, so netting benefit is captured. XvaEngine::run requires with_csa_terms; NettingSet::new is for exposure-only runs with a custom policy.

CsaTerms

pub struct CsaTerms {
    collateral_index: MarketIndex,       // discount curve for collateralised cashflows
    collateral_currency: Currency,       // currency of collateral
    credit_spread: f64,                  // flat counterparty hazard rate (if no credit_index)
    recovery: f64,                       // LGD = 1 - recovery
    funding_spread: f64,                 // flat funding spread (fallback)
    funding_spread_curve: Option<FundingSpreadCurve { dates: Vec<Date>, spreads: Vec<f64> }>,
    funding_index: Option<MarketIndex>,  // bootstrapped funding curve
    credit_index: Option<MarketIndex>,   // bootstrapped credit curve, e.g. Credit("CLIENT_A")
}

examples/cva/data/csa_terms.json:

{
  "collateral_index": "SOFR",
  "collateral_currency": "USD",
  "credit_spread": 0.01,
  "recovery": 0.4,
  "funding_index": "TermSOFR3m",
  "funding_spread_curve": {
    "dates": ["2026-11-11", "2028-11-11", "2030-11-11"],
    "spreads": [0.004, 0.005, 0.006]
  }
}

The CSA implies a SingleCurveCSADiscountPolicy::new(collateral_index, collateral_currency): claims in the collateral currency discount on collateral_index; claims in other currencies discount on MarketIndex::Collateral(ccy, collateral_currency), which therefore must have both a bootstrapped curve and an LgmModelConfig.

Selection rules inside the engine:

Field setAggregator
credit_indexCreditCurveCvaFactory with pillar survivals from the bootstrapped credit curve (sensitivities labelled <index>.pillar_i)
otherwiseCvaFactory with \(S(t)=e^{-\text{credit\_spread}\cdot t}\)
funding_indexFundingCurveFvaFactory using the spread between the funding curve and the system curve (labels <funding_index>.<date>)
funding_spread_curveFundingCurveFvaFactory with the explicit term structure (labels funding_spread.<date>)
otherwiseFvaFactory with the flat funding_spread

Building claims

let claims: Vec<ContingentClaim> = swap_trade.into_claims()?;             // IntoContingentClaims
let claim = MakeContingentClaim::default()
    .with_trade_id("MANUAL_1").with_leg_id("fixed").with_payment_date(d)
    .with_currency(Currency::USD).with_notional(1e6).with_side(Side::LongReceive)
    .with_evaluation_strategy(ClaimEvaluationStrategy::Deterministic { amount: 25_000.0 })
    .build()?;

Multiple trades — swaps, cross-currency swaps, FX forwards, options and ScriptedProducts — can share a netting set as long as their currencies are covered by fx_configs.

Multiple netting sets

run(&mut HashMap<String, NettingSet>) simulates a single market model for all sets and produces per-set XvaValues, so counterparties sharing the same market factors are evaluated on identical paths.