aiqtech commited on
Commit
b277084
ยท
verified ยท
1 Parent(s): b851497

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +143 -64
app.py CHANGED
@@ -1,21 +1,17 @@
1
  import gradio as gr
2
  import yfinance as yf
3
- from datetime import datetime # ์ด ๋ถ€๋ถ„์„ ์ถ”๊ฐ€ํ•˜์„ธ์š”.
4
  from pypfopt.discrete_allocation import DiscreteAllocation, get_latest_prices
5
  from pypfopt import EfficientFrontier
6
  from pypfopt import risk_models
7
  from pypfopt import expected_returns
8
- import matplotlib.pyplot as plt
9
- if "seaborn-deep" in plt.style.available:
10
- plt.style.use("seaborn-deep")
11
- else:
12
- print("'seaborn-deep' ์Šคํƒ€์ผ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ ์Šคํƒ€์ผ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.")
13
- plt.style.use("default")
14
  from pypfopt import plotting
15
  import copy
16
  import numpy as np
17
  import pandas as pd
18
  import plotly.express as px
 
 
 
19
 
20
  def plot_cum_returns(data, title, initial_capital=1000):
21
  # ์ผ์ผ ๋ˆ„์  ์ˆ˜์ต๋ฅ  ๊ณ„์‚ฐ ๋ฐ ์‹œ๊ฐํ™”
@@ -44,10 +40,105 @@ def plot_weights(weights):
44
  ax.axis('equal')
45
  return fig
46
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  def output_results(start_date, end_date, tickers_string):
48
  tickers = tickers_string.split(',')
49
  stocks_df = yf.download(tickers, start=start_date, end=end_date)['Adj Close']
50
-
51
  tickers_info = {}
52
  news_data = {}
53
  for ticker in tickers:
@@ -62,7 +153,6 @@ def output_results(start_date, end_date, tickers_string):
62
  fig_cum_returns = px.line(daily_cum_returns, title='๊ฐœ๋ณ„ ์ฃผ์‹์˜ ๋ˆ„์  ์ˆ˜์ต๋ฅ  ($1,000 ์‹œ์ž‘)')
63
  corr_df = stocks_df.corr().round(2)
64
  fig_corr = px.imshow(corr_df, text_auto=True, title='์ฃผ์‹ ๊ฐ„ ์ƒ๊ด€ ๊ด€๊ณ„')
65
-
66
  mu = expected_returns.mean_historical_return(stocks_df)
67
  S = risk_models.sample_cov(stocks_df)
68
  ef = EfficientFrontier(mu, S)
@@ -79,59 +169,48 @@ def output_results(start_date, end_date, tickers_string):
79
  for ticker in tickers
80
  ])
81
 
 
 
 
 
82
  return fig_cum_returns, fig_efficient_frontier, fig_corr, fig_indiv_prices, fig_weights, \
