AlanRex commited on
Commit
50be322
·
verified ·
1 Parent(s): 625124c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +120 -39
app.py CHANGED
@@ -13,6 +13,9 @@ import re
13
  from bs4 import BeautifulSoup
14
  import requests
15
 
 
 
 
16
  # 台股代號對應表 (移除台指期,因為它現在是獨立區塊)
17
  TAIWAN_STOCKS = {
18
  '元大台灣50': '0050.TW', # 新增
@@ -1476,57 +1479,135 @@ def update_comparison_analysis(selected_stocks, period):
1476
  [dash.dependencies.Input('stock-dropdown', 'value')]
1477
  )
1478
  def update_sentiment_analysis(selected_stock):
1479
- # 模擬情緒指標(實際應用中可接入新聞API或情緒分析服務)
1480
- sentiment_score = np.random.uniform(30, 80) # 模擬情緒分數 0-100
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1481
 
1482
- # 建立情緒指標圓形圖
1483
  gauge_fig = go.Figure(go.Indicator(
1484
- mode = "gauge+number+delta",
1485
- value = sentiment_score,
1486
  domain = {'x': [0, 1], 'y': [0, 1]},
1487
  title = {'text': "市場情緒指數"},
1488
- delta = {'reference': 50},
1489
  gauge = {
1490
- 'axis': {'range': [None, 100]},
1491
- 'bar': {'color': "darkred"},
1492
  'steps': [
1493
- {'range': [0, 30], 'color': "lightgreen"},
1494
- {'range': [30, 70], 'color': "lightgray"},
1495
- {'range': [70, 100], 'color': "lightcoral"}
1496
  ],
1497
- 'threshold': {
1498
- 'line': {'color': "red", 'width': 4},
1499
- 'thickness': 0.75,
1500
- 'value': 90
1501
- }
 
1502
  }
1503
  ))
1504
 
1505
  gauge_fig.update_layout(height=200, margin=dict(l=20, r=20, t=40, b=20))
1506
 
1507
- # 模擬新聞摘要
1508
- stock_name = [name for name, symbol in TAIWAN_STOCKS.items() if symbol == selected_stock][0]
1509
-
1510
- news_items = [
1511
- f"📈 {stock_name}獲外資調升目標價,看好後續發展前景",
1512
- f"💼 法人預期{stock_name}下季營收將較上季成長5-10%",
1513
- f"🌐 國際市場波動對{stock_name}影響有限,基本面穩健",
1514
- f"⚡ 產業景氣回溫,{stock_name}受惠程度值得關注",
1515
- f"📊 技術面顯示{stock_name}突破關鍵壓力,短線偏多"
1516
- ]
1517
-
1518
- news_content = html.Div([
1519
- html.P(news, style={
1520
- 'margin': '8px 0',
1521
- 'padding': '8px',
1522
- 'background': '#f8f9fa',
1523
- 'border-radius': '5px',
1524
- 'border-left': '3px solid #17a2b8',
1525
- 'font-size': '13px'
1526
- }) for news in news_items[:3] # 顯示前3條
1527
- ])
1528
-
1529
- return dcc.Graph(figure=gauge_fig), news_content
1530
 
1531
  # 在 Colab 中執行的設定
1532
  if __name__ == '__main__':
 
13
  from bs4 import BeautifulSoup
14
  import requests
15
 
16
+ # 引入 BERT 預測模組
17
+ from Bert_predict import predict_sentiment
18
+
19
  # 台股代號對應表 (移除台指期,因為它現在是獨立區塊)
20
  TAIWAN_STOCKS = {
21
  '元大台灣50': '0050.TW', # 新增
 
1479
  [dash.dependencies.Input('stock-dropdown', 'value')]
1480
  )
1481
  def update_sentiment_analysis(selected_stock):
