Credit Risk Modeling Approaches › Credit Scoring and Machine Learning Approaches

Michael BrenndoerferDecember 22, 202511 min read
Quantitative FinanceAll chapters
Part 10 of 15Risk Management and Financial Risk Controls
Chapter 55Credit Risk Modeling Approaches › Credit Scoring and Machine Learning Approaches
Reading section 4 of 6 · Credit Scoring and Machine Learning Approaches · 11 minSection 4 of 6 · 11 min

Book contents

Section 4 of 6 · 11 min read

Credit Risk Modeling Approaches › Credit Scoring and Machine Learning ApproachesOne section · Sections in this chapter4 / 6 ↓
Reading tools Definitions & inline links

Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.

Article links

Make inline references clickable

While structural and reduced-form models derive from financial theory, credit scoring uses historical data to predict which borrowers will default based on observable characteristics. This approach dominates retail lending (mortgages, credit cards, personal loans) and increasingly complements market-based models for corporate credit. Credit scoring identifies statistical patterns in observable characteristics that distinguish defaulters from non-defaulters. It does not model economic mechanisms like structural approaches.

Logistic Regression for Default Prediction

Logistic regression models the probability of default as a function of borrower characteristics. The model turns a linear combination of features (financial ratios, firm characteristics) into a probability between 0 and 1 using the logistic function:

P(default)=11+e−(β0+β1x1+⋯+βkxk)P(\text{default}) = \frac{1}{1 + e^{-(\beta_0 + \beta_1 x_1 + \cdots + \beta_k x_k)}}

where:

  • P(default)P(\text{default}): predicted probability of default (bounded between 0 and 1)
  • kk: number of borrower characteristics (features) in the model
  • xix_i: borrower characteristic ii for i=1,…,ki = 1, \ldots, k (e.g., debt-to-equity ratio, profitability, liquidity measures)
  • β0\beta_0: intercept term (baseline log-odds when all features are zero)
  • βi\beta_i: coefficient for feature xix_i, representing the change in log-odds per unit change in xix_i
  • ee: Euler's number (base of natural logarithm, approximately 2.71828)
  • β0+β1x1+⋯+βkxk\beta_0 + \beta_1 x_1 + \cdots + \beta_k x_k: linear combination forming the log-odds or credit score
  • The logistic function 11+e−z\frac{1}{1+e^{-z}} turns the unbounded log-odds zz into a probability between 0 and 1

The linear combination z=β0+β1x1+⋯+βkxkz = \beta_0 + \beta_1 x_1 + \cdots + \beta_k x_k is called the log-odds or credit score. The logistic function, also known as the sigmoid function, turns this potentially unbounded score into a proper probability.

The logistic function has several attractive properties for classification problems. It is monotonically increasing, so higher scores always correspond to higher default probability, which allows straightforward ranking of borrowers by risk. It asymptotically approaches 0 and 1 at the extremes, so predictions are always valid probabilities regardless of how extreme the input features become. It has a simple derivative that facilitates maximum likelihood estimation, making parameter fitting computationally tractable even for large datasets. The coefficients βi\beta_i have a clear interpretation: each coefficient represents the change in log-odds per unit change in the corresponding feature xix_i. A positive coefficient means higher values of that feature increase default probability, while a negative coefficient means higher values decrease default probability.

In[22]:
Code
import numpy as np

# Generate synthetic corporate credit data
np.random.seed(42)
n_firms = 2000

# Features (financial ratios)
debt_to_equity = np.random.exponential(1.5, n_firms)
current_ratio = np.random.lognormal(0.5, 0.4, n_firms)
interest_coverage = np.random.exponential(3, n_firms)
profit_margin = np.random.normal(0.08, 0.15, n_firms)
asset_turnover = np.random.lognormal(-0.3, 0.3, n_firms)

# Generate defaults based on financial ratios
log_odds = (
    -3
    + 0.5 * debt_to_equity
    - 0.8 * current_ratio
    - 0.2 * interest_coverage
    - 5 * profit_margin
    - 0.5 * asset_turnover
)
default_prob = 1 / (1 + np.exp(-log_odds))
defaults = np.random.binomial(1, default_prob)

# Create feature matrix
X = np.column_stack(
    [
        debt_to_equity,
        current_ratio,
        interest_coverage,
        profit_margin,
        asset_turnover,
    ]
)
feature_names = [
    "Debt/Equity",
    "Current Ratio",
    "Interest Coverage",
    "Profit Margin",
    "Asset Turnover",
]
y = defaults
In[23]:
Code
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

