Credit & Counterparty Risk

Compute the BA-CVA Fallback Charge

The basic approach charge, with and without CDS hedge recognition, alongside SA-CVA on the same two netting sets.

Counterparties
Hedge on CPTY-AOptional
0 = no hedge recognised

The full charge applies the regulation’s hedge recognition to CPTY-A; the reduced charge does not recognise the CDS hedge.

SimulationOptional
Java source
BaCvaRiskStudio.java

This exact source runs in TeaVM. Form changes update its Java literals and reset manual edits.

import com.nablatensor.cva.BaCva;
import com.nablatensor.cva.BaCvaParameters;
import com.nablatensor.cva.BaCvaResult;
import com.nablatensor.cva.CollateralAgreement;
import com.nablatensor.cva.CreditName;
import com.nablatensor.cva.CvaHedge;
import com.nablatensor.cva.CvaMarket;
import com.nablatensor.cva.CvaResult;
import com.nablatensor.cva.CvaRiskFactors;
import com.nablatensor.cva.ExposureSimulation;
import com.nablatensor.cva.HazardCurve;
import com.nablatensor.cva.InterestRateSwap;
import com.nablatensor.cva.NettingSet;
import com.nablatensor.cva.SaCva;
import com.nablatensor.cva.SaCvaParameters;
import com.nablatensor.cva.SaCvaSensitivities;
import com.nablatensor.risk.Sensitivities;
import java.util.List;

