Skip to main content

eqlx-ifrs9

Deterministic IFRS 9 expected credit loss: PD term structures, stage allocation, 12-month and lifetime ECL, scenario weighting, the provision matrix, and a rule profile for Turkey (BDDK). A Python library, a command line tool and a read-only MCP server for AI agents.

It computes. It does not estimate PD or LGD models and it does not forecast the economy: PDs, LGDs, scenario paths and thresholds are inputs. Same input, same output, and every figure can be traced back to the loan, the rule and the setting that produced it.

  • Explicit choices. IFRS 9 leaves a lot to the entity: what "significant" means, how many scenarios, when inside a period default happens. Each of those is a named setting, never a hidden default, and settings that supervisors have publicly criticised produce a warning.
  • Checked against published numbers. The IASB's own illustrative examples, the transition resource group's scenario example and a published rating matrix are reproduced in the test-suite; everything else is checked against closed forms, direct enumeration and simulation.
  • Built for agents. The agent decides what to look at; the tool returns the number and the reason. The MCP server only reads files in one folder and writes nothing.

Who it is for

Credit risk and finance teams who want an independent recalculation of their allowance, auditors and model validators who need a transparent benchmark, teams in smaller lenders who do not run a vendor engine, and people building AI agents for credit work.

Install

pip install eqlx-ifrs9            # library and command line
pip install "eqlx-ifrs9[mcp]"     # with the MCP server

Python 3.10 or later. Dependencies: NumPy and SciPy.

A first look

ifrs9 sample demo                 # a made-up portfolio of 2,011 loans, settings, and known answers
ifrs9 run demo/loans.csv --config demo/settings.json
loans 2,011   exposure 2,828,567,386.34   ECL 102,343,016.39   coverage 3.62%

stage      loans            exposure    share               ECL  coverage
1          1,607    2,249,809,211.77    79.5%     12,456,032.90     0.55%
2            348      441,415,469.37    15.6%     12,878,196.38     2.92%
3             56      137,342,705.20     4.9%     77,008,787.11    56.07%

stage 2 by primary reason
  pd_relative                    235      309,819,436.40     10,489,482.54
  days_past_due_backstop          56       67,610,588.76      1,669,616.00
  forborne                        29       37,901,342.97        530,776.72
  watchlist                       27       25,984,101.23        186,525.26
  probation                        1          100,000.00          1,795.86

scenarios (ECL if one scenario alone had full weight)
  base          weight   60%  same stages    94,135,368.37  restaged    92,655,649.27  (53 loans change stage)
  downside      weight   25%  same stages   132,299,414.92  restaged   142,398,307.48  (336 loans change stage)
  upside        weight   15%  same stages    85,246,277.60  restaged    83,600,059.51  (149 loans change stage)
  weighted / base: 1.105

checks
  stage 1 loans whose PD has tripled since origination: 0
  stage 2 only because of days past due: 56 (15.3% of stage 2 exposure)
  stage 1 kept by the low credit risk exemption: 1
  loans without origination PD: 0

Then ask about one loan, or about a different policy:

ifrs9 loan demo/loans.csv CASE-GROUP-X-CURRENT --config demo/settings.json
ifrs9 compare demo/loans.csv --config demo/settings.json --set staging.relative_threshold=3
ifrs9 list demo/loans.csv --config demo/settings.json --stage 2 --reason days_past_due_backstop

The first command explains a loan that is not past due itself and still sits in stage 3:

{
  "loan_id": "CASE-GROUP-X-CURRENT",
  "stage": 3,
  "reasons": ["profile_default"],
  "regulatory_group": 4,
  "regulatory_reasons": [
    "another loan of the borrower is non-performing: same group 4 (Art. 5(5))"
  ],
  "exposure": 5000000.0,
  "ecl": 2750000.0,
  "measurement": "exposure x loss rate in default"
}

As a library

from eqlx_ifrs9 import PDCurve, cycle, expected_credit_loss, schedule
from eqlx_ifrs9.staging import StagingPolicy, assess

