aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xpython/build_termination.py213
-rw-r--r--python/process_queue.py154
l---------python/terminate_swaption1
l---------python/terminate_tranche1
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