Skip to content

Commit

Permalink
BUG: index_base forecasting in the past with "monthly" `index_metho…
Browse files Browse the repository at this point in the history
…d` (#354)
  • Loading branch information
attack68 authored Aug 27, 2024
1 parent 7359a64 commit ba077ea
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 1 deletion.
3 changes: 3 additions & 0 deletions docs/source/i_whatsnew.rst
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ email contact through **[email protected]**.
* - Bug
- :class:`~rateslib.instruments.IndexFixedRateBond` now correctly initialises when using a
:class:`pandas.Series` as ``index_fixings`` argument.
* - Bug
- :class:`~rateslib.instruments.ZCIS` now raises if an `index_base` cannot be forecast from an *IndexCurve*
and the value should be known and input directly, to avoid *Solver* calibration failures.

1.3.0 (9th July 2024)
***********************
Expand Down
10 changes: 9 additions & 1 deletion python/rateslib/instruments.py
Original file line number Diff line number Diff line change
Expand Up @@ -6359,9 +6359,17 @@ def rate(
)
if self.leg2_index_base is NoInput.blank:
# must forecast for the leg
self.leg2.index_base = curves[2].index_value(
forecast_value = curves[2].index_value(
self.leg2.schedule.effective, self.leg2.index_method
)
if abs(forecast_value) < 1e-13:
raise ValueError(
"Forecasting the `index_base` for the ZCIS yielded 0.0, which is infeasible.\n"
"This might occur if the ZCIS starts in the past, or has a 'monthly' "
"`index_method` which uses the 1st day of the effective month, which is in the "
"past.\nA known `index_base` value should be input with the ZCIS specification."
)
self.leg2.index_base = forecast_value
leg2_npv = self.leg2.npv(curves[2], curves[3])

return self.leg1._spread(-leg2_npv, curves[0], curves[1]) / 100
Expand Down
18 changes: 18 additions & 0 deletions python/tests/test_instruments.py
Original file line number Diff line number Diff line change
Expand Up @@ -1275,6 +1275,24 @@ def test_leg2_index_base(self, curve):
result = zcis.rate(curves=[curve, curve, i_curve, curve])
assert result > (prior + 100)

def test_solver_failure_unspecified_index_base(self, curve):
# GH 349
curve = Curve({dt(2022, 1, 15): 1.0, dt(2023, 1, 1): 0.98})
i_curve = IndexCurve({dt(2022, 1, 15): 1.0, dt(2023, 1, 1): 0.99}, index_base=200.0)
zcis = ZCIS(
effective=dt(2022, 1, 15),
termination="9m",
frequency="A",
convention="1+",
calendar="nyc",
leg2_index_method="monthly",
currency="usd",
curves=[curve, curve, i_curve, curve],
leg2_index_lag=3,
)
with pytest.raises(ValueError, match="Forecasting the `index_base`"):
zcis.rate()


class TestValue:
def test_npv_adelta_cashflows_raises(self):
Expand Down

0 comments on commit ba077ea

Please sign in to comment.