Skip to content

Commit

Permalink
Merge pull request #26 from viventriglia/develop
Browse files Browse the repository at this point in the history
v0.2.1
  • Loading branch information
viventriglia authored Nov 6, 2024
2 parents eabe825 + be1943e commit 1855259
Show file tree
Hide file tree
Showing 8 changed files with 46 additions and 28 deletions.
Binary file modified data/in/demo.xlsx
Binary file not shown.
10 changes: 3 additions & 7 deletions src/aggregation.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,8 @@ def get_portfolio_pivot(
.sum()
.reset_index()
)
df_pivot["weight_pf"] = (
(100 * df_pivot["position_value"].div(pf_actual_value)).astype(float).round(1)
)
df_pivot["position_value"] = df_pivot["position_value"].astype(float).round(1)
df_pivot["weight_pf"] = 100 * df_pivot["position_value"].div(pf_actual_value)
df_pivot["position_value"] = df_pivot["position_value"]
return df_pivot


Expand All @@ -128,8 +126,6 @@ def get_pnl_by_asset_class(
group_by: Literal["asset_class", "macro_asset_class"],
) -> pd.DataFrame:
df_pnl = df.merge(df_dimensions, how="left", on="ticker_yf")
df_pnl["pnl"] = np.round(
((df_pnl["price"] - df_pnl["dca"]) * df_pnl["shares"]).astype(float), 1
)
df_pnl["pnl"] = ((df_pnl["price"] - df_pnl["dca"]) * df_pnl["shares"]).astype(float)
df_pnl = df_pnl.groupby(group_by)["pnl"].sum().reset_index().sort_values([group_by])
return df_pnl
30 changes: 17 additions & 13 deletions src/pages/1_🎯_Asset_Allocation_&_PnL.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,15 @@
consider_fees = st.checkbox("Take fees into account")

pf_actual_value = (df_j["shares"] * df_j["price"]).sum()
if consider_fees:
pnl = pf_actual_value - expense - fees
pnl_perc = 100 * (pf_actual_value - expense - fees) / expense
else:
pnl = pf_actual_value - expense
pnl_perc = 100 * (pf_actual_value - expense) / expense
total_expense = expense + fees if consider_fees else expense
pnl = pf_actual_value - total_expense
pnl_perc = 100 * pnl / total_expense
sign = "+" if pnl >= 0 else ""

col_l.metric(
label="Actual Portfolio Value",
value=f"{pf_actual_value: .1f} €",
delta=f"{pnl: .1f} € ({sign}{pnl_perc: .1f}%)",
value=f"{pf_actual_value: ,.1f} €",
delta=f"{pnl: ,.1f} € ({sign}{pnl_perc: .1f}%)",
)

df_j["position_value"] = df_j["shares"] * df_j["price"]
Expand All @@ -83,6 +80,7 @@
group_by = st.radio(
label="Aggregate by:",
options=["Macro Asset Classes", "Asset Classes", "Tickers"],
index=1,
horizontal=True,
)
df_pivot_ = get_portfolio_pivot(
Expand All @@ -91,18 +89,24 @@
pf_actual_value=pf_actual_value,
aggregation_level=DICT_GROUPBY_LEVELS[group_by],
)
df_pivot_.index += 1
st.table(
st.dataframe(
df_pivot_.rename(
columns={
"macro_asset_class": "Macro Asset Class",
"asset_class": "Asset Class",
"ticker_yf": "Ticker",
"name": "Name",
"position_value": "Position Value (€)",
"weight_pf": "Weight (%)",
"position_value": "Position Value",
"weight_pf": "Weight",
}
).style.format(
{
"Position Value": "{:,.1f} €",
"Weight": "{:,.1f}%",
}
).style.format(precision=1)
),
use_container_width=True,
hide_index=True,
)

st.markdown("***")
Expand Down
13 changes: 10 additions & 3 deletions src/pages/2_📈_Return_Analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,12 @@
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_n_shares = (
df_transactions.groupby("ticker_yf")
.agg(n_shares=("shares", "sum"))
.sort_values("n_shares", ascending=False)
)
ticker_list = df_n_shares.loc[~(df_n_shares == 0).all(axis=1)].index.unique().to_list()
df_common_history = get_max_common_history(ticker_list=ticker_list)

