Case Study · 跨領域作品 · 金融資料系統
智盤 TRADESIGHT
台股籌碼分析工具 —— 分點與法人動向、選股掃描、個股健檢與回測。桌面版已發布,只看盤、不下單。
這個專案有兩個決定是「主動放棄能力」換來的:做出了爬蟲卻拒絕用它,以及接了券商 API 卻從不建立下單元件。兩者都不是缺功能,是結構性選擇。
痛點
台股的籌碼資料(分點進出、三大法人、融資券、集保分散)是散戶最想看、卻最難乾淨取得的一類資料。市面工具多半把「抓到資料」當成終點,但如果要用它做選股與回測,真正的問題不是抓不抓得到,而是:這個數字是什麼時候、從哪裡抓的?後來被來源修訂過嗎?兩個來源對不起來時,你怎麼知道哪個是對的?
沒有這些欄位,任何回測結果都無法被信任 —— 因為你無法重現它。
關鍵決策一 —— 我做出了爬蟲,然後拒絕用它
專案第一階段(spike)我先驗證資料可行性:證明分點日報、三大法人、融資券、集保分散、月營收全部都能取得並解析。技術上是成功的。
然後我把整個 spike 封存,標記為「僅供參考、勿商用」,並寫下三個理由:
- ① 取得手段站不住腳
要拿到那些資料,我的 spike 得用 OCR 破解交易所的圖形驗證碼,另一側則是 reCAPTCHA。這既不穩定(對方一改版就壞),也有服務條款疑慮。一個要長期運作的系統,不能把地基放在這種手段上。
- ② 缺溯源欄位,做不出金融級對帳
爬下來的資料沒有「來源、抓取時間、checksum、修訂版本」。缺了這些,我無法回答「這個數字後來被改過嗎」,也無法在兩個來源衝突時判斷誰對 —— 也就是無法對帳,回測結果因此不可重現。
- ③ 價格用浮點數存,對金融場景是錯的
spike 把價格存成
REAL(浮點)。金融計算累積誤差不可接受,必須用精確數值型別。這條後來被寫成專案的鐵律之一:禁止用浮點存金額與股數。
正式版改走政府開放資料與使用者自己的券商帳號,並把 38 個資料源全部抽象成 provider 介面、每一筆都帶溯源欄位。代價是能拿到的欄位變少、開發變慢;換到的是一條可長期運作、可稽核、可重現的資料管線。
Trade-off
- 資料廣度縮減:部分只有透過爬取才拿得到的細粒度欄位,正式版就是沒有。這是為了合法性與可對帳而付的價。
- 開發速度變慢:接授權來源、寫欄位契約、補溯源欄位,遠比寫一個爬蟲慢。
- 公開網站版因此還沒部署:授權閘已就緒,但要確保公開版只用得到政府開放資料,這件事本身就是工作量。
關鍵決策二 —— 只看盤、不下單,而且是結構上做不到
接上券商 API 之後,最自然的下一步是加下單功能。我沒有做,而且刻意讓它在結構上做不到:
- 只建立三個唯讀元件
券商 API 只初始化登入、報價、回報三個唯讀元件;下單元件從不建立。不是靠介面上把按鈕藏起來,是那個能力根本沒被載進程式。
- CI 守門測試把它釘死
這件事有自動化驗收測試看守 —— 如果哪天有人(包括未來的我)加回下單元件,測試會直接失敗。把「我保證不做」變成「做了就會被擋下來」,這兩者的可信度差距很大。
- 為什麼值得這樣做
一個能下單的工具,對使用者的風險等級完全不同 —— 一個 bug 從「看到錯的數字」變成「送出錯的委託」。既然這個工具的價值在資料整理與確定性計算,那就把攻擊面與責任面一起關掉。
系統架構 —— 三個介面,一套後端
桌面 EXE、平板 PWA、公開網站(尚未部署)共用同一套 Python 後端;確定性計算與資料源分層,依賴方向單向往下。
- 1 · 桌面版 —— Tauri v2 殼 + Python sidecar
Tauri v2 外殼包一個 PyInstaller 打包的 Python 後端(onedir)。後端只綁
127.0.0.1,不對外開埠。前端是原生 JS(無框架)內嵌在殼裡。 - 2 · 平板 —— 區網 HTTPS + 連線碼
另起一個 TLS 終止代理綁指定網卡轉發到本機後端,把平板變成家中的看盤副螢幕。需8 碼連線碼(約 2³⁹·⁶ 熵、錯碼限速、恆定時間比對),閒置自動關閉,並有 DNS-rebinding 與 CSRF 防護;憑證與私鑰等 PC 端操作對平板一律 403。
- 3 · API 邊界 —— 契約驗證 fail-closed
FastAPI 提供 97 個端點,負責路由、契約驗證、快取與區網守門。回應邊界以
contracts/api_v1的 JSON Schema 驗證,驗不過就擋掉而不是照送。 - 4 · 確定性計算層
src/metrics(指標、籌碼、配息填息、回測)、src/screening(選股掃描)、src/health(個股健檢)、src/quality(資料品質檢查)。src/api/assemble.py只做純組裝,不做金融計算 —— 計算與組裝的界線刻意畫開。 - 5 · Provider 層 —— 38 個資料源,全帶溯源
政府開放資料、集保、第三方資料服務、使用者自有券商即時報價,全部實作同一 provider 介面,每筆資料都帶來源與抓取資訊。欄位契約寫在
docs/DATA_CONTRACTS.md。
授權閘 —— 用不到的資料就誠實說用不到
38 個資料源的授權條件不一樣:有的是政府開放資料可自由使用,有的受服務條款限制、或需要使用者自己的 token 與券商憑證。把它們混在一起用,公開部署就會踩線。
所以資料源依授權分層,由 DATA_MODE 環境變數把關 —— 而且是啟動時決定,沒有任何端點可以在執行期改它;無效值一律 fail-closed 鎖成最保守的公開模式。
| 來源類型 | 授權條件 | 公開版可用 |
|---|---|---|
| 政府開放資料(交易所 openapi) | 政府資料開放授權條款 | ✅ |
| 受 ToS 限制 / 需自備 token 的來源 | 條款限制 | ❌ 僅個人模式 |
| 券商即時報價(tick / 五檔) | 使用者自己的帳號 + 憑證 | ❌ 僅桌面個人版 |
最後一條原則我認為最重要:未授權的資料一律誠實顯示為「不可用」,不以 0 或推估值冒充。在金融工具裡,一個看起來像數字的空值比一個明確的「沒有」危險得多。
安全設計
- 憑據不落 HTTP
券商帳密走本機視窗輸入,不經網路、不進日誌、預設不儲存。選用性的第三方 token 以 Windows DPAPI(使用者範圍)加密落地 —— 換機或換帳號一律解不開。
- 更新通道必須驗簽
桌面版內建自動更新,走 HTTPS 並釘死 Ed25519 公鑰,安裝前必驗簽(minisign)。自動更新是最好的供應鏈攻擊入口,所以它反而需要最嚴格的驗證。
- 全回應防護標頭
X-Frame-Options: DENY、nosniff、frame-ancestors 'none'、no-referrer套在所有回應上,而不是只有頁面。
工程紀律 —— 三條不可協商的鐵律
這個 repo 由多個 AI 模型協作開發。要讓這件事在金融場景下安全,規則必須寫死、而不是靠自律:
- 作者不得自行核准合併,最終合併由 repo owner 執行 —— 人類 code review 最重要的那條規則,搬到與 AI 協作的流程上。
- 金融關鍵路徑須由非作者一方獨立重算驗證 —— 不是「再看一遍程式碼」,是另一方自己算一次看數字對不對。
- 不得用 LLM 當計算引擎;禁止用浮點存金額與股數;不得
verify=False—— 三個最容易為了方便而妥協的地方,直接列為禁止事項。
第三條的前半段是我在醫療系統學到的同一件事:語言模型不該出現在需要正確答案的路徑上。ClinCalc 的臨床判讀全部由確定性規則完成、LLM 只負責轉述;這裡更進一步,直接把「不得用 LLM 當計算引擎」寫成不可協商的專案規則。
測試與可驗證性
- 1,787 項自動化測試全綠,而且不只是功能測試 —— 包含安全與契約守門測試(例如前面提到的「下單元件不得存在」)。
- 回應邊界 fail-closed:所有 API 回應都要通過
contracts/api_v1的 JSON Schema;驗不過就擋,不會把格式錯誤的資料照送給前端。 - 架構決策紀錄(ADR):記錄「為什麼這樣選」而不只是「選了什麼」。封存爬蟲、不做下單這些決定之所以能講清楚,就是因為當時把理由寫下來了。
- 發布流程有明確踩雷紀錄:例如「動過前端就必須從打包步驟重跑,否則平板會拿到舊前端、而桌面端測不出來」—— 這種只有真的踩過才知道的事,寫進文件才不會再犯。
技術棧
反思 / 未來方向
- 「拒絕能用的東西」需要多少證據才算合理?封存 spike 是我憑三個理由做的判斷,但我沒有量化「用爬蟲會造成多少對帳失敗」。若能量出來,這個決策就從直覺變成證據。
- 授權閘的正確性能不能被證明?目前靠
DATA_MODE啟動時鎖定 + fail-closed + 測試守門。但「公開模式下絕不可能取用受限來源」這件事,現在是用測試涵蓋,而非形式化保證 —— 這與我在醫療系統遇到的「42 條資料庫權限規則無法證明完備」是同一類問題。 - 跨來源對帳的自動化程度 —— 偵測到不一致會標記,但仲裁仍需人看。能否用來源可靠度的歷史紀錄做加權自動仲裁?
- 與醫療系統的共通性 —— 「確定性計算優先、LLM 不進關鍵路徑、輸出必留可追溯資訊、寧可顯示不可用也不推估」這幾條,和我在 ClinCalc / ExClinCalc 的設計是同一套原則。兩個高風險領域獨立收斂到同一組取捨,這個現象本身值得研究。
延伸閱讀
- 公開發布版本紀錄 —— 可驗證版本歷史與安全性更新(主 repo 為私有)
- ClinCalc Case Study —— 同一套「規則優於 LLM」用在臨床判讀
- Kaizei Case Study —— 另一個金融領域作品(零知識加密)
- 先規則後 LLM 的三層架構 —— 這個設計主張的完整說明