wayfault¶
Wrong-Way Risk (WWR) estimation for counterparty credit risk.
wayfault quantifies the adverse dependence between exposure and counterparty
credit quality — the risk that exposure rises precisely when the counterparty
deteriorates (Wrong-Way Risk), and its favourable mirror, Right-Way
Risk.
It takes a Monte-Carlo exposure cube and a credit curve as inputs and produces:
- baseline (independence-assumption) exposure metrics and CVA,
- a conditional expected exposure given default under a pluggable dependence model,
- a WWR-adjusted CVA and the empirical alpha multiplier \(\alpha = \text{WWR-CVA} / \text{independent-CVA}\),
- ML-based calibration of the dependence parameter,
- WWR/RWR classification and diagnostics.
The library does not generate exposures or bootstrap curves — those are inputs.
Try it live
The Playground runs the real wayfault wheel in your
browser (via WebAssembly/Pyodide) with an interactive dashboard — adjust the
model and watch the CVA, alpha, and exposure charts update live.
Why wayfault¶
Design principles
- Minimal core. The only hard runtime dependency is
numpy. Everything else (pandas,scikit-learn,matplotlib) is an optional extra, imported lazily. - Hexagonal architecture. A pure domain, surrounded by ports (Protocols) and swappable adapters. The dependency rule points inward.
- Deterministic. Same seed ⇒ identical results.
- Typed & tested.
mypy --strictclean,ruffclean, ≥ 90 % coverage on the core.
Install¶
30-second example¶
import numpy as np
from wayfault import estimate_wwr
from wayfault.adapters.outbound.exposure_inmemory import InMemoryExposureSource
from wayfault.adapters.outbound.credit_flat import FlatHazardCreditCurveSource
from wayfault.adapters.outbound.dependence_hullwhite import HullWhiteHazardModel
cube = np.random.default_rng(0).normal(size=(10_000, 12)) + 1.0
tenors = [i / 4 for i in range(1, 13)] # quarterly to 3y
result = estimate_wwr(
exposure=InMemoryExposureSource(cube, tenors),
credit=FlatHazardCreditCurveSource(hazard=0.02, recovery=0.4),
model=HullWhiteHazardModel(b=0.5), # b > 0 -> wrong-way
)
print(result.baseline_cva, result.wwr_cva, result.alpha, result.classification)
Worked example: wrong-way risk on a 5-year swap¶
A realistic end-to-end study, computed by the real library (see
examples/case_study.py)
and rendered below with interactive Plotly
charts. The setup: a 5-year receiver interest-rate swap (humped exposure of
20 000 Monte-Carlo paths over 20 quarterly tenors) facing a BB-rated
counterparty with an upward-sloping hazard curve, discounted at a flat 3 %.
1. Baseline exposure metrics¶
From the exposure cube \(V(t)\) we form the independence-assumption profiles. The expected positive / negative exposure and potential future exposure are
and the effective EPE is the time-weighted running maximum \(\mathrm{EEPE} = \tfrac{1}{T}\sum_i \max_{j\le i}\mathrm{EPE}(t_j)\,\Delta t_i\).
2. Baseline CVA¶
Unilateral CVA integrates discounted expected exposure against the marginal default probability, with loss-given-default \(1-R\):
The counterparty's hazard \(\lambda(t)\) and survival \(S(t)\):
3. The wrong-way adjustment (Hull–White)¶
Under wrong-way risk, default intensity rises with exposure. The canonical Hull–White stochastic-hazard model couples them through
where \(a(t)\) is solved per tenor to reproduce the curve's marginal PDs and \(b\) is the wrong-way knob. The conditional expected exposure given default re-weights each scenario by its model-implied default likelihood, \(w_s \propto e^{\,b\,V_s(t)}\), lifting the exposure profile into the high-exposure tail:
4. Alpha multiplier and EAD¶
The empirical alpha multiplier and the regulatory exposure-at-default view are
Sweeping \(b\) traces how the adjustment turns on — monotone in \(b\), with \(\alpha \ge 1\) for wrong-way (\(b>0\)) and \(\alpha \le 1\) for right-way (\(b<0\)):
5. Where the risk concentrates¶
The per-tenor ratio \(\mathrm{EE}_{\text{cond}}(t)/\mathrm{EPE}(t)\) across the coupling \(b\) shows the adjustment is strongest where exposure peaks — the belly of the swap:
6. Model comparison¶
Different dependence families (Hull–White hazard, Gaussian copula, and the tail-dependent Clayton and Frank copulas) imply different uplifts for the same book:
7. Arbitrage consistency¶
A calibrated model must, integrated over the exposure distribution, reproduce the curve's marginal PDs — otherwise it mis-prices the unconditional default. The Hull–White model's model-implied PDs sit exactly on the target:
Continue with the Getting Started guide, or jump to the API Reference.