aboutsummaryrefslogtreecommitdiffstats
path: root/python
diff options
context:
space:
mode:
Diffstat (limited to 'python')
-rw-r--r--python/pnl_explain.py127
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))