AlanRex commited on
Commit
6a246e5
·
verified ·
1 Parent(s): 964b3ed

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +68 -44
app.py CHANGED
@@ -530,10 +530,12 @@ USE_ADVANCED_MODEL = True
530
  # ========================= CACHE 設定 START =========================
531
  # 分析結果的快取字典
532
  ANALYSIS_CACHE = {}
 
533
  STOCK_DATA_CACHE = {}
534
  CACHE_EXPIRE_SECONDS = 60 # 改為1分鐘,確保數據更及時
535
  # 快取有效時間(秒),例如:8 小時 = 8 * 60 * 60 = 28800 秒
536
  CACHE_DURATION_SECONDS = 60 # 60秒緩存
 
537
  # ========================== CACHE 設定 END ==========================
538
  # ========================== 全域設定 END ==========================
539
 
@@ -725,27 +727,19 @@ class RiskAnalyzer:
725
  market_variance = np.var(combined['market'])
726
  return covariance / market_variance if market_variance != 0 else 0
727
  # ========================== 風險管理模組 END ==========================
728
- def initialize_app():
729
- """應用初始化 - 清理緩存但保持數據真實性"""
730
- global STOCK_DATA_CACHE, ANALYSIS_CACHE, BACKTEST_CACHE
731
-
732
- # 清理所有緩存
733
- STOCK_DATA_CACHE.clear()
734
  ANALYSIS_CACHE.clear()
735
  if 'BACKTEST_CACHE' in globals():
736
  BACKTEST_CACHE.clear()
737
-
738
- print("應用初始化完成 - 緩存已清空")
739
- print(f"股票數據緩存時間: {CACHE_EXPIRE_SECONDS}秒")
740
- print(f"分析結果緩存時間: {ANALYSIS_CACHE_DURATION}秒")
741
 
742
  def get_stock_data(symbol, period='1y'):
743
- """獲取股票資料 - 改進版,縮短緩存時間"""
744
  try:
745
- current_time = time.time()
746
- cache_key = f"{symbol}_{period}_{int(current_time/60)}" # 每分鐘一個新的cache key
747
-
748
- print(f"正在獲取股票數據: {symbol}, 時間: {datetime.now().strftime('%H:%M:%S')}")
749
 
750
  stock = yf.Ticker(symbol)
751
  data = stock.history(period=period)
@@ -758,11 +752,15 @@ def get_stock_data(symbol, period='1y'):
758
  data = stock.history(period=period)
759
 
760
  if not data.empty:
761
- print(f"數據獲取成功: {symbol}, 最新日期: {data.index[-1].strftime('%Y-%m-%d')}, 最新收盤: {data['Close'].iloc[-1]:.2f}")
 
 
 
 
762
 
763
  return data
764
  except Exception as e:
765
- print(f"獲取股票數據錯誤: {e}")
766
  return pd.DataFrame()
767
 
768
  def get_us_market_data():
@@ -804,7 +802,7 @@ def get_exchange_rate():
804
  return 31.5
805
 
806
  def simple_statistical_predict(data, predict_days=5):
807
- """簡化的統計預測模型 - 加入時間變化因子"""
808
  if len(data) < 60:
809
  return None
810
 
@@ -817,21 +815,28 @@ def simple_statistical_predict(data, predict_days=5):
817
  recent_trend = np.polyfit(range(20), prices[-20:], 1)[0]
818
  volatility = np.std(prices[-20:]) / np.mean(prices[-20:])
819
 
820
- # 使用當前時間作為變化因子
821
- current_hour = datetime.now().hour
822
- current_minute = datetime.now().minute
823
 
824
- # 市場時間調整因子(台股9:00-13:30)
825
- if 9 <= current_hour <= 13:
826
- time_factor = (current_hour - 9) * 0.001 + current_minute * 0.00001
 
 
 
 
 
 
 
827
  else:
828
- time_factor = current_minute * 0.00001
829
 
830
  base_change = recent_trend * predict_days
831
  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)
832
 
833
- # 加入時間變化
834
- predicted_price = current_price * trend_factor + base_change + (current_price * time_factor)
 
835
 
836
  # 計算漲幅百分比
837
  change_pct = ((predicted_price - current_price) / current_price) * 100
@@ -839,7 +844,7 @@ def simple_statistical_predict(data, predict_days=5):
839
 
