你告訴我,你的模擬交易程序昨晚當機了。你在下一次決策前重新啟動程序,沒有看到任何錯誤,就以為它已經接續先前的狀態運作。接著,它竟然又買進一項你已經持有的資產。你想知道策略是不是有 bug。
有可能。但首先,確認重新啟動的程序掌握的資訊是否與模擬帳戶一致。重啟涉及狀態復原:持倉、現金、未成交委託,以及所有會影響下一次決策的策略記憶,都必須彼此吻合。讓程式重新跑起來,反而是最簡單的部分。
當機前,策略認為自己處於什麼狀態?
記下程序停止前做出的最後一個決策。針對每項交易標的,記錄預期持倉、帳戶實際持倉、未完成委託,以及會影響下一步動作的訊號狀態。如果沒有這些紀錄,你就無法判斷重啟時究竟還原了狀態,還是只建立了一個全新的策略。
假設你的每小時策略在趨勢訊號轉正時買進 1 單位,並持有到訊號轉負為止。程序在 14:00 送出買單,卻在記錄委託已受理之前當機。模擬交易平台成交了這筆委託。重啟時,策略看不到已記錄的持倉,而訊號仍為正,因此又送出一筆買單。訊號的反應前後一致;過時的是策略對帳戶持有資產的記憶。
因此,在允許送出新委託之前,必須先將帳戶目前的持倉與已保存的策略狀態核對一致。本機快照可以派上用場,但實際成交情況仍以帳戶或交易平台的紀錄為準。
哪些狀態必須在重啟後保留下來?
先從可能改變下一筆委託的狀態著手。每次更新都要留下含時間戳記與版本的永久紀錄;修改復原邏輯前,先複製一份資料,方便日後重現這次故障。
| 狀態 | 為何重要 | 復原檢查 |
|---|---|---|
| 持倉與現金 | 決定曝險與可用購買力 | 將已保存的數值與模擬帳戶比對 |
| 未成交委託 | 程序停擺期間,委託可能已經成交 | 查詢委託狀態,並核對部分成交情況 |
| 訊號記憶 | 交叉訊號、冷卻時間與持有期間可能跨越多次決策 | 還原最後一次已提交的決策輸入資料 |
| 最後處理的事件 | 決定策略從哪裡繼續讀取資料 | 從該事件之後重播,但不要重複套用 |
訊號記憶很容易被忽略。以交叉訊號交易的策略,可能會儲存昨天的指標值,以便偵測新的交叉。如果啟動時指標值是空的,就可能把既有狀態誤認成新事件。冷卻計時器也有同樣的問題:重啟不能默默重設原本應持續生效的規則。
如何讓復原流程可以重複執行?
為每筆委託建立穩定的 client ID,並根據策略執行批次與所屬決策產生。如果程序逾時後重試,就能先確認該決策是否已建立委託,而不是再送出重複委託。只有確認對應的帳戶事件後,才記錄狀態變更,並保留能說明變更原因的委託 ID 與成交 ID。
接著,測試這次事故發生時的關鍵節點。讓策略完成一次決策、保存狀態、停止程序,再利用模擬帳戶的持倉與委託歷史還原。將它接續執行時的下一個決策與最終委託,和不中斷執行的結果比對。再測試部分成交的委託,以及在送出委託後、收到確認前發生當機的情況。恢復執行後,策略不應憑空產生新持倉,也不應重複已完成的動作。
保留復原紀錄:最後處理的事件、帳戶快照時間、未成交委託狀態、還原後的策略版本,以及重啟後的第一個決策。這樣一來,「程序重新跑起來了」就成了可以稽核的事實。
重啟後,哪些事情值得信任?
只有在帳戶狀態與策略狀態核對一致、未完成委託的狀態都已確認,而且下一個決策符合不中斷執行時的預期,才可以信任程序。如果你無法解釋不一致之處,就先暫停模擬委託送出,並檢查事件紀錄。程序正在執行,不代表策略已成功復原。
這次當機已經讓你看見一個有用的問題:它揭露了平常運作時從未需要面對的假設。把重啟納入可重複測試的情境,你就能先確認策略記得哪些事,再讓它重新交易。
← 所有文章


