kimappl commited on
Commit
bc56d83
·
verified ·
1 Parent(s): df9fef1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +152 -2
app.py CHANGED
@@ -62,8 +62,158 @@ def generate_sample_data(tickers):
62
 
63
  return pd.DataFrame(data, index=dates)
64
 
65
- # Rest of the code remains the same...
66
- [Previous code from calculate_portfolio_metrics through the Gradio interface remains unchanged]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
67
 
68
  if __name__ == "__main__":
69
  app.launch()
 
62
 
63
  return pd.DataFrame(data, index=dates)
64
 
65
+ # Predefined S&P 500 Stock List (Sample tickers)
66
+ SP500_TICKERS = ['AAPL', 'MSFT', 'GOOGL', 'AMZN', 'TSLA', 'BRK-B', 'NVDA', 'JPM', 'JNJ', 'V']
67
+
68
+ def calculate_portfolio_metrics(weights, returns):
69
+ portfolio_return = np.sum(returns.mean() * weights) * 252
70
+ portfolio_volatility = np.sqrt(np.dot(weights.T, np.dot(returns.cov() * 252, weights)))
71
+ sharpe_ratio = portfolio_return / portfolio_volatility
72
+ return portfolio_return, portfolio_volatility, sharpe_ratio
73
+
74
+ def optimize_portfolio(returns, max_volatility):
75
+ num_assets = len(returns.columns)
76
+ args = (returns,)
77
+ constraints = (
78
+ {'type': 'eq', 'fun': lambda x: np.sum(x) - 1}, # Sum of weights must be 1
79
+ {'type': 'ineq', 'fun': lambda x: max_volatility - np.sqrt(np.dot(x.T, np.dot(returns.cov() * 252, x)))}
80
+ )
81
+ bounds = tuple((0, 1) for _ in range(num_assets))
82
+
83
+ result = sco.minimize(
84
+ lambda weights, returns: -calculate_portfolio_metrics(weights, returns)[2],
85
+ num_assets * [1. / num_assets,],
86
+ args=args,
87
+ method='SLSQP',
88
+ bounds=bounds,
89
+ constraints=constraints
90
+ )
91
+ return result.x
92
+
93
+ def simulate_investment(weights, mu, years, initial_investment=10000):
94
+ projected_return = np.dot(weights, mu) * years
95
+ return initial_investment * (1 + projected_return)
96
+
97
+ def output_results(risk_level):
98
+ try:
99
+ # Select random tickers
100
+ selected_tickers = random.sample(SP500_TICKERS, min(len(SP500_TICKERS), 5))
101
+
102
+ # Fetch real stock data
103
+ stocks_df = fetch_stock_data(selected_tickers)
104
+
105
+ if stocks_df.empty:
106
+ raise ValueError("No stock data received")
107
+
108
+ returns = stocks_df.pct_change().dropna()
109
+
110
+ # Set risk thresholds
111
+ risk_thresholds = {"Low": 0.15, "Medium": 0.25, "High": 0.35}
112
+ max_volatility = risk_thresholds.get(risk_level, 0.25)
113
+
114
+ # Calculate optimal portfolio
115
+ optimized_weights = optimize_portfolio(returns, max_volatility)
116
+ mu = returns.mean() * 252
117
+ portfolio_return, portfolio_volatility, sharpe_ratio = calculate_portfolio_metrics(optimized_weights, returns)
118
+
119
+ # Format metrics
120
+ expected_annual_return = f'{(portfolio_return * 100):.2f}%'
121
+ annual_volatility = f'{(portfolio_volatility * 100):.2f}%'
122
+ sharpe_ratio_str = f'{sharpe_ratio:.2f}'
123
+
124
+ # Create visualizations
125
+ weights_df = pd.DataFrame({
126
+ 'Ticker': selected_tickers,
127
+ 'Weight': [f'{w:.2%}' for w in optimized_weights]
128
+ })
129
+
130
+ # Correlation matrix
131
+ correlation_matrix = returns.corr()
132
+ fig_corr = px.imshow(
133
+ correlation_matrix,
134
+ text_auto=True,
135
+ title='Stock Correlation Matrix',
136
+ color_continuous_scale='RdBu'
137
+ )
138
+
139
+ # Cumulative returns
140
+ cumulative_returns = (1 + returns).cumprod()
141
+ fig_cum_returns = px.line(
142
+ cumulative_returns,
143
+ title='Cumulative Returns of Individual Stocks'
144
+ )
145
+
146
+ # Investment projection
147
+ projected_1yr = simulate_investment(optimized_weights, mu, 1)
148
+ projected_5yr = simulate_investment(optimized_weights, mu, 5)
149
+ projected_10yr = simulate_investment(optimized_weights, mu, 10)
150
+
151
+ projection_df = pd.DataFrame({
152
+ "Years": [1, 5, 10],
153
+ "Projected Value": [projected_1yr, projected_5yr, projected_10yr]
154
+ })
155
+
156
+ fig_simulation = px.line(
157
+ projection_df,
158
+ x='Years',
159
+ y='Projected Value',
160
+ title='Projected $10,000 Investment Growth'
161
+ )
162
+
163
+ return (
164
+ fig_cum_returns,
165
+ weights_df,
166
+ fig_corr,
167
+ expected_annual_return,
168
+ annual_volatility,
169
+ sharpe_ratio_str,
170
+ fig_simulation
171
+ )
172
+
173
+ except Exception as e:
174
+ print(f"Error in output_results: {str(e)}")
175
+ return None, None, None, f"Error: {str(e)}", "Error", "Error", None
176
+
177
+ # Create Gradio interface
178
+ with gr.Blocks(theme=gr.themes.Soft()) as app:
179
+ gr.Markdown("## Investment Portfolio Generator")
180
+ gr.Markdown("Select your risk level to generate a balanced portfolio based on S&P 500 stocks.")
181
+
182
+ with gr.Row():
183
+ risk_level = gr.Radio(
184
+ ["Low", "Medium", "High"],
185
+ label="Select Your Risk Level",
186
+ value="Medium"
187
+ )
188
+
189
+ btn = gr.Button("Generate Portfolio")
190
+
191
+ with gr.Row():
192
+ expected_annual_return = gr.Textbox(label="Expected Annual Return")
193
+ annual_volatility = gr.Textbox(label="Annual Volatility")
194
+ sharpe_ratio = gr.Textbox(label="Sharpe Ratio")
195
+
196
+ with gr.Row():
197
+ fig_cum_returns = gr.Plot(label="Cumulative Returns")
198
+ weights_df = gr.DataFrame(label="Portfolio Weights")
199
+
200
+ with gr.Row():
201
+ fig_corr = gr.Plot(label="Correlation Matrix")
202
+ fig_simulation = gr.Plot(label="Investment Projection")
203
+
204
+ btn.click(
205
+ output_results,
206
+ inputs=[risk_level],
207
+ outputs=[
208
+ fig_cum_returns,
209
+ weights_df,
210
+ fig_corr,
211
+ expected_annual_return,
212
+ annual_volatility,
213
+ sharpe_ratio,
214
+ fig_simulation
215
+ ]
216
+ )
217
 
218
  if __name__ == "__main__":
219
  app.launch()