Skip to content

Input Data Schemas

This page documents the authoritative schemas for all input data files required by the RWA calculator. These schemas are defined in src/rwa_calc/data/schemas.py and represent the single source of truth.

Quick Reference

Data Category File(s) Required Purpose
Counterparty counterparty/counterparties.parquet Yes Borrower/obligor information
Facility exposures/facilities.parquet Yes Committed credit limits
Loan exposures/loans.parquet Yes Drawn exposures
Contingent exposures/contingents.parquet No Off-balance sheet items
Collateral collateral/collateral.parquet No Security/collateral
Guarantee guarantee/guarantee.parquet No Credit protection
Provision provision/provision.parquet No IFRS 9 provisions
Rating ratings/ratings.parquet No Credit ratings
FX Rates fx_rates/fx_rates.parquet No Currency conversion rates
Specialised Lending ratings/specialised_lending.parquet No Slotting approach data
SFT Trade ccr/sft_trades.parquet No FCCM SFT EAD (CCR — Art. 220–223)
SFT Collateral ccr/sft_collateral.parquet No Optional collateral for FCCM SFTs
Equity Exposure N/A No Equity holdings
CIU Holdings N/A No Per-fund holdings for CIU look-through (Art. 132)
Model Permissions config/model_permissions.parquet No Per-model IRB approach permissions

Mapping Files:

Mapping File Purpose
Facility Mapping exposures/facility_mapping.parquet Facility-to-loan hierarchy
Org Mapping mapping/org_mapping.parquet Organisation hierarchy (rating inheritance)
Lending Mapping mapping/lending_mapping.parquet Lending groups (retail threshold aggregation)

Counterparty Schema

Purpose: Defines borrower/obligor information used for exposure classification, risk weight determination, and hierarchy resolution.

File: counterparty/counterparties.parquet

Column Type Required Description
counterparty_reference String Yes Unique identifier for the counterparty
counterparty_name String No Legal name of the counterparty
entity_type String Yes Single source of truth for exposure class (see valid values below)
country_code String No ISO 3166-1 alpha-2 country code
annual_revenue Float64 No Annual revenue in GBP (for SME classification - EUR 50m threshold)
total_assets Float64 No Total assets in GBP (for LFSE threshold: EUR 70bn under CRR Art. 142(1)(4); GBP 79bn under PS1/26 Glossary p. 78)
default_status Boolean No Whether counterparty is in default
sector_code String No Industry sector code (SIC-based)
apply_fi_scalar Boolean No User flag: True = apply 1.25x FI correlation scalar (CRR Art. 153(2))
is_managed_as_retail Boolean No SME managed on pooled retail basis (75% RW per CRR Art. 123)
is_natural_person Boolean No True for individuals (natural persons). Required to qualify a counterparty for the SA retail exposure class (CRR Art. 123 / PS1/26 Art. 123 — the class is restricted to "natural persons or to a small or medium-sized enterprise"). Also drives the Basel 3.1 retail RE classification gates (PS1/26 Art. 124E(1) primary-residence exception, Art. 124H natural-person CRE branch)
is_social_housing Boolean No True for social-housing providers. Under CRR Art. 123(d), exposures to a "social housing provider, or [a] non-profit association regulated by law" are eligible for retail-class treatment without the natural-person test. Under Basel 3.1 the same population qualifies for the Art. 124E(1) materially-dependent exception so the loan-splitter treats it as non-income-producing residential RE (PRA PS1/26)
is_financial_sector_entity Boolean No True for financial sector entities (FSEs) as defined in CRR Art. 119(5) — credit institutions, investment firms, financial institutions, insurance and reinsurance undertakings, and similar regulated/unregulated entities. Used in conjunction with apply_fi_scalar and total_assets for the LFSE 1.25x correlation gate (Art. 142(1)(4) — "large financial sector entity")
is_ccp_client_cleared Boolean No True when the counterparty is a CCP whose exposures arise from client-cleared trades — drives the QCCP 4% RW (vs 2% proprietary) under CRR Art. 306 / PS1/26 Art. 306
borrower_income_currency String No ISO 4217 currency in which the borrower earns income (or, for RRE indexation, the currency in which the borrower's repayment cashflows are denominated). Triggers two independent currency-mismatch tests: (1) PRA PS1/26 Art. 123A unhedged-FX retail uplift — when the exposure currency differs from borrower_income_currency for an unhedged retail exposure, the RW is multiplied by 1.5 (capped at 150%); (2) PS1/26 Art. 124(2)(c) RRE primary-residence carve-out — only available where the exposure currency matches the currency of the borrower's repayment cashflows
local_currency String No Counterparty's domestic currency (ISO 4217). Two use sites: (1) CRR Art. 114(4) sovereign domestic-currency carve-out — exposures to a central government or central bank denominated and funded in that sovereign's own domestic currency may receive a 0% RW regardless of CQS (compared to currency on the loan/facility row); (2) currency-mismatch test for retail under PS1/26 Art. 123A when borrower_income_currency is unavailable — local_currency is then used as the proxy "income" currency. Distinct from borrower_income_currency, which is the obligor's actual income currency
sovereign_cqs Int32 No External CQS for the counterparty's sovereign (i.e. the central government of the country in country_code). Counterparty-level — distinct from the row-level external_cqs derived on each exposure (which captures the obligor's own rating, not its sovereign). Primary use site is the SA sovereign risk weight table (CRR Art. 114(2) / PS1/26 Art. 114(2) — exposures to central governments and central banks rated by a nominated ECAI). Drives the domestic-currency preferential treatment (CRR Art. 114(4): exposures to the sovereign and central bank denominated and funded in the domestic currency may receive 0% RW), the third-country preferential treatment (CRR Art. 114(5)–(6): same treatment for non-EU/UK sovereigns where the third country applies an equivalent supervisory regime). Also feeds the sovereign-derived institution floor (CRR Art. 119(2) — institution RW must not be more favourable than its home sovereign's RW; PS1/26 Art. 121(1) Table 5 derives unrated-institution SCRA grades from the home sovereign's CQS), and SCRA derivations
institution_cqs Int8 No External CQS for the counterparty when treated as an institution — counterparty-level field, distinct from the row-level external_cqs derived on each exposure. Used by ECRA institution risk weights (CRR Art. 120 Table 3 / PS1/26 Art. 120 Table 3). Under ECRA, rated institutions take a CQS-driven RW; unrated institutions fall through to SCRA (PS1/26 Art. 121, where unrated grades may themselves be derived from the home sovereign via Art. 121(1) Table 5). When both sovereign_cqs and institution_cqs are populated, the sovereign floor at Art. 119(2) caps the institution treatment
scra_grade String No SCRA grade for unrated institutions: "A", "A_ENHANCED", "B", "C" (Basel 3.1 CRE20.16-21 / PRA PS1/26 Art. 121). Use "A_ENHANCED" when the counterparty satisfies the Art. 121(5) quantitative thresholds (CET1 ratio ≥ 14% and leverage ratio ≥ 5%) — yields a 30% RW (>3m) vs the standard Grade A 40% (>3m) / 20% (≤3m) weights.
is_investment_grade Boolean No Publicly traded + investment grade → 65% SA RW (Basel 3.1 CRE20.47)

Entity Type: The Single Source of Truth

The entity_type field is the authoritative source for determining both SA and IRB exposure classes. Each entity type maps to specific exposure classes for each approach. This design ensures consistent classification across the calculation pipeline.

Valid entity_type values:

