diff options
Diffstat (limited to 'python/innocap.py')
| -rw-r--r-- | python/innocap.py | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/python/innocap.py b/python/innocap.py new file mode 100644 index 00000000..191901f1 --- /dev/null +++ b/python/innocap.py @@ -0,0 +1,112 @@ +from io import BytesIO +from serenitas.utils.env import DAILY_DIR +import datetime +from serenitas.ops.citco import GIL, GTL +from serenitas.utils.remote import Client +from serenitas.utils.db import dbconn +from serenitas.analytics.dates import prev_business_day, next_business_day +from report_ops.sma import build_position_file +from report_ops.utils import SettlementMonitor + +settlement_sum_query = "SELECT currency, sum(payment_amount) as payment_amount FROM payment_settlements ps2 WHERE fund=%s AND asset_class in ('BOND', 'SPOT') AND settle_date BETWEEN %s AND %s group by currency;" +_account_fund = {"ISOS01": "ISOSEL"} + + +def concat_csv(file_type, date): + match file_type: + case "trade": + file_tag = "innocap_serenitas_trades" + case "instrument": + file_tag = "i.innocap_serenitas" + fname = f"Innocap_ISOSEL_{file_type}_{date:%Y-%m-%d}.csv" + buf = BytesIO() + buf.write((",".join(GTL if file_type == "trade" else GIL) + "\n").encode()) + for f in (DAILY_DIR / str(date)).iterdir(): + if f.is_file() and f.name.startswith(file_tag): + with f.open("rb") as fh: + next(fh) # Don't concat headers + buf.write(fh.read()) + return buf.getvalue(), fname + + +def upload_citco_files(date, upload): + for file_type in ("trade", "instrument"): + buf, fname = concat_csv(file_type, date) + dest = DAILY_DIR / str(date) / fname + dest.write_bytes(buf) + if upload: + innocap_sftp = Client.from_creds("innocap", folder="Innocap") + innocap_sftp.put(buf, fname) + + +def upload_position_files(date, fund, upload): + buf, dest = build_position_file( + date, + fund, + ) + if upload: + client = Client.from_creds("innocap", folder="Innocap") + client.put(buf, dest.name) + client = Client.from_creds("citco") + client.put(buf, dest.name) + + +def get_cash_balance(date, account, conn): + with conn.cursor() as c: + sql_str = "SELECT balance, currency_code from cash_balances WHERE account_number=%s AND date=%s" + c.execute(sql_str, (account, date)) + return {row.currency_code: row.balance for row in c} + + +def monitor_cash_balances(date, account, conn, upload): + cob = prev_business_day(date) + fund = _account_fund[account] + if cash_balances := get_cash_balance(cob, account, conn): + for projection_date in (date, next_business_day(date)): + with conn.cursor() as c: + c.execute(settlement_sum_query, (fund, date, projection_date)) + for row in c: + projection_balance = ( + cash_balances[row.currency] + row.payment_amount + ) + if projection_balance < 0: + SettlementMonitor.stage( + { + "date": projection_date, + "account": account, + "currency": row.currency, + "projected_balance": projection_balance, + } + ) + SettlementMonitor.email(fund) + SettlementMonitor._insert_queue.clear() + + else: + raise ValueError(f"No cash balances parsed for account {account}: {cob}") + + +if __name__ == "__main__": + import argparse + + parser = argparse.ArgumentParser() + parser.add_argument( + "workdate", + nargs="?", + type=datetime.date.fromisoformat, + default=datetime.date.today(), + help="file transfer date", + ) + parser.add_argument( + "--no-upload", + "-n", + action="store_true", + default=False, + help="uploads to citco and innocap", + ) + args = parser.parse_args() + cob = prev_business_day(args.workdate) + conn = dbconn("dawndb") + + upload_citco_files(cob, not args.no_upload) + upload_position_files(cob, "ISOSEL", not args.no_upload) + monitor_cash_balances(args.workdate, "ISOS01", conn, not args.no_upload) |
