Skip to content

terryuuang/TWSE_LINE_BOT

Repository files navigation

TWSE LINE Bot

Deploy on Zeabur Python FastAPI

台股 LINE 助理,提供每日選股推薦、個股查詢、我的最愛、手動追蹤提醒、AI 問答功能。
專案使用 FastAPI + LINE Messaging API + SQLite,並整合 twstock、TWSE OpenAPI、TPEx OpenAPI,並可選擇用 FinMind 補強單檔現金流。

目前完整度

目前專案已具備可本機驗證的 MVP 到早期 production-ready 基礎:LINE webhook、查詢、推薦、最愛/手動追蹤、告警、AI context、排程 ETL、SQLite schema、Docker/Zeabur 部署設定與使用者流程 QA 都已存在。

仍需留意的缺口:

  • 尚未納入正式監控、告警儀表板與備份/還原流程;SQLite 適合目前規模,但多人或高流量部署應規劃 Postgres。
  • 外部資料來源仍以交易所公開 API、twstock 與選配 FinMind 為主,需在 LINE payload 持續揭露資料日期、缺資料與限流狀態。
  • AI tool calling 預設關閉;上線前應以實際 LINE 對話檢查成本、延遲與錯誤 fallback。
  • 推薦邏輯已有 guard 與回測腳本,但若要宣稱模型有效,仍需要固定週期回測、樣本外驗證與績效紀錄。
  • CMONEY/Qdata/DataHub 這類商用資料源需要正式授權與憑證後再整合,不應依賴未公開或未授權端點。

功能

  • 每日推薦
    • 今日推薦預設回覆波段推薦
    • 可切換長投推薦
    • 推薦卡顯示產業、分項因子、資料完整度、現價/基準價、情境目標與轉弱價
  • 個股查詢
    • 支援代碼查詢,例如 查 2330
    • 支援名稱查詢,例如 查 台積電
    • 盤中優先使用即時報價
    • 基本面顯示 ROE、ROA、負債比、流動比、每股淨值
    • 可選擇補單檔營業現金流與自由現金流
    • 顯示近月 MOPS 重大訊息,輔助判斷公司公告事件
  • 我的最愛與手動追蹤
    • 建立最多 20 檔最愛清單
    • 可選擇手動記錄觀察成本
    • 快速新增 / 更新手動觀察紀錄
    • 手動追蹤 Flex 顯示
  • 告警與推播
    • 跌破均線
    • 停損 / 停利條件
    • 每日摘要與推薦推播
  • AI 問答
    • 結合個股技術面、基本面與使用者手動追蹤資訊
    • 詳細分析會合併最新價格/技術與最新完整市場日基本面,避免單檔背景補資料造成基本面缺漏
    • 若推薦快照基準日落後最新價格日,AI context 會標記 recommendation.is_stale=true,並提供 current_signal 作為當下估算
    • 基本面分析會附產業別與產業中位數比較
    • 可選擇啟用 AI tool calling,只在複雜對話中查詢必要工具
    • 輸出為 LINE 友善純文字,不使用 Markdown
  • 股票圖表
    • 查詢卡片內建近 31 日 K 線與成交量圖
    • 圖表由系統根據 OHLC 資料產生,不使用 AI 繪圖
  • LINE 介面
    • 歡迎訊息 Flex 化
    • 支援 LINE loading 動畫
    • Rich Menu 背景圖產生腳本
    • 自訂 Rich Menu 上傳腳本

技術架構

Web 與 Bot

  • FastAPI
  • line-bot-sdk
  • OpenAI Python SDK

資料來源

  • twstock
    • 股票代碼與名稱映射
    • 盤中即時報價
  • TWSE OpenAPI
    • 本益比 / 殖利率 / 股價淨值比
    • 月營收 YoY
    • 綜合損益表、資產負債表衍生指標
    • EPS、毛利率、營業利益率、淨利率
    • ROE、ROA、負債比、流動比、每股淨值
    • 注意股、處置股、暫停交易事件
  • TPEx OpenAPI
    • 上櫃本益比 / 殖利率 / 股價淨值比
    • 上櫃綜合損益表、資產負債表衍生指標
    • 上櫃 EPS、毛利率、營業利益率、淨利率
    • 上櫃 ROE、ROA、負債比、流動比、每股淨值
    • 上櫃注意股、處置股、暫停交易事件
  • FinMind(可選)
    • 單檔現金流量表
    • 營業現金流、投資現金流、籌資現金流、自由現金流
  • MOPS 公開資訊觀測站(免 API key,選配)
    • 近月重大訊息列表
    • 個股查詢卡與 AI context 會顯示公告日期、時間、主旨與資料來源
    • 使用 mopsov.twse.com.tw 查詢頁 HTML,需快取與 fallback;不可視為價格預測