Entity Type SA Exposure Class IRB Exposure Class Regulatory Reference
Sovereign Class
sovereign CENTRAL_GOVT_CENTRAL_BANK CENTRAL_GOVT_CENTRAL_BANK CRR Art. 112(a)
central_bank CENTRAL_GOVT_CENTRAL_BANK CENTRAL_GOVT_CENTRAL_BANK CRR Art. 112(a)
RGLA Class (Regional Governments/Local Authorities)
rgla_sovereign RGLA CENTRAL_GOVT_CENTRAL_BANK CRR Art. 115 - has taxing powers/govt guarantee
rgla_institution RGLA INSTITUTION CRR Art. 115 - no sovereign equivalence
PSE Class (Public Sector Entities)
pse_sovereign PSE CENTRAL_GOVT_CENTRAL_BANK CRR Art. 116 - govt guaranteed
pse_institution PSE INSTITUTION CRR Art. 116 - commercial PSE
MDB/International Org Class
mdb MDB CENTRAL_GOVT_CENTRAL_BANK CRR Art. 117(1) — non-named MDB; institution table (CRR) / dedicated Table 2B (PS1/26 Art. 117(1)(a))
mdb_named MDB CENTRAL_GOVT_CENTRAL_BANK CRR Art. 117(2) / PS1/26 Art. 117(2) — named MDBs on the eligible list (e.g. IBRD, IFC, EIB, EBRD) qualify for 0% RW. Use mdb for non-named MDBs that fall back to the institution / Table 2B treatment
international_org MDB CENTRAL_GOVT_CENTRAL_BANK CRR Art. 118 — international organisations (e.g. IMF, BIS); 0% RW
Institution Class
institution INSTITUTION INSTITUTION CRR Art. 112(d)
bank INSTITUTION INSTITUTION CRR Art. 112(d)
ccp INSTITUTION INSTITUTION CRR Art. 300-311 (CCP treatment)
financial_institution INSTITUTION INSTITUTION CRR Art. 112(d)
Covered Bond Class
covered_bond COVERED_BOND COVERED_BOND CRR Art. 129 / PS1/26 Art. 129 — eligible covered bonds. Rated: CQS lookup against Table 6A (CRR) / Table 7 (B31). Unrated: derived from issuing institution's senior unsecured RW per Art. 129(5). B31 adds new due-diligence requirement (Art. 129(4A)) and expands the unrated derivation table from 4 to 7 entries
Corporate Class
corporate CORPORATE CORPORATE CRR Art. 112(g)
company CORPORATE CORPORATE CRR Art. 112(g)
Retail Class
individual RETAIL_OTHER RETAIL_OTHER CRR Art. 112(h)
retail RETAIL_OTHER RETAIL_OTHER CRR Art. 112(h)
Specialised Lending Class
specialised_lending SPECIALISED_LENDING SPECIALISED_LENDING CRR Art. 147(8)
Equity Class
equity EQUITY EQUITY CRR Art. 133
High-Risk Class (Basel 3.1 only — see warning below)
high_risk HIGH_RISK HIGH_RISK PS1/26 Art. 128 — generic "items associated with particularly high risk"; 150% RW. Assessment criteria per Art. 128(3): high risk of loss from obligor default; impossible to assess on standard data
high_risk_venture_capital HIGH_RISK HIGH_RISK PS1/26 Art. 128 — venture capital exposures held outside the equity exposure class (priority 3 equity takes precedence; this bucket is for non-equity VC exposures only). 150% RW
high_risk_private_equity HIGH_RISK HIGH_RISK PS1/26 Art. 128 — private-equity exposures held outside the equity exposure class. 150% RW
high_risk_speculative_re HIGH_RISK HIGH_RISK PS1/26 Art. 128 — speculative immovable property financing (e.g. land acquisition with uncertain end use). 150% RW. Distinct from ADC (Art. 124K) which has its own loan-splitter treatment
Other Items Class (CRR Art. 134 / PS1/26 Art. 134)
other_cash OTHER OTHER CRR Art. 134(3) / PS1/26 Art. 134(3) — cash in hand and equivalent items; 0% RW
other_gold OTHER OTHER CRR Art. 134(4) / PS1/26 Art. 134(4) — gold bullion held in own vaults or on an allocated basis (backed by bullion liabilities); 0% RW
other_items_in_collection OTHER OTHER CRR Art. 134(2) / PS1/26 Art. 134(2) — cash items in the process of collection; 20% RW
other_tangible OTHER OTHER CRR Art. 134(7) / PS1/26 Art. 134(7) — other tangible assets, prepayments, and accrued income (where the counterparty cannot be identified); 100% RW
other_residual_lease OTHER OTHER CRR Art. 134(7) / PS1/26 Art. 134(7) — residual value of leasing exposures (i.e. the portion not captured as a lease receivable on the obligor); 100% RW

Art. 128 (high-risk items) is omitted from current UK CRR

Art. 128 was omitted from UK onshored CRR by SI 2021/1078 (the Capital Requirements Regulation (Amendment) Regulations 2021). The high-risk exposure class is therefore a dead letter under current UK CRR (pre-2027) — exposures tagged with any high_risk* entity_type will fall through to other classes under a CRR-mode run. The class is re-introduced under PRA PS1/26 Art. 128 with effect 1 January 2027. Use the high_risk* entity types only when running in Basel 3.1 mode, or accept that the row will be reclassified under CRR. See SA risk weights spec - High-risk exposures.

Why SA and IRB Classes Can Differ

For certain entity types, the regulatory treatment differs between SA and IRB approaches:

  • RGLA/PSE with sovereign treatment: Under SA, these use dedicated RGLA/PSE risk weight tables. Under IRB, those with government guarantees or taxing powers use the central govt/central bank IRB formula.
  • RGLA/PSE with institution treatment: Under SA, these use RGLA/PSE tables. Under IRB, commercial PSEs without sovereign backing use the institution IRB formula.
  • MDB/International Orgs: Under SA, named MDBs (Art. 117(2)) receive 0% RW; other MDBs use institution tables (CRR) or dedicated Table 2B (Basel 3.1). Under IRB, they use the central govt/central bank formula.

Additional Classification Flags

Column Purpose When Used
apply_fi_scalar Directly controls whether FI scalar (1.25x correlation) applies Financial sector entities with this flag set to True get FI scalar under IRB (CRR Art. 153(2))
is_managed_as_retail SME managed on pooled retail basis Can use 75% RW under SA (CRR Art. 123)

Financial Sector Entity (FSE) and FI Scalar

The 1.25x correlation multiplier (Art. 153(2)) applies to large financial sector entities (LFSEs) and unregulated financial sector entities. The LFSE total-assets threshold differs by framework:

Framework LFSE threshold Citation
CRR Total assets ≥ EUR 70 billion CRR Art. 142(1)(4)
Basel 3.1 Total assets ≥ GBP 79 billion PS1/26 Glossary p. 78 (Note: "corresponds to Article 142(1)(4) of CRR")

How it works in the calculator: The apply_fi_scalar flag on the counterparty record is the sole input — the calculator does not automatically compare total_assets against the framework-specific threshold. The user is responsible for setting apply_fi_scalar = True on counterparties that meet the regulatory LFSE (or unregulated FSE) criteria for the framework in use. The classifier derives requires_fi_scalar directly from this flag with no entity-type gate.

Two distinct thresholds — do not conflate

  • LFSE total-assets threshold (EUR 70bn CRR / GBP 79bn B31) → 1.25x correlation multiplier (Art. 153(2), both CRR and Basel 3.1). Applies to the asset correlation coefficient R, not to the capital requirement directly.
  • GBP 440m annual revenue → F-IRB only approach restriction (Art. 147A(1)(e), Basel 3.1 only). Does not affect correlation.

These thresholds serve entirely different purposes and apply to different entity populations. See Key Differences for details.

Example:

import polars as pl

counterparties = pl.DataFrame({
    "counterparty_reference": ["CORP_001", "CORP_002", "SOV_001", "BANK_001", "PSE_001"],
    "counterparty_name": ["Acme Corp Ltd", "Beta Industries PLC", "UK Treasury", "Major Bank PLC", "Local Council"],
    "entity_type": ["corporate", "corporate", "sovereign", "bank", "pse_sovereign"],
    "country_code": ["GB", "GB", "GB", "GB", "GB"],
    "annual_revenue": [25_000_000.0, 500_000_000.0, None, None, None],
    "total_assets": [30_000_000.0, 600_000_000.0, None, 80_000_000_000.0, 500_000_000.0],
    "default_status": [False, False, False, False, False],
    "sector_code": ["62.01", "28.11", None, "64.19", None],
    "apply_fi_scalar": [False, False, False, False, False],
    "is_managed_as_retail": [False, False, False, False, False],
})