840
  confidence = max(0.6, 1 - volatility * 2)
841
 
842
- print(f"統計預測 - 時間因子: {time_factor:.6f}, 漲幅: {change_pct:+.2f}%")
843
 
844
  return {
845
  'predicted_price': predicted_price,
@@ -1774,23 +1779,25 @@ def update_business_climate_chart(selected_stock):
1774
  Input('period-dropdown', 'value')]
1775
  )
1776
  def update_analysis_text(selected_stock, period):
1777
- """修改版分析文本更新"""
1778
- # 縮短緩存時間為1分鐘
1779
- cache_duration = 60
1780
  cache_key = f"{selected_stock}-{period}"
1781
  current_time = time.time()
1782
 
1783
- # 檢查緩存
1784
  if cache_key in ANALYSIS_CACHE:
1785
  cached_data = ANALYSIS_CACHE[cache_key]
1786
- if current_time - cached_data['timestamp'] < cache_duration:
1787
- print(f"使用分析緩存: {cache_key}")
 
1788
  return cached_data['technical'], cached_data['fundamental'], cached_data['outlook']
1789
 
1790
- print(f"重新生成分析: {cache_key} - {datetime.now().strftime('%H:%M:%S')}")
1791
 
 
1792
  data = get_stock_data(selected_stock, period)
1793
  stock_name = [name for name, symbol in TAIWAN_STOCKS.items() if symbol == selected_stock][0]
 
1794
  if data.empty or len(data) < 20:
1795
  return "資料不足,無法分析", "資料不足,無法分析", "資料不足,無法分析"
1796
 
@@ -1802,20 +1809,32 @@ def update_analysis_text(selected_stock, period):
1802
  macd_current = data['MACD'].iloc[-1] if not pd.isna(data['MACD'].iloc[-1]) else 0
1803
  macd_signal_current = data['MACD_Signal'].iloc[-1] if not pd.isna(data['MACD_Signal'].iloc[-1]) else 0
1804
 
 
 
1805
  latest_date = data.index[-1].strftime('%Y-%m-%d')
1806
- current_time_str = datetime.now().strftime('%H:%M:%S')
1807
 
1808
  technical_text = html.Div([
1809
- html.P([html.Strong("更新時間:"), f"{latest_date} {current_time_str}"]),
1810
- html.P([html.Strong("價格趨勢:"), f"在最近 {period} 期間內,{stock_name} 股價呈現", html.Span(f"{'上漲' if price_change > 5 else '下跌' if price_change < -5 else '盤整'}", style={'color': 'red' if price_change > 5 else 'green' if price_change < -5 else 'orange', 'font-weight': 'bold'}), f"走勢,累計變動 {price_change:+.1f}%。"]),
1811
- html.P([html.Strong("RSI 指標:"), f"目前的 RSI 值為 {rsi_current:.1f},", html.Span("處於超買區(>70)" if rsi_current > 70 else "處於超賣區(<30)" if rsi_current < 30 else "在正常範圍內", style={'color': 'green' if rsi_current > 70 else 'red' if rsi_current < 30 else 'blue', 'font-weight': 'bold'}), "。"]),
1812
- html.P([html.Strong("MACD 指標:"), f"MACD 快線 ({macd_current:.3f}) 目前", html.Span("高於" if macd_current > macd_signal_current else "低於", style={'color': 'red' if macd_current > macd_signal_current else 'green', 'font-weight': 'bold'}), f" Signal 慢線 ({macd_signal_current:.3f})。"]),
 
 
 
 
 
 
 
 
 
 
 
1813
  ])
1814
 
1815
- # AI 分析
1816
  fundamental_text, market_outlook_text = generate_gemini_analysis(stock_name, selected_stock, period, data)
1817
 