儲存

  • SQLite
    • stock_daily_features 同時保存完整市場日資料與背景單檔歷史補資料
    • 完整市場基準日由 MARKET_BASELINE_MIN_SYMBOLS 控制,避免 partial backfill date 誤導推薦與市場摘要
    • backfill_state 追蹤背景補資料進度

專案結構

app/
  handlers/     LINE 任務分派與功能 handler
  scheduler/    ETL、評分、告警與推播排程
  services/     資料抓取、評分、AI、LINE 傳送
  templates/    Flex Message 模板
  main.py       FastAPI 入口
scripts/
  init_db.py                    初始化資料庫
  generate_rich_menu_image.py   產生 Rich Menu 背景圖
  setup_rich_menu.py            Rich Menu 區塊設定參考
data/
  twse_bot.db
Dockerfile
zeabur.json

安裝

建議使用 Python 3.12。

python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

環境變數

專案使用 .env 載入設定。第一次部署只需要填最小必要變數:

OPENAI_API_KEY=your_openai_api_key
Channel_Secret=your_line_channel_secret
Channel_Access_Token=your_line_channel_access_token

第一次部署到 PaaS 時通常還沒有公開 URL,所以 PUBLIC_BASE_URL 可以先不填。服務啟動後,PaaS 會提供 domain;拿到 domain 後再回到環境變數補上:

PUBLIC_BASE_URL=https://your-app.example.com

PUBLIC_BASE_URL 不是 health check 用的,也不是 LINE 簽名驗證必要條件。它只用於產生個股 Flex 卡片裡的 K 線圖 URL;不填時系統仍可回覆 LINE 訊息,只是不顯示圖表。啟動 log 會提醒是否已設定,並在有設定時印出 Webhook 與 health URL。

LINE Developers 後台的 Webhook URL 請設定為:

https://your-domain-or-tunnel/callback

必要變數

  • Channel_Secret: LINE Messaging API Channel Secret
  • Channel_Access_Token: LINE Messaging API Channel Access Token
  • OPENAI_API_KEY: OpenAI API Key

常用選填

# 部署後取得 PaaS domain 再補上;用於個股卡片 K 線圖
PUBLIC_BASE_URL=https://your-app.example.com

# 多 worker 或多 instance 部署時,只能讓一個 instance 啟用排程
ENABLE_SCHEDULER=true

# 暫時關閉主動推播
ENABLE_PUSH=false

# AI 模型,預設 gpt-5.4-nano
MODEL=gpt-5.4-nano

# 若 PaaS 沒有自動注入 PORT,本機可自行指定
PORT=8000

其他進階參數包含資料保留天數、HTTP retry、backfill 批次、FinMind/MOPS 補強、AI tool calling 等,都已在 app/config.py 內建合理預設。進階使用者需要調整時,可直接新增對應 env 變數或修改 config。

啟動方式

1. 初始化資料庫

python scripts/init_db.py

2. 啟動服務

python scripts/run_server.py

啟動後可用以下端點確認服務是否正常:

curl http://127.0.0.1:${PORT:-8000}/health

3. 執行測試

./.venv/bin/python -m unittest discover -s tests -v

目前測試涵蓋資料 TTL 清理、FinMind 429 缺資料訊號保留、推薦卡渲染、MA60 歷史資料使用,以及詳細分析 context 合併最新價格與完整市場日基本面。

4. 執行使用者流程 QA

./.venv/bin/python scripts/qa_user_flows.py

此腳本不會發 LINE 訊息;它會本機模擬今日波段推薦、長投推薦與 1303 詳細分析 context,檢查推薦卡是否包含價格計畫、結構判讀、產業資訊,以及詳細分析是否包含 price_source_datemarket_fundamental_datecurrent_signalindustry_context

5. 執行 API / 按鈕流程 QA

./.venv/bin/python scripts/qa_api_flows.py

此腳本不會發 LINE 訊息;它會用 FastAPI TestClient 驗證 /health,並模擬 task=reco_todaywatchlist_viewdaily_summary 等 postback handler,檢查實際 Flex/Text payload 是否包含使用者會看到的日期、標籤、資料透明度與缺資料說明。

