aboutsummaryrefslogtreecommitdiffstats
path: root/python
diff options
context:
space:
mode:
Diffstat (limited to 'python')
-rw-r--r--python/pnl_explain.py65
1 files changed, 59 insertions, 6 deletions
diff --git a/python/pnl_explain.py b/python/pnl_explain.py
index 2c93cbd7..73c76fe6 100644
--- a/python/pnl_explain.py
+++ b/python/pnl_explain.py
@@ -2,9 +2,12 @@ import pandas as pd
from functools import reduce
from position import get_list
from sqlalchemy import create_engine
+from dates import bus_day, imm_dates
-def pnl_explain(engine, identifier, start_date = None, end_date = None):
+def pnl_explain(identifier, start_date = None, end_date = None,
+ uri = 'postgresql://dawn_user@debian/dawndb'):
""" if start_date is None, pnl since inception"""
+ engine = create_engine(uri)
trades = pd.read_sql_query("SELECT * FROM bonds where identifier=%s", engine,
params=(identifier,), parse_dates=['trade_date', 'settle_date'],
index_col=['settle_date'])
@@ -24,7 +27,7 @@ def pnl_explain(engine, identifier, start_date = None, end_date = None):
start_date = trades.index.min()
if end_date is None:
end_date = pd.datetime.today()
- dates = pd.bdate_range(start_date, end_date)
+ dates = pd.date_range(start_date, end_date, freq = bus_day)
keys1 = ['price','factor', 'coupon', 'prev_cpn_date']
df[keys1] = df[keys1].fillna(method='ffill')
keys2 = ['losses', 'principal','interest', 'faceamount','accrued_payment', 'principal_payment']
@@ -53,8 +56,58 @@ def pnl_explain_list(engine, id_list, start_date = None, end_date = None):
return reduce(lambda x,y: x.add(y, fill_value=0),
(pnl_explain(engine, identifier, start_date, end_date) for identifier in id_list))
+def cds_explain(engine, index, series, tenor, attach = None, detach = None,
+ start_date = None, end_date = None):
+ factors = pd.read_sql_query("SELECT * FROM index_desc WHERE index=%s AND series=%s AND tenor=%s "\
+ "ORDER BY lastdate",
+ engine, parse_dates=['lastdate'],
+ index_col='lastdate', params = (index, series, tenor))
+ if attach is None:
+ quotes = pd.read_sql_query("SELECT * from index_quotes WHERE index=%s AND series=%s AND tenor=%s " \
+ "ORDER BY date",
+ engine, parse_dates=['date'],
+ index_col='date', params = (index, series, tenor))
+ else:
+ quotes = pd.read_sql_query("SELECT quotedate, upfront_mid AS closeprice, tranche_spread " \
+ "FROM markit_tranche_quotes JOIN index_version " \
+ "USING (basketid) WHERE index=%s AND series=%s " \
+ "AND tenor=%s AND attach=%s AND detach=%s " \
+ "ORDER by quotedate",
+ engine, parse_dates=['quotedate'], index_col='quotedate',
+ params = (index, series, tenor, attach, detach))
+ if start_date is None:
+ start_date = quotes.index.min()
+ if end_date is None:
+ end_date = pd.datetime.today()
+ coupon = 0.01
+ dates = pd.date_range(start_date, end_date, freq = bus_day)
+ yearfrac = imm_dates(start_date, end_date)
+ yearfrac = yearfrac.to_series().reindex(dates, method='ffill')
+ yearfrac = yearfrac.index-yearfrac
+ yearfrac = (yearfrac.dt.days+1)/360
+ yearfrac.name = 'yearfrac'
+ quotes = quotes.reindex(dates, method='ffill')
+ recovery = -factors.indexfactor.diff()-factors.cumulativeloss.diff()
+ recovery.name = 'recovery'
+ recovery = recovery.shift(-1)/100
+ recovery = recovery.reindex(dates, fill_value=0).shift()
+ df = (quotes.
+ join(factors[['indexfactor']], how='left').
+ join(recovery).join(yearfrac))
+ df.indexfactor = df.indexfactor.bfill()/100
+ df.loc[df.indexfactor.isnull(), 'indexfactor'] = factors.indexfactor.iat[-1]/100
+ df['unrealized_accrued'] = df.yearfrac*coupon*df.indexfactor
+ df['accrued'] = df.unrealized_accrued.diff()
+ df['realized_accrued'] = -df.accrued.where(df.accrued<0, 0)
+ df.accrued = df.accrued.where(df.accrued>0, df.unrealized_accrued)
+ df.loc[df.realized_accrued>0, 'realized_accrued'] += df.loc[df.realized_accrued>0, 'accrued']
+ df['unrealized_pnl'] = df.closeprice.diff() * df.indexfactor.shift()/100
+ df['realized_pnl'] = df.closeprice/100*df.indexfactor.diff()+df.recovery
+ return df
+
if __name__=="__main__":
- engine = create_engine("postgresql://dawn_user@debian/dawndb")
- workdate = pd.datetime.today()
- clo_list = get_list(engine, workdate, 'Subprime')
- df = pnl_explain_list(engine, clo_list.identifier.tolist(), '2015-10-30', '2015-11-30')
+ # workdate = pd.datetime.today()
+ # clo_list = get_list(workdate, 'Subprime')
+ # df = pnl_explain_list(engine, clo_list.identifier.tolist(), '2015-10-30', '2015-11-30')
+ engine = create_engine("postgresql://serenitas_user@debian/serenitasdb")
+ df = cds_explain(engine, 'IG', 9, '10yr')