AlanRex commited on
Commit
b2e231a
·
verified ·
1 Parent(s): e3aa3de

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +21 -48
app.py CHANGED
@@ -15,28 +15,16 @@ from bs4 import BeautifulSoup
15
  import requests
16
  import time # 引用 time 模組以處理時間戳
17
 
18
- # ========================= 引用外部模組 START =========================
19
  # 引用您組員的預測器程式
20
  from Bert_predict import BertPredictor
21
 
22
- # 引用新的模型預測器
23
- from model_predictor import advanced_lstm_predict
24
- # ========================== 引用外部模組 END ==========================
25
-
26
- # ========================= 全域設定 START =========================
27
- # 【【【模型切換開關】】】
28
- # False: 使用簡易統計模型 (預設)
29
- # True: 使用 model_predictor.py 中的進階 LSTM 模型 (未來啟用)
30
- USE_ADVANCED_MODEL = False
31
-
32
-
33
  # ========================= CACHE 設定 START =========================
34
  # 分析結果的快取字典
35
  ANALYSIS_CACHE = {}
36
  # 快取有效時間(秒),例如:4 小時 = 4 * 60 * 60 = 14400 秒
37
  CACHE_DURATION_SECONDS = 8 * 60 * 60
38
  # ========================== CACHE 設定 END ==========================
39
- # ========================== 全域設定 END ==========================
40
 
41
  # 台股代號對應表 (移除台指期,因為它現在是獨立區塊)