1482
+ stock_name = [name for name, symbol in TAIWAN_STOCKS.items() if symbol == selected_stock][0]
1483
+
1484
+ # --- 修改部分:從 CSV 檔案讀取新聞 ---
1485
+ # 假設 CSV 檔案名稱是 'news_YYYY-MM-DD.csv' 並且與主程式在同一目錄
1486
+ # 您需要確保新聞檔案的命名規則與此一致,或者修改檔案名稱的獲取方式
1487
+ today_str = datetime.now().strftime('%Y-%m-%d') # 獲取今天的日期
1488
+ news_csv_filename = f'news_{today_str}.csv' # 例如: news_2025-09-12.csv
1489
+
1490
+ news_items_content = []
1491
+ try:
1492
+ # 檢查檔案是否存在
1493
+ if not os.path.exists(news_csv_filename):
1494
+ print(f"警告:新聞檔案 '{news_csv_filename}' 不存在。將使用預設新聞。")
1495
+ # 如果檔案不存在,可以選擇顯示錯誤訊息或使用預設模擬新聞
1496
+ news_items_content = [
1497
+ f"⚠️ 無法載入新聞檔案 '{news_csv_filename}',顯示預設內容。",
1498
+ f"📈 {stock_name} 股價受到市場關注。",
1499
+ f"📉 投資者情緒趨於謹慎。",
1500
+ ]
1501
+ else:
1502
+ news_df = pd.read_csv(news_csv_filename)
1503
+ # 確保 CSV 檔案中存在 '內容' 欄位
1504
+ if '內容' in news_df.columns:
1505
+ news_items_content = news_df['內容'].tolist()
1506
+ else:
1507
+ print(f"警告:CSV 檔案 '{news_csv_filename}' 中未找到 '內容' 欄位。")
1508
+ news_items_content = [
1509
+ f"⚠️ CSV 檔案 '{news_csv_filename}' 格式錯誤,未找到 '內容' 欄位。",
1510
+ f"📈 {stock_name} 股價動態。",
1511
+ f"📉 市場消息更新。",
1512
+ ]
1513
+ except FileNotFoundError:
1514
+ print(f"警告:新聞檔案 '{news_csv_filename}' 讀取時發生 FileNotFoundError。")
1515
+ news_items_content = [
1516
+ f"⚠️ 讀取新聞檔案 '{news_csv_filename}' 時發生錯誤。",
1517
+ f"📈 {stock_name} 股價分析。",
1518
+ f"📉 投資者情緒參考。",
1519
+ ]
1520
+ except Exception as e:
1521
+ print(f"讀取 CSV 檔案 '{news_csv_filename}' 時發生未預期錯誤:{e}")
1522
+ news_items_content = [
1523
+ f"⚠️ 讀取新聞檔案 '{news_csv_filename}' 時發生錯誤:{e}",
1524
+ f"📈 {stock_name} 股價資訊。",
1525
+ f"📉 市場趨勢分析。",
1526
+ ]
1527
+
1528
+ # --- 接著對讀取的新聞內容進行情緒分析 ---
1529
+ total_sentiment_score = 0
1530
+ analyzed_news_html = []
1531
+ sentiment_mapping = {'negative': 0, 'neutral': 50, 'positive': 100} # BERT 輸出的映射
1532
+
1533
+ if not news_items_content: # 如果 news_items_content 為空
1534
+ analyzed_news_html.append(html.P("目前沒有新聞可供分析。", style={'font-style': 'italic'}))
1535
+ avg_sentiment_score = 50 # 預設為中性
1536
+ else:
1537
+ for news in news_items_content:
1538
+ # 使用 BERT 模型進行預測
1539
+ # predict_sentiment 應返回 (sentiment_label, probability_score)
1540
+ # 例如:('positive', 0.95)
1541
+ sentiment_label, probability_score = predict_sentiment(news)
1542
+
1543
+ # 將情緒標籤轉換為數值分數
1544
+ numeric_score = sentiment_mapping.get(sentiment_label, 50) # 預設為中性
1545
+
1546
+ total_sentiment_score += numeric_score
1547
+
1548
+ # 設置顯示顏色和表情符號
1549
+ sentiment_emoji = '⚪'
1550
+ sentiment_color = 'gray'
1551
+ if sentiment_label == 'positive':
1552
+ sentiment_emoji = '🟢'
1553
+ sentiment_color = 'green'
1554
+ elif sentiment_label == 'neutral':
1555
+ sentiment_emoji = '🟡'
1556
+ sentiment_color = 'orange'
1557
+ elif sentiment_label == 'negative':
1558
+ sentiment_emoji = '🔴'
1559
+ sentiment_color = 'red'
1560
+
1561
+ # 建立新聞摘要的 HTML 元素
1562
+ analyzed_news_html.append(
1563
+ html.P([
1564
+ html.Span(f"{sentiment_emoji} ", style={'font-size': '1.2em'}),
1565
+ html.A(news, href="#", style={
1566
+ 'color': sentiment_color,
1567
+ 'text-decoration': 'none',
1568
+ 'font-weight': 'bold'
1569
+ }),
1570
+ html.Br(),
1571
+ html.Small(f"情緒: {sentiment_label}, 信賴度: {probability_score:.2%}", style={'margin-left': '20px', 'color': 'gray'})
1572
+ ], style={
1573
+ 'margin': '8px 0',
1574
+ 'padding': '8px',
1575
+ 'background': '#f8f9fa',
1576
+ 'border-radius': '5px',
1577
+ 'border-left': f'3px solid {sentiment_color}',
1578
+ 'font-size': '13px'
1579
+ })
1580
+ )
1581
+
1582
+ # 計算平均情緒分數
1583
+ avg_sentiment_score = total_sentiment_score / len(news_items_content)
1584
 
1585
+ # --- 建立情緒指標圓形圖 (Gauge Chart) ---
1586
  gauge_fig = go.Figure(go.Indicator(
1587
+ mode = "gauge+number",
1588
+ value = avg_sentiment_score,
1589
  domain = {'x': [0, 1], 'y': [0, 1]},
1590
  title = {'text': "市場情緒指數"},
 
1591
  gauge = {
1592
+ 'axis': {'range': [0, 100], 'tickvals': [0, 25, 50, 75, 100], 'ticktext': ['極度負面', '', '中性', '', '極度正面']},
1593
+ 'bar': {'color': "#667eea"}, # 預設的 bar 顏色,可選
1594
  'steps': [
1595
+ {'range': [0, 30], 'color': "#e74c3c"}, # 紅色 (負面)
1596
+ {'range': [30, 70], 'color': "#f1c40f"}, # 黃色 (中性)
1597
+ {'range': [70, 100], 'color': "#2ecc71"} # 綠色 (正面)
1598
  ],
1599
+ # 您可以在這裡調整 threshold 的設定,如果需要的話
1600
+ # 'threshold': {
1601
+ # 'line': {'color': "red", 'width': 4},
1602
+ # 'thickness': 0.75,
1603
+ # 'value': 75 # 例如,設定一個門檻值
1604
+ # }
1605
  }
1606
  ))
1607
 
1608
  gauge_fig.update_layout(height=200, margin=dict(l=20, r=20, t=40, b=20))
1609
 
1610
+ return dcc.Graph(figure=gauge_fig), html.Div(analyzed_news_html)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1611
 
1612
  # 在 Colab 中執行的設定
1613
  if __name__ == '__main__':