Credit default swaps
This page follows QuantLib's CDS example, its first two cases: a hazard curve bootstrapped from quoted spreads, then
ISDA's standard model. Its values match that example's output. The sample,
CreditDefaultSwaps.cs, carries QuantLib's notice.
A hazard curve from spreads
Four CDS quoted at 150 bp, from three months to two years, with a recovery of 50% and a flat 1% discount curve. A
SpreadCdsHelper per quote, and a piecewise curve of flat hazard rates bootstrapped through them:
Calendar calendar = new TARGET();
Date today = calendar.Adjust(new Date(15, Month.May, 2007));
var context = new EvaluationContext { EvaluationDate = today };
var discount = new FlatForward(today, 0.01, new Actual365Fixed());
int settlementDays = 1;
double recoveryRate = 0.5;
(Period Tenor, double Spread)[] quotes =
[
(new Period(3, TimeUnit.Months), 0.0150), (new Period(6, TimeUnit.Months), 0.0150),
(new Period(1, TimeUnit.Years), 0.0150), (new Period(2, TimeUnit.Years), 0.0150),
];
var helpers = new List<BootstrapHelper<DefaultProbabilityTermStructure>>();
foreach (var (tenor, spread) in quotes)
{
helpers.Add(new SpreadCdsHelper(spread, tenor, settlementDays, calendar, Frequency.Quarterly,
BusinessDayConvention.Following, DateGenerationRule.TwentiethIMM, new Actual365Fixed(), recoveryRate,
discount, context));
}
var curve = new PiecewiseDefaultCurve<HazardRate, BackwardFlat, IterativeBootstrap>(
today, helpers, new Actual365Fixed(), context);
The curve's nodes and its survival probabilities:
| Node | Hazard rate |
|---|---|
| 2007-05-15 | 0.0299685 |
| 2007-09-20 | 0.0299685 |
| 2007-12-20 | 0.0299613 |
| 2008-06-20 | 0.0299619 |
| 2009-06-22 | 0.0299607 |
| Horizon | Survival probability |
|---|---|
| 1Y | 97.040077% |
| 2Y | 94.175796% |
Each quoted CDS, priced on the curve by the mid-point engine:
Calendar calendar = new TARGET();
Date settlement = calendar.Advance(h.Today, 1, TimeUnit.Days);
foreach (var (tenor, spread) in h.Spreads)
{
Date maturity = calendar.Adjust(settlement + tenor, BusinessDayConvention.Following);
Schedule schedule = new MakeSchedule().From(settlement).To(maturity).WithFrequency(Frequency.Quarterly)
.WithCalendar(calendar).WithTerminationDateConvention(BusinessDayConvention.Unadjusted)
.WithRule(DateGenerationRule.TwentiethIMM).ToSchedule();
var cds = new CreditDefaultSwap(ProtectionSide.Seller, 1e6, spread, schedule, BusinessDayConvention.Following,
new Actual365Fixed());
CreditDefaultSwapResults result = MidPointCdsEngine.Calculate(cds, h.Context, h.Curve, 0.5, h.Discount);
results.Add((Name(tenor), result));
}
| Quote | Fair spread | NPV | Default leg | Coupon leg |
|---|---|---|---|---|
| 3M | 1.500000% | 0.00 | -5177.05 | 5177.05 |
| 6M | 1.500000% | 0.00 | -8841.72 | 8841.72 |
| 1Y | 1.500000% | 0.00 | -16101.8 | 16101.8 |
| 2Y | 1.500000% | 0.00 | -30154.5 | 30154.5 |
Each is worth nothing at its quoted spread, the bootstrap's condition, and its default and coupon legs offset.
ISDA's standard model
ISDA's rate curve from deposits and swaps, a flat hazard rate, and a reference trade, five years of protection bought
on 100 million at 100 bp, priced by IsdaCdsEngine:
// QuantLib's example sets IborCoupon::Settings::createAtParCoupons(), the context's UseAtParCoupons.
var context = new EvaluationContext { EvaluationDate = new Date(21, Month.October, 2014), UseAtParCoupons = true };
var helpers = new List<BootstrapHelper<YieldTermStructure>>();
foreach (var (months, rate) in new[]
{
(1, 0.000060), (2, 0.000450), (3, 0.000810), (6, 0.001840), (9, 0.002560), (12, 0.003370),
})
{
helpers.Add(new DepositRateHelper(rate, new Period(months, TimeUnit.Months), 2, new TARGET(),
BusinessDayConvention.ModifiedFollowing, false, new Actual360(), context));
}
var euribor6M = new Euribor(new Period(6, TimeUnit.Months));
foreach (var (years, rate) in new[]
{
(2, 0.002230), (3, 0.002760), (4, 0.003530), (5, 0.004520), (6, 0.005720), (7, 0.007050),
(8, 0.008420), (9, 0.009720), (10, 0.010900), (12, 0.012870), (15, 0.014970), (20, 0.017000),
(30, 0.018210),
})
{
helpers.Add(new SwapRateHelper(rate, new Period(years, TimeUnit.Years), new TARGET(), Frequency.Annual,
BusinessDayConvention.ModifiedFollowing, new Thirty360(Thirty360Convention.BondBasis), euribor6M, context));
}
var rateCurve = PiecewiseYieldCurve<Discount, LogLinear, IterativeBootstrap>.Create(
0, new WeekendsOnly(), helpers, new Actual365Fixed(), context);
FlatHazardRate defaultCurve = FlatHazardRate.Create(0, new WeekendsOnly(), 0.016739207493630, new Actual365Fixed(),
context);
var schedule = new Schedule(new Date(22, Month.September, 2014), new Date(20, Month.December, 2019),
new Period(3, TimeUnit.Months), new WeekendsOnly(), BusinessDayConvention.Following,
BusinessDayConvention.Unadjusted, DateGenerationRule.CDS, false, context);
var trade = new CreditDefaultSwap(ProtectionSide.Buyer, 100e6, 0.01, schedule, BusinessDayConvention.Following,
new Actual360(), true, true, new Date(22, Month.October, 2014), null, new Actual360(true), true);
CreditDefaultSwapResults result = IsdaCdsEngine.Calculate(trade, context, defaultCurve, 0.4, rateCurve, false,
IsdaCdsEngineNumericalFix.Taylor, IsdaCdsEngineAccrualBias.NoBias, IsdaCdsEngineForwardsInCouponPeriod.Piecewise);
The rate curve at its pillars:
| Pillar | Zero rate | Discount |
|---|---|---|
| 2014-11-24 | 6.08332e-05 | 0.999994 |
| 2014-12-23 | 0.00044368 | 0.999923 |
| 2015-01-23 | 0.000804988 | 0.999793 |
| 2015-04-23 | 0.00184508 | 0.99907 |
| 2015-07-23 | 0.00257462 | 0.998062 |
| 2015-10-23 | 0.00339272 | 0.996594 |
| 2016-10-24 | 0.00221731 | 0.995551 |
| 2017-10-23 | 0.00274915 | 0.991764 |
| 2018-10-23 | 0.00352107 | 0.985986 |
| 2019-10-23 | 0.00451599 | 0.977637 |
| 2020-10-23 | 0.0057249 | 0.966173 |
| 2021-10-25 | 0.00707627 | 0.951562 |
| 2022-10-24 | 0.00847959 | 0.934305 |
| 2023-10-23 | 0.009823 | 0.91529 |
| 2024-10-23 | 0.0110503 | 0.895248 |
| 2026-10-23 | 0.0131302 | 0.85407 |
| 2029-10-23 | 0.0153845 | 0.793724 |
| 2034-10-23 | 0.0176039 | 0.702988 |
| 2044-10-24 | 0.0188487 | 0.567776 |
| Reference trade | Value |
|---|---|
| First period's accrual on 24 October 2014 | 88888.9 |
| NPV | -40991.9 |