AlanRex commited on
Commit
46d6ad0
·
verified ·
1 Parent(s): e658165

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +72 -37
app.py CHANGED
@@ -217,59 +217,94 @@ def advanced_xgboost_predict(data, predict_days):
217
  def advanced_xgboost_predict(data, predict_days):
218
  """
219
  【進階模型橋接函式】
220
- - 準備 XGBoost 模型所需的輸入 DataFrame。
221
- - 呼叫模型進行預測。
222
  - 將模型的輸出格式轉換為主程式所需的格式。
223
  """
224
  if xgb_model is None or data.empty:
225
- print("XGBoost 模型未載入或數據為空")
226
- return None
227
-
228
- # 確保數據有足夠的歷史記錄來計算技術指標
229
- if len(data) < 30:
230
- print("歷史數據不足,無法計算技術指標")
231
  return None
232
 
233
  try:
234
- print(f"呼叫 XGBoost 模型進行 {predict_days} 天預測...")
235
 
236
- # 呼叫修正後的預測方法
237
- predictions = xgb_model.predict('xgboost_model', data)
 
 
238
 
239
- # 根據 predict_days 解析輸出
240
- day_to_key_map = {
241
- 1: 'Close_t0_pred',
242
- 5: 'Close_t5_pred',
243
- 10: 'Close_t10_pred',
244
- 20: 'Close_t20_pred'
245
- }
246
 
247
- prediction_key = day_to_key_map.get(predict_days)
 
 
248
 
249
- if prediction_key is None or prediction_key not in predictions:
250
- print(f"警告: XGBoost 模型沒有提供 {predict_days} 天的預測結果。")
251
- print(f"可用的預測鍵: {list(predictions.keys())}")
252
- # 使用最接近的預測天期
253
- available_days = [1, 5, 10, 20]
254
- closest_day = min(available_days, key=lambda x: abs(x - predict_days))
255
- prediction_key = day_to_key_map[closest_day]
256
- print(f"使用最接近的預測期間: {closest_day} 天")
 
 
 
 
257
 
258
- predicted_price = predictions[prediction_key]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
259
  current_price = data['Close'].iloc[-1]
260
  change_pct = ((predicted_price - current_price) / current_price) * 100
261
 
262
- result = {
263
- 'predicted_price': float(predicted_price),
264
- 'change_pct': float(change_pct),
265
- 'confidence': 0.85
266
  }
267
-
268
- print(f"XGBoost 預測成功: 當前價格={current_price:.2f}, 預測價格={predicted_price:.2f}, 變化={change_pct:.2f}%")
269
- return result
270
-
271
  except Exception as e:
272
- print(f"執行 XGBoost 預測時發生錯誤: {e}")
273
  import traceback
274
  traceback.print_exc()
275
  return None
 
217
  def advanced_xgboost_predict(data, predict_days):
218
  """
219
  【進階模型橋接函式】
220
+ - 準備 XGBoost 模型所需的20個特徵。
221
+ - 呼叫模型进行预测。
222
  - 將模型的輸出格式轉換為主程式所需的格式。
223
  """
224
  if xgb_model is None or data.empty:
 
 
 
 
 
 
225
  return None
226
 
227
  try:
228
+ print("正在準備 XGBoost 模型所需的20個輸入特徵...")
229
 
230
+ # 1. 獲取外部市場數據
231
+ # 建立一個與主股票數據相同索引的 DataFrame 以便對齊
232
+ start_date = data.index.min() - pd.Timedelta(days=5) # 提前幾天以確保數據填充
233
+ end_date = data.index.max()
234
 
235
+ df_aligned = pd.DataFrame(index=pd.date_range(start=start_date, end=end_date, freq='D'))
236
+
237
+ external_symbols = {'DJI': '^DJI', 'NAS': '^IXIC', 'SOX': '^SOX', 'S&P_500': '^GSPC', 'TSM_ADR': 'TSM'}
 
 
 
 
238
 
