Skip to content

Output Schemas

This page documents the schemas for calculation results and output data produced by each calculator and the final aggregated output.

Source of truth: All schemas are defined in src/rwa_calc/data/schemas.py. Result bundles are defined in src/rwa_calc/contracts/bundles.py.

SA Result Schema

Results from Standardised Approach calculation. Each exposure gets a risk weight looked up from regulatory tables by exposure class and CQS, then RWA = EAD × risk weight.

Source: SA_RESULT_SCHEMA in data/schemas.py

Column Type Description
exposure_reference String Exposure identifier
exposure_class String Regulatory exposure class
final_ead Float64 Exposure at default (from CRM stage)
sa_cqs Int8 Credit Quality Step used (1–6, 0 = unrated)
sa_base_risk_weight Float64 Base RW from regulatory lookup table
sa_rw_adjustment Float64 Any adjustments applied (e.g., defaulted uplift)
sa_rw_adjustment_reason String Reason for adjustment
sa_final_risk_weight Float64 Final SA risk weight
sa_rw_regulatory_ref String CRR article or CRE reference
sa_rwa Float64 final_ead × sa_final_risk_weight

IRB Result Schema

Results from IRB approach calculation (F-IRB and A-IRB). Includes the full IRB formula breakdown: PD → LGD → correlation → capital requirement K → maturity adjustment → RWA.

Source: IRB_RESULT_SCHEMA in data/schemas.py

Column Type Description
exposure_reference String Exposure identifier
exposure_class String Regulatory exposure class
final_ead Float64 Exposure at default
irb_pd_original Float64 PD before flooring
irb_pd_floor Float64 Applicable PD floor
irb_pd_floored Float64 max(pd_original, pd_floor)
irb_lgd_type String "supervisory" (F-IRB) or "modelled" (A-IRB)
irb_lgd_original Float64 LGD before flooring
irb_lgd_floor Float64 Applicable LGD floor (Basel 3.1 only)
irb_lgd_floored Float64 max(lgd_original, lgd_floor)
irb_maturity_m Float64 Effective maturity in years
irb_correlation_r Float64 Asset correlation from formula
irb_maturity_adj_b Float64 Maturity adjustment factor b
irb_capital_k Float64 Capital requirement K
irb_scaling_factor Float64 1.06 (CRR) or 1.0 (Basel 3.1)
irb_risk_weight Float64 12.5 × K × scaling_factor
irb_rwa Float64 final_ead × irb_risk_weight
irb_expected_loss Float64 PD × LGD × EAD

Slotting Result Schema

Results from slotting approach calculation for specialised lending. Risk weights are assigned by supervisory category, lending type, and (under CRR) remaining maturity.

Source: SLOTTING_RESULT_SCHEMA in data/schemas.py

Column Type Description
exposure_reference String Exposure identifier
sl_type String Specialised lending type (see Specialised Lending Schema)
slotting_category String strong/good/satisfactory/weak/default
remaining_maturity_years Float64 Remaining maturity (CRR maturity-band differentiation)
is_hvcre Boolean High Volatility CRE indicator
sl_base_risk_weight Float64 Base slotting risk weight
sl_maturity_adjusted_rw Float64 RW after maturity-band adjustment (CRR)
sl_final_risk_weight Float64 Final slotting risk weight
sl_rwa Float64 final_ead × sl_final_risk_weight

Calculation Output Schema

The master output schema covering all exposure-level results with full audit trail. Designed so that users can investigate why results occurred and replicate calculations from the output data alone.

Source: CALCULATION_OUTPUT_SCHEMA in data/schemas.py

Identification and lineage

Column Type Description
calculation_run_id String Unique run identifier for audit trail
calculation_timestamp Datetime When calculation was performed
exposure_reference String Links to source loan/facility/contingent
exposure_type String "loan", "facility", "contingent"
counterparty_reference String Links to counterparty
book_code String Portfolio/book classification
currency String Exposure currency
model_id String IRB model identifier (for model-level permission audit trail)
basel_version String "3.0" or "3.1"

