This project develops an end-to-end Python research pipeline to measure Interest Rate Risk in the Banking Book (IRRBB) for a Non-Maturity Deposit cohort under Basel-style assumptions.
Using data up to 31-Dec-2023, the framework estimates behavioural maturity (deposit decay), applies regulatory slotting constraints (including the 5-year cap), and quantifies risk through scenario-based ΔEVE and ΔNII (1-year horizon) measures.
The implementation follows a transparent research process:
-
Data ingestion and quality checks
- Load historical NMD balance, inflow, and outflow data.
- Parse and normalize curve tenors/rates.
- Diagnose accounting identity consistency: (Balance_t \approx Balance_{t-1} + Inflow_t - Outflow_t).
-
Behavioural modelling for NMD
- Build a retention/decay profile from cohort-level balance flow behaviour.
- Fit a mixture-exponential survival representation.
- Convert survival to monthly runoff weights and enforce Basel 5-year cap.
-
Basel slotting and repricing profile construction
- Use calculation-date balance as the notional base.
- Allocate behavioural balances into monthly repricing buckets.
- Validate that slotted totals reconcile to the starting balance.
-
Curve and shock scenario design
- Build a base zero-curve object with tenor interpolation.
- Apply four supervisory-style rate shocks:
parallel_upparallel_downshort_up_taperflattener
-
Risk computation and reporting
- Revalue slotting cashflows for EVE under base and shocked curves.
- Estimate NII sensitivity (1Y window) using repricing buckets.
- Export scenario results and identify worst-case ΔEVE and ΔNII.
Place data files in data/:
group-proj-1-data.xlsx(required)- Columns:
Date,Balance,Inflow,Outflow(Netflowoptional)
- Columns:
group-proj-1-curve.xlsx(required)- Columns:
Tenor,ZeroRate
- Columns:
group-proj-1-demo.xlsx(optional reference)
If Excel inputs are unavailable, the project falls back to committed samples:
data/sample_data.csvdata/sample_curve.csv
Running the pipeline writes artifacts to outputs/:
decay_profile.csvslotting_table.csvscenario_results.csvworst_case.jsonplot_decay.pngplot_slotting.pngplot_scenarios.png
.
├─ data/
│ ├─ group-proj-1-data.xlsx (manually provided, not committed)
│ ├─ group-proj-1-curve.xlsx (manually provided, not committed)
│ ├─ group-proj-1-demo.xlsx (optional reference, not committed)
│ ├─ sample_data.csv (development/testing fallback)
│ └─ sample_curve.csv (development/testing fallback)
├─ notebooks/
│ ├─ 01_eda_decay.ipynb (exploration and diagnostics)
│ └─ 02_results_plots.ipynb (figures and tables)
├─ src/
│ ├─ io/
│ │ ├─ loaders.py # load Excel/CSV and normalize tenor units
│ │ └─ validators.py # balance identity diagnostics
│ ├─ nmd/
│ │ ├─ preprocess.py # feature engineering for NMD behaviour
│ │ ├─ decay_model.py # mixture-exponential survival modelling
│ │ ├─ basel_slotting.py # core split, 5Y cap, bucket allocation
│ │ └─ repricing_profile.py # repricing table outputs
│ ├─ curve/
│ │ ├─ curve.py # zero-curve object and interpolation
│ │ └─ shocks.py # scenario shock generators
│ ├─ irrbb/
│ │ ├─ eve.py # PV and ΔEVE calculations
│ │ ├─ nii.py # 1Y-window ΔNII calculations
│ │ └─ report.py # worst-case aggregation and exports
│ └─ config.py # model and scenario configuration
├─ run.py # one-command pipeline execution
└─ README.md
Use Python 3.10+.
Install dependencies:
pip install -r requirements.txtRun the project:
python -m src.run- Tenors support
D/W/M/Ysuffixes and are normalized to year units. - Zero rates are normalized if expressed in percentage format.
- Curve interpolation is linear in
(tenor_years, zero_rate)space. - Discounting uses continuous compounding for EVE calculations.
- NII is computed over a one-year horizon using bucket repricing approximation.