### Development Setup for CreditRiskEngine Source: https://github.com/ankitjha67/baselkit/blob/main/CONTRIBUTING.md Clone the repository and install the project with development dependencies. Requires Python 3.11+. ```bash git clone https://github.com/ankitjha67/baselkit.git cd baselkit pip install -e ".[dev]" ``` -------------------------------- ### Install Documentation Dependencies and Serve Source: https://github.com/ankitjha67/baselkit/blob/main/README.md Instructions to install the necessary packages for building and serving the project's documentation locally using MkDocs. ```bash pip install -e ".[docs]" mkdocs serve ``` -------------------------------- ### Install CreditRiskEngine Source: https://github.com/ankitjha67/baselkit/blob/main/README.md Install the library using pip. Requires Python 3.11+. ```bash pip install creditriskengine ``` -------------------------------- ### Install CreditRiskEngine Source: https://github.com/ankitjha67/baselkit/blob/main/docs/getting_started.md Install the library using pip. For development, include the 'dev' extra. ```bash pip install creditriskengine ``` ```bash pip install creditriskengine[dev] ``` -------------------------------- ### Scenario Governance and Sensitivity Analysis Setup Source: https://github.com/ankitjha67/baselkit/blob/main/docs/guide/ecl.md Define scenarios with weights and ECL values, and create metadata for scenario sets including approval details and data sources. This is a setup for scenario governance and sensitivity analysis. ```python from creditriskengine.ecl.ifrs9.scenarios import ( Scenario, ScenarioSetMetadata, validate_scenario_governance, scenario_sensitivity_analysis, ) from datetime import datetime, UTC, timedelta scenarios = [ Scenario("base", 0.50, 500_000), Scenario("downside", 0.30, 900_000), Scenario("severe", 0.20, 1_500_000), ] meta = ScenarioSetMetadata( scenarios=scenarios, approved_by="Model Risk Committee", approval_date=datetime(2025, 1, 15, tzinfo=UTC), next_review_date=datetime(2025, 4, 15, tzinfo=UTC), methodology="Expert panel + GDP consensus forecasts", data_sources="IMF WEO Oct 2024, Bloomberg consensus", ) ``` -------------------------------- ### EBA Stress Test Setup Source: https://github.com/ankitjha67/baselkit/blob/main/docs/guide/stress.md Sets up an EBA stress test by defining a macroeconomic scenario with GDP growth and house price index variables. Requires base portfolio data (PDs, LGDS, EADs). ```python from creditriskengine.portfolio.stress_testing import EBAStressTest, MacroScenario import numpy as np scenario = MacroScenario( name="Adverse", horizon_years=3, variables={ "gdp_growth": np.array([-0.04, -0.02, 0.01]), "house_price_index": np.array([-0.15, -0.10, -0.03]), }, ) eba = EBAStressTest(scenario) result = eba.run(base_pds, base_lgds, base_eads) ``` -------------------------------- ### Apply Multi-Jurisdiction Provision Floors Source: https://github.com/ankitjha67/baselkit/blob/main/docs/guide/ecl.md Apply provision floor rules, such as the RBI Stage 2 floor for unsecured retail, to calculated ECL. This example demonstrates how the floor binds when the calculated ECL is lower than the floor. ```python from creditriskengine.ecl.ifrs9.revolving import apply_provision_floor from creditriskengine.core.types import Jurisdiction, IFRS9Stage # RBI Stage 2 floor: 5% of EAD for unsecured retail floored_ecl = apply_provision_floor( ecl=200.0, ead=10000.0, jurisdiction=Jurisdiction.INDIA, stage=IFRS9Stage.STAGE_2, ) # Returns 500.0 (5% floor binds) ``` -------------------------------- ### Apply Management Overlays and Scenario Sensitivity Source: https://github.com/ankitjha67/baselkit/blob/main/README.md Demonstrates applying management overlays to adjust model ECL and performing scenario sensitivity analysis. Overlays can be used for post-model adjustments, while scenario analysis assesses ECL changes under different economic conditions. ```python from creditriskengine.ecl.ifrs9.overlays import ( ManagementOverlay, OverlayType, apply_overlays, validate_overlay, ) from creditriskengine.ecl.ifrs9.scenarios import ( Scenario, ScenarioSetMetadata, weighted_ecl, scenario_sensitivity_analysis, validate_scenario_governance, ) from datetime import datetime, UTC, timedelta # --- Management Overlays (post-model adjustments) --- overlay = ManagementOverlay( name="CRE sector stress", overlay_type=OverlayType.SECTOR_SPECIFIC, adjustment_rate=0.15, # +15% uplift on model ECL rationale="Commercial real estate valuations declining in Q3", regulatory_basis="IFRS 9.B5.5.52", approved_by="Credit Risk Committee", approval_date=datetime.now(UTC), expiry_date=datetime.now(UTC) + timedelta(days=90), portfolio_scope="UK CRE Stage 2 exposures", ) # Validate governance completeness (auditor-ready) warnings = validate_overlay(overlay) # [] = fully compliant # Apply overlay to model ECL result = apply_overlays(model_ecl=1_000_000, overlays=[overlay]) print(f"Model ECL: {result.model_ecl:,.0f}") print(f"After overlay: {result.overlay_ecl:,.0f} (+{result.total_adjustment:,.0f})") # --- Scenario Sensitivity Analysis --- scenarios = [ Scenario("base", 0.50, 500_000), Scenario("downside", 0.30, 900_000), Scenario("severe", 0.20, 1_500_000), ] ecl = weighted_ecl(scenarios) # Probability-weighted ECL sensitivity = scenario_sensitivity_analysis(scenarios, shift_size=0.10) print(f"Most sensitive to: {sensitivity.max_sensitivity_scenario}") print(f" ECL changes {sensitivity.max_sensitivity_pct:.1f}% per 10pp weight shift") ``` -------------------------------- ### CreditRiskEngine Package Layout Source: https://github.com/ankitjha67/baselkit/blob/main/docs/architecture.md Illustrates the directory structure and modules within the CreditRiskEngine library, showing the organization of core components, risk-weighted assets, expected credit loss engines, model development tools, validation utilities, portfolio models, regulatory configurations, and reporting functionalities. ```tree creditriskengine/ ├── core/ # Data models, types, config, exceptions, audit │ ├── types.py # Enums: Jurisdiction, IRBAssetClass, SAExposureClass, ... │ ├── exposure.py # Pydantic Exposure + Collateral models │ ├── portfolio.py # Portfolio container with filtering │ ├── audit.py # AuditTrail, CalculationRecord, OverlayAuditRecord │ └── config.py # Jurisdiction config loader │ ├── rwa/ # Risk-Weighted Assets │ ├── standardized/ │ │ └── credit_risk_sa.py # CRE20 SA risk weights (all exposure classes) │ ├── irb/ │ │ └── formulas.py # CRE31 IRB: correlations, K, maturity adj, RW │ └── output_floor.py # RBC25 output floor with multi-jurisdiction phase-in │ ├── ecl/ # Expected Credit Loss engines │ ├── ifrs9/ # IFRS 9 impairment │ │ ├── ecl_calc.py # 12-month and lifetime ECL │ │ ├── staging.py # Three-stage assignment │ │ ├── sicr.py # Significant Increase in Credit Risk │ │ ├── lifetime_pd.py # Cumulative/marginal PD term structures │ │ ├── ttc_to_pit.py # TTC-to-PIT conversion (Vasicek Z-factor) │ │ ├── forward_looking.py # Satellite models, mean-reversion, LGD overlay │ │ ├── scenarios.py # Probability-weighted ECL, governance, sensitivity │ │ ├── overlays.py # Management overlay / PMA framework (7 types) │ │ └── revolving/ # Revolving credit ECL sub-engine │ ├── cecl/ # US CECL (ASC 326) │ │ ├── cecl_calc.py # PD/LGD and loss-rate methods │ │ ├── methods.py # WARM, vintage, DCF │ │ └── qualitative.py # Q-factor adjustments with governance caps │ └── ind_as109/ # Indian Accounting Standard 109 │ └── ind_as_ecl.py # Full RBI IRAC norms, provisioning, restructured accounts │ ├── models/ # PD / LGD / EAD model development │ ├── pd/ │ │ └── scorecard.py # Logistic scorecard, master scale, PD calibration │ ├── lgd/ │ │ └── lgd_model.py # Workout LGD, downturn LGD, LGD floors │ ├── ead/ │ │ └── ead_model.py # EAD calculation, CCF estimation, supervisory CCFs │ └── concentration/ │ └── concentration.py # Single-name HHI, sector concentration, GA │ ├── validation/ # Model validation toolkit │ ├── discrimination.py # AUROC, Gini, KS, CAP, IV, Somers' D │ ├── calibration.py # Binomial, HL, Spiegelhalter, traffic light, Jeffreys │ ├── stability.py # PSI, CSI, HHI, migration matrix stability │ ├── backtesting.py # PD backtest summary │ ├── benchmarking.py # Model-vs-benchmark comparison │ └── reporting.py # Validation summary generator │ ├── portfolio/ # Portfolio credit risk models │ ├── vasicek.py # Vasicek ASRF: conditional DR, loss quantile, distribution │ ├── copula.py # Single/multi-factor Gaussian copula Monte Carlo │ ├── economic_capital.py # EC via single-factor simulation │ ├── var.py # Parametric credit VaR, marginal VaR │ └── stress_testing.py # PD/LGD stress, RWA impact │ ├── regulatory/ # Jurisdiction-specific YAML configs (17 jurisdictions) │ ├── loader.py # YAML config loader │ ├── bcbs/ # BCBS d424 │ ├── eu/ # EU CRR3 │ ├── uk/ # UK PRA PS1/26 │ ├── us/ # US Basel III Endgame │ ├── india/ # RBI │ └── ... # + 12 more jurisdictions │ └── reporting/ # Regulatory reporting └── reports.py # COREP summary, Pillar 3 disclosure, model inventory ``` -------------------------------- ### Configure and Predict with Satellite Model Source: https://github.com/ankitjha67/baselkit/blob/main/docs/guide/ecl.md Configure a multi-variable satellite model with a logistic link and predict factors based on macro variable forecasts. Ensure correct variable names and coefficients are provided. ```python from creditriskengine.ecl.ifrs9.forward_looking import ( SatelliteModelConfig, satellite_model_predict, apply_fli_with_reversion, ) import numpy as np # Configure satellite model: GDP and unemployment drive PD config = SatelliteModelConfig( variable_names=["gdp_growth", "unemployment"], coefficients=[-2.0, 3.0], # GDP decreases PD, unemployment increases it intercept=1.0, link="logistic", # Bounded output in (0, 2) ) # Forecast 5 years of macro variables forecasts = { "gdp_growth": np.array([-0.02, 0.00, 0.01, 0.02, 0.02]), "unemployment": np.array([0.08, 0.07, 0.06, 0.05, 0.045]), } factors = satellite_model_predict(config, forecasts) ``` -------------------------------- ### Running Project Checks Source: https://github.com/ankitjha67/baselkit/blob/main/CONTRIBUTING.md Execute these commands to ensure tests pass (100% coverage), linting is correct, and type checking is strict before submitting a PR. ```bash pytest # Tests (100% line coverage required) ``` ```bash ruff check src/ tests/ # Linting ``` ```bash mypy src/creditriskengine/ # Type checking (strict mode) ``` -------------------------------- ### Calculate Discrimination Metrics Source: https://github.com/ankitjha67/baselkit/blob/main/docs/guide/validation.md Import and use functions for AUROC, Gini coefficient, and KS statistic. Requires true labels and predicted scores. ```python from creditriskengine.validation.discrimination import auroc, gini_coefficient, ks_statistic auc = auroc(y_true, y_score) gini = gini_coefficient(y_true, y_score) ks = ks_statistic(y_true, y_score) ``` -------------------------------- ### Run Tests with Pytest Source: https://github.com/ankitjha67/baselkit/blob/main/docs/getting_started.md Execute tests using pytest. Options include running all tests with coverage, quick runs without coverage, or targeting specific test modules. ```bash pytest # Run all tests with coverage pytest tests/ -q --no-cov # Quick run without coverage pytest tests/test_rwa/ -v # Run only RWA tests ``` -------------------------------- ### Apply Multi-Scenario Weighting to ECL Source: https://github.com/ankitjha67/baselkit/blob/main/docs/guide/ecl.md Calculate a final ECL by applying weights to ECL values derived from different economic scenarios. Requires Scenario objects with weights and ECL values. ```python from creditriskengine.ecl.ifrs9.scenarios import weighted_ecl, Scenario scenarios = [ Scenario("base", 0.50, ecl_base), Scenario("downside", 0.30, ecl_down), Scenario("severe", 0.20, ecl_severe), ] final_ecl = weighted_ecl(scenarios) ``` -------------------------------- ### Run Pytest Test Suite Source: https://github.com/ankitjha67/baselkit/blob/main/README.md Commands to execute the project's test suite using pytest. Includes options for a full run, a quick run without coverage, and targeting specific modules. ```bash # Run full test suite pytest # Quick run without coverage pytest -q --no-cov # Specific module pytest tests/test_rwa/ -v ``` -------------------------------- ### Run Tests and Linting Source: https://github.com/ankitjha67/baselkit/blob/main/README.md Execute the project's tests using pytest and perform code linting with Ruff. These commands are essential for maintaining code quality and ensuring the project adheres to standards. ```bash pytest # Run tests ruff check src/ tests/ # Lint ``` -------------------------------- ### Linting and Type Checking with Ruff and Mypy Source: https://github.com/ankitjha67/baselkit/blob/main/docs/getting_started.md Perform code linting using Ruff and type checking using Mypy on the project's source files. ```bash ruff check src/creditriskengine/ mypy src/creditriskengine/ --ignore-missing-imports ``` -------------------------------- ### Apply Management Overlays to ECL Source: https://github.com/ankitjha67/baselkit/blob/main/docs/guide/ecl.md Apply management overlays (post-model adjustments) to ECL calculations. This includes creating overlay objects with governance metadata, validating them, and applying them to model ECL. ```python from creditriskengine.ecl.ifrs9.overlays import ( ManagementOverlay, OverlayType, apply_overlays, overlay_impact_summary, validate_overlay, ) from datetime import datetime, UTC, timedelta overlay = ManagementOverlay( name="Emerging market stress", overlay_type=OverlayType.EMERGING_RISK, adjustment_rate=0.10, # +10% on model ECL rationale="Geopolitical risk not captured in PD models", regulatory_basis="IFRS 9.B5.5.52", approved_by="Credit Risk Committee", approval_date=datetime.now(UTC), expiry_date=datetime.now(UTC) + timedelta(days=90), portfolio_scope="EM sovereign and bank exposures", ) # Check governance completeness warnings = validate_overlay(overlay) # [] = passes all checks # Apply to model ECL result = apply_overlays(model_ecl=5_000_000, overlays=[overlay]) summary = overlay_impact_summary(result) print(f"Overlay impact: {summary['adjustment_pct']}% ") ``` -------------------------------- ### Calculate SA Risk Weight for Sovereign and Corporate Source: https://github.com/ankitjha67/baselkit/blob/main/docs/getting_started.md Calculate risk weights for sovereign and corporate exposures using standardized approach (SA) credit quality steps. ```python from creditriskengine.rwa.standardized.credit_risk_sa import ( get_sovereign_risk_weight, get_corporate_risk_weight, ) from creditriskengine.core.types import CreditQualityStep # AAA-rated sovereign rw = get_sovereign_risk_weight(CreditQualityStep.CQS_1) print(f"Sovereign RW: {rw}%") # 0% # BBB-rated corporate rw = get_corporate_risk_weight(CreditQualityStep.CQS_3) print(f"Corporate RW: {rw}%") # 75% ``` -------------------------------- ### Calculate IFRS 9 ECL for Stage 1 and Stage 2 Source: https://github.com/ankitjha67/baselkit/blob/main/docs/getting_started.md Calculate Expected Credit Losses (ECL) under IFRS 9 for Stage 1 (12-month) and Stage 2 (lifetime) exposures. Requires IFRS9Stage, PD, LGD, and EAD. ```python import numpy as np from creditriskengine.core.types import IFRS9Stage from creditriskengine.ecl.ifrs9.ecl_calc import calculate_ecl # Stage 1: 12-month ECL ecl = calculate_ecl(IFRS9Stage.STAGE_1, pd_12m=0.02, lgd=0.45, ead=1_000_000) print(f"12-month ECL: {ecl:,0f}") # 9,000 # Stage 2: Lifetime ECL marginal_pds = np.array([0.02, 0.025, 0.03, 0.035, 0.04]) ecl = calculate_ecl( IFRS9Stage.STAGE_2, pd_12m=0.02, lgd=0.45, ead=1_000_000, marginal_pds=marginal_pds, ) print(f"Lifetime ECL: {ecl:,0f}") ``` -------------------------------- ### FR 2052a Liquidity Report Components Source: https://github.com/ankitjha67/baselkit/blob/main/README.md Imports necessary components for building and validating the FR 2052a liquidity report. This includes record types for inflows and outflows, and enums for various classification categories. ```python from creditriskengine.reporting.fr2052a import ( InflowAssetRecord, OutflowDepositRecord, build_submission, validate_submission, generate_summary, AssetCategory, CounterpartyType, InsuredType, MaturityBucket, ReporterCategory, ) ``` -------------------------------- ### Build and Validate Financial Records Source: https://github.com/ankitjha67/baselkit/blob/main/README.md Constructs financial records for reporting entities and validates them using the `validate_submission` function. It then builds a submission object and generates a summary, including net liquidity. ```python records = [ InflowAssetRecord( reporting_entity="MegaBank", as_of_date="2024-06-30", product_id=1, # Unencumbered Assets maturity_bucket=MaturityBucket.OPEN, maturity_amount=5000.0, collateral_class=AssetCategory.A_1_Q, # US Treasury market_value=5000.0, treasury_control=True, ), OutflowDepositRecord( reporting_entity="MegaBank", as_of_date="2024-06-30", product_id=1, # Transactional Accounts maturity_bucket=MaturityBucket.OPEN, maturity_amount=3000.0, counterparty=CounterpartyType.RETAIL, insured=InsuredType.FDIC, ), ] # Validate and generate summary result = validate_submission(records, reporting_entity="MegaBank") print(f"Valid: {result.is_valid}") submission = build_submission( "MegaBank", "2024-06-30", ReporterCategory.CATEGORY_I, records ) summary = generate_summary(submission) print(f"Net liquidity: {summary['net_liquidity_position']:,.0f}M") # Net liquidity: 2,000M ``` -------------------------------- ### Calculate Output Floor Source: https://github.com/ankitjha67/baselkit/blob/main/docs/getting_started.md Use the OutputFloorCalculator to determine the floored RWA and check if the floor is binding. Requires jurisdiction and effective date. ```python from datetime import date from creditriskengine.core.types import Jurisdiction from creditriskengine.rwa.output_floor import OutputFloorCalculator calc = OutputFloorCalculator(Jurisdiction.EU, date(2026, 6, 30)) result = calc.calculate(irb_rwa=800.0, sa_rwa=1200.0) print(f"Floored RWA: {result['floored_rwa']}") print(f"Floor binding: {result['is_binding']}") ``` -------------------------------- ### Apply Forward-Looking Information with Mean Reversion Source: https://github.com/ankitjha67/baselkit/blob/main/docs/guide/ecl.md Adjust base Probability of Defaults (PDs) using predicted factors and apply mean reversion beyond a specified forecast horizon. Ensure base PDs, factors, long-run PD, forecast horizon, and reversion periods are correctly defined. ```python # Apply with mean-reversion beyond 3-year forecast horizon base_pds = np.full(5, 0.02) long_run_pd = 0.02 adjusted = apply_fli_with_reversion( base_pds, factors, long_run_pd, forecast_horizon=3, reversion_periods=2, ) ``` -------------------------------- ### Perform Binomial Calibration Test Source: https://github.com/ankitjha67/baselkit/blob/main/docs/guide/validation.md Utilize the binomial test for calibration assessment. Provide the number of defaults, total observations, and predicted probability of default. ```python from creditriskengine.validation.calibration import binomial_test, hosmer_lemeshow_test result = binomial_test(n_defaults=15, n_observations=1000, predicted_pd=0.02) ``` -------------------------------- ### Load Jurisdiction Configuration Source: https://github.com/ankitjha67/baselkit/blob/main/docs/getting_started.md Load configuration settings for a specific jurisdiction, such as regulatory details and output floor schedules. ```python from creditriskengine.core.types import Jurisdiction from creditriskengine.regulatory.loader import load_config config = load_config(Jurisdiction.EU) print(config["regulator"]) print(config["output_floor"]) ``` -------------------------------- ### Assign SA Risk Weight for Corporate and Residential Mortgage Source: https://github.com/ankitjha67/baselkit/blob/main/docs/guide/sa.md Use this function to assign risk weights for corporate exposures based on Credit Quality Steps (CQS) and for residential mortgages based on Loan-to-Value (LTV). Ensure correct SAExposureClass and CreditQualityStep or LTV are provided. ```python from creditriskengine.rwa.standardized.credit_risk_sa import assign_sa_risk_weight from creditriskengine.core.types import SAExposureClass, CreditQualityStep, Jurisdiction # Corporate with rating rw = assign_sa_risk_weight(SAExposureClass.CORPORATE, CreditQualityStep.CQS_2) print(f"A-rated corporate: {rw}%") # 50% # Residential mortgage by LTV rw = assign_sa_risk_weight(SAExposureClass.RESIDENTIAL_MORTGAGE, ltv=0.75) print(f"RRE at 75% LTV: {rw}%") # 35% ``` -------------------------------- ### Calculate 12-Month and Lifetime ECL (IFRS 9) Source: https://github.com/ankitjha67/baselkit/blob/main/docs/guide/ecl.md Calculate 12-month and lifetime ECL using provided probability of default (PD), loss given default (LGD), exposure at default (EAD), and effective interest rate (EIR). ```python from creditriskengine.ecl.ifrs9.ecl_calc import ecl_12_month, ecl_lifetime # Stage 1: 12-month ECL ecl_1 = ecl_12_month(pd_12m=0.02, lgd=0.40, ead=1_000_000, eir=0.05) # Stage 2: Lifetime ECL ecl_2 = ecl_lifetime( pd_term_structure=[0.02, 0.025, 0.03, 0.035, 0.04], lgd=0.40, ead=1_000_000, eir=0.05, ) ``` -------------------------------- ### Sign Commits with DCO Source: https://github.com/ankitjha67/baselkit/blob/main/CONTRIBUTING.md Append '-s' to your git commit command to sign off your contributions, certifying you have the right to submit under the project's license. ```bash git commit -s -m "Add downturn LGD floor for residential mortgages" ``` -------------------------------- ### Calculate ECL with RBI Floor Source: https://github.com/ankitjha67/baselkit/blob/main/docs/guide/ecl.md Calculate the Expected Credit Loss (ECL) for Ind AS 109, incorporating the RBI minimum provision floor. The ECL will be the higher of the model-calculated ECL and the regulatory minimum. ```python # ECL with RBI floor (higher of model ECL and IRAC minimum) ecl = calculate_ecl_ind_as( stage=stage, pd_12m=0.10, lgd=0.45, ead=1_000_000, marginal_pds=np.array([0.10, 0.08]), irac_class=irac, is_secured=True, ) ``` -------------------------------- ### Model Validation: Discrimination and Stability Source: https://github.com/ankitjha67/baselkit/blob/main/docs/getting_started.md Perform model validation using discrimination metrics (AUROC, Gini) and stability metrics (Population Stability Index - PSI). ```python import numpy as np from creditriskengine.validation.discrimination import auroc, gini_coefficient from creditriskengine.validation.stability import population_stability_index # Discrimination y_true = np.array([0, 0, 0, 1, 1, 1]) y_score = np.array([0.1, 0.2, 0.3, 0.7, 0.8, 0.9]) print(f"AUROC: {auroc(y_true, y_score):.3f}") print(f"Gini: {gini_coefficient(y_true, y_score):.3f}") # Stability rng = np.random.default_rng(42) expected = rng.normal(0, 1, 1000) actual = rng.normal(0.2, 1, 1000) psi = population_stability_index(actual, expected) print(f"PSI: {psi:.4f}") # < 0.10 = stable ``` -------------------------------- ### Calculate RBI Minimum Provision Source: https://github.com/ankitjha67/baselkit/blob/main/docs/guide/ecl.md Calculate the minimum provision required by RBI for a given exposure at default (EAD) and IRAC asset class, considering secured status. This function enforces regulatory floors. ```python # RBI minimum provision (15% secured substandard) floor = rbi_minimum_provision(ead=1_000_000, irac_class=irac) # 150,000 ``` -------------------------------- ### Calculate IRB Risk Weights Source: https://github.com/ankitjha67/baselkit/blob/main/docs/guide/irb.md Use this function to calculate risk weights for different asset classes. It supports corporate, SME, residential mortgage, and QRRE exposures. For SMEs, provide `turnover_eur_millions` for firm-size adjustment. For QRRE, set `is_qrre_transactor=True` for the transactor scalar. ```python from creditriskengine.rwa.irb.formulas import irb_risk_weight # Corporate exposure rw = irb_risk_weight(pd=0.01, lgd=0.45, asset_class="corporate", maturity=2.5) print(f"Corporate RW: {rw:.2f}%") # ~75% # SME with firm-size adjustment rw_sme = irb_risk_weight( pd=0.01, lgd=0.45, asset_class="corporate", maturity=2.5, turnover_eur_millions=15.0 ) print(f"SME RW: {rw_sme:.2f}%") # Lower than general corporate # Residential mortgage rw_rre = irb_risk_weight(pd=0.005, lgd=0.15, asset_class="residential_mortgage") # QRRE with transactor scalar rw_qrre = irb_risk_weight( pd=0.02, lgd=0.80, asset_class="qrre", is_qrre_transactor=True ) ``` -------------------------------- ### Calculate Revolving ECL from Exposure Object Source: https://github.com/ankitjha67/baselkit/blob/main/docs/guide/ecl.md Calculate ECL for revolving facilities directly from an Exposure object, which encapsulates all necessary credit and facility details. ```python from creditriskengine.core.exposure import Exposure from creditriskengine.ecl.ifrs9.revolving import revolving_ecl_from_exposure exposure = Exposure( exposure_id="CC-001", counterparty_id="CUST-001", ead=9200.0, drawn_amount=6000.0, undrawn_commitment=4000.0, jurisdiction="bcbs", approach="standardized", ifrs9_stage=IFRS9Stage.STAGE_1, current_pd=0.03, lgd=0.85, effective_interest_rate=0.18, is_revolving=True, credit_limit=10000.0, behavioral_life_months=36, ccf=0.80, ) result = revolving_ecl_from_exposure(exposure) ``` -------------------------------- ### Type Checking with MyPy Source: https://github.com/ankitjha67/baselkit/blob/main/README.md Perform static type checking on the project's source code using MyPy. This helps in identifying type-related errors before runtime. ```bash mypy src/ ``` -------------------------------- ### PD Scorecard: Score to PD, Master Scale, Rating Grade, Calibration Source: https://github.com/ankitjha67/baselkit/blob/main/docs/getting_started.md Utilities for PD scorecard modeling, including converting scores to PDs, building a master scale, assigning rating grades, and calibrating PDs. ```python import numpy as np from creditriskengine.models.pd.scorecard import ( score_to_pd, build_master_scale, assign_rating_grade, calibrate_pd_anchor_point, ) # Convert model scores to PDs scores = np.array([-3.0, -2.0, -1.0, 0.0, 1.0]) pds = score_to_pd(scores) # Build a master scale boundaries = [0.0003, 0.001, 0.005, 0.01, 0.05, 0.10, 0.20, 1.0] labels = ["AAA", "AA", "A", "BBB", "BB", "B", "CCC"] scale = build_master_scale(boundaries, labels) # Assign rating grade grade = assign_rating_grade(0.015, scale) print(f"Grade: {grade}") # BB # Calibrate PDs to a central tendency of 2% calibrated = calibrate_pd_anchor_point(0.02, pds) ``` -------------------------------- ### Ind AS 109 ECL with RBI IRAC Norms Source: https://github.com/ankitjha67/baselkit/blob/main/README.md Calculates Expected Credit Loss (ECL) under Ind AS 109, incorporating RBI IRAC norms for asset classification and provisioning. This includes classifying assets based on days past due and NPA duration, applying RBI minimum provisions, and calculating ECL with the provisioning floor. ```python from creditriskengine.ecl.ind_as109 import ( classify_irac, irac_to_ifrs9_stage, rbi_minimum_provision, calculate_ecl_ind_as, IRACAssetClass, ) from creditriskengine.core.types import IFRS9Stage import numpy as np # Classify per RBI IRAC norms irac = classify_irac(days_past_due=95, months_as_npa=3) print(f"IRAC class: {irac.value}") # "substandard" stage = irac_to_ifrs9_stage(irac) # Stage 3 # RBI minimum provision (15% for secured substandard) rbi_floor = rbi_minimum_provision(ead=1_000_000, irac_class=irac, is_secured=True) print(f"RBI floor: {rbi_floor:,.0f}") # 150,000 # ECL with RBI provisioning floor (higher of model ECL and RBI floor) ecl = calculate_ecl_ind_as( stage=stage, pd_12m=0.10, lgd=0.45, ead=1_000_000, marginal_pds=np.array([0.10, 0.08]), irac_class=irac, is_secured=True, ) print(f"ECL (with RBI floor): {ecl:,.0f}") ``` -------------------------------- ### Jurisdiction YAML Metadata Source: https://github.com/ankitjha67/baselkit/blob/main/docs/regulatory_versioning.md Each jurisdiction YAML file includes metadata such as jurisdiction name, framework, effective date, and document reference. ```yaml jurisdiction: EU framework: CRR3 / CRD6 effective_date: "2025-01-01" document_reference: Regulation (EU) 2024/1623 ``` -------------------------------- ### Assign SA Risk Weight for Banks using SCRA Grades Source: https://github.com/ankitjha67/baselkit/blob/main/docs/guide/sa.md Assign risk weights for bank exposures using SCRA (Supervisory Committee on Regulatory Affairs) grades when external ratings are not available. The grade ('A', 'B', 'C') determines the risk weight. ```python rw = assign_sa_risk_weight(SAExposureClass.BANK, scra_grade="A") # 40% rw = assign_sa_risk_weight(SAExposureClass.BANK, scra_grade="B") # 75% rw = assign_sa_risk_weight(SAExposureClass.BANK, scra_grade="C") # 150% ``` -------------------------------- ### UK PRA Loan-Splitting for Residential Mortgages Source: https://github.com/ankitjha67/baselkit/blob/main/docs/guide/sa.md Apply UK PRA loan-splitting rules for residential mortgage portfolios to determine blended risk weights. This function requires the loan amount and property value. ```python from creditriskengine.rwa.standardized.credit_risk_sa import uk_pra_loan_splitting_rre result = uk_pra_loan_splitting_rre(loan_amount=200_000, property_value=300_000) print(f"Blended RW: {result['blended_rw']:.1f}%") ``` -------------------------------- ### Calculate Population Stability Index Source: https://github.com/ankitjha67/baselkit/blob/main/docs/guide/validation.md Compute the Population Stability Index (PSI) to measure distribution shifts. Requires both base and current distributions. ```python from creditriskengine.validation.stability import population_stability_index psi = population_stability_index(base_distribution, current_distribution) ``` -------------------------------- ### Assign Standardized Approach Risk Weight Source: https://github.com/ankitjha67/baselkit/blob/main/README.md Assign a risk weight for a corporate exposure under the Standardized Approach (SA). Requires specifying exposure class, credit quality step, and jurisdiction. ```python from creditriskengine.rwa.standardized.credit_risk_sa import assign_sa_risk_weight from creditriskengine.core.types import SAExposureClass, CreditQualityStep, Jurisdiction rw = assign_sa_risk_weight( exposure_class=SAExposureClass.CORPORATE, cqs=CreditQualityStep.CQS_2, jurisdiction=Jurisdiction.EU, ) print(f"SA Risk Weight: {rw:.0f}%") ``` -------------------------------- ### Convert Scorecard Points to PD Source: https://github.com/ankitjha67/baselkit/blob/main/README.md Converts numerical scorecard points into Probability of Default (PD) values using a pre-defined scorecard. It also assigns rating grades based on these PDs and a master scale. ```python from creditriskengine.models.pd.scorecard import scorecard_to_pd, assign_rating_grade, build_master_scale import numpy as np scores = np.array([537, 587, 640, 706]) pds = scorecard_to_pd(scores) # Convert scorecard points to PD master_scale = build_master_scale([0.0003, 0.001, 0.005, 0.01, 0.02, 0.05, 0.10, 0.20, 1.0]) grades = [assign_rating_grade(pd, master_scale) for pd in pds] # grades: ['Grade_7', 'Grade_5', 'Grade_2', 'Grade_1'] print(f"PDs: {pds}") print(f"Grades: {grades}") ``` -------------------------------- ### Calculate Revolving Credit ECL (Drawn/Undrawn) Source: https://github.com/ankitjha67/baselkit/blob/main/docs/guide/ecl.md Calculate ECL for revolving credit facilities, considering behavioral life, drawn and undrawn amounts, and credit conversion factors (CCF). The result includes separate ECL for drawn and undrawn portions. ```python from creditriskengine.ecl.ifrs9.revolving import ( calculate_revolving_ecl, determine_behavioral_life, RevolvingProductType, ) from creditriskengine.core.types import IFRS9Stage import numpy as np # Determine behavioral life (IFRS 9 B5.5.40) life = determine_behavioral_life( product_type=RevolvingProductType.CREDIT_CARD ) # 36 months # Monthly marginal PDs over the behavioral life marginal_pds = np.full(life, 0.0025) # ~3% annual PD result = calculate_revolving_ecl( stage=IFRS9Stage.STAGE_2, drawn=6000.0, undrawn=4000.0, ccf=0.80, pd_12m=0.03, lgd=0.85, eir=0.015, marginal_pds=marginal_pds, behavioral_life_months=life, ) print(f"Total ECL: ${result.total_ecl:,.2f}") print(f" Drawn: ${result.ecl_drawn:,.2f} (loss allowance)") print(f" Undrawn: ${result.ecl_undrawn:,.2f} (provision)") ``` -------------------------------- ### Calculate IFRS 9 ECL Source: https://github.com/ankitjha67/baselkit/blob/main/README.md Calculate the Expected Credit Loss (ECL) for a 12-month period under IFRS 9. Requires specifying stage, 12-month PD, LGD, EAD, and EIR. ```python from creditriskengine.ecl.ifrs9.ecl_calc import calculate_ecl from creditriskengine.core.types import IFRS9Stage ecl = calculate_ecl( stage=IFRS9Stage.STAGE_1, pd_12m=0.02, lgd=0.40, ead=1_000_000, eir=0.05, ) print(f"12-month ECL: {ecl:,.2f}") ```