Counterparty hierarchy (rating inheritance)

Column Type Description
counterparty_has_parent Boolean Whether counterparty is part of org hierarchy
parent_counterparty_reference String Immediate parent in org structure
ultimate_parent_reference String Top-level parent
counterparty_hierarchy_depth Int8 Levels from ultimate parent (0 = top)
rating_inherited Boolean Whether rating came from parent
rating_source_counterparty String Counterparty whose rating was used
rating_inheritance_reason String "own_rating", "parent_rating", etc.

Lending group hierarchy (retail threshold)

Column Type Description
lending_group_reference String Lending group parent if applicable
lending_group_total_exposure Float64 Aggregated exposure across group
retail_threshold_applied Float64 £1m (CRR) or £880k (Basel 3.1)
retail_eligible_via_group Boolean Whether retail classification based on group

Exposure hierarchy (facility structure)

Column Type Description
exposure_has_parent Boolean Whether exposure is child of a facility
parent_facility_reference String Parent facility reference
root_facility_reference String Top-level facility in hierarchy
facility_hierarchy_depth Int8 Levels from root facility
facility_hierarchy_path List(String) Full path from root to this exposure

CRM inheritance (from hierarchy)

Column Type Description
collateral_source_level String "exposure", "facility", "counterparty"
collateral_inherited_from String Reference of entity collateral inherited from
collateral_allocation_method String "direct", "pro_rata", "waterfall", "optimised"
guarantee_source_level String "exposure", "facility", "counterparty"
guarantee_inherited_from String Reference of entity guarantee inherited from
provision_source_level String "exposure", "facility", "counterparty"
provision_inherited_from String Reference of entity provision inherited from
crm_allocation_notes String Explanation of how CRM was allocated

Exposure classification

Column Type Description
exposure_class String Determined regulatory class
exposure_class_reason String Explanation of classification decision
approach_permitted String "standardised", "foundation_irb", "advanced_irb" based on permissions
approach_applied String Actual approach used
approach_selection_reason String Why this approach was selected

Original exposure values

Column Type Description
drawn_amount Float64 Original drawn balance
undrawn_amount Float64 Undrawn commitment amount
original_maturity_date Date Contractual maturity
residual_maturity_years Float64 Years to maturity

CCF application (off-balance sheet conversion)

Column Type Description
ccf_applied Float64 CCF percentage (0%, 20%, 40%, 50%, 100%)
ccf_source String Reference to regulatory article
converted_undrawn Float64 undrawn_amount × ccf_applied

CRM — collateral impact

Column Type Description
collateral_references List(String) IDs of collateral items used
collateral_types List(String) Types of collateral
collateral_gross_value Float64 Total market value before haircuts
collateral_haircut_applied Float64 Weighted average haircut percentage
fx_haircut_applied Float64 FX mismatch haircut (8% or 0%)
maturity_mismatch_adjustment Float64 Adjustment for maturity mismatch
collateral_adjusted_value Float64 Net collateral value after haircuts

CRM — life insurance collateral (Art. 232)

Captures life-insurance-policy collateral recognised under the Other Funded Credit Protection Method (PS1/26 Art. 232 / CRR Art. 232). Unlike financial collateral, life-insurance policies do not reduce EAD on the SA side — they map the secured portion to a preferential risk weight via the Art. 232(3) insurer-RW table:

Insurer SA RW Mapped secured-portion RW
20% 20%
30% / 50% 35%
65% / 100% / 135% 70%
150% 150%

The SA calculator then blends the mapped RW across the secured / unsecured portions of the exposure (no Art. 222 floor applies, unlike FCSM). On the IRB side, life-insurance collateral feeds the LGD waterfall with LGD_S = 40% (Art. 232(2)(b)) — the columns below describe the SA-side mechanic only.