83
- f"{expected_annual_return*100:.2f}%", f"{annual_volatility*100:.2f}%", f"{sharpe_ratio:.2f}", ticker_info_output
84
-
85
- def predict_stock(ticker):
86
- data = yf.download(ticker, start="2019-01-01")['Close'].reset_index()
87
- data.rename(columns={'Date': 'ds', 'Close': 'y'}, inplace=True)
88
-
89
- model = Prophet(daily_seasonality=False, yearly_seasonality=True)
90
- model.fit(data)
91
-
92
- future = model.make_future_dataframe(periods=5 * 365, freq='D')
93
- forecast = model.predict(future)
94
-
95
- fig = plot_plotly(model, forecast)
96
- fig.update_layout(title=f'5-Year Forecast for {ticker}')
97
-
98
- return forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail(365 * 5), fig
99
-
100
- def setup_ui():
101
- with gr.Blocks() as app:
102
- with gr.Tabs() as tabs:
103
- with gr.TabItem("ํฌํŠธํด๋ฆฌ์˜ค ๋ถ„์„"):
104
- # ํฌํŠธํด๋ฆฌ์˜ค ๋ถ„์„ ์ฝ”๋“œ
105
- with gr.Row():
106
- start_date = gr.Textbox("2013-01-01", label="์‹œ์ž‘ ์ผ์ž")
107
- end_date = gr.Textbox(datetime.now().date(), label="์ข…๋ฃŒ ์ผ์ž")
108
- tickers_string = gr.Textbox("NVDA,^GSPC,GC=F,MSFT,BTC-USD", label="์ฃผ์‹ ํ‹ฐ์ปค๋ฅผ ์‰ผํ‘œ๋กœ ๊ตฌ๋ถ„ํ•˜์—ฌ ์ž…๋ ฅํ•˜์„ธ์š”")
109
- analyze_button = gr.Button("ํฌํŠธํด๋ฆฌ์˜ค ์ตœ์ ํ™” ๊ฒฐ๊ณผ ๋ณด๊ธฐ")
110
-
111
- # ํฌํŠธํด๋ฆฌ์˜ค ๊ฒฐ๊ณผ ์ถœ๋ ฅ ๊ตฌ์—ญ
112
- with gr.Row():
113
- expected_annual_return = gr.Text(label="์˜ˆ์ƒ ์—ฐ๊ฐ„ ์ˆ˜์ต๋ฅ ")
114
- annual_volatility = gr.Text(label="์—ฐ๊ฐ„ ๋ณ€๋™์„ฑ")
115
- sharpe_ratio = gr.Text(label="์ƒคํ”„ ๋น„์œจ")
116
- with gr.Column():
117
- fig_cum_returns = gr.Plot(label="์ตœ์ ํ™”๋œ ํฌํŠธํด๋ฆฌ์˜ค์˜ ๋ˆ„์  ์ˆ˜์ต๋ฅ  (์‹œ์ž‘ ๊ฐ€๊ฒฉ $1,000)")
118
- fig_efficient_frontier = gr.Plot(label="ํšจ์œจ์  ํˆฌ์ž์„ ")
119
- fig_corr = gr.Plot(label="์ฃผ์‹ ๊ฐ„ ์ƒ๊ด€ ๊ด€๊ณ„")
120
- fig_indiv_prices = gr.Plot(label="๊ฐœ๋ณ„ ์ฃผ์‹ ๊ฐ€๊ฒฉ")
121
- fig_weights = gr.Plot(label="ํฌํŠธํด๋ฆฌ์˜ค ์ตœ์  ํˆฌ์ž ๋น„์œจ")
122
- ticker_info_output = gr.Textbox(label="ํ‹ฐ์ปค ์ •๋ณด ๋ฐ ๋‰ด์Šค")
123
- analyze_button.click(fn=output_results, inputs=[start_date, end_date, tickers_string], outputs=[fig_cum_returns, fig_efficient_frontier, fig_corr, fig_indiv_prices, fig_weights, expected_annual_return, annual_volatility, sharpe_ratio, ticker_info_output])
124
-
125
- with gr.TabItem("๋ฏธ๋ž˜ ์ฃผ๊ฐ€ ์˜ˆ์ธก"):
126
- with gr.Column():
127
- ticker_input = gr.Textbox(value="AAPL", label="Enter Stock Ticker")
128
- forecast_button = gr.Button("Generate Forecast")
129
- forecast_output = gr.Textbox(label="Forecast Data")
130
- forecast_chart = gr.Plot(label="Forecast Chart")
131
-
132
- forecast_button.click(fn=predict_stock, inputs=[ticker_input], outputs=[forecast_output, forecast_chart])
133
-
134
- return app
135
-
136
- app = setup_ui()
137
- app.launch()
 
1
  import gradio as gr
2
  import yfinance as yf
 
3
  from pypfopt.discrete_allocation import DiscreteAllocation, get_latest_prices
4
  from pypfopt import EfficientFrontier
5
  from pypfopt import risk_models
6
  from pypfopt import expected_returns
 
 
 
 
 
 
7
  from pypfopt import plotting
8
  import copy
9
  import numpy as np
10
  import pandas as pd
11
  import plotly.express as px
12
+ import matplotlib.pyplot as plt
13
+ from matplotlib import gridspec
14
+ from datetime import datetime
15
 
16
  def plot_cum_returns(data, title, initial_capital=1000):
17
  # ์ผ์ผ ๋ˆ„์  ์ˆ˜์ต๋ฅ  ๊ณ„์‚ฐ ๋ฐ ์‹œ๊ฐํ™”
 
40
  ax.axis('equal')
41
  return fig
42
 
