create an app that visualises historical investment portfolio data. you can see the total value of the portfolio over time, as well as break downs of asset classes or individual stocks. the app allows users to set target percentages. the app tells them how far off target they are and how they can rebalance their portfolio
Drop files here
or click to upload
import streamlit as st
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
from datetime import datetime, timedelta
import numpy as np
st.set_page_config(layout="wide", page_title="Portfolio Tracker")
# Initialize sample data
if 'portfolio_data' not in st.session_state:
# Generate sample historical data
dates = pd.date_range(start='2022-01-01', end='2023-12-31', freq='D')
np.random.seed(42)
# Sample portfolio with different asset classes
stocks = 100000 * (1 + np.random.normal(0.0002, 0.02, len(dates)).cumsum())
bonds = 50000 * (1 + np.random.normal(0.0001, 0.01, len(dates)).cumsum())
cash = 20000 * (1 + np.random.normal(0.0001, 0.001, len(dates)).cumsum())
real_estate = 30000 * (1 + np.random.normal(0.0002, 0.015, len(dates)).cumsum())
st.session_state.portfolio_data = pd.DataFrame({
'Date': dates,
'Stocks': stocks,
'Bonds': bonds,
'Cash': cash,
'Real Estate': real_estate
})
# App title and description
st.title("Portfolio Tracker & Rebalancing Tool")
st.write("Track your investment portfolio and analyze asset allocation")
# Sidebar for target allocation settings
st.sidebar.header("Target Allocation")
# Get current values
current_data = st.session_state.portfolio_data.iloc[-1]
total_value = current_data[['Stocks', 'Bonds', 'Cash', 'Real Estate']].sum()
# Target allocation inputs
target_stocks = st.sidebar.slider("Target Stocks %", 0, 100, 60)
target_bonds = st.sidebar.slider("Target Bonds %", 0, 100, 25)
target_cash = st.sidebar.slider("Target Cash %", 0, 100, 5)
target_real_estate = st.sidebar.slider("Target Real Estate %", 0, 100, 10)
# Check if allocations sum to 100%
total_allocation = target_stocks + target_bonds + target_cash + target_real_estate
if total_allocation != 100:
st.sidebar.error(f"Total allocation must equal 100% (currently {total_allocation}%)")
# Main content area
col1, col2 = st.columns(2)
with col1:
st.subheader("Portfolio Value Over Time")
# Calculate total portfolio value
st.session_state.portfolio_data['Total'] = st.session_state.portfolio_data[
['Stocks', 'Bonds', 'Cash', 'Real Estate']].sum(axis=1)
# Plot total portfolio value
fig = px.line(st.session_state.portfolio_data, x='Date', y='Total')
st.plotly_chart(fig, use_container_width=True)
with col2:
st.subheader("Current Asset Allocation")
# Calculate current allocation percentages
current_stocks_pct = (current_data['Stocks'] / total_value) * 100
current_bonds_pct = (current_data['Bonds'] / total_value) * 100
current_cash_pct = (current_data['Cash'] / total_value) * 100
current_real_estate_pct = (current_data['Real Estate'] / total_value) * 100
# Create pie chart
fig = go.Figure(data=[go.Pie(
labels=['Stocks', 'Bonds', 'Cash', 'Real Estate'],
values=[current_stocks_pct, current_bonds_pct, current_cash_pct, current_real_estate_pct]
)])
st.plotly_chart(fig, use_container_width=True)
# Rebalancing analysis
st.header("Portfolio Rebalancing Analysis")
col3, col4 = st.columns(2)
with col3:
st.subheader("Current vs Target Allocation")
comparison_data = pd.DataFrame({
'Asset': ['Stocks', 'Bonds', 'Cash', 'Real Estate'],
'Current %': [current_stocks_pct, current_bonds_pct, current_cash_pct, current_real_estate_pct],
'Target %': [target_stocks, target_bonds, target_cash, target_real_estate],
'Difference': [
current_stocks_pct - target_stocks,
current_bonds_pct - target_bonds,
current_cash_pct - target_cash,
current_real_estate_pct - target_real_estate
]
})
st.dataframe(comparison_data.round(2))
with col4:
st.subheader("Rebalancing Actions Needed")
# Calculate the dollar amount changes needed
for asset in ['Stocks', 'Bonds', 'Cash', 'Real Estate']:
current_pct = (current_data[asset] / total_value) * 100
target_pct = comparison_data[comparison_data['Asset'] == asset]['Target %'].values[0]
dollar_change = (target_pct - current_pct) * total_value / 100
if abs(dollar_change) > 1:
if dollar_change > 0:
st.write(f"Buy ${abs(dollar_change):,.2f} of {asset}")
else:
st.write(f"Sell ${abs(dollar_change):,.2f} of {asset}")
# Historical allocation chart
st.header("Historical Asset Allocation")
# Calculate percentages over time
for asset in ['Stocks', 'Bonds', 'Cash', 'Real Estate']:
st.session_state.portfolio_data[f'{asset} %'] = (
st.session_state.portfolio_data[asset] /
st.session_state.portfolio_data[['Stocks', 'Bonds', 'Cash', 'Real Estate']].sum(axis=1) * 100
)
# Plot historical allocation
fig = px.area(
st.session_state.portfolio_data,
x='Date',
y=['Stocks %', 'Bonds %', 'Cash %', 'Real Estate %'],
title='Asset Allocation Over Time',
labels={'value': 'Percentage', 'variable': 'Asset Class'}
)
st.plotly_chart(fig, use_container_width=True)
Hi! I can help you with any questions about Streamlit and Python. What would you like to know?