6. 執行回測

./.venv/bin/python scripts/backtest_recommendations.py

回測只使用已寫入的推薦快照與之後實際價格,不偷看未來資料。歷史資料不足時會顯示 insufficient forward prices,需等待背景補資料累積。

PaaS 部署說明

  • 專案程式會優先讀取 PORT,因此可直接部署到 Zeabur、Render、Railway、Fly.io 或其他 PaaS。
  • PORT 沒有提供,才會 fallback 到本機預設 8000
  • RELOAD 預設為 false,避免在 PaaS 或 VPS 上誤開開發模式。
  • 本機使用 ngrok 時,只需要把 ngrok 指到本機服務埠,例如 8000

AI Tool Calling

AI_TOOL_CALLING_ENABLED=true 時,只會在「問 AI」流程啟用工具呼叫。一般查詢、推薦、Rich Menu、推播不受影響。

目前工具皆為唯讀:

  • 解析對話中的股票或 ETF 標的
  • 查單檔或最多 3 檔股票快照
  • 查市場摘要
  • 查最新推薦清單
  • 查使用者我的最愛

設計限制:

  • 預設關閉,需手動設定 AI_TOOL_CALLING_ENABLED=true
  • 單回合最多 AI_TOOL_MAX_CALLS=2
  • 工具結果含 sourceas_ofmissing_data
  • 工具失敗會 fallback 到原本 deterministic context
  • 工具層有短期快取,降低 LINE 對話延遲與 OpenAI 反覆查詢成本
  • FinMind 現金流補強預設開啟,但只在單檔查詢或 AI 單檔分析時按需抓取
  • 若 FinMind 超過免費額度,系統會回傳 missing_data,AI 會明確說缺資料,個股卡片也會直接顯示「FinMind 限流中」(HTTP 429
  • 推薦卡只會對當次回傳的少量標的做按需補強;若補強當下遇到 429,長期推薦卡也會顯示限流提醒

Docker

建置映像

docker build -t twse-line-bot .

本機執行

docker run --rm \
  -p 8000:8000 \
  -e PORT=8000 \
  -e Channel_Secret=your_line_channel_secret \
  -e Channel_Access_Token=your_line_channel_access_token \
  -e OPENAI_API_KEY=your_openai_api_key \
  twse-line-bot

容器啟動時會先執行 scripts/init_db.py,再啟動 uvicorn。

LINE Webhook

請將 LINE Developers 後台的 Webhook URL 指向:

https://your-domain-or-tunnel/callback

本機開發若沒有公開網址,可搭配反向代理或 tunnel 工具。

排程

系統在 FastAPI 啟動時會自動啟用排程:

  • 03:45 資料清理與 retention cleanup
  • 08:00 每日 ETL
  • 08:30 每日評分
  • HISTORICAL_BACKFILL_INTERVAL_MINUTES 分鐘背景補少量歷史日資料,服務啟動後也會先跑一批

資料基準日規則

  • price_source_date: 單檔最新價格/技術資料日期,可能來自背景歷史補資料。
  • market_fundamental_date: 最新完整市場日,用於基本面與推薦快照基準。
  • recommendation.trading_date: 推薦快照基準日,必須是完整市場日。
  • price_source_date 晚於 recommendation.trading_date,詳細分析會標示舊快照並提供 current_signal 當下估算。
  • 14:30 盤後告警掃描與推播

排程時區為 Asia/Taipei

資料流程

每日 ETL

  1. 找最近交易日
  2. 抓取上市與上櫃收盤行情
  3. 補上市與上櫃估值資料
  4. 補月營收 YoY
  5. 補 EPS、毛利率、營業利益率、淨利率與財報期別
  6. 補 ROE、ROA、負債比、流動比、每股淨值
  7. 預設啟用 FinMind,單檔查詢 / AI 單檔分析時按需補營業、投資、籌資與自由現金流
  8. 補注意股、處置股、暫停交易事件旗標
  9. 寫入 stock_daily_features
  10. 計算 MA / RSI / MACD

MOPS 重大訊息補強

  • 單檔查詢與 AI 單檔分析會按需查詢近月 MOPS 重大訊息。
  • 結果只作為公告事件背景,不直接改推薦分數,也不呈現為保證預測。
  • 查詢結果有記憶體快取,避免同一標的在短時間內重複打公開資訊觀測站。
  • 若 MOPS 暫時不可用,LINE payload 與 AI context 會保留既有資料,並以缺資料訊號處理。

每日評分

  • 波段評分
    • 趨勢
    • 量價
    • 強度
    • 事件與風險扣分
  • 長期評分
    • 品質
    • 成長
    • 估值
    • 現金流品質
    • 風險扣分
  • 額外處理
    • 排除注意股、處置股、暫停交易等交易所風險事件
    • 同分 symbol hash tiebreaker
    • 產業分散,同產業最多優先保留 2 檔

支援指令

查詢與推薦

  • 查 2330
  • 查 台積電
  • 今日推薦
  • 推薦波段
  • 推薦長投
  • 推薦長期
  • 今日摘要

我的最愛與手動追蹤

  • 加入最愛 2330
  • 加入最愛 台積電
  • 移除最愛 2330
  • 我的最愛
  • 新增追蹤 2330
  • 買入 2330 980 1張
  • 賣出 2330 1020 1張
  • 手動追蹤

其他

  • 賣出警示
  • 比較 2330 和 2454

未命中固定指令時,會 fallback 到 AI 問答。

Zeabur

README 上方已放置 Zeabur badge,會導向 Zeabur 建立新專案頁面。
若你要做真正的「一鍵部署模板按鈕」,需要先在 Zeabur Dashboard 建立 template,再把 Zeabur 提供的按鈕碼貼回 README。

Zeabur 官方文件指出,deploy button 必須綁定 template,只有 template 作者能產生按鈕:

使用 zeabur.json

專案根目錄已提供 zeabur.json

  • 使用 Docker build
  • 宣告必要 env 變數
  • 預設 PORT=8000
  • 預設 RELOAD=false

若你用 GitHub 連 Zeabur,通常只要:

  1. 在 Zeabur 建立新專案
  2. 匯入此 repo
  3. 填入 Channel_SecretChannel_Access_TokenOPENAI_API_KEY
  4. 讓平台自動部署

Rich Menu

產生背景圖

python scripts/generate_rich_menu_image.py

輸出檔案:

assets/rich_menu/rich_menu_main.png

參考設定

python scripts/setup_rich_menu.py

此腳本會輸出 Rich Menu 區塊配置,可再接 LINE Messaging API 上傳。

正式部署到 LINE

python scripts/deploy_rich_menu.py

這支腳本會:

  1. 建立新的 Rich Menu
  2. 上傳 assets/rich_menu/rich_menu_main.png
  3. 設成預設 Rich Menu

資料表

主要資料表如下:

  • users
  • positions
  • transactions
  • alerts
  • recommendation_snapshots
  • stock_daily_features
  • push_logs
  • ai_sessions
  • watchlists

已知限制

  • 即時報價依賴 twstock 與 TWSE 即時資料來源,盤中偶爾可能回傳缺值。
  • 盤中推薦會顯示即時價格與更新時間,但本質上仍受 LINE 使用者端開啟聊天視窗、TWSE 即時資料延遲與網路狀況影響。
  • 財報資料以交易所 OpenAPI 最新揭露季別為準,並非即時財報預估值。
  • 注意股、處置股、暫停交易事件依交易所公告 API 更新;盤中仍可能有公告時間差。
  • AI tool calling 目前是實驗功能,只讀取現有 DB、twstock、TWSE/TPEx 資料,不會寫入使用者資料或執行交易。
  • README 內的 Zeabur badge 目前是通用入口;若要真正的一鍵部署模板按鈕,仍需你在 Zeabur 建立 template 後替換。

開發建議

  • 若要手動驗證資料流,建議先跑一次 scripts/init_db.py,再啟動服務觀察排程與 webhook log。
  • 若要測試盤中即時查詢,可直接從 LINE 傳 查 台積電查 2330
  • 若要關閉主動推播,可將 ENABLE_PUSH=false
  • 多 worker 或多 instance 部署時,請只保留一個 instance 設定 ENABLE_SCHEDULER=true,其餘設為 false,避免重複 ETL、backfill 或推播。

License

MIT

About

台股 LINE 助理,提供每日選股推薦、個股查詢、我的最愛、手動追蹤提醒、AI 問答功能。 專案使用 FastAPI + LINE Messaging API + SQLite,並整合 twstock、TWSE OpenAPI、TPEx OpenAPI,並可選擇用 FinMind 補強單檔現金流

Topics

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors