Retail Exposures¶
Retail exposures are claims on individuals or small businesses that meet specific criteria for size, product type, and portfolio management.
Definition¶
Retail exposures must meet ALL of the following criteria:
| Criterion | Requirement |
|---|---|
| Counterparty | Individual or small business |
| Product | Revolving credit, personal loans, mortgages, or small business facilities |
| Size | Total exposure ≤ EUR 1m (CRR, FX-converted) or ≤ GBP 880k (Basel 3.1, fixed) |
| Management | Managed as part of a portfolio with similar characteristics |
Conceptual Logic
The following illustrates the retail classification decision logic. For the actual implementation,
see stages/classify/subtypes.py
(reclassify_corporate_to_retail).
# Conceptual overview - actual implementation in subtypes.reclassify_corporate_to_retail
def is_retail(exposure, counterparty, lending_group_adjusted_exposure):
return (
counterparty.type in ["individual", "retail", "small_business"] and
lending_group_adjusted_exposure <= 1_000_000 and # EUR threshold
is_managed_as_retail_pool(exposure) # cp_is_managed_as_retail flag
)
Actual Implementation (stages/classify/subtypes.py)
def reclassify_corporate_to_retail(
exposures: pl.LazyFrame,
config: CalculationConfig,
schema_names: set[str],
*,
pack: ResolvedRulepack | None = None,
) -> pl.LazyFrame:
"""
Reclassify qualifying corporates to retail.
Retail outranks corporate in the exposure class waterfall per
CRR Art. 147(5) / Basel CRE30.16-17. Corporate exposures are
reclassified to retail when all of:
1. Managed as part of a retail pool (is_managed_as_retail=True)
2. Aggregated exposure < EUR 1m (qualifies_as_retail=True)
3. Has internally modelled LGD (lgd IS NOT NULL)
4. Counterparty is SME-sized (CRR Art. 4(1)(128D) — turnover <
EUR 50m OR balance-sheet total < EUR 43m when turnover null)
Reclassification is an exposure-class decision, independent of
approach permissions. The approach (AIRB/FIRB/SA) is determined
later by _assign_approach using model_permissions.
"""
resolved_pack = pack if pack is not None else RulepackV0.from_config(config).pack
is_sme_by_size = is_sme_by_size_expr(config, pack=resolved_pack)
# Reclassification eligibility expression (inlined — not a column ref)
reclassification_expr = (
(
pl.col("exposure_class").is_in(
[
ExposureClass.CORPORATE.value,
ExposureClass.CORPORATE_SME.value,
]
)
)
& (pl.col("cp_is_managed_as_retail") == True) # noqa: E712
& (pl.col("qualifies_as_retail") == True) # noqa: E712
& (pl.col("lgd").is_not_null())
& is_sme_by_size
)
# Has property collateral expression (inlined)
has_property_expr = _build_has_property_expr(schema_names)
# Single .with_columns: reclassified_to_retail, has_property_collateral,
# exposure_class update — all using inlined expressions (not column refs)
return exposures.with_columns(
[
reclassification_expr.alias("reclassified_to_retail"),
has_property_expr.alias("has_property_collateral"),
pl.when(reclassification_expr & has_property_expr)
.then(pl.lit(ExposureClass.RETAIL_MORTGAGE.value))
.when(reclassification_expr)
.then(pl.lit(ExposureClass.RETAIL_OTHER.value))
.otherwise(pl.col("exposure_class"))
.alias("exposure_class"),
]
)
Retail Sub-Classes¶
| Sub-Class | Description | IRB Correlation |
|---|---|---|
| Retail Mortgage | Residential mortgages | 15% |
| Retail QRRE | Qualifying revolving retail | 4% |
| Retail Other | All other retail | 3-16% |
Retail Mortgage¶
Definition¶
Exposures secured by residential property that is or will be: - Occupied by the borrower, OR - Rented out
SA Risk Weights¶
For exposures classified as RETAIL_MORTGAGE, CRR Art. 125 applies 35% to
the portion of the exposure up to 80% LTV and 75% to any residual portion
above 80% LTV (rather than 75% on the whole loan). Basel 3.1 replaces this
treatment with LTV-based bands from 20% to 70%+ for general mortgages, and
30% to 105% for income-producing (buy-to-let).
The CRR 35%/75% treatment is conditional on the Art. 125(2) qualifying
conditions (property value not materially dependent on borrower credit
quality, repayment not materially dependent on cash flows from the property,
Art. 208 / 229 valuation requirements). Residential-mortgage-secured
exposures to non-retail counterparties (corporates, institutions) are
not routed through RETAIL_MORTGAGE; they enter the SA real-estate
loan-splitter via RESIDENTIAL_MORTGAGE instead — see
Real Estate Loan-Splitter.
Details: See Key Differences — Residential Real Estate for the complete LTV tables.
IRB Treatment¶
Retail mortgage correlation is fixed at 15% with no maturity adjustment. PD floors: 0.03% (CRR) / 0.10% (Basel 3.1, Art. 163(1)(b)). Basel 3.1 introduces a 5% LGD floor for residential RE.
Details: See IRB Approach for the full formula and parameter details.
QRRE (Qualifying Revolving Retail Exposures)¶
Definition¶
To qualify as QRRE, ALL criteria must be met:
| Criterion | Requirement |
|---|---|
| Counterparty | Individual (not corporate) |
| Product | Revolving credit line |
| Maximum limit | ≤ EUR 100,000 |
| Security | Unsecured |
| Cancellability | Unconditionally cancellable |
Examples: - Credit cards - Personal overdrafts - Revolving personal lines
SA Risk Weight¶
| Framework | Non-Transactor | Transactor |
|---|---|---|
| CRR | 75% | 75% (no split) |
| Basel 3.1 | 75% (Art. 123(3)(b)) | 45% (Art. 123(3)(a)) |
Transactor vs Non-Transactor (Basel 3.1)¶
Basel 3.1 introduces a 45% preferential SA risk weight (and a 0.05% IRB PD floor) for transactor QRRE exposures. The PRA Glossary (PS1/26 Appendix 1, p. 9) defines a transactor via one of two behavioural tests over the previous 12-month period:
- A revolving facility (credit cards, charge cards, and similar) where the obligor has repaid the balance in full at each scheduled repayment date for the previous 12-month period; or
- An overdraft facility that the obligor has not drawn down over the previous 12-month period.
Accounts that fail either test — including newly originated accounts with less than 12 months of repayment history (Art. 154(4)) — are non-transactor exposures. Set is_qrre_transactor = True in the input only when the 12-month history has been verified by the institution; the calculator does not validate the underlying behaviour. See the Basel 3.1 SA Risk Weights spec for full details.
IRB Treatment¶
QRRE correlation is fixed at 4%. PD floors: 0.03% (CRR all), 0.05% (Basel 3.1 transactors, Art. 163(1)(c)), 0.10% (Basel 3.1 revolvers). Bank-estimated LGD subject to 50% floor (Basel 3.1 unsecured). The same transactor definition (PRA Glossary) governs the IRB PD-floor split; Art. 154(4) requires any account with less than 12 months of repayment history to be classified as non-transactor for IRB purposes.
Retail Other¶
Definition¶
All retail exposures not qualifying as mortgage or QRRE: - Personal loans - Auto finance - Consumer durable financing - Small business facilities (below retail threshold: EUR 1m CRR / GBP 880k Basel 3.1)
SA Risk Weight¶
| Framework | Risk Weight |
|---|---|
| CRR | 75% |
| Basel 3.1 | 75% |
IRB Treatment¶
Other retail correlation is PD-dependent (3%–16%), decreasing as PD increases. No maturity adjustment for retail.
Details: See IRB Approach — Retail Correlations for the formula and correlation values by PD.
Calculation Examples¶
Example 1: Residential Mortgage (SA)¶
Exposure: - £250,000 mortgage - Property value: £350,000 - LTV: 71.4% - Owner-occupied
CRR Calculation:
Basel 3.1 Calculation:
Example 2: Credit Card (QRRE)¶
Exposure: - £15,000 credit limit - £8,000 current balance - Unconditionally cancellable - Revolver (carries balance)
CRR Calculation:
# QRRE 75% RW
# CCF = 0% for unconditionally cancellable (CRR)
EAD = £8,000 # Current balance only
Risk_Weight = 75%
RWA = £8,000 × 75% = £6,000
Basel 3.1 Calculation:
# CCF = 10% for unconditionally cancellable
Undrawn = £15,000 - £8,000 = £7,000
EAD = £8,000 + (£7,000 × 10%) = £8,700
# Revolver = 75% RW
Risk_Weight = 75%
RWA = £8,700 × 75% = £6,525
Example 3: Retail IRB¶
Exposure: - £50,000 personal loan - Bank PD: 2% - Bank LGD: 40% - "Other retail" category
Calculation:
# Correlation (PD = 2%)
R = 0.03 × (1 - exp(-35 × 0.02)) / (1 - exp(-35)) +
0.16 × (1 - (1 - exp(-35 × 0.02)) / (1 - exp(-35)))
R = 0.072 # 7.2%
# K calculation (no maturity adjustment for retail)
K ≈ 0.0285
# RWA
RWA = K × 12.5 × EAD
RWA = 0.0285 × 12.5 × £50,000
RWA = £17,813
# Risk Weight equivalent
RW = 35.6%
Lending Groups and Retail Threshold¶
Retail Lending Groups¶
For retail SME exposures, total exposure is calculated across the lending group: - Connected individuals/entities - Common ownership or control - Aggregated for threshold purposes
CRR vs Basel 3.1 Retail Threshold
Under CRR (Art. 123(c)), the retail aggregate exposure limit is EUR 1,000,000 dynamically converted to GBP at the prevailing EUR/GBP rate (default 0.8732 → ~GBP 873k). Under Basel 3.1 (Art. 123(1)(b)(ii)), the PRA replaces this with a fixed GBP 880,000 — no FX conversion required. This eliminates exchange rate volatility from retail classification boundaries. The QRRE individual limit also changes from EUR 100k to GBP 90,000 (Art. 147(5A)(c)). See Key Differences — Retail Classification Threshold for the full comparison.
Residential Property Exclusion (CRR Art. 123(c))¶
Important: Exposures secured by residential property are excluded from the retail threshold calculation when they are assigned to the residential property exposure class under the Standardised Approach.
This exclusion applies because: - Per CRR Art. 123(c), exposures "fully and completely secured on residential property collateral that have been assigned to the exposure class laid down in point (i) of Article 112" are excluded from the aggregation - This means the collateral value (capped at the exposure amount) is deducted from the total amount owed
Key Rules:
| Approach | Residential Property Treatment |
|---|---|
| SA | Excluded from retail threshold; stays as residential mortgage |
| IRB | NOT excluded from retail threshold (per EBA Q&A 2018_4012) |
Conceptual Logic
The following illustrates the residential property exclusion logic. For the actual implementation,
see stages/hierarchy/enrich.py
(enrich_with_property_coverage).
# Conceptual overview - actual implementation in enrich.enrich_with_property_coverage
def calculate_adjusted_exposure(exposures, residential_collateral):
"""
Per CRR Art. 123(c), residential property secured exposures (SA)
are excluded from the retail threshold calculation.
"""
for exposure in exposures:
# Get residential collateral securing this exposure
res_collateral_value = residential_collateral.get(exposure.id, 0)
# Cap at exposure amount (can't exclude more than exposure)
exclusion = min(res_collateral_value, exposure.amount)
# Adjusted exposure for threshold
exposure.for_retail_threshold = exposure.amount - exclusion
return exposures
Actual Implementation (stages/hierarchy/enrich.py)
The real implementation uses Polars LazyFrames for efficient processing:
def enrich_with_property_coverage(
exposures: pl.LazyFrame,
collateral: pl.LazyFrame | None,
) -> pl.LazyFrame:
"""
Add property collateral coverage columns to exposures inline.
Calculates two separate values per exposure:
1. residential_collateral_value: For CRR Art. 123(c) retail threshold exclusion
(only residential property counts for threshold exclusion)
2. property_collateral_value: For retail_mortgage classification
(both residential AND commercial property qualify for mortgage treatment)
Uses .over() window functions for facility/counterparty allocation weights
instead of group_by + join-back, avoiding plan tree branching.
Args:
exposures: Unified exposures with hierarchy metadata
collateral: Collateral data with property_type and market_value
Returns:
Exposures with columns added: residential_collateral_value,
property_collateral_value, has_facility_property_collateral,
exposure_for_retail_threshold
"""
# Per CRR Article 147, "total amount owed" = drawn amount only (not undrawn)
exposures = exposures.with_columns(
pl.col("drawn_amount").clip(lower_bound=0.0).alias("total_exposure_amount"),
)
required_cols = {
"beneficiary_reference",
"collateral_type",
"market_value",
"property_type",
}
if not has_required_columns(collateral, required_cols):
return exposures.with_columns(
[
pl.lit(0.0).alias("residential_collateral_value"),
pl.lit(0.0).alias("property_collateral_value"),
pl.lit(0.0).alias("residential_collateral_value_uncapped"),
pl.lit(0.0).alias("commercial_collateral_value_uncapped"),
pl.lit(False).alias("has_facility_property_collateral"),
pl.lit(False).alias("re_collateral_non_qualifying"),
pl.col("total_exposure_amount").alias("exposure_for_retail_threshold"),
]
)
# Single filter for all property collateral; split residential inline
all_property_collateral = collateral.filter(
pl.col("collateral_type").str.to_lowercase() == "real_estate"
)
# PRA PS1/26 Art. 124(4): a single non-qualifying RE component (Art. 124A
# failure, e.g. valuation-independence breach) forces the WHOLE mixed-RE
# exposure to Art. 124J. Track per-beneficiary whether any RE collateral
# row fails the qualifying test so the classifier can fire the gate.
# ``is_qualifying_re`` has no schema default — null means "unreported"
# and is treated as qualifying here (fill_null(True) is a value fill).
is_non_qualifying_re = pl.col("is_qualifying_re").fill_null(True) == False # noqa: E712
# Multi-level linking with .over() allocation weights
exposures = _join_property_collateral_multi_level(
exposures,
all_property_collateral,
is_non_qualifying_re=is_non_qualifying_re,
)
# Fill nulls, then cap at exposure amount and derive threshold.
# Preserve the UNCAPPED residential / commercial RE collateral values
# for the loan-splitter: the PRA PS1/26 Art. 124(4) pro-rata split is by
# raw collateral value (and the 0.55xV cap is also on raw property value),
# so the per-exposure cap applied below — which exists for the CRR retail
# threshold — must not distort the split shares.
exposures = (
exposures.with_columns(
[
pl.col("residential_collateral_value").fill_null(0.0),
pl.col("property_collateral_value").fill_null(0.0),
pl.col("re_collateral_non_qualifying").fill_null(False),
]
)
.with_columns(
[
pl.col("residential_collateral_value").alias(
"residential_collateral_value_uncapped"
),
(pl.col("property_collateral_value") - pl.col("residential_collateral_value"))
.clip(lower_bound=0.0)
.alias("commercial_collateral_value_uncapped"),
]
)
.with_columns(
[
pl.min_horizontal("residential_collateral_value", "total_exposure_amount").alias(
"residential_collateral_value"
),
pl.min_horizontal("property_collateral_value", "total_exposure_amount").alias(
"property_collateral_value"
),
(
pl.col("total_exposure_amount")
- pl.min_horizontal("residential_collateral_value", "total_exposure_amount")
).alias("exposure_for_retail_threshold"),
]
)
)
return exposures
Lending Group Threshold Check:
The adjusted exposure is aggregated across the connected-client group. When a counterparty is not part of an explicit lending group, the counterparty itself acts as a group-of-one (CRR Art. 4(1)(39)) — every exposure booked against that obligor counts toward the limit, not just the current line.
# Total adjusted exposure to the connected-client group (from hierarchy resolver).
# If a lending_group_reference exists, sum across every member; otherwise sum
# across the counterparty's own exposures.
group_key = exposure.lending_group_reference or exposure.counterparty_reference
adjusted_group_exposure = sum(
exp.exposure_for_retail_threshold
for exp in all_exposures
if (exp.lending_group_reference or exp.counterparty_reference) == group_key
)
# Must be ≤ threshold for retail treatment
# CRR: EUR 1m (FX-converted); Basel 3.1: GBP 880k (fixed)
if adjusted_group_exposure <= retail_threshold:
treatment = "RETAIL"
else:
treatment = "CORPORATE_SME" # SMEs retain firm-size adjustment
Treatment When Threshold Exceeded¶
| Counterparty Type | Exceeds Threshold | Treatment |
|---|---|---|
| Individual (mortgage) | Yes | Stays as RETAIL_MORTGAGE (SA Art. 112(i)) |
| Individual (other) | Yes | Reclassified to CORPORATE |
| SME (any product) | Yes | Reclassified to CORPORATE_SME |
Regulatory References: - CRR Art. 123(c) - Retail exclusion for residential property - EBA Q&A 2013_72 - SA residential property exclusion clarification - EBA Q&A 2018_4012 - IRB residential property NOT excluded
Example: Threshold Calculation with Exclusion¶
Scenario: Lending group with EUR 2m total exposure
| Exposure | Amount | Residential Collateral | For Threshold |
|---|---|---|---|
| Term loan | EUR 1m | EUR 0 | EUR 1m |
| Mortgage | EUR 1m | EUR 1m | EUR 0 |
| Total | EUR 2m | EUR 1m |
Result: Adjusted exposure = EUR 1m (at threshold) - qualifies as retail
CRM for Retail¶
Eligible Collateral¶
| Collateral Type | Treatment |
|---|---|
| Residential property | Mortgage RW |
| Financial collateral | Haircut method |
| Physical collateral | LGD reduction (IRB) |
Guarantees¶
Limited guarantee recognition for retail: - Government guarantees accepted - Institution guarantees under conditions - Individual guarantees generally not recognized
Regulatory References¶
| Topic | CRR Article | BCBS CRE | EBA Q&A |
|---|---|---|---|
| Retail definition | Art. 123 (CRR) / Art. 123(1) (B31) | CRE20.50-60 | - |
| Retail threshold | Art. 123(c) (EUR 1m) / Art. 123(1)(b)(ii) (GBP 880k) | CRE20.65 | 2016_2626 |
| Residential property exclusion | Art. 123(c), Art. 112(i) | - | 2013_72, 2018_4012 |
| Retail mortgage | Art. 125 | CRE20.70-75 | - |
| QRRE | Art. 154 | CRE31.10-12 | - |
| Retail IRB | Art. 154 | CRE31 | - |
| Correlation | Art. 154 | CRE31.13-15 | - |