References: PRA PS1/26 Art. 232 (Other Funded Credit Protection Method, including the new 7-tier mapping with 30% / 65% / 135% bands); CRR Art. 232 (4-tier 20% / 50% / 100% / 150% mapping); Art. 200(b) (eligibility); Art. 212(2) (operational requirements). Source: engine/crm/life_insurance.py::compute_life_insurance_columns.

Column Type Description
life_ins_collateral_value Float64 Total surrender value (sum of market_value across eligible life-insurance policies pledged to the exposure), capped at ead_gross. Defaults to 0.0 when no life-insurance collateral is present.
life_ins_secured_rw Float64 Value-weighted Art. 232(3) mapped risk weight across the pledged policies. Defaults to 0.0 when no life-insurance collateral is present. Consumed via lf.pipe(apply_life_insurance_rw_mapping) (engine/sa/rw_adjustments.py) during SA risk-weight blending.

Single source of truth — CRM methodology

The Art. 232 derivation table, eligibility gates, and CRR vs PS1/26 differences (4-tier vs 7-tier insurer-RW mapping, OFCP scope gate, mandatory maturity-mismatch adjustment) are documented in Basel 3.1 CRM — Other Funded Credit Protection Method (Art. 232). These two columns are emitted on the exposure frame by the CRM processor and survive through to the SA result frame as auxiliary columns (they are not part of the canonical SA_RESULT_SCHEMA dict but are present whenever life-insurance collateral exists in the input bundle).

CRM — guarantee impact (substitution approach)

Column Type Description
guarantee_references List(String) IDs of guarantees used
guarantor_references List(String) Guarantor counterparty IDs
guarantee_coverage_pct Float64 Percentage of exposure guaranteed
guaranteed_amount Float64 Amount covered by guarantee
guarantor_risk_weight Float64 RW of guarantor (for substitution)
guarantee_benefit Float64 RWA reduction from guarantee

Pre/post CRM counterparty tracking

Column Type Description
pre_crm_counterparty_reference String Original borrower reference
pre_crm_exposure_class String Original exposure class
post_crm_counterparty_guaranteed String Guarantor reference for guaranteed portion
post_crm_exposure_class_guaranteed String Derived from guarantor's entity_type
guarantor_reference String Foreign key to guarantor data
is_guaranteed Boolean Whether exposure has effective guarantee
guaranteed_portion Float64 EAD covered by guarantee
unguaranteed_portion Float64 EAD not covered
pre_crm_risk_weight Float64 Borrower's RW before substitution
guarantee_benefit_rw Float64 RW reduction from guarantee
rwa_irb_original Float64 IRB RWA before guarantee substitution
risk_weight_irb_original Float64 IRB RW before guarantee substitution
guarantee_method_used String "SA_RW_SUBSTITUTION", "PD_SUBSTITUTION", or "NO_GUARANTEE"
guarantee_status String Detailed status

CRM — provision impact

Column Type Description
provision_references List(String) IDs of provisions applied
scra_provision_amount Float64 Specific provisions
gcra_provision_amount Float64 General provisions
provision_capped_amount Float64 Amount eligible for CRM

CRM — currency mismatch (Basel 3.1 only)

Captures the unhedged-FX retail uplift for residential mortgages and qualifying retail exposures whose servicing currency differs from the borrower's primary income currency.

Reference: PRA PS1/26 Art. 123B / BCBS CRE20.93 — applies a 1.5× risk-weight multiplier (capped at 150%) to the otherwise-applicable risk weight when there is no natural or financial hedge in place. Under CRR there is no equivalent retail FX uplift.

Column Type Description
borrower_income_currency String ISO 4217 currency of borrower's primary income (mirrored from input)
currency_mismatch_multiplier_applied Boolean True if the 1.5× RW multiplier was applied (Basel 3.1 only; always False under CRR)

Source field on input

borrower_income_currency is also an input field on LoanData; the value on the output is the resolved value used for the multiplier test (after any inheritance from the counterparty). See Input Schemas — Counterparty.