43
+ def plot_top_ticker_graphs(top_ticker, stock_data, portfolio_data, weights):
44
+ fig = plt.figure(figsize=(20, 20))
45
+ gs = gridspec.GridSpec(5, 2, wspace=0.3, hspace=0.3)
46
+
47
+ ax1 = plt.subplot(gs[0, 0])
48
+ # ํฌํŠธํด๋ฆฌ์˜ค ๋‚ด ์ž์‚ฐ ๋ฐฐ๋ถ„ ๋น„์œจ ๊ทธ๋ž˜ํ”„ (๋ง‰๋Œ€ ๊ทธ๋ž˜ํ”„ ๋˜๋Š” ํŒŒ์ด ์ฐจํŠธ)
49
+ ax1.pie(list(weights.values()), labels=list(weights.keys()), autopct='%1.1f%%')
50
+ ax1.axis('equal')
51
+ ax1.set_title('Portfolio Asset Allocation')
52
+
53
+ ax2 = plt.subplot(gs[0, 1])
54
+ # ํฌํŠธํด๋ฆฌ์˜ค์˜ ์—ฐ๊ฐ„ ์ˆ˜์ต๋ฅ  ๋ฐ ๋ณ€๋™์„ฑ ์ถ”์ด ๊ทธ๋ž˜ํ”„
55
+ portfolio_returns = portfolio_data.pct_change().dropna()
56
+ portfolio_returns = (portfolio_returns + 1).cumprod()
57
+ portfolio_returns.plot(ax=ax2)
58
+ ax2.set_title('Portfolio Annual Returns and Volatility')
59
+ ax2.set_ylabel('Cumulative Returns')
60
+
61
+ ax3 = plt.subplot(gs[1, 0])
62
+ # ํฌํŠธํด๋ฆฌ์˜ค์˜ ์ƒคํ”„ ๋น„์œจ(Sharpe Ratio) ์ถ”์ด ๊ทธ๋ž˜ํ”„
63
+ sharpe_ratio = portfolio_returns.mean() / portfolio_returns.std() * np.sqrt(252)
64
+ sharpe_ratio.plot(ax=ax3)
65
+ ax3.set_title('Portfolio Sharpe Ratio')
66
+ ax3.set_ylabel('Sharpe Ratio')
67
+
68
+ ax4 = plt.subplot(gs[1, 1])
69
+ # ๊ฐœ๋ณ„ ์ฃผ์‹์˜ ์›”๋ณ„ ์ˆ˜์ต๋ฅ  ๊ทธ๋ž˜ํ”„
70
+ stock_data[top_ticker].resample('M').last().pct_change().plot(ax=ax4)
71
+ ax4.set_title(f'{top_ticker} Monthly Returns')
72
+ ax4.set_ylabel('Returns')
73
+
74
+ ax5 = plt.subplot(gs[2, 0])
75
+ # ๊ฐœ๋ณ„ ์ฃผ์‹์˜ ์—ฐ๊ฐ„ ์ˆ˜์ต๋ฅ  ๊ทธ๋ž˜ํ”„
76
+ stock_data[top_ticker].resample('Y').last().pct_change().plot(ax=ax5)
77
+ ax5.set_title(f'{top_ticker} Annual Returns')
78
+ ax5.set_ylabel('Returns')
79
+
80
+ ax6 = plt.subplot(gs[2, 1])
81
+ # ๊ฐœ๋ณ„ ์ฃผ์‹์˜ ์ด๋™ํ‰๊ท ์„ (์˜ˆ: 20์ผ, 50์ผ, 200์ผ) ๊ทธ๋ž˜ํ”„
82
+ stock_data[top_ticker].plot(ax=ax6)
83
+ stock_data[top_ticker].rolling(window=20).mean().plot(ax=ax6, label='20-day MA')
84
+ stock_data[top_ticker].rolling(window=50).mean().plot(ax=ax6, label='50-day MA')
85
+ stock_data[top_ticker].rolling(window=200).mean().plot(ax=ax6, label='200-day MA')
86
+ ax6.set_title(f'{top_ticker} Moving Averages')
87
+ ax6.set_ylabel('Price')
88
+ ax6.legend()
89
+
90
+ ax7 = plt.subplot(gs[3, 0])
91
+ # ํฌํŠธํด๋ฆฌ์˜ค์˜ ๋“œ๋กœ๋‹ค์šด(Drawdown) ๊ทธ๋ž˜ํ”„
92
+ portfolio_drawdown = (portfolio_returns.cummax() - portfolio_returns) / portfolio_returns.cummax()
93
+ portfolio_drawdown.plot(ax=ax7)
94
+ ax7.set_title('Portfolio Drawdown')
95
+ ax7.set_ylabel('Drawdown')
96
+
97
+ ax8 = plt.subplot(gs[3, 1])
98
+ # ๊ฐœ๋ณ„ ์ฃผ์‹์˜ RSI(Relative Strength Index) ๊ทธ๋ž˜ํ”„
99
+ delta = stock_data[top_ticker].diff()
100
+ up = delta.clip(lower=0)
101
+ down = -1 * delta.clip(upper=0)
102
+ ema_up = up.ewm(com=13, adjust=False).mean()
103
+ ema_down = down.ewm(com=13, adjust=False).mean()
104
+ rs = ema_up / ema_down
105
+ rsi = 100 - (100 / (1 + rs))
106
+ rsi.plot(ax=ax8)
107
+ ax8.set_title(f'{top_ticker} RSI')
108
+ ax8.set_ylabel('RSI')
109
+
110
+ ax9 = plt.subplot(gs[4, 0])
111
+ # ๊ฐœ๋ณ„ ์ฃผ์‹์˜ MACD(Moving Average Convergence Divergence) ๊ทธ๋ž˜ํ”„
112
+ exp1 = stock_data[top_ticker].ewm(span=12, adjust=False).mean()
113
+ exp2 = stock_data[top_ticker].ewm(span=26, adjust=False).mean()
114
+ macd = exp1 - exp2
115
+ signal = macd.ewm(span=9, adjust=False).mean()
116
+ ax9.plot(macd, label='MACD')
117
+ ax9.plot(signal, label='Signal')
118
+ ax9.set_title(f'{top_ticker} MACD')
119
+ ax9.set_ylabel('MACD')
120
+ ax9.legend()
121
+
122
+ ax10 = plt.subplot(gs[4, 1])
123
+ # ๊ฐœ๋ณ„ ์ฃผ์‹์˜ ๋ณผ๋ฆฐ์ € ๋ฐด๋“œ(Bollinger Bands) ๊ทธ๋ž˜ํ”„
124
+ rolling_mean = stock_data[top_ticker].rolling(window=20).mean()
125
+ rolling_std = stock_data[top_ticker].rolling(window=20).std()
126
+ upper_band = rolling_mean + (rolling_std * 2)
127
+ lower_band = rolling_mean - (rolling_std * 2)
128
+ ax10.plot(stock_data[top_ticker], label='Price')
129
+ ax10.plot(rolling_mean, label='Moving Average')
130
+ ax10.plot(upper_band, label='Upper Band')
131
+ ax10.plot(lower_band, label='Lower Band')
132
+ ax10.set_title(f'{top_ticker} Bollinger Bands')
133
+ ax10.set_ylabel('Price')
134
+ ax10.legend()
135
+
136
+ plt.tight_layout()
137
+ return fig
138
+
139
  def output_results(start_date, end_date, tickers_string):
