Interest Rate Swaps: Pricing and Risk for Quants
A vanilla interest-rate swap exchanges a fixed cash-flow stream for a floating-rate stream, with value determined by discount factors and forward rates rather than a single “swap yield.” The valuation looks elementary only after curve construction, day-count conventions, payment lags, and collateral currency have been specified.
Cash flows and the par rate
Let \(P(0,T)\) be the collateralized discount factor and \(\alphai\) the fixed-leg accrual. For notional \(N\), fixed rate \(K\), and payment dates \(Ti\),
PV_fixed = N K Σ α_i P(0, T_i) = N K A
PV_float = N Σ δ_i F_i P(0, U_i)
For a spot-starting, single-curve swap with no spread, the floating leg telescopes to N(1 - P(0,Tn)). Hence:
K_par = (1 - P(0, Tn)) / A
The formula is a useful check, not permission to ignore conventions. With SOFR compounded in arrears, payment lag, stubs, or different discount and projection curves, explicitly generate every coupon.
| Object | Role |
|---|---|
| OIS curve | discount collateralized USD cash flows |
| Term/SOFR forward curve | project floating coupons |
| Schedule | accrual and payment dates |
| Day count | ACT/360, 30/360, etc. |
| CSA | collateral currency and funding assumptions |
Bootstrap before pricing
Curve bootstrapping turns liquid quotes—deposits, OIS, futures, and swaps—into discount factors or zero rates. Each instrument must reprice to its market quote. Interpolate a quantity that preserves desirable behavior: log discount factors often avoid pathological forward rates better than interpolating zero rates.
def par_swap_rate(discount_factors, accruals):
annuity = np.dot(accruals, discount_factors[1:])
return (1.0 - discount_factors[-1]) / annuity
def swap_pv(notional, fixed_rate, dfs, accruals):
annuity = np.dot(accruals, dfs[1:])
return notional * ((1.0 - dfs[-1]) - fixed_rate * annuity)
This minimal example assumes a shared curve. A multi-curve implementation must project each forward from its forwarding curve and discount it using the OIS curve. The post-2008 basis is economically real, so using one curve can produce mispriced risk even if the initial PV is forced to zero.
Risk: PV01, curve deltas, and gamma
Fixed-leg annuity makes the swap PV01 approximately N A 1e-4; a payer swap has negative PV01 to its fixed coupon but its net market-rate sensitivity requires repricing both legs. Quote PV01, zero-rate DV01, and bucketed risk are different objects. The first shocks the fixed coupon; the second shocks the curve representation; the third allocates sensitivity across curve pillars.
def central_bucketed_dv01(price_fn, curve, pillar, bump=1e-4):
up = curve.bump(pillar, bump)
dn = curve.bump(pillar, -bump)
return (price_fn(dn) - price_fn(up)) / 2
Central bumps reduce truncation error, but risk results depend on the bump shape. A “5Y” bump should identify whether it is a market-quote bump followed by recalibration or a direct zero-rate bump. Only the former maps naturally to hedging instruments.
Hedging and P&L explain
A 10-year swap is exposed to the entire curve: discounting, forwards, and basis. Hedging only its aggregate DV01 with one future leaves twist risk. Build a sensitivity matrix against liquid hedges, solve a constrained least-squares hedge, then test historical and hypothetical curve moves. Liquidity, transaction costs, and roll dates are constraints, not afterthoughts.
Rate swaps also affect multi-asset allocation: a portfolio’s covariance model should distinguish bond beta from curve-factor beta. Robust covariance design is covered in covariance shrinkage.
Key takeaways
- Price swap legs from schedules, discount factors, and forwards—not a generic yield.
- OIS discounting and forwarding curves serve different economic functions.
- Report risks as clearly defined quote or curve shocks, then validate hedges with full revaluation.
Production validation
Every curve build should have instrument-level residual diagnostics: par deposits, futures, and swaps must reprice within a defined tolerance after bootstrapping. A small PV error can imply a material DV01 error if an interpolation or schedule convention is wrong. Reconcile curve pillars and stale quote handling with the market-data team rather than silently carrying forward invalid inputs.
For P&L explain, first isolate realized cash flows, then attribute remaining P&L to curve moves, theta, fixing updates, basis, and model changes. Reprice yesterday’s trade on yesterday’s and today’s curves to make the attribution additive. Residual P&L should be investigated, not assigned automatically to “model noise.”
