from utils.db import serenitas_pool, dbconn import datetime import pandas as pd from pandas.tseries.offsets import BDay from psycopg2.extras import execute_values from pyisda.date import default_accrual, previous_twentieth from analytics.index import CreditIndex from copy import copy def get_outstanding_positions(conn, trade_date, fcm, fund="SERCGMAST"): with conn.cursor() as c: c.execute( "SELECT security_id, notional, folder, nextredindexcode, currency, " "maturity, indexfactor " "FROM list_cds_positions_by_strat_fcm(%s, %s, %s) a " "JOIN index_version_markit " "ON a.security_id=index_version_markit.redindexcode " "WHERE nextredindexcode IS NOT NULL AND nextredindexcode !='2I65BRUV0'", (trade_date, fcm, fund), ) yield from c def default_adjustment(conn, company_id, seniority, end_date): with conn.cursor() as c: c.execute( "SELECT recovery, event_date, auction_date FROM defaulted WHERE id=%s " "AND seniority=%s", (company_id, seniority), ) recovery, event_date, auction_date = next(c) fee = 1 - recovery start_date = previous_twentieth(event_date) accrual_days, _ = default_accrual( auction_date, event_date, start_date, end_date, 1.0, 1.0 ) return accrual_days, fee PORTFOLIO = { "HYOPTDEL": "OPTIONS", "HEDGE_MBS": "MORTGAGES", "HYINX": "TRANCHE", "SER_IGCURVE": "CURVE", "HEDGE_CLO": "CLO", } def rebook(conn, trade_date, company_id, seniority, fcm, fund="SERCGMAST"): dawndb = dbconn("dawndb") upfront_settle_date = trade_date + 3 * BDay() effective_date = trade_date + datetime.timedelta(days=1) for r in get_outstanding_positions(dawndb, trade_date, fcm, fund): accrual_days, fee = default_adjustment(conn, company_id, seniority, r.maturity) index_new = CreditIndex( redcode=r.nextredindexcode, maturity=r.maturity, value_date=trade_date, notional=r.notional, ) adj = ( (fee - accrual_days * index_new.fixed_rate * 1e-4 / 360) * r.notional * (r.indexfactor - index_new.factor) ) index_new.mark() trade_new = { "fund": fund, "action": "NEW", "portfolio": PORTFOLIO[r.folder], "folder": r.folder, "cp_code": "CONTRA", "custodian": "NONE", "trade_date": trade_date, "effective_date": effective_date, "maturity": r.maturity, "currency": r.currency, "payment_rolldate": "Following", "notional": abs(r.notional), "fixed_rate": index_new.fixed_rate / 100, "day_count": "ACT/360", "frequency": 4, "protection": index_new.direction, "security_id": r.nextredindexcode, "security_desc": f"CDX {index_new.index_type} CDSI S{index_new.series} 5Y", "upfront": index_new.pv, "upfront_settle_date": upfront_settle_date, "swap_type": "CD_INDEX", "account_code": fcm, } trade_prev = copy(trade_new) trade_prev["protection"] = ( "Seller" if trade_new["protection"] == "Buyer" else "Buyer" ) trade_prev["upfront"] = adj - index_new.pv trade_prev["security_id"] = r.security_id sql_str = f"INSERT INTO cds({','.join(trade_new.keys())}) VALUES %s" with dawndb.cursor() as c: execute_values( c, sql_str, [tuple(trade_prev.values()), tuple(trade_new.values())] ) dawndb.commit() dawndb.close() def insert_newids(dawndb, d: datetime.date, df: pd.DataFrame): with dawndb.cursor() as c: c.execute( "INSERT INTO id_mapping ( " " SELECT %s, 'CDS', serenitas_id, new_id FROM ( " " SELECT * FROM unnest(%s, %s) AS t(globeop_id, new_id) " " LEFT JOIN id_mapping USING (globeop_id)) a" ")", (d, df.old_ids.tolist(), df.new_ids.to_list()), ) dawndb.commit() if __name__ == "__main__": conn = serenitas_pool.getconn() # PKD # rebook(datetime.date(2019, 1, 24), 101148) # WINDSSE # rebook(datetime.date(2019, 4, 8), 36806879) # WFT # rebook(datetime.date(2019, 7, 26), 103633, "WF") # rebook(datetime.date(2019, 7, 26), 103633, "BAML") # DF # rebook(datetime.date(2019, 12, 11), 154954, "Senior", "BAML") # MNI # rebook(datetime.date(2020, 3, 13), 100957, "Senior", "BAML") # rebook(datetime.date(2020, 3, 13), 100957, "Senior", "WF") # WLL # rebook(datetime.date(2020, 5, 7), 8240322, "Senior", "BAML") # rebook(datetime.date(2020, 5, 7), 8240322, "Senior", "WF") # rebook(conn, datetime.date(2020, 5, 7), 8240322, "Senior", "GS", "BOWDST") # FCA rebook(conn, datetime.date(2020, 5, 14), 100337, "Senior", "BAML") rebook(conn, datetime.date(2020, 5, 14), 100337, "Senior", "WF") rebook(conn, datetime.date(2020, 5, 14), 100337, "Senior", "GS", "BOWDST") serenitas_pool.putconn(conn)