Minimal QuantLib IRS curve bootstrapping for EM and frontier rates (PLN, HUF, CZK, ZAR).
Project description
quantlib-irs-toolkit
Minimal, opinionated QuantLib helpers to bootstrap interest-rate swap curves from market par rates, with sensible conventions for the EM and frontier currencies most often missing from generic tutorials.
Currently supported out of the box:
- PLN (WIBOR 3M)
- HUF (BUBOR 3M)
- CZK (PRIBOR 3M)
- ZAR (JIBAR 3M, quarterly fixed)
Adding a new currency is a single dict entry; see Adding a currency.
Install
QuantLib's Python bindings are the only dependency.
pip install quantlib-irs-toolkit
For local development:
git clone https://github.com/fawraw/quantlib-irs-toolkit.git
cd quantlib-irs-toolkit
pip install -e ".[test]"
pytest
QuantLib wheels are available on PyPI for the major platforms. On macOS Apple Silicon you may need to install QuantLib via brew install quantlib first.
Quick start
from quantlib_irs_toolkit import build_irs_curve
result = build_irs_curve(
ccy="PLN",
rates={
"1Y": 4.235,
"2Y": 4.150,
"3Y": 4.100,
"5Y": 4.050,
"7Y": 4.100,
"10Y": 4.200,
"15Y": 4.350,
},
)
print(result["zero_rates"])
# {'ON': 4.187..., '1W': 4.187..., '1M': 4.190..., ..., '15Y': 4.391...}
print(result["forward_rates"])
# {'1y1y': 4.067..., '5y5y': 4.231..., ...}
rates are quoted in percent: 4.235 means 4.235 %, not 0.04235.
What you get back
{
"currency": "PLN",
"curve_date": "2026-05-13",
"settlement_date": "20260515",
"conventions": {
"day_count": "ACT/365",
"fixed_frequency": "Annual",
"index": "WIBOR3M",
"settlement_days": 2,
"calendar": "Poland",
},
"input_tenors": ["1Y", "2Y", "3Y", "5Y", "7Y", "10Y", "15Y"],
"input_rates": { ... },
"discount_factors": { "ON": 0.9999..., "1M": 0.9965..., ..., "15Y": 0.5235... },
"zero_rates": { "ON": 4.187, "1M": 4.190, ..., "15Y": 4.391 },
"forward_rates": { "1y1y": 4.067, "2y1y": 4.055, ..., "5y5y": 4.231 },
"error": None,
}
If something goes wrong (bad currency, missing rates, unbootstrappable inputs), error is a human-readable message and the other fields may be absent.
Conventions per currency
| Currency | Day count | Fixed freq | Floating index | Settle | Calendar |
|---|---|---|---|---|---|
| PLN | ACT/365 | Annual | WIBOR 3M | T+2 | Poland |
| HUF | ACT/360 | Annual | BUBOR 3M | T+2 | Hungary |
| CZK | ACT/360 | Annual | PRIBOR 3M | T+2 | CzechRepublic |
| ZAR | ACT/365 | Quarterly | JIBAR 3M | T+0 | SouthAfrica |
The conventions table (CCY_CONVENTIONS in curves.py) is the source of truth. If you disagree with a value (eg. your desk uses a different settlement period for ZAR), patch it at runtime:
from quantlib_irs_toolkit import CCY_CONVENTIONS
CCY_CONVENTIONS["ZAR"]["settlement_days"] = 2 # T+2 instead of T+0
Adding a currency
from quantlib_irs_toolkit import CCY_CONVENTIONS, build_irs_curve
CCY_CONVENTIONS["TRY"] = {
"day_count": "ACT/360",
"fixed_frequency": "Quarterly",
"index_name": "TRLIBOR3M",
"index_tenor": 3,
"settlement_days": 2,
"calendar": "TARGET", # use TARGET or WeekendsOnly if QL has no native calendar
}
result = build_irs_curve("TRY", { "1Y": 45.0, "2Y": 40.0, "5Y": 32.0 })
Supported calendar names (from _ql_calendar): Poland, Hungary, CzechRepublic, SouthAfrica, TARGET, WeekendsOnly. Extend the mapping in curves.py if you need more.
Output tenors
By default, the toolkit returns:
- Discount factors and zero rates at:
ON, 1W, 1M, 3M, 6M, 1Y, 2Y, 3Y, 4Y, 5Y, 6Y, 7Y, 8Y, 9Y, 10Y, 12Y, 15Y - Forward rates at:
1y1y, 2y1y, 3y1y, 5y1y, 1y4y, 5y5y, 2y3y, 3y2y
Both sets are exposed as tuples (OUTPUT_TENORS, FORWARD_PAIRS) and can be overridden by copying and editing curves.py.
Method
The bootstrapping uses QuantLib's PiecewiseFlatForward with SwapRateHelper instances for each input tenor. Extrapolation is enabled by default so queries slightly past the longest swap don't raise; pass extrapolate=False to build_irs_curve if you'd rather fail loudly.
The IBOR index is built generically (ql.IborIndex) rather than relying on QuantLib's built-in Euribor-style classes, because the EM indices (WIBOR, BUBOR, PRIBOR, JIBAR) are not all natively shipped in QuantLib.
Not in scope
- Multi-curve pricing (separate discount and projection curves)
- OIS-discounted swap pricing
- Cross-currency basis
- Sensitivity / bucketed risk
These are deliberately out of scope for v0. If you need them, this code is a reasonable starting point but you'll want to extend the helpers and the curve construction.
License
MIT. See LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file quantlib_irs_toolkit-0.1.0.tar.gz.
File metadata
- Download URL: quantlib_irs_toolkit-0.1.0.tar.gz
- Upload date:
- Size: 9.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
34bd45d82695bf4a2984b76e55b6626a85019685f0e96b240cecabce6db26e69
|
|
| MD5 |
b6f178a41dec3ef5ab57633812a962e8
|
|
| BLAKE2b-256 |
0acf9fcd8f2bcdf4743cd78224bab31a63067682602040dc8a5bc073e77027e1
|
Provenance
The following attestation bundles were made for quantlib_irs_toolkit-0.1.0.tar.gz:
Publisher:
publish.yml on fawraw/quantlib-irs-toolkit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
quantlib_irs_toolkit-0.1.0.tar.gz -
Subject digest:
34bd45d82695bf4a2984b76e55b6626a85019685f0e96b240cecabce6db26e69 - Sigstore transparency entry: 1524494842
- Sigstore integration time:
-
Permalink:
fawraw/quantlib-irs-toolkit@88f0852cbf61a06434a6f61582850801a55ae3b7 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/fawraw
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@88f0852cbf61a06434a6f61582850801a55ae3b7 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file quantlib_irs_toolkit-0.1.0-py3-none-any.whl.
File metadata
- Download URL: quantlib_irs_toolkit-0.1.0-py3-none-any.whl
- Upload date:
- Size: 9.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a8d6656951fd9991b5b8f0c34ec06d069d4e6ef8cf5099d5e77c2d6382078017
|
|
| MD5 |
cf68e93eccf17f26fd4204e4d235a7ad
|
|
| BLAKE2b-256 |
1ec2100375167dbd0f8e6cfbe9a735cd2c6ed8e6ce736d8b0bdc19d70498d307
|
Provenance
The following attestation bundles were made for quantlib_irs_toolkit-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on fawraw/quantlib-irs-toolkit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
quantlib_irs_toolkit-0.1.0-py3-none-any.whl -
Subject digest:
a8d6656951fd9991b5b8f0c34ec06d069d4e6ef8cf5099d5e77c2d6382078017 - Sigstore transparency entry: 1524494893
- Sigstore integration time:
-
Permalink:
fawraw/quantlib-irs-toolkit@88f0852cbf61a06434a6f61582850801a55ae3b7 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/fawraw
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@88f0852cbf61a06434a6f61582850801a55ae3b7 -
Trigger Event:
workflow_dispatch
-
Statement type: