Class IsdaCdsModel
CdsPricer. Sources: ISDA CDS Standard Model v1.8.2
(the open-source JPMorgan library, functions JpmcdsCdsContingentLegPV
and JpmcdsFeeLegPV); "ISDA CDS Standard Model proposed numerical
fix" (Markit, 2009); Markit, "The CDS Big Bang" (2009) for the contract
conventions; O'Kane, Modelling Single-name and Multi-name Credit
Derivatives (Wiley 2008), ch. 6.
Contract conventions (all implemented here):
- Coupon dates are the IMM dates 20 Mar, 20 Jun, 20 Sep, 20 Dec. Maturity rolls semi-annually (ISDA, December 2015 rule): a trade dated on or after 20 Mar and before 20 Sep matures on 20 Jun of year + tenor; on or after 20 Sep, 20 Dec of year + tenor; before 20 Mar, 20 Dec of year - 1 + tenor. Maturity is not adjusted.
- Step-in date T+1 calendar day; cash settlement T+3 business days; accrual starts on the last IMM date, business-day adjusted (following), on or before the step-in date.
- Quarterly periods. Accrual and payment dates are adjusted following; the last accrual period ends on maturity + 1 day (the maturity date itself is protected and accrues) and pays on the adjusted maturity. Accrual is ACT/360.
- Business days are Monday to Friday by default (the 2.1
behaviour). Pass
IsdaCdsModel.Conventionswith a holiday calendar (for exampleHolidayCalendars.calendar(Market.NEW_YORK_FED, ...)) to adjust accrual, payment and settlement dates for holidays too.
Model (all times ACT/365F from the trade date, curves as
IsdaCurve, so hazard lambda and forward f are
constant on each segment between the merged node times of the
discount and survival curves). On a segment of length dt starting
with survival Q0 and discount P0, with k = lambda + f:
protection: integral h Q P dt = lambda Q0 P0 (1 - e^{-k dt}) / k
accrual on default, accrued c(t) = a (t - tS):
integral a (t - tS) h Q P dt = a lambda Q0 P0 [ (t0 - tS) (1 - e^{-k dt}) / k
+ (1 - e^{-k dt} (1 + k dt)) / k^2 ]
(the second is the integration by parts of the first; small k uses
the Taylor series). Protection runs from the trade date (step-in minus
one day) to maturity and pays 1 - R at default. Each premium
period pays ACT/360(start, end) at the payment date if the
name survives to end - 1 day, plus the accrued coupon at
default, the accrual rate being a = ACT/360 days / ACT/365 span
on the window [start - 1 day, end - 1 day] (the v1.8.2
observation-offset convention). Present values are divided by P at the
cash-settlement date, so they are amounts paid on that date.
Quoting: cleanUpfront = protection - coupon * (RPV01_dirty -
accrued) is the points upfront the buyer pays per unit notional;
dirtyUpfront = protection - coupon * RPV01_dirty is the cash
that changes hands at settlement. The quoted (conventional) spread is
the par spread of the flat hazard curve that reprices the upfront,
with recovery 40% for standard contracts and fixed coupon 100bp or
500bp.
Half-day accrual on default (optional, IsdaCdsModel.Conventions.halfDayAccrual):
the plain idea is that a default can happen at any time during the
default day, on average at mid-day, and the protection seller is owed
the coupon accrued up to that moment, which the integral above,
counting from the start of the accrual day, sets half a day short.
With the option on, the accrued at default becomes
a (t - tS + 1/730), adding a / 730 * integral h Q P dt
per period (O'Kane 2008, sec. 6.6; R. White, "The Pricing and Risk
Management of Credit Default Swaps, with a Focus on the ISDA Model",
OpenGamma 2013, on the accrual-on-default term). Off by default, which
keeps the 2.1 numbers. The ISDA Standard Model itself includes the
half-day term: the official RFR test grids below match only with it on.
Verification against the official ISDA CDS Standard Model RFR test
grids (cdsmodel.com, USD SOFR 2021-04-26 and 2022-06-21, 7164 rows
each; published reference): with half-day accrual on, a weekends-only
calendar for the 2021 grid and the New York calendar for the 2022 grid,
cash settlement amounts agree within 1e-6 USD on 10mm notional and
clean upfronts within 1e-13. With half-day accrual off the clean
upfront is off by up to 4.6e-5 (about 460 USD on 10mm). The grids are
copyright and not in the repository; IsdaGridVerificationTest
runs when QFL_ISDA_GRID_DIR points at CSVs made by
scripts/isda-grid-to-csv.py, and the swap-curve bootstrap it
needs lives in that test. The in-repo tests also pin the closed-form
segment integrals against Gauss-Legendre quadrature to 1e-10 and the
holiday and half-day variants against an independent re-implementation.
Research lane, deterministic.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic final recordOne CDS contract's dates and terms.static final recordModel conventions beyond the contract terms.static final recordOne premium period of the coupon schedule. -
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final doubleStandard investment-grade coupon, 100bp.static final doubleStandard high-yield coupon, 500bp.static final doubleStandard recovery rate for senior unsecured quoting. -
Method Summary
Modifier and TypeMethodDescriptionstatic LocalDateaccrualStartDate(LocalDate stepInDate) Accrual start for a step-in date: the last adjusted IMM date on or before it.static LocalDateaccrualStartDate(LocalDate stepInDate, BusinessCalendar calendar) Accrual start on a holiday calendar: the last IMM date, adjusted following oncalendar, on or before the step-in date.static doubleAccrued premium fraction at step-in:ACT/360(accrual start, step-in).static LocalDateaddBusinessDays(LocalDate date, int days) Adds Monday-to-Friday business days.static LocalDateadjustFollowing(LocalDate date) Moves a weekend date to the following Monday.static IsdaCurvebootstrap(LocalDate tradeDate, int[] tenorYears, double[] parSpreads, double recovery, IsdaCurve discount) Bootstraps a piecewise-constant hazard curve from par spreads of standard contracts traded today, one node per maturity.static IsdaCurvebootstrap(LocalDate tradeDate, int[] tenorYears, double[] parSpreads, double recovery, IsdaCurve discount, IsdaCdsModel.Conventions conventions) Bootstraps under explicit conventions; the standard contracts are built on the conventions' calendar.static doublecleanUpfront(IsdaCdsModel.Contract c, IsdaCurve discount, IsdaCurve survival) Points upfront per unit notional paid by the protection buyer (clean).static doublecleanUpfront(IsdaCdsModel.Contract c, IsdaCurve discount, IsdaCurve survival, IsdaCdsModel.Conventions conventions) Clean points upfront under explicit conventions.static doubledirtyUpfront(IsdaCdsModel.Contract c, IsdaCurve discount, IsdaCurve survival) Cash settlement amount per unit notional paid by the buyer (dirty).static doubledirtyUpfront(IsdaCdsModel.Contract c, IsdaCurve discount, IsdaCurve survival, IsdaCdsModel.Conventions conventions) Dirty upfront under explicit conventions.static doubleflatHazardForParSpread(IsdaCdsModel.Contract c, double parSpread, IsdaCurve discount) The flat hazard whose par spread equalsparSpread.static doubleflatHazardForParSpread(IsdaCdsModel.Contract c, double parSpread, IsdaCurve discount, IsdaCdsModel.Conventions conventions) Flat hazard for a par spread under explicit conventions.static LocalDatenextImmDate(LocalDate date) The first IMM date (20 Mar/Jun/Sep/Dec) strictly afterdate.static doubleparSpread(IsdaCdsModel.Contract c, IsdaCurve discount, IsdaCurve survival) Par spread: protection over clean risky annuity.static doubleparSpread(IsdaCdsModel.Contract c, IsdaCurve discount, IsdaCurve survival, IsdaCdsModel.Conventions conventions) Par spread under explicit conventions.static LocalDatepreviousImmDate(LocalDate date) The last IMM date on or beforedate(unadjusted).static doubleprotectionLeg(IsdaCdsModel.Contract c, IsdaCurve discount, IsdaCurve survival) Protection leg value per unit notional, paid at cash settlement:(1 - R) integral_0^tM h Q P dt / P(t_cs).static doublequotedSpreadToUpfront(IsdaCdsModel.Contract c, double quotedSpread, IsdaCurve discount) Converts a quoted (conventional) spread to clean points upfront at the contract's coupon: flat hazard calibrated so the par spread is the quote, using the contract's recovery.static doublequotedSpreadToUpfront(IsdaCdsModel.Contract c, double quotedSpread, IsdaCurve discount, IsdaCdsModel.Conventions conventions) Quoted spread to clean upfront under explicit conventions.static doubleriskyAnnuityClean(IsdaCdsModel.Contract c, IsdaCurve discount, IsdaCurve survival) Clean risky annuity: dirty minus the accrued fraction.static doubleriskyAnnuityClean(IsdaCdsModel.Contract c, IsdaCurve discount, IsdaCurve survival, IsdaCdsModel.Conventions conventions) Clean risky annuity under explicit conventions.static doubleriskyAnnuityDirty(IsdaCdsModel.Contract c, IsdaCurve discount, IsdaCurve survival) Dirty risky annuity: the premium leg per unit coupon, including the full current coupon and accrual on default, paid at cash settlement.static doubleriskyAnnuityDirty(IsdaCdsModel.Contract c, IsdaCurve discount, IsdaCurve survival, IsdaCdsModel.Conventions conventions) Dirty risky annuity under explicit conventions (holiday calendar, half-day accrual on default).static List<IsdaCdsModel.Period> The coupon schedule from the accrual start to maturity.static List<IsdaCdsModel.Period> schedule(IsdaCdsModel.Contract c, BusinessCalendar calendar) The coupon schedule with accrual and payment dates adjusted following on a holiday calendar.static IsdaCdsModel.ContractstandardContract(LocalDate tradeDate, int tenorYears, double coupon, double recovery) A standard contract: rolled maturity, IMM accrual start, T+1 step-in and T+3 business-day settlement.static IsdaCdsModel.ContractstandardContract(LocalDate tradeDate, int tenorYears, double coupon, double recovery, BusinessCalendar calendar) A standard contract with settlement and accrual start adjusted on a holiday calendar.static LocalDatestandardMaturity(LocalDate tradeDate, int tenorYears) Standard maturity under the semi-annual roll (20 Jun / 20 Dec).static doubleupfrontToQuotedSpread(IsdaCdsModel.Contract c, double cleanUpfront, IsdaCurve discount) Converts clean points upfront to the quoted spread: flat hazard that reprices the upfront, then its par spread.static doubleupfrontToQuotedSpread(IsdaCdsModel.Contract c, double cleanUpfront, IsdaCurve discount, IsdaCdsModel.Conventions conventions) Clean upfront to quoted spread under explicit conventions.
-
Field Details
-
STANDARD_RECOVERY
public static final double STANDARD_RECOVERYStandard recovery rate for senior unsecured quoting.- See Also:
-
COUPON_100BP
public static final double COUPON_100BPStandard investment-grade coupon, 100bp.- See Also:
-
COUPON_500BP
public static final double COUPON_500BPStandard high-yield coupon, 500bp.- See Also:
-
-
Method Details
-
standardContract
public static IsdaCdsModel.Contract standardContract(LocalDate tradeDate, int tenorYears, double coupon, double recovery) A standard contract: rolled maturity, IMM accrual start, T+1 step-in and T+3 business-day settlement.- Parameters:
tradeDate- trade datetenorYears- tenor in years, 1 to 30coupon- fixed coupon (usuallyCOUPON_100BPorCOUPON_500BP)recovery- recovery rate (usuallySTANDARD_RECOVERY)- Returns:
- the contract
-
standardContract
public static IsdaCdsModel.Contract standardContract(LocalDate tradeDate, int tenorYears, double coupon, double recovery, BusinessCalendar calendar) A standard contract with settlement and accrual start adjusted on a holiday calendar.- Parameters:
tradeDate- trade datetenorYears- tenor in years, 1 to 30coupon- fixed couponrecovery- recovery ratecalendar- business-day calendar- Returns:
- the contract
-
standardMaturity
-
nextImmDate
-
previousImmDate
-
accrualStartDate
-
accrualStartDate
Accrual start on a holiday calendar: the last IMM date, adjusted following oncalendar, on or before the step-in date.- Parameters:
stepInDate- step-in datecalendar- business-day calendar- Returns:
- adjusted accrual start
-
adjustFollowing
-
addBusinessDays
-
schedule
The coupon schedule from the accrual start to maturity.- Parameters:
c- the contract- Returns:
- the periods in order
-
schedule
public static List<IsdaCdsModel.Period> schedule(IsdaCdsModel.Contract c, BusinessCalendar calendar) The coupon schedule with accrual and payment dates adjusted following on a holiday calendar.- Parameters:
c- the contractcalendar- business-day calendar- Returns:
- the periods in order
-
protectionLeg
Protection leg value per unit notional, paid at cash settlement:(1 - R) integral_0^tM h Q P dt / P(t_cs).- Parameters:
c- the contractdiscount- discount curve, base date = trade datesurvival- survival curve, base date = trade date- Returns:
- the protection leg PV
-
riskyAnnuityDirty
public static double riskyAnnuityDirty(IsdaCdsModel.Contract c, IsdaCurve discount, IsdaCurve survival) Dirty risky annuity: the premium leg per unit coupon, including the full current coupon and accrual on default, paid at cash settlement.- Parameters:
c- the contractdiscount- discount curvesurvival- survival curve- Returns:
- dirty RPV01 in years
-
riskyAnnuityDirty
public static double riskyAnnuityDirty(IsdaCdsModel.Contract c, IsdaCurve discount, IsdaCurve survival, IsdaCdsModel.Conventions conventions) Dirty risky annuity under explicit conventions (holiday calendar, half-day accrual on default).- Parameters:
c- the contractdiscount- discount curvesurvival- survival curveconventions- model conventions- Returns:
- dirty RPV01 in years
-
accruedYearFraction
Accrued premium fraction at step-in:ACT/360(accrual start, step-in).- Parameters:
c- the contract- Returns:
- accrued year fraction
-
riskyAnnuityClean
public static double riskyAnnuityClean(IsdaCdsModel.Contract c, IsdaCurve discount, IsdaCurve survival) Clean risky annuity: dirty minus the accrued fraction. -
riskyAnnuityClean
public static double riskyAnnuityClean(IsdaCdsModel.Contract c, IsdaCurve discount, IsdaCurve survival, IsdaCdsModel.Conventions conventions) Clean risky annuity under explicit conventions. -
parSpread
Par spread: protection over clean risky annuity. -
parSpread
public static double parSpread(IsdaCdsModel.Contract c, IsdaCurve discount, IsdaCurve survival, IsdaCdsModel.Conventions conventions) Par spread under explicit conventions. -
cleanUpfront
Points upfront per unit notional paid by the protection buyer (clean). -
cleanUpfront
public static double cleanUpfront(IsdaCdsModel.Contract c, IsdaCurve discount, IsdaCurve survival, IsdaCdsModel.Conventions conventions) Clean points upfront under explicit conventions. -
dirtyUpfront
Cash settlement amount per unit notional paid by the buyer (dirty). -
dirtyUpfront
public static double dirtyUpfront(IsdaCdsModel.Contract c, IsdaCurve discount, IsdaCurve survival, IsdaCdsModel.Conventions conventions) Dirty upfront under explicit conventions. -
quotedSpreadToUpfront
public static double quotedSpreadToUpfront(IsdaCdsModel.Contract c, double quotedSpread, IsdaCurve discount) Converts a quoted (conventional) spread to clean points upfront at the contract's coupon: flat hazard calibrated so the par spread is the quote, using the contract's recovery.- Parameters:
c- the contract (coupon and recovery)quotedSpread- conventional spread, decimal, > 0discount- discount curve- Returns:
- clean upfront per unit notional
-
quotedSpreadToUpfront
public static double quotedSpreadToUpfront(IsdaCdsModel.Contract c, double quotedSpread, IsdaCurve discount, IsdaCdsModel.Conventions conventions) Quoted spread to clean upfront under explicit conventions. -
upfrontToQuotedSpread
public static double upfrontToQuotedSpread(IsdaCdsModel.Contract c, double cleanUpfront, IsdaCurve discount) Converts clean points upfront to the quoted spread: flat hazard that reprices the upfront, then its par spread.- Parameters:
c- the contract (coupon and recovery)cleanUpfront- points upfront per unit notionaldiscount- discount curve- Returns:
- the quoted spread, decimal
-
upfrontToQuotedSpread
public static double upfrontToQuotedSpread(IsdaCdsModel.Contract c, double cleanUpfront, IsdaCurve discount, IsdaCdsModel.Conventions conventions) Clean upfront to quoted spread under explicit conventions. -
flatHazardForParSpread
public static double flatHazardForParSpread(IsdaCdsModel.Contract c, double parSpread, IsdaCurve discount) The flat hazard whose par spread equalsparSpread.- Parameters:
c- the contractparSpread- target spread, decimal, > 0discount- discount curve- Returns:
- the hazard per year
-
flatHazardForParSpread
public static double flatHazardForParSpread(IsdaCdsModel.Contract c, double parSpread, IsdaCurve discount, IsdaCdsModel.Conventions conventions) Flat hazard for a par spread under explicit conventions. -
bootstrap
public static IsdaCurve bootstrap(LocalDate tradeDate, int[] tenorYears, double[] parSpreads, double recovery, IsdaCurve discount) Bootstraps a piecewise-constant hazard curve from par spreads of standard contracts traded today, one node per maturity.- Parameters:
tradeDate- trade datetenorYears- ascending tenors in yearsparSpreads- par spreads, decimal, > 0recovery- recovery ratediscount- discount curve- Returns:
- the survival curve
-
bootstrap
public static IsdaCurve bootstrap(LocalDate tradeDate, int[] tenorYears, double[] parSpreads, double recovery, IsdaCurve discount, IsdaCdsModel.Conventions conventions) Bootstraps under explicit conventions; the standard contracts are built on the conventions' calendar.- Parameters:
tradeDate- trade datetenorYears- ascending tenors in yearsparSpreads- par spreads, decimal, > 0recovery- recovery ratediscount- discount curveconventions- model conventions- Returns:
- the survival curve
-