EAD calculation

Column Type Description
gross_ead Float64 drawn + converted_undrawn
ead_after_collateral Float64 After collateral CRM
ead_after_guarantee Float64 Portion not guaranteed
final_ead Float64 Final EAD for RWA calculation
ead_calculation_method String "simple", "comprehensive", "supervisory_haircut"

Risk weight determination — SA

Column Type Description
sa_cqs Int8 Credit Quality Step (1–6, 0 = unrated)
sa_rating_source String Rating agency or "internal"
sa_base_risk_weight Float64 Base RW from lookup table
sa_rw_adjustment Float64 Adjustments applied
sa_rw_adjustment_reason String Reason for adjustment
sa_final_risk_weight Float64 Final SA risk weight
sa_rw_regulatory_ref String CRR article or CRE reference

Risk weight determination — IRB

Column Type Description
irb_pd_original Float64 PD before flooring
irb_pd_floor Float64 Applicable PD floor
irb_pd_floored Float64 max(pd_original, pd_floor)
irb_lgd_type String "supervisory" (F-IRB) or "modelled" (A-IRB)
irb_lgd_original Float64 LGD before flooring
irb_lgd_floor Float64 LGD floor (Basel 3.1)
irb_lgd_floored Float64 max(lgd_original, lgd_floor)
irb_maturity_m Float64 Effective maturity (M)
irb_correlation_r Float64 Asset correlation
irb_maturity_adj_b Float64 Maturity adjustment factor
irb_capital_k Float64 Capital requirement (K)
irb_risk_weight Float64 12.5 × K × scaling_factor

Specialised lending and equity

Column Type Description
sl_type String SL category if applicable
sl_slotting_category String strong/good/satisfactory/weak/default
sl_risk_weight Float64 Slotting RW
equity_type String Equity category if applicable
equity_risk_weight Float64 Equity RW

Real estate specific

Column Type Description
property_type String "residential" / "commercial"
property_ltv Float64 Loan-to-value ratio
ltv_band String LTV band for RW lookup
is_income_producing Boolean CRE income flag
is_adc Boolean ADC exposure flag
mortgage_risk_weight Float64 LTV-based RW

Final RWA calculation

Column Type Description
rwa_before_floor Float64 EAD × RW (before output floor)
sa_equivalent_rwa Float64 SA RWA for floor comparison
output_floor_pct Float64 Floor percentage (72.5% for Basel 3.1)
output_floor_rwa Float64 sa_equivalent_rwa × floor_pct
floor_binding Boolean Whether floor increased RWA
floor_impact Float64 Additional RWA from floor
final_rwa Float64 max(rwa_before_floor, output_floor_rwa)
risk_weight_effective Float64 final_rwa / final_ead (implied RW)

Post-model adjustments (Basel 3.1 only)

Captures the IRB post-model adjustment (PMA) overlays required by PRA PS1/26 to compensate for known IRB model deficiencies. Sequencing is regulatorily prescribed: the mortgage RW floor (Art. 154(4A)(b)) is applied first to establish the post-floor RWEA base, then general PMA scalars (Art. 146(3) / Art. 153(5A) / Art. 154(4A)(a)) and unrecognised-exposure adjustments are applied on top of the floored amount.

References: PRA PS1/26 Art. 146(3) (PMA root obligation), Art. 153(5A) (corporate / institution / sovereign sequencing), Art. 154(4A) (retail sequencing and 10% mortgage RW floor), Art. 158(6A) (EL monotonicity — PMA can only increase EL, never decrease it).

Column Type Description
rwa_pre_adjustments Float64 RWEA before post-model adjustments (post-formula, post-mortgage-floor)
mortgage_rw_floor_adjustment Float64 RWEA increase from the 10% residential mortgage RW floor (Art. 154(4A)(b))
post_model_adjustment_rwa Float64 General PMA add-on to RWEA (Art. 146(3) / Art. 153(5A) / Art. 154(4A)(a))
unrecognised_exposure_adjustment Float64 RWEA increase covering exposures not captured by the IRB model
el_pre_adjustment Float64 Expected loss before post-model adjustments
post_model_adjustment_el Float64 General PMA add-on to EL — must be ≥ 0 (Art. 158(6A) monotonicity)
el_after_adjustment Float64 EL after post-model adjustments

