import datetime import pandas as pd from . import DAILY_DIR from .common import load_pdf, get_col, next_business_day, parse_num def load_file(d, fund="Serenitas"): try: fname = next( (DAILY_DIR / fund / "CITI_reports").glob( f"262966_Portfolio_{d.strftime('%Y%m%d')}*" ) ) except StopIteration: raise FileNotFoundError(f"CITI file not found for date {d}") return pd.read_excel(fname, skiprows=6, skipfooter=2) def download_files(em, count=20, fund="Serenitas", **kwargs): if fund != "Serenitas": return emails = em.get_msgs( path=["NYops", "Margin Calls Citi"], count=count, subject__startswith="262966" ) DATA_DIR = DAILY_DIR / fund / "CITI_reports" for msg in emails: for attach in msg.attachments: fname = attach.name p = DATA_DIR / fname if not p.exists(): p.write_bytes(attach.content) def get_df(l, col1, col2, col3): df = pd.DataFrame( {"amount": get_col(l, *col2), "currency": get_col(l, *col3)}, index=get_col(l, *col1), ) df.amount = df.amount.apply(parse_num) df.index = df.index.str.lstrip() return df def get_total_collateral(d: datetime.date, fund="Serenitas"): try: fname = next( (DAILY_DIR / fund / "CITI_reports").glob( f"262966_MarginNotice_{d.strftime('%Y%m%d')}_*.pdf" ) ) except StopIteration: raise FileNotFoundError(f"CITI file not found for date {d}") l = load_pdf(fname) col1 = (370, 500, 70, 250) col2 = (370, 500, 300, 530) col3 = (370, 500, 530, 600) variation_margin = get_df(l, col1, col2, col3) anchor = next(c for c in l if c.text == "Non Regulatory Initial Margin") top = int(anchor["top"]) + 10 bottom = top + 160 col1 = (top, bottom, 70, 320) col2 = (top, bottom, 320, 530) col3 = (top, bottom, 530, 600) initial_margin = get_df(l, col1, col2, col3) try: net_im = -initial_margin.loc["Non Reg IM Requirement Due Customer", "amount"] except KeyError: net_im = -initial_margin.loc["Non Reg IM Requirement Due Citi", "amount"] return ( variation_margin.loc["VM Total Collateral", "amount"], initial_margin.loc["Non Reg IM Total Collateral", "amount"], -variation_margin.loc["Regulatory VM Requirement", "amount"], net_im, ) def collateral(d, dawn_trades, fund="Serenitas", **kwargs): if fund != "Serenitas": raise ValueError df = load_file(next_business_day(d), fund) collat = sum(get_total_collateral(d, fund)[:2]) df = df[["Operations File", "Market Value", "BasicAmt"]].dropna( subset=["Operations File"] ) # missing Operations File means assignment usually # but could be a fee df = df.merge( dawn_trades, how="left", left_on="Operations File", right_on="cpty_id" ) missing_ids = df.loc[df.cpty_id.isnull(), "Operations File"] if not missing_ids.empty: raise ValueError(f"{missing_ids.tolist()} not in the database") df = df.groupby("folder").sum() df = df[["Market Value", "BasicAmt"]].sum(axis=1).to_frame(name="Amount") df["Currency"] = "USD" df = df.reset_index() df.columns = ["Strategy", "Amount", "Currency"] df.Amount *= -1 df.loc[len(df.index)] = ["M_CSH_CASH", collat - df.Amount.sum(), "USD"] df["date"] = d return df.set_index("Strategy")