Hi everyone,
I am currently working on implementing Mordern Portfolio Theory in python. I have successfully plotted the efficient frontier for 10 rolling windows, from which you can hover upon the graph and get information about each portfolio.
I also wish to plot the Sharpe ratio point and the Minimum variance Portfolio. I have managed to do so, but when you hover upon the SR point and MVP for each rolling window, it dosent update the information to the new rolling window. It just stays with the information from the first rolling window.
My code for the plotly plot looks like this:
color_scale = [
[0, 'red'], # Low ESG score -> red
[0.5, 'yellow'], # Mid ESG score -> yellow
[1, 'green'] # High ESG score -> green
]
for i in range(len(rolling_returns)):
weights_str_sr = [f'{w*100:.2f}%' for w in sr_w_list[i]]
weights_text_sr = ', '.join(weights_str_sr)
#filter out returns and volatility less than or equal to -0.5
filtered_returns = []
filtered_volatility = []
filtered_weights = []
filtered_wa_esg = []
filtered_wa_e = []
filtered_wa_s = []
filtered_wa_g = []
filtered_esg_sr = []
for j in range(len(rolling_returns[i])):
#if rolling_returns[i][j] > -0.3:
filtered_returns.append(rolling_returns[i][j])
filtered_volatility.append(vol_list[i][j])
filtered_weights.append(ef_weights_list[i][j])
filtered_wa_esg.append(wa_esg_list[i][j])
filtered_wa_e.append(wa_e_list[i][j])
filtered_wa_s.append(wa_s_list[i][j])
filtered_wa_g.append(wa_g_list[i][j])
fig = go.Figure()
fig.add_trace(go.Scatter(
x=filtered_volatility,
y=filtered_returns,
mode ='markers',
name='Efficient Frontier',
marker=dict(
color=filtered_wa_esg,
colorscale=color_scale,
colorbar=dict(title='WA ESG Score')
),
text=[f'Weights: {", ".join([f"(Ticker: {ticker}, Weight: {w*100:.2f}%)" for ticker, w in zip(tickers, wts)])}<br>' +
f'Volatility: {vol:.2%}<br>' +
f'Return: {rets:.2%}<br>' +
f'WA ESG Score: {esg:.4}<br>' +
f'WA Enviromental Score: {e:.4}<br>' +
f'WA Social Score: {s:.4}<br>' +
f'WA Governance Score: {g:.4}'
for tickers, wts, vol, rets, esg, e, s, g in zip(tickers_list*len(filtered_weights), filtered_weights, filtered_volatility, filtered_returns, filtered_wa_esg, filtered_wa_e, filtered_wa_s, filtered_wa_g)],
hovertemplate='%{text}',
hoverlabel=dict(
font_size=10)
))
fig.add_trace(go.Scatter(x = [vol_sr_list[i]], y = [er_sr_list[i]],
marker=dict(color='red', size=12),
mode='markers',
name='SR portfolio',
text=[f'Weights: {", ".join([f"(Ticker: {t_sr}, Weight: {w_sr*100:.2f}%)" for t_sr, w_sr in zip(tickers_sr, wts_sr)])}<br>' +
f'Volatility: {vol_sr:.2%}<br>' +
f'Return: {rets_sr:.2%} <br>' +
f'Sharpe ratio: {sharpe}<br>' +
f'WA ESG Score: {esg_sr:.4}'
for tickers_sr, wts_sr, vol_sr, sharpe, rets_sr, esg_sr in zip(sr_t_list*len(sr_w_list), sr_w_list, vol_sr_list, sr_list, er_sr_list, sr_esg_list)],
hovertemplate='%{text}',
hoverlabel=dict(
font_size=10)
))
fig.add_trace(go.Scatter(x = [vol_mvp_list[i]], y = [er_mvp_list[i]],
marker=dict(color='White', size=12),
mode='markers',
name='Minimum Variance Portfolio',
text=[f'Weights: {", ".join([f"(Ticker: {t_mvp}, Weight: {w_mvp*100:.2f}%)" for t_mvp, w_mvp in zip(tickers_mvp, wts_mvp)])}<br>' +
f'Volatility: {vol_mvp:.2%}<br>' +
f'Return: {rets_mvp:.2%} <br>'
for tickers_mvp, wts_mvp, vol_mvp, rets_mvp in zip(mvp_t_list*len(mvp_w_list), mvp_w_list, vol_mvp_list, er_mvp_list)],
hovertemplate='%{text}',
hoverlabel=dict(
font_size=10)
))
fig.update_layout(legend=dict(
orientation="h",
yanchor="bottom",
y=1.02,
xanchor="right",
x=1
))
# Update layout
fig.update_layout(
template='plotly_dark',
title='Efficient Frontier',
xaxis_title='Volatility',
yaxis_title='Return',
hovermode='closest',
width=1000,
height=600,
margin=dict(l=50, r=50, b=50, t=50, pad=4)
)
fig.show()
In the picture below you can see how i looks when you hover upon the SR point. Can anyone help me or give me some hints, as to why it dosent update the information about the SR point, but does for every other portfolio on the efficient frontier.