Skip to content

Commit ed166f0

Browse files
authored
UPG: pyo3 and py14 (#189) (#1110)
1 parent f8fae20 commit ed166f0

File tree

14 files changed

+90
-73
lines changed

14 files changed

+90
-73
lines changed

.github/workflows/ubuntu-latest.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
strategy:
1717
fail-fast: false
1818
matrix:
19-
python-version: ["3.13"]
19+
python-version: ["3.14"]
2020

2121
steps:
2222
- uses: actions/checkout@v4

.github/workflows/windows-latest.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
strategy:
1717
fail-fast: false
1818
matrix:
19-
python-version: ["3.13"]
19+
python-version: ["3.14"]
2020
env:
2121
MPLBACKEND: Agg # https://github.com/orgs/community/discussions/26434
2222

Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "rateslib"
3-
version = "2.1.0"
3+
version = "2.5.0"
44
edition = "2021"
55
exclude = [
66
".github/*",
@@ -34,10 +34,10 @@ chrono = { version = "0.4", features = ["serde"] }
3434
indexmap = { version = "2.7", features = ["serde"] }
3535
ndarray = { version = "0.16", features = ["serde"] }
3636
internment = { version = "0.8", features = ["serde"] }
37-
pyo3 = "0.25"
37+
pyo3 = "0.27"
3838
num-traits = "0.2"
3939
auto_ops = "0.3"
40-
numpy = "0.25"
40+
numpy = "0.27"
4141
itertools = "0.14"
4242
statrs = "0.18"
4343
bincode = { version = "2.0", features = ["serde"] }

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ features = ["pyo3/extension-module"]
1515

1616
[project]
1717
name = "rateslib"
18-
version = "2.1.0"
18+
version = "2.5.0"
1919
description = "A fixed income library for trading interest rates"
2020
readme = "README.md"
2121
authors = [{ name = "J H M Darbyshire"}]
@@ -36,7 +36,7 @@ classifiers = [
3636
[project.optional-dependencies]
3737
dev = [
3838
# testing
39-
"pytest>=8.3.2,<9.0",
39+
"pytest>=8.3.2,<10.0",
4040
"coverage>=7.6.1,<8.0",
4141
# style/linting
4242
"ruff>=0.6.3,<1.0",

python/rateslib/data/fixings.py

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1505,20 +1505,22 @@ def _rate_tenor_maybe_from_fixings(
15051505
if isinstance(rate_fixings, str | Series):
15061506
if isinstance(rate_fixings, str):
15071507
identifier = rate_fixings
1508-
fixings_ = fixings[identifier][1]
1508+
_, fixings_, bounds = fixings[identifier]
15091509
else:
15101510
identifier = "<SERIES_OBJECT>"
15111511
fixings_ = rate_fixings
1512+
bounds = (rate_fixings.index.min(), rate_fixings.index.max())
15121513

1513-
try:
1514-
fixing = fixings_.loc[fixing_date]
1515-
return Ok(fixing + float_spread / 100.0)
1516-
except KeyError:
1517-
warnings.warn(
1518-
f"Fixings are provided in series: '{identifier}', but the value for required"
1519-
f" date: {fixing_date} is not found.\nAttempting to forecast from "
1520-
f"the `rate_curve`.",
1521-
)
1514+
if fixing_date <= bounds[1]:
1515+
try:
1516+
fixing = fixings_.loc[fixing_date]
1517+
return Ok(fixing + float_spread / 100.0)
1518+
except KeyError:
1519+
warnings.warn(
1520+
f"Fixings are provided in series: '{identifier}', but the value for "
1521+
f" date: {fixing_date} is not found.\nAttempting to forecast from "
1522+
f"the `rate_curve`.",
1523+
)
15221524
return _IBORRate._rate_tenor_forecast_from_curve(
15231525
rate_curve=rate_curve,
15241526
fixing_date=fixing_date,

python/tests/instruments/test_instruments_bonds_legacy.py

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2695,18 +2695,23 @@ def test_se_gbb_eom(self):
26952695

26962696
def test_act_act_icma(self):
26972697
# gh 144
2698-
bill_actacticma = Bill(
2699-
effective=dt(2024, 2, 29),
2700-
termination=dt(2024, 5, 29), # 90 calendar days
2701-
modifier="NONE",
2702-
calendar="bus",
2703-
payment_lag=0,
2704-
notional=-1000000,
2705-
currency="usd",
2706-
convention="ACTACTICMA",
2707-
settle=0,
2708-
calc_mode="us_gbb",
2709-
)
2698+
with pytest.warns(
2699+
UserWarning,
2700+
match="`frequency` cannot be 'Zero' variant in combination with 'ActActICMA",
2701+
):
2702+
bill_actacticma = Bill(
2703+
effective=dt(2024, 2, 29),
2704+
termination=dt(2024, 5, 29), # 90 calendar days
2705+
modifier="NONE",
2706+
calendar="bus",
2707+
payment_lag=0,
2708+
notional=-1000000,
2709+
currency="usd",
2710+
convention="ACTACTICMA",
2711+
settle=0,
2712+
calc_mode="us_gbb",
2713+
)
2714+
assert bill_actacticma.leg1._regular_periods[0].period_params.dcf == 0.2465753424657534
27102715

27112716
bill_act360 = Bill(
27122717
effective=dt(2024, 2, 29),
@@ -2720,8 +2725,6 @@ def test_act_act_icma(self):
27202725
settle=0,
27212726
calc_mode="us_gbb",
27222727
)
2723-
2724-
assert bill_actacticma.leg1._regular_periods[0].period_params.dcf == 0.2465753424657534
27252728
assert bill_act360.leg1._regular_periods[0].period_params.dcf == 0.25
27262729

27272730

python/tests/instruments/test_instruments_legacy.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2663,11 +2663,11 @@ def test_nonmtmxcs_cashflows(self, curve, curve2) -> None:
26632663
expected = DataFrame(
26642664
{
26652665
"Type": ["Cashflow", "FloatPeriod"],
2666-
"Period": [None, "Regular"],
2666+
"Period": [np.nan, "Regular"],
26672667
"Ccy": ["NOK", "USD"],
26682668
"Notional": [-10000000, -10000000.0],
26692669
"FX Rate": [0.10002256337062124, 1.0],
2670-
"FX Fixing": [None, 0.09967340252423884],
2670+
"FX Fixing": [np.nan, 0.09967340252423884],
26712671
},
26722672
index=MultiIndex.from_tuples([("leg1", 0), ("leg2", 8)]),
26732673
)
@@ -2950,11 +2950,11 @@ def test_nonmtmfixxcs_cashflows(self, curve, curve2) -> None:
29502950
expected = DataFrame(
29512951
{
29522952
"Type": ["Cashflow", "FloatPeriod"],
2953-
"Period": [None, "Regular"],
2953+
"Period": [np.nan, "Regular"],
29542954
"Ccy": ["NOK", "USD"],
29552955
"Notional": [-10000000, -10000000.0],
29562956
"FX Rate": [0.10002256337062124, 1.0],
2957-
"FX Fixing": [None, 0.09967340252423884],
2957+
"FX Fixing": [np.nan, 0.09967340252423884],
29582958
},
29592959
index=MultiIndex.from_tuples([("leg1", 0), ("leg2", 8)]),
29602960
)
@@ -3731,12 +3731,12 @@ def test_mtmxcs_cashflows(self, curve, curve2) -> None:
37313731
expected = DataFrame(
37323732
{
37333733
"Type": ["Cashflow", "FloatPeriod", "MtmCashflow"],
3734-
"Period": [None, "Regular", None],
3734+
"Period": [np.nan, "Regular", np.nan],
37353735
"Ccy": ["NOK", "USD", "USD"],
37363736
"Notional": [-10000000, -10000000.0, 10000000.0],
3737-
"Rate": [None, 8.181151773810475, None],
3737+
"Rate": [np.nan, 8.181151773810475, np.nan],
37383738
"FX Rate": [0.10002256337062124, 1.0, 1.0],
3739-
"FX Fixing": [None, 0.0990019249688802, 0.09829871161519926],
3739+
"FX Fixing": [np.nan, 0.0990019249688802, 0.09829871161519926],
37403740
},
37413741
index=MultiIndex.from_tuples([("leg1", 0), ("leg2", 11), ("leg2", 14)]),
37423742
)

python/tests/periods/test_fixings_load.py

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -417,14 +417,15 @@ def test_ibor12M_fixing_identifier(self):
417417
assert p.rate_params.rate_fixing.identifier == "TEST_12M"
418418

419419
def test_ibor_stub_fixing_identifier(self):
420-
p = FloatPeriod(
421-
start=dt(2000, 1, 1),
422-
end=dt(2000, 3, 1),
423-
frequency=Frequency.Months(3, None),
424-
payment=dt(2000, 1, 4),
425-
fixing_method=FloatFixingMethod.IBOR,
426-
stub=True,
427-
rate_fixings="TEST",
428-
)
429-
assert p.rate_params.fixing_identifier == "TEST"
430-
assert p.rate_params.rate_fixing.identifier == "TEST"
420+
with pytest.warns(UserWarning, match=err.UW_NO_TENORS[:15]):
421+
p = FloatPeriod(
422+
start=dt(2000, 1, 1),
423+
end=dt(2000, 3, 1),
424+
frequency=Frequency.Months(3, None),
425+
payment=dt(2000, 1, 4),
426+
fixing_method=FloatFixingMethod.IBOR,
427+
stub=True,
428+
rate_fixings="TEST",
429+
)
430+
assert p.rate_params.fixing_identifier == "TEST"
431+
assert p.rate_params.rate_fixing.identifier == "TEST"

python/tests/periods/test_float_rate.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import os
12
from datetime import datetime as dt
23

34
import pytest
@@ -190,19 +191,18 @@ def test_tenor_rate_from_fixing_str(self, curve, line_curve, curve2, line_curve2
190191

191192
def test_tenor_rate_from_fixing_str_fallback(self, curve, line_curve, curve2, line_curve2):
192193
# test an IBOR rate is calculated correctly from a curve when no fixing date exists
193-
fixings.add("TEST_VALUES_3M", Series(index=[dt(1900, 1, 1)], data=[1.2]))
194+
name = str(hash(os.urandom(8)))
195+
fixings.add(f"{name}_3M", Series(index=[dt(2001, 1, 1)], data=[1.2]))
194196
for rate_curve in [
195197
curve,
196198
line_curve,
197199
{"3m": curve, "6m": curve2},
198200
{"3m": line_curve, "6m": line_curve2},
199201
]:
200-
with pytest.warns(
201-
UserWarning, match="Fixings are provided in series: 'TEST_VALUES_3M',"
202-
):
202+
with pytest.warns(UserWarning, match=f"Fixings are provided in series: '{name}_3M',"):
203203
result = rate_value(
204204
rate_curve=rate_curve,
205-
rate_fixings="TEST_VALUES_3M",
205+
rate_fixings=f"{name}_3M",
206206
start=dt(2000, 1, 3),
207207
end=dt(2000, 4, 3),
208208
stub=False,
@@ -212,7 +212,7 @@ def test_tenor_rate_from_fixing_str_fallback(self, curve, line_curve, curve2, li
212212
float_spread=18.0,
213213
)
214214
assert abs(result - 2.18) < 1e-12
215-
fixings.pop("TEST_VALUES_3M")
215+
fixings.pop(f"{name}_3M")
216216

217217
def test_stub_rate_from_fixing_dict(self, curve, line_curve, curve2, line_curve2):
218218
# test an IBOR rate is calculated correctly from a fixing series

python/tests/periods/test_periods_legacy.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1536,7 +1536,8 @@ def test_ibor_fixing_unavailable(self) -> None:
15361536
curve = Curve({dt(2022, 1, 1): 1.0, dt(2025, 1, 1): 0.90}, calendar="bus")
15371537
lcurve = LineCurve({dt(2022, 1, 1): 2.0, dt(2025, 1, 1): 4.0}, calendar="bus")
15381538
fixings_ = Series([2.801], index=[dt(2023, 3, 1)])
1539-
fixings.add("TEST_VALUES_3M", fixings_)
1539+
name = str(hash(os.urandom(8)))
1540+
fixings.add(f"{name}_3M", fixings_)
15401541
float_period = FloatPeriod(
15411542
start=dt(2023, 3, 20),
15421543
end=dt(2023, 6, 20),
@@ -1545,13 +1546,13 @@ def test_ibor_fixing_unavailable(self) -> None:
15451546
fixing_method="ibor",
15461547
method_param=2,
15471548
calendar="bus",
1548-
rate_fixings="TEST_VALUES",
1549+
rate_fixings=name,
15491550
)
15501551
result = float_period.rate(curve) # fixing occurs 18th Mar, not in `fixings`
15511552
assert abs(result - 3.476095729528156) < 1e-5
15521553
result = float_period.rate(lcurve) # fixing occurs 18th Mar, not in `fixings`
15531554
assert abs(result - 2.801094890510949) < 1e-5
1554-
fixings.pop("TEST_VALUES_3M")
1555+
fixings.pop(f"{name}_3M")
15551556

15561557
def test_ibor_fixings_exposure_with_fixing(self) -> None:
15571558
curve = Curve({dt(2022, 1, 1): 1.0, dt(2025, 1, 1): 0.90}, calendar="bus")

0 commit comments

Comments
 (0)