BUILD · M / W / F
量化實驗室系列 * 閃崩實驗室 2

一個值得反覆思考的觀點。
游泳池
2026 年 3 月 10 日,我做了一個糟糕透頂的決定:我開啟了生產環境。
公平地說,當時一點也不覺得糟糕,反而覺得壯麗極了。窗外,香港的天際線照舊帶著不知疲倦的能量嗡嗡作響;窗內,一臺 iMac 穩定地發著光,照亮了我幾乎憑空造出來的東西。十二天前,我手裡只有一個空白資料夾、荒廢了二十年的軟體直覺、一個老交易員對市場結構的本能,以及一個名叫 Codex 的 AI 程式設計代理。現在,完全出乎所有理性預期,我居然擁有了一間能執行的量化交易實驗室。
螢幕背後,是整整七年的比特幣逐筆歷史資料,經過細緻回放和壓力測試。最後一次研究執行裡有九十七筆模擬交易,由一套確定性策略串聯起來,累計收益高達七十九 R。沙盒像一座墓地:埋著失敗的假設,也留下倖存的引數、執行日誌、單元測試、標註圖表,以及名字越來越鄭重其事的檔案。這個系統被我親切地叫作 The Alligator(鱷魚)。它透過了我能想到的每一場統計考試、蒙特卡洛模擬和常識檢查。於是,我自然得出了一個結論:該讓它拿真錢去捕獵了。
這套邏輯,大概和那些在郊區游泳池裡造精密帆船的愛好者一模一樣。沙盒裡有水,船也浮起來了。還能出什麼問題呢?
生產版本看起來確實威風凜凜。它不再只是終端裡的一段指令碼,而是一個生態系統:排程器、後臺看門狗、基礎設施心跳、結構化日誌管道、交易所直連、本地持倉對賬,以及帶止損和止盈管理的自動風險引數,一應俱全。它甚至還有一套 Telegram 駕駛艙,配備 TOTP 保護的多因素認證,讓我能直接從手機遠端檢視、武裝,或者對這隻自主行動的加密捕食者按下 kill-switch。
我可以輸入 /status,問它還在不在呼吸;傳送 /kill,立即禁止新開倉;再發 /unkill,允許它重新潛伏在訂單簿裡。我對這個功能的喜愛明顯超出了合理比例。離開嚴肅軟體工程二十年後,我走在中環街頭,口袋裡揣著一隻演算法爬行動物的遙控器。年輕時學計算機的我一定會被迷得神魂顛倒;如今這個年紀、坐在管理層位置上的我,大概應該深感不安。
最初什麼戲劇性事件都沒有發生,而這恰恰成了最煎熬的部分。鱷魚本來就是個耐心的獵手。它不靠噪音交易,也不會每小時翻來覆去地刷合約。它等待非常精確的條件:系統性疲弱、槓桿過度擁擠、結構耗竭,以及毫不含糊的破位。它可以一動不動地趴上好幾天。
所以,我的實盤量化入門並沒有腎上腺素飆升的劇情,只有催眠般單調的系統日誌。
綠色。
綠色。
綠色。
還是綠色。
沒有訊號。沒有持倉。沒有劇情。我花了將近兩週造出一臺複雜機器,而它最突出的運營才能似乎是剋制地什麼都不做。這是數字自制力的勝利。
一家微型夜班公司
然後,現實不可避免地介入了。一個下午,輸入資料流裡一段至關重要的管道悄無聲息地停住了。未平倉量不再更新。策略高度依賴未平倉量;槓桿擁擠是必須同時滿足的條件之一。沒有新鮮的未平倉量,鱷魚仍然看得見價格和資金費率,卻等於失去了嗅覺。
主程序還在執行,訊號引擎仍然活躍,後臺排程器甚至報告一切健康。然而,支撐判斷的一個核心輸入已經悄悄凍結。生產環境第一次讓我認識一種陰險的軟體故障:沒有明顯崩潰,沒有丟擲異常,也沒有滿屏刺眼的紅色警報。機器只是變得沒那麼真實了。
我們鑽進管道深處,排查端點、快取層、資料新鮮度時間戳和底層網路延遲。一度,區域 VPN 成了頭號嫌疑人。iMac 在香港,執行伺服器從別處路由,一個 IP 地址悄悄變了,第三方資料提供商也開始用不同方式返回快取響應。我盯著網路追蹤圖直搖頭:我明明是來研究比特幣的宏觀市場級聯,為什麼下午卻在除錯國際網路拓撲?
鱷魚對我的存在主義困惑毫無興趣。它只想要新鮮的未平倉量。我們修好管道,恢復資料完整性,看著數字重新跳動起來。那隻動物又開始呼吸,而我也少天真了一點。
接著,執行排程器開始行為古怪。沙盒裡的研究指令碼很聽話:你觸發它,它按順序執行,然後乾乾淨淨地結束。生產軟體卻有複雜的社交生活。它按時鐘週期自己醒來,和陌生 API 交談,把持久狀態寫入本地資料庫,輪詢外部程序,處理動態重啟,還會留下一些微妙的數字痕跡。偶爾在凌晨三點,它會斷定旁邊的後臺程序已經死了,其實對方只是在喘口氣。
為了解決這個問題,我們引入了排程器;然後又造了看門狗來監視排程器;接著發現看門狗需要一套專門的心跳,才能分清排程器是真的死了,還是只是在安靜工作;最後我們又花了幾個小時調心跳閾值,因為一個過分熱心的看門狗,可能比它負責監視的程序危險得多。
到了某個時刻,我意識到自己無意間造出了一套微型數字官僚機構:排程器負責幹活,看門狗負責監督排程器,心跳負責證明排程器確實在幹活,Telegram 向高層彙報狀態,而所謂高層,就是半夜躺在床上盯著 iPhone 的我。它已經不太像高頻交易臺,更像一家只在深夜營業、員工全部是過度緊張微服務的小公司。
不過到此為止,我的本金一分錢都沒動。
5 月 18 日
直到 5 月 18 日。
那天下午,鱷魚終於聞到了氣味。一個真正的訊號出現了——不是 CSV 檔案裡的歷史回放,也不是沙盒試跑,而是波動劇烈的比特幣市場裡,一個真實的生產級機會。安靜監控了幾個星期後,多層條件終於完全對齊:市場狀態確認、結構脆弱性,以及價格觸發。大嘴張開了。
就是這一刻:第一次完全自主的開倉。
訂單立刻被拒絕。
我難以置信地盯著控制檯。鱷魚準備了兩個月的晚餐,宴席擺到面前,卻連叉子都塞不進嘴裡。系統實際上攔住了自己的交易。
我的第一反應是常見的技術摩擦:API 許可權不對、端點超時、合約格式錯誤,或者少了一個名字很神秘的交易所引數,比如 tdMode。Codex 和我立刻鑽進原始交易所日誌,逐行追蹤請求載荷。
然後,數學上的真相浮出了水面。策略的風險引擎被設定為每筆交易承擔固定金額的風險,大約 5,000 美元。紙面上這完全合理。但我在急著從研究轉向生產時忽略了一件事:風險預算 和 名義持倉規模 根本不是同一個東西。
當時的市場結構要求初始止損放得非常緊。止損越窄,要在被止損時恰好損失固定金額,底層持倉就必須越大。緊止損疊加固定美元風險,算出來的就是鉅額名義槓桿。
我看了看計算出的下單規模,又看了看交易所允許的最大槓桿,再回頭看那隻機器人。這個演算法認為,我區區 5,000 美元的風險預算,足以配上一家小型對沖基金的資產負債表。
幸運的是,有人事先想到了這種場景。不幸的是,對我當下的交易雄心而言,那個人正是我自己。幾個星期前,某種自保本能讓我在執行層寫死了一條絕不妥協的安全引數:系統嚴禁使用超過 交易所最大持倉上限的百分之七十。
訂單失敗,不是因為平臺壞了;它失敗,是因為安全治理器完全按照設計工作。過去的 Robin 跳出來,保護了現在的 Robin,不受現在這個 Robin 自己那套不受約束的量化策略傷害。這個發現很好笑,也很讓人洩氣。
我們把安全緩衝原封不動地保留下來。沒有情急之下強行繞過,沒有提高槓杆引數,也沒有倉促改配置。交易視窗過去,市場繼續向前,鱷魚依舊餓著。
一筆和自己意見不一致的持倉
幾天後,市場又給了一次機會。這一次,計算出的倉位舒舒服服地落在全部風險引數之內,訂單毫無阻力地進入訂單簿。我們第一次真正擁有了一筆活的實盤持倉:真實交易所、真實比特幣永續合約、真實本金、有效止損,以及明確的止盈目標。
我盯著螢幕,心裡一半是職業上的滿足,一半是深深的懷疑。機器終於跨過了理論模型與經濟現實之間的邊界。幾個月來,每一筆交易都活在歷史圖表和模擬成交構成的無菌、無摩擦世界裡。現在,一筆倉位真的待在野外,要接受現實世界的處置。
確認訂單引數已經穩定後,我去睡覺了。
第二天早上,我開啟儀表盤檢視持倉,立刻感到一陣發冷。不對勁。本地資料庫說的是一種狀態,交易所報告的卻是完全不同的狀態。很少有事情比發現自己的自主交易指令碼可能根本不知道自己目前持有什麼,更能讓人瞬間清醒。
我直接開啟 OKX 交易所頁面,調出機器人原始日誌,對照 Telegram 事件流,開始逐一核對時間戳。交易所裡的物理持倉的確存在,但本地記賬模組被一個意外的執行狀態徹底搞糊塗了。
我人工介入:關閉未平的交易腿,取消失去歸屬的保護訂單,再發出遠端 kill 指令,阻止任何新開倉。隨後,Codex 和我進入了漸漸變成晨間例行公事的環節:數字取證。機器人以為發生了什麼?交易所實際執行了什麼?狀態從什麼時候開始漂移?本地磁碟寫下了什麼?訂單簿裡又究竟成交了什麼?
策略在理論上有多優雅已經不重要了。唯一重要的問題是:兩個獨立的計算機系統,能否對“我此刻到底擁有什麼”保持絕對共識。
我們從頭重建狀態對賬模組,強制每筆交易之後都做同步狀態檢查。但生產環境還沒上完課。很快,它又暴露出一種更微妙的結構摩擦。
鱷魚可以在同一段趨勢裡產生多個邏輯開倉。在回測環境中,這些開倉被當作完全獨立的交易:交易 A 有自己的入場價和保護止損,交易 B 也有獨立邏輯、風險配置和退出觸發。策略回測器分別追蹤它們,交易日誌分別記錄它們;概念上,它們是不同的實體。
交易所的現實卻簡單得多。賬戶採用淨持倉模式。從交易所看來,同一個合約連續做兩筆空單,並不是什麼“兩件不同的哲學事件”,而只是一筆合併後的空頭持倉:總規模相加,入場價格取一個加權平均。
我們造了一套優雅的內部本體論。交易所只做基礎算術。
我記得自己盯著螢幕想:不,這明明是兩個完全不同的交易想法。
交易所 API 彷彿回答:真可愛。現在它們是一個了。
我們只好再次適應,重新設計執行架構,把多個策略層的邏輯持倉持續對映到交易所層的一筆合併持倉上。本地狀態可以儲存三個獨立的交易概念,交易所則只保留一個淨持倉,而兩種表述必須始終保持對賬一致。
日子一天天變成幾個星期,生產環境系統性地拆掉了我們在沙盒裡習以為常的每一條假設。止損單可能存在於本地記憶體,卻因為速率限制沒能登記到交易所;持倉可能已經成交,配套保護訂單卻還沒確認;一個有效訊號可能用了稍微延遲的資料點;看門狗可能把短暫的網路沉默誤判為系統死亡;交易所也可能拒絕一個數學上完全正確的訂單,只因為合約張數、保證金模式或步長取整規則根本不在乎回測有多漂亮。
現實一層層擠進系統。它並沒有帶來更復雜的數學引數,而是要求更嚴格的運營紀律。我們加入 API 預檢、明確的訂單回讀、失敗即關閉的安全流程、防禦性錯誤處理、更細的健康狀態,以及不可變事件賬本。軟體在紙面上沒那麼優雅了,在實踐中卻堅韌得多。我不再追逐刺激的新功能,反而開始從安靜、無聊的狀態日誌裡獲得巨大安慰。綠色成了世界上最好看的顏色。
T008 在咬桌子
然而,系統在機械層面越來越可靠時,另一個領悟開始浮現。它和軟體無關,而和交易本身有關。
鱷魚會發起一場戰役。第一筆通常很漂亮,正好抓住破位的拐點。可價格繼續下跌時,後續訊號也會一個接一個觸發,不斷往倉位上疊。回測認可這種做法:歷史上,次級入場的期望值仍為正。數學上,它說得通。
可是親眼看著它在實盤裡發生,視覺和直覺都越來越覺得魯莽。
有一場行情把問題暴露得格外清楚。第一筆空單抓住了一段巨大、乾淨的向下擴張,是教科書式的交易。第二筆在更低處進場,第三個訊號又在更低處觸發。等第四筆空單幾乎在行情最底部提交時,它看起來已經不像經過計算的統計優勢,更像一個忘記了“系統性捕獵”和“盲目追價”根本不同的演算法。
我調出執行圖,盯著那一簇標記:T005、T006、T007 和 T008。
我拿起便箋,寫了四行:
T005 是咬下去。
T006 是咀嚼。
T007 是追著吃碎屑。
T008 是在咬桌子。
這句話好笑到讓人過目不忘,但背後的教訓很嚴肅。第一筆入場抓住了真正的市場結構變化;最後一筆只是對已經耗盡的動量作出反應。演算法把每個有效觸發都當成彼此獨立的機會,而我的眼睛看到的卻是同一場延伸過度的戰役:主要擴張早已完成,只剩一隻怎麼也不肯離開餐桌的動物。
開放海域
到了暮春,鱷魚已經徹底變了樣。它最初只是一個乾淨研究資料夾裡的一組優雅方程,如今卻帶著實盤部署留下的一身傷痕。
資料管道曾經變舊;區域 VPN 迫使我們研究地理位置;排程器需要看門狗,看門狗又需要心跳;我的手機多了一個遠端 kill-switch;交易所拒絕過第一筆訂單;百分之七十安全規則悄悄把我們從自己的槓桿數學裡救了出來;一筆真實持倉暴露了狀態同步缺陷;而交易所把我們精細的交易想法壓扁成了簡單的淨持倉算術。
七年回測沒有為這些事情中的任何一件做好準備,因為回測安穩地活在過去。生產環境則完全活在現在,每一個決定都會立刻產生後果。
深夜,又一張比特幣圖表在黑暗裡發光。系統在後臺安靜執行,提交心跳、輪詢 API,等待下一次結構變化。鱷魚終於離開游泳池,進入了開放海域。也是從專案開始以來第一次,我意識到最重要的工程挑戰,已經不再是教機器什麼時候咬下去。
真正的挑戰,是教會它什麼時候停止進食。