Spaces:
Sleeping
Sleeping
| 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 | |