public final class BaCvaRiskStudio {
  public static void main(String[] args) {
    double r0 = 0.0200000000000, hazardA = 150 / 10000.0, hazardB = 110 / 10000.0, recovery = 40 / 100.0,
        hedgeNotional = 1500000.00000;
    long paths = 3000L, seed = 20260902L;
    int steps = 20;
    CreditName a = CreditName.of()
        .id("CPTY-A")
        .curve(HazardCurve.fromFlatSpread(hazardA * 10000.0, recovery, 10.0))
        .recovery(recovery)
        .rating(CreditName.RatingEnum.BBB)
        .sector(CreditName.SectorEnum.FINANCIAL)
        .build();
    NettingSet nsA = NettingSet.of()
        .id("NS-CPTY-A")
        .counterparty(a)
        .trades(List.of(InterestRateSwap.of()
        .id("A-SWAP-PAY")
        .side(InterestRateSwap.SideEnum.PAY_FIXED)
        .notional(100000000.0)
        .fixedRate(0.02)
        .startYears(0.0)
        .maturityYears(7.0)
        .accrualYears(0.5)
        .build(), InterestRateSwap.of()
        .id("A-SWAP-REC")
        .side(InterestRateSwap.SideEnum.RECEIVE_FIXED)
        .notional(40000000.0)
        .fixedRate(0.036)
        .startYears(0.0)
        .maturityYears(5.0)
        .accrualYears(0.5)
        .build()))
        .collateral(CollateralAgreement.uncollateralised())
        .build();
    CreditName b = CreditName.of()
        .id("CPTY-B")
        .curve(HazardCurve.fromFlatSpread(hazardB * 10000.0, recovery, 10.0))
        .recovery(recovery)
        .rating(CreditName.RatingEnum.A)
        .sector(CreditName.SectorEnum.CORPORATE)
        .build();
    NettingSet nsB = NettingSet.of()
        .id("NS-CPTY-B")
        .counterparty(b)
        .trades(List.of(InterestRateSwap.of()
        .id("B-SWAP-PAY")
        .side(InterestRateSwap.SideEnum.PAY_FIXED)
        .notional(75000000.0)
        .fixedRate(0.022)
        .startYears(0.0)
        .maturityYears(7.0)
        .accrualYears(0.5)
        .build()))
        .collateral(CollateralAgreement.dailyMargined(2000000.0))
        .build();
    CvaMarket market = CvaMarket.of()
        .r0(r0)
        .hwLevel(r0)
        .hwMeanReversion(0.03)
        .hwSigma(0.01)
        .hazardShort(hazardA)
        .hazardMid(hazardA)
        .hazardLong(hazardA)
        .recovery(recovery)
        .fxSpot(1.1)
        .fxVol(0.12)
        .fxForeignRate(0.024)
        .build();
    ExposureSimulation simA = ExposureSimulation.of(nsA, steps)
        .on("cpu")
        .fp64(true);
    CvaResult resultA = simA.run(market, paths, seed);
    CvaMarket marketB = CvaMarket.of()
        .r0(r0)
        .hwLevel(r0)
        .hwMeanReversion(0.03)
        .hwSigma(0.01)
        .hazardShort(hazardB)
        .hazardMid(hazardB)
        .hazardLong(hazardB)
        .recovery(recovery)
        .fxSpot(1.1)
        .fxVol(0.12)
        .fxForeignRate(0.024)
        .build();
    ExposureSimulation simB = ExposureSimulation.of(nsB, steps)
        .on("cpu")
        .fp64(true);
    CvaResult resultB = simB.run(marketB, paths, seed + 1);
    BaCvaParameters bp = BaCvaParameters.standard();
    double alpha = bp.alpha();
    BaCva calc = new BaCva(bp);
    BaCva.Exposure ea = new BaCva.Exposure(a, nsA.effectiveMaturityYears(), alpha * resultA.expectedPositiveExposure());
    BaCva.Exposure eb = new BaCva.Exposure(b, nsB.effectiveMaturityYears(), alpha * resultB.expectedPositiveExposure());
    BaCvaResult reduced = calc.charge(List.of(ea, eb), List.of());
    CvaHedge hedge = CvaHedge.of()
        .kind(CvaHedge.KindEnum.SINGLE_NAME_CDS)
        .referenceId("CPTY-A")
        .notional(hedgeNotional)
        .maturityYears(7.0)
        .riskWeight(0.05)
        .correlation(1.0)
        .build();
    BaCvaResult full = calc.charge(List.of(ea, eb), hedge.notional() > 0 ? List.of(hedge) : List.of());
    // Reuse the same exposures and charge implementation; do not rerun Monte Carlo for the sweep.
    if (hedge.kind() == CvaHedge.KindEnum.SINGLE_NAME_CDS && hedge.referenceId()
        .equals(a.id())) {
      double scvaA = reduced.scvaByCounterparty()
          .get(a.id()), scvaB = reduced.scvaByCounterparty()
          .get(b.id());
      double unit = hedge.riskWeight() * hedge.maturityYears() * hedge.supervisoryDiscount();
      double maxNotional = Math.max(1000000.0, Math.max(2.0 * hedge.notional(), unit > 0 ? 2.0 * (Math.abs(scvaA)
          + Math.abs(scvaB)) / unit : 0.0));
      for (int i = 0; i <= 80; i++) {
        double notional = maxNotional * i / 80.0;
        CvaHedge trial = CvaHedge.of()
            .kind(hedge.kind())
            .referenceId(hedge.referenceId())
            .notional(notional)
            .maturityYears(hedge.maturityYears())
            .riskWeight(hedge.riskWeight())
            .correlation(hedge.correlation())
            .build();
        BaCvaResult point = calc.charge(List.of(ea, eb), List.of(trial));
        System.out.println("BA_SWEEP|" + notional + "|" + point.reduced() + "|" + point.full());
      }
      System.out.println("BA_SELECTED|" + hedge.notional() + "|" + full.reduced() + "|" + full.full());
      System.out.println("BA_COUNTERPARTY|CPTY-A|" + scvaA + "|" + (scvaA - hedge.correlation() * hedge.discountedWeightedNotional()));
      System.out.println("BA_COUNTERPARTY|CPTY-B|" + scvaB + "|" + scvaB);
    }
    CvaRiskFactors ka = new CvaRiskFactors("USD", a, "EURUSD"), kb = new CvaRiskFactors("USD", b,
        "EURUSD");
    Sensitivities sens = SaCvaSensitivities.adjoint(resultA, ka)
        .plus(SaCvaSensitivities.adjoint(resultB, kb));
    double sa = new SaCva(SaCvaParameters.demo())
        .charge(sens)
        .total();
    System.out.println("RESULT|" + resultA.value() + "|" + resultB.value() + "|" + reduced.reduced()
        + "|" + full.full() + "|" + sa + "|" + resultA.sweepSeconds() + "|" + resultB.sweepSeconds()
        + "|" + reduced.scvaByCounterparty()
        .get("CPTY-A") + "|" + reduced.scvaByCounterparty()
        .get("CPTY-B"));
  }
}
TeaVM compiles and runs the Java source above in this browser.