## Split data and train model
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=42
)

## Standardize features
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

## Fit logistic regression
logreg = LogisticRegression(random_state=42)
logreg.fit(X_train_scaled, y_train)

# Predictions
y_pred_proba = logreg.predict_proba(X_test_scaled)[:, 1]
Out[24]:
Console
Logistic Regression Credit Scoring Model
==================================================

Model Performance:
  AUC-ROC Score: 0.7556
  Default Rate (Test Set): 1.0%

Feature Coefficients (Standardized):
  Debt/Equity         : +0.7771 (↑ risk)
  Current Ratio       : -0.7393 (↓ risk)
  Interest Coverage   : -0.9778 (↓ risk)
  Profit Margin       : -0.7906 (↓ risk)
  Asset Turnover      : -0.0806 (↓ risk)

The model demonstrates useful discriminatory power with an AUC-ROC score of about 0.756, indicating that it ranks a randomly chosen defaulter above a randomly chosen non-defaulter roughly three-quarters of the time. The coefficients reveal intuitive relationships consistent with financial theory: higher debt-to-equity increases default risk (positive coefficient) because more leverage means less cushion to absorb losses. Better profitability (negative coefficient on profit margin) reduces default risk because profitable firms generate cash to service debt. Stronger liquidity (negative coefficients on current ratio and interest coverage) also reduces default risk because liquid firms can meet short-term obligations. The test set default rate matches the training distribution, though a full calibration assessment would require additional diagnostics beyond the default-rate comparison.

Out[25]:
Visualization
Horizontal bar chart of five standardized logistic-regression coefficients ordered by absolute magnitude. Debt-to-equity is the only positive coefficient, while current ratio, interest coverage, profit margin, and asset turnover are negative; distinct fills and signed value labels show direction and magnitude.
Standardized logistic regression coefficients from a credit scoring model ordered by absolute magnitude. Interest coverage has the largest protective coefficient (-0.98), while debt-to-equity is the only positive coefficient (+0.78); profit margin (-0.79) and current ratio (-0.74) also materially reduce predicted default risk.

The coefficient visualization provides immediate insight into which factors drive default risk in the model. Debt-to-equity ratio is the only positive coefficient, indicating that higher leverage raises predicted default risk. All other features have negative coefficients, meaning higher values reduce default probability. Interest coverage shows the strongest protective effect, followed by profit margin and the current ratio; together they reflect the importance of debt-service capacity, profitability, and liquidity. Asset turnover has a smaller but still negative effect, suggesting operationally efficient firms face lower default risk.

Altman Z-Score: A Classic Scoring Model

Edward Altman's 1968 Z-score remains widely used for bankruptcy prediction. It demonstrates that simple models with clear economic interpretation can be highly effective. The model combines five financial ratios that collectively capture liquidity, profitability, leverage, solvency, and activity:

Z=1.2X1+1.4X2+3.3X3+0.6X4+1.0X5Z = 1.2X_1 + 1.4X_2 + 3.3X_3 + 0.6X_4 + 1.0X_5

where:

  • ZZ: composite bankruptcy risk score
  • X1X_1: Working Capital / Total Assets (measures liquidity and short-term financial health)
  • X2X_2: Retained Earnings / Total Assets (measures cumulative profitability and firm age)
  • X3X_3: EBIT / Total Assets (measures operating efficiency and profitability before interest and taxes)
  • X4X_4: Market Value of Equity / Book Value of Debt (measures leverage and market confidence in the firm)
  • X5X_5: Sales / Total Assets (measures asset turnover and revenue generation efficiency)
  • The coefficients 1.2, 1.4, 3.3, 0.6, and 1.0 were determined empirically through discriminant analysis on historical bankruptcy data
  • Higher ZZ-scores indicate lower bankruptcy risk, lower scores indicate higher risk

Firms with Z<1.81Z < 1.81 are classified as distressed, indicating high default risk. Values with Z>2.99Z > 2.99 indicate healthy firms with low default risk. Values between 1.81 and 2.99 fall in the gray zone where classification is uncertain.

