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 |
| Equity Exposure | N/A | No | Equity holdings |
| 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 |
Yes | Legal name of the counterparty |
entity_type |
String |
Yes | Single source of truth for exposure class (see valid values below) |
country_code |
String |
Yes | 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 large FSE threshold - EUR 70bn per CRR Art. 4(1)(146)) |
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) |
scra_grade |
String |
No | SCRA grade for unrated institutions: "A", "B", "C" (Basel 3.1 CRE20.16-21) |
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 - 0% RW if on eligible list |
international_org |
MDB | CENTRAL_GOVT_CENTRAL_BANK | CRR Art. 118 |
| 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) |
| 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 |
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, these typically receive 0% RW from the MDB table. 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) Determination¶
The following entity types are classified as Financial Sector Entities for FI scalar purposes:
institutionbankccpfinancial_institutionpse_institution(PSE treated as institution)rgla_institution(RGLA treated as institution)
FI Scalar applies when (CRR Art. 153(2)):
1. Large FSE: total_assets >= EUR 70bn, OR
2. Financial sector entity with apply_fi_scalar = True
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:
- Entity Type Mapping: Maps
entity_typeto both SA and IRB exposure classes - SME Classification: Checks if
annual_revenue < EUR 50mfor corporates - Retail Threshold: Aggregates exposures by lending group against EUR 1m threshold
- Default Identification: Checks
default_statusfor defaulted treatment - FI Scalar Determination: Identifies large/unregulated FSEs for 1.25x correlation
- 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 |
Yes | Product classification |
book_code |
String |
Yes | Portfolio/book classification |
counterparty_reference |
String |
Yes | Link to counterparty |
value_date |
Date |
Yes | Facility start date |
maturity_date |
Date |
Yes | Final maturity date |
currency |
String |
Yes | ISO 4217 currency code |
limit |
Float64 |
Yes | Committed facility limit |
committed |
Boolean |
Yes | Whether facility is committed |
lgd |
Float64 |
No | Internal LGD estimate (A-IRB) |
beel |
Float64 |
No | Best estimate expected loss |
is_revolving |
Boolean |
Yes | Revolving vs term facility |
is_qrre_transactor |
Boolean |
No | QRRE transactor flag (CRR Art. 147(5), CRE30.55) — True if borrower repays in full each period |
seniority |
String |
Yes | senior or subordinated (affects F-IRB LGD) |
risk_type |
String |
Yes | Off-balance sheet risk category (see below) |
ccf_modelled |
Float64 |
No | A-IRB modelled CCF (0.0-1.5) |
is_short_term_trade_lc |
Boolean |
No | Short-term trade LC for goods movement (Art. 166(9)) |
is_buy_to_let |
Boolean |
No | Buy-to-let property lending — excluded from SME supporting factor (CRR Art. 501) |
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 |
Yes | Product classification |
book_code |
String |
Yes | Portfolio/book classification |
counterparty_reference |
String |
Yes | Link to counterparty |
value_date |
Date |
Yes | Loan origination date |
maturity_date |
Date |
Yes | Loan maturity date |
currency |
String |
Yes | ISO 4217 currency code |
drawn_amount |
Float64 |
Yes | Outstanding principal balance |
interest |
Float64 |
No | Accrued interest (adds to on-balance-sheet EAD) |
lgd |
Float64 |
No | Internal LGD estimate (A-IRB) |
beel |
Float64 |
No | Best estimate expected loss |
seniority |
String |
Yes | senior or subordinated (affects F-IRB LGD) |
is_buy_to_let |
Boolean |
No | Buy-to-let property lending — excluded from SME supporting factor (CRR Art. 501) |
has_netting_agreement |
Boolean |
No | Whether loan is part of a netting agreement |
netting_facility_reference |
String |
No | Reference to netting facility (if applicable) |
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],
"has_netting_agreement": [False, False, False],
"netting_facility_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 |
Yes | Product classification |
book_code |
String |
Yes | Portfolio/book classification |
counterparty_reference |
String |
Yes | Link to counterparty |
value_date |
Date |
Yes | Contract start date |
maturity_date |
Date |
Yes | Contract expiry date |
currency |
String |
Yes | ISO 4217 currency code |
nominal_amount |
Float64 |
Yes | Notional/nominal amount |
lgd |
Float64 |
No | Internal LGD estimate (A-IRB) |
beel |
Float64 |
No | Best estimate expected loss |
seniority |
String |
Yes | senior or subordinated |
risk_type |
String |
Yes | Off-balance sheet risk category (see Facility schema) |
ccf_modelled |
Float64 |
No | A-IRB modelled CCF (0.0-1.5) |
is_short_term_trade_lc |
Boolean |
No | Short-term trade LC for goods movement (Art. 166(9)) |
bs_type |
String |
No | "ONB" (on-balance-sheet / drawn) or "OFB" (off-balance-sheet / undrawn). Default: "OFB" |
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 |
Yes | 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 |
is_eligible_financial_collateral |
Boolean |
No | Meets SA eligibility (CRR Art 197) |
is_eligible_irb_collateral |
Boolean |
No | Meets IRB eligibility (CRR Art 199) |
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 | Loan-to-value ratio (RE only) |
is_income_producing |
Boolean |
No | Material income dependence (CRE) |
is_adc |
Boolean |
No | Acquisition/Development/Construction |
is_presold |
Boolean |
No | ADC pre-sold to qualifying buyer |
Valid collateral_type values:
| Value | Description |
|---|---|
cash |
Cash collateral (0% haircut) |
gold |
Gold collateral (15% 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],
"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 |
Yes | Type of guarantee |
guarantor |
String |
Yes | Guarantor counterparty reference |
currency |
String |
Yes | ISO 4217 currency code |
maturity_date |
Date |
No | Guarantee expiry date |
amount_covered |
Float64 |
Yes | Amount covered by guarantee |
percentage_covered |
Float64 |
No | Percentage of exposure covered |
beneficiary_type |
String |
Yes | Level of allocation |
beneficiary_reference |
String |
Yes | Reference to counterparty/facility/loan |
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. |
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% |
*UK deviation: CQS 2 institutions get 30% RW (not 50%)
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 |
slotting_category |
String |
Yes | 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) |
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 |
Yes | Type of equity exposure |
currency |
String |
Yes | ISO 4217 currency code |
carrying_value |
Float64 |
Yes | Balance sheet value |
fair_value |
Float64 |
No | Mark-to-market value |
is_speculative |
Boolean |
No | Speculative unlisted equity |
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 |
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% | Government-supported programme |
unlisted |
250% | Unlisted equities |
private_equity |
250% | Private equity investments |
private_equity_diversified |
190% | Diversified private equity portfolio |
speculative |
400% | Speculative unlisted |
ciu |
Look-through | Collective investment undertakings |
other |
250% | Other equity exposures |
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 / GBP 880k).
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-DDformat - [ ] 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¶
- Data Validation Guide - Validation rules and error handling
- Intermediate Schemas - Pipeline intermediate data
- Output Schemas - Calculation results