Reporting

PMA add-ons are reported in COREP IRB column 0252 (adjustment for post-model adjustments). See A-IRB Specification — Post-Model Adjustments for the formulae and worked examples.

Double default (CRR only)

CRR Art. 153(3) provides a double-default treatment for IRB exposures with eligible unfunded credit protection (Art. 202 — eligible protection providers; Art. 217-218 — operational requirements). Under PRA PS1/26 Art. 153(3), Art. 202, and Art. 217 are all "[Note: Provision left blank]" — the double-default treatment has been removed and these columns will be False / 0 / null for Basel 3.1 runs.

References: CRR Art. 153(3) (RWEA formula with double-default scalar), Art. 202 (eligible protection providers), Art. 217-218 (operational requirements).

Column Type Description
is_double_default_eligible Boolean Whether the exposure qualifies for DD treatment under CRR Art. 153(3) (always False under Basel 3.1)
double_default_unfunded_protection Float64 Guaranteed portion treated under DD — feeds COREP CR IRB column 0220
irb_lgd_double_default Float64 LGD used in the DD formula (the obligor's own LGD, not the protection provider's)

Basel 3.1 deprecation

For Basel 3.1 / PRA PS1/26 calculations these columns are populated for schema parity but the DD treatment is not applied. Guaranteed exposures fall back to standard parameter substitution (Art. 236) or risk-weight substitution (Art. 235). See CRM methodology — Double Default.

Expected loss (IRB)

EL is compared against Pool B of Art. 159 — provisions plus additional value adjustments (AVA, Art. 34) plus other own-funds reductions. The Pool B formula determines whether IRB exposures generate a CET1 deduction (el_shortfall, Art. 36(1)(d)) or a T2 credit (el_excess, capped at 0.6% of IRB credit-risk RWA, Art. 62(d)).

References: CRR Art. 159(1)(a) (provisions), Art. 159(1)(c) / Art. 34 (AVA), Art. 159(1)(d) (other own-funds reductions). When ava_amount or other_own_funds_reductions are absent from the input bundle, they default to zero so that pre-Pool-B implementations behave the same as before.

Column Type Description
irb_expected_loss Float64 PD × LGD × EAD
provision_held Float64 Total provision amount allocated to this IRB exposure
ava_amount Float64 Additional value adjustments (Art. 34) — Pool B component (Art. 159(1)(c))
other_own_funds_reductions Float64 Other own-funds reductions — Pool B component (Art. 159(1)(d))
el_shortfall Float64 max(0, EL − pool_b) where pool_b = provision_held + ava_amount + other_own_funds_reductions
el_excess Float64 max(0, pool_b − EL)

Portfolio totals

Per-exposure el_shortfall / el_excess are aggregated into the ELPortfolioSummary bundle, where t2_credit_cap = 0.6% × total_irb_rwa and t2_credit = min(total_el_excess, t2_credit_cap) per Art. 62(d). See the Provisions specification — Portfolio-Level Summary for portfolio-level Pool B aggregates (total_ava_amount, total_other_own_funds_reductions, total_pool_b).

Supporting factors (CRR only)

The supporting-factor columns capture both the SME (CRR Art. 501) and infrastructure (CRR Art. 501a) RWA reductions. Under Basel 3.1 / PRA PS1/26 these factors are not available and the columns are populated for schema parity only (supporting_factor = 1.0, supporting_factor_applied = False). The *_applied flag is generic — it is True whenever any qualifying factor was applied, regardless of whether the binding factor was SME or infrastructure.

