Skip to content

Commit

Permalink
DEP: remove IndexCurve (#691)
Browse files Browse the repository at this point in the history
Co-authored-by: JHM Darbyshire (M1) <[email protected]>
  • Loading branch information
attack68 and attack68 authored Feb 26, 2025
1 parent d9f2f7a commit 640689b
Show file tree
Hide file tree
Showing 11 changed files with 144 additions and 95 deletions.
3 changes: 3 additions & 0 deletions docs/source/i_whatsnew.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ email contact, see `rateslib <https://rateslib.com>`_.

* - Feature
- Description
* - **Removed**
- ``IndexCurve``, which was deprecated with warnings in 1.7.0, has been removed.
(`691 <https://github.com/attack68/rateslib/pull/691>`_)
* - Period
- Add :class:`~rateslib.periods.NonDeliverableFixedPeriod`
(`681 <https://github.com/attack68/rateslib/pull/681>`_)
Expand Down
2 changes: 0 additions & 2 deletions python/rateslib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ def __exit__(self, *args) -> None: # type: ignore[no-untyped-def]
from rateslib.curves import (
CompositeCurve,
Curve,
IndexCurve,
LineCurve,
MultiCsaCurve,
ProxyCurve,
Expand Down Expand Up @@ -183,7 +182,6 @@ def __exit__(self, *args) -> None: # type: ignore[no-untyped-def]
# curves.py
"Curve",
"LineCurve",
"IndexCurve",
"MultiCsaCurve",
"CompositeCurve",
"ProxyCurve",
Expand Down
2 changes: 1 addition & 1 deletion python/rateslib/calendars/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ def add_tenor(
from rateslib.calendars import add_tenor, get_calendar, create_calendar, dcf
from rateslib.scheduling import Schedule
from rateslib.curves import Curve, LineCurve, interpolate, index_left, IndexCurve
from rateslib.curves import Curve, LineCurve, interpolate, index_left
from rateslib.dual import Dual, Dual2
from rateslib.periods import FixedPeriod, FloatPeriod, Cashflow, IndexFixedPeriod, IndexCashflow, NonDeliverableCashflow, NonDeliverableFixedPeriod
from rateslib.legs import FixedLeg, FloatLeg, CustomLeg, FloatLegMtm, FixedLegMtm, IndexFixedLeg, ZeroFixedLeg, ZeroFloatLeg, ZeroIndexLeg
Expand Down
2 changes: 0 additions & 2 deletions python/rateslib/curves/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
from rateslib.curves.curves import (
CompositeCurve,
Curve,
IndexCurve,
LineCurve,
MultiCsaCurve,
ProxyCurve,
Expand All @@ -13,7 +12,6 @@
__all__ = (
"CompositeCurve",
"Curve",
"IndexCurve",
"LineCurve",
"MultiCsaCurve",
"ProxyCurve",
Expand Down
27 changes: 3 additions & 24 deletions python/rateslib/curves/curves.py
Original file line number Diff line number Diff line change
Expand Up @@ -623,7 +623,7 @@ def shift(
interpolation="linear",
)
else: # or type(self) is IndexCurve
shifted = IndexCurve(
shifted = Curve(
nodes={start: 1.0, end: 1.0 / (1 + d * spread / 10000) ** days},
convention=self.convention,
calendar=self.calendar,
Expand Down Expand Up @@ -2128,25 +2128,6 @@ def roll(self, tenor: datetime | str) -> Curve:
return super().roll(tenor)


class IndexCurve(Curve):
"""
Deprecated. Use :class:`~rateslib.curves.Curve` with a valid ``index_base``.
"""

def __init__( # type: ignore[no-untyped-def]
self,
*args,
**kwargs,
) -> None:
warnings.warn(
"`IndexCurve` is deprecated: use a `Curve` instead and the same arguments.",
DeprecationWarning,
)
super().__init__(*args, **{"interpolation": "linear_index", **kwargs})
if isinstance(self.index_base, NoInput):
raise ValueError("`index_base` must be given for IndexCurve.")


class CompositeCurve(Curve):
"""
A dynamic composition of a sequence of other curves.
Expand Down Expand Up @@ -2366,7 +2347,7 @@ def __init__(

def _validate_curve_collection(self) -> None:
"""Perform checks to ensure CompositeCurve can exist"""
if type(self) is MultiCsaCurve and isinstance(self.curves[0], LineCurve | IndexCurve):
if type(self) is MultiCsaCurve and isinstance(self.curves[0], LineCurve):
raise TypeError("Multi-CSA curves must be of type `Curve`.")

if type(self) is MultiCsaCurve and self.multi_csa_min_step > self.multi_csa_max_step:
Expand All @@ -2380,9 +2361,7 @@ def _validate_curve_collection(self) -> None:
)

if not (
all(_ is Curve or _ is ProxyCurve for _ in types)
or all(_ is LineCurve for _ in types)
or all(_ is IndexCurve for _ in types)
all(_ is Curve or _ is ProxyCurve for _ in types) or all(_ is LineCurve for _ in types)
):
raise TypeError(f"`curves` must be a list of similar type curves, got {types}.")

Expand Down
4 changes: 2 additions & 2 deletions python/rateslib/instruments/rates/inflation.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ class ZCIS(BaseDerivative):
},
id="usd",
)
us_cpi = IndexCurve(
us_cpi = Curve(
nodes={
dt(2022, 1, 1): 1.0,
dt(2027, 1, 1): 0.85,
Expand Down Expand Up @@ -303,7 +303,7 @@ class IIRS(BaseDerivative):
},
id="usd",
)
us_cpi = IndexCurve(
us_cpi = Curve(
nodes={
dt(2022, 1, 1): 1.0,
dt(2027, 1, 1): 0.85,
Expand Down
52 changes: 26 additions & 26 deletions python/tests/test_curves.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
from rateslib.curves import (
CompositeCurve,
Curve,
IndexCurve,
LineCurve,
MultiCsaCurve,
index_left,
Expand Down Expand Up @@ -51,7 +50,7 @@ def line_curve():

@pytest.fixture
def index_curve():
return IndexCurve(
return Curve(
nodes={
dt(2022, 3, 1): 1.00,
dt(2022, 3, 31): 0.999,
Expand Down Expand Up @@ -189,7 +188,7 @@ def test_serialization_round_trip(curve, line_curve, index_curve) -> None:
assert constructed == line_curve

serial = index_curve.to_json()
constructed = IndexCurve.from_json(serial)
constructed = Curve.from_json(serial)
assert constructed == index_curve


Expand Down Expand Up @@ -787,7 +786,7 @@ def test_indexcurve_shift(ad_order, composite) -> None:


def test_indexcurve_shift_dual_input() -> None:
curve = IndexCurve(
curve = Curve(
nodes={
dt(2022, 1, 1): 1.0,
dt(2023, 1, 1): 0.988,
Expand Down Expand Up @@ -872,7 +871,7 @@ def test_curve_shift_ad_orders(curve, line_curve, index_curve, c_obj, ini_ad, sp
1e-8,
),
(
IndexCurve(
Curve(
nodes={
dt(2022, 1, 1): 1.0,
dt(2023, 1, 1): 0.988,
Expand Down Expand Up @@ -1103,7 +1102,7 @@ def test_curve_spline_warning() -> None:


def test_index_curve_roll() -> None:
crv = IndexCurve(
crv = Curve(
nodes={
dt(2022, 1, 1): 1.0,
dt(2023, 1, 1): 0.988,
Expand Down Expand Up @@ -1276,9 +1275,10 @@ def test_curve_index_linear_daily_interp(self) -> None:
expected = 200.010001001 # value is linearly interpolated between index values.
assert abs(result - expected) < 1e-7

def test_indexcurve_raises(self) -> None:
with pytest.raises(ValueError, match="`index_base` must be given"):
IndexCurve({dt(2022, 1, 1): 1.0})
# SKIP: with deprecation of IndexCurve errors must be deferred to price time.
# def test_indexcurve_raises(self) -> None:
# with pytest.raises(ValueError, match="`index_base` must be given"):
# Curve({dt(2022, 1, 1): 1.0})

def test_index_value_raises(self) -> None:
curve = Curve({dt(2022, 1, 1): 1.0}, index_base=100.0)
Expand Down Expand Up @@ -1307,14 +1307,14 @@ def test_historic_rate_is_none(self) -> None:
assert curve.rate(dt(2021, 3, 4), "1b", "f") is None

def test_repr(self):
curve = IndexCurve(
curve = Curve(
nodes={dt(2022, 1, 1): 1.0, dt(2022, 1, 5): 0.9999}, index_base=200.0, id="us_cpi"
)
expected = f"<rl.IndexCurve:us_cpi at {hex(id(curve))}>"
expected = f"<rl.Curve:us_cpi at {hex(id(curve))}>"
assert expected == curve.__repr__()

def test_typing_as_curve(self):
curve = IndexCurve(
curve = Curve(
nodes={dt(2022, 1, 1): 1.0, dt(2022, 1, 5): 0.9999}, index_base=200.0, id="us_cpi"
)
assert isinstance(curve, Curve)
Expand Down Expand Up @@ -1552,8 +1552,8 @@ def test_index_curves_take_first_value(self, lag, base) -> None:
assert cc.index_lag == lag[0]

def test_index_curves_attributes(self) -> None:
ic1 = IndexCurve({dt(2022, 1, 1): 1.0, dt(2023, 1, 1): 0.99}, index_lag=3, index_base=101.1)
ic2 = IndexCurve({dt(2022, 1, 1): 1.0, dt(2023, 1, 1): 0.99}, index_lag=3, index_base=101.1)
ic1 = Curve({dt(2022, 1, 1): 1.0, dt(2023, 1, 1): 0.99}, index_lag=3, index_base=101.1)
ic2 = Curve({dt(2022, 1, 1): 1.0, dt(2023, 1, 1): 0.99}, index_lag=3, index_base=101.1)
cc = CompositeCurve([ic1, ic2])
assert cc.index_lag == 3
assert cc.index_base == 101.1
Expand All @@ -1571,8 +1571,8 @@ def test_index_curves_attributes(self) -> None:
assert abs(result - expected) < 1e-5

def test_index_curves_interp_raises(self) -> None:
ic1 = IndexCurve({dt(2022, 1, 1): 1.0, dt(2023, 1, 1): 0.99}, index_lag=3, index_base=101.1)
ic2 = IndexCurve({dt(2022, 1, 1): 1.0, dt(2023, 1, 1): 0.99}, index_lag=3, index_base=101.1)
ic1 = Curve({dt(2022, 1, 1): 1.0, dt(2023, 1, 1): 0.99}, index_lag=3, index_base=101.1)
ic2 = Curve({dt(2022, 1, 1): 1.0, dt(2023, 1, 1): 0.99}, index_lag=3, index_base=101.1)
cc = CompositeCurve([ic1, ic2])
with pytest.raises(ValueError, match="`interpolation` for `index_value` must"):
cc.index_value(dt(2022, 1, 31), interpolation="bad interp")
Expand Down Expand Up @@ -2089,16 +2089,16 @@ def test_plot_diff(self, curve) -> None:
@pytest.mark.parametrize("left", [NoInput(0), dt(2022, 1, 1), "0d"])
@pytest.mark.parametrize("right", [NoInput(0), dt(2022, 2, 1), "0d"])
def test_plot_index(self, left, right) -> None:
i_curve = IndexCurve({dt(2022, 1, 1): 1.0, dt(2022, 2, 1): 1.0}, index_base=2.0)
i_curve = Curve({dt(2022, 1, 1): 1.0, dt(2022, 2, 1): 1.0}, index_base=2.0)
fig, ax, lines = i_curve.plot_index(left=left, right=right)
result = lines[0].get_data()
assert result[0][0] == dt(2022, 1, 1)
assert abs(result[1][0].real - 2.0) < 1e-6
plt.close("all")

def test_plot_index_comparators(self) -> None:
i_curve = IndexCurve({dt(2022, 1, 1): 1.0, dt(2022, 2, 1): 1.0}, index_base=2.0)
i_curv2 = IndexCurve({dt(2022, 1, 1): 1.0, dt(2022, 2, 1): 1.0}, index_base=2.0)
i_curve = Curve({dt(2022, 1, 1): 1.0, dt(2022, 2, 1): 1.0}, index_base=2.0)
i_curv2 = Curve({dt(2022, 1, 1): 1.0, dt(2022, 2, 1): 1.0}, index_base=2.0)
fig, ax, lines = i_curve.plot_index(comparators=[i_curv2])
assert len(lines) == 2
res1 = lines[0].get_data()
Expand All @@ -2108,8 +2108,8 @@ def test_plot_index_comparators(self) -> None:
plt.close("all")

def test_plot_index_diff(self) -> None:
i_curv = IndexCurve({dt(2022, 1, 1): 1.0, dt(2022, 2, 1): 1.0}, index_base=2.0)
i_curv2 = IndexCurve({dt(2022, 1, 1): 1.0, dt(2022, 2, 1): 1.0}, index_base=2.0)
i_curv = Curve({dt(2022, 1, 1): 1.0, dt(2022, 2, 1): 1.0}, index_base=2.0)
i_curv2 = Curve({dt(2022, 1, 1): 1.0, dt(2022, 2, 1): 1.0}, index_base=2.0)
fig, ax, lines = i_curv.plot_index("1d", comparators=[i_curv2], difference=True)
assert len(lines) == 1
result = lines[0].get_data()
Expand All @@ -2118,7 +2118,7 @@ def test_plot_index_diff(self) -> None:
plt.close("all")

def test_plot_index_raises(self) -> None:
i_curve = IndexCurve({dt(2022, 1, 1): 1.0, dt(2022, 2, 1): 1.0}, index_base=2.0)
i_curve = Curve({dt(2022, 1, 1): 1.0, dt(2022, 2, 1): 1.0}, index_base=2.0)
with pytest.raises(ValueError, match="`left` must be supplied as"):
i_curve.plot_index(left=2.0)
with pytest.raises(ValueError, match="`right` must be supplied as"):
Expand Down Expand Up @@ -2186,7 +2186,7 @@ class TestStateAndCache:
[
Curve(nodes={dt(2000, 1, 1): 1.0, dt(2002, 1, 1): 0.99}),
LineCurve(nodes={dt(2000, 1, 1): 1.0, dt(2002, 1, 1): 0.99}),
IndexCurve(
Curve(
nodes={
dt(2022, 1, 1): 1.0,
dt(2023, 1, 1): 0.98,
Expand All @@ -2207,7 +2207,7 @@ def test_method_does_not_change_state(self, curve, method, args):
[
Curve(nodes={dt(2000, 1, 1): 1.0, dt(2002, 1, 1): 0.99, dt(2003, 1, 1): 0.98}),
LineCurve(nodes={dt(2000, 1, 1): 1.0, dt(2002, 1, 1): 0.99}),
IndexCurve(
Curve(
nodes={
dt(2000, 1, 1): 1.0,
dt(2002, 1, 1): 0.98,
Expand Down Expand Up @@ -2236,7 +2236,7 @@ def test_method_changes_state(self, curve, method, args):
[
Curve(nodes={dt(2000, 1, 1): 1.0, dt(2002, 1, 1): 0.99}),
LineCurve(nodes={dt(2000, 1, 1): 1.0, dt(2002, 1, 1): 0.99}),
IndexCurve(
Curve(
nodes={
dt(2022, 1, 1): 1.0,
dt(2023, 1, 1): 0.98,
Expand All @@ -2255,7 +2255,7 @@ def test_populate_cache(self, curve):
[
Curve(nodes={dt(2000, 1, 1): 1.0, dt(2002, 1, 1): 0.99, dt(2003, 1, 1): 0.98}),
LineCurve(nodes={dt(2000, 1, 1): 1.0, dt(2002, 1, 1): 0.99}),
IndexCurve(
Curve(
nodes={
dt(2000, 1, 1): 1.0,
dt(2002, 1, 1): 0.98,
Expand Down
Loading

0 comments on commit 640689b

Please sign in to comment.