aboutsummaryrefslogtreecommitdiffstats
path: root/python/citco_monitor.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/citco_monitor.py')
-rw-r--r--python/citco_monitor.py68
1 files changed, 68 insertions, 0 deletions
diff --git a/python/citco_monitor.py b/python/citco_monitor.py
index 82bdb3e0..c08a9854 100644
--- a/python/citco_monitor.py
+++ b/python/citco_monitor.py
@@ -3,6 +3,7 @@ from exchangelib import HTMLBody
from serenitas.analytics.dates import prev_business_day
from serenitas.utils.db import dbconn
+from serenitas.ops.dataclass_mapping import _citco_cp_isda
from report_ops.utils import check_cleared_cds, Monitor
from report_ops.misc import _recon_recipients, _cc_recipients
@@ -45,6 +46,47 @@ class BondFactorMonitor(
)
+class SwaptionExerciseNotification(
+ Monitor,
+ headers=(
+ "swaption_fix_id",
+ "security_desc",
+ "fund",
+ "expiration_date",
+ "strike",
+ "clearing_agent",
+ "putcall",
+ "notional",
+ "swaption_expiration_status",
+ "exercised_fix_id",
+ ),
+ num_format=[("{0:,.4f}", 4), ("{0:,.2f}", 7)],
+):
+ @classmethod
+ def email(cls, fund, expiration_date):
+ if not cls._staging_queue:
+ return
+ cls._em.send_email(
+ f"Citco Exercise Notification: {fund} Expiration: {expiration_date}",
+ HTMLBody(
+ f"""
+<html>
+ <head>
+ <style>
+ table, th, td {{ border: 1px solid black; border-collapse: collapse;}}
+ th, td {{ padding: 5px; }}
+ </style>
+ </head>
+ <body>
+ Hello,<br><br>We would like to notify you of the exercised/expired swaptions:<br><br>{cls.to_tabulate()}
+ </body>
+</html>"""
+ ),
+ to_recipients=_recon_recipients[fund],
+ cc_recipients=_cc_recipients[fund],
+ )
+
+
def check_bond_factors(date, fund, conn):
with conn.cursor() as c:
c.execute(
@@ -57,6 +99,31 @@ def check_bond_factors(date, fund, conn):
BondFactorMonitor.email(fund)
+def notify_swaption_exercise(expiration_date, fund, conn):
+ with conn.cursor() as c:
+ c.execute(
+ "SELECT * FROM get_exercised_swaptions(%s, %s)",
+ (
+ expiration_date,
+ fund,
+ ),
+ )
+ for row in c:
+ d = row._asdict()
+ if d["security_desc"].startswith("CDX IG"):
+ d["strike"] /= 1000
+ d["putcall"] = "PUT" if d["option_type"] == "PAYER" else "CALL"
+ d["notional"] = d["notional"] * (1 if d["buysell"] else -1)
+ d["swaption_fix_id"] = d["dealid"]
+ d["exercised_fix_id"] = d["new_trade"]
+ d["clearing_agent"] = _citco_cp_isda[d["cp_code"]]
+ d["swaption_expiration_status"] = (
+ "EXERCISED" if d["new_trade"] else "EXPIRED"
+ )
+ SwaptionExerciseNotification.stage(d)
+ SwaptionExerciseNotification.email(fund, expiration_date)
+
+
if __name__ == "__main__":
import argparse
@@ -73,3 +140,4 @@ if __name__ == "__main__":
for fund in ("ISOSEL",):
check_cleared_cds(args.cob, fund, conn)
check_bond_factors(args.cob, fund, conn)
+ notify_swaption_exercise(args.cob, fund, conn)