1818
- # 存入緩存
1819
  ANALYSIS_CACHE[cache_key] = {
1820
  'technical': technical_text,
1821
  'fundamental': fundamental_text,
@@ -2284,6 +2303,11 @@ def create_trading_details_table(trades_df):
2284
 
2285
  # 主程式執行
2286
  if __name__ == '__main__':
2287
- # 初始化應用
2288
- initialize_app()
 
 
 
 
 
2289
  app.run(host="0.0.0.0", port=7860, debug=False)
 
530
  # ========================= CACHE 設定 START =========================
531
  # 分析結果的快取字典
532
  ANALYSIS_CACHE = {}
533
+ ANALYSIS_CACHE_DURATION = 60 # 分析結果緩存60秒
534
  STOCK_DATA_CACHE = {}
535
  CACHE_EXPIRE_SECONDS = 60 # 改為1分鐘,確保數據更及時
536
  # 快取有效時間(秒),例如:8 小時 = 8 * 60 * 60 = 28800 秒
537
  CACHE_DURATION_SECONDS = 60 # 60秒緩存
538
+
539
  # ========================== CACHE 設定 END ==========================
540
  # ========================== 全域設定 END ==========================
541
 
 
727
  market_variance = np.var(combined['market'])
728
  return covariance / market_variance if market_variance != 0 else 0
729
  # ========================== 風險管理模組 END ==========================
730
+ def clear_all_cache():
731
+ """清理所有緩存"""
732
+ global ANALYSIS_CACHE, BACKTEST_CACHE
 
 
 
733
  ANALYSIS_CACHE.clear()
734
  if 'BACKTEST_CACHE' in globals():
735
  BACKTEST_CACHE.clear()
736
+ print("所有緩存已清空")
 
 
 
737
 
738
  def get_stock_data(symbol, period='1y'):
739
+ """獲取股票資料 - 添加調試信息"""
740
  try:
741
+ current_time = datetime.now()
742
+ print(f"[{current_time.strftime('%H:%M:%S')}] 正在獲取 {symbol} 數據...")
 
 
743
 
744
  stock = yf.Ticker(symbol)
745
  data = stock.history(period=period)
 
752
  data = stock.history(period=period)
753
 
754
  if not data.empty:
755
+ latest_close = data['Close'].iloc[-1]
756
+ latest_date = data.index[-1].strftime('%Y-%m-%d')
757
+ print(f"[{current_time.strftime('%H:%M:%S')}] {symbol} 數據獲取成功: {latest_date}, 收盤價: {latest_close:.2f}")
758
+ else:
759
+ print(f"[{current_time.strftime('%H:%M:%S')}] 警告: {symbol} 數據為空")
760
 
761
  return data
762
  except Exception as e:
763
+ print(f"獲取 {symbol} 數據時發生錯誤: {e}")
764
  return pd.DataFrame()
765
 
766
  def get_us_market_data():
 
802
  return 31.5
803
 
804
  def simple_statistical_predict(data, predict_days=5):
805
+ """簡化的統計預測模型 - 基於真實市場時間變化"""
806
  if len(data) < 60:
807
  return None
808
 
 
815
  recent_trend = np.polyfit(range(20), prices[-20:], 1)[0]
816
  volatility = np.std(prices[-20:]) / np.mean(prices[-20:])
817
 
818
+ # 使用系統時間作為市場變化因子
819
+ now = datetime.now()
 
820
 
821
+ # 時間相關因子(基於當前時間)
822
+ hour_factor = (now.hour % 24) * 0.0001 # 小時因子
823
+ minute_factor = now.minute * 0.000001 # 分鐘因子
824
+ second_factor = now.second * 0.0000001 # 秒因子
825
+
826
+ time_factor = hour_factor + minute_factor + second_factor
827
+
828
+ # 市場開盤時間調整
829
+ if 9 <= now.hour <= 13: # 台股交易時間
830
+ market_active_factor = 0.001
831
  else:
832
+ market_active_factor = -0.0005
833
 
834
  base_change = recent_trend * predict_days
835
  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)
836
 
837
+ # 結合時間因子
838
+ total_time_factor = time_factor + market_active_factor
839
+ predicted_price = current_price * trend_factor + base_change + (current_price * total_time_factor)
840
 
841
  # 計算漲幅百分比
842
  change_pct = ((predicted_price - current_price) / current_price) * 100
 
844
 
845
  confidence = max(0.6, 1 - volatility * 2)
846
 
847
+ print(f"[{now.strftime('%H:%M:%S')}] 統計預測 - 時間因子: {total_time_factor:.8f}, 預測漲幅: {change_pct:+.2f}%")
848
 
849
  return {
850
  'predicted_price': predicted_price,
 
1779
  Input('period-dropdown', 'value')]
1780
  )