Classification Algorithm Summary

The classifier (engine/classifier.py) processes counterparties through these steps:

  1. Entity Type Mapping: Maps entity_type to both SA and IRB exposure classes
  2. SME Classification: Checks if annual_revenue < EUR 50m for corporates
  3. Retail Threshold: Aggregates exposures by lending group against retail threshold (EUR 1m CRR / GBP 880k Basel 3.1)
  4. Default Identification: Checks default_status for defaulted treatment
  5. FI Scalar Determination: Identifies large/unregulated FSEs for 1.25x correlation
  6. Approach Assignment: Assigns SA/F-IRB/A-IRB/Slotting based on IRB permissions

See Classification for the complete classification algorithm.


Facility Schema

Purpose: Defines committed credit facilities (parent nodes in exposure hierarchy). Facilities represent credit limits; actual drawings are captured in the Loan schema.

File: exposures/facilities.parquet

Column Type Required Description
facility_reference String Yes Unique identifier for the facility
product_type String No Product classification
book_code String No Portfolio/book classification
counterparty_reference String Yes Link to counterparty
value_date Date No Facility start date
maturity_date Date No Final maturity date — used to derive M for IRB unless effective_maturity is populated
facility_termination_date Date No Bank's contractual right-to-terminate date — overrides maturity_date for IRB M derivation when shorter (Art. 162(2)(g))
currency String No ISO 4217 currency code
limit Float64 No Committed facility limit
committed Boolean No Whether the facility is a binding commitment to lend (default True). When False, the facility is treated as unconditionally cancellable: the hierarchy resolver does not generate a facility_undrawn exposure row, so no commitment CCF / EAD / RWA is held against the unused headroom. Loans and contingents already mapped to the facility are unaffected and continue to flow through the pipeline as their own exposure rows, with normal counterparty / parent rollup and collateral allocation.
lgd Float64 No Internal LGD estimate (A-IRB)
lgd_unsecured Float64 No A-IRB unsecured LGD estimate, applied to the residual EAD after eligible collateral (CRR Art. 181)
beel Float64 No Best estimate expected loss
has_sufficient_collateral_data Boolean No A-IRB attestation that the firm has data quality sufficient to recognise own-estimate collateral effects under Art. 181(1)(f). When False, the LGD floor framework treats the row as if no collateral data is available
is_revolving Boolean No Revolving vs term facility (default False)
is_qrre_transactor Boolean No QRRE transactor flag. Drives the Basel 3.1 SA 45% weight (Art. 123(3)(a)) and the IRB 0.05% PD floor (Art. 163(1)(c)). True iff the revolving account has been repaid in full at each scheduled repayment date for the previous 12 months, OR the overdraft has not been drawn for the previous 12 months (PRA Glossary p. 9). Per Art. 154(4), accounts with less than 12 months of repayment history must be flagged False. Assessed upstream — not validated by the calculator. See Transactor Exposure.
seniority String No senior (default) or subordinated (affects F-IRB LGD)
risk_type String No Off-balance sheet risk category (see below)
underlying_risk_type String No Underlying-exposure risk type used by the CRM substitution path when the facility's own risk_type would otherwise mask the protection's true category
ccf_modelled Float64 No A-IRB modelled CCF (0.0-1.5)
ead_modelled Float64 No A-IRB modelled EAD — when populated and approach is A-IRB, replaces the drawn_amount + ccf x undrawn_amount derivation (CRR Art. 166(8a))
is_short_term_trade_lc Boolean No Short-term trade LC for goods movement (Art. 166(9))
is_payroll_loan Boolean No Payroll-deduction / pension lending — qualifies for the Basel 3.1 35% retail RW (PS1/26 Art. 123(2))
is_buy_to_let Boolean No Buy-to-let property lending — excluded from SME supporting factor (CRR Art. 501)
has_one_day_maturity_floor Boolean No Set True for short-term self-liquidating trade exposures and certain capital-markets-driven exposures eligible for the 1-day M floor under CRR Art. 162(3) (otherwise the standard 1-year floor applies)
is_sft Boolean No Securities Financing Transaction — selects the F-IRB 0.5-year repo-style supervisory maturity (M) under CRR Art. 162(1) (a fixed value, not a floor; deleted under Basel 3.1)
effective_maturity Float64 No Explicit numeric M override (years) per CRR Art. 162(3) / PS1/26. When populated it supersedes the maturity_date-derived M and bypasses the 1-year floor — firm-owned judgement for short-term carve-outs

Valid product_type values:

Value Description
rcf Revolving credit facility
term_loan Term loan facility
mortgage Mortgage facility
overdraft Overdraft facility
credit_card Credit card facility
trade_finance Trade finance facility
guarantee Guarantee facility
project_finance Project finance

Valid seniority values:

Value F-IRB LGD Description
senior 45% Senior unsecured claims
subordinated 75% Subordinated claims

Valid risk_type values (CRR Art. 111 CCF Categories):

Code Full Value SA CCF F-IRB CCF Description
FR full_risk 100% 100% Direct credit substitutes, guarantees, acceptances
MR medium_risk 50% 75% NIFs, RUFs, standby LCs, committed undrawn
MLR medium_low_risk 20% 75% Documentary credits, trade finance
LR low_risk 0% 0% Unconditionally cancellable commitments

Note: Under F-IRB (CRR Art. 166(8)), MR and MLR both become 75% CCF.

F-IRB Exception (Art. 166(9)): Short-term letters of credit arising from the movement of goods retain 20% CCF under F-IRB. To flag these exposures, set is_short_term_trade_lc = True for MLR risk type items.

Column Type Required Description
is_short_term_trade_lc Boolean No True for short-term trade LCs for goods movement (Art. 166(9) - retains 20% CCF under F-IRB)

A-IRB Modelled CCF: For A-IRB exposures, provide the bank's own modelled CCF estimate (0.0 to 1.5) in ccf_modelled. Retail IRB CCFs can exceed 100% due to additional drawdown behaviour. When populated and approach is A-IRB, this value takes precedence over the risk_type lookup.

Example:

from datetime import date
import polars as pl

facilities = pl.DataFrame({
    "facility_reference": ["FAC_001", "FAC_002"],
    "product_type": ["rcf", "term_loan"],
    "book_code": ["CORP_LENDING", "CORP_LENDING"],
    "counterparty_reference": ["CORP_001", "CORP_002"],
    "value_date": [date(2024, 1, 15), date(2023, 6, 1)],
    "maturity_date": [date(2029, 1, 15), date(2028, 6, 1)],
    "currency": ["GBP", "GBP"],
    "limit": [10_000_000.0, 5_000_000.0],
    "committed": [True, True],
    "lgd": [None, None],  # Supervisory LGD used for F-IRB
    "beel": [None, None],
    "is_revolving": [True, False],
    "seniority": ["senior", "senior"],
    "risk_type": ["MR", "MR"],  # Medium risk - committed undrawn
    "ccf_modelled": [None, None],  # No modelled CCF (use regulatory)
})

Loan Schema

Purpose: Defines drawn loan exposures (leaf nodes in exposure hierarchy). Loans represent actual credit usage under facilities.

File: exposures/loans.parquet

