TOAD: a Python toolkit for building credit scorecards
ESC Team's credit scorecard tools.
At a glance
- What is it?
- TOAD is a Python package for the industrial model development workflow, with the emphasis on scorecards: information value calculation, feature selection, fine binning with a chi-squared method, model validation and a one-step scorecard transformation. It is MIT licensed, documents in English and Chinese, and ships both a pure Python build and a Rust core.
- Who is it for?
- TOAD suits a credit risk analyst who has to build and document a scorecard rather than chase the highest accuracy metric, because it covers the awkward steps, feature selection and fine binning, with the binning and the scorecard scaling wired together.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 129 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The workflow TOAD is built around
TOAD is dedicated to facilitating the model development process, especially for a scorecard. It provides functions covering the entire process, from exploratory data analysis, feature engineering and selection through to results validation and scorecard transformation. The README names the two steps it is designed to simplify most, feature selection and fine binning.
That framing matters because it tells you what TOAD is not. It is not a general machine learning library, and it is not a model-fitting wrapper. It is a set of procedures for the specific workflow of a credit risk scorecard, where a model has to be explainable enough to hand to a regulator, a business team or a model risk function.
The topic list confirms the domain: credit-risk, credit-scoring, data-analysis, financial-analysis, scorecard. The project is dedicated by the ESC Team, the homepage is toad.readthedocs.io, the licence is MIT, and the primary language is Python. The README is bilingual, with the English and Chinese descriptions side by side, and the documentation includes both an English tutorial and a Chinese guide, plus a WeChat group for questions.
Two usage patterns are worth noticing. The package exposes a flat top-level API for the simple operations, so toad.quality(data, 'target', indicators = ['iv']) computes information value for every feature in one call, and the heavier procedures live in submodules such as toad.selection and toad.transform. That is a deliberate split between the one-liners and the machinery.
Installation, and three different builds
Three installation routes are documented, and the difference between them matters more than usual here because of how the package is built.
With pip:
pip install toad # to install
pip install -U toad # to upgradeWith conda:
conda install toad --channel conda-forge # to install
conda install -U toad --channel conda-forge # to upgradeAnd from source:
python setup.py installNow look at the packaging files. The pyproject.toml names maturin as the build backend, requiring maturin 1.0 or newer, and configures maturin to build the toad Python package with the test files excluded. There is a Cargo.toml alongside it defining a crate called toad with a cdylib library named toad_core, built against pyo3 0.22 with the extension-module and abi3-py39 features, plus numpy, ndarray, ndarray-stats and num-traits, with opt-level 3, link-time optimisation and a single codegen unit in the release profile.
And there is a setup.py, which is the older build path. It compiles two Cython extensions, toad.c_utils from toad/c_utils.pyx and toad.merge from toad/merge.pyx, both including numpy's headers, and it reads the version from toad/version.py and the dependencies from requirements.txt.
So the package can be built as a Rust extension through maturin or as Cython extensions through setuptools, and the choice affects whether you need a Rust toolchain or a C compiler and NumPy headers. The console script is toad = toad.cli:main, so the CLI is installed as a toad command either way.
Information value and the selection stage
The first thing TOAD does is measure. The one-liner for information value is:
toad.quality(data, 'target', indicators = ['iv'])Information value is the standard credit risk measure of how much a feature separates good from bad borrowers, and computing it for every column at once is the natural first step of a scorecard build.
Selection comes in two stages. The first is preliminary selection based on criteria, and the second is stepwise feature selection with an optimised algorithm:
selected_data = toad.selection.select(data,target = 'target', empty = 0.5, iv = 0.02, corr = 0.7, return_drop=True, exclude=['ID','month'])
final_data = toad.selection.stepwise(data_woe,target = 'target', estimator='ols', direction = 'both', criterion = 'aic', exclude = to_drop)Read the arguments. empty = 0.5 drops features that are more than half empty. iv = 0.02 sets the information value threshold, which is a low bar, and is the kind of number that is usually tightened by a risk policy rather than by the tool. corr = 0.7 sets a correlation ceiling, which is how the library avoids carrying two features that say the same thing into the same model. exclude names columns to skip outright, and the ID and month examples are typical exclusions for a time-series-flavoured dataset. return_drop=True gives you the list of dropped columns back, which you need because the next stage needs to know what to exclude.
The stepwise call then works on the woe-transformed data, with an estimator, a direction that can be both, and an information criterion for deciding when to stop. The direction and criterion parameters are the ones to think about, because a stepwise procedure with the wrong criterion will quietly give you a different model than the one you would have chosen by hand.
Fine binning with a chi-squared method
Binning is where scorecards live and where TOAD's Combiner does its most specific work. The documented example:
# Chi-squared fine binning
c = toad.transform.Combiner()
c.fit(data_selected.drop(to_drop, axis=1), y = 'target', method = 'chi', min_samples = 0.05)
print(c.export())
# Visualisation to check binning results
col = 'feature_name'
bin_plot(c.transform(data_selected[[col,'target']], labels=True), x=col, target='target')The Combiner is fitted on the data with the target column named, using method = 'chi', which selects the chi-squared method for determining bins. The min_samples = 0.05 argument is a guard on bin size, stopping the procedure from creating bins that are too small to read. The export call prints the resulting binning specification, which is the artefact a reviewer needs to see.
The visualisation step is not optional decoration. bin_plot takes the transformed feature with labels=True, so each row is tagged with its bin, and plots the target distribution per bin. That plot is how you check whether the binning actually separates the classes or whether the procedure produced something statistically valid but commercially useless.
The Combiner is a separate object from the transformer, and that separation is what makes the pipeline composable: the same fitted Combiner is passed into the ScoreCard later, so the binning used in development is the binning used in production.
Model validation and the scorecard transformation
Validation is presented through the metrics module, and the example given is a bucketed KS statistic:
toad.metrics.KS_bucket(pred_proba, final_data['target'], bucket=10, method = 'quantile')KS, the Kolmogorov-Smirnov statistic, is the standard measure of how well a score separates good from bad, and bucket = 10 with method = 'quantile' computes it across ten equal-count buckets of the predicted probability. Reporting KS per bucket rather than as one number is what a risk committee asks for, because a single KS can hide a model that discriminates well in the middle of the population and badly in the tails.
The scorecard transformation is where everything comes together:
card = toad.ScoreCard(
combiner = c,
transer = transer,
class_weight = 'balanced',
C=0.1,
base_score = 600,
base_odds = 35 ,
pdo = 60,
rate = 2
)
card.fit(final_data[col], final_data['target'])
print(card.export())The parameters are the credit scoring convention. base_score = 600 and base_odds = 35 fix the point where the scale is anchored, so a score of 600 corresponds to odds of 35 to 1. pdo = 60 is the points to double the odds, meaning every 60 points doubles the odds of being good. rate = 2 is the rate at which the scale increases with the odds, in the FICO-style points scheme. Together these four numbers are the entire business decision, and they are why a scorecard is not just a model with a header.
The Combiner built earlier goes in as combiner, the fitted woe transformer as transer, so the binning and the transformation used in fitting are the ones used at scoring time. card.fit then takes a single column and the target, which suggests the card is built per feature and combined, and card.export produces the scorecard specification to hand over.
Where TOAD stops
Three limits are worth stating. The first is the domain lock. TOAD is a scorecard toolkit, and the feature list reflects that: information value, weight of evidence, binning, stepwise selection, score scaling. If your problem is a general supervised learning task, the standard scientific Python stack serves you better, and a general library lets you use any estimator rather than the ones this package wires up.
The second is that it is a modelling aid, not a governance system. TOAD will happily produce a scorecard, but nothing in the package version of the README describes monitoring, model validation governance, or documentation generation beyond the export calls. In a regulated environment, the artefacts TOAD produces are inputs to a process you own.
The third is the packaging friction, and here the evidence is in the repository itself. There are two build systems coexisting. The pyproject.toml targets maturin and a Rust core, while setup.py targets Cython extensions, and setup.py declares python_requires = '>=3.7' while pyproject.toml requires-python = ">=3.9" and the classifiers list 3.9 through 3.12. That inconsistency between files is exactly the kind of thing that makes a build fail on one platform and work on another, and it is worth testing on your target environment rather than assuming.
There is also a hint of a Rust rewrite in progress. The Cargo.toml exists with a release profile tuned for speed, the crate builds a cdylib named toad_core through pyo3 with the abi3-py39 feature, and the release tags include an aarch64 variant published on 2026-06-16 alongside the v0.1.7 tag from 2026-05-18. The separate requirements-nn.txt, requirements-pmml.txt and requirements-tools.txt optional dependency groups suggest the neural network, PMML export and tooling extras are pluggable, with an all group that installs them together. A project mid-rewrite between a Cython implementation and a Rust core is one to watch rather than to depend on heavily, and the MIT licence at least means you can vendor it.
Editorial conclusion
TOAD suits a credit risk analyst who has to build and document a scorecard rather than chase the highest accuracy metric, because it covers the awkward steps, feature selection and fine binning, with the binning and the scorecard scaling wired together. It is the wrong tool if you need a general machine learning toolkit, since the feature list is specialised, and it is the wrong tool if your organisation does not want a compiled extension in its build chain, because the fast path is a Rust crate and the legacy path is Cython. Verify first which build you are getting, since the packaging carries both setuptools with Cython extensions and a maturin Rust build, and note that the newest release is v0.1.7 from 2026-05-18 with an aarch64 build tagged on 2026-06-16 and the last push on 2026-06-16.
Frequently asked questions
What is TOAD used for?
It is a Python package for the industrial model development process, especially scorecard development, covering exploratory data analysis, feature engineering, feature selection, results validation and scorecard transformation. Its main contribution is simplifying feature selection and fine binning.
How do I install TOAD?
With pip using pip install toad, with conda using conda install toad --channel conda-forge, or from source with python setup.py install. The pyproject.toml uses maturin as its build backend, so building from source can involve a Rust toolchain.
How do I compute information value for all features in TOAD?
Call toad.quality with the data, the target column name and the indicators list, so toad.quality(data, 'target', indicators = ['iv']).
How does the chi-squared fine binning in TOAD work?
You create a toad.transform.Combiner, fit it with method = 'chi' and a min_samples floor so bins do not become too small, then call export to see the binning specification. bin_plot on the transformed data with labels=True lets you check the binning visually against the target.
What do base_score, base_odds, pdo and rate mean in the TOAD scorecard?
They are the credit scoring scale parameters. base_score = 600 and base_odds = 35 anchor the scale so a score of 600 means odds of 35 to 1, pdo = 60 is the number of points that doubles the odds, and rate = 2 is the rate at which the scale increases with the odds.
Is TOAD built in Rust or Cython?
Both paths exist. The pyproject.toml uses maturin with a Cargo.toml defining a toad_core cdylib through pyo3, while setup.py compiles two Cython extensions, toad.c_utils and toad.merge, from .pyx sources.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/amphibian-dev-toad)Was this useful?