Results from a precomputed Java run.

BA-CVA charge (full, hedged)286,411
BA-CVA reduced (unhedged)618,589hedge benefit 332,178
SA-CVA (comparison)74,045
Portfolio CVA110,910
CounterpartySCVA_cCVA
CPTY-A617,117109,479
CPTY-B5,7861,431

Precomputed Java adjoint exposure sweeps: 0.259s + 0.120s.

Capital versus CDS notional

Vary the CDS on CPTY-A while holding both exposure inputs, parameters and other hedge settings fixed. The full charge retains an unhedged component; excessive protection can increase it. Hover over a curve point for its amounts.

  • Full K
  • Reduced K (unhedged)
  • Chosen CDS notional

Scroll horizontally to see all chart labels on narrow screens.

Capital versus CDS notionalJava calculated 81 hedge sizes with fixed exposures. At the chosen notional of 1.500 $m, full K is 0.286 $m and reduced K is 0.619 $m. All K values precede the Basel scalar.00.1720.3440.5160.68801.052.113.164.22K ($m)Single-name CDS notional ($m)CDS 0.000 $m; full K 0.619 $m; reduced K 0.619 $mCDS 0.053 $m; full K 0.607 $m; reduced K 0.619 $mCDS 0.105 $m; full K 0.595 $m; reduced K 0.619 $mCDS 0.158 $m; full K 0.584 $m; reduced K 0.619 $mCDS 0.211 $m; full K 0.572 $m; reduced K 0.619 $mCDS 0.264 $m; full K 0.560 $m; reduced K 0.619 $mCDS 0.316 $m; full K 0.549 $m; reduced K 0.619 $mCDS 0.369 $m; full K 0.537 $m; reduced K 0.619 $mCDS 0.422 $m; full K 0.525 $m; reduced K 0.619 $mCDS 0.475 $m; full K 0.513 $m; reduced K 0.619 $mCDS 0.527 $m; full K 0.502 $m; reduced K 0.619 $mCDS 0.580 $m; full K 0.490 $m; reduced K 0.619 $mCDS 0.633 $m; full K 0.478 $m; reduced K 0.619 $mCDS 0.686 $m; full K 0.467 $m; reduced K 0.619 $mCDS 0.738 $m; full K 0.455 $m; reduced K 0.619 $mCDS 0.791 $m; full K 0.443 $m; reduced K 0.619 $mCDS 0.844 $m; full K 0.432 $m; reduced K 0.619 $mCDS 0.896 $m; full K 0.420 $m; reduced K 0.619 $mCDS 0.949 $m; full K 0.408 $m; reduced K 0.619 $mCDS 1.002 $m; full K 0.397 $m; reduced K 0.619 $mCDS 1.055 $m; full K 0.385 $m; reduced K 0.619 $mCDS 1.107 $m; full K 0.373 $m; reduced K 0.619 $mCDS 1.160 $m; full K 0.362 $m; reduced K 0.619 $mCDS 1.213 $m; full K 0.350 $m; reduced K 0.619 $mCDS 1.266 $m; full K 0.338 $m; reduced K 0.619 $mCDS 1.318 $m; full K 0.327 $m; reduced K 0.619 $mCDS 1.371 $m; full K 0.315 $m; reduced K 0.619 $mCDS 1.424 $m; full K 0.303 $m; reduced K 0.619 $mCDS 1.477 $m; full K 0.292 $m; reduced K 0.619 $mCDS 1.529 $m; full K 0.280 $m; reduced K 0.619 $mCDS 1.582 $m; full K 0.268 $m; reduced K 0.619 $mCDS 1.635 $m; full K 0.257 $m; reduced K 0.619 $mCDS 1.687 $m; full K 0.245 $m; reduced K 0.619 $mCDS 1.740 $m; full K 0.233 $m; reduced K 0.619 $mCDS 1.793 $m; full K 0.222 $m; reduced K 0.619 $mCDS 1.846 $m; full K 0.210 $m; reduced K 0.619 $mCDS 1.898 $m; full K 0.198 $m; reduced K 0.619 $mCDS 1.951 $m; full K 0.187 $m; reduced K 0.619 $mCDS 2.004 $m; full K 0.175 $m; reduced K 0.619 $mCDS 2.057 $m; full K 0.164 $m; reduced K 0.619 $mCDS 2.109 $m; full K 0.160 $m; reduced K 0.619 $mCDS 2.162 $m; full K 0.170 $m; reduced K 0.619 $mCDS 2.215 $m; full K 0.182 $m; reduced K 0.619 $mCDS 2.268 $m; full K 0.193 $m; reduced K 0.619 $mCDS 2.320 $m; full K 0.205 $m; reduced K 0.619 $mCDS 2.373 $m; full K 0.216 $m; reduced K 0.619 $mCDS 2.426 $m; full K 0.228 $m; reduced K 0.619 $mCDS 2.478 $m; full K 0.240 $m; reduced K 0.619 $mCDS 2.531 $m; full K 0.251 $m; reduced K 0.619 $mCDS 2.584 $m; full K 0.263 $m; reduced K 0.619 $mCDS 2.637 $m; full K 0.275 $m; reduced K 0.619 $mCDS 2.689 $m; full K 0.286 $m; reduced K 0.619 $mCDS 2.742 $m; full K 0.298 $m; reduced K 0.619 $mCDS 2.795 $m; full K 0.310 $m; reduced K 0.619 $mCDS 2.848 $m; full K 0.321 $m; reduced K 0.619 $mCDS 2.900 $m; full K 0.333 $m; reduced K 0.619 $mCDS 2.953 $m; full K 0.345 $m; reduced K 0.619 $mCDS 3.006 $m; full K 0.356 $m; reduced K 0.619 $mCDS 3.058 $m; full K 0.368 $m; reduced K 0.619 $mCDS 3.111 $m; full K 0.380 $m; reduced K 0.619 $mCDS 3.164 $m; full K 0.392 $m; reduced K 0.619 $mCDS 3.217 $m; full K 0.403 $m; reduced K 0.619 $mCDS 3.269 $m; full K 0.415 $m; reduced K 0.619 $mCDS 3.322 $m; full K 0.427 $m; reduced K 0.619 $mCDS 3.375 $m; full K 0.438 $m; reduced K 0.619 $mCDS 3.428 $m; full K 0.450 $m; reduced K 0.619 $mCDS 3.480 $m; full K 0.462 $m; reduced K 0.619 $mCDS 3.533 $m; full K 0.473 $m; reduced K 0.619 $mCDS 3.586 $m; full K 0.485 $m; reduced K 0.619 $mCDS 3.639 $m; full K 0.497 $m; reduced K 0.619 $mCDS 3.691 $m; full K 0.508 $m; reduced K 0.619 $mCDS 3.744 $m; full K 0.520 $m; reduced K 0.619 $mCDS 3.797 $m; full K 0.532 $m; reduced K 0.619 $mCDS 3.849 $m; full K 0.543 $m; reduced K 0.619 $mCDS 3.902 $m; full K 0.555 $m; reduced K 0.619 $mCDS 3.955 $m; full K 0.567 $m; reduced K 0.619 $mCDS 4.008 $m; full K 0.578 $m; reduced K 0.619 $mCDS 4.060 $m; full K 0.590 $m; reduced K 0.619 $mCDS 4.113 $m; full K 0.602 $m; reduced K 0.619 $mCDS 4.166 $m; full K 0.613 $m; reduced K 0.619 $mCDS 4.219 $m; full K 0.625 $m; reduced K 0.619 $mChosen CDS 1.500 $m; full K 0.286 $m

