Skip to content

Commit

Permalink
Merge pull request #28 from viventriglia/develop
Browse files Browse the repository at this point in the history
v0.2.3
  • Loading branch information
viventriglia authored Nov 9, 2024
2 parents 8a75bc9 + 59b0a9d commit 8cafb60
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 30 deletions.
51 changes: 40 additions & 11 deletions src/0_🏠_Home.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,14 @@
import streamlit as st

from input_output import load_data, write_disclaimer
from var import GLOBAL_STREAMLIT_STYLE, DATA_PATH, FAVICON, APP_VERSION, COVER
from var import (
GLOBAL_STREAMLIT_STYLE,
DATA_PATH,
FILE_UPLOADER_CSS,
FAVICON,
APP_VERSION,
COVER,
)

st.set_page_config(
page_title="PFN",
Expand Down Expand Up @@ -56,17 +63,21 @@
""",
unsafe_allow_html=True,
)
col_l, col_r = st.columns([0.8, 1], gap="small")
col_l, col_r = st.columns([0.2, 0.95], gap="small")

uploaded_file = col_l.file_uploader(
label="Upload your Data", label_visibility="collapsed", accept_multiple_files=False
uploaded_file = col_r.file_uploader(
label="Upload your Data",
type=["xls", "xlsx", "xlsm", "xlsb", "odf", "ods"],
label_visibility="collapsed",
accept_multiple_files=False,
)
st.markdown(FILE_UPLOADER_CSS, unsafe_allow_html=True)
if uploaded_file is not None:
try:
df_storico, df_anagrafica = load_data(uploaded_file)
st.session_state["data"] = df_storico
st.session_state["dimensions"] = df_anagrafica
except:
except ValueError:
st.error("Please check your file format and make sure it matches the template")

with open(DATA_PATH / Path("template.xlsx"), "rb") as f:
Expand All @@ -76,15 +87,20 @@
data=f,
file_name="template.xlsx",
mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
help="Fill in this template and upload it using the adjacent button",
)

st.markdown("<br>", unsafe_allow_html=True)
st.markdown(
"If you wish to explore the app first, load some **demo** data instead.",
"<br>If you wish to explore the app first, load some **demo** data instead.",
unsafe_allow_html=True,
)

if st.button(label="Load Mock Data", icon="📊", key="load_mock_df"):
if st.button(
label="Load Mock Data",
icon="📊",
key="load_mock_df",
help="Load data to start a demo",
):
df_storico, df_anagrafica = load_data(DATA_PATH / Path("demo.xlsx"))
st.session_state["data"] = df_storico
st.session_state["dimensions"] = df_anagrafica
Expand All @@ -106,10 +122,23 @@
)
col_l_l, col_l_m, col_l_r = st.columns([1, 1, 1], gap="large")
col_l_l.page_link(
"pages/1_🎯_Asset_Allocation_&_PnL.py", label="Asset Allocation & PnL", icon="🎯"
"pages/1_🎯_Asset_Allocation_&_PnL.py",
label="Asset Allocation & PnL",
icon="🎯",
help="Portfolio composition, PnL, wealth evolution",
)
col_l_m.page_link(
"pages/2_📈_Return_Analysis.py",
label="Return Analysis",
icon="📈",
help="Distribution and correlation of returns, rolling returns",
)
col_l_r.page_link(
"pages/3_⚠️_Risk_Analysis.py",
label="Risk Analysis",
icon="⚠️",
help="Portfolio drawdowns",
)
col_l_m.page_link("pages/2_📈_Return_Analysis.py", label="Return Analysis", icon="📈")
col_l_r.page_link("pages/3_⚠️_Risk_Analysis.py", label="Risk Analysis", icon="⚠️")

st.markdown(
"""
Expand Down
3 changes: 2 additions & 1 deletion src/input_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ def write_load_message(df_data: pd.DataFrame, df_dimensions: pd.DataFrame) -> No
st.error(
f"There are null values: {n_data_na} among transactions, {n_dimensions_na} among tickers' descriptions"
)
st.stop()

if set_data_tickers != set_dimensions_tickers:
st.warning(
Expand Down Expand Up @@ -152,7 +153,7 @@ def get_last_closing_price_from_api(ticker: str, days_of_delay: int = 5) -> List
def get_full_price_history(ticker_list: List[str]) -> Dict:
df_history = dict()

for i, ticker_ in zip(range(len(ticker_list)), ticker_list):
for ticker_ in ticker_list:
ticker_data = yf.Ticker(ticker_)
df_history[ticker_] = ticker_data.history(
period="max",
Expand Down
44 changes: 34 additions & 10 deletions src/pages/1_🎯_Asset_Allocation_&_PnL.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from datetime import datetime

import streamlit as st

from var import (
Expand Down Expand Up @@ -44,25 +46,47 @@
expense = (df_j["shares"] * df_j["dca"]).sum()
fees = df_storico["fees"].sum().round(2)

st.markdown("## Profit and Loss")
st.markdown("## Profit & Loss")

col_l, col_r = st.columns([1, 1], gap="small")
col_l, col_m, col_r = st.columns([1, 1, 1], gap="small")

consider_fees = st.checkbox("Take fees into account")

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

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

col_m.metric(
label="Return On Investment (ROI)",
value=f"{sign}{pnl_perc: .1%}",
help="""
ROI shows the total gain or loss as a percentage of the original amount
invested, regardless of how long the investment was held
""",
)

first_transaction = df_storico["transaction_date"].sort_values()[0]
n_years = (datetime.now() - first_transaction).days / 365.25
annualised_ret = ((pf_actual_value / total_expense) ** (1 / n_years)) - 1

col_r.metric(
label="Annualised return",
value=f"{sign}{annualised_ret: .1%}",
help="""
This measures the average yearly return, helping compare investments
held for different periods by standardising the return on an annual basis
""",
)

df_j["position_value"] = df_j["shares"] * df_j["price"]
df_pivot = get_portfolio_pivot(
df=df_j,
df_dimensions=df_anagrafica,
Expand All @@ -72,7 +96,7 @@

st.markdown("***")

st.markdown("## Current Portfolio Asset Allocation")
st.markdown("## Current portfolio asset allocation")
fig = plot_sunburst(df=df_pivot)
st.plotly_chart(fig, use_container_width=True, config=PLT_CONFIG_NO_LOGO)

Expand Down Expand Up @@ -111,7 +135,7 @@

st.markdown("***")

st.markdown("## Profit and Loss by asset class")
st.markdown("## Profit & Loss by asset class")

group_by = st.radio(
label="Evaluate PnL with respect to:",
Expand All @@ -135,7 +159,7 @@

st.markdown("***")

st.markdown("## Daily value of the Accumulation Plan")
st.markdown("## Wealth history")

df_wealth = get_wealth_history(df_transactions=df_storico, ticker_list=ticker_list)

Expand Down
3 changes: 2 additions & 1 deletion src/pages/2_📈_Return_Analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
horizontal=True,
index=2,
key="level",
help="Choose how to aggregate data for analysis: Tickers provides the most granular view, while Macro Asset Classes aggregates at the highest level",
)
freq = col_r_up.radio(
label="Frequency of returns:",
Expand Down Expand Up @@ -75,7 +76,7 @@
st.markdown(f"## Correlation of {freq.lower().replace('day','dai')}ly returns")

enhance_corr = st.radio(
"Kind of correlation to enhance:",
"Kind of correlation to highlight:",
options=["Positive", "Null", "Negative"],
index=1,
horizontal=True,
Expand Down
1 change: 1 addition & 0 deletions src/pages/3_⚠️_Risk_Analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
horizontal=True,
index=2,
key="level",
help="Choose how to aggregate data for analysis: Tickers provides the most granular view, while Macro Asset Classes aggregates at the highest level",
)
freq = col_r_up.radio(
label="Frequency of returns:",
Expand Down
27 changes: 20 additions & 7 deletions 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.2"
APP_VERSION = "0.2.3"

# Data/images

Expand All @@ -20,12 +20,25 @@
# Streamlit/Plotly vars

GLOBAL_STREAMLIT_STYLE = """
<style>
#MainMenu {visibility: hidden;}
footer {visibility: hidden;}
.css-15zrgzn {display: none}
</style>
"""
<style>
#MainMenu {visibility: hidden;}
footer {visibility: hidden;}
.css-15zrgzn {display: none}
</style>
"""

FILE_UPLOADER_CSS = """
<style>
[data-testid='stFileUploader'] section {
padding: 0;
float: left;
}
[data-testid='stFileUploader'] section > input + div {
display: none;
}
</style>
"""


PLT_CONFIG = {
"displaylogo": False,
Expand Down

0 comments on commit 8cafb60

Please sign in to comment.