aboutsummaryrefslogtreecommitdiffstats
path: root/python
diff options
context:
space:
mode:
Diffstat (limited to 'python')
-rw-r--r--python/analytics/tranche_basket.py40
1 files changed, 23 insertions, 17 deletions
diff --git a/python/analytics/tranche_basket.py b/python/analytics/tranche_basket.py
index eeba7495..01261808 100644
--- a/python/analytics/tranche_basket.py
+++ b/python/analytics/tranche_basket.py
@@ -53,8 +53,7 @@ class DualCorrTranche():
self._Z, self._w = GHquad(self._Ngh)
self.rho = [corr_attach, corr_detach]
self.tranche_running = tranche_running
- self._direction = -1. if notional > 0 else 1.
- self.notional = abs(notional)
+ self.notional = notional
self.cs = credit_schedule(value_date, None,
1., self._index.yc, self._index.maturities[0])
self._accrued = cds_accrued(value_date, tranche_running * 1e-4)
@@ -64,8 +63,7 @@ class DualCorrTranche():
def _default_prob(self, epsilon=0.):
return 1 - self._index.survival_matrix(
- self.cs.index.values.astype('M8[D]').
- view('int') + 134774, epsilon)[0]
+ self.cs.index.to_numpy("M8[D]").view("int") + 134774, epsilon)[0]
def __hash__(self):
def aux(v):
@@ -96,7 +94,7 @@ class DualCorrTranche():
instance.direction = rec['protection']
if rec['index_ref'] is not None:
instance._index.tweak(rec['index_ref'])
-
+ instance.reset_pv()
return instance
@property
@@ -160,7 +158,7 @@ class DualCorrTranche():
@property
def direction(self):
- if self._direction == -1.:
+ if self.notional > 0.:
return "Buyer"
else:
return "Seller"
@@ -168,16 +166,20 @@ class DualCorrTranche():
@direction.setter
def direction(self, d):
if d == "Buyer":
- self._direction = -1.
+ self.notional = abs(self.notional)
elif d == "Seller":
- self._direction = 1.
+ self.notional = -abs(self.notional)
else:
raise ValueError("Direction needs to be either 'Buyer' or 'Seller'")
@property
def pv(self):
pl, cl = self._pv()
- return float(-pl - cl + self._accrued)
+ return -self.notional * (pl + cl)
+
+ @property
+ def clean_pv(self):
+ return self.pv + self.notional * self._accrued
def _pv(self, epsilon=0.):
""" computes coupon leg, protection leg and bond price.
@@ -203,7 +205,9 @@ class DualCorrTranche():
@property
def upfront(self):
- return self._direction * self.notional * (self.pv - self._accrued)
+ """ returns upfront in points"""
+ pl, cl = self._pv()
+ return -100 * (pl + cl - self._accrued)
@upfront.setter
def upfront(self, upf):
@@ -214,18 +218,18 @@ class DualCorrTranche():
print(r.converged)
def reset_pv(self):
- self._original_pv = self.pv
+ self._original_clean_pv = self.clean_pv
self._trade_date = self.value_date
@property
def pnl(self):
- if self._original_pv is None:
+ if self._original_clean_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 + self._original_pv +
- self.tranche_running * 1e-4 * days_accrued)
+ return (self.clean_pv - self._original_clean_pv +
+ self.tranche_running * 1e-4 * days_accrued)
def __repr__(self):
s = [f"{self.index_type}{self.series} {self.tenor} Tranche",
@@ -282,7 +286,10 @@ class DualCorrTranche():
self.rho = []
for tranche_id, corr in c:
self.rho.append(corr)
- self._tranche_id = tranche_id
+ try:
+ self._tranche_id = tranche_id
+ except UnboundLocalError:
+ pass
conn.close()
@property
@@ -307,8 +314,7 @@ class DualCorrTranche():
calc = self._greek_calc()
factor = self.tranche_factor / self._index.factor
return (calc['bp'][1] - calc['bp'][2]) / \
- (calc['indexbp'][1] - calc['indexbp'][2]) * \
- factor * -self._direction
+ (calc['indexbp'][1] - calc['indexbp'][2]) * factor
@property
def gamma(self):