239
+ # 使用 yf.download 一次性獲取所有外部數據
240
+ ext_data = yf.download(list(external_symbols.values()), start=start_date, end=end_date, progress=False)['Close']
241
+ ext_data.rename(columns={v: k for k, v in external_symbols.items()}, inplace=True)
242
 
243
+ # 2. 合併所有數據源
244
+ # 將主數據與外部數據合併
245
+ input_df = data.join(ext_data, how='left')
246
+
247
+ # 載入並合併景氣燈號和 PMI
248
+ df_climate = get_business_climate_data() #
249
+ df_pmi = get_pmi_data() #
250
+
251
+ # 將 'Date' 轉為 datetime 物件以進行合併
252
+ input_df.index = pd.to_datetime(input_df.index)
253
+ df_climate['Date'] = pd.to_datetime(df_climate['Date']) #
254
+ df_pmi['Date'] = pd.to_datetime(df_pmi['Date']) #
255
 
256
+ input_df = pd.merge(input_df, df_climate.rename(columns={'Index': 'business_climate'}), on='Date', how='left')
257
+ input_df = pd.merge(input_df, df_pmi.rename(columns={'Index': 'PMI'}), on='Date', how='left')
258
+
259
+ # 向前填充所有缺失值 (例如假日)
260
+ input_df.ffill(inplace=True)
261
+ input_df.bfill(inplace=True) # 向後填充開頭可能存在的缺失值
262
+
263
+ # 3. 計算技術指標與新增其他特徵
264
+ input_df = calculate_technical_indicators(input_df) #
265
+ news_score = predictor.get_news_index() if predictor else 0
266
+ input_df['NEWS'] = news_score if news_score is not None else 0
267
+ input_df['rate'] = 1.75 # 注意:此為利率佔位符,請替換為真實數據源
268
+
269
+ # 4. 格式化最終輸入
270
+ input_df.rename(columns={
271
+ 'Close': 'close', 'Volume': 'volume', 'MACD_Signal': 'MACDsign',
272
+ 'MACD_Histogram': 'MACDvol'
273
+ }, inplace=True)
274
+
275
+ columns_to_keep = [
276
+ 'close', 'volume', 'rate', 'DJI', 'NAS', 'SOX', 'S&P_500', 'TSM_ADR', 'NEWS',
277
+ 'RSI', 'MACD', 'MACDsign', 'MACDvol', 'K', 'D', '+DI', '-DI', 'ADX',
278
+ 'business_climate', 'PMI'
279
+ ]
280
+
281
+ # 確保所有欄位都存在
282
+ for col in columns_to_keep:
283
+ if col not in input_df.columns:
284
+ print(f"錯誤:準備好的資料中缺少欄位 '{col}'")
285
+ return None
286
+
287
+ final_input = input_df[columns_to_keep].tail(1)
288
+
289
+ if final_input.isnull().values.any():
290
+ print(f"警告: 最終輸入數據中存在缺失值,無法預測。\n{final_input.isnull().sum()}")
291
+ return None
292
+
293
+ # 5. 呼叫模型預測
294
+ print("特徵準備完成,呼叫 XGBoost 模型...")
295
+ predictions = xgb_model.predict('xgboost_model', final_input)
296
+
297
+ predicted_price = predictions['Close_t5_pred'] # 預設獲取5日預測
298
  current_price = data['Close'].iloc[-1]
299
  change_pct = ((predicted_price - current_price) / current_price) * 100
300
 
301
+ return {
302
+ 'predicted_price': predicted_price,
303
+ 'change_pct': change_pct,
304
+ 'confidence': 0.95
305
  }
 
 
 
 
306
  except Exception as e:
307
+ print(f"執行 XGBoost 預測時發生嚴重錯誤: {e}")
308
  import traceback
309
  traceback.print_exc()
310
  return None