Column Type Required Description
loan_reference String Yes Unique identifier for the loan
product_type String No Product classification
book_code String No Portfolio/book classification
counterparty_reference String Yes Link to counterparty
value_date Date No Loan origination date
maturity_date Date No Loan maturity date
currency String No ISO 4217 currency code
drawn_amount Float64 No Outstanding principal balance (default 0.0)
interest Float64 No Accrued interest (adds to on-balance-sheet EAD)
lgd Float64 No Internal LGD estimate (A-IRB)
lgd_unsecured Float64 No A-IRB unsecured LGD estimate, applied to the residual EAD after eligible collateral (CRR Art. 181)
beel Float64 No Best estimate expected loss
has_sufficient_collateral_data Boolean No A-IRB collateral data-quality attestation per Art. 181(1)(f). See Facility schema
seniority String No senior (default) or subordinated (affects F-IRB LGD)
is_payroll_loan Boolean No Payroll-deduction / pension lending — qualifies for the Basel 3.1 35% retail RW (PS1/26 Art. 123(2))
is_buy_to_let Boolean No Buy-to-let property lending — excluded from SME supporting factor (CRR Art. 501)
has_one_day_maturity_floor Boolean No Eligible for the CRR Art. 162(3) 1-day M floor in lieu of the standard 1-year floor
is_sft Boolean No Securities Financing Transaction — see Facility schema
effective_maturity Float64 No Explicit numeric M override (years) per CRR Art. 162(3) / PS1/26. Bypasses the 1-year floor when populated
netting_agreement_reference String No CRR Art. 195/219 on-balance-sheet netting set. A non-null reference is the sole signal that the loan participates in a netting agreement; exposures net against each other iff they share the same reference — independent of facility or counterparty
due_diligence_performed Boolean No Basel 3.1 Art. 110A: True if the firm has performed the prescribed due-diligence assessment of the obligor. Required for the SA RW override below to apply. Absence raises diagnostic warning SA004 under B3.1
due_diligence_override_rw Float64 No Basel 3.1 Art. 110A SA RW override (decimal, e.g. 1.50 for 150%). Applied as max(calculated_rw, override_rw) — the override can only increase the regulatory RW, never decrease it. CRR-only runs ignore this column

Note: Loans do not have CCF fields (risk_type, ccf_modelled, is_short_term_trade_lc) because CCF only applies to off-balance sheet items. For drawn loans, EAD = drawn_amount + interest directly.

Example:

from datetime import date
import polars as pl

loans = pl.DataFrame({
    "loan_reference": ["LOAN_001", "LOAN_002", "LOAN_003"],
    "product_type": ["rcf_drawing", "term_loan", "term_loan"],
    "book_code": ["CORP_LENDING", "CORP_LENDING", "CORP_LENDING"],
    "counterparty_reference": ["CORP_001", "CORP_001", "CORP_002"],
    "value_date": [date(2024, 3, 1), date(2024, 4, 15), date(2023, 6, 1)],
    "maturity_date": [date(2029, 1, 15), date(2029, 1, 15), date(2028, 6, 1)],
    "currency": ["GBP", "GBP", "GBP"],
    "drawn_amount": [2_000_000.0, 1_500_000.0, 5_000_000.0],
    "interest": [10_000.0, 7_500.0, 25_000.0],  # Accrued interest
    "lgd": [None, None, None],
    "beel": [None, None, None],
    "seniority": ["senior", "senior", "senior"],
    "is_buy_to_let": [False, False, False],
    "netting_agreement_reference": [None, None, None],
})

Contingent Schema

Purpose: Defines off-balance sheet commitments that require Credit Conversion Factor (CCF) application.

File: exposures/contingents.parquet

Column Type Required Description
contingent_reference String Yes Unique identifier
product_type String No Product classification
book_code String No Portfolio/book classification
counterparty_reference String Yes Link to counterparty
value_date Date No Contract start date
maturity_date Date No Contract expiry date
currency String No ISO 4217 currency code
nominal_amount Float64 No Notional/nominal amount (default 0.0)
lgd Float64 No Internal LGD estimate (A-IRB)
lgd_unsecured Float64 No A-IRB unsecured LGD estimate, applied to the residual EAD after eligible collateral (CRR Art. 181)
beel Float64 No Best estimate expected loss
has_sufficient_collateral_data Boolean No A-IRB collateral data-quality attestation per Art. 181(1)(f). See Facility schema
seniority String No senior (default) or subordinated
risk_type String No Off-balance sheet risk category (see Facility schema)
underlying_risk_type String No Underlying-exposure risk type for CRM substitution (see Facility schema)
ccf_modelled Float64 No A-IRB modelled CCF (0.0-1.5)
ead_modelled Float64 No A-IRB modelled EAD — replaces the CCF-derived value when populated under A-IRB (CRR Art. 166(8a))
is_short_term_trade_lc Boolean No Short-term trade LC for goods movement (Art. 166(9))
has_one_day_maturity_floor Boolean No Eligible for the CRR Art. 162(3) 1-day M floor
is_sft Boolean No Securities Financing Transaction — see Facility schema
effective_maturity Float64 No Explicit numeric M override (years) per CRR Art. 162(3) / PS1/26
bs_type String No "ONB" (on-balance-sheet / drawn) or "OFB" (off-balance-sheet / undrawn). Default: "OFB"
due_diligence_performed Boolean No Basel 3.1 Art. 110A due-diligence attestation (see Loan schema)
due_diligence_override_rw Float64 No Basel 3.1 Art. 110A SA RW override (max-only — see Loan schema)

Example:

from datetime import date
import polars as pl

contingents = pl.DataFrame({
    "contingent_reference": ["CONT_001", "CONT_002", "CONT_003"],
    "product_type": ["trade_finance", "guarantee", "import_lc"],
    "book_code": ["TRADE", "GUARANTEE", "TRADE"],
    "counterparty_reference": ["CORP_001", "CORP_002", "CORP_003"],
    "value_date": [date(2024, 1, 1), date(2024, 2, 1), date(2024, 3, 1)],
    "maturity_date": [date(2025, 1, 1), date(2025, 2, 1), date(2024, 6, 1)],
    "currency": ["GBP", "GBP", "GBP"],
    "nominal_amount": [500_000.0, 1_000_000.0, 250_000.0],
    "lgd": [None, None, None],
    "beel": [None, None, None],
    "seniority": ["senior", "senior", "senior"],
    "risk_type": ["FR", "MR", "MLR"],  # FR=100%, MR=50%/75%, MLR=20%/75%
    "ccf_modelled": [None, None, None],  # No modelled CCF
    "is_short_term_trade_lc": [False, False, True],  # Third is Art. 166(9) exception
    "bs_type": ["OFB", "OFB", "OFB"],  # Off-balance sheet (default)
})

Collateral Schema

Purpose: Defines collateral/security items used for Credit Risk Mitigation (CRM). Collateral can be linked at counterparty, facility, or loan level.

File: collateral/collateral.parquet