The Z-score's enduring popularity stems from its simplicity and interpretability. Each ratio captures a different dimension of financial health: X1X_1 measures liquidity, the firm's ability to meet short-term obligations. X2X_2 captures cumulative profitability and implicitly firm age, since retained earnings accumulate over time. X3X_3 measures operating performance, the core earnings power of the business before financing decisions. X4X_4 combines market information with book values, capturing both leverage and the market's confidence in the firm's prospects. X5X_5 measures asset efficiency, how effectively the firm uses its assets to generate revenue. The weights reflect their relative importance in predicting bankruptcy, with operating profitability (X3X_3) receiving the highest weight of 3.3, indicating it is the strongest discriminator between healthy and distressed firms.

In[26]:
Code
def altman_z_score(
    working_capital,
    retained_earnings,
    ebit,
    market_equity,
    book_debt,
    sales,
    total_assets,
):
    """
    Calculate Altman Z-Score for bankruptcy prediction.

    Returns
    -------
    z_score : float
        Altman Z-Score
    classification : str
        Risk classification
    """
    X1 = working_capital / total_assets
    X2 = retained_earnings / total_assets
    X3 = ebit / total_assets
    X4 = market_equity / book_debt
    X5 = sales / total_assets

    z = 1.2 * X1 + 1.4 * X2 + 3.3 * X3 + 0.6 * X4 + 1.0 * X5

    if z < 1.81:
        classification = "Distressed (High Default Risk)"
    elif z > 2.99:
        classification = "Safe (Low Default Risk)"
    else:
        classification = "Gray Zone (Uncertain)"

    return z, classification
In[27]:
Code
# Example: Two companies
# Company A: Strong financials
z_a, class_a = altman_z_score(
    working_capital=50,
    retained_earnings=80,
    ebit=30,
    market_equity=200,
    book_debt=50,
    sales=300,
    total_assets=250,
)

# Company B: Weak financials
z_b, class_b = altman_z_score(
    working_capital=-10,
    retained_earnings=20,
    ebit=5,
    market_equity=30,
    book_debt=100,
    sales=150,
    total_assets=180,
)
Out[28]:
Console
Altman Z-Score Analysis
========================================

Company A:
  Z-Score: 4.68
  Classification: Safe (Low Default Risk)

Company B:
  Z-Score: 1.19
  Classification: Distressed (High Default Risk)

Company A demonstrates financial health with a Z-score above 3, placing it firmly in the safe zone with low default risk. The strong working capital position indicates liquidity to meet short-term obligations. High retained earnings relative to assets suggest mature profitability and financial stability accumulated over time. Healthy EBIT margins demonstrate operating efficiency, while the favorable ratio of market equity to book debt reflects both low leverage and market confidence in the firm's prospects. In contrast, Company B shows financial distress with a Z-score below 1.81, indicating high default risk. Negative working capital is a serious warning sign, suggesting the firm may struggle to pay current obligations. Weak profitability ratios indicate the core business is not generating adequate returns. High leverage relative to market equity suggests the firm is overleveraged, with debt exceeding what the market believes the equity is worth. These results show how the Z-score effectively synthesizes multiple financial dimensions into a single risk metric. It can be easily communicated and compared across firms.

ROC Analysis and Model Discrimination

The Receiver Operating Characteristic (ROC) curve visualizes how well a credit scoring model separates defaulters from non-defaulters across different probability thresholds. This diagnostic tool is essential for evaluating and comparing credit models.

In[29]:
Code
from sklearn.metrics import roc_auc_score, roc_curve

# Calculate ROC curve
fpr, tpr, thresholds = roc_curve(y_test, y_pred_proba)
auc_score = roc_auc_score(y_test, y_pred_proba)
Out[30]:
Visualization
ROC line rising above the random-classifier diagonal, with an area under the curve of 0.756.
Receiver Operating Characteristic (ROC) curve for the logistic regression credit scoring model. The curve plots true-positive rate against false-positive rate across classification thresholds and achieves an AUC of 0.756, clearly outperforming the diagonal random-classifier benchmark while leaving room for model improvement.

The ROC curve shows useful model performance, with the fitted curve remaining above the diagonal random-classifier line. The diagonal represents a model with no discriminatory power: one that assigns default probabilities randomly and thus performs no better than chance. The area under the ROC curve (AUC) quantifies overall ranking ability. An AUC of 0.5 represents random guessing, while 1.0 represents perfect discrimination where all defaulters receive higher risk scores than all non-defaulters. Here the logistic regression model achieves an AUC of about 0.756, so it provides meaningful separation without approaching perfect classification. The curve also reveals the tradeoff faced at any threshold: moving left along the curve reduces false positives (healthy firms incorrectly flagged) but also reduces true positives (actual defaults caught).