Chosen CDS: 1.500 $m · Full K: 0.286 $m · Reduced K: 0.619 $m. Indicative parameters; K values precede the Basel 0.65 scalar.

Counterparty inputs before and after hedging

Compare unhedged SCVA with the residual after recognising the selected CDS. CPTY-B is unchanged. Negative residuals indicate overhedging. These inputs undergo correlation aggregation and do not add directly to capital.

  • Unhedged SCVA
  • Residual after CDS

Scroll horizontally to see all chart labels on narrow screens.

Counterparty inputs before and after hedgingCPTY-A: unhedged SCVA 0.617 $m, residual 0.174 $m. CPTY-B: unhedged SCVA 0.006 $m, residual 0.006 $m. These are aggregation inputs, not additive capital allocations.00.1820.3640.5460.728CPTY-ACPTY-A: unhedged SCVA 0.617 $m0.617CPTY-A: residual after CDS 0.174 $m0.174CPTY-BCPTY-B: unhedged SCVA 0.006 $m0.006CPTY-B: residual after CDS 0.006 $m0.006Counterparty aggregation input ($m)
Implementation guide

BA-CVA as a prescribed fallback

The Basic Approach uses supervisory parameters and exposure measures to provide a simpler CVA-capital result than SA-CVA.

Core mechanism