# A 36-month instalment loan, 12-month PD 3%, LGD 60%, effective interest rate 31%.
loan = schedule.annuity(100_000, 0.30, 36)
curve = PDCurve.flat(0.03, 36)
res = expected_credit_loss(curve, loan.ead(), lgd=0.60, effective_interest_rate=0.31)
res.twelve_month, res.lifetime  # 1406.99, 2351.36

# The same loan in a downturn: long-run PD shifted year by year (z < 0 is a bad year).
down = cycle.pit_curve(curve, rho=0.06, z_by_year=[-1.6, -1.0, -0.4])
expected_credit_loss(down, loan.ead(), 0.60, 0.31).lifetime  # 4226.37

# Has credit risk increased significantly? Compare with the PD that was expected at origination
# for the SAME remaining window: two years into a five-year loan, that is years 3 to 5.
at_origination = PDCurve.from_cumulative([0.01, 0.025, 0.045, 0.07, 0.10], periods_per_year=1)
expected_then = at_origination.forward(2).pd_over()  # 0.0769, not the five-year 0.10
r = assess(StagingPolicy(relative_threshold=2.0), pd_now=[0.16], pd_origination=[expected_then])
r.stage[0], r.reason_names(0), r.pd_ratio[0]  # 2, ['pd_relative'], 2.08

Modules: curves (PD term structures), transitions (rating matrices, generators, cycle shift), cycle (one-factor point-in-time adjustment), schedule (repayment and exposure), lgd (collateral, workout, credit-impaired assets), ecl, staging, scenarios, simplified (provision matrix), profiles.tr_bddk, and for whole portfolios data, config, engine, report.

For AI agents (MCP)

ifrs9 mcp --root /path/to/folder

Claude Code, Claude Desktop or any other MCP client can then use these tools. All are read-only and confined to that folder; nothing is written and nothing leaves the machine.

Tool What it returns
list_files loan files (.csv) and settings files (.json) in the folder
describe_loans what a loan file contains, and what is missing, before any calculation
run_portfolio stage and ECL for every loan: tables by stage, segment, reason and scenario, checks, warnings
list_loans loans matching a filter, with every rule that fired
explain_loan one loan step by step: staging test, PD and ECL per scenario and year
compare_settings what a different threshold, weight or scenario would change
calculate_ecl 12-month and lifetime ECL of one instrument from plain numbers
pd_term_structure cumulative PD by grade from a transition matrix, with generator diagnostics
provision_matrix simplified approach for trade receivables
turkey_reclassification_check BDDK conditions for moving a loan back up, with article numbers

Input

Loan file (CSV, one row per instrument). Required: loan_id, balance, eir, remaining_months, lgd, and pd_12m or grade. Optional columns cover the borrower, segment, repayment type, undrawn limits, origination risk, days past due and status flags; the full list is in eqlx_ifrs9/data.py. Rates and PDs are fractions (0.05 for 5%).

Settings (JSON). Staging thresholds, scenarios with weights and a z path per forecast year, reversion after the forecast horizon, segment parameters (asset correlation, prepayment, a transition matrix), calculation conventions and an optional profile. ifrs9 sample writes a complete example; eqlx_ifrs9/config.py documents every key. Unknown keys and out-of-range values are rejected.

How it is verified

What Checked against
12-month ECL, explicit PD IFRS 9 Illustrative Example 8: CU1,250
Loss rate approach Illustrative Example 9: CU750 and CU675
Exposure of revolving facilities Illustrative Example 10: CU25,000 and CU45,000
Provision matrix Illustrative Example 12: CU580,000; IFRS 7 IG20D: CU114 and CU145 thousand
Probability weighting Transition resource group, December 2015: CU92 against CU70 for one scenario
Generators of rating matrices Israel, Rosenthal and Wei (2001): error norms 0.002736 and 0.002686
Lifetime ECL with discounting closed form for a bullet loan; continuous-time limit; direct enumeration
The same, amortising loan simulation of two million default times
One-factor shift the average over the cycle returns the long-run PD and matrix (numerical integration)
Portfolio run every loan recomputed with the scalar functions; independence of row order and chunking
Turkey profile article by article against the regulation text; contagion against direct enumeration

