website/figures/pipeline-strip.svg.
This chapter requires:
- XVA-01: Expected Exposure EE$(t)$ and EPE
- XVA-02: Netted/collateralised portfolio EE$(t)$ per netting set
No credit background assumed: the CDS spread and the hazard rate are built from scratch here.
By the end, you can compute CVA from an exposure profile and a hazard rate curve, and know which assumptions the formula requires.
The problem CVA solves
You enter a five-year interest rate swap with a corporate counterparty. On day one it is at-the-money, worth zero to both sides. Rates move, the swap becomes valuable to you, and then they default. You close out and recover some fraction of what they owed you, but not all of it.
This is counterparty credit risk, and it creates a loss that has nothing to do with rates moving against you. It is a credit loss caused by the coincidence of two things: your trade being in-the-money and your counterparty being insolvent. CVA is the expected present value of that loss, computed at trade inception and charged as an upfront adjustment to the risk-free price.
With $V^{\text{rf}}$ the risk-free mark-to-market, the price you should quote to a counterparty with non-trivial default risk is:
Deriving the CVA formula
On default you recover a fraction $R$ (the recovery rate) of the amount owed. If your counterparty defaults at $\tau \leq T$ when the trade is worth $V(\tau) > 0$ to you, your loss is $(1 - R) \cdot V(\tau)$. If $V(\tau) \leq 0$, the close-out amount is a claim of the estate on you: you pay it in full and neither lose nor gain. Only the $V(\tau) > 0$ side costs anything, which is why CVA is non-negative. The mirror image, your own default seen from their side, gives rise to DVA.
You do not know when they will default, nor what the trade will be worth when they do, so average over both under $\mathbb{Q}$: over every default date $t$, weighted by the marginal probability $dPD(t)$ that default lands in $[t, t+\mathrm{d}t]$, and over every path the trade can take by then, which is $\text{EE}(t)$ from XVA-01. Discount on the curve $P(0,t)$ of IR-01:
The integral runs over the life of the trade. At each instant, you weight the exposure you are running by the probability of losing it. The $(1-R)$ factor accounts for the partial recovery you receive from the bankruptcy estate.
Why this substitution is legal
That formula compresses three steps, each a place where published derivations quietly cut a corner. None changes the answer; all three change whether you are entitled to it.
Throughout this XVA series, $\tau$ denotes the counterparty's default time (a random variable, distinct from the day-count fraction $\tau_j$ used in the IR series). The loss at default time $\tau$ is $(1-R) \cdot V^+(\tau)$, where $V^+(\tau) = \max(V(\tau), 0)$ is the positive part. Discounting back to today and taking expectations under the risk-neutral measure $\mathbb{Q}$, the discount factor is the genuinely stochastic accumulator $\beta(0,\tau)^{-1} = \exp(-\int_0^\tau r_s\,ds)$, evaluated at the random time $\tau$:
Note the difference between $e^{-\int_0^\tau r_s\,ds}$ (random, depends on the path of $r$ up to the random time $\tau$) and the deterministic curve $P(0,t) = \mathbb{E}^{\mathbb{Q}}\!\bigl[e^{-\int_0^t r_s\,ds}\bigr]$ (a function of a fixed maturity $t$). The substitution of the deterministic $P(0,t)$ for the stochastic accumulator is only legal after we condition on $\tau$ and invoke an independence assumption two steps below.
Condition on the default time $\tau$. The law of total expectation turns the outer expectation into an integral over default dates, weighted by $dPD(t)$:
To pull the bond price out of the conditional expectation we need two assumptions, jointly known as the independence assumption for unilateral CVA: the default time $\tau$ is independent of both the short-rate process $r$ and the exposure process $V$, and (for stochastic-rate models) the rate and exposure processes are themselves independent under $\mathbb{Q}$ (or, equivalently, $V^+(t)$ is interpreted in the $T_t$-forward measure with the $T_t$-forward EE; see Brigo, Morini & Pallavicini 2013, Ch. 13, and Crépey 2015, Ch. 4). Under these assumptions:
Substituting back gives the working formula above.
Every EE number below comes from xvafoundations.pricing.reprice_swap_paths on a Hull-White simulation with $a = 0.05$, $\sigma = 0.007$, seed 42, 5,000 paths, quarterly grid. Those two parameters are asserted, not calibrated: IR-05 and IR-06 are unwritten, so nothing here is a calibration result.
Default probability from the CDS market
The other ingredient is a term structure of default probabilities: risk-neutral ones, implied by the credit default swap market rather than measured from history. The CDS spread $s(T)$ is the annual premium charged to insure against default over $[0, T]$; from it we extract a hazard rate $\lambda(t)$, the instantaneous probability of defaulting in the next instant given survival to $t$.
Under a flat hazard rate, the survival probability to time $t$ is:
The marginal default probability in $[t, t+\mathrm{d}t]$ is then $\mathrm{d}\text{PD}(t) = \lambda e^{-\lambda t}\,\mathrm{d}t$, and for a spread $s$ quoted in decimal form against a recovery rate $R$:
A CDS contract has two legs. The protection leg pays $(1-R)$ at default. The premium leg pays the spread $s$ continuously until default or maturity $T$. At inception, the two legs are equal:
$$\underbrace{(1-R)\int_0^T e^{-(\lambda+r)t}\lambda\,dt}_{\text{protection leg}} = \underbrace{s\int_0^T e^{-(\lambda+r)t}\,dt}_{\text{premium leg}}$$
Under a flat hazard rate $\lambda$ and flat risk-free rate $r$, both integrals share the same kernel $e^{-(\lambda+r)t}$, which cancels. What remains is $(1-R)\lambda = s$, giving $\lambda = s/(1-R)$.
This identity is exact for continuous premium payments and constant $\lambda$. With discrete quarterly payments or a term structure of spreads, it becomes a first-order approximation. For precise calibration, bootstrap piecewise-constant hazard rates from the full CDS curve.
One counterparty carries the rest of this chapter: 5Y CDS at 120 bp, recovery 40%, so $\lambda = 0.0120\,/\,0.60 = 0.020$. That flat hazard also prices the 10Y trade of the maturity comparison below, where ten-year survival is $e^{-0.20} = 81.9\%$. The complementary 18.1% is risk-neutral: it carries the market's default risk premium and sits well above the realised default frequency of a triple-B issuer.
window.CHART_DATA["xva-03-cva"].survival, flat $\lambda = 0.0200$. Vertical axis truncated at 0.900 so the decay is legible; the drops are to scale with each other.
Discretised CVA: a numerical example
In practice the integral is discretised over monitoring dates $t_1 < t_2 < \cdots < t_M = T$, with $\text{PD}(t_{j-1}, t_j) = Q(\tau > t_{j-1}) - Q(\tau > t_j)$:
The trade is a 5-year payer swap, USD 10 million notional, struck at its own par rate of 3.92% so it is worth zero on day one.
window.CHART_DATA["xva-03-cva"], from xvafoundations.xva.cva, seed 42, 5,000 paths. Panel A is the quarterly profile; panels B to D are the five annual monitoring dates. CVA is USD 5,561.30 before rounding.
Adding the printed column gives 5,561.31 against an unrounded USD 5,561.30. Rounding before summing is how a published CVA stops matching its own table, so every total here is rounded once, at the end, from the unrounded profile.
The sum above evaluates $\text{EE}$ and $P(0,\cdot)$ at the right endpoint $t_j$ of each interval $[t_{j-1}, t_j]$, which matches the library implementation in xvafoundations.xva.cva. This right-point quadrature is first-order accurate: halving the step size halves the error. The trapezoidal rule, which averages the contributions at both endpoints of each interval, is second-order accurate and significantly better for smooth EE profiles. In practice, quarterly monitoring dates ($M = 20$ for a 5-year trade) combined with trapezoidal quadrature is standard and sufficient for most portfolios.
What that costs, measured rather than asserted: same paths, same curve, same hazard rate on the quarterly grid gives USD 5,080.39 against the annual grid's USD 5,561.30, an overstatement of 9.5%. Discretisation, not model risk, and its direction is not an accident: the swap pays annually, so each annual node lands just before a payment date, exactly where the sawtooth in EE peaks.
How CVA scales
xvafoundations.xva.cva on the quarterly grid, seed 42, 5,000 paths. Maturity panel: Trade B (5Y) and Trade A (10Y), both USD 10m and struck at their own par rate.
Notional. Exactly linear: $\text{EE}(t)$ is proportional to notional.
Maturity. Super-linear for swaps. EE grows before it decays, so extending maturity adds high-exposure intervals rather than low-exposure ones.
Volatility. Higher volatility typically increases CVA for at-the-money trades. The expected exposure $\text{EE}(t) = \mathbb{E}^{\mathbb{Q}}[\max(V(t), 0)]$ is option-like, so when $\mathbb{E}^{\mathbb{Q}}[V(t)]$ is held fixed, Jensen's inequality on the convex function $x \mapsto x^+$ gives a one-sided benefit from dispersion. The argument is cleanest at-the-money; for a deep in-the-money trade the positive part is approximately linear over the bulk of the distribution, and additional volatility can shift mass into the negative tail (where the max is zero) without proportionally raising the positive tail, so the relationship can weaken or even reverse. The unconditional rule of thumb "more vol, more CVA" should be read as an ATM statement.
Hazard rate. Linear in $\lambda$ at small spreads, sub-linear as they widen: $e^{-\lambda t}$ decays faster and erodes the far-dated exposure you were charging for. Doubling 120 bp to 240 bp multiplies CVA by 1.91 rather than 2, and by 960 bp the compounded factor is 5.87 rather than 8.
Computing CVA in code
compute_cva in xvafoundations.xva.cva takes an EE profile, discount factors, a survival curve and the recovery rate:
from datetime import date
import torch
from xvafoundations.calibration import Stripper
from xvafoundations.conventions import DayCount, year_fraction
from xvafoundations.curves import InterpolationMethod
from xvafoundations.data import sofr
from xvafoundations.instruments import (
build_instruments, initial_rates, pillar_maturities,
)
from xvafoundations.models import HullWhite1F
from xvafoundations.pricing import SwapSpec, reprice_swap_paths
from xvafoundations.xva.exposure import compute_ee, compute_ene
from xvafoundations.xva.cva import compute_cva, compute_dva
torch.set_default_dtype(torch.float64)
# ── Market and model, as in XVA Ch.01: the IR-01 SOFR curve, then
# Hull-White with a = 0.05 and sigma = 0.007 asserted, not calibrated.
specs, valuation_date = sofr.INSTRUMENTS, sofr.VALUATION_DATE
stripper = Stripper(
maturities=torch.tensor(pillar_maturities(specs, valuation_date)),
initial_rates=torch.tensor(initial_rates(specs)),
instrument_factory=lambda c: build_instruments(specs, valuation_date, c),
method=InterpolationMethod.LOGLINEAR,
)
stripper.calibrate()
curve = stripper.get_curve()
model = HullWhite1F(a=0.05, sigma=0.007, curve=curve)
# ── Trade: the 5Y payer swap, USD 10m, annual ACT/360 schedule, struck
# at its own par rate of 3.9200%. Quarterly grid, 5,000 paths, seed 42.
schedule = [
year_fraction(valuation_date,
date(valuation_date.year + 1 + k, 1, 15), DayCount.ACT360)
for k in range(5)
]
par = curve.par_swap_rate(torch.tensor(0.0), torch.tensor(schedule)).item()
spec = SwapSpec(notional=1.0e7, fixed_rate=par,
fixed_payment_times=schedule, pay_fixed=True)
short_rates, times = model.simulate(5000, 20, 5.0, seed=42) # 0.00 .. 5.00
mtm_paths = reprice_swap_paths(model, spec, short_rates, times) # (5000, 21)
ee = compute_ee(mtm_paths) # shape (21,)
ene = compute_ene(mtm_paths) # shape (21,), non-negative
# P(0,t) is the bootstrapped SOFR curve from IR Ch.01, not a flat rate.
discount = curve.zc_price(torch.tensor(0.0), times)
# ── Two credit curves, not one ──────────────────────────────────────
# CVA uses the COUNTERPARTY's spread; DVA uses YOUR OWN.
cpty_hazard = 0.0120 / (1.0 - 0.40) # lambda = s / (1-R), s = 120 bp
own_hazard = 0.0060 / (1.0 - 0.40) # your own name, s = 60 bp
cpty_survival = torch.exp(-cpty_hazard * times)
own_survival = torch.exp(-own_hazard * times)
# ── CVA and DVA ─────────────────────────────────────────────────────
cva = compute_cva(ee, times, discount, cpty_survival, recovery=0.40)
dva = compute_dva(ene, times, discount, own_survival, own_recovery=0.40)
print(f"CVA = USD {cva.item():,.2f}") # CVA = USD 5,080.39
print(f"DVA = USD {dva.item():,.2f}") # DVA = USD 2,508.30
print(f"Bilateral adjustment = USD {(dva - cva).item():,.2f}")
# Bilateral adjustment = USD -2,572.09
Simulation and repricing dominate the listing; CVA itself is tensor arithmetic on the finished profile. The annual table above is the same call on the five nodes $t = 1, \ldots, 5$.
CVA Greeks: sensitivities that matter
CVA is hedged dynamically, not charged and forgotten. Two sensitivities matter most.
CS01 (credit spread delta): the change in CVA for a 1 bp parallel shift in the counterparty's CDS curve, hedged by buying protection. It differentiates the quoted spread $s$, not the hazard rate $\lambda$, and the distinction is not cosmetic. Since $\lambda = s/(1-R)$, the chain rule contributes a $1/(1-R)$ that cancels the $(1-R)$ in front of the integral, and recovery drops out of the leading term:
The $\lambda\bar{T}$ term is what the naive $\text{CVA}/s$ misses: widening the spread also accelerates the survival decay. On the annual grid $\bar{T} = 2.72$ years, so $\lambda\bar{T} = 5.4\%$ and the closed form gives USD 43.83 per basis point against a naive USD 46.34. On the quarterly grid $\bar{T} = 2.46$ years and the answer is USD 40.26 per basis point. Both are the closed form on the published profile, never a bump-and-revalue: a one-sided bump prices a shifted trade rather than a derivative, and its answer moves with the bump size.
window.CHART_DATA["xva-03-cva"]. The check is a central difference at $h = 10^{-5}$ on the same sums, quoted to show the residual, not to price it.
IR Delta: a curve shift moves the mark-to-market on every path, the EE profile, and CVA with it, so the overlay must be hedged jointly with the swap itself. The cross-gamma to credit is wrong-way risk showing up in the Greeks: a payer swap gains value when rates rise, and if the counterparty's spread widens in those same states, CVA rises non-linearly.
Wrong-way risk
Wrong-way risk (WWR) is what the independence assumption buys the formula, and it is often violated: a counterparty is more likely to default precisely when your exposure to them is large.
Formally WWR is a statement about the conditional expectation along the default-time slice, not a static correlation: it arises whenever $\mathbb{E}^{\mathbb{Q}}[V^+(t)\,|\,\tau = t] > \mathbb{E}^{\mathbb{Q}}[V^+(t)]$ (Hull and White 2012, "CVA and Wrong-Way Risk"; Brigo, Morini & Pallavicini 2013, Ch. 13). The factorisation needs independence, not merely zero correlation, which is strictly weaker, so $P(0,t)\,\text{EE}(t)$ stops being a valid substitution and the integral does not factor.
Two ways out. A Gaussian copula of parameter $\rho$ ties the rate driver to the default time: simulate both jointly and average $V^+(t)$ over the default-time slice, at the cost of the factorisation (Brigo, Morini & Pallavicini 2013). Or solve CVA, exposure and intensity as one coupled BSDE, where dependence falls out of the dynamics rather than being imposed, at the cost of regression Monte Carlo (Crépey 2015).
A note on DVA
Everything above is unilateral CVA. You might also default, which is a risk to them; the symmetric adjustment is DVA, Debt Valuation Adjustment. Under full bilateral netting:
xvafoundations.xva.cva and compute_dva on compute_ee and compute_ene, quarterly grid, seed 42, 5,000 paths.
DVA has a sign that feels counterintuitive until you ask whose balance sheet it sits on. Your own credit deteriorating makes your DVA larger, which reduces the value of what you owe: a liability you are less likely to pay in full is worth less to whoever holds it. That is why a bank carrying DVA in P&L books a gain when its own spreads widen. The gain is arithmetically correct and economically unrealisable, since collecting it requires defaulting, which is why Basel III filters it out of CET1.
FVA, the funding valuation adjustment, captures the cost of funding uncollateralised exposures, and it has partially displaced DVA in practitioner thinking.
Scope and limitations
Two assumptions carry everything above. The framework assumes independence between exposure and default probability, so no wrong-way risk: once that fails, $P(0,t)\,\text{EE}(t)$ no longer factors out, and where the dependence runs the wrong way the number here understates the charge. It assumes a constant recovery rate, used identically in $\lambda = s/(1-R)$ and in the loss given default $(1-R)$, which is exactly why $R$ cancels from the leading CS01 term; stochastic recovery breaks that cancellation. FVA, KVA, SA-CVA and the wrong-way-risk models above each relax one of the two and keep this arithmetic underneath.
References
- Gregory, J. (2020). The xVA Challenge (4th ed.). Wiley. The standard practitioner reference.
- Crépey, S. (2015). Counterparty Risk and Funding: A Tale of Two Puzzles. Chapman & Hall/CRC. The BSDE treatment used above.
- Green, A. (2015). XVA: Credit, Funding and Capital Valuation Adjustments. Wiley.
- Brigo, D., Morini, M. & Pallavicini, A. (2013). Counterparty Credit Risk, Collateral and Funding. Wiley. Bilateral CVA, wrong-way risk, the forward-measure argument.
- Hull, J. & White, A. (2012). "CVA and Wrong-Way Risk." Financial Analysts Journal, 68(5), 58-69. The conditional-expectation definition of WWR adopted here.
- Cesari, G., Aquilina, J., Charpillon, N., Filipović, Z., Lee, G. & Manda, I. (2009). Modelling, Pricing, and Hedging Counterparty Credit Exposure. Springer.
- Brigo, D. & Mercurio, F. (2006). Interest Rate Models: Theory and Practice (2nd ed.). Springer.