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

python
# ===================================================================
# 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

  1. Implement AI-powered credit scoring.

  2. Use alternative data for financial inclusion.

  3. Diversify credit portfolio.

  4. Conduct regular stress testing.

  5. Maintain adequate provisioning.

  6. Ensure fair lending compliance.

  7. Prepare for Lesson 3: Market Risk Management.


[END OF LESSON 2 – MODULE 8]

 
Â