import pandas as pd import numpy as np from datetime import datetime as dt from pypfopt.efficient_frontier import EfficientFrontier import streamlit as st import plotly.graph_objects as go import plotly.express as px def ef_viz(stock_df,choices): st.write("EF Visualization KOI EDITS") symbols, weights, investment = choices.values() tickers = symbols #tickers.append('sp500') st.write(tickers) #st.write(stock_df) # Yearly returns for individual companies #https://stackoverflow.com/questions/69284773/unable-to-resample-the-pandas-with-date-column-typeerror-only-valid-with-dateti stock_dff = stock_df.copy() stock_dff['Date'] = pd.to_datetime(stock_dff['Date']) # ind_er_df = stock_dff.set_index('Date') #st.write(stock_dff.columns) ind_er_df = stock_dff.resample('Y', on = 'Date').last().pct_change().mean() ind_er = ind_er_df[tickers] #st.write(ind_er) ann_sd = stock_df[tickers].pct_change().apply(lambda x: np.log(1+x)).std().apply(lambda x: x*np.sqrt(250)) assets = pd.concat([ind_er, ann_sd], axis=1) # Creating a table for visualising returns and volatility of assets assets.columns = ['Returns', 'Volatility'] assets st.write(assets) ln_pct_change = stock_df[tickers].pct_change().apply(lambda x: np.log(1+x))[1:] #Cov Matrix cov_matrix =ln_pct_change.cov() p_ret = [] # Define an empty array for portfolio returns p_vol = [] # Define an empty array for portfolio volatility p_weights = [] # Define an empty array for asset weights num_assets = len(tickers) num_portfolios = 10000 for portfolio in range(num_portfolios): weights = np.random.random(num_assets) weights = weights/np.sum(weights) p_weights.append(weights) returns = np.dot(weights, ind_er) # Returns are the product of individual expected returns of asset and its # weights p_ret.append(returns) var = cov_matrix.mul(weights, axis=0).mul(weights, axis=1).sum().sum()# Portfolio Variance sd = np.sqrt(var) # Daily standard deviation ann_sd = sd*np.sqrt(250) # Annual standard deviation = volatility p_vol.append(ann_sd) data = {'Returns':p_ret, 'Volatility':p_vol} for counter, symbol in enumerate(stock_df[tickers].columns.tolist()): #print(counter, symbol) data[symbol] = [w[counter] for w in p_weights] port_ef_df = pd.DataFrame(data) st.write(port_ef_df[tickers].T) rf = 0.041 min_vol_port = port_ef_df.iloc[port_ef_df['Volatility'].idxmin()] optimal_risky_port = port_ef_df.iloc[((port_ef_df['Returns']-rf)/port_ef_df['Volatility']).idxmax()] ## Create Figure # fig = go.Figure() # fig.add_trace(go.Scatter(x=port_ef_df['Volatility'], y=port_ef_df['Returns'], \ # color=port_ef_df['Volatility'], mode='markers', name='markers')) fig = px.scatter(port_ef_df, 'Volatility', 'Returns', size='Returns', size_max=20, color='Volatility', \ custom_data=tickers) fig.update_traces(hovertemplate="
".join([ "%{tickers[0]}:%{custom_data[0]}", "%{tickers[1]}:%{custom_data[1]}", "%{tickers[2]}:%{custom_data[2]}", "%{tickers[3]}:%{custom_data[3]}" ]) ) #https://stackoverflow.com/questions/59057881/python-plotly-how-to-customize-hover-template-on-with-what-information-to-show st.plotly_chart(fig, use_container_width=True) #st.write(stock_df)