Machine Learning

How to Build a Credit Grid From an Asset Amortization Model

All code used in this article is available on GitHub. The business logic and modeling functions are available in src/selection directory, specifically to the following file:

src/modeling/score_computation.py

Corresponding analysis and results are documented in:

09_score_computation.qmd

Figures, tables, and charts were produced with the help of the Codex code assistant.

Your credit score follows you everywhere. It determines whether you get a loan, a credit card, or an apartment. The model behind many of these decisions is FICO. Its logic is simple once you break it down.

FICO is weighted by five factors:

  • Payment history (35%): pay your bills on time.
  • Debt (30%): keep your debt utilization below 20%.
  • Length of history (15%): the longer, the better.
  • Credit mix (10%): use different types of credit.
  • New credit (10%): limit new applications.

When you pay your credit card bills on time, your credit score goes up. Payment history carries a lot of weight.

These weights produce a score, divided into ranges:

  • 300–579: The poor.
  • 580–669: Fair.
  • 670–739: Good.
  • 740–799: Very good.
  • 800-850: Very good.

This article follows the same reasoning, but applies it to our model.

We use the dataset of this series to build a scoring model. The goal is simple: give each stored variable a weight, calculate the score for each client in our data, and show how the new client's score is calculated.

As before, Codex helped write the code and created tables and charts. I keep saying this because it's important: you can use AI agents to speed up your work. But check their result. Trust grows only when you have confirmed it. Use these tools, but be careful.

Let's remember what we found in the past. We have kept four variables:

  • loan_int_rate: loan interest rate.
  • loan_percent_income: the proportion of income used for loan payments.
  • cb_person_default_on_file: even if the borrower has previously defaulted.
  • home_ownership_3: the condition of the borrower's house.

Like FICO, we give each variable a weight and create a score from 0 to 1000. Higher scores mean lower risk. A lower score means a greater risk of default.

From the Coefficients of the models to the result

We turn each coefficient into a score.

Score each variable category

Take it loan_int_rate as an example. Category score ii by:

𝑺𝑪(𝒋,𝒊)=1000x|𝒄(𝒋,𝒊)𝜶𝒋|𝒋=1💑𝜶𝒋bm{ SC(j,i) = 1000 times frac{ left|c(j,i)-alpha_jright| {sum_{j=1}^{p}alpha_j }}

Here, c(j,i)c(j,i) is the phase coefficient ii of change jj. Again ajalpha_j is the highest coefficient of variation jj. For example, in the variable loan_int_rate, the highest coefficient is aj=1.357044926979alpha_j = 1.357044926979 .

This formula gives the score table below.

Client score, step by step

Take on a new client. We examine which category they fall into for each variable:

  • loan_int_rate is 10%. Average: 181.72.
  • loan_percent_income is 25%. Score: 0.
  • No past defaults (cb_person_default_on_file = N). Average: 59.52.
  • You have their home (home_ownership_3 = OWN). Average: 373.94.

We add these points to get the client's final score:181.72+59.52+0+373.94=615.18bm{181.72 + 59.52 + 0 + 373.94 = 615.18}

We repeat this for all clients in our database.

How important is each variable

Once we get the scores, we ask: which variable drives you the most?

We measure this with training data:

Here:

  • pk: share of customers in the segment k of change j;p_k : text{ assignment of clients in category } k text{ variable } j;
  • The bar is empty SCjmathrm{SC}_j represents the mean score of variable j, scaled by the population;
  • mj: number of categories in the variable j;m_j : text{ number of sections in variable } j;
  • n: number of variables in the model.n : text{ number of variables in the model.}

In simple words, qjq_jshows how much is variable jj moves the score. The greater the difference between its different categories, the higher its weight.

The table below shows the weight of each variable.

loan_percent_income it weighs too much, at 35%. Then home_ownership_3 of 31%, loan_int_rate of 28%again cb_person_default_on_file last time.

This makes sense. A client who spends more than 20% of his income on loan repayments is risky. The fact that this variable drives the score so much is good news: the model is picking up the right signal.

Does the Score Correctly Classify Risk?

Before we build the risk grid, we check if the score does its job: separate defaulters from non-defaulters.

We plot the density of points for each group, automatically classified, for all train, test, and out-of-date data.

The more the two curves diverge, the more effective the score.

What we see: automatic clustering at low points. A non-default cluster for high scores. This is what we want: high score, low risk.

Creating a Risk Grid

Now we create a grid.

Step 1: Default level by score group

We divide the scores into 20 equal groups and plot a standardized mean for each group. We start by plotting the standard deviation against the vingtiles (20 segments of equal size) of the final score.

This chart is the basis of the grid: it provides a natural starting point for grouping the 20 segments into six risk categories.

Step 2: Six risk classes

Based on the chart, we group the 20 segments as follows:

  • Groups 1, 2, 3, with scores between 0 and 241: the lower the score, the higher the risk.
  • Groups 4, 5, 6, have between 241 and 331 points.
  • Groups 7, 8, have between 332 and 498 points.
  • Groups 9, 10, 11, 12, have between 498 and 589 points.
  • Groups 13, 14, 15, 16, 17, have between 589 and 780 points.
  • Groups 18, 19, 20, with points between 781 and 1000: the higher the score, the lower the risk.

These classes must meet three rules:

✓ Each class must be at the same level of risk;
✓ Each class must differ from the next by at least 30%;
✓ Each class must hold at least 1% of all clients.

The table above shows that these rules are followed.

Step 3: Stability test

A risk grid only works if it holds up over time. We look for two things:

  • Risk classes should always show high default values, throughout the full history.
  • The number of clients in each class should remain stable over time.

Both hold true: risk remains reasonable, and class sizes remain strong.

The conclusion

This article concludes our series on building a scoring model. We started with data and ended with a risk grid.

We created a score from 0 to 1000 by scoring each category for each variable. The client's score is the sum of these category scores. The result is a clear separation of risks: defaulters and non-defaulters live in distinctly different ranges.

The weight of each variable: loan_percent_income earns 35%, then home_ownership_3 by 31%, loan_int_rate by 28%, too cb_person_default_on_file last time.

👉 Good to know: the higher your income compared to your loan, the higher your score.

Final grid at risk:

  • 0–241: Very High Risk.
  • 241–331: Great risk.
  • 332–498: Moderate-High Risk.
  • 499–589: Middle Risk.
  • 590–789: Low Risk.
  • 790–1000: Very low risk.

I kept this article short on purpose. We've created a grid here using vingtiles and visual integration, but there are other mathematical methods for dividing scores into equal classes. K-methods, class clustering, and Weight of Evidence (WoE) all provide a robust approach to the same goal. That will be the subject of my next article.

References

[1] Lorenzo Beretta and Alessandro Santaniello.
Nearest Neighbor Enforcement Algorithms: A Critical Evaluation.
National Library of Medicine, 2016.

[2] Nexialog Consulting.
Traitement des données maquantes dans le milieu bancaire.
Working paper, 2022.

[3] John T. Hancock and Taghi M. Khoshgoftaar.
A Survey of Class Data in Sensor Networks.
Journal of Big Data, 7(28), 2020.

[4] Melissa J. Azur, Elizabeth A. Stuart, Constantine Frangakis, and Philip J. Leaf.
Multiple Imputation by Chained Equations: What Is It and How Does It Work?
International Journal of Psychological Research Methods, 2011.

[5] Majid Sarmad.
Robust Data Analysis of Industrial Experimental Designs: Advanced Methods and Software.
Department of Mathematics, University of Durham, England, 2006.

[6] Daniel J. Stekhoven and Peter Bühlmann.
MissForest—Non-Parametric Missing Value Imputation for Mixed-Type Data.Bioinformatics, 2011.

[7] Supriyanto Wibisono, Anwar, and Amin.
Multivariate Weather Anomaly Detection Using the DBSCAN Clustering Algorithm.
Journal of Physics: Conference Series, 2021.

[8] Laborda, J., & Ryoo, S. (2021). Feature selection in credit scoring models. Statistics, 9(7), 746.

Data and License

The dataset used in this article is licensed under the Creative Commons Attribution 4.0 International (CC BY 4.0) license.

This license allows anyone to share and adapt the dataset for any purpose, including commercial use, as long as proper attribution is given to the source.

For more information, see the official license text: CC0: Public Domain.

Disclaimer

Any remaining errors or inaccuracies are the responsibility of the author. Feedback and corrections are welcome.

Source link

Related Articles

Leave a Reply

Your email address will not be published. Required fields are marked *

Back to top button