Skip to content

Commit

Permalink
Merge pull request #16 from viventriglia/develop
Browse files Browse the repository at this point in the history
Advanced Stats
  • Loading branch information
viventriglia authored Aug 1, 2023
2 parents 9c0c856 + 4e7f902 commit a2d7bce
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 29 deletions.
8 changes: 2 additions & 6 deletions src/pages/1_📈_Basic_Stats.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
PLT_CONFIG,
PLT_CONFIG_NO_LOGO,
FAVICON,
DICT_GROUPBY_LEVELS,
)
from utils import (
aggregate_by_ticker,
Expand Down Expand Up @@ -86,16 +87,11 @@
options=["Macro Asset Classes", "Asset Classes", "Ticker"],
horizontal=True,
)
dict_group_by = {
"Macro Asset Classes": "macro_asset_class",
"Asset Classes": "asset_class",
"Ticker": "ticker",
}
df_pivot_ = get_portfolio_pivot(
df=df_j,
df_dimensions=df_anagrafica,
pf_actual_value=pf_actual_value,
aggregation_level=dict_group_by[group_by],
aggregation_level=DICT_GROUPBY_LEVELS[group_by],
)
df_pivot_.index += 1
st.table(
Expand Down
88 changes: 71 additions & 17 deletions src/pages/2_👩‍🔬_Advanced_Stats.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
import streamlit as st

from var import (
GLOBAL_STREAMLIT_STYLE,
# PLT_CONFIG,
# PLT_CONFIG_NO_LOGO,
FAVICON,
from var import GLOBAL_STREAMLIT_STYLE, PLT_CONFIG_NO_LOGO, FAVICON, DICT_GROUPBY_LEVELS

from utils import (
get_max_common_history,
write_disclaimer,
get_daily_returns,
)

# from utils import (
# sharpe_ratio,
# get_risk_free_rate_last_value,
# get_risk_free_rate_history,
# )
from plot import plot_correlation_map

st.set_page_config(
page_title="PFN | Advanced Stats",
Expand All @@ -21,15 +18,70 @@
)

st.markdown(GLOBAL_STREAMLIT_STYLE, unsafe_allow_html=True)
st.warning("Work in progress! Please, come back later", icon="🚧")

# df_common_history = get_max_common_history(ticker_list=ticker_list)
if "data" in st.session_state:
df_transactions = st.session_state["data"]
df_registry = st.session_state["dimensions"]
else:
st.error("Oops... there's nothing to display. Go through 🏠 first to load the data")
st.stop()

ticker_list = df_transactions["ticker_yf"].unique().tolist()
df_common_history = get_max_common_history(ticker_list=ticker_list)

st.markdown("## Correlation of daily returns")

col_l_up, col_r_up = st.columns([1, 1], gap="small")

level = col_l_up.radio(
label="Aggregate by:",
options=["Macro Asset Classes", "Asset Classes", "Ticker"],
horizontal=True,
index=2,
)

enhance_corr = col_r_up.radio(
"Kind of correlation to enhance:",
options=["Positive", "Null", "Negative"],
horizontal=True,
)

st.markdown("")
col_l_mid, col_r_mid = st.columns([1, 0.3], gap="small")

# weights = [
# df_pivot[df_pivot["ticker_yf"].eq(x_)]["weight_pf"].values[0]
# for x_ in df_common_history.columns
# ]
# weighted_average = pd.Series(np.average(df_common_history, weights=weights, axis=1))
first_transaction = df_transactions["transaction_date"].sort_values().values[0]
first_day, last_day = col_l_mid.select_slider(
"Select a time slice:",
options=df_common_history.index,
value=[first_transaction, df_common_history.index[-1]],
format_func=lambda value: str(value)[:10],
label_visibility="collapsed",
)

df_daily_rets = get_daily_returns(
df=df_common_history.loc[first_day:last_day, :],
df_registry=df_registry,
level=DICT_GROUPBY_LEVELS[level],
)

fig = plot_correlation_map(
df=df_daily_rets.corr(),
enhance_correlation=enhance_corr.lower(),
lower_triangle_only=True,
)
st.plotly_chart(fig, use_container_width=True, config=PLT_CONFIG_NO_LOGO)

# st.markdown("## Distribution of Daily Returns")

# diff_prev_day = get_wealth_history(
# df_transactions=df_transactions,
# df_prices=get_max_common_history(ticker_list=ticker_list),
# )['diff_previous_day']

# import plotly.express as px
# st.plotly_chart(px.histogram(diff_prev_day), use_container_width=True, config=PLT_CONFIG_NO_LOGO)

#################################

# returns = np.log(weighted_average.div(weighted_average.shift(1))).fillna(0)

Expand All @@ -46,3 +98,5 @@
# )

# st.write(sr)

write_disclaimer()
50 changes: 46 additions & 4 deletions src/plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,11 @@ def plot_pnl_by_asset_class(

def plot_wealth(df: pd.DataFrame) -> go.Figure:
fig = px.area(
data_frame=df,
x=df.index,
y="ap_daily_value",
data_frame=df, x=df.index, y="ap_daily_value", custom_data=["diff_previous_day"]
)
fig.update_traces(
hovertemplate="%{x}: <b>%{y:,.0f}€</b> <extra>Gain/Loss on previous day: %{customdata:,.0f}€</extra>"
)
fig.update_traces(hovertemplate="%{x}: <b>%{y:,.0f}€</b>")
fig.update_layout(
autosize=False,
height=550,
Expand All @@ -70,3 +70,45 @@ def plot_wealth(df: pd.DataFrame) -> go.Figure:
showlegend=False,
)
return fig


def plot_correlation_map(
df: pd.DataFrame,
enhance_correlation: Literal["positive", "null", "negative"],
lower_triangle_only: bool = False,
):
if lower_triangle_only:
mask = np.triu(np.ones_like(df, dtype=bool))

if enhance_correlation == "positive":
cuts = [-1, 0, 1]
colors = ["white", "white", "darkred"]
elif enhance_correlation == "null":
cuts = [-1, -0.3, 0, 0.3, 1]
colors = ["white", "white", "darkgreen", "white", "white"]
elif enhance_correlation == "negative":
cuts = [-1, 0, 1]
colors = ["darkblue", "white", "white"]
colorscale = [[(cut_ + 1) / 2, col_] for cut_, col_ in zip(cuts, colors)]

fig = go.Figure(
go.Heatmap(
z=df.mask(mask) if lower_triangle_only else df,
x=df.columns,
y=df.columns,
colorscale=colorscale,
zmin=-1,
zmax=1,
)
)
fig.update_traces(hovertemplate="<b>%{z:.2f} <extra></extra>")
fig.update_layout(
height=500,
hoverlabel_font_size=PLT_FONT_SIZE,
margin=dict(l=0, r=0, t=30, b=0),
yaxis=dict(autorange="reversed", showgrid=False),
# paper_bgcolor="rgba(0,0,0,0)",
# plot_bgcolor="rgba(0,0,0,0)",
)

return fig
26 changes: 25 additions & 1 deletion src/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,12 +274,14 @@ def get_wealth_history(
df_asset_allocation.loc[data, ticker] += total_shares
df_asset_allocation = df_asset_allocation.cumsum()

df_wealth = (
df_wealth = pd.DataFrame(
df_asset_allocation.multiply(df_prices.loc[begin_date:])
.fillna(method="ffill")
.sum(axis=1)
.rename("ap_daily_value")
)
df_wealth["diff_previous_day"] = df_wealth.diff()

return df_wealth


Expand Down Expand Up @@ -341,3 +343,25 @@ def write_disclaimer() -> None:
</span> </center>',
unsafe_allow_html=True,
)


@st.cache_data(ttl=CACHE_EXPIRE_SECONDS, show_spinner=False)
def get_daily_returns(
df: pd.DataFrame,
df_registry: pd.DataFrame,
level: Literal["ticker", "asset_class", "macro_asset_class"],
):
df_daily_rets = df.pct_change()[1:]

if level == "ticker":
return df_daily_rets
else:
classes = df_registry[level].unique()
df_daily_rets_classes = pd.DataFrame(columns=classes)
for class_ in classes:
cols_to_sum = df_registry[df_registry[level].eq(class_)][
"ticker_yf"
].to_list()

df_daily_rets_classes[class_] = df_daily_rets[cols_to_sum].sum(axis=1)
return df_daily_rets_classes
7 changes: 6 additions & 1 deletion src/var.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
os.path.join(*split_script_running_path[0 : len(split_script_running_path) - 1])
)

APP_VERSION = "0.1.0"
APP_VERSION = "0.1.1"

# Data/images

Expand Down Expand Up @@ -44,3 +44,8 @@
# Others

TRADING_DAYS_YEAR = 252
DICT_GROUPBY_LEVELS = {
"Macro Asset Classes": "macro_asset_class",
"Asset Classes": "asset_class",
"Ticker": "ticker",
}

0 comments on commit a2d7bce

Please sign in to comment.