140
  tickers = tickers_string.split(',')
141
  stocks_df = yf.download(tickers, start=start_date, end=end_date)['Adj Close']
 
142
  tickers_info = {}
143
  news_data = {}
144
  for ticker in tickers:
 
153
  fig_cum_returns = px.line(daily_cum_returns, title='๊ฐœ๋ณ„ ์ฃผ์‹์˜ ๋ˆ„์  ์ˆ˜์ต๋ฅ  ($1,000 ์‹œ์ž‘)')
154
  corr_df = stocks_df.corr().round(2)
155
  fig_corr = px.imshow(corr_df, text_auto=True, title='์ฃผ์‹ ๊ฐ„ ์ƒ๊ด€ ๊ด€๊ณ„')
 
156
  mu = expected_returns.mean_historical_return(stocks_df)
157
  S = risk_models.sample_cov(stocks_df)
158
  ef = EfficientFrontier(mu, S)
 
169
  for ticker in tickers
170
  ])
171
 
172
+ # ๊ฐ€์žฅ ์ˆ˜์ต๋ฅ ๊ณผ ๋น„์ค‘์ด ํฐ ์ข…๋ชฉ ์„ ํƒ
173
+ top_ticker = max(cleaned_weights, key=cleaned_weights.get)
174
+ fig_top_ticker = plot_top_ticker_graphs(top_ticker, stocks_df, daily_cum_returns[top_ticker], cleaned_weights)
175
+
176
  return fig_cum_returns, fig_efficient_frontier, fig_corr, fig_indiv_prices, fig_weights, \