The illustrative examples do not cover multi-period discounting, several scenarios or a numeric staging threshold. Those parts rest on the closed forms, the enumeration and the simulation. Tests also pin down frequent mistakes: summing conditional PDs without survival weighting, using a 12-month PD on a six-month loan, dividing an annual PD by twelve, giving a bullet loan no exposure in its last period, and comparing today's remaining-life PD with the full-life PD at origination.

Limits

This is a calculation tool, not an accounting opinion and not a validated model. It covers the impairment arithmetic of IFRS 9 Section 5.5 for loans, undrawn commitments and trade receivables. It does not cover classification and measurement, hedge accounting, purchased or originated credit-impaired assets, or the allowance movement table. See LIMITS.md before relying on a number.

References

  • IFRS 9 Financial Instruments, Section 5.5 and Application Guidance B5.5; Illustrative Examples (IFRS Foundation). TFRS 9 is the Turkish equivalent with the same paragraph numbers (KGK).
  • IFRS 7 Financial Instruments: Disclosures, paragraphs 35A-35N and Implementation Guidance IG20D.
  • IFRS Transition Resource Group for Impairment of Financial Instruments, meeting summaries 2015.
  • Basel Committee on Banking Supervision (2015), Guidance on credit risk and accounting for expected credit losses.
  • European Banking Authority (2021, 2023), IFRS 9 implementation by EU institutions, monitoring reports; ECB Banking Supervision, letter of 4 December 2020 on credit risk identification.
  • BDDK, Kredilerin Sınıflandırılması ve Bunlar İçin Ayrılacak Karşılıklara İlişkin Usul ve Esaslar Hakkında Yönetmelik, Official Gazette 22 June 2016, no. 29750, as amended.
  • Vasicek, O. (2002), "The distribution of loan portfolio value", Risk.
  • Belkin, B., Suchower, S. and Forest, L. (1998), "A one-parameter representation of credit risk and transition matrices", CreditMetrics Monitor.
  • Israel, R., Rosenthal, J. and Wei, J. (2001), "Finding generators for Markov chains via empirical transition matrices, with applications to credit ratings", Mathematical Finance 11(2).
  • Jarrow, R., Lando, D. and Turnbull, S. (1997), "A Markov model for the term structure of credit risk spreads", Review of Financial Studies 10(2).

License

Apache-2.0. Part of eqlx.org: deterministic tools for AI agents in credit and finance. Questions: research@eqlx.ai.

Metadata

Release files for eqlx-ifrs9 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for eqlx-ifrs9 0.1.0
File Size Uploaded Provenance Actions
eqlx_ifrs9-0.1.0.tar.gz 76.7 kB With provenance Details for eqlx_ifrs9-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for eqlx-ifrs9 0.1.0
File Interpreter ABI Platform Actions
eqlx_ifrs9-0.1.0-py3-none-any.whl Python 3 none any Details for eqlx_ifrs9-0.1.0-py3-none-any.whl

Total release size: 159.7 kB

Release files / eqlx_ifrs9-0.1.0.tar.gz

Download URL eqlx_ifrs9-0.1.0.tar.gz
Size 76.7 kB
Tags Source
SHA-256 checksum
How to use checksums
bca7260fde3561a3225b93e97227b6ef8f9d952769b9aa489cbfa017f481c24a
BLAKE2b-256 checksum
How to use checksums
49591fc38f5bcf0f238afd1d06e7ef370558dceb1538c282784881020d865013
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 10, 2026.

Transparency log

Release files / eqlx_ifrs9-0.1.0-py3-none-any.whl

Download URL eqlx_ifrs9-0.1.0-py3-none-any.whl
Size 83.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4b0a8c574a380ac09f6e765ef69eb12fca6db5cacab5b3f73c442d3981ddd1c1
BLAKE2b-256 checksum
How to use checksums
05a40c0aaa71d9437539bd4e8419bc2948a41eca729854d5eb771bdea9855958
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 10, 2026.

Transparency log

Security for eqlx-ifrs9 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for eqlx_ifrs9-0.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 10, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page