Credit Default Swaps (CDS) and Credit Derivatives › Worked Example: Pricing a 5-Year CDS

Michael BrenndoerferNovember 18, 20255 min read
Quantitative FinanceAll chapters
Part 4 of 15Swaps and Credit Derivatives
Chapter 22Credit Default Swaps (CDS) and Credit Derivatives › Worked Example: Pricing a 5-Year CDS
Reading section 8 of 16 · Worked Example: Pricing a 5-Year CDS · 5 minSection 8 of 16 · 5 min

Book contents

Section 8 of 16 · 5 min read

Credit Default Swaps (CDS) and Credit Derivatives › Worked Example: Pricing a 5-Year CDSOne section · Sections in this chapter8 / 16 ↓
Reading tools Definitions & inline links

Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.

Article links

Make inline references clickable

Let's work through a complete example of pricing a CDS contract. We'll calculate the fair spread for a 5-year CDS with quarterly premium payments. This example will demonstrate how the theoretical framework translates into concrete calculations that can be implemented programmatically.

Setup

Assume the following parameters:

In[11]:
Code
import numpy as np

# CDS parameters
maturity_years = 5
payments_per_year = 4
hazard_rate = 0.02  # 2% annual default intensity
recovery_rate = 0.40
risk_free_rate = 0.04
notional = 10_000_000

# Generate payment times
num_payments = maturity_years * payments_per_year
payment_times = np.array(
    [(i + 1) / payments_per_year for i in range(num_payments)]
)
delta_t = 1 / payments_per_year  # Time between payments (0.25 years)
Out[12]:
Console
Number of payment dates: 20
Payment times (years): [np.float64(0.25), np.float64(0.5), np.float64(0.75), np.float64(1.0)] ... [np.float64(4.25), np.float64(4.5), np.float64(4.75), np.float64(5.0)]

Calculate Survival and Discount Factors

In[13]:
Code
# Survival probabilities at each payment date
survival_probs = np.exp(-hazard_rate * payment_times)

# Discount factors (continuous compounding)
discount_factors = np.exp(-risk_free_rate * payment_times)

# Default probabilities for each period
# Q(t_{i-1}) - Q(t_i) = probability of default in period i
survival_probs_prev = np.concatenate([[1.0], survival_probs[:-1]])
default_probs = survival_probs_prev - survival_probs
Out[14]:
Console
Sample survival and discount factors:
------------------------------------------------------------
  Time   Survival Q(t)   Discount D(t)    Default Prob
------------------------------------------------------------
  0.25          0.9950          0.9900          0.0050
  1.00          0.9802          0.9608          0.0049
  2.00          0.9608          0.9231          0.0048
  3.00          0.9418          0.8869          0.0047
  4.00          0.9231          0.8521          0.0046
  5.00          0.9048          0.8187          0.0045
Out[15]:
Visualization
Line chart showing survival probability, discount factor, and their product plotted over the 5-year CDS payment schedule.
Survival probabilities and discount factors over the 5-year CDS term. Both factors decline over time, with the combined factor reaching approximately 0.74 by year 5, representing the joint impact of credit risk and the time value of money on premium payments.

Calculate the Risky Annuity (Premium Leg Factor)

In[16]:
Code
# Risky annuity: sum of delta_t * Q(t_i) * D(t_i)
risky_annuity = np.sum(delta_t * survival_probs * discount_factors)
pv_1bp = risky_annuity * notional / 10000
Out[17]:
Console
Risky Annuity (RPV01): 4.287380
PV of 1 bp spread on Notional: $4287.38

The risky annuity (RPV01) indicates that for every \1ofannualpremiumtheexpectedpresentvalueofpaymentsisapproximately1 of annual premium the expected present value of payments is approximately \\4.55. This factor accounts for both the time value of money and the probability that the entity survives to make payments. On the full notional, a 1 basis point spread is worth roughly \$4,546.

Calculate the Protection Leg Factor

In[18]:
Code
# Protection leg factor: sum of D(t_i) * [Q(t_{i-1}) - Q(t_i)]
protection_leg_factor = np.sum(discount_factors * default_probs)
Out[19]:
Console
Protection Leg Factor: 0.085962

The protection leg factor represents the present value of receiving \$1 contingent on default. It is calculated by summing the discounted probability of default for each period. This value (~0.057) is the cost of protection before adjusting for the recovery rate.

Calculate the Fair CDS Spread

In[20]:
Code
# Fair spread calculation
loss_given_default = 1 - recovery_rate
fair_spread = (loss_given_default * protection_leg_factor) / risky_annuity

# Convert to basis points
fair_spread_bps = fair_spread * 10000
annual_premium = fair_spread * notional
Out[21]:
Console
==================================================
FAIR CDS SPREAD CALCULATION
==================================================

Inputs:
  Hazard rate: 2.00%
  Recovery rate: 40.00%
  Risk-free rate: 4.00%
  Maturity: 5 years

Results:
  Fair CDS spread: 120.30 basis points
  Annual premium: $120,300.50

The calculation results in a fair spread of approximately 75 basis points. This means the protection buyer must pay 0.75% of the notional annually to equate the expected premium payments with the expected default compensation.

Verify: Check Spread vs. Hazard Rate Approximation

Recall our earlier approximation: s≈λ×(1−R)s \approx \lambda \times (1-R). Let's verify:

In[22]:
Code
# Simple approximation
approx_spread = hazard_rate * (1 - recovery_rate)
approx_spread_bps = approx_spread * 10000
difference = abs(fair_spread_bps - approx_spread_bps)
Out[23]:
Console
Exact fair spread: 120.30 bps
Approximation (λ × LGD): 120.00 bps
Difference: 0.30 bps

The approximation s≈λ(1−R)s \approx \lambda(1-R) is quite accurate. The small difference arises from timing effects: the exact formula accounts for discounting and the precise timing of premium and protection payments.