2026年九月21日 · 工程

在回測中途重新啟動策略,它還記得自己持有哪些部位嗎?

在回測中途重新啟動策略,它還記得自己持有哪些部位嗎?

一項實用的回測測試,和尋找更好的參數毫無關係:在程序執行到一半時將它停止,復原後繼續完成同一段重播。在輸入完全相同、執行模擬器受控的情況下,策略決策、委託和權益都應與不中斷的執行結果一致。

如果結果不一致,就表示你找到了狀態管理問題。策略依賴某些沒有儲存、也無法重建的資訊。只要研究工作會恢復執行、工作程序會被替換,或模擬交易服務會部署新程式碼,這項依賴就很重要。

我喜歡這項測試,因為預期答案格外明確。市場有沒有變化,無須爭論。兩次執行接收到的是同一個市場。

以下是 3 種錯誤的重新啟動方式。數字僅供說明;即使系統其他部分都具有確定性,這些問題仍可能發生。

1. 重新載入少數幾根 K 棒,就認定指標已完成暖機

假設策略使用 100 期指數移動平均線。它的更新公式如下:

alpha = 2 / 101
ema_next = alpha * close + (1 - alpha) * ema_previous

不中斷的程序會延續累積中的 EMA。重新啟動的程序則擷取 100 根 K 棒,以第一根收盤價作為 EMA 初始值,並認為 100 期指標需要 100 筆觀測資料。

這個假設把指標的平滑參數和有限記憶視窗混為一談。EMA 會保留初始狀態逐漸衰減的影響。如果兩個版本一開始的 EMA 相差 10 個價格單位,後續價格完全相同,這個差距會如下縮小:

初始化後的更新次數剩餘差距占初始誤差的比例
1001.35313.53%
2500.06740.674%
5000.0004540.00454%

計算方式是 10 * (99 / 101)^k。若第一筆觀測資料用來設定初始值,擷取 100 根 K 棒只會得到 99 次更新。

問題通常會在決策邊界附近顯現。一個版本判定價格高於 EMA,另一個版本卻判定價格低於 EMA。微小的數值差異就會多出一筆交易。一旦如此,冷卻時間、可用資金和後續決策也可能跟著分歧。

請儲存遞迴指標狀態、初始化狀態,以及最後處理的事件。另一個做法是從已知的起始狀態重新重播。延長暖機時間或許能得到可接受的近似值,但應根據明確的誤差容許值來選擇暖機長度,並確認該誤差是否可能改變決策。「週期的 5 倍」只是慣例,並非證明。

而且,歷史資料不只影響指標。移動百分位數需要保留視窗資料。線上模型可能需要最佳化器狀態。虧損後等待 3 根 K 棒的規則,則必須記住虧損事件和計數器。

2. 儲存持倉,卻忘了尚在處理中的委託

目標持倉是 10 單位。一筆買進 10 單位的委託已成交 4 單位,還有 6 單位未成交。你將持倉數量 4 存入檢查點,重新啟動後又針對缺少的 6 單位送出另一筆買進委託。

如果原委託的剩餘數量和替代委託都成交,你最後會持有 16 單位。

這類錯誤在回測中常常不易察覺,因為填單引擎重新啟動時,可能會悄悄清除尚未完成的委託。在模擬交易中,模擬器或外部服務則可能保留委託。如此一來,同一套復原程式碼會因為不同元件是否存活,而產生不同曝險。

重新啟動時實際狀態只根據持倉復原時看到的狀態
目標持倉1010
已成交持倉44
未成交買進數量60
還需要買進的數量06

問題可能表現為復原後立即出現一波無法解釋的委託。有時曝險會加倍,有時則會平掉某個仍有保護委託在場的持倉,導致該委託之後可能又開出新的持倉。

檢查點除了持倉,也必須包含委託識別資訊和生命週期狀態。產生新動作前,復原程序必須先向執行系統核對這些紀錄。結果不明的委託需要調查;把「沒有儲存確認回覆」當成「從未送出」,就會造成重複委託。

穩定的客戶端委託識別碼有助於查明委託結果。只有在接收端系統確實執行必要的唯一性或冪等性規則時,它們才能防止重複委託。也要保存已處理的成交識別碼,避免重播的成交再次增加持倉。

我對那種乏味的委託狀態畫面總是特別有好感。到了重新啟動的那一天,畫面上那些小小的資料列,忽然成了整棟大樓裡最吸引人的介面。

3. 還原持倉,卻重新開始計算損益帳本

來看一個不使用槓桿、沒有手續費的現貨範例。起始現金為 $10,000,以 $100 買進 10 單位,並在標記價格到達 $110 時建立檢查點。

正確的狀態是 $9,000 現金,加上價值 $1,100 的持倉,權益合計 $10,100。如果復原時還原了 10 單位,卻把現金重設為原本的 $10,000,帳面就會顯示 $11,100。你只靠重新啟動程序就憑空變出了 $1,000。

有些情況沒那麼戲劇化。復原後權益維持不變,進場價格卻被重設為 $110。權益總額可能仍然正確,但已實現與未實現損益的歸屬會改變。如果停損或出場條件會參照進場價格,這種帳務捷徑就會改變交易行為。

系統也可能忘記先前的權益高點。假設權益曾達到 $10,600,之後跌至 $10,100,回撤約為 4.72%。如果復原時重設歷史高點,策略就會突然認為回撤是 0。任何以回撤為依據的風險控管都因此遭到未授權重設。

因此,問題可能表現為權益突然跳變、回撤看起來異常改善,或風險規則在部署後停止觸發。請保留帳本和依賴帳務資訊的策略狀態:資金異動、持倉、適用的成本基礎、累積費用,以及風險控管記錄。在同一個估值時間點核對還原後的權益與帳本。

檢查點必須對應一致的狀態邊界。如果填單後才儲存現金,卻在填單前儲存持倉數量,得到的狀態就從未實際存在過。請將相關狀態一併提交,或記錄可用來重建狀態的持久事件序列。事件游標也要和該狀態一起儲存,讓復原時既不會漏掉成交,也不會重複套用。

我會在研究測試框架中保留這項測試:先執行一次不中斷的參考重播,再於刻意挑選的棘手時點重新啟動第二次執行:指標初始化期間、部分成交之後,以及風險限制生效期間。使用相同的事件順序,並保留模擬器的隨機狀態。比對復原後的第一個決策、委託和成交紀錄,以及權益變化軌跡。只比對最終餘額,即使錯誤彼此抵銷,也可能看不出來。

若要測試送出委託後、收到確認前發生當機的情況,測試框架也必須將執行服務的狀態獨立保留,不受策略程序影響。否則,你會刪掉自己正要測試的不確定性。

策略規格也包含它會記住哪些資訊。請明確描述這些記憶,讓你能在重播中途終止程序,並清楚展示它如何恢復運作。

策略狀態回測檢查點復原模擬交易
← 所有文章