aiqtech commited on
Commit
a5272ad
ยท
verified ยท
1 Parent(s): 6b2b41e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +13 -109
app.py CHANGED
@@ -10,7 +10,6 @@ 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):
@@ -40,105 +39,16 @@ def plot_weights(weights):
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,6 +63,7 @@ def output_results(start_date, end_date, tickers_string):
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,16 +80,14 @@ def output_results(start_date, end_date, tickers_string):
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>
@@ -194,23 +103,18 @@ with gr.Blocks(css=css) as app:
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()
 
10
  import pandas as pd
11
  import plotly.express as px
12
  import matplotlib.pyplot as plt
 
13
  from datetime import datetime
14
 
15
  def plot_cum_returns(data, title, initial_capital=1000):
 
39
  ax.axis('equal')
40
  return fig
41
 
42
+ def plot_individual_volatility(data):
43
+ # ๊ฐœ๋ณ„ ์ฃผ์‹์˜ ๋ณ€๋™์„ฑ ๊ทธ๋ž˜ํ”„ ์ถœ๋ ฅ
44
+ rolling_std = data.pct_change().rolling(window=30).std() * np.sqrt(252)
45
+ fig = px.line(rolling_std, title='๊ฐœ๋ณ„ ์ฃผ์‹์˜ ๋ณ€๋™์„ฑ (30์ผ ๋กค๋ง ์—ฐ๊ฐ„ํ™”)')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  return fig
47
 
48
  def output_results(start_date, end_date, tickers_string):
49
  tickers = tickers_string.split(',')
50
  stocks_df = yf.download(tickers, start=start_date, end=end_date)['Adj Close']
51
+
52
  tickers_info = {}
53
  news_data = {}
54
  for ticker in tickers:
 
63
  fig_cum_returns = px.line(daily_cum_returns, title='๊ฐœ๋ณ„ ์ฃผ์‹์˜ ๋ˆ„์  ์ˆ˜์ต๋ฅ  ($1,000 ์‹œ์ž‘)')
64
  corr_df = stocks_df.corr().round(2)
65
  fig_corr = px.imshow(corr_df, text_auto=True, title='์ฃผ์‹ ๊ฐ„ ์ƒ๊ด€ ๊ด€๊ณ„')
66
+
67
  mu = expected_returns.mean_historical_return(stocks_df)
68
  S = risk_models.sample_cov(stocks_df)
69
  ef = EfficientFrontier(mu, S)
 
80
  for ticker in tickers
81
  ])
82
 
 
 
 
 
83
  return fig_cum_returns, fig_efficient_frontier, fig_corr, fig_indiv_prices, fig_weights, \
84
+ f"{expected_annual_return*100:.2f}%", f"{annual_volatility*100:.2f}%", f"{sharpe_ratio:.2f}", ticker_info_output
85
+
86
+
87
 
88
  css = """footer { visibility: hidden; }"""
89
 
90
+
91
  with gr.Blocks(css=css) as app:
92
  gr.Markdown("""
93
  <style>
 
103
  end_date = gr.Textbox(datetime.now().date(), label="์ข…๋ฃŒ ์ผ์ž")
104
  tickers_string = gr.Textbox("NVDA,^GSPC,GC=F,MSFT,BTC-USD", label="์ฃผ์‹ ํ‹ฐ์ปค๋ฅผ ์‰ผํ‘œ๋กœ ๊ตฌ๋ถ„ํ•˜์—ฌ ์ž…๋ ฅํ•˜์„ธ์š”")
105
  btn = gr.Button("ํฌํŠธํด๋ฆฌ์˜ค ์ตœ์ ํ™” ๊ฒฐ๊ณผ ๋ณด๊ธฐ")
106
+
107
  with gr.Row():
108
  expected_annual_return = gr.Text(label="์˜ˆ์ƒ ์—ฐ๊ฐ„ ์ˆ˜์ต๋ฅ ")
109
  annual_volatility = gr.Text(label="์—ฐ๊ฐ„ ๋ณ€๋™์„ฑ")
110
  sharpe_ratio = gr.Text(label="์ƒคํ”„ ๋น„์œจ")
 
111
  with gr.Column():
112
  fig_cum_returns = gr.Plot(label="์ตœ์ ํ™”๋œ ํฌํŠธํด๋ฆฌ์˜ค์˜ ๋ˆ„์  ์ˆ˜์ต๋ฅ  (์‹œ์ž‘ ๊ฐ€๊ฒฉ $1,000)")
113
  fig_efficient_frontier = gr.Plot(label="ํšจ์œจ์  ํˆฌ์ž์„ ")
114
  fig_corr = gr.Plot(label="์ฃผ์‹ ๊ฐ„ ์ƒ๊ด€ ๊ด€๊ณ„")
115
  fig_indiv_prices = gr.Plot(label="๊ฐœ๋ณ„ ์ฃผ์‹ ๊ฐ€๊ฒฉ")
116
  fig_weights = gr.Plot(label="ํฌํŠธํด๋ฆฌ์˜ค ์ตœ์  ํˆฌ์ž ๋น„์œจ")
 
117
  ticker_info_output = gr.Textbox(label="ํ‹ฐ์ปค ์ •๋ณด ๋ฐ ๋‰ด์Šค")
118
+ btn.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])
119
 
120
+ app.launch()