aboutsummaryrefslogtreecommitdiffstats
path: root/python/analytics
diff options
context:
space:
mode:
Diffstat (limited to 'python/analytics')
-rw-r--r--python/analytics/__init__.py4
-rw-r--r--python/analytics/index.py9
-rw-r--r--python/analytics/option.py11
-rw-r--r--python/analytics/portfolio.py12
-rw-r--r--python/analytics/tranche_basket.py24
5 files changed, 50 insertions, 10 deletions
diff --git a/python/analytics/__init__.py b/python/analytics/__init__.py
index 39c0557b..e499288a 100644
--- a/python/analytics/__init__.py
+++ b/python/analytics/__init__.py
@@ -5,3 +5,7 @@ from .portfolio import Portfolio
from .basket_index import MarkitBasketIndex
from .tranche_basket import DualCorrTranche, TrancheBasket
from .ir_swaption import IRSwaption
+
+_ontr = CreditIndex('HY', 31, '5yr')
+_ontr.mark()
+_beta = {'HY': 1, 'IG': .3}
diff --git a/python/analytics/index.py b/python/analytics/index.py
index 3130398a..4c841a74 100644
--- a/python/analytics/index.py
+++ b/python/analytics/index.py
@@ -1,6 +1,7 @@
import array
import datetime
import pandas as pd
+import analytics
from .credit_default_swap import CreditDefaultSwap
from .db import _engine, dbengine, DataError
@@ -8,7 +9,6 @@ from bbg_helpers import BBG_IP, retrieve_data, init_bbg_session
from pandas.tseries.offsets import BDay
from pyisda.curve import SpreadCurve
-
def g(index, spread, exercise_date, pv=None):
"""computes the strike clean price using the expected forward yield curve. """
step_in_date = exercise_date + datetime.timedelta(days=1)
@@ -113,6 +113,13 @@ class CreditIndex(CreditDefaultSwap):
return instance
@property
+ def hy_equiv(self):
+ risk = self.notional * self.risky_annuity / analytics._ontr.risky_annuity
+ if self.index_type != 'HY':
+ risk *= analytics._beta[self.index_type]
+ return -risk if self.direction == 'Buyer' else risk
+
+ @property
def ref(self):
if self._quote_is_price:
return self.price
diff --git a/python/analytics/option.py b/python/analytics/option.py
index eecb9997..2930796e 100644
--- a/python/analytics/option.py
+++ b/python/analytics/option.py
@@ -3,6 +3,8 @@ import datetime
import math
import numpy as np
import pandas as pd
+import analytics
+
from db import dbengine
from .black import black, Nx
@@ -262,13 +264,20 @@ class BlackSwaption(ForwardIndex):
self._update()
notional_ratio = self.index.notional / self.notional
dv01 = self.pv - old_pv
- delta = -self.index._direction * dv01 * notional_ratio / \
+ delta = self.index._direction * dv01 * notional_ratio / \
(self.index.pv - old_index_pv)
self.index.spread = old_spread
self._update()
return delta
@property
+ def hy_equiv(self):
+ risk = self.delta * abs(self.index.hy_equiv/ \
+ self.index.notional) * self.notional
+ risk *= -1 if self.option_type == 'payer' else 1
+ return -risk if self.direction == 'Short' else risk
+
+ @property
def T(self):
if self._T:
return self._T
diff --git a/python/analytics/portfolio.py b/python/analytics/portfolio.py
index a4ed393d..ef1d5578 100644
--- a/python/analytics/portfolio.py
+++ b/python/analytics/portfolio.py
@@ -166,10 +166,14 @@ class Portfolio:
def theta(self):
return sum(t.theta for t in self.trades)
+ @property
+ def hy_equiv(self):
+ return sum(t.hy_equiv for t in self.trades)
+
def _todf(self):
headers = ["Product", "Index", "Notional", "Ref", "Strike", "Direction",
"Type", "Expiry", "Vol", "PV", "Delta", "Gamma", "Theta",
- "Vega", "attach", "detach", "Attach Rho", "Detach Rho"]
+ "Vega", "attach", "detach", "Attach Rho", "Detach Rho", "HY Equiv"]
rec = []
for t in self.trades:
if isinstance(t, CreditIndex):
@@ -177,19 +181,19 @@ class Portfolio:
r = ("Index", name, t.notional, t.ref, "N/A",
t.direction, "N/A", "N/A", None, t.pv,
1., 0., t.theta, 0.,
- None, None, None, None)
+ None, None, None, None, t.hy_equiv)
elif isinstance(t, BlackSwaption):
name = f"{t.index.index_type}{t.index.series} {t.index.tenor}"
r = ("Swaption", name, t.notional, t.ref, t.strike,
t.direction, t.option_type, t.forward_date, t.sigma, t.pv,
t.delta, t.gamma, t.theta, t.vega,
- None, None, None, None)
+ None, None, None, None, t.hy_equiv)
elif isinstance(t, DualCorrTranche):
name = f"{t.index_type}{t.series} {t.tenor}"
r = ("Tranche", name, t.notional, None, None,
t.direction, None, None, None, t.upfront,
t.delta, t.gamma, None, None,
- t.attach, t.detach, t.rho[0], t.rho[1])
+ t.attach, t.detach, t.rho[0], t.rho[1], t.hy_equiv)
else:
raise TypeError
rec.append(r)
diff --git a/python/analytics/tranche_basket.py b/python/analytics/tranche_basket.py
index dab528c6..1af4d4eb 100644
--- a/python/analytics/tranche_basket.py
+++ b/python/analytics/tranche_basket.py
@@ -13,9 +13,11 @@ from pyisda.date import cds_accrued
from scipy.optimize import brentq
from scipy.interpolate import CubicSpline, PchipInterpolator
from scipy.special import logit, expit
+
import datetime
import pandas as pd
import numpy as np
+import analytics
class DualCorrTranche():
@@ -175,7 +177,8 @@ class DualCorrTranche():
@property
def pv(self):
- return self._pv()
+ pl, cl = self._pv()
+ return float(-pl - cl + self._accrued)
def _pv(self, epsilon=0.):
""" computes coupon leg, protection leg and bond price.
@@ -192,7 +195,7 @@ class DualCorrTranche():
dK = np.diff(self.K)
pl = np.diff(pl) / dK
cl = np.diff(cl) / dK * self.tranche_running * 1e-4
- return float(-pl - cl + self._accrued)
+ return pl, cl
@property
def upfront(self):
@@ -246,7 +249,7 @@ class DualCorrTranche():
self._index.tweak_portfolio(ss, self.maturity, False)
for corrs in corr_shock:
#also need to map skew
- self.rho = np.fmin(1, orig_rho * (1 + corrs))
+ self.rho = orig_rho * (1 + corrs)
r.append([getattr(self, p) for p in actual_params])
self._index.curves = orig_curves
self.rho = orig_rho
@@ -283,6 +286,18 @@ class DualCorrTranche():
self._index.factor
@property
+ def duration(self):
+ return self._pv()[1] - self._accrued
+
+ @property
+ def hy_equiv(self):
+ risk = self.notional * self.delta * float(self._index.duration()) / \
+ analytics._ontr.risky_annuity
+ if self.index_type != 'HY':
+ risk *= analytics._beta[self.index_type]
+ return risk
+
+ @property
def delta(self):
calc = self._greek_calc()
factor = self.tranche_factor / self._index.factor
@@ -306,7 +321,8 @@ class DualCorrTranche():
bp = [self.pv]
for tweak in [eps, -eps, 2*eps]:
indexbp.append(self.tranche_legs(1., None, tweak).bond_price)
- bp.append(self._pv(tweak))
+ pl, cl = self._pv(tweak)
+ bp.append(float(-pl - cl + self._accrued))
return {'indexbp': indexbp, 'bp': bp}
class TrancheBasket(BasketIndex):