Counterparty exposures are weighted and aggregated according to the prescribed formula, with a defined treatment of eligible hedges. It deliberately does not depend on a bank's full CVA sensitivity model.

Practical workflow

Identify the applicable regulatory approach, map counterparties and maturities correctly, apply the current supervisory parameters, and reconcile scope with the SA-CVA population.

Key details

BA-CVA calculates capital for changes in a portfolio's credit valuation adjustment (CVA). The reduced version ignores hedges; the full version recognises eligible credit hedges. Portfolio CVA is the valuation adjustment itself, so it is a different measure from either capital charge.

This example has two counterparties: an uncollateralised BBB financial firm (CPTY-A) and a daily-margined A-rated corporate (CPTY-B). Simulated expected positive exposure supplies a simplified exposure-at-default input, EAD = 1.4 × expected positive exposure. This is a teaching proxy rather than a complete regulatory exposure calculation.

For each counterparty, the calculator combines EAD, effective maturity, a rating-and-sector risk weight and a supervisory discount factor into stand-alone capital (SCVA). The reduced charge aggregates these amounts with correlation ρ = 0.5. The full charge combines 25% of the reduced charge with 75% of the charge after hedge recognition.

Change the CDS notional to hedge CPTY-A. The reduced charge stays constant because it ignores hedges; the full charge initially falls, then can rise if the hedge becomes too large. The chart reuses the same exposure inputs at every notional, so the hedge sweep does not rerun the simulation.

The expensive step in this demo is generating the exposure paths. Once exposures are available, BA-CVA is a short aggregation calculation. The SA-CVA comparison uses adjoint CVA sensitivities from the same simulated portfolio; its result depends on a different method and parameter set. The example parameters are indicative, and the displayed charges illustrate the calculation rather than provide a regulatory reporting result.

Scope and review point

A simple formula is still regulatory reporting: eligibility, legal scope, parameter version and audit trail are essential.