import csv
import datetime
import json
import logging
import os
import os.path
import psycopg2
import re
import sys
import yaml
sys.path.append('.')
from csv import reader
from common import root
from db import dbconn
logger = logging.getLogger(__name__)
pattern1 = re.compile("REINVEST\[\w+::REINV_TBA(\d)\]\[DEAL,(\d+)\]=.*$")
# reinv end date
pattern2 = re.compile("(STANDARD_VAR\[)\w+(::#REINV_END,\d+\]=)(\d.*$)")
# reinvprices 1
pattern3 = re.compile("STANDARD_VAR\[\w+::#PRICE100_TBA(\d),(\d+)\]=")
pattern5 = re.compile("STANDARD_VAR\[\w+::#REINVPCT_TBA(\d),(\d+)\]=")
pattern7 = re.compile("KINGS3")
pattern8 = re.compile("(#COLLATREINV_REINV_PCT_EXT\[)\w+(::\*\]\[DEAL,\d+\])=100")
pattern9 = re.compile("(?PSEVERITY\[\w+,\d+\]=)mkt\(70\)")
# we use 84 so that it's both dividable by 2 and 3
global_reinvfloatpercentage = 84
global_reinvfixedpercentage = 16
def get_reinv_assets(conn, dealname, workdate):
sqlstr = 'select * from et_historicaldealinfo(%s, %s) where ReinvFlag IS TRUE'
d = {}
with conn.cursor() as c:
c.execute(sqlstr, (dealname, workdate))
for line in c:
d[line['issuername']] = line['fixedorfloat']
conn.commit()
return d
def get_recovery(conn, dealname, workdate, defaultrecovery = 50):
""" compute average price of defaulted assets """
sqlstr = "select sum(coalesce(price, %s) * currentbalance)/sum(currentbalance) " + \
"from et_aggdealinfo_historical(%s, %s) where defaultedflag is True"
with conn.cursor() as c:
c.execute(sqlstr, (defaultrecovery, dealname, workdate))
try:
recovery, = c.fetchone()
except TypeError:
recovery = defaultrecovery
finally:
if not recovery:
recovery = defaultrecovery
conn.commit()
return float(recovery)
def get_reinvenddate(conn, dealname):
sqlstr = 'SELECT reinv_end_date from deal_indicative where dealname=%s'
with conn.cursor() as c:
c.execute(sqlstr, (dealname,))
reinvenddate, = c.fetchone()
conn.commit()
if reinvenddate:
return reinvenddate.strftime("%Y%m%d")
else:
raise Exception("missing reinvestment end date")
def generate_scenarios(workdate, dealname, conn):
prometheus = os.path.join(root, "Scenarios", "prometheus.sss")
n_scenarios = 100
basedir = os.path.join(root, "Scenarios", "Intex curves_" + workdate)
defaultedprice = get_recovery(conn, dealname, workdate)
replace = "\g{0:.3f}".format(defaultedprice)
try:
with open(os.path.join(basedir, "csv", dealname + ".config")) as fh:
config = yaml.load(fh)
except IOError:
logger.error("{0}: config file doesn't exist".format(dealname))
return
reinvflag = config['reinvflag']
if reinvflag:
reinvenddate = get_reinvenddate(conn, dealname)
reinv_assets = get_reinv_assets(conn, dealname, workdate)
n_float_assets = len([v for v in reinv_assets.values() if v == 'FLOAT'])
n_fixed_assets = len([v for v in reinv_assets.values() if v == 'FIXED'])
rollingmat = config['rollingmat']
if n_fixed_assets == 0:
reinvfixedpercentage = 0
else:
reinvfixedpercentage = global_reinvfixedpercentage / n_fixed_assets
if n_float_assets > 0:
reinvfloatpercentage = (100 - n_fixed_assets * reinvfixedpercentage)/n_float_assets
try:
with open(os.path.join(basedir, "csv", dealname + "-reinvprices.csv"), "r") as fh:
dr = csv.DictReader(fh)
reinvprices = {f: [] for f in dr.fieldnames}
for line in dr:
for f in dr.fieldnames:
reinvprices[f].append("{0:.3f}".format(float(line[f])))
except IOError:
reinvflag = False
sssfile = os.path.join(basedir, "sss", dealname + ".sss")
if not os.path.exists(os.path.join(basedir, "sss")):
os.makedirs(os.path.join(basedir, "sss"))
cdrscenarios = os.path.join(basedir, "csv", dealname + "-cdr.csv")
recoveryscenarios = os.path.join(basedir, "csv", dealname + "-recovery.csv")
fhsss = open(sssfile, "w")
fhcdr = open(cdrscenarios, "r")
fhrecovery = open(recoveryscenarios, "r")
csvcdr = reader(fhcdr)
csvrecovery = reader(fhrecovery)
cdrline = next(csvcdr)
cdrline = "\t".join(["{0:.3f}".format(float(cdr)) for cdr in cdrline])
recoveryline = next(csvrecovery)
recoveryline = "\t".join(["{0:.3f}".format(float(recovery)) for recovery in recoveryline])
i=1
with open(prometheus) as fh:
for line in fh:
line = line.rstrip()
if "DEAL_NAME" in line:
newline = "DEAL_NAME=" + dealname.upper() + "\r\n"
fhsss.write(newline)
continue
if not reinvflag and pattern8.match(line):
line = re.sub(pattern8, r"\1{0}\2=0".format(dealname.upper()), line)
fhsss.write(line + "\r\n")
continue
if not reinvflag and "DO_REINV" in line:
fhsss.write("DO_REINV=0" + "\r\n")
continue
m = pattern1.match(line)
if reinvflag and m:
reinv_number, scen_number = m.groups()
key = "REINV_TBA" + reinv_number
if key in reinv_assets:
if reinv_assets[key] == "FLOAT":
coupon = 4
elif reinv_assets[key] == "FIXED":
coupon = 7
line = "REINVEST[{0}::REINV_TBA{1}][DEAL,{2}]=".format(dealname.upper(),
reinv_number,
scen_number)
line += "COUP_SPR={0}|AMORT=Bullet|USE_REINVEST_PIP=1|MAT_DATE={1}|".format(coupon,
rollingmat)
fhsss.write(line + "\r\n")
continue
if reinvflag and pattern2.match(line):
line = re.sub(pattern2, r"\1{0}\2{1}", line).format(dealname.upper(), reinvenddate)
fhsss.write(line + "\r\n")
continue
m = pattern3.match(line)
if reinvflag and m:
reinv_number, scen_number = m.groups()
if dealname=="litpt3" and reinv_number=="1":
line = "STANDARD_VAR[LITPT3::#REINVLOANP100,{0}]".format(scen_number) + \
"={0}".format(" ".join(reinvprices["REINV_TBA1"]))
fhsss.write(line + "\r\n")
continue
reinv_name = "REINV_TBA" + reinv_number
if reinv_name in reinvprices:
line = \
"STANDARD_VAR[{0}::#PRICE100_TBA{1},{2}]={3}".format(dealname.upper(),
reinv_number,
scen_number,
" ".join(reinvprices[reinv_name]))
fhsss.write(line + "\r\n")
continue
m = pattern5.match(line)
if reinvflag and m:
reinv_number, scen_number = m.groups()
reinv_name = "REINV_TBA" + reinv_number
if reinv_number=="1":
if dealname=="litpt3":
line = "STANDARD_VAR[LITPT3::#LOANREINVPCT,{0}]=100".format(scen_number)
fhsss.write(line + "\r\n")
continue
if dealname=="flags4":
line = "STANDARD_VAR[FLAGS4::#PCT100_TBA1,{0}]=100".format(scen_number)
fhsss.write(line + "\r\n")
continue
if reinv_name in reinv_assets:
if reinv_assets[reinv_name] == 'FIXED':
line = "STANDARD_VAR[{0}::#REINVPCT_TBA{1},{2}]={3}".format(dealname.upper(),
reinv_number,
scen_number,
reinvfixedpercentage)
elif reinv_assets[reinv_name] == 'FLOAT':
line = "STANDARD_VAR[{0}::#REINVPCT_TBA{1},{2}]={3}".format(dealname.upper(),
reinv_number,
scen_number,
reinvfloatpercentage)
fhsss.write(line + "\r\n")
continue
if pattern7.search(line):
line = re.sub(pattern7, dealname.upper(), line)
fhsss.write(line + "\r\n")
continue
if "LOSS_RATE[DEAL,{0}]".format(i) in line:
newcdrline = "LOSS_RATE[DEAL,{0}]=".format(i) + cdrline
fhsss.write(newcdrline + "\r\n")
continue
if "LOSS_SEVERITY[DEAL,{0}]".format(i) in line:
newrecoveryline = "LOSS_SEVERITY[DEAL,{0}]=".format(i) + recoveryline
fhsss.write(newrecoveryline + "\r\n")
i = i + 1
if i <= n_scenarios:
cdrline = next(csvcdr)
cdrline = "\t".join(["{0:.3f}".format(float(cdr)) for cdr in cdrline]) + "\r\n"
recoveryline = next(csvrecovery)
recoveryline = "\t".join(["{0:.3f}".format(float(recovery)) \
for recovery in recoveryline]) + "\r\n"
continue
if "LOSS_NONPERF_SEVERITY" in line:
line = re.sub(pattern9, replace, line)
fhsss.write(line + "\r\n")
fhsss.close()
fhrecovery.close()
fhcdr.close()
logger.info("generated scenarios for: {0}".format(dealname))
if __name__ == "__main__":
if len(sys.argv) > 1:
workdate = sys.argv[1]
else:
workdate = str(datetime.date.today())
if len(sys.argv) > 2:
dealnames = sys.argv[2:]
else:
dealnames = [d.split(".")[0] for d in
os.listdir(os.path.join(root, "Scenarios",
"Intex curves_" + workdate, "csv"))
if "RData" in d]
ET = dbconn('etdb')
for dealname in dealnames:
generate_scenarios(workdate, dealname, ET)
ET.close()