Skip to content

Worked Examples

Daniele Penza edited this page Oct 23, 2026 · 7 revisions

🧮 Worked Examples

Section Published Illustrative Units

📌 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.


📏 Units and tolerances

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).


📗 Published CRE99 examples

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).

1️⃣ Example 1: interest rate, unmargined

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.

2️⃣ Example 2: credit, unmargined

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.

3️⃣ Example 3: commodities, unmargined

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 DaysPerYear 360, 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, and BCBS-EX3 shows 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. DaysPerYear is a day-count convention and does not make the run WHAT-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 PASS uses 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.

4️⃣ Example 4: interest rate and credit, unmargined

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).

5️⃣ Example 5: interest rate and commodities, margined

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.

🔢 Reproducing the five published examples

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.


📙 Illustrative cases

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.

🧢 Posted VM and the cap (T16–T18)

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.

🎚️ Swaption forward at 1% (T19)

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.

➖ Negative interest-rate forward (T20–T22)

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.

🛢️ Negative commodity price (T23)

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.

🌀 Other risks (T24–T26)

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.

🌡️ Climatic conditions (T27)

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.

🏷️ Credit quality step (T28)

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.

🧩 Economic-trade legs

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.

➕ Other illustrative files

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

🏦 Clearing, CCP and settled-to-market cases (from 1.0.2)

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.


▶️ Running the cases

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.

TestCatalogue sheet with the 28 catalogue checks after a run

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.


🔗 Related

Clone this wiki locally