trailStream / app.py
rohanphadke's picture
Update app.py
4136930 verified
import altair as alt
import streamlit as st
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import yfinance as yf
# The efficient frontier function modified for use in Streamlit
def plot_efficient_frontier(dataframes, names):
# Your efficient frontier function with slight modifications for Streamlit
# This is the same function you've been working with, so ensure it's correctly adjusted for Streamlit output
# Ensure you include the code for the function here
# Calculate daily returns for each asset
returns = pd.concat([df['Close'].pct_change().dropna() for df in dataframes], axis=1)
returns.columns = names
mean_returns = returns.mean() * 252
cov_matrix = returns.cov() * 252
num_portfolios = 10000
all_weights = np.zeros((num_portfolios, len(dataframes)))
ret_arr = np.zeros(num_portfolios)
vol_arr = np.zeros(num_portfolios)
sharpe_arr = np.zeros(num_portfolios)
for i in range(num_portfolios):
weights = np.random.random(len(dataframes))
weights /= np.sum(weights)
all_weights[i, :] = weights
ret_arr[i] = np.dot(weights, mean_returns)
vol_arr[i] = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights)))
sharpe_arr[i] = ret_arr[i] / vol_arr[i]
max_sharpe_idx = np.argmax(sharpe_arr)
max_sharpe_return = ret_arr[max_sharpe_idx]
max_sharpe_volatility = vol_arr[max_sharpe_idx]
# Find the portfolio with the minimum volatility
min_vol_idx = np.argmin(vol_arr)
min_vol_return = ret_arr[min_vol_idx]
min_vol_volatility = vol_arr[min_vol_idx]
fig, ax = plt.subplots()
scatter = ax.scatter(vol_arr, ret_arr, c=sharpe_arr, cmap='Blues')
colorbar = plt.colorbar(scatter, ax=ax)
colorbar.set_label('Sharpe Ratio')
ax.scatter(max_sharpe_volatility, max_sharpe_return, c='red', s=200, marker='*', label='Optimal Portfolio - Max Sharpe Ratio')
ax.scatter(min_vol_volatility, min_vol_return, c='purple', s=150, edgecolors='black', marker='o', label='Minimum Volatility Portfolio')
ax.set_xlabel('Volatility')
ax.set_ylabel('Return')
# Set axes starting points
ax.set_xlim(left=0)
ax.set_ylim(bottom=0)
ax.set_title('Efficient Frontier')
st.pyplot(fig)
optimal_weights = all_weights[max_sharpe_idx]
st.divider()
st.subheader(f"Expected Annual Return: {max_sharpe_return:.2f}")
st.subheader(f"Annual Volatility/Risk: {max_sharpe_volatility:.2f}")
st.divider()
st.subheader("Optimal Portfolio Weights:")
for i, name in enumerate(names):
st.write(f"**{name}:** {100*optimal_weights[i]:.2f}%")
# Streamlit application layout
st.title("Portfolio Optimization with Efficient Frontier")
# User input for tickers
user_input = st.text_input("Enter tickers separated by commas (e.g., AAPL,MSFT,GOOGL)", "NVDA,AMD,AAPL,MSFT,GOOGL")
# Process input tickers
tickers = [ticker.strip().upper() for ticker in user_input.split(',')]
# Fetch data and calculate efficient frontier upon button click
if st.button("Optimize Portfolio"):
# Fetch stock data
timeframe = '1y' # Define the timeframe for data fetching
dataframes = []
for ticker in tickers:
tick = yf.Ticker(ticker)
stock_data = tick.history(period=timeframe)
dataframes.append(stock_data)
# Ensure we have the data before proceeding
if len(dataframes) > 0:
# Plot efficient frontier and display optimal weights
plot_efficient_frontier(dataframes, tickers)
else:
st.write("Please enter valid tickers.")
# Instructions to run the app