diff options
Diffstat (limited to 'python/citco_monitor.py')
| -rw-r--r-- | python/citco_monitor.py | 68 |
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) |
