Johan713 commited on
Commit
a0bf426
·
verified ·
1 Parent(s): 185dd5e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +69 -25
app.py CHANGED
@@ -41,25 +41,28 @@ class StockPredictor:
41
  self.model = None
42
 
43
  def preprocess_data(self):
44
- # Prophet requires columns named 'ds' and 'y'
45
  self.data = self.data.reset_index()
46
  self.data = self.data.rename(columns={'Date': 'ds', 'Close': 'y'})
47
 
48
- # Add any additional features you want to use
49
- self.data['SMA_20'] = self.data['y'].rolling(window=20).mean()
50
- self.data['EMA_20'] = self.data['y'].ewm(span=20, adjust=False).mean()
51
- self.data['RSI'] = self.calculate_rsi(self.data['y'], periods=14)
 
 
 
 
 
 
 
 
 
 
 
52
 
53
  # Handle NaN values
54
  self.data = self.data.dropna()
55
 
56
- def calculate_rsi(self, prices, periods=14):
57
- delta = prices.diff()
58
- gain = (delta.where(delta > 0, 0)).rolling(window=periods).mean()
59
- loss = (-delta.where(delta < 0, 0)).rolling(window=periods).mean()
60
- rs = gain / loss
61
- return 100 - (100 / (1 + rs))
62
-
63
  def train_model(self):
64
  try:
65
  self.model = Prophet(
@@ -72,9 +75,8 @@ class StockPredictor:
72
  )
73
 
74
  # Add additional regressors
75
- self.model.add_regressor('SMA_20')
76
- self.model.add_regressor('EMA_20')
77
- self.model.add_regressor('RSI')
78
 
79
  self.model.fit(self.data)
80
  return True
@@ -87,8 +89,8 @@ class StockPredictor:
87
  future = self.model.make_future_dataframe(periods=days)
88
 
89
  # Add regressor values for future dates
90
- for feature in ['SMA_20', 'EMA_20', 'RSI']:
91
- future[feature] = self.data[feature].iloc[-1] # Use last known value
92
 
93
  forecast = self.model.predict(future)
94
  return forecast
@@ -111,6 +113,11 @@ class StockPredictor:
111
 
112
  return mse, mape, rmse
113
 
 
 
 
 
 
114
  def fetch_stock_data(ticker):
115
  try:
116
  end_date = datetime.now()
@@ -180,6 +187,24 @@ def create_prediction_plot(data, predicted_data, company_name):
180
  name='Predicted Data',
181
  line=dict(color='yellow')
182
  ))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
183
 
184
  fig.update_layout(
185
  title=f'{company_name} Stock Price Prediction',
@@ -246,7 +271,7 @@ def main():
246
  predict_stock_prices()
247
 
248
  def test_model():
249
- st.header("Test Prophet Model")
250
 
251
  col1, col2 = st.columns(2)
252
 
@@ -266,13 +291,11 @@ def test_model():
266
  st.write(data.describe())
267
  st.dataframe(data.head())
268
 
269
- st.markdown(get_table_download_link(data), unsafe_allow_html=True)
270
-
271
  split_index = int(len(data) * (1 - test_split))
272
  train_data = data.iloc[:split_index]
273
  test_data = data.iloc[split_index:]
274
 
275
- predictor = StockPredictor(train_data)
276
  predictor.preprocess_data()
277
  if predictor.train_model():
278
  test_pred = predictor.predict(days=len(test_data))
@@ -290,6 +313,18 @@ def test_model():
290
 
291
  plot = create_test_plot(predictor.data, test_data.reset_index().rename(columns={'Date': 'ds', 'Close': 'y'}), test_pred, company_name)
292
  st.plotly_chart(plot, use_container_width=True)
 
 
 
 
 
 
 
 
 
 
 
 
293
  else:
294
  st.error("Failed to evaluate the model. The evaluation metrics are None.")
295
  else:
@@ -298,7 +333,7 @@ def test_model():
298
  st.error("Failed to train the Prophet model. Please try a different dataset.")
299
 
300
  def predict_stock_prices():
301
- st.header("Predict Stock Prices")
302
 
303
  col1, col2 = st.columns(2)
304
 
@@ -318,9 +353,7 @@ def predict_stock_prices():
318
  st.write(data.describe())
319
  st.dataframe(data.head())
320
 
321
- st.markdown(get_table_download_link(data), unsafe_allow_html=True)
322
-
323
- predictor = StockPredictor(data)
324
  predictor.preprocess_data()
325
  if predictor.train_model():
326
  predictions = predictor.predict(days=days_to_predict)
@@ -337,6 +370,17 @@ def predict_stock_prices():
337
  pred_df.columns = ['Date', 'Predicted Price', 'Lower Bound', 'Upper Bound']
338
  st.dataframe(pred_df)
339
 
 
 
 
 
 
 
 
 
 
 
 
340
  news = fetch_news(company_name)
341
  st.subheader("Latest News")
342
  for item in news:
 
41
  self.model = None
42
 
43
  def preprocess_data(self):
 
44
  self.data = self.data.reset_index()
45
  self.data = self.data.rename(columns={'Date': 'ds', 'Close': 'y'})
46
 
47
+ # Add technical indicators
48
+ self.data['SMA_20'] = SMAIndicator(close=self.data['y'], window=20).sma_indicator()
49
+ self.data['EMA_20'] = EMAIndicator(close=self.data['y'], window=20).ema_indicator()
50
+ self.data['RSI'] = RSIIndicator(close=self.data['y'], window=14).rsi()
51
+ bb = BollingerBands(close=self.data['y'], window=20, window_dev=2)
52
+ self.data['BB_high'] = bb.bollinger_hband()
53
+ self.data['BB_low'] = bb.bollinger_lband()
54
+
55
+ # Add lagged features
56
+ self.data['lag_1'] = self.data['y'].shift(1)
57
+ self.data['lag_7'] = self.data['y'].shift(7)
58
+
59
+ # Add rolling statistics
60
+ self.data['rolling_mean_7'] = self.data['y'].rolling(window=7).mean()
61
+ self.data['rolling_std_7'] = self.data['y'].rolling(window=7).std()
62
 
63
  # Handle NaN values
64
  self.data = self.data.dropna()
65
 
 
 
 
 
 
 
 
66
  def train_model(self):
67
  try:
68
  self.model = Prophet(
 
75
  )
76
 
77
  # Add additional regressors
78
+ for column in ['SMA_20', 'EMA_20', 'RSI', 'BB_high', 'BB_low', 'lag_1', 'lag_7', 'rolling_mean_7', 'rolling_std_7']:
79
+ self.model.add_regressor(column)
 
80
 
81
  self.model.fit(self.data)
82
  return True
 
89
  future = self.model.make_future_dataframe(periods=days)
90
 
91
  # Add regressor values for future dates
92
+ for column in ['SMA_20', 'EMA_20', 'RSI', 'BB_high', 'BB_low', 'lag_1', 'lag_7', 'rolling_mean_7', 'rolling_std_7']:
93
+ future[column] = self.data[column].iloc[-1] # Use last known value
94
 
95
  forecast = self.model.predict(future)
96
  return forecast
 
113
 
114
  return mse, mape, rmse
115
 
116
+ def cross_validate_model(self):
117
+ df_cv = cross_validation(self.model, initial='730 days', period='180 days', horizon='90 days')
118
+ df_p = performance_metrics(df_cv)
119
+ return df_p
120
+
121
  def fetch_stock_data(ticker):
122
  try:
123
  end_date = datetime.now()
 
187
  name='Predicted Data',
188
  line=dict(color='yellow')
189
  ))
