aboutsummaryrefslogtreecommitdiffstats
path: root/python
diff options
context:
space:
mode:
Diffstat (limited to 'python')
-rw-r--r--python/analytics/cms_spread.py72
-rw-r--r--python/exploration/test_cms.py16
2 files changed, 58 insertions, 30 deletions
diff --git a/python/analytics/cms_spread.py b/python/analytics/cms_spread.py
index 32c16ed1..e518c498 100644
--- a/python/analytics/cms_spread.py
+++ b/python/analytics/cms_spread.py
@@ -1,9 +1,8 @@
import numpy as np
import matplotlib.pyplot as plt
-from .tranche_functions import GHquad
from math import exp, sqrt, log
from .black import bachelier, cnd_erf
-from numba import jit, float64, boolean
+from numba import cfunc, int64, float64, boolean, types
from quantlib.time.api import (
Date, Period, Days, Months, Years, UnitedStates, Actual365Fixed, Following)
from quantlib.termstructures.yields.api import YieldTermStructure
@@ -21,23 +20,45 @@ from quantlib.quotes import SimpleQuote
from quantlib.math.matrix import Matrix
from scipy.interpolate import RectBivariateSpline
from db import dbconn
+from numba import cfunc
-@jit(float64(float64, float64, float64, float64, float64, float64, float64,
- float64, float64, boolean), cache=True, nopython=True)
-def h(z, K, S1, S2, mu_x, mu_y, sigma_x, sigma_y, rho, call=True):
- # z = (y - mu_y) / sigma_y
+# @jit(float64(float64, float64, float64, float64, float64, float64, float64,
+# float64, float64, boolean), cache=True, nopython=True)
+# def h(z, K, S1, S2, mu_x, mu_y, sigma_x, sigma_y, rho, call=True):
+# # z = (y - mu_y) / sigma_y
+# u1 = mu_x + rho * sigma_x * z
+# Ktilde = K + S2 * exp(mu_y + sigma_y * z)
+# u2 = log(Ktilde / S1)
+
+# v = sigma_x * sqrt(1 - rho * rho)
+# v2 = sigma_x * sigma_x * (1 - rho * rho)
+# if call:
+# x = (u1 - u2) / v
+# return 0.5 * (S1 * exp(u1 + 0.5 * v2) * cnd_erf(x + v) - Ktilde * cnd_erf(x))
+# else:
+# x = (u2 - u1) / v
+# return 0.5 * (Ktilde * cnd_erf(x) - S1 * exp(u1 + 0.5 * v2) * cnd_erf(x - v))
+
+sig = types.double(types.intc, types.CPointer(types.double))
+@cfunc(sig, cache=True, nopython=True)
+def h1(n, args):
+ z = args[0]
+ K = args[1]
+ S1 = args[2]
+ S2 = args[3]
+ mu_x = args[4]
+ mu_y = args[5]
+ sigma_x = args[6]
+ sigma_y = args[7]
+ rho = args[8]
u1 = mu_x + rho * sigma_x * z
Ktilde = K + S2 * exp(mu_y + sigma_y * z)
u2 = log(Ktilde / S1)
v = sigma_x * sqrt(1 - rho * rho)
v2 = sigma_x * sigma_x * (1 - rho * rho)
- if call:
- x = (u1 - u2) / v
- return 0.5 * (S1 * exp(u1 + 0.5 * v2) * cnd_erf(x + v) - Ktilde * cnd_erf(x))
- else:
- x = (u2 - u1) / v
- return 0.5 * (Ktilde * cnd_erf(x) - S1 * exp(u1 + 0.5 * v2) * cnd_erf(x - v))
+ x = (u1 - u2) / v
+ return 0.5 * (S1 * exp(u1 + 0.5 * v2) * cnd_erf(x + v) - Ktilde * cnd_erf(x))
def get_fixings(conn, tenor1, tenor2, fixing_date=None):
@@ -88,7 +109,7 @@ def get_swaption_vol_data(source="ICPL", vol_type=VolatilityType.ShiftedLognorma
with conn.cursor() as c:
c.execute(sql_str, params)
surf_data = next(c)
- return surf_data[0], np.array(surf_data[1:-1], order='F').T
+ return surf_data[0], np.array(surf_data[1:-1], order='F', dtype='float64').T
def get_swaption_vol_surface(date, vol_type):
@@ -118,26 +139,33 @@ def get_swaption_vol_matrix(date, data, vol_type=VolatilityType.ShiftedLognormal
def quantlib_model(date, spread_index, yc, cap, rho, maturity, mean_rev=0.,
- vol_type=VolatilityType.ShiftedLognormal):
+ vol_type=VolatilityType.ShiftedLognormal,
+ notional=300_000_000):
date, surf = get_swaption_vol_data(date=date, vol_type=vol_type)
atm_vol = get_swaption_vol_matrix(date, surf, vol_type)
pricer = LinearTsrPricer(atm_vol, SimpleQuote(mean_rev), yc)
vol_type = VolatilityType(atm_vol.volatility_type)
- cmsspread_pricer = LognormalCmsSpreadPricer(pricer,
- SimpleQuote(rho),
- yc)
+ if isinstance(rho, float):
+ rho = SimpleQuote(rho)
+ cmsspread_pricer = LognormalCmsSpreadPricer(pricer, rho, yc)
end_date = Date.from_datetime(maturity)
pay_date = spread_index.fixing_calendar.advance(end_date, 0, Days)
start_date = end_date - Period(1, Years)
- end_date = Date(19, 1, 2020)
- cms_spread_coupon = CappedFlooredCmsSpreadCoupon(
- pay_date, 300_000_000, start_date, end_date,
+ end_date = Date.from_datetime(maturity)
+ # we build an in arrear floored coupon
+ # see line 38 in ql/cashflows/capflooredcoupon.hpp
+ # The payoff $P$ of a floored floating-rate coupon is:
+ # \[ P = N \times T \times \max(a L + b, F). \]
+ # where $N$ is the notional, $T$ is the accrual time, $L$ is the floating rate,
+ # $a$ is its gearing, $b$ is the spread, and $F$ the strike
+ capped_floored_cms_spread_coupon = CappedFlooredCmsSpreadCoupon(
+ pay_date, notional, start_date, end_date,
spread_index.fixing_days, spread_index, 1., -cap,
floor=0.,
day_counter=Actual365Fixed(),
is_in_arrears=True)
- cms_spread_coupon.set_pricer(cmsspread_pricer)
- return cms_spread_coupon
+ capped_floored_cms_spread_coupon.set_pricer(cmsspread_pricer)
+ return capped_floored_cms_spread_coupon
def plot_surf(surf, tenors):
diff --git a/python/exploration/test_cms.py b/python/exploration/test_cms.py
index 57677b43..10a04084 100644
--- a/python/exploration/test_cms.py
+++ b/python/exploration/test_cms.py
@@ -2,8 +2,8 @@ from analytics.cms_spread import (
quantlib_model, globeop_model, build_spread_index, VolatilityType)
from yieldcurve import YC
import pandas as pd
-
-cms30y2y, yc = build_spread_index(30, 2)
+from quantlib.time.api import Date
+swap_index_30y2y, yc = build_spread_index(30, 2)
cap = 0.00758
corr = 0.8
r = []
@@ -11,16 +11,16 @@ maturity = pd.Timestamp("2020-01-19")
today = pd.Timestamp.today()
for d in pd.bdate_range("2018-01-19", today, closed="left", normalize=True):
+ d = pd.Timestamp("2018-01-19")
yc.link_to(YC(evaluation_date=d.date()))
yc.extrapolation = True
if d == pd.Timestamp("2018-02-16"):
continue
- cms_spread_coupon_ln = quantlib_model(d, cms30y2y, yc, cap, corr, maturity)
+ capped_floored_cms_spread_coupon_ln = \
+ quantlib_model(d, swap_index_30y2y, yc, cap, corr, maturity)
rate1 = cms_spread_coupon_ln.rate
- cms_spread_coupon_n = quantlib_model(d, cms30y2y, yc, cap, corr, maturity,
+ cms_spread_coupon_n = quantlib_model(d, swap_index_30y2y, yc, cap, corr, maturity,
VolatilityType.Normal)
rate2 = cms_spread_coupon_n.rate
- rate3 = globeop_model(d, cms30y2y, yc, cap, corr - 0.075, maturity)
- r.append((d, rate1, rate2, rate3))
-
-df = pd.DataFrame(r, columns=['date', 'QL_ln', 'QL_n', 'Globeop']).set_index('date')
+ rate3 = globeop_model(d, swap_index_30y2y, yc, cap, corr - 0.075, maturity)
+# df = pd.DataFrame(r, columns=['date', 'QL_ln', 'QL_n', 'Globeop']).set_index('date')