為什麼漂亮的回測可能什麼都不代表——以及如何分辨真正的優勢和曲線擬合的幻覺。
當一個策略的參數被精確調整到能夠完美符合歷史資料時,它實際上是在記憶過去,而不是學習可以泛化的規則。回測看起來卓越,實盤卻表現很差——甚至和隨機沒有差別。
過擬合通常不是有意為之的。每當你做了以下事情,它就自然發生:
假設你掃描了 100 個參數組合。就算你的策略完全沒有優勢,在 5% 的顯著水準下,單純靠機率就有大約 5 個組合會產生正的 Sharpe。如果你挑出最好的那個並回報為策略績效,你是在把雜訊當訊號。
這個問題隨著參數數量增加而惡化。兩個參數做 20×20 的格子有 400 個組合;四個參數做 10×10×10×10 有 10,000 個。每增加一個維度,撞上幸運峰值的機率就倍增。
避免過擬合最重要的實務技巧是:不要挑峰值。
看一張參數掃描的 Sharpe 熱力圖。絕對最佳的格子可能顯示 Sharpe 1.8。往左移一格:0.4。往上移一格:0.3。這個峰值很脆弱——它之所以存在,是因為那個特定的參數組合剛好符合了訓練資料裡幾個特定的市場事件。
正確的做法是找高原(Plateau):在許多鄰近參數組合上 Sharpe 都持續偏高的區域。如果一個 3×3 鄰域的 Sharpe 平均都在 1.2 左右,這才是穩健的訊號——優勢存在於一個參數範圍之內,不只在單一的精確值。
# BlaveClaw 的 find_plateau: # 選的是鄰域(3×3 窗口)平均 Sharpe 最高的格子, # 而不是單點最大值。 best_idx = argmax(neighborhood_average_sharpe)
這就是為什麼 BlaveClaw 的 scan.py 使用 find_plateau 而不是直接取最佳 Sharpe。位於平滑高原上的參數組合,遠比位於孤立峰值的組合更可能泛化到未來。
衡量策略真實績效的唯一有效方式,是在它從未「見過」的資料上測試。如果你用 2020–2023 的資料優化參數,然後在 2024 的資料上評估,2024 的績效就是真正的樣本外估計。
如果你用 2020–2024 的資料優化,再回報 2020–2024 的績效:那是樣本內。即使你並沒有刻意過擬合,優化過程本身已經隱性地使用了 2020–2024 的結果來選擇參數。回報的 Sharpe 包含了事後之明的好處。
| 方法 | 有效? | 說明 |
|---|---|---|
| 用全部歷史資料優化,回報全部歷史績效 | ✗ | 樣本內——必然過擬合 |
| 用前 70% 優化,回報後 30% 績效 | ✓ | 簡單訓練/測試分割——有效但有限 |
| 走步向前:用滾動窗口優化,回報下一段 | ✓✓ | 最真實——和實盤的方式相同 |
另一個常見的過擬合陷阱是把掃描範圍設得太廣,包含在歷史上幾乎從未出現過的極端參數值,讓某個異常市場期的偶然事件拉高那個參數的 Sharpe。
BlaveClaw 對門檻型策略採用不同的做法:從指標本身的分佈來決定掃描範圍。進場門檻的候選值來自指標歷史分佈的上半段(p50–p90);出場門檻候選值來自下半段(p10–p50)。這讓兩個門檻都落在有足夠歷史資料的範圍內,不會把歷史上只出現過兩次的極端值當作候選。
實際效果是:你不會去測試指標歷史上只到達過兩次的進場門檻,因為那個水準根本沒有足夠的歷史案例可以統計。
Sharpe 熱力圖上的孤立峰值。 最佳參數組合的鄰近格子 Sharpe 大幅下跌。往任何方向移動一格就掉 0.5 以上。優勢不穩健,只是局部的。
回測 Sharpe 在樣本外大幅下滑。 訓練期 Sharpe 2.0,測試期 Sharpe 0.2。落差越大,策略越過擬合。
交易筆數太少。 三年回測只有 12 筆交易,幾乎沒有統計效力。幾筆幸運的交易就能純靠機率製造 Sharpe 2.0。需要至少 30–50 筆完整交易,回測數字才有意義。
績效完全集中在單一市場環境。 如果回測績效完全來自某一段牛市或熊市,其他時期都是平盤或虧損,策略可能只是學會了那個特定的市場環境,而不是一個普遍的規則。
為了「修掉」虧損期而加入參數。 在圖表上看到某段回撤後,特意加入一個條件來避開它,然後在同樣的資料上重測——這是最典型的過擬合操作,因為未來不會再有一模一樣的虧損期等你去避開。
沒有通用的上限,但有一個實用原則:每一個額外的自由參數都應該有先驗的理由存在於策略邏輯中。不是因為加了它能讓資料擬合得更好,而是因為它代表了你所利用的市場機制的一個真實維度。
一個有兩個參數、代表有意義概念的策略(例如快速訊號窗口和慢速確認窗口),比一個有六個參數、其中幾個是為了「修掉」圖表上特定虧損期而加入的策略,更有說服力。
← 回到目錄