aboutsummaryrefslogtreecommitdiffstats
path: root/python
diff options
context:
space:
mode:
Diffstat (limited to 'python')
-rw-r--r--python/analytics/tranche_basket.py60
1 files changed, 48 insertions, 12 deletions
diff --git a/python/analytics/tranche_basket.py b/python/analytics/tranche_basket.py
index 1d58219c..ff46c74e 100644
--- a/python/analytics/tranche_basket.py
+++ b/python/analytics/tranche_basket.py
@@ -3,7 +3,7 @@ from .tranche_functions import (
credit_schedule, adjust_attachments, GHquad, BCloss_recov_dist,
BCloss_recov_trunc, tranche_cl, tranche_pl)
from .index_data import get_tranche_quotes
-from .utils import memoize
+from .utils import memoize, build_table
from collections import namedtuple
from db import dbconn
from copy import deepcopy
@@ -27,13 +27,18 @@ class DualCorrTranche():
value_date: pd.Timestamp=pd.Timestamp.today().normalize()):
self._index = BasketIndex(index_type, series, [tenor], value_date=value_date)
- def get_quotes(self, spread):
- maturity = self.maturities[0]
- return {maturity:
- self._snacpv(spread * 1e-4, self.coupon(maturity), self.recovery,
- maturity)}
- # monkey patch _get_quotes (don't try it at home)
- BasketIndex._get_quotes = get_quotes
+ # def get_quotes(self, spread):
+ # index = self.
+
+ # maturity = self._index.maturities[0]
+ # return {maturity:
+ # self._snacpv(spread * 1e-4, self.coupon(maturity), self.recovery,
+ # maturity)}
+ # # monkey patch _get_quotes (don't try it at home)
+ # BasketIndex._get_quotes = get_quotes
+ self.maturity = self._index.maturities[0]
+ self.index_type = index_type
+ self.series = series
self.tenor = tenor
self.K_orig = np.array([attach, detach]) / 100
self.attach, self.detach = attach, detach
@@ -163,19 +168,50 @@ class DualCorrTranche():
def reset_pv(self):
self._original_pv = self.pv
- self._trade_date = self._value_date
+ self._trade_date = self.value_date
+ @property
def pnl(self):
if self._original_pv is None:
raise ValueError("original pv not set")
else:
# TODO: handle factor change
days_accrued = (self.value_date - self._trade_date).days / 360
- return self.notional * self._direction * (self.pv.bond_price - self._original_pv +
+ return self.notional * self._direction * -(self.pv - self._original_pv +
self.tranche_running * days_accrued)
- def shock(self, params=['pnl'], *, corr_shock, kwargs):
- pass
+ def __repr__(self):
+ s = ["{}{} {} Tranche".format(self.index_type, self.series, self.tenor),
+ "",
+ "{:<20}\t{:>15}".format("Value Date", ('{:%m/%d/%y}'.
+ format(self.value_date)))]
+ rows = [["Notional", self.notional * self._direction, "PV", self.pv *100],
+ ["Attach", self.attach, "Detach", self.detach],
+ ["Attach Corr", self.rho[0] * 100, "Detach Corr", self.rho[1] * 100]]
+ format_strings = [[None, '{:,.0f}', None, '{:,.4f}%'],
+ [None, '{:.2f}', None, '{:,.2f}'],
+ [None, '{:.3f}%', None, '{:.3f}%']]
+ s += build_table(rows, format_strings, "{:<20}{:>19}\t\t{:<19}{:>16}")
+ return "\n".join(s)
+
+ def shock(self, params=['pnl'], *, spread_shock, corr_shock, **kwargs):
+ orig_spread, orig_rho = self._index.spread()[0], self.rho
+ r = []
+ actual_params = [p for p in params if hasattr(self, p)]
+ for ss in spread_shock:
+ orig_curves = deepcopy(self._index.curves)
+ self._index.tweak_portfolio(ss, self.maturity)
+ for corrs in corr_shock:
+ #also need to map skew
+ self.rho = np.fmin(1, orig_rho * (1 + corrs))
+ r.append([getattr(self, p) for p in actual_params])
+ self._index.curves = orig_curves
+ self.rho = orig_rho
+ return pd.DataFrame.from_records(
+ r,
+ columns=actual_params,
+ index=pd.MultiIndex.from_product([spread_shock, corr_shock],
+ names=['spread_shock', 'corr_shock']))
class TrancheBasket(BasketIndex):