Yim-Koi commited on
Commit
563e922
·
1 Parent(s): 58ea282

Big update to ef.py include centering of visual objects

Browse files
Files changed (1) hide show
  1. ef.py +97 -34
ef.py CHANGED
@@ -5,7 +5,7 @@ from pypfopt.efficient_frontier import EfficientFrontier
5
  import streamlit as st
6
  import plotly.graph_objects as go
7
  import plotly.express as px
8
-
9
 
10
  ### START AND RUN STREAMLIT
11
  #https://docs.streamlit.io/library/get-started/installation
@@ -13,14 +13,7 @@ import plotly.express as px
13
  def ef_viz(stock_df,choices):
14
  #st.write("EF Visualization KOI EDITS")
15
  # st.header('CAPM Model and the Efficient Frontier')
16
- # """
17
- # CAPM model measure systematic risks, however it has unrealistic assumptions and relies heavily on a linear interpretation
18
- # of the risks vs. returns relationship. It is better to use CAPM model in conjunction with the Efficient Frontier to better
19
- # graphically depict volatility (a measure of investment risk) for the defined rate of return. <br>
20
- # Each circle depicted above is a variation of the portfolio with the same input assest, only different weights.
21
- # Portfolios with higher volatilities has a yellower shade of hue, while portfolios with a higher return has a bigger radius. <br>
22
- # As you input different porfolio assets, take note of how diversification can improve a portfolio's risk versus reward profile.
23
- # """
24
  symbols, weights, investment, rf, A_coef = choices.values()
25
  tickers = symbols
26
 
@@ -54,7 +47,7 @@ def ef_viz(stock_df,choices):
54
  p_weights = [] # Define an empty array for asset weights
55
 
56
  num_assets = len(tickers)
57
- num_portfolios = 10000
58
 
59
  for portfolio in range(num_portfolios):
60
  weights = np.random.random(num_assets)
@@ -75,14 +68,41 @@ def ef_viz(stock_df,choices):
75
  data[symbol] = [w[counter] for w in p_weights]
76
 
77
  port_ef_df = pd.DataFrame(data)
78
- #st.write(port_ef_df[tickers].T)
 
79
  ## NEEDS INPUT INSTEAD OF HARD CODE
80
  #a = 5 #the coefficient of risk aversion is A. If an invest is less risk averse A is small. We assume 25 < A < 35.
81
  #rf = 0.041
82
 
83
  min_vol_port = port_ef_df.iloc[port_ef_df['Volatility'].idxmin()]
84
  optimal_risky_port = port_ef_df.iloc[((port_ef_df['Returns']-rf)/port_ef_df['Volatility']).idxmax()]
85
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
86
 
87
  ## CREATE CAPM LINE #https://www.youtube.com/watch?v=JWx2wcrSGkk
88
  cal_x = []
@@ -91,7 +111,7 @@ def ef_viz(stock_df,choices):
91
 
92
 
93
 
94
- for er in np.linspace(rf, max(data['Returns']),20):
95
  sd = (er - rf)/ ((optimal_risky_port[0] - rf)/ optimal_risky_port[1])
96
  u = er - 0.5*A_coef*(sd**2)
97
  cal_x.append(sd)
@@ -103,28 +123,71 @@ def ef_viz(stock_df,choices):
103
  utl_df = pd.DataFrame(data2)
104
 
105
  ## Create Figure
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
106
 
