aboutsummaryrefslogtreecommitdiffstats
path: root/python/tests/test_cms_spread.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/tests/test_cms_spread.py')
-rw-r--r--python/tests/test_cms_spread.py87
1 files changed, 87 insertions, 0 deletions
diff --git a/python/tests/test_cms_spread.py b/python/tests/test_cms_spread.py
new file mode 100644
index 00000000..457d8fbd
--- /dev/null
+++ b/python/tests/test_cms_spread.py
@@ -0,0 +1,87 @@
+import datetime
+import math
+import numpy as np
+import unittest
+from analytics.cms_spread import (
+ build_spread_index, VolatilityType,
+ get_swaption_vol_data, get_swaption_vol_matrix, get_cms_coupons,
+ get_params, h_call, h_put)
+from quantlib.quotes import SimpleQuote
+from quantlib.time.api import (Actual365Fixed, Days, Date, ModifiedFollowing,
+ Period, Years)
+from yieldcurve import YC
+from quantlib.cashflows.conundrum_pricer import (
+ AnalyticHaganPricer, YieldCurveModel)
+from quantlib.experimental.coupons.cms_spread_coupon import (
+ CappedFlooredCmsSpreadCoupon)
+from quantlib.experimental.coupons.lognormal_cmsspread_pricer import (
+ LognormalCmsSpreadPricer)
+from scipy.special import roots_hermitenorm
+
+
+class TestCmsSpread(unittest.TestCase):
+
+ def setUp(self):
+ self.trade_date = datetime.date(2018, 1, 19)
+ option_tenor = Period(2, Years)
+ maturity = Date.from_datetime(self.trade_date) + Period(2, Years)
+ spread_index, self.yc = build_spread_index(30, 2)
+ fixing_date = (spread_index.
+ fixing_calendar.
+ adjust(maturity, ModifiedFollowing))
+ payment_date = (spread_index.
+ fixing_calendar.
+ advance(fixing_date, 2, Days))
+ accrued_end_date = payment_date
+ accrued_start_date = accrued_end_date - Period(1, Years)
+
+ self.cap = 0.0075835
+
+ self.notional = 100_000_000
+ self.cms30y2y_cap = CappedFlooredCmsSpreadCoupon(
+ payment_date,
+ self.notional,
+ start_date=accrued_start_date,
+ end_date=accrued_end_date,
+ fixing_days=spread_index.fixing_days,
+ index=spread_index,
+ gearing=1.,
+ spread=-self.cap,
+ floor=0.,
+ day_counter=Actual365Fixed(),
+ is_in_arrears=True)
+
+ self.cms2y, self.cms30y = get_cms_coupons(self.trade_date,
+ self.notional,
+ option_tenor,
+ spread_index)
+
+ def test_black_model(self):
+ evaluation_date = datetime.date(2018, 8, 23)
+ self.yc.link_to(YC(evaluation_date=evaluation_date))
+ self.yc.extrapolation = True
+ date, surf = get_swaption_vol_data(date=evaluation_date,
+ vol_type=VolatilityType.ShiftedLognormal)
+ atm_vol = get_swaption_vol_matrix(evaluation_date, surf)
+ μ = SimpleQuote(0.1)
+ ρ = SimpleQuote(0.8)
+ cms_pricer = AnalyticHaganPricer(atm_vol, YieldCurveModel.Standard, μ)
+ params = get_params(self.cms2y, self.cms30y, cms_pricer, atm_vol)
+ x, w = roots_hermitenorm(16)
+ val_call = 1 / math.sqrt(2 * math.pi) * np.dot(w,
+ h_call(x, self.cap, *params, ρ.value))
+ val_put = 1 / math.sqrt(2 * math.pi) * np.dot(w,
+ h_put(x, self.cap, *params, ρ.value))
+ cms_spread_pricer = LognormalCmsSpreadPricer(
+ cms_pricer,
+ ρ,
+ integration_points=20)
+ self.cms30y2y_cap.set_pricer(cms_spread_pricer)
+ self.assertAlmostEqual(self.cms30y2y_cap.rate,
+ val_call)
+ self.assertAlmostEqual(-self.cms30y2y_cap.underlying.rate, val_put - val_call)
+ self.assertAlmostEqual(self.cms30y.rate - self.cms2y.rate - self.cap,
+ self.cms30y2y_cap.underlying.rate)
+
+if __name__ == "__main__":
+ unittest.main()