Skip to content

Commit

Permalink
BUG: cms remove repo proceeds method (#693)
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 640689b commit dec17c9
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 8 deletions.
4 changes: 4 additions & 0 deletions docs/source/i_whatsnew.rst
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ email contact, see `rateslib <https://rateslib.com>`_.
* - Refactor
- Rename :class:`~rateslib.instruments.BaseMixin` to :class:`~rateslib.instruments.Metrics`.
(`678 <https://github.com/attack68/rateslib/pull/678>`_)
* - Refactor
- Minor changes to :class:`BondFuture.cms <rateslib.instruments.BondFuture.cms>` to avoid
the proceeds method of repo rates and utilise only a bond curve for forward bond prices.
(`693 <https://github.com/attack68/rateslib/pull/693>`_)
* - Bug
- Add :class:`~rateslib.instruments.NDF` to global *rateslib* namespace.
(`682 <https://github.com/attack68/rateslib/pull/682>`_)
Expand Down
13 changes: 5 additions & 8 deletions python/rateslib/instruments/bonds/futures.py
Original file line number Diff line number Diff line change
Expand Up @@ -490,16 +490,13 @@ def cms(
}
for shift in shifts:
_curve = bcurve.shift(shift, composite=False)
future_price = self.rate(curves=_curve, metric="future_price")
data.update(
{
shift: self.net_basis(
future_price=self.rate(curves=_curve),
prices=[_.rate(curves=_curve, metric=metric) for _ in self.basket],
repo_rate=_curve._rate_with_raise(settlement, self.delivery[1], "NONE"),
settlement=settlement,
delivery=delivery,
convention=_curve.convention,
dirty=dirty,
shift: tuple(
bond.rate(curves=_curve, metric="clean_price", forward_settlement=delivery)
- self.cfs[i] * future_price
for i, bond in enumerate(self.basket)
),
},
)
Expand Down
96 changes: 96 additions & 0 deletions python/tests/test_instruments_bonds.py
Original file line number Diff line number Diff line change
Expand Up @@ -2688,3 +2688,99 @@ def test_futures_duration_and_convexity(self, delivery) -> None:
result = future.duration(112.98, delivery=delivery, metric="modified")[0]
expected = 7.23419455163
assert abs(result - expected) < 1e-3

def test_cms(self):
data = DataFrame(
data=[
[
FixedRateBond(
dt(2022, 1, 1), dt(2039, 8, 15), fixed_rate=4.5, spec="ust", curves="bcurve"
),
98.6641,
],
[
FixedRateBond(
dt(2022, 1, 1),
dt(2040, 2, 15),
fixed_rate=4.625,
spec="ust",
curves="bcurve",
),
99.8203,
],
[
FixedRateBond(
dt(2022, 1, 1),
dt(2041, 2, 15),
fixed_rate=4.75,
spec="ust",
curves="bcurve",
),
100.7734,
],
[
FixedRateBond(
dt(2022, 1, 1),
dt(2040, 5, 15),
fixed_rate=4.375,
spec="ust",
curves="bcurve",
),
96.6953,
],
[
FixedRateBond(
dt(2022, 1, 1),
dt(2042, 11, 15),
fixed_rate=4.00,
spec="ust",
curves="bcurve",
),
90.4766,
],
],
columns=["bonds", "prices"],
)
usz3 = BondFuture( # Construct the BondFuture Instrument
coupon=6.0,
delivery=(dt(2023, 12, 1), dt(2023, 12, 29)),
basket=data["bonds"],
nominal=100e3,
calendar="nyc",
currency="usd",
calc_mode="ust_long",
)
result = usz3.cms(prices=data["prices"], settlement=dt(2023, 11, 22), shifts=[-50, 0, 50])
expected = DataFrame(
data={
"Bond": [
"4.500% 15-08-2039",
"4.625% 15-02-2040",
"4.750% 15-02-2041",
"4.375% 15-05-2040",
"4.000% 15-11-2042",
],
-50: [
0.0,
0.10938764224876252,
0.32693578691382186,
0.24721845093496597,
1.1960030963801813,
],
0: [
0.0,
0.01148721023514554,
0.016282194434154462,
0.032902987886402,
0.33598669301149187,
],
50: [
0.43066112621522734,
0.3653207547713322,
0.19632745772335625,
0.27120849999053576,
0.0
],
}
)
assert_frame_equal(result, expected)

0 comments on commit dec17c9

Please sign in to comment.