Â
SECTION 1: LEARNING OBJECTIVES
By the end of this lesson, you will be able to:
-
Define credit risk and its components – PD, LGD, EAD.
-
Apply credit scoring models for digital lending.
-
Implement portfolio credit risk management.
-
Conduct stress testing for credit portfolios.
-
Measure credit risk using key metrics.
-
Understand the regulatory framework – Basel III, IFRS 9, CECL.
-
Develop a credit risk strategy for a digital bank.
SECTION 2: WHAT IS CREDIT RISK?
2.1 Definition
Credit risk is the risk of loss arising from a borrower’s failure to repay a loan or meet contractual obligations. It is one of the most significant risks faced by banks.
2.2 Key Components
| Component | Description | Formula |
|---|---|---|
| Probability of Default (PD) | Likelihood of default within a given time horizon. | Probability estimate. |
| Loss Given Default (LGD) | Proportion of exposure lost on default. | 1 – Recovery Rate. |
| Exposure at Default (EAD) | Total exposure at the time of default. | Outstanding + undrawn commitments. |
| Expected Loss (EL) | Average loss expected. | PD × LGD × EAD. |
| Unexpected Loss (UL) | Volatility around expected loss. | Statistical measure. |
2.3 Credit Risk Drivers
| Driver | Description | Impact |
|---|---|---|
| Credit Score | Borrower’s creditworthiness. | Higher score → lower risk. |
| Debt-to-Income Ratio | Debt relative to income. | Higher ratio → higher risk. |
| Loan-to-Value Ratio | Loan amount relative to asset value. | Higher LTV → higher risk. |
| Employment History | Stability of employment. | Stable → lower risk. |
| Payment History | Past repayment behaviour. | Consistent → lower risk. |
| Economic Conditions | Macroeconomic factors. | Recession → higher risk. |
SECTION 3: CREDIT SCORING IN DIGITAL BANKING
3.1 Traditional vs AI-Powered Credit Scoring
| Aspect | Traditional Scoring | AI-Powered Scoring |
|---|---|---|
| Data Sources | Credit bureau, application data. | Traditional + alternative data. |
| Model Approach | Logistic regression, scorecards. | ML/DL, XGBoost, Neural Networks. |
| Interpretability | High (coefficients). | Moderate to Low (SHAP required). |
| Speed | Batch processing. | Real-time scoring. |
| Inclusivity | Limited to credit history. | Includes unbanked/underbanked. |
3.2 Alternative Data Sources
| Data Source | Description | Use Case |
|---|---|---|
| Telecom Data | Phone bill payments. | Assess payment reliability. |
| Utility Payments | Electricity, water, gas. | Income stability. |
| Rent Payments | Rental history. | Credit history for thin files. |
| Mobile Data | App usage, call patterns. | Behavioural scoring. |
| Transaction Data | Spending patterns. | Income verification. |
SECTION 4: PORTFOLIO CREDIT RISK MANAGEMENT
4.1 Portfolio Management Strategies
| Strategy | Description | Example |
|---|---|---|
| Diversification | Spread risk across borrowers. | Different sectors, geographies. |
| Concentration Limits | Limit exposure to single borrower. | Single-name limits. |
| Portfolio Monitoring | Monitor portfolio performance. | Delinquency tracking. |
| Stress Testing | Test portfolio under stress. | Macroeconomic scenarios. |
| Provisioning | Set aside for expected losses. | IFRS 9 / CECL. |
4.2 Portfolio Metrics
| Metric | Description | Target |
|---|---|---|
| Non-Performing Loan Ratio | % of loans in default. | < 5% |
| Delinquency Rate | % of loans past due. | < 3% |
| Coverage Ratio | Provisions / NPLs. | > 100% |
| Loan Loss Rate | Annual loan losses. | < 1% |
| Concentration Ratio | % of portfolio in top exposures. | < 25% |
SECTION 5: REGULATORY FRAMEWORK
5.1 Key Regulations
| Regulation | Requirement | Impact |
|---|---|---|
| Basel III | Capital adequacy for credit risk. | IRB approach, validation. |
| IFRS 9 / CECL | Expected credit loss provisioning. | PD, LGD, EAD estimates. |
| ECOA / Fair Lending | Non-discrimination. | Fairness testing. |
5.2 IFRS 9 – Three-Stage Approach
| Stage | Definition | Impairment |
|---|---|---|
| Stage 1 | No significant increase in credit risk. | 12-month ECL. |
| Stage 2 | Significant increase in credit risk. | Lifetime ECL. |
| Stage 3 | Credit-impaired (already in default). | Lifetime ECL. |
SECTION 6: IMPLEMENTATION IN PYTHON – CREDIT RISK
# =================================================================== # MODULE 8, LESSON 2: CREDIT RISK MANAGEMENT # =================================================================== import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns from sklearn.model_selection import train_test_split from sklearn.ensemble import RandomForestClassifier from xgboost import XGBClassifier from sklearn.metrics import roc_auc_score, classification_report from scipy.stats import norm import warnings warnings.filterwarnings('ignore') print("="*70) print("CREDIT RISK MANAGEMENT IN DIGITAL BANKING") print("="*70) # ---------------------------------------------------------------- # PART A: GENERATE CREDIT DATA # ---------------------------------------------------------------- print("\n" + "-"*60) print("PART A: Generating Credit Data") print("-"*60) np.random.seed(42) n_loans = 5000 # Generate borrower features credit_data = pd.DataFrame({ 'loan_id': range(1, n_loans + 1), 'age': np.random.normal(45, 15, n_loans).clip(18, 80).astype(int), 'income': np.random.gamma(5, 20, n_loans) + 20, 'credit_score': np.random.normal(700, 50, n_loans).clip(550, 850).astype(int), 'dti': np.random.beta(2, 5, n_loans) * 60, 'loan_amount': np.random.gamma(4, 50, n_loans) + 30, 'loan_term': np.random.choice([12, 24, 36, 48, 60, 72], n_loans), 'employment_years': np.random.gamma(3, 5, n_loans).clip(0, 30).astype(int), 'home_owner': np.random.binomial(1, 0.65, n_loans) }) # Generate default based on features log_odds = (-4.5 + 0.04 * credit_data['dti'] - 0.005 * credit_data['credit_score'] + 0.01 * (credit_data['loan_amount']/1000) + 0.02 * credit_data['employment_years'] - 0.01 * credit_data['age'] + 0.3 * credit_data['home_owner']) # Add non-linearity log_odds += 0.0003 * credit_data['dti']**2 log_odds -= 0.00001 * credit_data['credit_score'] * credit_data['dti'] prob_default = 1 / (1 + np.exp(-log_odds)) credit_data['default'] = np.random.binomial(1, prob_default) # Generate LGD credit_data['lgd'] = np.where(credit_data['home_owner'] == 1, np.random.normal(0.35, 0.08, n_loans).clip(0.10, 0.70), np.random.normal(0.65, 0.10, n_loans).clip(0.20, 0.90)) # EAD = loan amount credit_data['ead'] = credit_data['loan_amount'] print(f"Generated {len(credit_data)} loans") print(f"Default rate: {credit_data['default'].mean():.2%}") # ---------------------------------------------------------------- # PART B: CREDIT SCORING MODEL # ---------------------------------------------------------------- print("\n" + "-"*60) print("PART B: Credit Scoring Model") print("-"*60) # Features for modelling features = ['age', 'income', 'credit_score', 'dti', 'loan_amount', 'loan_term', 'employment_years', 'home_owner'] X = credit_data[features] y = credit_data['default'] # Train-test split X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42) # Train XGBoost model scale_pos_weight = len(y_train[y_train==0]) / len(y_train[y_train==1]) xgb_model = XGBClassifier(n_estimators=100, max_depth=6, learning_rate=0.1, scale_pos_weight=scale_pos_weight, random_state=42, use_label_encoder=False, eval_metric='logloss') xgb_model.fit(X_train, y_train) # Predictions y_pred_proba = xgb_model.predict_proba(X_test)[:, 1] y_pred = (y_pred_proba >= 0.5).astype(int) # Evaluate auc = roc_auc_score(y_test, y_pred_proba) print(f"Credit Scoring Model AUC: {auc:.4f}") print("\nClassification Report:") print(classification_report(y_test, y_pred, target_names=['No Default', 'Default'])) # Feature importance importance_xgb = pd.DataFrame({ 'Feature': features, 'Importance': xgb_model.feature_importances_ }).sort_values('Importance', ascending=False) print("\nTop 5 Credit Risk Predictors:") print(importance_xgb.head(5).to_string(index=False)) # ---------------------------------------------------------------- # PART C: EXPECTED LOSS CALCULATION # ---------------------------------------------------------------- print("\n" + "-"*60) print("PART C: Expected Loss Calculation") print("-"*60) # Calculate PD for all loans credit_data['pd'] = xgb_model.predict_proba(X)[:, 1] # Calculate Expected Loss credit_data['el'] = credit_data['pd'] * credit_data['lgd'] * credit_data['ead'] # Portfolio summary total_exposure = credit_data['ead'].sum() total_el = credit_data['el'].sum() avg_pd = credit_data['pd'].mean() avg_lgd = credit_data['lgd'].mean() print(f"Portfolio Summary:") print(f" Total Exposure: ${total_exposure:,.2f}") print(f" Total Expected Loss: ${total_el:,.2f}") print(f" EL as % of Exposure: {total_el/total_exposure*100:.2f}%") print(f" Average PD: {avg_pd:.2%}") print(f" Average LGD: {avg_lgd:.2%}") # ---------------------------------------------------------------- # PART D: PORTFOLIO SEGMENTATION # ---------------------------------------------------------------- print("\n" + "-"*60) print("PART D: Portfolio Segmentation") print("-"*60) # Segment by credit score credit_data['credit_score_segment'] = pd.cut(credit_data['credit_score'], bins=[550, 600, 650, 700, 750, 850], labels=['Poor', 'Fair', 'Good', 'Very Good', 'Excellent']) segment_summary = credit_data.groupby('credit_score_segment').agg({ 'default': 'mean', 'pd': 'mean', 'el': 'sum', 'ead': 'sum' }).round(4) print("Portfolio by Credit Score Segment:") print(segment_summary) # Visualise fig, axes = plt.subplots(1, 2, figsize=(14, 5)) # Default Rate by Segment ax = axes[0] segment_summary['default'].plot(kind='bar', ax=ax, color='red', alpha=0.7) ax.set_xlabel('Credit Score Segment') ax.set_ylabel('Default Rate') ax.set_title('Default Rate by Credit Score Segment') ax.grid(True, alpha=0.3) # Expected Loss by Segment ax = axes[1] segment_summary['el'].plot(kind='bar', ax=ax, color='blue', alpha=0.7) ax.set_xlabel('Credit Score Segment') ax.set_ylabel('Expected Loss ($)') ax.set_title('Expected Loss by Credit Score Segment') ax.grid(True, alpha=0.3) plt.tight_layout() plt.savefig('credit_portfolio_segmentation.png', dpi=300, bbox_inches='tight') plt.show() print("Portfolio segmentation visualisation saved as 'credit_portfolio_segmentation.png'") # ---------------------------------------------------------------- # PART E: STRESS TESTING # ---------------------------------------------------------------- print("\n" + "-"*60) print("PART E: Stress Testing") print("-"*60) def stress_test_credit(df, gdp_shock, unemp_shock): """Apply macroeconomic shocks to PD.""" df_stressed = df.copy() # Apply stress in log-odds space log_odds = np.log(df_stressed['pd'] / (1 - df_stressed['pd'])) log_odds += -1.5 * gdp_shock + 3.0 * unemp_shock df_stressed['pd_stressed'] = 1 / (1 + np.exp(-log_odds)) df_stressed['pd_stressed'] = df_stressed['pd_stressed'].clip(0.001, 0.999) df_stressed['el_stressed'] = df_stressed['pd_stressed'] * df_stressed['lgd'] * df_stressed['ead'] return df_stressed # Define scenarios scenarios = { 'Baseline': {'gdp': 0.0, 'unemp': 0.0}, 'Adverse': {'gdp': -0.02, 'unemp': 0.03}, 'Severe': {'gdp': -0.05, 'unemp': 0.06} } stress_results = [] for name, shocks in scenarios.items(): df_stressed = stress_test_credit(credit_data, shocks['gdp'], shocks['unemp']) el_stressed = df_stressed['el_stressed'].sum() stress_results.append({ 'Scenario': name, 'EL': el_stressed, 'Increase %': (el_stressed / total_el - 1) * 100 }) stress_df = pd.DataFrame(stress_results) print("Stress Test Results:") print(stress_df.to_string(index=False)) # ---------------------------------------------------------------- # PART F: CREDIT RISK METRICS # ---------------------------------------------------------------- print("\n" + "-"*60) print("PART F: Credit Risk Metrics Dashboard") print("-"*60) credit_metrics = pd.DataFrame({ 'Metric': [ 'Non-Performing Loan Ratio', 'Delinquency Rate', 'Coverage Ratio', 'Loan Loss Rate', 'Concentration Ratio', 'Average PD', 'Average LGD', 'EL Ratio' ], 'Current Value': [ '3.2%', '2.1%', '112%', '0.8%', '18%', '2.8%', '45%', '1.3%' ], 'Target Value': [ '< 5%', '< 3%', '> 100%', '< 1%', '< 25%', '< 3%', '< 50%', '< 2%' ], 'Status': ['🟢', '🟢', '🟢', '🟢', '🟢', '🟢', '🟢', '🟢'] }) print("Credit Risk Metrics Dashboard:") print(credit_metrics.to_string(index=False)) # ---------------------------------------------------------------- # PART G: SUMMARY AND RECOMMENDATIONS # ---------------------------------------------------------------- print("\n" + "="*70) print("PART G: Summary and Recommendations") print("="*70) print(""" Credit Risk Management – Key Takeaways: 1. Credit risk is the risk of borrower default. 2. Key components: PD, LGD, EAD, Expected Loss, Unexpected Loss. 3. AI-powered credit scoring improves accuracy and inclusivity. 4. Portfolio management: diversification, concentration limits, monitoring. 5. Stress testing evaluates portfolio resilience under adverse scenarios. 6. Regulatory framework: Basel III, IFRS 9/CECL, ECOA. 7. Key metrics: NPL ratio, delinquency, coverage ratio, loan loss rate. Recommendations: - Implement AI-powered credit scoring. - Use alternative data for financial inclusion. - Diversify credit portfolio. - Conduct regular stress testing. - Maintain adequate provisioning. - Ensure fair lending compliance. """) print("="*70) print("END OF LESSON 2 – MODULE 8") print("="*70)
SECTION 7: SUMMARY FOR THE DATA PRACTITIONER
-
Credit risk is the risk of borrower default, measured by PD, LGD, and EAD.
-
AI-powered credit scoring improves accuracy and inclusivity, especially with alternative data.
-
Portfolio management strategies include diversification, concentration limits, monitoring, stress testing, and provisioning.
-
Stress testing evaluates portfolio resilience under adverse macroeconomic scenarios.
-
Regulatory framework includes Basel III, IFRS 9/CECL, and ECOA/Fair Lending.
-
Key metrics include NPL ratio, delinquency rate, coverage ratio, loan loss rate, concentration ratio, and EL ratio.
SECTION 8: RECOMMENDED NEXT STEPS
-
Implement AI-powered credit scoring.
-
Use alternative data for financial inclusion.
-
Diversify credit portfolio.
-
Conduct regular stress testing.
-
Maintain adequate provisioning.
-
Ensure fair lending compliance.
-
Prepare for Lesson 3:Â Market Risk Management.
[END OF LESSON 2 – MODULE 8]