Column Type Required Description
collateral_reference String Yes Unique identifier
collateral_type String Yes Type of collateral (see valid values)
currency String No ISO 4217 currency code
maturity_date Date No Collateral maturity (if applicable)
market_value Float64 Conditional Current market value (required unless pledge_percentage provided)
nominal_value Float64 No Nominal/face value
pledge_percentage Float64 Conditional Fraction of beneficiary EAD (0.5 = 50%). Used when market_value not provided. Resolved to absolute market_value before haircuts.
beneficiary_type String Yes Level of allocation
beneficiary_reference String Yes Reference to counterparty/facility/loan
issuer_cqs Int8 No CQS of issuer (for securities)
issuer_type String No Issuer type (for haircut lookup)
residual_maturity_years Float64 No Residual maturity in years
original_maturity_years Float64 No Original maturity in years — used for collateral maturity-band differentiation where the haircut depends on issuance maturity rather than residual maturity
is_eligible_financial_collateral Boolean No Meets SA eligibility (CRR Art 197)
is_eligible_irb_collateral Boolean No Meets IRB eligibility (CRR Art 199)
is_airb_model_collateral Boolean No Default False. When True, the firm asserts the collateral has been used to construct the internal LGD model (CRR Art. 181 / Basel 3.1 Art. 169A). The CRM allocator excludes flagged rows from non-AIRB exposures (no double-counting of the modelled-LGD effect) and routes them only to AIRB-pool exposures whose modelled LGD is preserved. Direct allocation of a flagged row onto a non-AIRB exposure raises CRM006
is_qualifying_re Boolean No Meets Basel 3.1 qualifying real-estate criteria for the loan-splitter (PS1/26 Art. 124A finished-property / legal-enforceability / valuation / borrower-ability tests). Drives Art. 124F (RRE) / Art. 124H (CRE) eligibility
is_main_index Boolean No Equity collateral listed on a recognised main index (e.g. FTSE 100) — qualifies for the lower main-index haircut (CRR Art. 197(8))
valuation_date Date No Date of last valuation
valuation_type String No market, indexed, independent
property_type String No residential or commercial (RE only)
property_ltv Float64 No Regulatory LTV per Art. 124C — must include prior/pari passu charges (Art. 124C(3)) in numerator
prior_charge_ltv Float64 No LTV portion from prior/pari passu charges only (Art. 124C(3)); 0.0 = first charge. Used by Art. 124F(2)/124G(2) junior charge treatment
is_income_producing Boolean No Material dependency on property cash flows per Art. 124E. True = materially dependent (residential: Art. 124G whole-loan; commercial: Art. 124I). False/null = not materially dependent (residential: Art. 124F loan-splitting; commercial: Art. 124H). For residential RE, this requires upstream assessment of Art. 124E(1) exceptions (primary residence, three-property limit, social housing, cooperative). For commercial RE, the own-business-use test (Art. 124E(6)). See Art. 124E spec
is_adc Boolean No Acquisition/Development/Construction
is_presold Boolean No ADC pre-sold to qualifying buyer
rental_to_interest_ratio Float64 No CRR Art. 126(2)(d): rental income / interest payments ratio. The ≥ 1.5 test gates the 50% preferential CRE risk weight; if absent, CRE collateral is conservatively treated as failing the test under CRR and the loan-splitter leaves the exposure in its original corporate / retail class. Not used under Basel 3.1.
liquidation_period_days Int32 No Liquidation period in business days — used to scale supervisory haircuts under the Comprehensive method when the firm's holding period differs from the supervisory minimum (CRR Art. 224)
qualifies_for_zero_haircut Boolean No Repo-style transaction qualifying for the zero-haircut carve-out under CRR Art. 224(1) / Art. 227 (core market participants, eligible securities, daily margining)
insurer_risk_weight Float64 No Credit-protection insurer risk weight override — when funded credit protection is provided by an eligible insurer, this RW is substituted for the obligor RW on the protected portion (CRR Art. 235)
credit_event_reduction Float64 No Adjustment factor (decimal, default 0.0) applied to the protection's covered amount when the contract restricts the set of credit events. Reduces recognised CRM accordingly (CRR Art. 213-216)

Valid collateral_type values:

Value Description
cash Cash collateral (0% haircut)
gold Gold collateral (CRR 15% / B31 20% haircut)
bond Bond securities — haircut depends on issuer_type, issuer_cqs, and residual_maturity_years
equity Equity securities
real_estate Real estate — use property_type for residential/commercial classification
receivables Trade receivables
other_physical Other physical collateral

Valid beneficiary_type values:

Value Description
counterparty Allocated at counterparty level (expands to all exposures)
facility Allocated at facility level (expands to facility + child loans)
loan Allocated directly to specific loan
contingent Allocated directly to contingent

Example:

from datetime import date
import polars as pl

collateral = pl.DataFrame({
    "collateral_reference": ["COLL_001", "COLL_002"],
    "collateral_type": ["cash", "real_estate"],
    "currency": ["GBP", "GBP"],
    "maturity_date": [None, None],
    "market_value": [1_000_000.0, 500_000.0],
    "nominal_value": [1_000_000.0, None],
    "beneficiary_type": ["counterparty", "loan"],
    "beneficiary_reference": ["CORP_001", "LOAN_003"],
    "issuer_cqs": [None, None],
    "issuer_type": [None, None],
    "residual_maturity_years": [None, None],
    "is_eligible_financial_collateral": [True, False],
    "is_eligible_irb_collateral": [True, True],
    "valuation_date": [date(2024, 12, 31), date(2024, 11, 15)],
    "valuation_type": ["market", "independent"],
    "property_type": [None, "residential"],
    "property_ltv": [None, 0.65],  # Art. 124C: includes prior charges in numerator
    "prior_charge_ltv": [None, 0.0],  # Art. 124C(3): 0.0 = first charge
    "is_income_producing": [None, False],
    "is_adc": [None, False],
    "is_presold": [None, None],
})

Guarantee Schema

Purpose: Defines guarantee protection for Credit Risk Mitigation using the substitution approach.

File: guarantee/guarantee.parquet

Column Type Required Description
guarantee_reference String Yes Unique identifier
guarantee_type String No Type of guarantee
guarantor String Yes Guarantor counterparty reference
currency String No ISO 4217 currency code
maturity_date Date No Guarantee expiry date
amount_covered Float64 Conditional Amount covered by guarantee (required unless percentage_covered provided)
percentage_covered Float64 Conditional Fraction of exposure covered (1.0 = 100%). Used when amount_covered not provided
beneficiary_type String Yes Level of allocation
beneficiary_reference String Yes Reference to counterparty/facility/loan
protection_type String No "guarantee" (default) or "credit_derivative" — drives CRM treatment under CRR Art. 213 vs Art. 215 (credit-derivative-specific eligibility tests)
includes_restructuring Boolean No True when the credit derivative includes restructuring as a credit event. Required for full recognition under CRR Art. 216(1)(d); when False the recognised cover is reduced to 60% per Art. 216(1)(e)

Valid guarantee_type values:

Value Description
guarantee Standard guarantee
credit_derivative Credit derivative protection
counter_guarantee Counter-guarantee

Example:

from datetime import date
import polars as pl

guarantees = pl.DataFrame({
    "guarantee_reference": ["GUAR_001"],
    "guarantee_type": ["guarantee"],
    "guarantor": ["SOV_001"],  # UK Treasury guaranteeing
    "currency": ["GBP"],
    "maturity_date": [date(2030, 12, 31)],
    "amount_covered": [2_000_000.0],
    "percentage_covered": [1.0],
    "beneficiary_type": ["counterparty"],
    "beneficiary_reference": ["CORP_001"],
})

Provision Schema

Purpose: Defines IFRS 9 provisions/impairments for EAD reduction and IRB expected loss comparison.

File: provision/provision.parquet

Column Type Required Description
provision_reference String Yes Unique identifier
provision_type String Yes scra (specific) or gcra (general)
ifrs9_stage Int8 No IFRS 9 stage (1, 2, or 3)
currency String Yes ISO 4217 currency code
amount Float64 Yes Provision amount
as_of_date Date Yes Provision as-of date
beneficiary_type String Yes Level of allocation
beneficiary_reference String Yes Reference to counterparty/facility/loan

Valid provision_type values:

Value Description Usage
scra Specific Credit Risk Adjustment Reduces exposure value; affects defaulted RW
gcra General Credit Risk Adjustment Reduces exposure value

Valid beneficiary_type values:

Value Description Resolution
loan Allocated directly to a specific loan Matched by beneficiary_reference = loan_reference
contingent Allocated directly to a contingent Matched by beneficiary_reference = contingent_reference
facility Allocated at facility level Distributed pro-rata across facility's exposures by ead_gross
counterparty Allocated at counterparty level Distributed pro-rata across all counterparty exposures by ead_gross

Valid ifrs9_stage values:

Stage Description ECL Type
1 Performing 12-month ECL
2 Performing, significant increase in credit risk Lifetime ECL
3 Non-performing/credit-impaired Lifetime ECL

Example:

from datetime import date
import polars as pl

provisions = pl.DataFrame({
    "provision_reference": ["PROV_001", "PROV_002"],
    "provision_type": ["scra", "gcra"],
    "ifrs9_stage": [1, 2],
    "currency": ["GBP", "GBP"],
    "amount": [50_000.0, 100_000.0],
    "as_of_date": [date(2024, 12, 31), date(2024, 12, 31)],
    "beneficiary_type": ["loan", "counterparty"],
    "beneficiary_reference": ["LOAN_001", "CORP_002"],
})