Column Type Description
supporting_factor Float64 Effective (most beneficial) factor applied — min(sme_factor, infra_factor). Defaults to 1.0 when no factor applies or under Basel 3.1.
supporting_factor_applied Boolean True when supporting_factor < 1.0. Generic flag covering both Art. 501 (SME) and Art. 501a (infrastructure).
rwa_pre_factor Float64 RWA before any supporting factor was applied.
rwa_post_factor Float64 rwa_pre_factor × supporting_factor — RWA after the most beneficial factor.
sme_supporting_factor Float64 SME factor component (0.7619 below threshold / 0.85 above, blended on E*). CRR only.
infra_supporting_factor Float64 Infrastructure factor component (0.75). CRR only.
supporting_factor_benefit Float64 RWA reduction from the applied factor (rwa_pre_factor − rwa_post_factor).

Column rename — generic supporting_factor_applied

Earlier releases emitted sme_supporting_factor_applied. The column was renamed to the generic supporting_factor_applied when the Art. 501a infrastructure factor was added to the same code path (engine/supporting_factors.py, engine/aggregator/_supporting_factors.py) — the flag now signals whichever factor was binding. The legacy sme_supporting_factor_applied and infrastructure_factor_applied keys are still defined in CRR_OUTPUT_SCHEMA_ADDITIONS for back-compat with COREP-driven exporters; new consumers should read supporting_factor_applied together with is_sme / is_infrastructure to disambiguate.

Warnings and validation

Column Type Description
calculation_warnings List(String) Issues or assumptions made during calculation
data_quality_flags List(String) Missing or imputed values

Framework-Specific Output Additions

CRR (Basel 3.0) additions

Source: CRR_OUTPUT_SCHEMA_ADDITIONS in data/schemas.py

Column Type Description
regulatory_framework String "CRR"
crr_effective_date Date Regulation effective date
sme_supporting_factor_eligible Boolean Turnover < EUR 50m (CRR Art. 501)
supporting_factor_applied Boolean Generic flag — True whenever any factor (Art. 501 SME or Art. 501a infrastructure) was applied. Emitted by engine/supporting_factors.py; replaces the legacy sme_supporting_factor_applied / infrastructure_factor_applied pair (which remain in CRR_OUTPUT_SCHEMA_ADDITIONS as legacy aliases for COREP back-compat).
sme_supporting_factor_value Float64 0.7619 below threshold / 0.85 above (CRR Art. 501)
rwa_before_sme_factor Float64 RWA before SME factor
rwa_sme_factor_benefit Float64 RWA reduction from SME factor
infrastructure_factor_eligible Boolean Qualifies as infrastructure (CRR Art. 501a)
infrastructure_factor_value Float64 0.75 (CRR Art. 501a)
rwa_infrastructure_factor_benefit Float64 RWA reduction from infrastructure factor
crr_exposure_class String CRR-specific classification
crr_exposure_subclass String Sub-classification where applicable
crr_mortgage_treatment String "35_pct" or "split_treatment"
crr_mortgage_ltv_threshold Float64 80% LTV threshold
crr_pd_floor Float64 0.03% single floor
crr_airb_lgd_floor_applied Boolean Always False under CRR (per-exposure floors not applicable; CRR Art. 164(4) portfolio-level floors are not implemented — see D3.38)

Basel 3.1 (PRA PS1/26) additions

Source: BASEL31_OUTPUT_SCHEMA_ADDITIONS in data/schemas.py

