aboutsummaryrefslogtreecommitdiffstats
path: root/python/analytics
diff options
context:
space:
mode:
Diffstat (limited to 'python/analytics')
-rw-r--r--python/analytics/cms_spread.py39
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)