Skip to content

Commit 9f602b0

Browse files
mikelyncattack68
andauthored
TST: forward in NPV (#201) (#1119)
Co-authored-by: JHM Darbyshire (M1) <[email protected]> Co-authored-by: Mike Lync <[email protected]>
1 parent 5db5509 commit 9f602b0

File tree

2 files changed

+186
-2
lines changed

2 files changed

+186
-2
lines changed

python/tests/instruments/test_instruments_legacy.py

Lines changed: 185 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ def curve2():
7878
dt(2022, 7, 1): 0.97,
7979
dt(2022, 10, 1): 0.95,
8080
}
81-
return Curve(nodes=nodes, interpolation="log_linear")
81+
return Curve(nodes=nodes, interpolation="log_linear", index_base=100.0)
8282

8383

8484
@pytest.fixture
@@ -4355,6 +4355,18 @@ def test_bad_metric_raises(self):
43554355
leg2_fixed=True,
43564356
).rate(metric="bad")
43574357

4358+
def test_leg1_mtm(self):
4359+
# if notional given on leg1 this will error with nd `pair` not given.
4360+
XCS(
4361+
effective=dt(2000, 1, 1),
4362+
termination="6m",
4363+
frequency="Q",
4364+
currency="eur",
4365+
leg2_currency="usd",
4366+
mtm=True,
4367+
leg2_notional=10.0,
4368+
)
4369+
43584370