107
- # fig = go.Figure()
108
- # fig.add_trace(go.Scatter(x=port_ef_df['Volatility'], y=port_ef_df['Returns'], \
109
- # color=port_ef_df['Volatility'], mode='markers', name='markers'))
110
-
111
- fig = px.scatter(port_ef_df, 'Volatility', 'Returns', size='Returns', size_max=20, color='Volatility', \
112
- custom_data=tickers)
113
- fig.update_traces(hovertemplate="<br>".join([
114
- "%{tickers[0]}:%{custom_data[0]}",
115
- "%{tickers[1]}:%{custom_data[1]}",
116
- "%{tickers[2]}:%{custom_data[2]}",
117
- "%{tickers[3]}:%{custom_data[3]}"
118
-
119
- ])
120
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
121
 
122
- fig1 = px.line(utl_df, x="cal_x", y="cal_y")
123
- fig1.update_traces(line=dict(color = 'rgba(11,156,49,1)'))
124
- #https://stackoverflow.com/questions/59057881/python-plotly-how-to-customize-hover-template-on-with-what-information-to-show
125
- #https://stackoverflow.com/questions/65124833/plotly-how-to-combine-scatter-and-line-plots-using-plotly-express
126
 
127
- fig3 = go.Figure(data=fig.data + fig1.data)
 
128
 
129
- st.plotly_chart(fig3, use_container_width=True)
130
- #st.write(stock_df)
 
 
5
  import streamlit as st
6
  import plotly.graph_objects as go
7
  import plotly.express as px
8
+ from PIL import Image
9
 
10
  ### START AND RUN STREAMLIT
11
  #https://docs.streamlit.io/library/get-started/installation
 
13
  def ef_viz(stock_df,choices):
14
  #st.write("EF Visualization KOI EDITS")
15
  # st.header('CAPM Model and the Efficient Frontier')
16
+
 
 
 
 
 
 
 
17
  symbols, weights, investment, rf, A_coef = choices.values()
18
  tickers = symbols
19
 
 
47
  p_weights = [] # Define an empty array for asset weights
48
 
49
  num_assets = len(tickers)
50
+ num_portfolios = 1000
51
 
52
  for portfolio in range(num_portfolios):
53
  weights = np.random.random(num_assets)
 
68
  data[symbol] = [w[counter] for w in p_weights]
69
 
70
  port_ef_df = pd.DataFrame(data)
71
+ port_ef_df['Vol'] = port_ef_df['Volatility']
72
+
73
  ## NEEDS INPUT INSTEAD OF HARD CODE
74
  #a = 5 #the coefficient of risk aversion is A. If an invest is less risk averse A is small. We assume 25 < A < 35.
75
  #rf = 0.041
76
 
77
  min_vol_port = port_ef_df.iloc[port_ef_df['Volatility'].idxmin()]
78
  optimal_risky_port = port_ef_df.iloc[((port_ef_df['Returns']-rf)/port_ef_df['Volatility']).idxmax()]
79
+
80
+ ### Make DF and data string for when hover over data points
81
+ def make_op_df(df, tickers):
82
+ new = {}
83
+ op_str = str()
84
+ new['Returns'] = df[0]
85
+ new['Volatility'] = df[1]
86
+
87
+ for i in range(0,len(tickers)):
88
+ new[tickers[i]]= df[i+2]
89
+ op_str += str(tickers[i]) + ': ' + str(round(df[i+2],4)) + '<br>'
90
+
91
+ return pd.DataFrame(new, index=[0]), op_str
92
+
93
+ op_df, op_str = make_op_df(optimal_risky_port, tickers)
94
+
95
+ def make_port_str(df, tickers):
96
+ port_str_lst = []
97
+ for i in range(0,len(df)):
98
+ temp = str()
99
+ for u in range(0,len(tickers)):
100
+ temp += str(tickers[u])+ ': ' + str(round(df[tickers[u]][i],4)) + '<br>'
101
+ port_str_lst.append(temp)
102
+
103
+ return port_str_lst
104
+
105
+ port_str_lst = make_port_str(port_ef_df, tickers)
106
 
107
  ## CREATE CAPM LINE #https://www.youtube.com/watch?v=JWx2wcrSGkk
108
  cal_x = []
 
111
 
112
 
113
 
114
+ for er in np.linspace(rf, max(data['Returns'])+rf,20):
115
  sd = (er - rf)/ ((optimal_risky_port[0] - rf)/ optimal_risky_port[1])
116
  u = er - 0.5*A_coef*(sd**2)
117
  cal_x.append(sd)
 
123
  utl_df = pd.DataFrame(data2)
124
 
125
  ## Create Figure
126
+ fig3 = go.Figure()
127
+
128
+ #https://plotly.com/python/colorscales/
129
+ fig3.add_trace(go.Scatter(x=port_ef_df['Volatility'], y=port_ef_df['Returns'], hovertemplate='Volatility: %{x} <br>Returns: %{y} <br>%{text}',\
130
+ text= port_str_lst, mode='markers', \
131
+ marker=dict(color=port_ef_df['Volatility'], colorbar=dict(title="Volatility"), \
132
+ size=port_ef_df['Returns']*50, cmax=max(port_ef_df['Volatility']),\
133
+ cmin=min(port_ef_df['Volatility'])),name='Portfolio'))
134
+ #, mode='markers', size=port_ef_df['Returns'], \
135
+ #size_max=30, color=port_ef_df['Vol']))
136
+ fig3.add_trace(go.Scatter(x=utl_df['cal_x'], y=utl_df['cal_y'], mode='lines', line = dict(color='rgba(11,156,49,1)'),name='Ultility Function',\
137
+ hovertemplate='Volatility: %{x} <br>Returns: %{y}')) #))
138
+
139
+ fig3.add_trace(go.Scatter(x=op_df['Volatility'], y=op_df['Returns'], mode='markers', \
140
+ marker=dict(color= 'rgba(11,156,49,1)', size=30),\
141
+ hovertemplate='Volatility: %{x} <br>Returns: %{y} <br>%{text}',\
142
+ text=[op_str]))
143
+ ### HOVER TEMPLATE # https://plotly.com/python/hover-text-and-formatting/
144
+
145
+
146
+ # ### SAVE IN CASE CANNOT FIGURE OUT THE HOVER TEMPLATE
147
+ # fig2 = px.scatter(op_df, 'Volatility', 'Returns')
148
+ # fig2.update_traces(marker=dict(color= 'rgba(11,156,49,1)', size=35))
149
+
150
+ # fig1 = px.line(utl_df, x="cal_x", y="cal_y")
151
+ # #fig1.update_traces(line=dict(color = 'rgba(11,156,49,1)'))
152
+
153
+ # fig = px.scatter(port_ef_df, 'Volatility', 'Returns', size='Returns', size_max=30, color='Vol')
154
+ # #https://stackoverflow.com/questions/59057881/python-plotly-how-to-customize-hover-template-on-with-what-information-to-show
155
+ # #https://stackoverflow.com/questions/65124833/plotly-how-to-combine-scatter-and-line-plots-using-plotly-express
156
 
157
+ # #data3 =
158
+ # fig3.data = [fig2.data,fig1.data,fig.data]
159
+ # #fig3.update_traces(line=dict(color = 'rgba(11,156,49,1)'))
160
+ # ####
161
+
162
+ fig3.update_layout(showlegend=False)#, legend_title_text = "Contestant")
163
+ fig3.update_xaxes(title_text="Volatility")
164
+ fig3.update_yaxes(title_text="Portfolio Return Rates")
165
+
166
+ st.plotly_chart(fig3, use_container_width=True)
167
+
168
+ #st.write(op_str)
169
+ op_df = op_df.style.set_properties(**{'color':'green'})
170
+ st.subheader('Optimal Returns vs Volatility and Portfolio weights')
171
+ col1, col2, col3 = st.columns([1,6,1])
172
+ with col1:
173
+ st.write("")
174
+
175
+ with col2:
176
+ st.write(op_df)
177
+
178
+ with col3:
179
+ st.write("")
180
+
181
+ im = Image.open('EFvsMinvar.png')
182
+ st.subheader('Understand the Efficient Frontier')
183
+ col1, col2, col3 = st.columns([1,6,1])
184
 
185
+ with col1:
186
+ st.write("")
 
 
187
 
188
+ with col2:
189
+ st.image(im, caption='Elements of the Efficient Frontier',use_column_width='auto')
190
 
191
+ with col3:
192
+ st.write("")
193
+