177
+ f"{expected_annual_return*100:.2f}%", f"{annual_volatility*100:.2f}%", f"{sharpe_ratio:.2f}", \
178
+ ticker_info_output, fig_top_ticker
179
+
180
+ css = """footer { visibility: hidden; }"""
181
+
182
+ with gr.Blocks(css=css) as app:
183
+ gr.Markdown("""
184
+ <style>
185
+ .markdown-text h2 {
186
+ font-size: 18px; # ํฐํŠธ ํฌ๊ธฐ๋ฅผ 18px๋กœ ์„ค์ •
187
+ }
188
+ </style>
189
+ <h2>AIQ ์ž์‚ฐ ํฌํŠธํด๋ฆฌ์˜ค: ๊ธ€๋กœ๋ฒŒ ์ž์‚ฐ(์ฃผ์‹, ์ง€์ˆ˜, BTC, ์ƒํ’ˆ ๋“ฑ) AI ํฌํŠธํด๋ฆฌ์˜ค ์ตœ์ ํ™” ์„œ๋น„์Šค</h2>
190
+ <h2>์ „์„ธ๊ณ„ ๋ชจ๋“  ํ‹ฐ์ปค ๋ณด๊ธฐ(์•ผํ›„ ํŒŒ์ด๋‚ธ์Šค): <a href="https://finance.yahoo.com/most-active" target="_blank">์—ฌ๊ธฐ๋ฅผ ํด๋ฆญ</a></h2>
191
+ """)
192
+ with gr.Row():
193
+ start_date = gr.Textbox("2013-01-01", label="์‹œ์ž‘ ์ผ์ž")
194
+ end_date = gr.Textbox(datetime.now().date(), label="์ข…๋ฃŒ ์ผ์ž")
195
+ tickers_string = gr.Textbox("NVDA,^GSPC,GC=F,MSFT,BTC-USD", label="์ฃผ์‹ ํ‹ฐ์ปค๋ฅผ ์‰ผํ‘œ๋กœ ๊ตฌ๋ถ„ํ•˜์—ฌ ์ž…๋ ฅํ•˜์„ธ์š”")
196
+ btn = gr.Button("ํฌํŠธํด๋ฆฌ์˜ค ์ตœ์ ํ™” ๊ฒฐ๊ณผ ๋ณด๊ธฐ")
197
+
198
+ with gr.Row():
199
+ expected_annual_return = gr.Text(label="์˜ˆ์ƒ ์—ฐ๊ฐ„ ์ˆ˜์ต๋ฅ ")
200
+ annual_volatility = gr.Text(label="์—ฐ๊ฐ„ ๋ณ€๋™์„ฑ")
201
+ sharpe_ratio = gr.Text(label="์ƒคํ”„ ๋น„์œจ")
202
+
203
+ with gr.Column():
204
+ fig_cum_returns = gr.Plot(label="์ตœ์ ํ™”๋œ ํฌํŠธํด๋ฆฌ์˜ค์˜ ๋ˆ„์  ์ˆ˜์ต๋ฅ  (์‹œ์ž‘ ๊ฐ€๊ฒฉ $1,000)")
205
+ fig_efficient_frontier = gr.Plot(label="ํšจ์œจ์  ํˆฌ์ž์„ ")
206
+ fig_corr = gr.Plot(label="์ฃผ์‹ ๊ฐ„ ์ƒ๊ด€ ๊ด€๊ณ„")
207
+ fig_indiv_prices = gr.Plot(label="๊ฐœ๋ณ„ ์ฃผ์‹ ๊ฐ€๊ฒฉ")
208
+ fig_weights = gr.Plot(label="ํฌํŠธํด๋ฆฌ์˜ค ์ตœ์  ํˆฌ์ž ๋น„์œจ")
209
+ fig_top_ticker = gr.Plot(label="๊ฐ€์žฅ ์ˆ˜์ต๋ฅ ๊ณผ ๋น„์ค‘์ด ํฐ ์ข…๋ชฉ์˜ ๊ทธ๋ž˜ํ”„")
210
+ ticker_info_output = gr.Textbox(label="ํ‹ฐ์ปค ์ •๋ณด ๋ฐ ๋‰ด์Šค")
211
+
212
+ btn.click(fn=output_results, inputs=[start_date, end_date, tickers_string],
213
+ outputs=[fig_cum_returns, fig_efficient_frontier, fig_corr, fig_indiv_prices, fig_weights,
214
+ expected_annual_return, annual_volatility, sharpe_ratio, ticker_info_output, fig_top_ticker])
215
+
216
+ app.launch()