diff options
Diffstat (limited to 'python/analytics')
| -rw-r--r-- | python/analytics/__init__.py | 4 | ||||
| -rw-r--r-- | python/analytics/index.py | 9 | ||||
| -rw-r--r-- | python/analytics/option.py | 11 | ||||
| -rw-r--r-- | python/analytics/portfolio.py | 12 | ||||
| -rw-r--r-- | python/analytics/tranche_basket.py | 24 |
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): |
