台股 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 上傳腳本
- 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.comPUBLIC_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 SecretChannel_Access_Token: LINE Messaging API Channel Access TokenOPENAI_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。
python scripts/init_db.pypython scripts/run_server.py啟動後可用以下端點確認服務是否正常:
curl http://127.0.0.1:${PORT:-8000}/health./.venv/bin/python -m unittest discover -s tests -v目前測試涵蓋資料 TTL 清理、FinMind 429 缺資料訊號保留、推薦卡渲染、MA60 歷史資料使用,以及詳細分析 context 合併最新價格與完整市場日基本面。
./.venv/bin/python scripts/qa_user_flows.py此腳本不會發 LINE 訊息;它會本機模擬今日波段推薦、長投推薦與 1303 詳細分析 context,檢查推薦卡是否包含價格計畫、結構判讀、產業資訊,以及詳細分析是否包含 price_source_date、market_fundamental_date、current_signal、industry_context。
./.venv/bin/python scripts/qa_api_flows.py此腳本不會發 LINE 訊息;它會用 FastAPI TestClient 驗證 /health,並模擬 task=reco_today、watchlist_view、daily_summary 等 postback handler,檢查實際 Flex/Text payload 是否包含使用者會看到的日期、標籤、資料透明度與缺資料說明。
./.venv/bin/python scripts/backtest_recommendations.py回測只使用已寫入的推薦快照與之後實際價格,不偷看未來資料。歷史資料不足時會顯示 insufficient forward prices,需等待背景補資料累積。
- 專案程式會優先讀取
PORT,因此可直接部署到 Zeabur、Render、Railway、Fly.io 或其他 PaaS。 - 若
PORT沒有提供,才會 fallback 到本機預設8000。 RELOAD預設為false,避免在 PaaS 或 VPS 上誤開開發模式。- 本機使用 ngrok 時,只需要把 ngrok 指到本機服務埠,例如
8000。
AI_TOOL_CALLING_ENABLED=true 時,只會在「問 AI」流程啟用工具呼叫。一般查詢、推薦、Rich Menu、推播不受影響。
目前工具皆為唯讀:
- 解析對話中的股票或 ETF 標的
- 查單檔或最多 3 檔股票快照
- 查市場摘要
- 查最新推薦清單
- 查使用者我的最愛
設計限制:
- 預設關閉,需手動設定
AI_TOOL_CALLING_ENABLED=true - 單回合最多
AI_TOOL_MAX_CALLS=2 - 工具結果含
source、as_of、missing_data - 工具失敗會 fallback 到原本 deterministic context
- 工具層有短期快取,降低 LINE 對話延遲與 OpenAI 反覆查詢成本
- FinMind 現金流補強預設開啟,但只在單檔查詢或 AI 單檔分析時按需抓取
- 若 FinMind 超過免費額度,系統會回傳
missing_data,AI 會明確說缺資料,個股卡片也會直接顯示「FinMind 限流中」(HTTP429) - 推薦卡只會對當次回傳的少量標的做按需補強;若補強當下遇到
429,長期推薦卡也會顯示限流提醒
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 Developers 後台的 Webhook URL 指向:
https://your-domain-or-tunnel/callback
本機開發若沒有公開網址,可搭配反向代理或 tunnel 工具。
系統在 FastAPI 啟動時會自動啟用排程:
03:45資料清理與 retention cleanup08:00每日 ETL08: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。
- 找最近交易日
- 抓取上市與上櫃收盤行情
- 補上市與上櫃估值資料
- 補月營收 YoY
- 補 EPS、毛利率、營業利益率、淨利率與財報期別
- 補 ROE、ROA、負債比、流動比、每股淨值
- 預設啟用 FinMind,單檔查詢 / AI 單檔分析時按需補營業、投資、籌資與自由現金流
- 補注意股、處置股、暫停交易事件旗標
- 寫入
stock_daily_features - 計算 MA / RSI / MACD
- 單檔查詢與 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 問答。
README 上方已放置 Zeabur badge,會導向 Zeabur 建立新專案頁面。
若你要做真正的「一鍵部署模板按鈕」,需要先在 Zeabur Dashboard 建立 template,再把 Zeabur 提供的按鈕碼貼回 README。
Zeabur 官方文件指出,deploy button 必須綁定 template,只有 template 作者能產生按鈕:
- Zeabur Deploy Button 文件: https://zeabur.com/docs/en-US/deploy/methods/deploy-button
- Zeabur Python / PORT 行為: https://zeabur.com/docs/en-US/guides/python/flask
專案根目錄已提供 zeabur.json:
- 使用 Docker build
- 宣告必要 env 變數
- 預設
PORT=8000 - 預設
RELOAD=false
若你用 GitHub 連 Zeabur,通常只要:
- 在 Zeabur 建立新專案
- 匯入此 repo
- 填入
Channel_Secret、Channel_Access_Token、OPENAI_API_KEY - 讓平台自動部署
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 上傳。
python scripts/deploy_rich_menu.py這支腳本會:
- 建立新的 Rich Menu
- 上傳
assets/rich_menu/rich_menu_main.png - 設成預設 Rich Menu
主要資料表如下:
userspositionstransactionsalertsrecommendation_snapshotsstock_daily_featurespush_logsai_sessionswatchlists
- 即時報價依賴
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 或推播。
MIT