前面十七篇的策略共用一套基礎設施。這篇把它組裝成一個藍圖,然後列出十二個會讓它壞掉的方式——後半部比前半部重要。
五層架構
┌─────────────────────────────────────────────────────┐
│ ⑤ 風控/監控層 │
│ 曝險上限 · 斷路器 · 對帳 · 校準紀錄 · 警報 │
└────────────┬────────────────────────────────────────┘
│ 否決權(可停止下面任何一層)
┌────────────┴────────────────────────────────────────┐
│ ④ 執行層 │
│ maker/taker 決策 · tick/最小量對齊 · 令牌桶排程 │
│ 部分成交處理 · dead-man switch · 樂觀部位帳本 │
└────────────┬────────────────────────────────────────┘
│ 目標部位
┌────────────┴────────────────────────────────────────┐
│ ③ 決策層 │
│ 門檻檢查 |q−p| > φp(1−p) · Kelly · LP 求解 │
│ 多市場配置 · 資本效率排序 · 無交易區間 │
└────────────┬────────────────────────────────────────┘
│ q ± τ,或「棄權」
┌────────────┴────────────────────────────────────────┐
│ ② 估計層 │
│ 盲估 · LR 合併 · 向市價收縮 · 混淆矩陣修正 │
│ 模糊度分數 · 陪審團 · 對抗性驗證 · 棄權判定 │
└────────────┬────────────────────────────────────────┘
│ 結構化事實與似然比
┌────────────┴────────────────────────────────────────┐
│ ① 資料層 │
│ 市場元資料 · 條款編譯 · 訂單簿 WS · 鏈上 OO 事件 │
│ 權威來源輪詢 · 賠率 · 新聞 · 歷史結算資料庫 │
└─────────────────────────────────────────────────────┘
層與層之間的介面規則
這五層之間的介面比層本身重要。 三條硬規則:
- ①→② 傳結構化事實,不傳原始文字。 估計層不應該直接讀網頁。
- ②→③ 傳
(q, τ, 棄權旗標),不傳部位。 見 LLM 產生中間產物、程式產生決策。 - ⑤ 對所有層有否決權,且否決是同步的——不能是「發個警報然後繼續交易」。
① 資料層
| 元件 | 來源 | 更新頻率 | 注意事項 |
|---|---|---|---|
| 市場元資料 | Gamma API | 增量,快取 | /markets 300/10s 是最緊的限制 |
| 條款編譯結果 | LLM,離線 | 市場上架時一次 + 版本追蹤 | 三個策略共用(抽取層) |
| 訂單簿 | CLOB WebSocket | 即時 | 靜默斷線是最大風險 |
| 鏈上預言機事件 | Polygon 日誌訂閱 | 即時 | ProposePrice / DisputePrice |
| 權威來源 | 條款推導的輪詢器 | 發布節奏模型 | 條件請求 + 版面雜湊 |
| 賠率 | 多家 API | 秒級 | 跨市場一致性檢查 |
| 歷史結算資料庫 | 自建 | 每日 | 這是所有校準與驗證的基礎 |
最後一項最容易被跳過,也最不該跳過。 沒有歷史結算資料庫,你無法做 收縮權重回歸、無法建 混淆矩陣、無法做參考類別檢索。它應該是第一個建的東西,不是最後一個。
② 估計層
輸出的規格:
{
market_id, timestamp,
q_model, tau, // 盲估的點估計與不確定度
evidence: [ {source, LR, confidence}, ... ],
ambiguity_score, // 陪審團分歧率
alpha_hat, beta_hat, // 該分層的混淆矩陣
q_final, // 混淆矩陣修正 + 向市價收縮後
abstain: bool, reason
}
abstain 是輸出,不是例外。 決策層必須把它當成正常路徑。
③ 決策層
順序固定,且每一步都可能終止:
1. abstain? → 停
2. |q − p| > φ·p(1−p)? → 否則停
3. Kelly 部位 = f(q, p, φ) × 分數係數
4. 曝險上限截斷(市場 / 叢集 / 結算來源 / 總量)
5. 流動性截斷(買到邊際 edge 歸零為止)
6. 與現有部位比較 → 落在無交易區間內則停
7. 輸出目標部位
步驟 4 在步驟 3 之後、5 之前,順序有意義:先用風險預算截斷數學結果,再用市場現實截斷。
④ 執行層
- maker/taker 決策:用 決策式,需要即時估計的
ρ(成交率)與A(逆選擇成本)。 - tick / 最小量對齊:對齊到市場的 tick size 與 5 股倍數。tick size 被拒是正常路徑,要重查重送。
- 令牌桶排程:本地模擬伺服器端的令牌桶(見 分層表),按 edge 大小排優先權。1.5 秒的爆發預算要留給最重要的市場。
- 樂觀部位帳本:下單即扣、失敗即回沖,定期與鏈上對帳。不要每次決策都查鏈。
⑤ 風控/監控層
斷路器清單(任一觸發即停止新部位):
| 斷路器 | 閾值範例 |
|---|---|
| 當日已實現+未實現虧損 | 總資金 3% |
| 單一驅動因子曝險 | 總資金 8% |
| 單一結算來源/提案者曝險 | 總資金 15% |
| 總未結算曝險 | 總資金 50% |
| 被凍結(爭議中)資金 | 總資金 15% |
| WebSocket 資料新鮮度 | > 5 秒無更新 |
| 對帳差異 | 任何不符即停 |
| 估計層棄權率異常 | 突然大幅上升或下降 |
最後一項是被低估的訊號:棄權率突變通常代表上游資料壞了(例如條款抽取器因為 API 格式改變而全部失敗),而它會比損益更早顯示問題。
十二個失效模式
按「會不會讓你虧錢」而非「會不會報錯」排序。前六個不會報錯。
1. WebSocket 靜默斷線
症狀:連線看似正常,但沒有訊息。系統用陳舊價格繼續掛單,市場已經跑掉。 為什麼致命:這是做市系統最典型的死法,且不會拋出例外。 處理:heartbeat(伺服器端 ping 或自發的訂閱測試)+ 資料新鮮度斷路器 + dead-man switch:本地維護一個計時器,超過閾值未收到資料就自動撤銷所有掛單。
dead-man switch 必須是本地的,不能依賴「請伺服器幫我撤單」——因為連線壞了正是問題所在。
2. 靜默的解析失敗
症狀:權威來源的 HTML 改版,解析器回傳 null,系統當成「沒有新資料」。
為什麼致命:你會錯過事件而完全不知道。
處理:版面雜湊 + 心跳測試——定期用已知的歷史值驗證解析器仍然正確,失敗就停用該市場的自動交易並發警報。null 與「確認沒有變化」必須是兩個不同的回傳值。
3. LLM 幻覺出的邏輯邊或條款漏洞
症狀:LP 求解器報告「無風險套利」,但那條蘊含關係是編出來的。 處理:陪審團一致率門檻 + 對抗性驗證 + 機率鬆弛(見 LP 那篇)。分層:合約強制的邏輯做純套利,LLM 推斷的邏輯只做 Kelly 配置。
4. 錨定洩漏
症狀:某次提示模板改動,讓市價資訊洩漏進盲估階段。你的 q 開始貼著 p,看起來「模型變準了」。
為什麼致命:它偽裝成改善。
處理:假市價注入測試自動化——定期用擾動過的價格跑一批市場,檢查 q_model 是否隨之移動。這個測試要放進 CI,不是手動跑。
5. 樣本外的樣本內
症狀:策略參數在同一批資料上調過,然後在同一批資料上驗證。 處理:時間切分 + 預先登記 + 多重比較的明確計數。記錄你試過幾個策略變體,並據此調整顯著性門檻。
6. 相關性被低估
症狀:20 個部位「分散」,但它們是同一個總體判斷。 處理:標籤化曝險上限(叢集 / 驅動因子 / 結算來源),而非估計相關性矩陣。
7. tick size 快取失效
症狀:訂單被拒。py-clob-client 有已知的本地快取問題(issue 122)。
處理:把拒絕當正常路徑——重查 tick size、重算、重送。不要重試同一筆訂單。
8. V1/V2 簽章遷移
症狀:2026-04-28 之後,V1 SDK 與 V1 簽章的訂單在生產環境完全失效。 處理:確認使用 v2 客戶端。這也是一個一般性教訓:把「交易所升級」列進系統的預期事件,而不是意外。 訂閱官方公告,並在啟動時檢查 API 版本。
9. 部分成交的殘餘部位
症狀:小於 5 股的殘餘無法透過 CLOB 平掉。 處理:訂單量對齊 5 的倍數;殘餘部位獨立記帳;不要試圖平掉零頭,湊到可交易規模或持有到結算。
10. 速率限制導致的單邊成交
症狀:多腿套利時,速率限制讓部分腿沒送出,你持有裸部位。 為什麼致命:這是**「風控機制本身造成風險」的典型案例。 處理:多腿交易前預留足夠的令牌預算**;按最不流動的腿優先;設「未對沖曝險」上限,超過就停止新的套利嘗試。
11. 爭議凍結的連鎖反應
症狀:一次爭議凍結大量資金,導致其他策略無法執行,錯過機會。 處理:把「可凍結資金」當成獨立的預算科目,並在配置時就保留。這不是事後應對,是事前的資本規劃。
12. 結算延遲導致的帳本失真
症狀:CLOB 撮合成功但鏈上結算未完成,系統以為部位還在/已經在。 處理:樂觀部位帳本 + 定期對帳 + 對帳差異即斷路。
上線順序
失效模式的清單很長,所以上線應該分階段,每階段有明確的通過條件:
| 階段 | 內容 | 通過條件 |
|---|---|---|
| 0 | 只讀:資料層 + 估計層 + 預先登記 | 累積 400 筆已結算預測,BSS > 0 且 b 顯著 |
| 1 | 影子交易:完整決策,不真的下單 | 模擬損益為正;所有斷路器至少觸發過一次(用注入測試) |
| 2 | 極小額實盤,單一策略,單一類別(建議氣象或體育) | 執行層無失效;ρ、A 估計穩定 |
| 3 | 擴大到多策略 | 相關性標籤系統驗證有效 |
| 4 | 提高部位 | 每次提高後重新觀察至少 100 筆 |
階段 0 是最重要也最容易被跳過的一階段。 它不需要任何執行層程式碼,卻能回答「這整件事有沒有 edge」這個唯一重要的問題。在階段 0 沒通過就寫執行層,是把工程投入押在一個未驗證的假設上。
一個設計哲學
回看整個藍圖,它的組織原則不是「效能」也不是「彈性」,是可歸因性:
當損益不如預期時,你要能在一小時內指出是哪一層、哪一個元件出的問題。
這解釋了為什麼:
- 估計層輸出
LR而非q(可以對每個訊號源獨立算校準) - LLM 輸出中間產物而非決策(可以檢驗中間產物的對錯)
- 預先登記包含未交易的樣本(避免選擇偏誤)
- 棄權是顯式輸出(可以量測棄權率的變化)
在一個需要數百筆樣本才能證明 edge 的領域(見 樣本量),改進速度取決於歸因速度,而不是取決於初始設計有多聰明。
這篇的重點
- 五層架構,介面規則比層本身重要;風控層有同步否決權。
- 歷史結算資料庫應該第一個建,它是所有校準與驗證的基礎。
abstain是正常輸出,不是例外。- 決策層順序固定:棄權 → 門檻 → Kelly → 風險截斷 → 流動性截斷 → 無交易區間。
- 前六個失效模式都不會報錯,這是它們危險的原因。
- dead-man switch 必須是本地的。
- 假市價注入測試要進 CI,錨定洩漏會偽裝成改善。
- 階段 0(只讀 + 預先登記)不需要執行層程式碼,卻回答唯一重要的問題。
- 整個架構的組織原則是可歸因性,因為改進速度取決於歸因速度。
下一步:風控與現實限制。