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), hedgeNotional > 0 ? List.of(hedge) : List.of());
    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.
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

Analysis note — where the heaviest computation in CVA risk capital sits and whether NablaTensor helps. Date: 2026-09-02. §4 is implemented in the nablatensor-cva module and the demo/cva-capital.sh walk-through; the parameter tables are still indicative. Verdict: Strong fit — the widest adjoint-AD margin of any regime covered in these notes. Calculators, not sign-off. This note describes where the computation sits and what NablaTensor could compute — the numbers the rules ask for. Model validation, parameter attestation and regulatory submission stay with the user.

Capital for the risk of mark-to-market losses on the credit valuation adjustment of a derivative portfolio. Two approaches:

Binding dates. With FRTB in each jurisdiction: 🇪🇺 1 Jan 2027 (inside the same CRR3 targeted-relief delegated act), 🇺🇸 2027 phase-in, 🇬🇧 1 Jan 2027. UK Basel 3.1 eliminates all CVA internal models and replaces them with three risk-sensitive standardised methods, so every UK bank with material CVA needs a sensitivities engine — not a Monte-Carlo IMM-CVA model — for capital.

where each exposure path requires a full revaluation of every trade in the netting set at every simulation time step. The cost shape is:

The SA-CVA capital charge then needs CVA delta and vega to every prescribed risk factor — dozens to a few hundred credit-spread, rates, FX, equity and commodity factors. Computed by bump-and-revalue, that is the entire exposure simulation re-run once per risk factor.

The bottleneck is the per-risk-factor re-simulation of the netting-set exposure paths for the SA-CVA sensitivity vector.

Yes — this is where bump-and-revalue is most expensive and adjoint AD wins by the widest margin of any regime covered in these notes.

Scope and review point

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