diff options
Diffstat (limited to 'python/build_termination.py')
| -rwxr-xr-x | python/build_termination.py | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/python/build_termination.py b/python/build_termination.py new file mode 100755 index 00000000..ba36ac41 --- /dev/null +++ b/python/build_termination.py @@ -0,0 +1,213 @@ +#! /usr/bin/python +import argparse +import csv +import datetime +from process_queue import build_termination, upload_file +from env import DAILY_DIR +from utils.db import dbconn +from io import StringIO + + +def build_termination( + base_dir, + dawndb, + dealid, + fee, + *, + termination_date=datetime.date.today(), + termination_amount=None, + termination_cp=None, + deal_type="CreditDefaultSwapDeal", +): + """ if termination_amount is None, assume full termination + if termination_cp is None assume termination, otherwise assignment + """ + if deal_type == "CreditDefaultSwapDeal": + table = "cds" + elif deal_type == "SwaptionDeal": + table = "swaptions" + else: + raise ValueError("Unkown deal_type: {deal_type}") + + with dawndb.cursor() as c: + c.execute( + "SELECT dealid, cp_code, notional, termination_amount, " + "globeop_id, currency " + f"FROM {table} where id=%s", + (dealid,), + ) + dealid, cp_code, notional, partial_amounts, globeopid, ccy = c.fetchone() + if partial_amounts is not None: + remaining_notional = notional - sum(partial_amounts) + else: + remaining_notional = notional + termination_amount = termination_amount or remaining_notional + if deal_type == "CreditDefaultSwapDeal": + c.execute( + f"UPDATE {table} " + "SET termination_amount=termination_amount||%s::float8, " + "termination_cp=termination_cp||%s::text, " + "termination_fee=termination_fee||%s::float8, " + "termination_date=termination_date||%s::date " + "WHERE dealid=%s", + ( + termination_amount, + termination_cp or cp_code, + fee, + termination_date, + dealid, + ), + ) + else: + c.execute( + f"UPDATE {table} " + "SET termination_amount=%s::float8, " + "termination_cp=%s::text, " + "termination_fee=%s::float8, " + "termination_date=%s::date " + "WHERE dealid=%s", + ( + termination_amount, + termination_cp or cp_code, + fee, + termination_date, + dealid, + ), + ) + dawndb.commit() + headers = [ + "DealType", + "DealId", + "Action", + "Client", + "SubAction", + "PartialTermination", + "TerminationAmount", + "TerminationDate", + "FeesPaid", + "FeesReceived", + "DealFunction", + "Reserved", + "ClientReference", + ] + if deal_type == "CreditDefaultSwapDeal": + headers += ["TradeDate", "EffectiveDate", "FirstCouponDate"] + else: + headers += ["Reserved"] * 3 + headers += ["FeePaymentDate", "SpecialInstructions"] + + if termination_cp is not None: + headers += ["AssignedCounterparty"] + else: + headers += ["Reserved"] + if deal_type == "CreditDefaultSwapDeal" and termination_cp is not None: + headers += [ + "AssignmentFee", + "AssignedFeeTradeDate", + "AssignedFeeValueDate", + "AssignedCustodian", + "AssignedCashAccount", + "Reserved", + "FeeCurrency", + ] + else: + headers += ["Reserved"] * 7 + headers += ["GoTradeId"] + if deal_type == "CreditDefaultSwapDeal": + headers += ["FeeComments", "ZeroOutInterestCashFlows"] + else: + headers += ["Reserved"] * 2 + headers += ["Reserved"] * 4 + if deal_type == "SwaptionDeal": + headers += ["Reserved"] * 2 + ["InMoney", "FeeCurrency"] + elif deal_type == "CreditDefaultSwapDeal": + if termination_cp is None: + headers += ["Reserved"] * 3 + else: + headers += ["AssignedDealFunction"] + ["Reserved"] * 2 + headers += ["InitialMargin", "InitialMarginCurrency"] + if termination_cp is None: + headers += ["Reserved"] * 4 + ["CreditEventOccured"] + d = { + "DealType": deal_type, + "GoTradeId": int(globeopid[3:9]), + "Action": "Update", + "Client": "Serenitas", + "SubAction": "Termination", + "PartialTermination": "Y" + if remaining_notional - termination_amount > 0 + else "N", + "TerminationAmount": termination_amount, + "TerminationDate": termination_date, + "FeesPaid": -fee if fee < 0 else None, + "FeesReceived": fee if fee > 0 else None, + "FeePaymentDate": (termination_date + 3 * bus_day).date(), + } + if "FeeCurrency" in headers: + d["FeeCurrency"] = ccy + if termination_cp is not None: + d["AssignedCounterparty"] = termination_cp + buf = StringIO() + csvwriter = csv.DictWriter(buf, headers) + csvwriter.writeheader() + csvwriter.writerow(d) + timestamp = datetime.datetime.now() + trade_type = f"{deal_type}A" if termination_cp is not None else f"{deal_type}T" + file_path = ( + base_dir + / str(timestamp.date()) + / f"Serenitas.ALL.{timestamp:%Y%m%d.%H%M%S}.{trade_type}.csv" + ) + file_path.write_bytes(buf.getvalue().encode()) + return file_path + + +if __name__ == "__main__": + parser = argparse.ArgumentParser( + description="helper script to terminate or assign a trade" + ) + parser.add_argument("dealid", help="Serenitas id", type=int) + parser.add_argument( + "fee", help="termination fee ( >0 we receive money)", type=float + ) + parser.add_argument( + "--date", + "-d", + help="termination date, default to today's date", + type=datetime.date.fromisoformat, + default=datetime.date.today(), + ) + parser.add_argument( + "--amount", + "-a", + help="termination amount, if missing full termination", + default=None, + required=False, + ) + parser.add_argument( + "--counterparty", + "-c", + help="termination counterparty, if missing, original counterparty is used (termination)", + default=None, + required=False, + ) + args = parser.parse_args() + dawndb = dbconn("dawndb") + if "tranche" in __file__: + deal_type = "CreditDefaultSwapDeal" + elif "swaption" in __file__: + deal_type = "SwaptionDeal" + else: + raise RuntimeError("Incorrect deal type") + + p = build_termination( + DAILY_DIR, + dawndb, + args.dealid, + args.fee, + termination_date=args.date, + termination_cp=args.counterparty, + termination_amount=args.amount, + deal_type=deal_type, + ) + upload_file(p) |