190
+
191
+ # Add prediction intervals
192
+ fig.add_trace(go.Scatter(
193
+ x=future_dates,
194
+ y=predicted_data['yhat_upper'],
195
+ mode='lines',
196
+ line=dict(width=0),
197
+ showlegend=False
198
+ ))
199
+ fig.add_trace(go.Scatter(
200
+ x=future_dates,
201
+ y=predicted_data['yhat_lower'],
202
+ mode='lines',
203
+ line=dict(width=0),
204
+ fillcolor='rgba(255, 255, 0, 0.3)',
205
+ fill='tonexty',
206
+ name='Prediction Interval'
207
+ ))
208
 
209
  fig.update_layout(
210
  title=f'{company_name} Stock Price Prediction',
 
271
  predict_stock_prices()
272
 
273
  def test_model():
274
+ st.header("Test Enhanced Prophet Model")
275
 
276
  col1, col2 = st.columns(2)
277
 
 
291
  st.write(data.describe())
292
  st.dataframe(data.head())
293
 
 
 
294
  split_index = int(len(data) * (1 - test_split))
295
  train_data = data.iloc[:split_index]
296
  test_data = data.iloc[split_index:]
297
 
298
+ predictor = EnhancedStockPredictor(train_data)
299
  predictor.preprocess_data()
300
  if predictor.train_model():
301
  test_pred = predictor.predict(days=len(test_data))
 
313
 
314
  plot = create_test_plot(predictor.data, test_data.reset_index().rename(columns={'Date': 'ds', 'Close': 'y'}), test_pred, company_name)
315
  st.plotly_chart(plot, use_container_width=True)
316
+
317
+ # Cross-validation results
318
+ st.subheader("Cross-Validation Results")
319
+ cv_results = predictor.cross_validate_model()
320
+ st.dataframe(cv_results)
321
+
322
+ # Feature importance
323
+ st.subheader("Feature Importance")
324
+ feature_importance = pd.DataFrame(predictor.model.params['regressor_coefficients'].items(), columns=['Feature', 'Importance'])
325
+ feature_importance = feature_importance.sort_values('Importance', ascending=False)
326
+ fig = px.bar(feature_importance, x='Feature', y='Importance', title='Feature Importance')
327
+ st.plotly_chart(fig, use_container_width=True)
328
  else:
329
  st.error("Failed to evaluate the model. The evaluation metrics are None.")
330
  else:
 
333
  st.error("Failed to train the Prophet model. Please try a different dataset.")
334
 
335
  def predict_stock_prices():
336
+ st.header("Predict Stock Prices with Enhanced Model")
337
 
338
  col1, col2 = st.columns(2)
339
 
 
353
  st.write(data.describe())
354
  st.dataframe(data.head())
355
 
356
+ predictor = EnhancedStockPredictor(data)
 
 
357
  predictor.preprocess_data()
358
  if predictor.train_model():
359
  predictions = predictor.predict(days=days_to_predict)
 
370
  pred_df.columns = ['Date', 'Predicted Price', 'Lower Bound', 'Upper Bound']
371
  st.dataframe(pred_df)
372
 
373
+ # Component-wise forecast
374
+ st.subheader("Forecast Components")
375
+ fig = predictor.model.plot_components(predictions)
376
+ st.pyplot(fig)
377
+
378
+ # Changepoints
379
+ st.subheader("Detected Changepoints")
380
+ fig = predictor.model.plot(predictions)
381
+ a = add_changepoints_to_plot(fig.gca(), predictor.model, predictions)
382
+ st.pyplot(fig)
383
+
384
  news = fetch_news(company_name)
385
  st.subheader("Latest News")
386
  for item in news: