diff options
| -rw-r--r-- | python/analytics/cms_spread.py | 39 |
1 files changed, 27 insertions, 12 deletions
diff --git a/python/analytics/cms_spread.py b/python/analytics/cms_spread.py index d9b0ecce..31d2e4f3 100644 --- a/python/analytics/cms_spread.py +++ b/python/analytics/cms_spread.py @@ -6,8 +6,7 @@ import pandas as pd import re from math import exp, sqrt, log, pi from .black import bachelier, cnd_erf -from numba import (cfunc, types, jit, float64, boolean, - optional, vectorize) +from numba import (cfunc, types, float64, vectorize) from quantlib.time.api import ( Date, Period, Days, Months, Years, UnitedStates, Actual365Fixed, Following, ModifiedFollowing) @@ -27,11 +26,15 @@ from quantlib.cashflows.linear_tsr_pricer import LinearTsrPricer from quantlib.quotes import SimpleQuote from quantlib.math.matrix import Matrix +from scipy import LowLevelCallable +from scipy.integrate import quad from scipy.interpolate import RectBivariateSpline from scipy.special import roots_hermitenorm from yieldcurve import YC from db import dbconn +__all__ = ["CmsSpread"] + _serenitasdb = dbconn('serenitasdb') _dawndb = dbconn('dawndb') @@ -56,7 +59,7 @@ def h_call(z, K, S1, S2, mu_x, mu_y, sigma_x, sigma_y, rho): @vectorize([float64(float64, float64, float64, float64, float64, float64, float64, float64, float64)], cache=True, nopython=True) -def h_put(z, K, S1, S2, mu_x, mu_y, sigma_x, sigma_y, rho,): +def h_put(z, K, S1, S2, mu_x, mu_y, sigma_x, sigma_y, rho): # z = (y - mu_y) / sigma_y u1 = mu_x + rho * sigma_x * z Ktilde = K + S2 * exp(mu_y + sigma_y * z) @@ -67,10 +70,11 @@ def h_put(z, K, S1, S2, mu_x, mu_y, sigma_x, sigma_y, rho,): 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)) +_sig = types.double(types.intc, types.CPointer(types.double)) -@cfunc(sig, cache=True, nopython=True) -def h1(n, args): +@cfunc(_sig, cache=True, nopython=True) +def _h1(n, args): + #z = (y - mu_y) / sigma_y z = args[0] K = args[1] S1 = args[2] @@ -87,8 +91,9 @@ def h1(n, args): v = sigma_x * sqrt(1 - rho * rho) v2 = sigma_x * sigma_x * (1 - rho * rho) x = (u1 - u2) / v - return 0.5 * (S1 * exp(u1 + 0.5 * v2) * cnd_erf(x + v) - Ktilde * cnd_erf(x)) + return 0.5 * (S1 * exp(u1 + 0.5 * v2) * cnd_erf(x + v) - Ktilde * cnd_erf(x)) * exp(-0.5 * z * z) +_call_integrand = LowLevelCallable(_h1.ctypes) def get_fixings(conn, tenor1, tenor2, fixing_date=None): if fixing_date: @@ -320,8 +325,14 @@ class CmsSpread: m = re.match(r"USD(\d{1,2})-(\d{1,2})CMS", r['floating_rate_index']) if m: tenor2, tenor1 = map(int, m.groups()) - instance = CmsSpread(r['expiration_date'], tenor1, tenor2, r['strike'] * 0.01, - value_date=r['trade_date'], notional=r['amount']) + if trade_id == 3: + instance = CmsSpread(r['expiration_date'], tenor1, tenor2, r['strike'] * 0.01, + value_date=r['trade_date'], notional=r['amount'], + conditional1=0.025) + else: + instance = CmsSpread(r['expiration_date'], tenor1, tenor2, r['strike'] * 0.01, + value_date=r['trade_date'], notional=r['amount'], + conditional1=0.025) return instance @property @@ -348,9 +359,13 @@ class CmsSpread: @property def pv(self): + args = (self.strike, *self._params, self.corr) + norm_const = 1 / sqrt(2 * pi) if self.conditional1 is not None: bound = (log(self.conditional1 / self._params[1]) - self._params[3]) / self._params[-1] + val, _ = quad(_call_integrand, -np.inf, bound, args=args) + return self.notional * norm_const * val * self.yc.discount(self.cms1.fixing_date) else: - return self.notional * 1 / sqrt(2 * pi) * \ - np.dot(self._w, h_call(self._x, self.strike, *self._params, self.corr)) * \ - self.yc.discount(self.cms1.fixing_date) + return self.notional * norm_const * \ + np.dot(self._w, h_call(self._x, *args)) * \ + self.yc.discount(self.cms1.fixing_date) |
