diff options
Diffstat (limited to 'python/tranche_functions.py')
| -rw-r--r-- | python/tranche_functions.py | 58 |
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 |