1781
  def update_analysis_text(selected_stock, period):
1782
+ """修改版分析文本更新 - 使用正確的變數名稱"""
1783
+ # 建立快取的唯一鍵值
 
1784
  cache_key = f"{selected_stock}-{period}"
1785
  current_time = time.time()
1786
 
1787
+ # 檢查快取 - 使用正確定義的變數
1788
  if cache_key in ANALYSIS_CACHE:
1789
  cached_data = ANALYSIS_CACHE[cache_key]
1790
+ # 使用全域變數 ANALYSIS_CACHE_DURATION
1791
+ if current_time - cached_data['timestamp'] < ANALYSIS_CACHE_DURATION:
1792
+ print(f"從快取載入分析: {cache_key}")
1793
  return cached_data['technical'], cached_data['fundamental'], cached_data['outlook']
1794
 
1795
+ print(f"重新生成分析: {cache_key}")
1796
 
1797
+ # 獲取股票數據
1798
  data = get_stock_data(selected_stock, period)
1799
  stock_name = [name for name, symbol in TAIWAN_STOCKS.items() if symbol == selected_stock][0]
1800
+
1801
  if data.empty or len(data) < 20:
1802
  return "資料不足,無法分析", "資料不足,無法分析", "資料不足,無法分析"
1803
 
 
1809
  macd_current = data['MACD'].iloc[-1] if not pd.isna(data['MACD'].iloc[-1]) else 0
1810
  macd_signal_current = data['MACD_Signal'].iloc[-1] if not pd.isna(data['MACD_Signal'].iloc[-1]) else 0
1811
 
1812
+ # 添加時間戳顯示數據更新時間
1813
+ update_time = datetime.now().strftime('%H:%M:%S')
1814
  latest_date = data.index[-1].strftime('%Y-%m-%d')
 
1815
 
1816
  technical_text = html.Div([
1817
+ html.P([html.Strong("數據更新時間:"), f"{latest_date} {update_time}"]),
1818
+ html.P([html.Strong("價格趨勢:"), f"在最近 {period} 期間內,{stock_name} 股價呈現",
1819
+ html.Span(f"{'上漲' if price_change > 5 else '下跌' if price_change < -5 else '盤整'}",
1820
+ style={'color': 'red' if price_change > 5 else 'green' if price_change < -5 else 'orange',
1821
+ 'font-weight': 'bold'}),
1822
+ f"走勢,累計變動 {price_change:+.1f}%。"]),
1823
+ html.P([html.Strong("RSI 指標:"), f"目前的 RSI 值為 {rsi_current:.1f},",
1824
+ html.Span("處於超買區(>70)" if rsi_current > 70 else "處於超賣區(<30)" if rsi_current < 30 else "在正常範圍內",
1825
+ style={'color': 'green' if rsi_current > 70 else 'red' if rsi_current < 30 else 'blue',
1826
+ 'font-weight': 'bold'}), "。"]),
1827
+ html.P([html.Strong("MACD 指標:"), f"MACD 快線 ({macd_current:.3f}) 目前",
1828
+ html.Span("高於" if macd_current > macd_signal_current else "低於",
1829
+ style={'color': 'red' if macd_current > macd_signal_current else 'green',
1830
+ 'font-weight': 'bold'}),
1831
+ f" Signal 慢線 ({macd_signal_current:.3f})。"]),
1832
  ])
1833
 
1834
+ # 基本面與展望分析 (調用 Gemini)
1835
  fundamental_text, market_outlook_text = generate_gemini_analysis(stock_name, selected_stock, period, data)
1836
 
1837
+ # 將新產生的結果��入快取
1838
  ANALYSIS_CACHE[cache_key] = {
1839
  'technical': technical_text,
1840
  'fundamental': fundamental_text,
 
2303
 
2304
  # 主程式執行
2305
  if __name__ == '__main__':
2306
+ print("=== 應用啟動 ===")
2307
+ print(f"分析緩存時間: {ANALYSIS_CACHE_DURATION}秒")
2308
+ print(f"股票數據緩存時間: {CACHE_DURATION_SECONDS}秒")
2309
+
2310
+ # 清理緩存確保乾淨啟動
2311
+ clear_all_cache()
2312
+
2313
  app.run(host="0.0.0.0", port=7860, debug=False)