42
  TAIWAN_STOCKS = {
@@ -67,7 +55,7 @@ TAIWAN_STOCKS = {
67
  '合庫金': '5880.TW',
68
  '華南金': '2880.TW',
69
  '台光電': '2383.TW',
70
- '世芯-KY': '3661.TW',
71
  '奇鋐': '3017.TW',
72
  '凱基金': '2883.TW',
73
  '大立光': '3008.TW',
@@ -181,9 +169,10 @@ def get_stock_data(symbol, period='1y'):
181
  except:
182
  return pd.DataFrame()
183
 
184
- def simple_statistical_predict(data, predict_days=5):
185
- """【備用模型】簡化的統計預測模型。"""
186
- if len(data) < 60: return None
 
187
  prices = data['Close'].values
188
  ma_short = np.mean(prices[-5:])
189
  ma_medium = np.mean(prices[-20:])
@@ -191,29 +180,21 @@ def simple_statistical_predict(data, predict_days=5):
191
  recent_trend = np.polyfit(range(20), prices[-20:], 1)[0]
192
  volatility = np.std(prices[-20:]) / np.mean(prices[-20:])
193
  base_change = recent_trend * predict_days
194
- trend_factor = 1.0 + (0.02 if ma_short > ma_medium > ma_long else -0.02 if ma_short < ma_medium < ma_long else 0)
 
 
 
 
 
 
195
  noise_factor = np.random.normal(1, volatility * 0.1)
196
  predicted_price = prices[-1] * trend_factor + base_change + (prices[-1] * noise_factor * 0.01)
197
  change_pct = ((predicted_price - prices[-1]) / prices[-1]) * 100
198
- return {'predicted_price': predicted_price, 'change_pct': change_pct, 'confidence': max(0.6, 1 - volatility * 2)}
199
-
200
- def get_prediction(data, predict_days=5):
201
- """
202
- 【【模型預測控制器】】
203
- 根據 USE_ADVANCED_MODEL 的設定,呼叫對應的預測模型。
204
- """
205
- if USE_ADVANCED_MODEL:
206
- print(f"模式: 進階LSTM模型 | 預測天期: {predict_days}天")
207
- prediction = advanced_lstm_predict(predict_days)
208
- # 如果進階模型預測失敗,則自動降級使用簡易模型
209
- if prediction is not None:
210
- return prediction
211
- else:
212
- print("進階模型預測失敗,自動降級為簡易統計模型。")
213
-
214
- # 預設或降級時執行簡易模型
215
- print(f"模式: 簡易統計模型 | 預測天期: {predict_days}天")
216
- return simple_statistical_predict(data, predict_days)
217
 
218
  def calculate_technical_indicators(df):
219
  """計算技術指標"""
@@ -410,7 +391,7 @@ app.layout = html.Div([
410
  html.Div([
411
  html.Div([
412
  html.Label("選擇股票:"),
413
- dcc.Dropdown(id='stock-dropdown', options=[{'label': name, 'value': symbol} for name, symbol in TAIWAN_STOCKS.items()], value='0050.TW', style={'margin-bottom': '10px'})
414
  ], style={'width': '30%', 'display': 'inline-block', 'vertical-align': 'top'}),
415
  html.Div([
416
  html.Label("時間範圍:"),
@@ -484,26 +465,18 @@ app.layout = html.Div([
484
  def update_taiex_prediction(predict_days):
485
  data = get_stock_data('^TWII', '2y')
486
  if data.empty: return html.Div("無法獲取台指期資料"), {}
487
-
488
- # === 修改點:統一呼叫 get_prediction 控制器 ===
489
- final_prediction = get_prediction(data, predict_days)
490
-
491
  if final_prediction is None: return html.Div("資料不足,無法進行預測"), {}
492
  current_price, last_date = data['Close'].iloc[-1], data.index[-1]
493
  predicted_price, change_pct, confidence = final_prediction['predicted_price'], final_prediction['change_pct'], final_prediction['confidence']
494
-
495
  prediction_paths = {1: [1], 5: [1, 5], 10: [1, 5, 10], 20: [1, 10, 20], 60: [1, 10, 20, 60]}
496
  intervals_to_predict = prediction_paths.get(predict_days, [predict_days])
497
  prediction_dates, prediction_prices = [last_date], [current_price]
498
-
499
  for days in intervals_to_predict:
500
- # === 修改點:迴圈內也使用統一的預測控制器 ===
501
- interim_prediction = get_prediction(data, days)
502
  if interim_prediction:
503
  prediction_dates.append(last_date + timedelta(days=days))
504
  prediction_prices.append(interim_prediction['predicted_price'])
505
-
506
- # (後續繪圖邏輯不變)
507
  color, arrow = ('red', '📈') if change_pct >= 0 else ('green', '📉')
508
  result_card = html.Div([
509
  html.H4(f"{predict_days}日後預測結果", style={'margin': '0 0 15px 0', 'color': 'white'}),
 
15
  import requests
16
  import time # 引用 time 模組以處理時間戳
17
 
 
18
  # 引用您組員的預測器程式
19
  from Bert_predict import BertPredictor
20
 
 
 
 
 
 
 
 
 
 
 
 
21
  # ========================= CACHE 設定 START =========================
22
  # 分析結果的快取字典
23
  ANALYSIS_CACHE = {}
24
  # 快取有效時間(秒),例如:4 小時 = 4 * 60 * 60 = 14400 秒
25
  CACHE_DURATION_SECONDS = 8 * 60 * 60
26
  # ========================== CACHE 設定 END ==========================
27
+
28
 
29
  # 台股代號對應表 (移除台指期,因為它現在是獨立區塊)
30
  TAIWAN_STOCKS = {
 
55
  '合庫金': '5880.TW',
56
  '華南金': '2880.TW',
57
  '台光電': '2383.TW',
58
+ '世芯-KY': '3661.TWO',
59
  '奇鋐': '3017.TW',
60
  '凱基金': '2883.TW',
61
  '大立光': '3008.TW',
 
169
  except:
170
  return pd.DataFrame()
171
 
172
+ def simple_lstm_predict(data, predict_days=5):
173
+ """簡化的LSTM預測模型 (使用統計方法模擬)"""
174
+ if len(data) < 60:
175
+ return None
176
  prices = data['Close'].values
177
  ma_short = np.mean(prices[-5:])
178
  ma_medium = np.mean(prices[-20:])
 
180
  recent_trend = np.polyfit(range(20), prices[-20:], 1)[0]
181
  volatility = np.std(prices[-20:]) / np.mean(prices[-20:])
182
  base_change = recent_trend * predict_days
183
+ trend_factor = 1.0
184
+ if ma_short > ma_medium > ma_long:
185
+ trend_factor = 1.02
186
+ elif ma_short < ma_medium < ma_long:
187
+ trend_factor = 0.98
188
+ else:
189
+ trend_factor = 1.0
190
  noise_factor = np.random.normal(1, volatility * 0.1)
191
  predicted_price = prices[-1] * trend_factor + base_change + (prices[-1] * noise_factor * 0.01)
192
  change_pct = ((predicted_price - prices[-1]) / prices[-1]) * 100
193
+ return {
194
+ 'predicted_price': predicted_price,
195
+ 'change_pct': change_pct,
196
+ 'confidence': max(0.6, 1 - volatility * 2)
197
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
198
 
199
  def calculate_technical_indicators(df):
200
  """計算技術指標"""
 
391
  html.Div([
392
  html.Div([
393
  html.Label("選擇股票:"),
394
+ dcc.Dropdown(id='stock-dropdown', options=[{'label': name, 'value': symbol} for name, symbol in TAIWAN_STOCKS.items()], value='2330.TW', style={'margin-bottom': '10px'})
395
  ], style={'width': '30%', 'display': 'inline-block', 'vertical-align': 'top'}),
396
  html.Div([
397
  html.Label("時間範圍:"),
 
465
  def update_taiex_prediction(predict_days):
466
  data = get_stock_data('^TWII', '2y')
467
  if data.empty: return html.Div("無法獲取台指期資料"), {}
468
+ final_prediction = simple_lstm_predict(data, predict_days)
 
 
 
469
  if final_prediction is None: return html.Div("資料不足,無法進行預測"), {}
470
  current_price, last_date = data['Close'].iloc[-1], data.index[-1]
471
  predicted_price, change_pct, confidence = final_prediction['predicted_price'], final_prediction['change_pct'], final_prediction['confidence']
 
472
  prediction_paths = {1: [1], 5: [1, 5], 10: [1, 5, 10], 20: [1, 10, 20], 60: [1, 10, 20, 60]}
473
  intervals_to_predict = prediction_paths.get(predict_days, [predict_days])
474
  prediction_dates, prediction_prices = [last_date], [current_price]
 
475
  for days in intervals_to_predict:
476
+ interim_prediction = simple_lstm_predict(data, days)
 
477
  if interim_prediction:
478
  prediction_dates.append(last_date + timedelta(days=days))
479
  prediction_prices.append(interim_prediction['predicted_price'])
 
 
480
  color, arrow = ('red', '📈') if change_pct >= 0 else ('green', '📉')
481
  result_card = html.Div([
482
  html.H4(f"{predict_days}日後預測結果", style={'margin': '0 0 15px 0', 'color': 'white'}),