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.py119
1 files changed, 40 insertions, 79 deletions
diff --git a/python/pnl_explain.py b/python/pnl_explain.py
index f398ae6d..e21d19b4 100644
--- a/python/pnl_explain.py
+++ b/python/pnl_explain.py
@@ -68,7 +68,7 @@ def get_swaption_pv(
end_date: datetime.date,
fund: str,
conn: connection,
- **kwargs
+ **kwargs,
):
dr = pd.bdate_range(start_date, end_date, freq=bus_day)
pv = []
@@ -113,7 +113,7 @@ def get_tranche_pv(
end_date: datetime.date,
fund: str,
conn: connection,
- **kwargs
+ **kwargs,
):
dr = pd.bdate_range(start_date, end_date, freq=bus_day)
pv = []
@@ -173,7 +173,7 @@ def get_tranche_pv2(
end_date: datetime.date,
fund: str,
conn: connection,
- **kwargs
+ **kwargs,
):
df = pd.read_sql_query(
"SELECT date, tranche_id AS id, clean_nav, accrued, folder "
@@ -235,27 +235,39 @@ def get_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
+ asset_class: Union[None, str],
+ **kwargs,
):
dr = pd.bdate_range(start_date - bus_day, end_date, freq=bus_day)
- dfs = {}
+ dfs, dfs_1 = {}, {}
for d in dr:
dfs[d] = pd.read_sql_query(
- "SELECT identifier, notional, usd_market_value, int_acc "
+ "SELECT identifier, usd_market_value, int_acc "
"FROM risk_positions(%s, %s, %s)",
conn,
params=(d.date(), asset_class, fund),
index_col=["identifier"],
)
+ dfs_1[d] = pd.read_sql_query(
+ "SELECT identifier, notional " "FROM list_positions(%s, %s, False, %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)
+ notionals = pd.concat(dfs_1, names=["date", "identifier"])
+ positions = positions.merge(
+ notionals, how="left", left_index=True, right_index=True
+ )
+ 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 "
@@ -266,93 +278,42 @@ def get_bond_pv(
)
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, "
+ "sum(CASE WHEN buysell THEN -principal_payment ELSE "
+ "principal_payment END) as principal_payment, "
+ "sum(CASE WHEN buysell THEN -accrued_payment ELSE "
+ "accrued_payment END) as accrued_payment, "
"asset_class "
"FROM bonds WHERE trade_date BETWEEN %s AND %s "
- f"AND fund=%s",
+ f"AND fund=%s "
+ "group by date, identifier, asset_class",
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)
+ trades.drop("asset_class", axis=1, inplace=True)
df = pd.concat([positions, cashflows, trades], axis=1)
- df.interest *= df.notional /100
- df.principal *= df.principal / 100
+ df.interest *= df.notional / 100
+ df.principal *= df.notional / 100
return df
-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.loc[trades.buysell]
- sells = trades.loc[~trades.buysell]
-
- 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])
+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 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
from utils.db import dbconn