from dataclasses import field, dataclass from serenitas.ops.trade_dataclasses import Deal, Fund from serenitas.analytics.dates import prev_business_day import datetime import gpg from serenitas.utils.exchange import ExchangeMessage from serenitas.utils.env import DAILY_DIR import pandas as pd from serenitas.utils.db import dbconn, dawn_engine from typing import ClassVar @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"}) 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}) def to_globeop(self, action): obj = super().to_globeop(action) obj["Deal Type"] = "IamDeal" obj["ExpirationDate"] = self.trade_date if self.action == "UPDATE" else None obj["CallNoticeIndicator"] = "24H" if self.action == "NEW" else None obj["TransactionIndicator"] = ("DEPOSIT" if obj["StartMoney"] > 0 else "LOAN",) obj["StartMoney"] = abs(obj["StartMoney"]) obj["Folder"] = ( "M_CSH_CASH" if obj["strategy"] == "CSH_CASH" else obj["strategy"] ) obj["DealFunction"] = "OTC" obj["MarginType"] = "Variation" obj["Basis"] = "ACT/360" return obj @dataclass class CashReport: fund: ClassVar[str] date: datetime.date _conn: ClassVar[dbconn] = dbconn("dawndb") def __init_subclass__(cls, fund): cls.fund = fund def download_report(self): em = ExchangeMessage() for msg in em.get_msgs(path=["SeleneOps", "Passport"]): for attach in msg.attachments: message_date = attach.last_modified_time.date() if ( attach.name == "Attachment1.pgp" and prev_business_day(message_date) == self.date ): dest = ( DAILY_DIR / str(message_date) / "Reports" / f"{message_date:%Y%m%d}_ISOSEL.csv" ) dest.parent.mkdir(exist_ok=True, parents=True) with attach.fp as fp, dest.open("w") as csvfh: plaintext, result, verify_result = gpg.Context().decrypt( fp.read(), passphrase="Serenitas1", sink=csvfh ) return dest raise ValueError(f"No reports found for fund: {self.fund} date: {self.date}") def to_db(self): df = pd.read_csv(self.download_report(), on_bad_lines="warn", sep="\t") df = df[df["T-NARR-LONG"] == "CLOSING BALANCE"] df = df[["Consolidation", "Currency code", "A-TRAN-AMT", "Account name"]] df = df.reset_index(drop=True).rename( { "Consolidation": "account_number", "Currency code": "currency_code", "Account name": "account_name", "A-TRAN-AMT": "balance", }, axis=1, ) df["date"] = self.date df["fund"] = self.fund with self._conn.cursor() as c: c.execute( "DELETE FROM cash_balances WHERE fund=%s AND date=%s", (self.fund, self.date), ) self._conn.commit() df.to_sql("cash_balances", index=False, if_exists="append", con=dawn_engine) class IsoselCashReport(CashReport, fund="ISOSEL"): pass