Rating Schema

Purpose: Defines internal and external credit ratings for risk weight determination.

File: ratings/ratings.parquet

Column Type Required Description
rating_reference String Yes Unique identifier
counterparty_reference String Yes Link to counterparty
rating_type String Yes internal or external
rating_agency String Yes Rating source
rating_value String Yes Rating value (e.g., AAA, Aa1)
cqs Int8 Yes Credit Quality Step (1-6)
pd Float64 No Probability of Default (internal ratings)
rating_date Date Yes Rating as-of date
is_solicited Boolean No Whether rating was solicited
model_id String No IRB model identifier — links to Model Permissions for per-model approach gating. Flows through rating inheritance pipeline to exposures. Null defaults to SA.
is_short_term Boolean No True flags this row as a dedicated short-term ECAI assessment (PRA PS1/26 Art. 120(2B) Table 4A / Art. 122(3) Table 6A). Defaults to False (long-term, counterparty-wide).
scope_type String No Which exposure the short-term rating attaches to: facility, loan, or contingent. Must be populated when is_short_term=True; must be null otherwise.
scope_id String No Matching facility_reference / loan_reference / contingent_reference. Must be populated when is_short_term=True; must be null otherwise.

Short-term ECAI assessments (Art. 120(2B) / Art. 122(3)): Short-term assessments are issue-specific — they attach to a particular exposure rather than to the counterparty as a whole. Populate is_short_term=True together with scope_type and scope_id to override the counterparty-level long-term rating for the targeted exposure. When the scope is facility, the override propagates to all loans and undrawn portions drawn under that facility. The SA engine routes the overridden exposure via Table 4A (institution) or Table 6A (corporate). The producer is responsible for ensuring the underlying exposure satisfies the regulatory maturity test before flagging the rating short-term — the engine does not re-check maturity.

Valid rating_agency values:

Value Description
internal Internal rating system
SP Standard & Poor's
MOODYS Moody's
FITCH Fitch Ratings
DBRS DBRS Morningstar

CQS Mapping:

CQS S&P/Fitch Moody's Sovereign RW Institution RW Corporate RW
1 AAA to AA- Aaa to Aa3 0% 20% 20%
2 A+ to A- A1 to A3 20% 30%* 50%
3 BBB+ to BBB- Baa1 to Baa3 50% 50% 100%
4 BB+ to BB- Ba1 to Ba3 100% 100% 100%
5 B+ to B- B1 to B3 100% 100% 150%
6 CCC+ and below Caa1 and below 150% 150% 150%

*CRR Art. 120 Table 3 assigns CQS 2 institutions 50%. Basel 3.1 ECRA (PRA PS1/26 Art. 120 Table 3) reduces this to 30%.

Example:

from datetime import date
import polars as pl

ratings = pl.DataFrame({
    "rating_reference": ["RAT_001", "RAT_002"],
    "counterparty_reference": ["CORP_001", "SOV_001"],
    "rating_type": ["external", "external"],
    "rating_agency": ["SP", "SP"],
    "rating_value": ["BBB+", "AA"],
    "cqs": [3, 1],
    "pd": [None, None],
    "rating_date": [date(2024, 6, 15), date(2024, 1, 1)],
    "is_solicited": [True, True],
})

FX Rates Schema

Purpose: Defines FX (foreign exchange) rates for converting exposure amounts from their original currencies to a reporting currency. This enables consistent RWA calculations across multi-currency portfolios.

File: fx_rates/fx_rates.parquet

Column Type Required Description
currency_from String Yes Source currency code (ISO 4217)
currency_to String Yes Target currency code (ISO 4217)
rate Float64 Yes Conversion multiplier: target_amount = source_amount * rate

Usage: - Rates should be provided for all currency pairs needed (source → target) - Include identity rates (e.g., GBP→GBP = 1.0) for the target currency - The target currency should match CalculationConfig.base_currency

Converted Fields: - Exposures: drawn_amount, undrawn_amount, nominal_amount - Collateral: market_value, nominal_value - Guarantees: amount_covered - Provisions: amount

Audit Trail: After conversion, the following columns are added: - original_currency - Currency before conversion - original_amount - Amount before conversion (drawn + nominal) - fx_rate_applied - Rate used (null if no conversion needed)

Example:

from datetime import date
import polars as pl

fx_rates = pl.DataFrame({
    "currency_from": ["GBP", "USD", "EUR", "JPY", "CHF"],
    "currency_to": ["GBP", "GBP", "GBP", "GBP", "GBP"],
    "rate": [1.0, 0.79, 0.88, 0.0053, 0.89],
})

Behaviour: - Missing rates: Exposures in currencies without rates retain original values; fx_rate_applied is null - FX disabled: Set apply_fx_conversion=False in CalculationConfig to skip conversion - No FX file: If fx_rates.parquet is not provided, no conversion occurs


Specialised Lending Schema

Purpose: Defines specialised lending metadata for slotting approach treatment (CRE33). Keyed by counterparty_reference — all exposures to an SL counterparty inherit the same slotting treatment. This allows a corporate counterparty to have both SL and non-SL exposures.

File: ratings/specialised_lending.parquet

Column Type Required Description
counterparty_reference String Yes Links to counterparty (all exposures inherit SL treatment)
sl_type String Yes Type of specialised lending
project_phase String No Project lifecycle phase — typically "planning", "construction", or "operational". Drives the CRE33.5 < 2.5-year strong/good preferential weights (which only apply during construction / pre-operational phase)
slotting_category String No Slotting category
is_hvcre Boolean No High-volatility commercial real estate

Valid sl_type values:

Value Description
project_finance Project finance (PF)
object_finance Object finance (OF)
commodities_finance Commodities finance (CF)
ipre Income-producing real estate
hvcre High-volatility commercial real estate

Valid slotting_category values:

Category CRR RW Description
strong 70% Excellent risk profile
good 90% (70% if <2.5yr) Good risk profile
satisfactory 115% Acceptable risk profile
weak 250% Higher risk profile
default 0% In default (provisions apply)

SFT Input Schemas (FCCM)

Purpose: Dedicated input contract for securities financing transactions (SFTs) — repos, reverse repos, securities-borrowing/lending and margin-lending — whose exposure-at-default is computed by the Financial Collateral Comprehensive Method (FCCM) under CRR Art. 220–223. SFTs are a peer of the SA-CCR derivative book, not a sub-mode of it: they have their own input bundle, their own dataloads and their own pipeline stage.

Two unrelated meanings of \"SFT\"

The transaction_type == "sft" / FCCM path documented here (CCR EAD, CRR Art. 220–223) is a completely different concept from the is_sft Boolean carried on the loan / contingent / facility schemas (which selects the F-IRB 0.5-year repo-style supervisory maturity under CRR Art. 162(1)). Same acronym, different concept. (FCCM SFT rows that route to IRB carry their Art. 162 maturity via a dedicated ccr_effective_maturity carrier — never is_sft.) See The two meanings of "SFT" below.

How SFTs flow through the pipeline

SFT inputs are loaded into a dedicated bundle and processed by a dedicated stage that runs as a peer of the SA-CCR derivative stage:

sft_trades.parquet (+ optional sft_collateral.parquet)
   → RawSFTBundle  (RawDataBundle.sft)
   → sft_fccm stage  (engine/stages/sft.py)
   → E* = max(0, E·(1+HE) − CVA·(1−HC−HFX))   (CRR Art. 223(5))
   → one synthetic exposure row per netting set
        (risk_type = "CCR_SFT", ccr_method = "fccm_sft", drawn_amount = E*)
   → Classifier → CRM → SA / IRB exposure ladder

The sft_fccm stage sits immediately after ccr_sa_ccr in the literal pipeline registry, so the two regulatory EAD methods are adjacent and visible:

Stage Input bundle Regulatory EAD basis Output risk_type
ccr_sa_ccr RawDataBundle.ccr SA-CCR EAD = α·(RC + PFE) (CRR Art. 274) CCR_DERIVATIVE
sft_fccm RawDataBundle.sft FCCM E* (CRR Art. 220–223 via Art. 271(2)) CCR_SFT

