Repository navigation
Worked Examples
📌 Guide, not policy. tests/expected/ and tests/fixtures/, with docs/methodology/TEST_CASES.md and the catalogue in tests/README.md, govern; these files define the implementation and test specification. Applicable law and official regulatory texts prevail over repository documentation.
The worked examples are the numerical test cases of K-SACCR: five Basel
examples printed in CRE99, whose values are the only published evidence of
v1.0.2, and a set of illustrative cases that show the CRR rules and the engine's
behaviour. Each case is a JSON fixture with one expected file per regime; the
generated module TEST_Cases runs them in Excel through the input sheets.
Status at v1.0.2: version 1.0.2, released on 2026-10-23
(GitHub Release).
The values below are the expected values stored in the repository; the
"template run" column is a saved demonstration-portfolio result, not a new Excel execution. The examples and catalogue mapping below describe v1.0.2; links to main may evolve. The fixed-version fixture and expected-file links below allow reproduction of that baseline. The CRE99 and T15–T28 values are those of 1.0.1; 1.0.2 adds the illustrative clearing, CCP and settled-to-market cases.
| Item | Published CRE99 cases | Illustrative cases |
|---|---|---|
| Currency and scale | CRE99 prints USD thousands; the fixtures hold unscaled USD, the printed figures times 1,000 | The template's figures, labelled EUR (some cases USD) |
| Rounding | CRE99 keeps intermediate results unrounded and rounds the displayed results and the final EAD (CRE99.20) | Full precision |
| Tolerance | Half a unit of the last printed digit: 500 USD for amounts, 0.0005 for a multiplier printed to three decimals, 0.00005 for the delta printed to four, 0 for the MPOR; relative tolerance 0 | As stored on each output: the catalogue's tolerances for T15–T28 (500 USD for T15; 1e-9 relative or 1e-9 to 1e-12 absolute for the others), 0.01 USD absolute and 1e-9 relative for the sum-of-absolutes case, 1e-6 absolute for the format example |
| Valuation date | 2026-09-30 | 2026-09-30 (2026-01-02 for the format example) |
| Tolerance of the 1.0.2 cases | — | As stored on each output, for example 1e-9 for an MPOR or a maturity factor and 1e-6 absolute for an amount, with 1e-9 relative |
| Day count | 365 days a year, except Example 3: DaysPerYear 360 |
365 days a year; 250 business days |
A value matches when |actual − expected| ≤ max(absolute, relative × |expected|),
both bounds stated on every output. A published value is printed in a
registered source with an exact locator; an illustrative value shows a
behaviour and can check regressions or input guards, but does not establish independent numerical validation of regulatory compliance
(reference classes).
All five are Basel (BCBS) cases. The values were checked against CRE99 on
2026-10-09 (Regulatory Sources).
| Test | Case | Quantity | Published | Expected | Locator | Template run |
|---|---|---|---|---|---|---|
| T01 | cre99-example-1.bcbs |
Adjusted notional, EX1-T1 | 78,694 | 78,694,000 | CRE99.29 | 78,693.868 |
| T02 | cre99-example-1.bcbs |
Supervisory delta, EX1-T3 | −0.2694 | −0.2694 | CRE99.32 | −0.269395 |
| T03 | cre99-example-1.bcbs |
Interest-rate add-on | 347 | 347,000 | CRE99.39 | 346.764 |
| T04 | cre99-example-1.bcbs |
EAD | 569 | 569,000 | CRE99.40 | 569.470 |
| T05 | cre99-example-2.bcbs |
Multiplier | 0.965 | 0.965 | CRE99.57 | 0.965208 |
| T06 | cre99-example-2.bcbs |
EAD | 381 | 381,000 | CRE99.58 | 381.238 |
| T07 | cre99-example-3.bcbs |
EAD | 5,406 | 5,406,000 | CRE99.76 | 5,404.620 (see note) |
| T08 | cre99-example-4.bcbs |
Replacement cost | 40 | 40,000 | CRE99.77 | 40 |
| T09 | cre99-example-4.bcbs |
Aggregate add-on | 629 | 629,000 | CRE99.78 | 628.893 |
| T10 | cre99-example-4.bcbs |
EAD | 936 | 936,000 | CRE99.79 | 936.451 |
| T11 | cre99-example-5.bcbs |
MPOR | 14 business days | 14 | CRE99.83 | 14 |
| T12 | cre99-example-5.bcbs |
Aggregate add-on | 1,401 | 1,401,000 | CRE99.95 | 1,400.962 |
| T13 | cre99-example-5.bcbs |
Multiplier | 0.958 | 0.958 | CRE99.96 | 0.958123 |
| T14 | cre99-example-5.bcbs |
EAD | 1,879 | 1,879,000 | CRE99.97 | 1,879.213 |
Units: monetary figures in the Published and Template run columns are USD thousands; monetary Expected figures are unscaled USD. Delta and multiplier are dimensionless; MPOR is in business days. The 500 USD tolerance applies only to the published monetary outputs, not to every row.
T08–T10 are also printed in BCBS 279 Annex 4a, page 29. T02 is printed as −0.2694; the prototype catalogue had rounded it to −0.27. The template's TestCatalogue sheet now uses −0.2694 within 0.00005, as the expected file does (#267).
| Trade | Terms (USD thousands) | MtM |
|---|---|---|
| EX1-T1 | 10-year USD swap, long, notional 10,000, ends 2036-09-27 | 30 |
| EX1-T2 | 4-year USD swap, short, notional 10,000, ends 2030-09-29 | −20 |
| EX1-T3 | Bought 1-into-10-year EUR receiver swaption (a put), notional 5,000, forward 6%, strike 5%, exercise 2027-09-30, underlying ends 2037-09-27 | 50 |
No margin agreement and no collateral: V = 60, RC = 60 and, since V − C > 0, the multiplier is 1 (CRE99.25). The swaption's start date is its exercise date, so its supervisory duration covers the underlying swap. Published: d of T1 = 78,694, δ of T3 = −0.2694, interest-rate add-on 347, EAD 569.
| Trade | Terms (USD thousands) | MtM |
|---|---|---|
| EX2-T1 | Single-name CDS on Firm A, rated AA, protection bought (long), 3 years, notional 10,000 | 20 |
| EX2-T2 | Single-name CDS on Firm B, rated BBB, protection sold (short), 6 years, notional 10,000 | −40 |
| EX2-T3 | CDX.IG 5-year index CDS, protection bought (long), notional 10,000 | 0 |
V = −20, so RC = 0 and the multiplier falls below 1. CRE99 prints Firm B's trade in EUR; the fixture holds every amount already in USD. Published: multiplier 0.965, EAD 381.
| Trade | Terms (USD thousands) | MtM |
|---|---|---|
| EX3-T1 | WTI crude oil forward, long, notional 10,000, residual maturity 9 months | −50 |
| EX3-T2 | Brent crude oil forward, short, notional 20,000, 2 years | −30 |
| EX3-T3 | Silver forward, long, notional 10,000, 5 years | 100 |
V = 20, RC = 20, multiplier 1. WTI and Brent are one commodity type, entered
with the risk factor CRUDE OIL, in the energy hedging set; silver is in
metals. This grouping reproduces the published example; it is not a universal permission to ignore material basis risk between oil products (CRE52.71). Published: EAD 5,406.
📝 5,405 or 5,406. CRE99 prints a residual maturity of 9 months for the WTI trade, MF = sqrt(0.75). The fixture enters that maturity as 270 days with
DaysPerYear360, exactly 0.75 years, and matches 5,406. The demonstration portfolio in the template enters calendar dates over 365 days a year: its WTI trade matures on 2027-07-01, 274 days after the reporting date, so TradeCalc shows M = 0.7507, andBCBS-EX3shows 5,405 (5,404.62 thousand), about 1.4 thousand below the printed figure. The template's TestCatalogue sheet therefore compares T07 within 2 thousand; the fixture keeps the published tolerance of 500 USD.DaysPerYearis a day-count convention and does not make the runWHAT-IF.Different inputs, not an engine rounding error: the fixture gives 5,405,615.98 USD, within 500 USD of the published 5,406,000. The demo gives 5,404,619.69 USD, outside that published tolerance; its
PASSuses a separate 2,000 USD tolerance. That demo result is not evidence of matching the published benchmark within 500 USD. Reproducing the benchmark requires the exact 0.75-year horizon, not changing the engine's rounding.
The six trades of Examples 1 and 2 in one netting set, without collateral. V = 60 − 20 = 40, so RC = 40 (T08) and the multiplier is 1. The aggregate add-on is the sum of the two asset-class add-ons, with no diversification across classes: 629 (T09). Published: EAD 936 (T10).
The six trades of Examples 1 and 3 under a margin agreement:
| Term | Value (USD thousands) |
|---|---|
| Remargining | Weekly, N = 5 business days |
| Threshold TH; MTA | 0; 5 |
| Net independent amount (NICA) | 150 |
| Total net collateral held | 200, of which VM 50 |
| V | 30 − 20 + 50 − 50 − 30 + 100 = 80 |
RC = max(80 − 200, 0 + 5 − 150, 0) = 0. The MPOR is 9 + 5 = 14 business days (CRE99.83, T11), the engine's 10 + 5 − 1, so every trade takes MF = 1.5 × sqrt(14 / 250). With V − C = −120, the published figures are aggregate add-on 1,401 (T12), multiplier 0.958 (T13) and EAD 1,879 (T14). Using displayed, rounded inputs gives 1.4 × (0 + 0.958 × 1,401) = 1,879.0212 thousand, an approximation. The full-precision calculation uses add-on 1,400,962.3796965722 USD and multiplier 0.958123327392663, giving 1,879,212.63 USD. Both round to the published 1,879 thousand; intermediate rounded values must not replace full-precision values in the calculation. The cap at the unmargined EAD does not bind.
The following amounts are unscaled USD, computed from the fixture inputs without rounding intermediates. They are an arithmetic cross-check, not a new Excel run or a newly registered independent expected-value source. Displayed amounts below are rounded to cents; the JSON expected values remain the published rounded benchmarks.
| Example | RC | Aggregate add-on | Multiplier | EAD | Published EAD | Absolute difference |
|---|---|---|---|---|---|---|
| 1 | 60,000.00 | 346,764.39 | 1 | 569,470.14 | 569,000 | 470.14 |
| 2 | 0.00 | 282,128.83 | 0.965208281 | 381,238.32 | 381,000 | 238.32 |
| 3 | 20,000.00 | 3,841,154.27 | 1 | 5,405,615.98 | 5,406,000 | 384.02 |
| 4 | 40,000.00 | 628,893.22 | 1 | 936,450.51 | 936,000 | 450.51 |
| 5 | 0.00 | 1,400,962.38 | 0.958123327 | 1,879,212.63 | 1,879,000 | 212.63 |
For Example 3, the energy add-on is 18% × abs(10,000,000 × sqrt(0.75) − 20,000,000) = 2,041,154.27 USD; the metals add-on is 18% × 10,000,000 = 1,800,000 USD. Add these and apply 1.4 × (20,000 + aggregate add-on). For Example 4, add the unrounded IR and credit add-ons from Examples 1 and 2. Example 5 recomputes the trade effective notionals with MF = 1.5 × sqrt(14 / 250), rather than reusing the unmargined add-ons unchanged.
For all examples, obtain signed effective notionals from adjusted notional ×
supervisory delta × maturity factor, then apply the asset-class aggregation
rules. Credit uses the prescribed systematic and idiosyncratic aggregation;
IR permits offsets within a currency's maturity buckets, not across currencies.
Amounts are already converted into the fixture's calculation currency:
an EUR interest-rate risk-factor label is not a request to convert that
fixture's USD notional again.
| Example | Fixed v1.0.2 inputs | Fixed v1.0.2 Basel expected outputs |
|---|---|---|
| 1 | Fixture | Expected |
| 2 | Fixture | Expected |
| 3 | Fixture | Expected |
| 4 | Fixture | Expected |
| 5 | Fixture | Expected |
The 1.0.2 fixtures add the CCP and settlement fields of the new format, left
blank (null, ordinary); the inputs and expected values are those of 1.0.1.
Official source: CRE99, examples 1–5, including the rounding convention in CRE99.20.
These cases exercise behaviour and can detect regressions; none counts as independent regulatory numerical validation under the project evidence policy. The values of T15–T28
come from hand calculations or from a Python implementation
that is not in the repository; those of the 1.0.2 cases from separate
derivations in tests/derivations/. They stay illustrative unless an external
implementation registered as a source reproduces them
(#100); no
independent review is required. Every CRR value in the suite is illustrative.
| Test | Case | Quantity | Expected | What it shows |
|---|---|---|---|---|
| T15 | cre99-example-5.crr |
EAD | 1,879,000 USD | Example 5 under CRR: the cap does not bind, same EAD as Basel |
| T16 | illustrative-posted-vm-cap.bcbs |
EAD | 40,774,849.34860364 EUR | The cap with C = NICA binds |
| — | illustrative-posted-vm-cap.bcbs |
Cap applied | Y |
|
| T17 | illustrative-posted-vm-cap.crr |
EAD | 40,774,849.34860364 EUR | The same under CRR |
| T18 | illustrative-posted-vm-cap.crr |
Cap applied | Y |
|
| T19 | illustrative-swaption-forward-1pct.crr |
EAD | 760.4939328393385 EUR | Swaption with a 1% forward, λ = 0 |
| T20 | illustrative-negative-ir-forward.crr |
λ, NIR-C | 0.003 | CRR lambda for a negative forward |
| T21 | illustrative-negative-ir-forward.crr |
δ, NIR-C | −0.9941752720429311 | Delta with the shift |
| T22 | illustrative-negative-ir-forward.bcbs |
Status, NIR-C | EXCLUDED |
Basel without an entered λ rejects it |
| T23 | illustrative-negative-commodity-price.crr |
λ, NCO-1 | 5.5 | CRR lambda for a negative commodity price |
| T24 | illustrative-other-risks.crr |
Other-risks add-on | 880 EUR | 8%, hedging set per risk driver |
| T25 | illustrative-other-risks.crr |
EAD | 1,232 EUR | 1.4 × 880 |
| T26 | illustrative-other-risks.bcbs |
Status, OT-1 | EXCLUDED |
No other-risks class under Basel |
| T27 | illustrative-climatic-commodity.crr |
Hedging set, CL-1 | CO|CLIMATIC|STD |
Climatic conditions, own hedging set |
| T28 | illustrative-credit-quality-step.crr |
SF, B03 | 0.0042 | Credit quality step 2 = 0.42% |
The uncatalogued expected files are illustrative-ir-sum-of-absolutes.bcbs,
illustrative-ir-swap-unmargined.bcbs and .crr, and
illustrative-partly-rejected.crr.
A margined netting set (daily remargining, NICA 0, threshold and MTA 0) has posted 1.3 billion EUR of VM against one short 10-year swap, notional 5,845 million, worth −1.1 billion. On the cap basis C = NICA = 0: RC 0, add-on 229,982,829.40, multiplier 0.126639, EAD 40,774,849.35. On the margined basis C = −1.3 billion: RC 200 million, MF 0.3, EAD 376,592,788.35. The cap binds in both regimes. The full arithmetic is on Replacement Cost and Collateral. The scenario comes from the EBA question 2022_6354, rejected without an answer, and is an engineering case, not an authoritative figure.
Example 1's three trades in a CRR netting set, scaled to notionals of 10,000, 10,000 and 5,000 EUR with MtM 30, −20 and 50, and the swaption's forward set to 1% against the 5% strike. Under CRR, λ = max(0.10% − min(1%, 5%), 0) = 0, so the shift changes nothing and the deep in-the-money receiver swaption has a delta near −1. V = 60 gives RC 60 and a multiplier of 1, so the expected EAD of 760.49 corresponds to a PFE of 760.49 / 1.4 − 60 = 483.21. The catalogue cites figures of about 483 and 761 from EBA work on the RTS, a source that was not opened; the value is illustrative.
A bought receiver swaption (a put), notional 10,000 EUR, exercisable on 2027-09-30 into a swap ending 2032-09-28, with forward −0.20% and strike 0.10%.
| Regime | λ | Result |
|---|---|---|
CRR |
max(0.10% − (−0.20%), 0) = 0.30% (T20) | δ = −0.9941752720429311 (T21) |
BCBS |
None entered | P + λ ≤ 0: the trade is EXCLUDED (T22) and the netting set INCOMPLETE: 1 of 1 trade(s) rejected
|
Under Basel, the user enters a λ on the trade (CRE52.40 FAQ2), applying the required consistency across IR options in the same currency and considering supervisory guidance. The engine does not enforce that currency-wide consistency. T22 verifies rejection without a usable shift; it does not show that Basel cannot treat negative rates.
A bought commodity call (oil and gas, WTI), notional 10,000, price −5, strike
−4. Under CRR, λ = max(−(1 + 0.1) × min(−5, −4), 0) = 5.5, so P + λ = 0.5 and
K + λ = 1.5.
Three linear trades in the other-risks class: a longevity swap of 10,000 and an
opposite one of 4,000 on the same index, which share a hedging set, and a
catastrophe-loss swap of 5,000 in its own; all maturities exceed one year and
MtM is 0. Under CRR, add-on = 8% × (|10,000 − 4,000| + |5,000|) = 880 and
EAD = 1.4 × 880 = 1,232, status VALID. Under Basel every trade is
EXCLUDED and the netting set is INCOMPLETE: 3 of 3 trade(s) rejected.
A heating-degree-day swap, notional 1,000, sub-class CLIMATIC, in a CRR
netting set: its hedging set is CO|CLIMATIC|STD, separate from the other
commodity hedging sets, with a factor of 18% (CRR Art. 277a(1)(e)(v),
280e(5)). The 18% was checked against Art. 280e(5) on 2026-10-09; that is a
source check, not a numerical validation. T27 checks the hedging-set key; it does not by itself validate the complete commodity add-on or EAD.
A sold single-name CDS on a name of credit quality step 2 (CQS2), notional
8 million EUR, in a margined CRR netting set: its supervisory factor is
0.42% (CRR Art. 280c(5), Table 3), the factor Basel gives to rating A. T28 checks that factor, not an entire credit-portfolio EAD or the correctness of the reference entity's rating assignment.
The input-validation suite (legs-two-risk-categories, CRR, unmargined) enters
one economic trade E1 as two legs: an equity single-name forward of 10,000
with MtM 30, flagged as the MtM leg, and an EUR/USD forward of 10,000 with MtM 0.
Expected: RC 30, equity add-on 32% × 10,000 = 3,200, FX add-on
4% × 10,000 = 400, multiplier 1, EAD 1.4 × (30 + 3,600) = 5,082, with
one economic trade read and used and two legs. Variants with two MtM legs, the
MtM repeated on the second leg, or no MtM leg reject both legs, and the netting
set is INCOMPLETE: 2 of 2 trade(s) rejected.
| Case | Expected | What it shows |
|---|---|---|
illustrative-ir-sum-of-absolutes.bcbs |
IR add-on 625,153.1562746512 USD; EAD 959,214.4187845117 USD | Example 1 with IRBucketOffset = FALSE: 0.5% × (36,253,849.38 + 78,693,868.06) for USD plus 0.5% × 10,082,913.81 for EUR, against 346,764.39 with offsets |
illustrative-ir-swap-unmargined.bcbs, .crr
|
RC 100,000 EUR | Format example: one 5-year swap worth 100,000 with no collateral |
illustrative-partly-rejected.crr |
PR-1 OK, PR-2 EXCLUDED, netting set INCOMPLETE: 1 of 2 trade(s) rejected
|
A matured trade is rejected and the EAD withheld rather than calculated on the rest |
Thirteen expected files added in 1.0.2, valued on 2026-09-30 in EUR, each
under CRR and BCBS unless stated. Their values come from separate Python
implementations in
tests/derivations/
that share no code with the engine; they are illustrative.
| Case | Netting set | Expected (CRR / BCBS) | What it shows |
|---|---|---|---|
illustrative-clearing-member-listed |
Margined, role CM, daily remargining: a listed equity index future and a bought call expiring with it |
MPOR 5 / 5; RC 80,000; call δ 0.524741; EAD 486,904.87 / 486,904.87 EUR | The clearing member's 5-day floor in both regimes (#359) |
illustrative-clearing-client-listed |
The same as role CLIENT, weekly remargining |
MPOR 9 / 14; EAD 614,987.67 / 739,335.84 EUR | The client's 5-day floor under CRR, 10 under BCBS, plus N − 1 (#359) |
illustrative-ccp-trade-exposure |
Margined, role CCP, QCCP Y, no retained VM, daily remargining: the same future and call |
MPOR 10 / 10; MF margined 0.3; EAD 642,195.55 / 642,195.55 EUR | The 10-day floor of a trade exposure to a CCP, the same EAD in both regimes (#112) |
illustrative-ccp-retained-vm |
The same role with retained VM: equity forwards maturing in 7 days, 182 days and two years | MPOR 10; trade MF margined 0.3, 1.0592062 and 1.5; EAD 218,844.52 EUR (both regimes) | Each trade's horizon: the 10-day floor, 182/365 × 250 business days, and one year (#112) |
illustrative-ccp-non-qualifying (CRR) |
The first CCP set with QCCP N
|
EAD 642,195.55 EUR | The QCCP status changes the stated risk weight, not the EAD (#112) |
illustrative-settled-to-market-daily |
Unmargined: an equity index future and a bought call, STM, reset the next day |
M 1/365 years; MF 0.2; EAD 353,463.70 EUR (both regimes) | M at the 10-day floor; the call keeps its expiry for the delta (#360) |
illustrative-settled-to-market-periodic |
Unmargined: a five-year EUR swap, an equity index call and a Brent forward, STM, reset in 30 days |
M 30/365 years; MF 0.286691; EAD 266,378.10 EUR (both regimes) | The swap keeps its supervisory duration and its bucket by E; the forward's reset falls on its maturity date, which is accepted (#360) |
TEST_Aggregation adds a mixed clearing population (#361): an ordinary, a
CM, a CLIENT and a CCP netting set holding the same swap, margined with
daily remargining under CRR, and a CCP set without its QCCP status. Each
VALID set takes its role's MPOR (10, 5, 5 and 10 business days), TOTAL CRR
is the sum of the four EADs and reads 4 of 5 netting set(s) VALID; 1 withheld, and the CCP line on Checks names one of two CCP sets VALID with
its EAD.
python tools/check.py validates every fixture and expected file against the
format and checks that the generated tests/modules/TEST_Cases.bas is current;
it runs no Excel. In Excel, TEST_Cases.RunCaseTests (also run by
TEST_Suite.Test_RunAll with every other suite) writes each fixture into the
NettingSets and Trades sheets, sets its parameters, the regime and the FX rate
of its currency to 1, runs the engine, compares the output cells within the
stated tolerance and attempts to restore the workbook. Check the final suite result and restore=PASS; a failure to restore is a test failure requiring attention, not a successful run. See Test Catalogue and
Validation Approach.

The TestCatalogue sheet runs the 28 catalogue checks on the template's demonstration portfolio: monetary values are in thousands, while ratios, factors and day counts keep their own units. The image is a static illustration, not evidence of the latest run. The JSON fixtures above are the governing test data.
These examples cover selected rules and outputs, not the full SA-CCR product and arrangement scope. In particular, an excluded trade, a matching factor or a matching hedging-set label does not validate an entire asset class; the published examples do not validate CCP/client-clearing exceptions or settled-to-market trades, and no published example here makes the margined-EAD cap bind. See Regulatory Basis for the rule-by-rule evidence and Basel vs CRR for regime interpretations and limitations.
🏦 K-SACCR · ⚖️ EU CRR · Basel CRE52 · 🧪 Published CRE99 checks T01–T14; CRR implemented, not numerically validated · 📦 Release 1.0.2 published 2026-10-23 · 🧮 No real portfolio data · ⚡ 500,000 synthetic trade legs in under two minutes · Repository · Validation Approach · Open Items
🏦 K-SACCR
⚖️ Regulation
- 📐 SA-CCR Overview
- 📚 Regulatory Sources
- 🧭 Regulatory Basis
- 🛡️ Replacement Cost and Collateral
- ⏱️ Margining and MPOR
- 📊 Potential Future Exposure
- ⚖️ Basel vs CRR
- 🧮 Worked Examples
🧮 Workbook
- 🚀 Getting Started
- 🗺️ Workbook Guide
- 📥 Inputs
- 📤 Outputs and Statuses
- 🔁 Reconciliation and Evidence
- ⚙️ How It Works
- 🧾 Worksheet Functions
- 🧪 Test Catalogue
- ✅ Validation Approach
- 🛠️ Troubleshooting
- 🚧 Open Items and Limitations
📌 Guide, not policy: the repository documents govern.