diff options
Diffstat (limited to 'python/pnl_explain.py')
| -rw-r--r-- | python/pnl_explain.py | 127 |
1 files changed, 83 insertions, 44 deletions
diff --git a/python/pnl_explain.py b/python/pnl_explain.py index 2bab82d5..387cadaf 100644 --- a/python/pnl_explain.py +++ b/python/pnl_explain.py @@ -230,11 +230,61 @@ def get_tranche_pv2( def get_pv(**kwargs): - kwargs.pop("bond_type") - if kwargs.pop("pnl_type") == "swaption": + pnl_type = kwargs.pop("pnl_type") + if pnl_type == "swaption": return get_swaption_pv(**kwargs) - else: + elif pnl_type == "tranche": return get_tranche_pv(**kwargs) + else: + return get_bond_pv(**kwargs) + +def get_bond_pv( + start_date: datetime.date, + end_date: datetime.date, + fund: str, + conn: connection, + asset_class: Union[None,str], + **kwargs +): + dr = pd.bdate_range(start_date - bus_day, end_date, freq=bus_day) + dfs = {} + for d in dr: + dfs[d] = pd.read_sql_query( + "SELECT identifier, notional, usd_market_value, int_acc " + "FROM risk_positions(%s, %s, %s)", + conn, + params=(d.date(), asset_class, fund), + index_col=["identifier"], + ) + positions = pd.concat(dfs, names=["date", "identifier"]) + positions[["usd_market_value", "int_acc"]] -= \ + positions.groupby(level="identifier")[["usd_market_value", "int_acc"]].shift(fill_value=0.0) + positions = positions.drop(start_date - bus_day) + cashflows = pd.read_sql_query( + "SELECT identifier, last_pay_date AS date, interest, principal " + "FROM factors_history WHERE last_pay_date BETWEEN %s AND %s", + conn, + params=(start_date, end_date), + index_col=["date", "identifier"], + ) + trades = pd.read_sql_query( + "SELECT trade_date AS date, identifier, " + "CASE WHEN buysell THEN -principal_payment ELSE principal_payment END, " + "CASE WHEN buysell THEN -accrued_payment ELSE accrued_payment END, " + "asset_class " + "FROM bonds WHERE trade_date BETWEEN %s AND %s " + f"AND fund=%s", + conn, + params=(start_date, end_date, fund), + index_col=["date", "identifier"], + ) + if asset_class is not None: + trades = trades[trades.asset_class == asset_class] + trades.drop("asset_class", axis=1) + df = pd.concat([positions, cashflows, trades], axis=1) + df.interest *= df.notional /100 + df.principal *= df.principal / 100 + return df def bond_pnl( @@ -289,6 +339,22 @@ def bond_pnl( return pd.DataFrame({"strat": strat, "pnl": pnl}, index=[end_date]) +def get_pnl(df_instrument, asset_class: Literal['bond', 'tranche', 'swaption']): + if asset_class == "bond": + return (df_instrument. + drop("notional", axis=1). + groupby("date"). + sum(). + sum(axis=1)) + elif asset_class == "tranche": + return df_instrument.pv.diff() + df_instrument[ + ["upfront", "accrued"] + ].sum(axis=1) + elif asset_class == "swaption": + return df_instrument.pv.diff() + df_instrument.daily + +def cumulative_from_daily(df): + return pd.concat([df, df.cumsum()], axis=1, keys=["daily", "cumulative"]) if __name__ == "__main__": import argparse @@ -331,58 +397,31 @@ if __name__ == "__main__": help="fund we run the pnl for", ) parser.add_argument( - "-b", - "--bond_type", + "-a", + "--asset-class", action="store", - dest="bond_type", + choices=("Subprime", "CLO", "CRT"), help="bond type for which we want the pnl ('Subprime', 'CLO', 'CRT')", ) + args = parser.parse_args() strats = { "swaption": ("IGOPTDEL", "HYOPTDEL"), "hedge": ("HEDGE_MBS", "HEDGE_CLO", "HEDGE_MAC"), "tranche": ("IGINX", "HYINX", "XOINX"), + "bond": None, } - if args.pnl_type in ("tranche", "swaption"): + 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[["upfront", "accrued"]].sum(axis=1) + if args.pnl_type != "hedge": df_instrument = get_pv(conn=dawndb, **vars(args)) - pnl_instrument = df_instrument.pv.diff() + df_instrument[ - ["upfront", "accrued"] - ].sum(axis=1) - if args.pnl_type != "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[["upfront", "accrued"]].sum(axis=1) - - if args.pnl_type in ("tranche", "swaption"): + pnl_instrument = get_pnl(df_instrument, args.pnl_type) 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"], - ) - ) + + print(cumulative_from_daily(pnl.sum(axis=1))) elif args.pnl_type == "hedge": - 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.split(",") - 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"],)) + print(cumulative_from_daily(pnl_index)) |
