AlanRex commited on
Commit
9bb6ac9
·
verified ·
1 Parent(s): 819d41a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +65 -130
app.py CHANGED
@@ -29,7 +29,7 @@ from model_predictor import XGBoostModel
29
  # 【【【模型切換開關】】】
30
  # False: 使用簡易統計模型 (預設)
31
  # True: 使用 model_predictor.py 中的進階 XGBoost 模型
32
- USE_ADVANCED_MODEL = True
33
 
34
  # ========================= CACHE 設定 START =========================
35
  # 分析結果的快取字典
@@ -242,7 +242,7 @@ def simple_statistical_predict(data, predict_days=5):
242
 
243
  def advanced_xgboost_predict(predict_days=5):
244
  """
245
- 【進階模型】使用 XGBoost 模型進行預測
246
  """
247
  try:
248
  print(f"開始使用 XGBoost 模型進行 {predict_days} 天預測...")
@@ -259,12 +259,6 @@ def advanced_xgboost_predict(predict_days=5):
259
  # 計算技術指標
260
  taiex_data = calculate_technical_indicators(taiex_data)
261
 
262
- # 獲取美股市場數據
263
- us_market = get_us_market_data()
264
-
265
- # 獲取匯率數據
266
- exchange_rate = get_exchange_rate()
267
-
268
  # 獲取新聞情緒分數
269
  try:
270
  if predictor is not None:
@@ -279,127 +273,71 @@ def advanced_xgboost_predict(predict_days=5):
279
  # 準備特徵數據 (使用最新的數據點)
280
  latest_data = taiex_data.iloc[-1]
281
 
282
- # 建立特徵向量 (按照訓練數據記錄的順序)
283
- # 先檢查每個技術指標是否存在並記錄狀態
284
  tech_indicators_status = {}
285
 
286
- # RSI 檢查
287
- rsi_value = latest_data['RSI'] if not pd.isna(latest_data['RSI']) else 50
288
- tech_indicators_status['RSI'] = {
289
- 'value': rsi_value,
290
- 'is_real': not pd.isna(latest_data['RSI']),
291
- 'source': 'calculated' if not pd.isna(latest_data['RSI']) else 'default'
292
- }
293
-
294
- # MACD 相關檢查
295
- macd_value = latest_data['MACD'] if not pd.isna(latest_data['MACD']) else 0
296
- macd_signal_value = latest_data['MACD_Signal'] if not pd.isna(latest_data['MACD_Signal']) else 0
297
- macd_hist_value = latest_data['MACD_Histogram'] if not pd.isna(latest_data['MACD_Histogram']) else 0
298
-
299
- tech_indicators_status['MACD'] = {
300
- 'value': macd_value,
301
- 'is_real': not pd.isna(latest_data['MACD']),
302
- 'source': 'calculated' if not pd.isna(latest_data['MACD']) else 'default'
303
- }
304
- tech_indicators_status['MACD_Signal'] = {
305
- 'value': macd_signal_value,
306
- 'is_real': not pd.isna(latest_data['MACD_Signal']),
307
- 'source': 'calculated' if not pd.isna(latest_data['MACD_Signal']) else 'default'
308
- }
309
- tech_indicators_status['MACD_Histogram'] = {
310
- 'value': macd_hist_value,
311
- 'is_real': not pd.isna(latest_data['MACD_Histogram']),
312
- 'source': 'calculated' if not pd.isna(latest_data['MACD_Histogram']) else 'default'
313
- }
314
-
315
- # KD 指標檢查
316
- k_value = latest_data['K'] if not pd.isna(latest_data['K']) else 50
317
- d_value = latest_data['D'] if not pd.isna(latest_data['D']) else 50
318
-
319
- tech_indicators_status['K'] = {
320
- 'value': k_value,
321
- 'is_real': not pd.isna(latest_data['K']),
322
- 'source': 'calculated' if not pd.isna(latest_data['K']) else 'default'
323
- }
324
- tech_indicators_status['D'] = {
325
- 'value': d_value,
326
- 'is_real': not pd.isna(latest_data['D']),
327
- 'source': 'calculated' if not pd.isna(latest_data['D']) else 'default'
328
  }
329
 