43594371
class TestFixedFloatXCS:
43604372
def test_mtmfixxcs_rate(self, curve, curve2) -> None:
@@ -8039,3 +8051,175 @@ def test_sabr_surface(self):
80398051
def test_unpriced_cashflows_string_id(inst):
80408052
result = inst.cashflows()
80418053
assert isinstance(result, DataFrame)
8054+
8055+
8056+
@pytest.mark.parametrize(
8057+
("inst", "curves"),
8058+
[
8059+
(IRS(dt(2022, 2, 1), "1m", spec="usd_irs", fixed_rate=2.0), ["c"]),
8060+
(
8061+
SBS(dt(2022, 2, 1), "2m", frequency="2M", leg2_frequency="1M", float_spread=2.0),
8062+
["c", "c", "c2", "c"],
8063+
),
8064+
(STIRFuture(dt(2022, 2, 1), "1m", spec="usd_stir1", price=99.0), ["c"]),
8065+
(
8066+
XCS(
8067+
dt(2022, 1, 1),
8068+
"2m",
8069+
fixed=True,
8070+
leg2_fixed=True,
8071+
fixed_rate=2.0,
8072+
leg2_fixed_rate=2.5,
8073+
frequency="1M",
8074+
leg2_fx_fixings=2.0,
8075+
),
8076+
["c", "c", "c2", "c"],
8077+
),
8078+
(
8079+
XCS(
8080+
dt(2022, 1, 1),
8081+
"2m",
8082+
fixed=True,
8083+
fixed_rate=2.0,
8084+
frequency="1M",
8085+
leg2_fx_fixings=2.0,
8086+
),
8087+
["c", "c", "c2", "c"],
8088+
),
8089+
(
8090+
XCS(
8091+
dt(2022, 1, 1),
8092+
"2m",
8093+
leg2_fixed=True,
8094+
leg2_fixed_rate=2.0,
8095+
float_spread=0.0,
8096+
frequency="1M",
8097+
leg2_fx_fixings=2.0,
8098+
),
8099+
["c", "c", "c2", "c"],
8100+
),
8101+
(
8102+
XCS(
8103+
dt(2022, 1, 1),
8104+
"2m",
8105+
float_spread=0.0,
8106+
leg2_float_spread=0.0,
8107+
frequency="1M",
8108+
leg2_fx_fixings=2.0,
8109+
),
8110+
["c", "c", "c2", "c"],
8111+
),
8112+
(CDS(dt(2022, 2, 1), "1m", frequency="1M", fixed_rate=1.0), ["c2", "c"]),
8113+
(ZCS(dt(2022, 1, 1), "2m", frequency="3M", fixed_rate=2.0), ["c"]),
8114+
(
8115+
ZCIS(
8116+
dt(2022, 1, 1),
8117+
"2M",
8118+
frequency="3M",
8119+
fixed_rate=2.0,
8120+
leg2_index_base=99.0,
8121+
leg2_index_lag=0,
8122+
),
8123+
["c2", "c"],
8124+
),
8125+
(
8126+
IIRS(
8127+
dt(2022, 1, 1), "2M", spec="usd_irs", fixed_rate=2.0, index_base=99.0, index_lag=0
8128+
),
8129+
["c2", "c", "c", "c"],
8130+
),
8131+
(FRA(dt(2022, 2, 1), "1m", fixed_rate=1.0, frequency="1M"), ["c"]),
8132+
],
8133+
)
8134+
def test_forward_npv_argument(curve, curve2, inst, curves):
8135+
c_ = {"c": curve, "c2": curve2}
8136+
npv = inst.npv(curves=[c_[v] for v in curves])
8137+
forward_npv = inst.npv(curves=[c_[v] for v in curves], forward=dt(2022, 3, 15))
8138+
assert abs(forward_npv - npv / curve[dt(2022, 3, 15)]) < 1e-10
8139+
8140+
8141+
@pytest.mark.parametrize(
8142+
("inst", "curves"),
8143+
[
8144+
(
8145+
XCS(
8146+
dt(2022, 1, 1),
8147+
"2m",
8148+
mtm=True,
8149+
fixed=True,
8150+
leg2_fixed=True,
8151+
fixed_rate=2.0,
8152+
leg2_fixed_rate=3.0,
8153+
frequency="1M",
8154+
fx_fixings=2.0,
8155+
currency="eur",
8156+
leg2_currency="usd",
8157+
leg2_notional=10e6,
8158+
),
8159+
["c", "c", "c2", "c2"],
8160+
),
8161+
(
8162+
XCS(
8163+
dt(2022, 1, 1),
8164+
"2m",
8165+
mtm=True,
8166+
fixed=True,
8167+
fixed_rate=2.0,
8168+
frequency="1M",
8169+
fx_fixings=2.0,
8170+
currency="eur",
8171+
leg2_currency="usd",
8172+
leg2_notional=10e6,
8173+
),
8174+
["c", "c", "c2", "c2"],
8175+
),
8176+
(
8177+
XCS(
8178+
dt(2022, 1, 1),
8179+
"2m",
8180+
mtm=True,
8181+
leg2_fixed=True,
8182+
leg2_fixed_rate=2.0,
8183+
float_spread=0.0,
8184+
frequency="1M",
8185+
fx_fixings=2.0,
8186+
currency="eur",
8187+
leg2_currency="usd",
8188+
leg2_notional=10e6,
8189+
),
8190+
["c", "c", "c2", "c2"],
8191+
),
8192+
(
8193+
XCS(
8194+
dt(2022, 1, 1),
8195+
"2m",
8196+
mtm=True,
8197+
float_spread=0.0,
8198+
leg2_float_spread=0.0,
8199+
frequency="1M",
8200+
fx_fixings=2.0,
8201+
currency="eur",
8202+
leg2_currency="usd",
8203+
leg2_notional=10e6,
8204+
),
8205+
["c", "c", "c2", "c2"],
8206+
),
8207+
(NDF(dt(2022, 2, 15), pair="eurusd", fx_rate=1.15), ["c2"]),
8208+
(
8209+
FXSwap(dt(2022, 2, 15), "1m", pair="eurusd", leg2_fx_fixings=1.15, points=56.5),
8210+
["c", "c2"],
8211+
),
8212+
(FXForward(dt(2022, 2, 16), "eurusd", fx_rate=1.15), ["c", "c2"]),
8213+
],
8214+
)
8215+
def test_forward_npv_argument_with_fx(curve, curve2, inst, curves):
8216+
fxr = FXRates({"eurusd": 1.12}, settlement=dt(2022, 1, 3))
8217+
fxf = FXForwards(fx_rates=fxr, fx_curves={"eureur": curve, "eurusd": curve, "usdusd": curve2})
8218+
c_ = {"c": curve, "c2": curve2}
8219+
npv = inst.npv(curves=[c_[v] for v in curves], fx=fxf, base="eur")
8220+
forward_npv = inst.npv(
8221+
curves=[c_[v] for v in curves], forward=dt(2022, 3, 15), fx=fxf, base="eur"
8222+
)
8223+
8224+
result = npv / curve[dt(2022, 3, 15)] - forward_npv
8225+
assert abs(result) < 1e-7

python/tests/test_solver.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ def s(x):
116116
assert result["iterations"] < 12
117117

118118
result2 = ift_1dim(s, s_tgt, "bisection", (1.15, 5.0), conv_tol=1e-12)
119-
assert result["time"] <= result2["time"]
119+
assert 30 < result2["iterations"] < 50
120120

121121
def test_dekker_conv_tol(self):
122122
def s(x):

0 commit comments

Comments
 (0)