st.markdown("## Global settings")
Expand Down Expand Up @@ -79,6 +84,7 @@
df_rets = get_period_returns(
df=df_common_history.loc[first_day:last_day, :],
df_registry=df_registry,
tickers_to_evaluate=ticker_list,
period=DICT_FREQ_RESAMPLE[freq],
level=DICT_GROUPBY_LEVELS[level],
)
Expand All @@ -97,7 +103,7 @@
cols = st.multiselect(
f"Choose the {level.lower()} to display:",
options=default_objs,
default=default_objs[1],
default=default_objs[0],
key="sel_lev_1",
)

Expand All @@ -118,7 +124,7 @@
cols = col_l_lw.multiselect(
f"Choose the {level.lower()} to display:",
options=default_objs,
default=default_objs[1],
default=default_objs[0],
key="sel_lev_2",
)

Expand All @@ -132,6 +138,7 @@
df_roll_ret = get_rolling_returns(
df_prices=df_common_history.loc[first_day:last_day, :].ffill(),
df_registry=df_registry,
tickers_to_evaluate=ticker_list,
level=DICT_GROUPBY_LEVELS[level],
window=window,
)[cols]
Expand Down
10 changes: 8 additions & 2 deletions src/pages/3_⚠️_Risk_Analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,12 @@
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_n_shares = (
df_transactions.groupby("ticker_yf")
.agg(n_shares=("shares", "sum"))
.sort_values("n_shares", ascending=False)
)
ticker_list = df_n_shares.loc[~(df_n_shares == 0).all(axis=1)].index.unique().to_list()
df_common_history = get_max_common_history(ticker_list=ticker_list)

st.markdown("## Global settings")
Expand Down Expand Up @@ -73,6 +78,7 @@
df_rets = get_period_returns(
df=df_common_history.loc[first_day:last_day, :],
df_registry=df_registry,
tickers_to_evaluate=ticker_list,
period=DICT_FREQ_RESAMPLE[freq],
level=DICT_GROUPBY_LEVELS[level],
)
Expand All @@ -81,7 +87,7 @@
cols = st.multiselect(
f"Choose the {level.lower()} to display:",
options=default_objs,
default=default_objs[1],
default=default_objs[0],
key="sel_lev_3",
)

Expand Down
2 changes: 1 addition & 1 deletion src/plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def plot_pnl_by_asset_class(
hoverinfo="skip",
)
)
fig.update_traces(texttemplate="%{y:.1f}")
fig.update_traces(texttemplate="%{y:,.1f}")
fig.update_layout(
autosize=False,
height=550,
Expand Down
7 changes: 6 additions & 1 deletion src/returns.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@
def get_period_returns(
df: pd.DataFrame,
df_registry: pd.DataFrame,
tickers_to_evaluate: list[str],
period: Literal["Y", "Q", "M", "W", None],
level: Literal["ticker", "asset_class", "macro_asset_class"],
):
# Filtra solo i ticker effettivamente in portafoglio
df_registry = df_registry[df_registry["ticker_yf"].isin(tickers_to_evaluate)]
# Calcolo il ritorno
df_rets = df.pct_change()[1:]
# Se il periodo è None, la frequenza è giornaliera
Expand All @@ -29,7 +32,6 @@ def get_period_returns(
cols_to_sum = df_registry[df_registry[level].eq(class_)][
"ticker_yf"
].to_list()

df_rets_classes[class_] = df_rets[cols_to_sum].sum(axis=1)
return df_rets_classes
# Se il periodo non è None, faccio resampling al periodo desiderato
Expand All @@ -52,9 +54,12 @@ def get_period_returns(
def get_rolling_returns(
df_prices: pd.DataFrame,
df_registry: pd.DataFrame,
tickers_to_evaluate: list[str],
window: int,
level: Literal["ticker", "asset_class", "macro_asset_class"],
) -> pd.DataFrame:
# Filtra solo i ticker effettivamente in portafoglio
df_registry = df_registry[df_registry["ticker_yf"].isin(tickers_to_evaluate)]

df_log_ret = np.log(df_prices.div(df_prices.shift(1)))
df_roll_log_ret = df_log_ret.rolling(window=window).sum()
Expand Down
2 changes: 1 addition & 1 deletion src/var.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
os.path.join(*split_script_running_path[0 : len(split_script_running_path) - 1])
)

APP_VERSION = "0.2.0"
APP_VERSION = "0.2.1"

# Data/images

Expand Down

0 comments on commit 1855259

Please sign in to comment.