diff options
| -rwxr-xr-x | python/build_termination.py | 213 | ||||
| -rw-r--r-- | python/process_queue.py | 154 | ||||
| l--------- | python/terminate_swaption | 1 | ||||
| l--------- | python/terminate_tranche | 1 |
4 files changed, 215 insertions, 154 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) diff --git a/python/process_queue.py b/python/process_queue.py index cf1ff370..25480b47 100644 --- a/python/process_queue.py +++ b/python/process_queue.py @@ -324,160 +324,6 @@ def rename_keys(d, mapping): d[v] = d.pop(k) -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 - - def build_line(obj, trade_type="bond"): obj["Client"] = "Serenitas" obj["State"] = "Valid" diff --git a/python/terminate_swaption b/python/terminate_swaption new file mode 120000 index 00000000..27d7aacd --- /dev/null +++ b/python/terminate_swaption @@ -0,0 +1 @@ +build_termination.py
\ No newline at end of file diff --git a/python/terminate_tranche b/python/terminate_tranche new file mode 120000 index 00000000..27d7aacd --- /dev/null +++ b/python/terminate_tranche @@ -0,0 +1 @@ +build_termination.py
\ No newline at end of file |