The stage no-ops when RawDataBundle.sft is None (a firm with no SFT book is unaffected), and it re-seals its output to the existing ccr_exit edge brand so SFT and derivative rows share the same downstream contract.

Details: see the SFT (FCCM EAD) specification for the E* formula, haircut treatment, and the architectural separation from SA-CCR.

SFT Trade Schema

File: ccr/sft_trades.parquet (the single primary SFT dataload; optional)

One row per SFT. The netting-set counterparty is denormalised onto the trade row — FCCM's current scope is single-trade, single-counterparty netting sets (Art. 220(1)(a)), so no separate SFT netting-set table is needed. The three exposure_* columns carry the Art. 223(5) exposure-side volatility-haircut (HE) inputs.

Column Type Required Description
trade_id String Yes Unique identifier for the SFT
netting_set_id String Yes Netting-set reference — used for the ccr__<netting_set_id> output reference and the collateral join
counterparty_reference String Yes Counterparty (denormalised from the netting set) — drives the SA institution risk-weight lookup (CRR Art. 120(1) Table 3)
notional Float64 Yes E — the exposure amount lent / sold under the SFT (Art. 223(5))
currency String Yes ISO 4217 currency code of the exposure
maturity_date Date Yes SFT maturity date
start_date Date Yes SFT start date
exposure_collateral_type String No HE input — exposure-side security type for the Art. 224 Table 1 haircut lookup. Null when the exposure side is cash / a standard loan (HE = 0)
exposure_security_cqs Int8 No HE input — exposure-side issuer CQS
exposure_security_residual_maturity_years Float64 No HE input — exposure-side residual maturity (years)
is_margined Boolean No (default False) Branch selector (Art. 224(2) final subparagraph). False → unmargined branch (today's behaviour); True → the margined Art. 285 MPOR branch
remargining_frequency_days Int16 No (default 1) Dual role: N_R for the Art. 226 non-daily revaluation factor on the unmargined branch (1 = daily revaluation, factor = 1.0) / N in MPOR = F + N − 1 on the margined branch
mpor_floor_category String No (default repo_only) MPOR floor F selector (margined branch only): repo_only → 5 (Art. 285(2)(a)) / other → 10 (Art. 285(2)(b)) / illiquid_or_large → 20 (Art. 285(3)). Constrained to VALID_MPOR_FLOOR_CATEGORIES
has_margin_dispute_doubling Boolean No (default False) True doubles F for the two quarters following more than two margin disputes (Art. 285(4))
mpor_days_override Int16 No (default null) Explicit MPOR in business days; supersedes the F + N − 1 derivation when set

The five margining columns are inert on the unmargined-daily path

All five margining columns default so that is_margined = False with remargining_frequency_days = 1 reproduces today's E* exactly (the Art. 226 non-daily factor collapses to 1.0 at daily revaluation). They take effect only when is_margined = True (the Art. 285 MPOR branch) or remargining_frequency_days > 1 (non-daily revaluation). See the SFT specification — two mutually-exclusive branches.

These three columns were previously schema-orphaned

exposure_collateral_type, exposure_security_cqs and exposure_security_residual_maturity_years are first-class on SFT_TRADE_SCHEMA. They are not the identically-named columns on LOAN_SCHEMA / CONTINGENTS_SCHEMA (which serve an unrelated lending purpose) — grepping the name across schemas can mislead.

SFT Collateral Schema

File: ccr/sft_collateral.parquet (optional — appears only when securities are posted)

Collateral received against an SFT, keyed by netting_set_id (a genuinely different grain — 0..n securities per netting set — so it stays a separate optional file). Feeds the CVA·(1 − HC − HFX) collateral term of the FCCM E* formula. An uncollateralised SFT carries no collateral row, so for the common case this is literally one file.

Column Type Required Description
sft_collateral_reference String Yes Unique identifier for the collateral row
netting_set_id String Yes Join key back to the SFT trade's netting_set_id
collateral_type String Yes Collateral security type — HC input for the Art. 224 Table 1 lookup
market_value Float64 No (default 0.0) CVA — collateral market value in the E* formula; 0.0 when unknown (no collateral credit)
currency String No Collateral currency. Drives the HFX same-currency shortcut (Art. 224 Table 4: HFX = 0 when collateral and exposure currencies match)
issuer_cqs Int8 No HC input — collateral issuer CQS
residual_maturity_years Float64 No HC input — collateral residual maturity (years)

transaction_type discriminator

The CCR/SFT split key is transaction_type on the SA-CCR TRADE_SCHEMA, constrained to VALID_TRANSACTION_TYPES = {"derivative", "sft"} via COLUMN_VALUE_CONSTRAINTS. A bad value (e.g. "SFT", "repo") would otherwise silently mis-route an SFT into the SA-CCR Art. 274 chain (≈£0 EAD); the value constraint surfaces it as a DQ006 data-quality error instead. SFT rows belong in SFT_TRADE_SCHEMA / RawDataBundle.sft, not on the SA-CCR trade frame.

Configuration

SFTConfig.method (on CalculationConfig.sft) selects the SFT EAD method per CRR Art. 271(2):

method Meaning Status
"fccm" (default) Financial Collateral Comprehensive Method (Art. 220–223) Implemented
"var" VaR method (Art. 221) Reserved — engine fails loud (NotImplementedError)
"imm" Internal Model Method (Art. 283) Reserved — engine fails loud

The method is exposed as the sft_method factory argument on CalculationConfig.crr() / .basel_3_1().

The two meanings of "SFT"

The acronym "SFT" denotes two unrelated concepts that never interact:

FCCM SFT (this section) Lending is_sft
Carrier transaction_type == "sft" on SFT_TRADE_SCHEMA is_sft Boolean on LOAN / CONTINGENT / FACILITY schemas
Concept Securities financing transaction routed to FCCM CCR EAD A lending exposure flagged as an SFT for the F-IRB maturity carve-out
Drives The sft_fccm stage: E* = max(0, E·(1+HE) − CVA·(1−HC−HFX)) The F-IRB 0.5-year fixed supervisory maturity (M) for repo-style transactions, in place of the 2.5-year default
Regulatory basis CRR Art. 220–223, Art. 271(2) CRR Art. 162(1) (fixed M = 0.5y; deleted under Basel 3.1)
Engine site engine/sft/fccm.py engine/irb/transforms.py

The lending is_sft Boolean is deliberately not renamed as part of the SFT/FCCM separation — that would touch the sealed hierarchy_resolved edge, the IRB transforms and every fixture that sets is_sft — so it is reserved for a standalone future codemod. See the SFT (FCCM EAD) specification.


Equity Exposure Schema

Purpose: Defines equity holdings (SA only under Basel 3.1, IRB approaches withdrawn).

Column Type Required Description
exposure_reference String Yes Unique identifier
counterparty_reference String Yes Link to counterparty
equity_type String No Type of equity exposure (default "other")
currency String No ISO 4217 currency code
carrying_value Float64 No Balance sheet value
fair_value Float64 No Mark-to-market value
is_speculative Boolean No Higher-risk equity (unlisted + business < 5yr)
is_exchange_traded Boolean No Listed on recognised exchange
is_government_supported Boolean No Government-supported programme
is_significant_investment Boolean No >10% of CET1
ciu_approach String No CIU treatment selector — "look_through" (Art. 132(3)), "mandate_based" (Art. 132(4)), or "fallback" (1,250% per Art. 132(2)). When null the calculator selects based on data availability and falls back conservatively
ciu_mandate_rw Float64 No Mandate-based RW (decimal) when ciu_approach = "mandate_based". Calculated upstream from the fund's investment mandate
ciu_third_party_calc Boolean No True when the look-through RW has been calculated by an eligible third party (custodian / depositary / management company) per Art. 132(3) — relaxes the holding-level evidence requirement
fund_reference String No Join key into the CIU Holdings schema. Required when ciu_approach = "look_through" and ciu_third_party_calc = False
fund_nav Float64 No Fund NAV — denominator of the look-through RW formula sum(holding_value_i × rw_i) / fund_nav. See equity-approach spec

Valid equity_type values:

Value Risk Weight Description
central_bank 0% Central bank equity holdings (Art. 133(6))
listed 100% Exchange-traded equities
exchange_traded 100% Listed on recognised exchange
government_supported 100% CRR / 250% B31 Government-supported programme
unlisted 250% Unlisted equities
private_equity 250% Private equity investments
private_equity_diversified 190% Diversified private equity portfolio
speculative 400% Higher-risk (unlisted + business < 5yr)
ciu Look-through Collective investment undertakings
other 250% Other equity exposures

CIU Holdings Schema

Purpose: Per-holding constituents of a Collective Investment Undertaking (CIU) used by the look-through approach (Art. 132(3)). Each row represents one underlying exposure inside a fund, joined to the parent equity row via fund_reference. The look-through RW is computed as sum(holding_value_i × rw_i) / fund_nav and applied to the equity exposure's carrying value.

File: No canonical loader path — passed in-memory via DataSourceConfig.ciu_holdings_file (loader source: engine/loader.py:139). Not part of the standard fixture registry, since the CIU look-through is opt-in.

When required: Only when one or more EQUITY_EXPOSURE rows have ciu_approach = "look_through" and ciu_third_party_calc = False. If absent, CIU rows fall through to the mandate-based or punitive 1,250% fallback (Art. 132(2)) — see equity-approach spec.

Column Type Required Description
fund_reference String Yes Join key to EQUITY_EXPOSURE.fund_reference — uniquely identifies the parent fund
holding_reference String Yes Unique identifier for the holding within the fund
exposure_class String Yes Exposure class of the underlying holding ("corporate", "institution", "sovereign", etc.) — drives the SA risk weight applied
cqs Int8 No Credit Quality Step of the underlying holding, where applicable
holding_value Float64 No Market value of the holding inside the fund — numerator of the look-through formula

Regulatory references:

  • CRR Art. 132: CIU treatment under the Standardised Approach
  • PRA PS1/26 Art. 132(2): Punitive 1,250% fallback when neither look-through nor mandate-based data is available
  • PRA PS1/26 Art. 132(3): Look-through approach — requires sufficient and frequent information about the underlying exposures
  • PRA PS1/26 Art. 132(4): Mandate-based approach — uses the fund's investment mandate / prospectus

Example:

import polars as pl

ciu_holdings = pl.DataFrame({
    "fund_reference": ["FUND_001", "FUND_001", "FUND_001"],
    "holding_reference": ["HOLD_001", "HOLD_002", "HOLD_003"],
    "exposure_class": ["corporate", "sovereign", "institution"],
    "cqs": [3, 1, 2],
    "holding_value": [40_000_000.0, 30_000_000.0, 30_000_000.0],
})

# Parent equity row links via fund_reference:
equity_exposures = pl.DataFrame({
    "exposure_reference": ["EQ_001"],
    "counterparty_reference": ["FUND_MGR_001"],
    "equity_type": ["ciu"],
    "ciu_approach": ["look_through"],
    "ciu_third_party_calc": [False],
    "fund_reference": ["FUND_001"],
    "fund_nav": [100_000_000.0],
    "carrying_value": [5_000_000.0],
    # ... other equity fields
})

Facility Mapping Schema

Purpose: Defines parent-child relationships between facilities, loans, and contingents.

File: exposures/facility_mapping.parquet

Column Type Required Description
parent_facility_reference String Yes Parent facility reference
child_reference String Yes Child facility/loan/contingent reference
child_type String Yes facility, loan, or contingent

Example:

import polars as pl

facility_mapping = pl.DataFrame({
    "parent_facility_reference": ["FAC_001", "FAC_001", "FAC_001"],
    "child_reference": ["LOAN_001", "LOAN_002", "FAC_001A"],
    "child_type": ["loan", "loan", "facility"],
})

Org Mapping Schema

Purpose: Defines organisation hierarchy for rating and turnover inheritance.

File: mapping/org_mapping.parquet

Column Type Required Description
parent_counterparty_reference String Yes Parent counterparty reference
child_counterparty_reference String Yes Child counterparty reference

Example:

import polars as pl

org_mapping = pl.DataFrame({
    "parent_counterparty_reference": ["CORP_PARENT", "CORP_PARENT"],
    "child_counterparty_reference": ["CORP_001", "CORP_002"],
})

Lending Mapping Schema

Purpose: Defines lending groups for retail threshold aggregation.

File: mapping/lending_mapping.parquet

Column Type Required Description
parent_counterparty_reference String Yes Lending group lead reference
child_counterparty_reference String Yes Member counterparty reference

Exposures are aggregated to the group level for retail eligibility (threshold: EUR 1m CRR Art. 123(c) / GBP 880k Basel 3.1 Art. 123(1)(b)(ii)).


Model Permissions Schema

Purpose: Defines per-model IRB approach permissions, enabling granular control over which exposures can use FIRB, AIRB, or slotting. When permission_mode=PermissionMode.IRB, model permissions drive all approach routing. When absent in IRB mode, the pipeline falls back to SA for all exposures with a warning.

Why model-level permissions matter: Banks typically have multiple IRB models, each approved for specific exposure classes, geographies, and portfolios. This schema allows the calculator to resolve the correct approach per-exposure based on the model it belongs to, rather than applying a single org-wide permission.

File: config/model_permissions.parquet

Column Type Required Description
model_id String Yes Unique model identifier (e.g., "UK_CORP_PD_01") — referenced by model_id on internal ratings
exposure_class String Yes ExposureClass value this permission covers (e.g., "corporate", "institution")
approach String Yes Approved approach: "foundation_irb", "advanced_irb", or "slotting"
country_codes String No Comma-separated ISO country codes where this permission applies. Null = all geographies.
excluded_book_codes String No Comma-separated book codes excluded from this permission. Null = no exclusions.

Optional columns

When country_codes or excluded_book_codes columns are entirely absent from the input file, they are treated as null for all rows — all geographies are permitted and no book codes are excluded. You only need to include these columns if you want to restrict permissions by geography or exclude specific book codes.

Approach determination logic:

Condition Result
AIRB permission + internal_pd + modelled lgd A-IRB
AIRB permission + internal_pd + no lgd SA (falls back unless FIRB permission also exists)
FIRB permission + internal_pd + no lgd F-IRB (uses regulatory LGD floors)
Both AIRB + FIRB permissions + internal_pd + lgd A-IRB (higher approach wins)
Both AIRB + FIRB permissions + internal_pd + no lgd F-IRB (fallback)
Slotting permission + internal_pd Slotting
No model_id on internal rating SA (default)

Example:

import polars as pl

model_permissions = pl.DataFrame({
    "model_id": ["UK_CORP_PD_01", "UK_CORP_PD_01", "EU_INST_01"],
    "exposure_class": ["corporate", "corporate_sme", "institution"],
    "approach": ["advanced_irb", "foundation_irb", "advanced_irb"],
    "country_codes": ["GB", "GB,IE", None],  # None = all geographies
    "excluded_book_codes": [None, "LEGACY_BOOK", None],
})

Data Preparation Checklist

Before running the calculator, verify your data meets these requirements:

  • [ ] All required files present in expected locations
  • [ ] Column names match schema exactly (case-sensitive)
  • [ ] Data types match expected types
  • [ ] All required columns have non-null values
  • [ ] Reference columns have valid foreign key relationships
  • [ ] Dates are in YYYY-MM-DD format
  • [ ] Currency codes are valid ISO 4217
  • [ ] Country codes are valid ISO 3166-1 alpha-2
  • [ ] Numeric amounts are non-negative where expected
  • [ ] PD values are in range [0, 1]
  • [ ] LGD values are in range [0, 1.25]

See Data Validation Guide for validation functions and troubleshooting.


Next Steps