aboutsummaryrefslogtreecommitdiffstats
path: root/python/tranche_functions.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/tranche_functions.py')
-rw-r--r--python/tranche_functions.py58
1 files changed, 49 insertions, 9 deletions
diff --git a/python/tranche_functions.py b/python/tranche_functions.py
index 6e095ed5..8cfbb116 100644
--- a/python/tranche_functions.py
+++ b/python/tranche_functions.py
@@ -1,6 +1,9 @@
import numpy as np
from ctypes import *
-import pdb
+from quantlib.time.schedule import Schedule, CDS
+from quantlib.time.api import Actual360, Period, UnitedStates, Following, today
+from quantlib.util.converter import qldate_to_pydate, pydate_to_qldate
+import pandas as pd
libloss = np.ctypeslib.load_library("lossdistrib", "/home/share/CorpCDOs/code/R")
libloss.fitprob.restype = None
@@ -66,20 +69,27 @@ def BClossdist(defaultprob, issuerweights, recov, rho, Z, w, Ngrid = 101, defaul
byref(c_int(Ngrid)), byref(c_int(defaultflag)), L, R)
return L, R
+def adjust_attachments(K, losstodate, factor):
+ """
+ computes the attachments adjusted for losses
+ on current notional
+ """
+ return np.minimum(np.maximum((K-losstodate)/factor, 0), 1)
+
def trancheloss(L, K1, K2):
- np.maximum(L - K1, 0) - np.maximum(L - K2, 0)
+ return np.maximum(L - K1, 0) - np.maximum(L - K2, 0)
def trancherecov(R, K1, K2):
- np.maximum(R - 1 + K2, 0) - np.maximum(R - 1 + K1, 0)
+ return np.maximum(R - 1 + K2, 0) - np.maximum(R - 1 + K1, 0)
def tranche_cl(L, R, cs, K1, K2, scaled = False):
if(K1 == K2):
return 0
else:
support = np.linspace(0, 1, L.shape[0])
- size = K2 - K1 - np.dot(trancheloss(support, K1, K2), L) -
- np.dot(trancherecov(support, K1, K2), R)
- sizeadj = 0.5 * (size + np.hstack([K2-K1], size[:-1]))
+ size = K2 - K1 - np.dot(trancheloss(support, K1, K2), L) - \
+ np.dot(trancherecov(support, K1, K2), R)
+ sizeadj = 0.5 * (size + np.hstack((K2-K1, size[:-1])))
if scaled:
return 1/(K2-K1) * np.dot(sizeadj * cs["coupons"], cs["df"])
else:
@@ -91,11 +101,41 @@ def tranche_pl(L, cs, K1, K2, scaled=False):
else:
support = np.linspace(0, 1, L.shape[0])
cf = K2 - K1 - np.dot(trancheloss(support, K1, K2), L)
- cf = np.hstack([K2-K1], cf)
+ cf = np.hstack((K2-K1, cf))
if scaled:
return 1/(K2-K1) * np.dot(np.diff(cf), cs["df"])
else:
return np.dot(np.diff(cf), cs["df"])
-def tranche_pv(L, R, cs, K2, K2):
- tranche_pl(L, cs, K1, K2) + tranche_cl(L, R, cs, K2, K2)
+def tranche_pv(L, R, cs, K1, K2):
+ return tranche_pl(L, cs, K1, K2) + tranche_cl(L, R, cs, K2, K2)
+
+def creditSchedule(tradedate, tenor, coupon, yc, enddate = None):
+ tradedate = pydate_to_qldate(tradedate)
+ start = tradedate - Period('4Mo')
+ enddate = pydate_to_qldate(enddate)
+ if enddate is None:
+ enddate = tradedate + Period(tenor)
+ cal = UnitedStates()
+ DC = Actual360()
+ sched = Schedule(start, enddate, Period('3Mo'), cal, date_generation_rule=CDS)
+ prevpaydate = sched.previous_date(tradedate)
+ sched = [d for d in sched if d>=prevpaydate]
+ df = [yc.discount(d) for d in sched if d > tradedate]
+
+ dates = pd.to_datetime([str(d) for d in sched if d > tradedate], "%m/%d/%Y")
+ coupons = np.diff([DC.year_fraction(prevpaydate, d) * coupon for d in sched])
+
+ return pd.DataFrame({"df":df, "coupons":coupons}, dates)
+
+def cdsAccrued(tradedate, coupon):
+ tradedate = pydate_to_qldate(tradedate)
+ start = tradedate - Period('3Mo')
+ end = tradedate + Period('3Mo')
+
+ start_protection = tradedate + 1
+ DC = Actual360()
+ cal = UnitedStates()
+ sched = Schedule(start, end, Period('3Mo'), cal, date_generation_rule=CDS)
+ prevpaydate = sched.previous_date(tradedate)
+ return DC.year_fraction(prevpaydate, start_protection) * coupon