330
- # DMI 指標檢查
331
- plus_di_value = latest_data['+DI'] if not pd.isna(latest_data['+DI']) else 25
332
- minus_di_value = latest_data['-DI'] if not pd.isna(latest_data['-DI']) else 25
333
- adx_value = latest_data['ADX'] if not pd.isna(latest_data['ADX']) else 25
334
-
335
- tech_indicators_status['+DI'] = {
336
- 'value': plus_di_value,
337
- 'is_real': not pd.isna(latest_data['+DI']),
338
- 'source': 'calculated' if not pd.isna(latest_data['+DI']) else 'default'
339
- }
340
- tech_indicators_status['-DI'] = {
341
- 'value': minus_di_value,
342
- 'is_real': not pd.isna(latest_data['-DI']),
343
- 'source': 'calculated' if not pd.isna(latest_data['-DI']) else 'default'
344
- }
345
- tech_indicators_status['ADX'] = {
346
- 'value': adx_value,
347
- 'is_real': not pd.isna(latest_data['ADX']),
348
- 'source': 'calculated' if not pd.isna(latest_data['ADX']) else 'default'
349
- }
350
 
351
- # 建立特徵向量
352
  features_list = [
353
- latest_data['Close'], # close
354
- latest_data['Volume'], # volume
355
- exchange_rate, # rate
356
- us_market['DJI'], # DJI
357
- us_market['NAS'], # NAS
358
- us_market['SOX'], # SOX
359
- us_market['S&P_500'], # S&P_500
360
- us_market['TSM_ADR'], # TSM_ADR
361
- sentiment_score_raw, # NEWS (使用原始 sentiment_score_raw)
362
- rsi_value, # RSI
363
- macd_value, # MACD
364
- macd_signal_value, # MACDsign
365
- macd_hist_value, # MACDvol
366
- k_value, # K
367
- d_value, # D
368
- plus_di_value, # +DI
369
- minus_di_value, # -DI
370
- adx_value, # ADX
371
- 15, # business_climate (手動填入值)
372
- 46.7 # PMI (手動填入值)
373
  ]
374
 
375
- # 轉換為 DataFrame (XGBoost 模型期望的格式)
376
  column_names = [
377
- 'close', 'volume', 'rate', 'DJI', 'NAS', 'SOX', 'S&P_500', 'TSM_ADR',
378
- 'NEWS', 'RSI', 'MACD', 'MACDsign', 'MACDvol', 'K', 'D',
379
- '+DI', '-DI', 'ADX', 'business_climate', 'PMI'
380
  ]
381
 
 
382
  input_df = pd.DataFrame([features_list], columns=column_names)
383
 
384
  # 詳細的資料驗證日誌
385
  print("=" * 50)
386
- print("XGBoost 模型輸入特徵詳細檢查報告")
387
  print("=" * 50)
388
 
389
- # 基本市場數據
390
- print("📊 基本市場數據:")
391
- print(f" 收盤價 (close): {latest_data['Close']:.2f}")
392
- print(f" 成交量 (volume): {latest_data['Volume']:,.0f}")
393
- print(f" 匯率 (rate): {exchange_rate:.4f}")
394
-
395
- # 美股指數
396
- print("\n🇺🇸 美股指數數據:")
397
- for key, value in us_market.items():
398
- status = "✅ 正常" if value > 0 else "⚠️ 可能異常(=0)"
399
- print(f" {key}: {value:.2f} {status}")
400
-
401
- # 新聞情緒
402
- print(f"\n📰 新聞情緒 (NEWS): {sentiment_score_raw:.6f}")
403
  if sentiment_score_raw == 0:
404
  print(" ⚠️ 新聞情緒分數為0,可能無新聞數據")
405
  else:
@@ -407,32 +345,28 @@ def advanced_xgboost_predict(predict_days=5):
407
 
408
  # 技術指標詳細狀態
409
  print("\n📈 技術指標狀態:")
410
- for indicator, status in tech_indicators_status.items():
 
411
  status_symbol = "✅" if status['is_real'] else "⚠️"
412
- source_info = "實際計算值" if status['is_real'] else "預設替代值"
413
- print(f" {indicator}: {status['value']:.4f} {status_symbol} ({source_info})")
414
-
415
- # 手動填入數據
416
- print("\n🔧 手動填入數據:")
417
- print(f" business_climate: 15 ✅")
418
- print(f" PMI: 46.7 ✅")
419
 
420
- # 統計資料完整性
421
  real_indicators = sum(1 for status in tech_indicators_status.values() if status['is_real'])
422
  total_indicators = len(tech_indicators_status)
423
  completeness = (real_indicators / total_indicators) * 100
424
 
425
- print(f"\n📋 技術指標完整性統計:")
426
  print(f" 實際計算指標: {real_indicators}/{total_indicators} ({completeness:.1f}%)")
427
- if completeness < 80:
428
- print(" ⚠️ 警告:超過20%的技術指標使用預設值,可能影響預測準確性")
429
  else:
430
- print(" ✅ 技術指標完整性良好")
431
 
432
- # 顯示完整輸入向量
433
  print(f"\n🔢 完整特徵向量 (共{len(features_list)}個特徵):")
434
  for i, (name, value) in enumerate(zip(column_names, features_list)):
435
- print(f" [{i:2d}] {name:15s}: {value:10.4f}")
436
 
437
  print("=" * 50)
438
 
@@ -453,7 +387,7 @@ def advanced_xgboost_predict(predict_days=5):
453
  pred_key = pred_mapping[closest_day]
454
 
455
  predicted_price = predictions[pred_key]
456
- current_price = features_list[0] # close price
457
  change_pct = ((predicted_price - current_price) / current_price) * 100
458
 
459
  print(f"XGBoost 預測完成:")
@@ -461,6 +395,7 @@ def advanced_xgboost_predict(predict_days=5):
461
  print(f"- 當前價格: {current_price:.2f}")
462
  print(f"- 預測價格: {predicted_price:.2f}")
463
  print(f"- 預測變化: {change_pct:+.2f}%")
 
464
 
465
  return {
466
  'predicted_price': predicted_price,
@@ -619,12 +554,12 @@ def generate_gemini_analysis(stock_name, stock_symbol, period, data):
619
  **你的任務:**
620
  1. **基本面分析 (約 150 字):**
621
  - 評論這家公司的產業地位、近期營運亮點或挑戰。
622
- - 提及任何可能影響其基本面的關鍵因素 (例如:公告財報的最近日期、法說會最近日期、最近一次的EPS數值、最近一個月的MOM%的數值、政策、供應鏈變化等)。
623
  - 請用專業、客觀的語氣撰寫。
624
 
625
  2. **市場展望與投資建議 (約 150 字):**
626
  - 基於上述所有資訊,提供對該股票的短期和中期市場展望。
627
- - 提出具體的投資建議,例如:適合何種類型的投資(價值投資、波段投資、動能投資)、潛在的風險點。
628
  - 請直接提供分析內容,不要包含任何問候語。
629
 
630
  **輸出格式:**
 
29
  # 【【【模型切換開關】】】
30
  # False: 使用簡易統計模型 (預設)
31
  # True: 使用 model_predictor.py 中的進階 XGBoost 模型
32
+ USE_ADVANCED_MODEL = False
33
 
34
  # ========================= CACHE 設定 START =========================
35
  # 分析結果的快取字典
 
242
 
243
  def advanced_xgboost_predict(predict_days=5):
244
  """
245
+ 【進階模型】使用 XGBoost 模型進行預測 - 簡化版 (11個特徵)
246
  """
247
  try:
248
  print(f"開始使用 XGBoost 模型進行 {predict_days} 天預測...")
 
259
  # 計算技術指標
260
  taiex_data = calculate_technical_indicators(taiex_data)
261
 
 
 
 
 
 
 
262
  # 獲取新聞情緒分數
263
  try:
264
  if predictor is not None:
 
273
  # 準備特徵數據 (使用最新的數據點)
274
  latest_data = taiex_data.iloc[-1]
275
 
276
+ # 技術指標檢查和狀態記錄
 
277
  tech_indicators_status = {}
278
 
279
+ # 檢查各技術指標並記錄狀態
280
+ indicators_map = {
281
+ 'RSI': (latest_data['RSI'], 50),
282
+ 'MACD': (latest_data['MACD'], 0),
283
+ 'MACDsign': (latest_data['MACD_Signal'], 0),
284
+ 'MACDvol': (latest_data['MACD_Histogram'], 0),
285
+ 'K': (latest_data['K'], 50),
286
+ 'D': (latest_data['D'], 50),
287
+ '+DI': (latest_data['+DI'], 25),
288
+ '-DI': (latest_data['-DI'], 25),
289
+ 'ADX': (latest_data['ADX'], 25),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
290
  }
291
 
292
+ processed_values = {}
293
+ for indicator, (value, default) in indicators_map.items():
294
+ if pd.isna(value):
295
+ processed_values[indicator] = default
296
+ tech_indicators_status[indicator] = {
297
+ 'value': default,
298
+ 'is_real': False,
299
+ 'source': 'default'
300
+ }
301
+ else:
302
+ processed_values[indicator] = value
303
+ tech_indicators_status[indicator] = {
304
+ 'value': value,
305
+ 'is_real': True,
306
+ 'source': 'calculated'
307
+ }
 
 
 
 
308
 
309
+ # 建立簡化的特徵向量 (按您指定的順序)
310
  features_list = [
311
+ latest_data['Close'], # close
312
+ sentiment_score_raw, # NEWS
313
+ processed_values['MACD'], # MACD
314
+ processed_values['MACDsign'], # MACDsign
315
+ processed_values['MACDvol'], # MACDvol
316
+ processed_values['K'], # K
317
+ processed_values['D'], # D
318
+ processed_values['+DI'], # +DI
319
+ processed_values['-DI'], # -DI
320
+ processed_values['ADX'], # ADX
321
+ processed_values['RSI'], # RSI
 
 
 
 
 
 
 
 
 
322
  ]
323
 
324
+ # 對應的欄位名稱
325
  column_names = [
326
+ 'close', 'NEWS', 'MACD', 'MACDsign', 'MACDvol',
327
+ 'K', 'D', '+DI', '-DI', 'ADX', 'RSI'
 
328
  ]
329
 
330
+ # 轉換為 DataFrame (XGBoost 模型期望的格式)
331
  input_df = pd.DataFrame([features_list], columns=column_names)
332
 
333
  # 詳細的資料驗證日誌
334
  print("=" * 50)
335
+ print("XGBoost 簡化模型輸入特徵檢查報告")
336
  print("=" * 50)
337
 
338
+ # 基本資料
339
+ print(f"收盤價 (close): {latest_data['Close']:.2f}")
340
+ print(f"新聞情緒 (NEWS): {sentiment_score_raw:.6f}")
 
 
 
 
 
 
 
 
 
 
 
341
  if sentiment_score_raw == 0:
342
  print(" ⚠️ 新聞情緒分數為0,可能無新聞數據")
343
  else:
 
345
 
346
  # 技術指標詳細狀態
347
  print("\n📈 技術指標狀態:")
348
+ for indicator in ['MACD', 'MACDsign', 'MACDvol', 'K', 'D', '+DI', '-DI', 'ADX', 'RSI']:
349
+ status = tech_indicators_status[indicator]
350
  status_symbol = "✅" if status['is_real'] else "⚠️"
351
+ source_info = "實際計算" if status['is_real'] else "預設值"
352
+ print(f" {indicator:10s}: {status['value']:8.4f} {status_symbol} ({source_info})")
 
 
 
 
 
353
 
354
+ # 統計完整性
355
  real_indicators = sum(1 for status in tech_indicators_status.values() if status['is_real'])
356
  total_indicators = len(tech_indicators_status)
357
  completeness = (real_indicators / total_indicators) * 100
358
 
359
+ print(f"\n📋 技術指標完整性:")
360
  print(f" 實際計算指標: {real_indicators}/{total_indicators} ({completeness:.1f}%)")
361
+ if completeness < 70:
362
+ print(" ⚠️ 警告:超過30%的指標使用預設值,可能影響預測準確性")
363
  else:
364
+ print(" ✅ 指標完整性良好")
365
 
366
+ # 顯示完整特徵向量
367
  print(f"\n🔢 完整特徵向量 (共{len(features_list)}個特徵):")
368
  for i, (name, value) in enumerate(zip(column_names, features_list)):
369
+ print(f" [{i:2d}] {name:10s}: {value:12.6f}")
370
 
371
  print("=" * 50)
372
 
 
387
  pred_key = pred_mapping[closest_day]
388
 
389
  predicted_price = predictions[pred_key]
390
+ current_price = latest_data['Close']
391
  change_pct = ((predicted_price - current_price) / current_price) * 100
392
 
393
  print(f"XGBoost 預測完成:")
 
395
  print(f"- 當前價格: {current_price:.2f}")
396
  print(f"- 預測價格: {predicted_price:.2f}")
397
  print(f"- 預測變化: {change_pct:+.2f}%")
398
+ print(f"- 使用特徵數: {len(features_list)} 個")
399
 
400
  return {
401
  'predicted_price': predicted_price,
 
554
  **你的任務:**
555
  1. **基本面分析 (約 150 字):**
556
  - 評論這家公司的產業地位、近期營運亮點或挑戰。
557
+ - 提及任何可能影響其基本面的關鍵因素 (例如:財報、法說會、政策、供應鏈變化等)。
558
  - 請用專業、客觀的語氣撰寫。
559
 
560
  2. **市場展望與投資建議 (約 150 字):**
561
  - 基於上述所有資訊,提供對該股票的短期和中期市場展望。
562
+ - 提出具體的投資建議,例如:適合何種類型的投資人、潛在的風險點。
563
  - 請直接提供分析內容,不要包含任何問候語。
564
 
565
  **輸出格式:**