Column Type Description
regulatory_framework String "BASEL_3_1"
b31_effective_date Date 1 January 2027
output_floor_applicable Boolean Whether floor applies
output_floor_percentage Float64 72.5% (fully phased in)
rwa_irb_unrestricted Float64 IRB RWA before floor
rwa_sa_equivalent Float64 Parallel SA calculation
rwa_floor_amount Float64 sa_equivalent × floor_pct
rwa_floor_impact Float64 Additional RWA from floor
is_floor_binding Boolean Whether floor increased RWA
b31_ltv_band String LTV band (e.g., "0-50%", "50-60%")
b31_ltv_band_rw Float64 Risk weight for LTV band (20%–70%)
b31_pd_floor_class String Exposure class for PD floor
b31_pd_floor_value Float64 0.03%/0.05%/0.10% by class
b31_pd_floor_binding Boolean Whether PD floor was binding
b31_lgd_floor_class String Classification for LGD floor
b31_lgd_floor_value Float64 0%/5%/10%/15%/25% by collateral
b31_lgd_floor_binding Boolean Whether LGD floor was binding
b31_sme_factor_note String "Not available under Basel 3.1"

Result Bundles

AggregatedResultBundle

The final result from the output aggregator. Combines SA, IRB, slotting, and equity results with output floor application and supporting factor adjustments.

Source: AggregatedResultBundle in contracts/bundles.py

@dataclass(frozen=True)
class AggregatedResultBundle:
    """Final aggregated output from the output aggregator."""

    results: pl.LazyFrame                               # Final RWA results
    sa_results: pl.LazyFrame | None = None               # Original SA results
    irb_results: pl.LazyFrame | None = None              # Original IRB results
    slotting_results: pl.LazyFrame | None = None         # Original slotting results
    equity_results: pl.LazyFrame | None = None           # Equity results
    floor_impact: pl.LazyFrame | None = None             # Output floor impact analysis
    supporting_factor_impact: pl.LazyFrame | None = None # Supporting factor impact (CRR)
    summary_by_class: pl.LazyFrame | None = None         # RWA by exposure class
    summary_by_approach: pl.LazyFrame | None = None      # RWA by approach
    pre_crm_summary: pl.LazyFrame | None = None          # Gross view by original class
    post_crm_detailed: pl.LazyFrame | None = None        # Split rows for guarantees
    post_crm_summary: pl.LazyFrame | None = None         # Net view by effective class
    el_summary: ELPortfolioSummary | None = None          # EL summary with T2 credit cap
    errors: list = field(default_factory=list)            # All pipeline errors

ELPortfolioSummary

Portfolio-level expected loss summary with T2 credit cap (CRR Art. 62(d)).

@dataclass(frozen=True)
class ELPortfolioSummary:
    total_expected_loss: float        # Sum of EL across IRB exposures
    total_provisions_allocated: float # Sum of provisions allocated to IRB
    total_el_shortfall: float         # Sum of max(0, EL − provisions) per exposure
    total_el_excess: float            # Sum of max(0, provisions − EL) per exposure
    total_irb_rwa: float              # Total IRB RWA (denominator for T2 cap)
    t2_credit_cap: float              # 0.6% of total IRB RWA
    t2_credit: float                  # min(total_el_excess, t2_credit_cap)
    cet1_deduction: float             # 100% of total_el_shortfall (Art. 36(1)(d))
    t2_deduction: float               # Always zero (no T2 deduction for shortfall)

Other result bundles

Bundle Key fields Description
SAResultBundle results, calculation_audit, errors SA calculator output
IRBResultBundle results, expected_loss, calculation_audit, errors IRB calculator output
SlottingResultBundle results, calculation_audit, errors Slotting calculator output
EquityResultBundle results, calculation_audit, approach, errors Equity calculator output
ComparisonBundle crr_results, b31_results, exposure_deltas, summaries Dual-framework comparison
TransitionalScheduleBundle timeline, yearly_results, errors Year-by-year floor impact
CapitalImpactBundle exposure_attribution, portfolio_waterfall, summaries RWA delta decomposition

Export Formats

Parquet

result.results.collect().write_parquet("rwa_results.parquet")

Full precision, efficient compression, schema preservation.

CSV

result.results.collect().write_csv("rwa_results.csv")

Human-readable, Excel-compatible.

Excel (via API export module)

from rwa_calc.api.export import ResultExporter

exporter = ResultExporter(result)
exporter.to_excel("rwa_results.xlsx")

Next Steps