aboutsummaryrefslogtreecommitdiffstats
path: root/python/pnl_explain.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/pnl_explain.py')
-rw-r--r--python/pnl_explain.py156
1 files changed, 123 insertions, 33 deletions
diff --git a/python/pnl_explain.py b/python/pnl_explain.py
index c768052d..49a699f0 100644
--- a/python/pnl_explain.py
+++ b/python/pnl_explain.py
@@ -159,18 +159,20 @@ def get_tranche_pv2(
conn: connection,
**kwargs
):
- df = pd.read_sql_query("SELECT date, tranche_id AS id, clean_nav, accrued, folder "
- "FROM tranche_risk "
- "JOIN cds ON tranche_id=id "
- "WHERE date BETWEEN %s and %s AND fund=%s",
- conn,
- params=(start_date, end_date, fund),
- parse_dates=("date", "maturity"),
- index_col=["date", "id"])
+ df = pd.read_sql_query(
+ "SELECT date, tranche_id AS id, clean_nav, accrued, folder "
+ "FROM tranche_risk "
+ "JOIN cds ON tranche_id=id "
+ "WHERE date BETWEEN %s and %s AND fund=%s",
+ conn,
+ params=(start_date, end_date, fund),
+ parse_dates=("date", "maturity"),
+ index_col=["date", "id"],
+ )
df = df.sort_index()
strategies = df.folder
df = df[["clean_nav", "accrued"]]
- df -= df.groupby(level="id")[["clean_nav", "accrued"]].shift(fill_value=0.)
+ df -= df.groupby(level="id")[["clean_nav", "accrued"]].shift(fill_value=0.0)
df = df.drop(start_date)
with conn.cursor() as c:
c.execute(
@@ -184,7 +186,9 @@ def get_tranche_pv2(
"AND fund=%s",
(start_date, end_date, fund),
)
- df_terminations = pd.DataFrame.from_records(c, columns=[desc.name for desc in c.description])
+ df_terminations = pd.DataFrame.from_records(
+ c, columns=[desc.name for desc in c.description]
+ )
with conn.cursor() as c:
c.execute(
"SELECT trade_date AS date, id, "
@@ -195,14 +199,17 @@ def get_tranche_pv2(
"AND swap_type='CD_INDEX_TRANCHE' AND fund=%s",
(start_date, end_date, fund),
)
- df_upfronts = pd.DataFrame.from_records(c, columns=[desc.name for desc in c.description])
+ df_upfronts = pd.DataFrame.from_records(
+ c, columns=[desc.name for desc in c.description]
+ )
for df_temp in (df_terminations, df_upfronts):
df_temp.date = pd.to_datetime(df_temp.date)
df_temp.set_index(["date", "id"], inplace=True)
daily = pd.concat([df_terminations, df_upfronts], axis=1).sum(axis=1)
- daily.name = 'daily'
+ daily.name = "daily"
return pd.concat([df, daily], axis=1).join(strategies).sort_index()
+
def get_pv(**kwargs):
if kwargs.pop("pnl_type") == "swaption":
return get_swaption_pv(**kwargs)
@@ -210,6 +217,59 @@ def get_pv(**kwargs):
return get_tranche_pv(**kwargs)
+def bond_pnl(
+ start_date: datetime.date,
+ end_date: datetime.date,
+ fund: str,
+ conn: connection,
+ strat: str,
+ **kwargs
+):
+ start_df = pd.read_sql_query(
+ "SELECT * from risk_positions(%s, %s, %s)",
+ conn,
+ params=(start_date, strat, fund),
+ index_col=["identifier"],
+ )
+ end_df = pd.read_sql_query(
+ "SELECT * from risk_positions(%s, %s, %s)",
+ conn,
+ params=(end_date, strat, fund),
+ index_col=["identifier"],
+ )
+ cash_flow = pd.read_sql_query(
+ "SELECT * from factors_history where "
+ "last_pay_date >= %s and last_pay_date < %s",
+ conn,
+ params=(start_date, end_date),
+ index_col=["identifier"],
+ )
+ trades = pd.read_sql_query(
+ "SELECT * from bonds where "
+ "trade_date >= %s and trade_date < %s "
+ "and asset_class = %s and fund = %s",
+ conn,
+ params=(start_date, end_date, strat, fund),
+ index_col=["identifier"],
+ )
+ start_df = start_df.merge(cash_flow, how="left", on="identifier")
+ start_df.interest = start_df.interest * start_df.notional / 100
+ start_df.principal = start_df.principal * start_df.notional / 100
+ buys = trades[trades.buysell == True]
+ sells = trades[trades.buysell == False]
+
+ pnl = (
+ (end_df.usd_market_value.sum() + end_df.int_acc.sum())
+ - (start_df.usd_market_value.sum() + start_df.int_acc.sum())
+ + start_df.interest.sum()
+ + start_df.principal.sum()
+ + (sells.principal_payment.sum() + sells.accrued_payment.sum())
+ - (buys.principal_payment.sum() + buys.accrued_payment.sum())
+ )
+
+ return pd.DataFrame({"strat": strat, "pnl": pnl}, index=[end_date])
+
+
if __name__ == "__main__":
import argparse
from utils.db import dbconn
@@ -240,7 +300,7 @@ if __name__ == "__main__":
action="store",
default="tranche",
dest="pnl_type",
- help="instrument for which we want the pnl (one of 'tranche' or 'swaption')",
+ help="instrument for which we want the pnl ('tranche', 'swaption', 'bond', 'hedge')",
)
parser.add_argument(
"-f",
@@ -250,26 +310,56 @@ if __name__ == "__main__":
dest="fund",
help="fund we run the pnl for",
)
- args = parser.parse_args()
- swaption_strats = ("IGOPTDEL", "HYOPTDEL")
- tranche_strats = ("IGINX", "HYINX", "XOINX")
- if args.pnl_type == "tranche":
- index_strats = tranche_strats
- else:
- index_strats = swaption_strats
- df_index = get_index_pv(
- args.start_date, args.end_date, args.fund, dawndb, index_strats
+ parser.add_argument(
+ "-b",
+ "--bond_type",
+ action="store",
+ dest="bond_type",
+ help="bond type for which we want the pnl ('Subprime', 'CLO', 'CRT')",
)
+ args = parser.parse_args()
+ strats = {}
+ strats["swaption"] = ("IGOPTDEL", "HYOPTDEL")
+ strats["hedge"] = ("HEDGE_MBS", "HEDGE_CLO", "HEDGE_MAC")
+ strats["tranche"] = ("IGINX", "HYINX", "XOINX")
+ if args.pnl_type in ("tranche", "swaption"):
+ df_instrument = get_pv(conn=dawndb, **vars(args))
+ pnl_instrument = df_instrument.pv.diff() + df_instrument.daily
+ if args.pnl_type not in ("bond"):
+ df_index = get_index_pv(
+ args.start_date, args.end_date, args.fund, dawndb, strats[args.pnl_type]
+ )
+ pnl_index = df_index.pv.diff() + df_index.daily
- df_instrument = get_pv(conn=dawndb, **vars(args))
-
- pnl_index = df_index.pv.diff() + df_index.daily
- pnl_instrument = df_instrument.pv.diff() + df_instrument.daily
- pnl = pd.concat([pnl_index, pnl_instrument], keys=["index", args.pnl_type], axis=1)
- print(
- pd.concat(
- [pnl.sum(axis=1), pnl.sum(axis=1).cumsum()],
- axis=1,
- keys=["daily", "cumulative"],
+ if args.pnl_type in ("tranche", "swaption"):
+ pnl = pd.concat(
+ [pnl_index, pnl_instrument], keys=["index", args.pnl_type], axis=1
)
- )
+ print(
+ pd.concat(
+ [pnl.sum(axis=1), pnl.sum(axis=1).cumsum()],
+ axis=1,
+ keys=["daily", "cumulative"],
+ )
+ )
+ elif args.pnl_type not in ("bond"):
+ print(
+ pd.concat(
+ [pnl_index, pnl_index.cumsum()], axis=1, keys=["daily", "cumulative"],
+ )
+ )
+ else:
+ dates = pd.date_range(args.start_date, args.end_date)
+ df_bond = pd.DataFrame()
+ if args.bond_type is None:
+ bonds = ["Subprime", "CLO", "CRT"]
+ else:
+ bonds = [args.bond_type]
+ for asset_class in bonds:
+ for s, e in zip(dates.shift(-1), dates):
+ df_bond = df_bond.append(
+ bond_pnl(s.date(), e.date(), args.fund, dawndb, asset_class)
+ )
+ df_bond.index.name = "date"
+ pnl = df_bond.groupby("date").sum()
+ print(pd.concat([pnl, pnl.cumsum()], axis=1, keys=["daily", "cumulative"],))