Python bindings for libitofin: a Rust port of QuantLib for pricing, risk, and calibration.
Project description
itofin
Idiomatic Python bindings over the libitofin Rust core, a ground-up port of QuantLib for pricing, risk, and calibration. The heavy numerics run in Rust; Python drives them. The pricing snippets below reproduce the cached Rust test oracles exactly; the abbreviated calibration snippets converge to the same targets within the tests' calibration tolerance (the full matrices live in tests/).
The API mirrors QuantLib's ql/ layout: types live in submodules (itofin.time, itofin.instruments, itofin.models, ...), while Settings and ItofinError stay at the top level.
Install
pip install itofin
Requires Python >= 3.13.
Price a European option and its greeks
from itofin import Settings
from itofin.instruments import OptionType, VanillaOption
from itofin.processes import BlackScholesProcess
from itofin.time import Date, DayCounter
s = Settings()
s.set_evaluation_date(Date(15, 6, 2026))
dc = DayCounter.actual360()
process = BlackScholesProcess(60.0, 0.08, 0.0, 0.30, Date(15, 6, 2026), dc)
option = VanillaOption(OptionType.Call, 65.0, Date(15, 6, 2026) + 90, s)
option.set_engine(process)
print(f"NPV {option.npv():.10f}")
print(f"delta {option.delta():.10f}")
print(f"vega {option.vega():.10f}")
print(f"rho {option.rho():.10f}")
NPV 2.1333684449
delta 0.3724827980
vega 11.3515440535
rho 5.0538998582
Price under Heston and calibrate to a flat-vol surface
Semi-analytic Heston pricing:
from itofin import Settings
from itofin.instruments import OptionType, VanillaOption
from itofin.models import HestonModel
from itofin.processes import HestonProcess
from itofin.time import Date, DayCounter
s = Settings()
s.set_evaluation_date(Date(27, 12, 2004))
dc = DayCounter.actual_actual_isda()
# HestonProcess(risk_free, dividend, spot, v0, kappa, theta, sigma, rho, reference_date, day_counter)
process = HestonProcess(
0.0225, 0.02, 1.0, 0.1, 3.16, 0.09, 0.4, -0.2, Date(27, 12, 2004), dc
)
model = HestonModel(process)
option = VanillaOption(OptionType.Call, 1.05, Date(28, 3, 2005), s)
option.set_heston_engine(model, 64)
print(f"Heston NPV {option.npv():.10f}")
Heston NPV 0.0404774515
Calibrating the model to a flat 10% vol surface drives the vol-of-vol sigma toward zero and both v0 and theta toward the flat variance (0.10 squared = 0.01). The snippet below fits a 3-maturity by 3-strike grid; the full 21-helper matrix and its tighter tolerances live in tests/test_heston_calibration.py.
import math
from itofin import Settings
from itofin.models import CalibrationErrorType, HestonModel, HestonModelHelper
from itofin.optimization import EndCriteria, LevenbergMarquardt
from itofin.processes import HestonProcess
from itofin.termstructures import FlatForward
from itofin.time import Calendar, Date, DayCounter, Period
s = Settings()
s.set_evaluation_date(Date(15, 1, 2026))
dc = DayCounter.actual360()
ref = Date(15, 1, 2026)
risk_free = FlatForward(ref, 0.04, dc)
dividend = FlatForward(ref, 0.50, dc)
VOL = 0.10
helpers = []
for n in (1, 2, 3):
tau = float(n)
forward = dividend.discount(tau) / risk_free.discount(tau) # spot = 1.0
for moneyness in (-1.0, 0.0, 1.0):
strike = forward * math.exp(-moneyness * VOL * math.sqrt(tau))
helpers.append(HestonModelHelper(
Period(n, "Years"),
Calendar.null_calendar(),
1.0, # spot
strike,
VOL, # 10% flat vol
0.04, # risk-free
0.50, # dividend yield
CalibrationErrorType.RelativePriceError,
ref,
dc,
s,
))
process = HestonProcess(0.04, 0.50, 1.0, 0.01, 0.2, 0.02, 0.5, -0.75, ref, dc)
model = HestonModel(process)
method = LevenbergMarquardt(1e-8, 1e-8, 1e-8, False)
end_criteria = EndCriteria(400, 40, 1e-8, 1e-8, 1e-8)
model.calibrate(helpers, method, end_criteria, 96)
print(f"sigma {model.sigma():.6f}")
print(f"v0 {model.v0():.6f}")
print(f"theta {model.theta():.6f}")
sigma 0.000216
v0 0.010000
theta 0.010000
Calibrate Hull-White to a swaption matrix
from itofin import Settings
from itofin.indexes import Euribor
from itofin.models import CalibrationErrorType, HullWhite, SwaptionHelper
from itofin.optimization import EndCriteria, LevenbergMarquardt
from itofin.termstructures import FlatForward
from itofin.time import Date, DayCounter, Period
s = Settings()
s.set_evaluation_date(Date(15, 2, 2002))
curve = FlatForward(Date(19, 2, 2002), 0.04875825, DayCounter.actual365_fixed())
model = HullWhite(curve, 0.1, 0.01)
index = Euribor.six_months(curve, s)
# (option tenor, swap tenor, Black vol); the full co-terminal matrix is in the tests.
swaptions = [(1, 5, 0.1148), (2, 4, 0.1108), (3, 3, 0.1070), (4, 2, 0.1021), (5, 1, 0.1000)]
helpers = [
SwaptionHelper(
Period(maturity, "Years"),
Period(length, "Years"),
vol,
index,
Period(1, "Years"),
DayCounter.thirty360_bond_basis(),
DayCounter.actual360(),
curve,
CalibrationErrorType.RelativePriceError,
1.0,
)
for maturity, length, vol in swaptions
]
method = LevenbergMarquardt(1e-8, 1e-8, 1e-8, False)
end_criteria = EndCriteria(10000, 100, 1e-6, 1e-8, 1e-8)
model.calibrate(helpers, method, end_criteria, False) # fix_reversion=False, fit a and sigma
print(f"a {model.a():.7f}")
print(f"sigma {model.sigma():.7f}")
a 0.0464113
sigma 0.0057992
Price a European swaption with the Jamshidian engine
from itofin import Settings
from itofin.indexes import Euribor
from itofin.instruments import (
EuropeanExercise,
SettlementMethod,
SettlementType,
Swaption,
SwapType,
VanillaSwap,
)
from itofin.models import HullWhite
from itofin.termstructures import FlatForward
from itofin.time import BusinessDayConvention, Calendar, Date, DayCounter, Frequency, Schedule
s = Settings()
s.set_evaluation_date(Date(15, 1, 2026))
curve = FlatForward(Date(15, 1, 2026), 0.03, DayCounter.actual365_fixed())
fixed = Schedule(
Date(15, 1, 2028), Date(15, 1, 2033),
Frequency.Annual, Calendar.target(),
BusinessDayConvention.Unadjusted,
)
floating = Schedule(
Date(15, 1, 2028), Date(15, 1, 2033),
Frequency.Semiannual, Calendar.target(),
BusinessDayConvention.Unadjusted,
)
index = Euribor.six_months(curve, s)
swap = VanillaSwap(
SwapType.Payer, 100.0,
fixed, 0.03, DayCounter.thirty360_bond_basis(),
floating, index, 0.0, DayCounter.actual360(), s,
)
swaption = Swaption(
swap, EuropeanExercise(Date(15, 1, 2027)),
SettlementType.Physical, SettlementMethod.PhysicalOTC, s,
)
swaption.set_jamshidian_engine(HullWhite(curve, 0.05, 0.01))
print(f"payer swaption NPV {swaption.npv():.10f}")
payer swaption NPV 1.5666103956
License
BSD-3-Clause, matching the libitofin core. See the repository for the layer status table, the divergences-from-QuantLib catalogue, and the Rust test oracles behind the numbers above.
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 Distributions
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 itofin-0.7.0.tar.gz.
File metadata
- Download URL: itofin-0.7.0.tar.gz
- Upload date:
- Size: 2.1 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1f175085bdb36839c1270277c9c8a3d230bb7bb6f528520b8ad8d446bba0751f
|
|
| MD5 |
b25eb1920c913c66db091373b3d5aa01
|
|
| BLAKE2b-256 |
ab73e81e6aaeeea3570119edd3dcea4626bd13ecacd6954cb42c7f1a018066b1
|
Provenance
The following attestation bundles were made for itofin-0.7.0.tar.gz:
Publisher:
semantic-release.yml on benbenbang/libitofin
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
itofin-0.7.0.tar.gz -
Subject digest:
1f175085bdb36839c1270277c9c8a3d230bb7bb6f528520b8ad8d446bba0751f - Sigstore transparency entry: 2230327541
- Sigstore integration time:
-
Permalink:
benbenbang/libitofin@f608793d62f3dc30c27e2017969cbf1fb0874201 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/benbenbang
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
semantic-release.yml@f608793d62f3dc30c27e2017969cbf1fb0874201 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file itofin-0.7.0-cp313-abi3-win_amd64.whl.
File metadata
- Download URL: itofin-0.7.0-cp313-abi3-win_amd64.whl
- Upload date:
- Size: 595.7 kB
- Tags: CPython 3.13+, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
adaa9841bd4b2476b4f740fa33f3de473d2eb3c4f7af1d9e4e055a59ad334b9b
|
|
| MD5 |
d2d3cc53e937c713ca58c8cf658d4671
|
|
| BLAKE2b-256 |
58590d8e7e3e77ba6961b5315cde00de155e146f0e8a8f3cc9e4ee114fa83389
|
Provenance
The following attestation bundles were made for itofin-0.7.0-cp313-abi3-win_amd64.whl:
Publisher:
semantic-release.yml on benbenbang/libitofin
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
itofin-0.7.0-cp313-abi3-win_amd64.whl -
Subject digest:
adaa9841bd4b2476b4f740fa33f3de473d2eb3c4f7af1d9e4e055a59ad334b9b - Sigstore transparency entry: 2230329460
- Sigstore integration time:
-
Permalink:
benbenbang/libitofin@f608793d62f3dc30c27e2017969cbf1fb0874201 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/benbenbang
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
semantic-release.yml@f608793d62f3dc30c27e2017969cbf1fb0874201 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file itofin-0.7.0-cp313-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: itofin-0.7.0-cp313-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 812.1 kB
- Tags: CPython 3.13+, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c04a3f5df23adcbbe5c1596a145d0e522ae177d706ec7719160b5206716601fd
|
|
| MD5 |
88373ad5ca1a194d5a68a474d82a8155
|
|
| BLAKE2b-256 |
b772f9c191fce7fa944e655d5a7874b2611e2c6211eb9d0079d6e6e6b6661338
|
Provenance
The following attestation bundles were made for itofin-0.7.0-cp313-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
semantic-release.yml on benbenbang/libitofin
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
itofin-0.7.0-cp313-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
c04a3f5df23adcbbe5c1596a145d0e522ae177d706ec7719160b5206716601fd - Sigstore transparency entry: 2230328073
- Sigstore integration time:
-
Permalink:
benbenbang/libitofin@f608793d62f3dc30c27e2017969cbf1fb0874201 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/benbenbang
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
semantic-release.yml@f608793d62f3dc30c27e2017969cbf1fb0874201 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file itofin-0.7.0-cp313-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: itofin-0.7.0-cp313-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 721.5 kB
- Tags: CPython 3.13+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
175b7e313244797a929db27c37af26e05c2f4f3ff07cfd356e1e8bc8c42acaf0
|
|
| MD5 |
9f5378aab63608816250c943f986b1d6
|
|
| BLAKE2b-256 |
04d5fe9b7cd353b87e310b5a0511ec31d41850dc7ca5bd32983229cc459f73fc
|
Provenance
The following attestation bundles were made for itofin-0.7.0-cp313-abi3-macosx_11_0_arm64.whl:
Publisher:
semantic-release.yml on benbenbang/libitofin
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
itofin-0.7.0-cp313-abi3-macosx_11_0_arm64.whl -
Subject digest:
175b7e313244797a929db27c37af26e05c2f4f3ff07cfd356e1e8bc8c42acaf0 - Sigstore transparency entry: 2230328947
- Sigstore integration time:
-
Permalink:
benbenbang/libitofin@f608793d62f3dc30c27e2017969cbf1fb0874201 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/benbenbang
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
semantic-release.yml@f608793d62f3dc30c27e2017969cbf1fb0874201 -
Trigger Event:
workflow_dispatch
-
Statement type: