Class IsdaRateCurve

java.lang.Object
com.quantfinlib.credit.IsdaRateCurve

public final class IsdaRateCurve extends Object
Builds the discount curve of the ISDA CDS Standard Model from par swap rates (the swap-only RFR curve used by the SOFR-era test grids).

Plain idea. The quoted swaps are priced at par one at a time, shortest first. For each new maturity we search for the one zero rate that makes that swap worth zero, keeping the zero rates already found for the shorter swaps. The result is an IsdaCurve, so it plugs straight into IsdaCdsModel.

Formal statement. With trade date T (the curve base date) and spot S = T + 2 business days, a swap of tenor m months matures at M = MF(S + m months) (modified following). Its fixed leg pays annually on MF(S + 12k months), the last payment on M; a tenor below one year has a single payment. Accrual fractions are ACT/360. The zero rate r_i at t_i = (M - T)/365 solves P(M) + c * sum_k tau_k P(d_k) - P(S) = 0, where P is the IsdaCurve with knots (t_1..t_i, r_1..r_i), linear in r t between knots and flat outside them. The root is found by 200 bisection steps on [-0.5, 1.0], far more than needed to reach double precision.

Worked example. Trade Monday 2021-04-26 on a weekends-only calendar, so spot is 2021-04-28. A 6M swap at 2% matures 2021-10-28 and pays once, 183/360 of the coupon. Its knot sits at 185/365 years, and the zero rate solves P(185/365) (1 + 0.02 * 183/360) = P(2/365); with the flat extrapolation of IsdaCurve both discount factors use the same rate, giving r = ln(1 + 0.02 * 183/360) / (183/365), about 2.0175% (own test, IsdaRateCurveTest).

Evidence. Used with the official ISDA CDS Standard Model RFR grids (cdsmodel.com, USD SOFR 2021-04-26 and 2022-06-21, 7164 rows each), the curve reproduces cash settlement within 1e-6 USD on 10mm notional and clean upfront within 1e-13 (published reference, checked by IsdaGridVerificationTest when QFL_ISDA_GRID_DIR is set). Money-market deposits are not supported: the RFR grids quote swaps only.

  • Method Details

    • bootstrapSwaps

      public static IsdaCurve bootstrapSwaps(LocalDate tradeDate, List<IsdaRateCurve.Swap> swaps, BusinessCalendar calendar)
      Bootstraps the swap-only zero curve.
      Parameters:
      tradeDate - curve base date
      swaps - par swaps in strictly increasing maturity order
      calendar - business calendar for spot, rolls and payment dates
      Returns:
      zero curve with one knot per swap maturity (ACT/365F from trade date)
    • parSwapValue

      public static double parSwapValue(IsdaCurve curve, LocalDate tradeDate, IsdaRateCurve.Swap swap, BusinessCalendar calendar)
      Value per unit notional of a receive-fixed swap on curve under the conventions above, including the notional exchange: zero for a quote the curve was bootstrapped from.
      Parameters:
      curve - discount curve with base date tradeDate
      tradeDate - curve base date
      swap - the swap
      calendar - business calendar
      Returns:
      P(M) + c * sum tau_k P(d_k) - P(S)