diff options
Diffstat (limited to 'python')
| -rw-r--r-- | python/risk/indices.py | 28 | ||||
| -rw-r--r-- | python/swaption_pnl.py | 99 |
2 files changed, 127 insertions, 0 deletions
diff --git a/python/risk/indices.py b/python/risk/indices.py new file mode 100644 index 00000000..210d8aae --- /dev/null +++ b/python/risk/indices.py @@ -0,0 +1,28 @@ +import datetime +from analytics import Portfolio, CreditIndex +from psycopg2.extensions import connection +from typing import Tuple + + +def get_index_portfolio( + d: datetime.date, strategies: Tuple[str], conn: connection, **kwargs +): + with conn.cursor() as c: + c.execute( + "SELECT security_id AS redcode, notional, maturity " + "FROM list_cds_positions_by_strat(%s) " + "WHERE folder in %s", + (d, strategies), + ) + trades = [ + CreditIndex( + redcode=rec.redcode, + maturity=rec.maturity, + notional=rec.notional, + value_date=d, + ) + for rec in c + ] + portf = Portfolio(trades) + portf.mark() + return portf diff --git a/python/swaption_pnl.py b/python/swaption_pnl.py new file mode 100644 index 00000000..cf0cc653 --- /dev/null +++ b/python/swaption_pnl.py @@ -0,0 +1,99 @@ +import datetime +import pandas as pd +from psycopg2.extensions import connection +from risk.swaptions import get_swaption_portfolio +from risk.indices import get_index_portfolio +from pandas.tseries.offsets import BDay +from pyisda.date import previous_twentieth +from typing import Tuple + + +def get_index_pv( + start_date: datetime.date, + end_date: datetime.date, + strategies: Tuple[str], + conn: connection, +): + dr = pd.bdate_range(start_date, end_date) + pvs = [] + daily = [] + dates = [] + + for d in dr: + prev_day = (d - BDay()).date() + if previous_twentieth(d, roll=True) == d.date(): + accrued = 0.0 + for t in portf.trades: + d, amount = t._fee_leg.cashflows[0] + accrued -= amount * t.notional * t.factor * t.fixed_rate * 1e-4 + else: + accrued = 0.0 + portf = get_index_portfolio(prev_day, strategies, conn) + nav = 0.0 + with conn.cursor() as c: + c.execute( + "SELECT upfront FROM cds WHERE trade_date=%s " "AND folder in %s", + (prev_day, strategies), + ) + for (fee,) in c: + nav += fee + daily.append(nav + accrued) + pvs.append(portf.pv) + dates.append(prev_day) + df = pd.DataFrame({"pv": pvs, "daily": daily}, index=pd.to_datetime(dates)) + return df + + +def get_swaption_pv( + start_date: datetime.date, end_date: datetime.date, conn: connection +): + dr = pd.bdate_range(start_date, end_date) + pv = [] + daily = [] + dates = [] + for d in dr: + print(d) + prev_day = (d - BDay()).date() + portf = get_swaption_portfolio(prev_day, conn, source_list=["GS"]) + nav = 0.0 + # add terminations + with conn.cursor() as c: + c.execute( + "SELECT termination_fee " + "FROM swaptions WHERE termination_date=%s AND folder != 'STEEP'", + (prev_day,), + ) + for (fee,) in c: + nav += fee + # add new trades + with conn.cursor() as c: + c.execute( + "SELECT notional * price/100 * (CASE WHEN buysell THEN -1. ELSE 1. END) " + "FROM swaptions WHERE trade_date=%s AND folder != 'STEEP'", + (prev_day,), + ) + for (fee,) in c: + nav += fee + dates.append(prev_day) + pv.append(portf.pv) + daily.append(nav) + df = pd.DataFrame({"pv": pv, "daily": daily}, index=pd.to_datetime(dates)) + return df + + +if __name__ == "__main__": + import argparse + from utils.db import dbconn + + dawndb = dbconn("dawndb") + parser = argparse.ArgumentParser() + parser.add_argument("start_date", type=datetime.datetime.fromisoformat) + parser.add_argument("end_date", type=datetime.datetime.fromisoformat) + args = parser.parse_args() + df_index = get_index_pv( + args.start_date, args.end_date, ("IGOPTDEL", "HYOPTDEL"), dawndb + ) + df_swaption = get_swaption_pv(args.start_date, args.end_date, dawndb) + pnl_index = df_index.pv.diff() + df_index.daily + pnl_swaption = df_swaption.pv.diff() + df_swaption.daily + pnl = pd.concat([pnl_index, pnl_swaption], keys=["index", "swaption"], axis=1) |
