kimappl commited on
Commit
08029e1
·
verified ·
1 Parent(s): 5a59b95

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +142 -0
app.py ADDED
@@ -0,0 +1,142 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import pandas as pd
3
+ import numpy as np
4
+ import matplotlib.pyplot as plt
5
+ import plotly.express as px
6
+ import scipy.optimize as sco
7
+ from datetime import datetime, timedelta
8
+ import requests
9
+ import random
10
+
11
+ # Predefined S&P 500 Stock List (Example Tickers, replace with real ones if needed)
12
+ SP500_TICKERS = ['AAPL', 'MSFT', 'GOOGL', 'AMZN', 'TSLA', 'BRK-B', 'NVDA', 'JPM', 'JNJ', 'V', 'PG', 'UNH', 'HD', 'MA', 'DIS', 'PYPL', 'NFLX', 'KO', 'XOM', 'PFE']
13
+
14
+ def fetch_stock_data(tickers, start_date, end_date):
15
+ url = "https://yahoo-finance166.p.rapidapi.com/api/news/list-by-symbol"
16
+ querystring = {"s": ",".join(tickers), "region": "US", "snippetCount": "500"}
17
+ headers = {
18
+ "x-rapidapi-key": "YOUR_RAPIDAPI_KEY",
19
+ "x-rapidapi-host": "yahoo-finance166.p.rapidapi.com"
20
+ }
21
+ try:
22
+ response = requests.get(url, headers=headers, params=querystring)
23
+ data = response.json()
24
+ if not data:
25
+ raise ValueError("No stock data returned. Please check the API response.")
26
+ return pd.DataFrame(data)
27
+ except Exception as e:
28
+ return f"Error fetching stock data: {str(e)}"
29
+
30
+ def calculate_portfolio_metrics(weights, returns):
31
+ portfolio_return = np.sum(returns.mean() * weights) * 252
32
+ portfolio_volatility = np.sqrt(np.dot(weights.T, np.dot(returns.cov() * 252, weights)))
33
+ sharpe_ratio = portfolio_return / portfolio_volatility
34
+ return portfolio_return, portfolio_volatility, sharpe_ratio
35
+
36
+ def optimize_portfolio(returns, max_volatility):
37
+ num_assets = len(returns.columns)
38
+ args = (returns,)
39
+ constraints = (
40
+ {'type': 'eq', 'fun': lambda x: np.sum(x) - 1}, # Sum of weights must be 1
41
+ {'type': 'ineq', 'fun': lambda x: max_volatility - np.sqrt(np.dot(x.T, np.dot(returns.cov() * 252, x)))} # Volatility constraint
42
+ )
43
+ bounds = tuple((0, 1) for _ in range(num_assets))
44
+ result = sco.minimize(lambda weights, returns: -calculate_portfolio_metrics(weights, returns)[2],
45
+ num_assets * [1. / num_assets,],
46
+ args=args,
47
+ method='SLSQP',
48
+ bounds=bounds,
49
+ constraints=constraints)
50
+ return result.x
51
+ num_assets = len(returns.columns)
52
+ args = (returns,)
53
+ constraints = (
54
+ {'type': 'eq', 'fun': lambda x: np.sum(x) - 1}, # Sum of weights must be 1
55
+ )
56
+ bounds = tuple((0, 1) for _ in range(num_assets))
57
+ result = sco.minimize(lambda weights, returns: -calculate_portfolio_metrics(weights, returns)[2],
58
+ num_assets * [1. / num_assets,],
59
+ args=args,
60
+ method='SLSQP',
61
+ bounds=bounds,
62
+ constraints=constraints)
63
+ return result.x
64
+
65
+ def simulate_investment(weights, mu, years, initial_investment=1000):
66
+ projected_return = np.dot(weights, mu) * years
67
+ return initial_investment * (1 + projected_return)
68
+
69
+ def output_results(risk_level):
70
+ try:
71
+ start_date = (datetime.now() - timedelta(days=365 * 5)).strftime('%Y-%m-%d')
72
+ end_date = datetime.now().strftime('%Y-%m-%d')
73
+ selected_tickers = random.sample(SP500_TICKERS, 15)
74
+
75
+ stocks_df = fetch_stock_data(selected_tickers, start_date, end_date)
76
+ if isinstance(stocks_df, str):
77
+ return stocks_df, None, None, "Error", "Error", "Error", None, None, None
78
+
79
+ returns = stocks_df.pct_change().dropna()
80
+ risk_thresholds = {"Low": 0.10, "Medium": 0.20, "High": 0.30}
81
+ max_volatility = risk_thresholds.get(risk_level, 0.20)
82
+ optimized_weights = optimize_portfolio(returns, max_volatility)
83
+ mu = returns.mean() * 252
84
+ portfolio_return, portfolio_volatility, sharpe_ratio = calculate_portfolio_metrics(optimized_weights, returns)
85
+
86
+ expected_annual_return = f'{(portfolio_return * 100):.2f}%'
87
+ annual_volatility = f'{(portfolio_volatility * 100):.2f}%'
88
+ sharpe_ratio_str = f'{sharpe_ratio:.2f}'
89
+
90
+ weights_df = pd.DataFrame({'Ticker': selected_tickers, 'Weight': optimized_weights})
91
+ correlation_matrix = stocks_df.corr()
92
+ fig_corr = px.imshow(correlation_matrix, text_auto=True, title='Stock Correlation Matrix')
93
+ cumulative_returns = (returns + 1).cumprod()
94
+ fig_cum_returns = px.line(cumulative_returns, title='Cumulative Returns of Individual Stocks')
95
+
96
+ projected_1yr = simulate_investment(optimized_weights, mu, 1)
97
+ projected_5yr = simulate_investment(optimized_weights, mu, 5)
98
+ projected_10yr = simulate_investment(optimized_weights, mu, 10)
99
+ projection_df = pd.DataFrame({"Years": [1, 5, 10], "Projected Value": [projected_1yr, projected_5yr, projected_10yr]})
100
+ fig_simulation = px.line(projection_df, x='Years', y='Projected Value', title='Projected Investment Growth')
101
+
102
+ return fig_cum_returns, weights_df, fig_corr, expected_annual_return, annual_volatility, sharpe_ratio_str, fig_simulation
103
+ except Exception as e:
104
+ return f"Unexpected error: {str(e)}", None, None, "Error", "Error", "Error", None, None, None
105
+
106
+ with gr.Blocks(theme=gr.themes.Soft(primary_hue='yellow')) as app:
107
+ gr.Markdown("## Beginner-Friendly Investment Portfolio Generator")
108
+ gr.Markdown("Select your risk level and let the app generate a balanced portfolio based on the S&P 500.")
109
+
110
+ risk_level = gr.Radio(["Low", "Medium", "High"], label="Select Your Risk Level")
111
+ btn = gr.Button("Generate Portfolio", elem_id='highlighted-button')
112
+
113
+ with gr.Row():
114
+ expected_annual_return = gr.Textbox(label="Expected Annual Return")
115
+ annual_volatility = gr.Textbox(label="Annual Volatility")
116
+ sharpe_ratio = gr.Textbox(label="Sharpe Ratio")
117
+
118
+ with gr.Row():
119
+ fig_cum_returns = gr.Plot(label="Cumulative Returns of Individual Stocks")
120
+ weights_df = gr.DataFrame(label="Optimized Weights")
121
+
122
+ with gr.Row():
123
+ fig_corr = gr.Plot(label="Stock Correlation Matrix")
124
+ fig_simulation = gr.Plot(label="Projected Investment Growth")
125
+
126
+ btn.click(output_results, inputs=[risk_level], outputs=[
127
+ fig_cum_returns, weights_df, fig_corr, expected_annual_return,
128
+ annual_volatility, sharpe_ratio, fig_simulation
129
+ ])
130
+
131
+ app.css = """
132
+ #highlighted-button {
133
+ background-color: yellow !important;
134
+ font-weight: bold;
135
+ border: 2px solid black;
136
+ padding: 10px;
137
+ font-size: 16px;
138
+ cursor: pointer;
139
+ }
140
+ """
141
+
142
+ app.launch()