diff options
Diffstat (limited to 'python')
| -rw-r--r-- | python/reallocate_iam.py | 199 | ||||
| -rw-r--r-- | python/report_ops/cash.py | 18 |
2 files changed, 87 insertions, 130 deletions
diff --git a/python/reallocate_iam.py b/python/reallocate_iam.py index cbbc5c43..07f827db 100644 --- a/python/reallocate_iam.py +++ b/python/reallocate_iam.py @@ -1,11 +1,11 @@ from serenitas.utils.misc import rename_keys import datetime from collections import defaultdict -from psycopg2.errors import UniqueViolation -from serenitas.analytics.dates import bus_day from serenitas.ops.funds import Service +from report_ops.cash import IAMDeal +from serenitas.analytics.dates import prev_business_day -_iam_brokers = { +_bowdst_iam_cp = { "BAML_ISDA": "BOANNY", "CS": "CSITLN", "GS": "GOLINY", @@ -14,138 +14,92 @@ _iam_brokers = { "JPM": "JPCBNY", "GS_FCM": "GOLDNY", } -_custodian = {"GOLDNY": "GS"} -_cash_account = {"GOLDNY": "057363418ICE-CDS"} +_serenitas_iam_cp = { + "BAML_ISDA": "BAMSNY", + "CS": "CSFBBO", + "GS": "GOLDNY", + "BNP": "BNPBNY", + "MS": "MSCSNY", + "JPM": "JPCBNY", + "GS_FCM": "GOLDNY", +} -def iam_serialize(obj, action, trade_date): - rename_keys( - obj, - { - "dealid": "Deal Id", - "counterparty": "Counterparty", - "currency": "Currency", - "start_money": "StartMoney", - "trade_date": "Trade Date", - }, - ) - deal_fields = { - "Deal Type": "IamDeal", - "Client": "HEDGEMARK", - "Fund": "BOS_PAT_BOWDOIN", - "Custodian": _custodian.get(obj["Counterparty"], "BNY"), - "Cash Account": _cash_account.get(obj["Counterparty"], 751254), - "State": "Valid", - "SettlementDate": obj["Trade Date"], - "Basis": "ACT/360", - "MarginType": "Variation", - "DealFunction": "OTC", - "Folder": "M_CSH_CASH" if obj["strategy"] == "CSH_CASH" else obj["strategy"], - "Action": action, - "TransactionIndicator": "DEPOSIT" if obj["StartMoney"] > 0 else "LOAN", - "ExpirationDate": trade_date - if action == "UPDATE" - else None, # We are updating old IAMDeals to expire - "CallNoticeIndicator": "24H" if action == "NEW" else None, # This is a new IAM - } - obj["StartMoney"] = abs(obj["StartMoney"]) - obj.update(deal_fields) - return obj +def get_counterparty(fund, iam_broker): + match fund: + case "SERCGMAST": + return _serenitas_iam_cp[iam_broker] + case "BOWDST": + return _bowdst_iam_cp[iam_broker] -def gen_offset(totals, trade_date): - offsets = [ - (trade_date, "NEW", "CSH_CASH", broker, None, -amount, "USD", True) - for broker, amount in totals.items() - ] - return offsets +def get_custodian_account(fund, iam_broker): + match fund, iam_broker: + case ("SERCGMAST", "WF_FCM"): + return ("WELLSFCM", "WFNSCLMFCM") + case ("SERCGMAST", "BAML_FCM"): + return ("BOMLCM", "V0NSCLMFCM") + case ("BOWDST", "GS_FCM"): + return ("GS", "057363418ICE-CDS") + case ("SERCGMAST", _): + return ("UMB", "159260.1") + case ("BOWDST", _): + return ("BNY", "751254") -def gen_strat_alloc(conn, trade_date): - new_iam = [] - totals = defaultdict(int) # Need to figure out how much to offset +def globeop_mapping(fund, iam_broker): + (custodian, cash_account) = get_custodian_account(fund, iam_broker) + return { + "custodian": custodian, + "cash_account": cash_account, + "counterparty": get_counterparty(fund, iam_broker), + } + + +def gen_new_iam_deals(fund, cob, conn): with conn.cursor() as c: - strategy_allocation = ( - "SELECT broker, amount, currency, strategy FROM (SELECT *, rank() " - "OVER(PARTITION BY broker,fund ORDER BY date desc) FROM strategy_im si " - "WHERE fund = 'BOWDST' AND date<=%s ORDER BY date DESC) test WHERE RANK=1 and abs(amount) >= .01;" + c.execute( + "SELECT * FROM list_iam(%s, %s)", + ( + cob, + fund, + ), ) - c.execute(strategy_allocation, (trade_date,)) for row in c: - new_iam.append( - ( - trade_date, - "NEW", - row.strategy, - _iam_brokers[row.broker], - None, - row.amount, - row.currency, - False, - ) - ) - if row.broker != "GS_FCM": # HM doesn't book FCM, no need to offset - totals[_iam_brokers[row.broker]] += row.amount - new_iam += gen_offset(totals, trade_date) - return new_iam + d = row._asdict() | globeop_mapping(fund, row.broker) + yield IAMDeal.from_dict(**d) -def process_trades(conn, trade_date): - # We will be grabbing the IAM deals from the DB for the new trades and for the updated trades - deals = [] - actions = [ - ( - "NEW", - "UPDATE iam_tickets set uploaded=True where maturity is null and trade_date =%s " - "and action='NEW' and not uploaded returning *", - (trade_date,), - ), - ( - "UPDATE", - "UPDATE iam_tickets set maturity=%s where trade_date != %s and maturity is null and action='NEW' returning *", - (trade_date, trade_date), - ), - ] - for action, query, params in actions: - with conn.cursor() as c: - c.execute(query, params) - for row in c: - deals.append(iam_serialize(row._asdict(), action, trade_date)) - return deals - - -def gen_iam_deals(conn, trade_date): - new_iam = gen_strat_alloc(conn, trade_date) - iam_deals = [] +def gen_new_iam_offsets(fund, cob, conn): with conn.cursor() as c: - insert_query = ( - "INSERT INTO iam_tickets(trade_date, action, strategy, counterparty, maturity, start_money, currency, booked_offset) " - "VALUES (%s, %s, %s, %s, %s, %s, %s, %s)" + c.execute( + "SELECT trade_date, broker, currency, fund, sum(start_money) AS start_money " + "FROM list_iam(%s, %s) GROUP BY (trade_date, broker, currency, fund);", + ( + cob, + fund, + ), ) - try: - c.executemany(insert_query, new_iam) - except UniqueViolation: - # We already uploaded the IAM tickets today in that case, we need to update and cancel the old uploads - conn.rollback() - c.execute( - "DELETE FROM iam_tickets where trade_date=%s returning *", (trade_date,) + for row in c: + d = ( + row._asdict() + | globeop_mapping(fund, row.broker) + | {"offset": True, "folder": "M_CSH_CASH"} ) - cancel_iam_deals = [ - iam_serialize(row._asdict(), "CANCEL", trade_date) for row in c - ] - iam_deals += cancel_iam_deals - c.executemany(insert_query, new_iam) - iam_deals += process_trades(conn, trade_date) - return iam_deals + return IAMDeal.from_dict(**d) -def process_upload(conn, trade_date, iam_deals): - bowdst = Service["BOWDST"]() - bowdst.staging_queue.extend(iam_deals) - if bowdst.staging_queue: - buf, dest = bowdst.build_buffer("iam") - bowdst.upload(buf, dest.name) +def main(fund, cob, conn): + service = Service[fund] + for iam in gen_iam_deals(fund, cob, conn): + iam.stage() + if fund in ("BOWDST"): + for iam in gen_iam_offsets(fund, cob, conn): + iam.stage() + for iam in IamDeal.commit(): + service.push(iam) + buf, dest = service.build_buffer() if __name__ == "__main__": @@ -155,12 +109,11 @@ if __name__ == "__main__": conn = dbconn("dawndb") parser = argparse.ArgumentParser(description="Generate IAM file for globeop") parser.add_argument( - "date", + "cob", nargs="?", type=datetime.date.fromisoformat, - default=(datetime.date.today() - bus_day).date(), + default=prev_business_day(datetime.date.today()), ) args = parser.parse_args() - iam_deals = gen_iam_deals(conn, args.date) - process_upload(conn, args.date, iam_deals) - conn.commit() + for fund in ("BOWDST",): + main(fund, args.cob, conn) diff --git a/python/report_ops/cash.py b/python/report_ops/cash.py index eabe5805..027cb350 100644 --- a/python/report_ops/cash.py +++ b/python/report_ops/cash.py @@ -13,17 +13,21 @@ from functools import partial @dataclass class IAMDeal(Deal, deal_type=None, table_name="iam_tickets"): trade_date: datetime.date = field(metadata={"globeop": "SettlementDate"}) - action: str = field(metadata={"globeop": "Action"}) - strategy: str = field(metadata={"globeop": "Folder"}) + folder: str = field(metadata={"globeop": "Folder"}) counterparty: str = field(metadata={"globeop": "Counterparty"}) - maturity: datetime.date start_money: float = field(metadata={"globeop": "StartMoney"}) currency: str = field(metadata={"globeop": "Currency"}) - booked_offset: bool - uploaded: bool fund: Fund - dealid: str = field(metadata={"insert": False}) - id: int = field(metadata={"insert": False}) + maturity: datetime.date = None + uploaded: bool = False + booked_offset: bool = False + dealid: str = None + id: int = None + cash_account: str = field( + default=None, + metadata={"insert": False, "select": False, "globeop": "Cash Account"}, + ) + custodian: str = field(default=None, metadata={"insert": False, "select": False}) def to_globeop(self, action): obj = super().to_globeop(action) |
