量化入門

回測過擬合怎麼看出來?參數最佳化之後該做的三件事

2026-10-06·7 分鐘閱讀

你把參數掃了一輪,回測曲線漂亮到讓你想直接按 live trading——年化 120%、最大回撤 8%、勝率 62%。 接下來大概率會發生的事:實盤第一個月就吃掉回測三年淨利的一半。這不是壞運氣,是「過擬合」 (overfitting)留下的收據。

這篇不評論你用哪個策略邏輯——邏輯本身可能沒問題,問題往往出在參數怎麼挑的、用哪段資料挑的。 給你三件事,都是最佳化按下去之後、把策略搬上實盤之前該做的驗證,一件都不能省。

先講結論
先講結論:參數最佳化跑完不是終點,是起點。挑到「最佳」那一組之後, 至少要做三件事——樣本外重跑(walk-forward)、參數敏感度掃描、以及用 1/3 部位的小規模實盤—— 三關通過才有資格上正常倉。回測數字看得再漂亮,這三關沒過就是還沒驗過。

先講清楚:過擬合到底把「什麼」配給「什麼」

過擬合的機制很直接:你在同一段歷史資料上,同時做「選策略」與「調參數」兩件事, 最後挑到的那一組,本質上是對這段歷史的雜訊拿到滿分——不是對市場的 結構性行為拿到滿分。

把資料想成一張考卷。你先看完考卷再回頭挑答題方法,考出來當然全對——但那不能推論你 下一張考卷也會這樣。過擬合的核心就是這個:你用未來看過的資料回頭挑參數,然後用同一份 資料驗證挑得對不對,整個流程裡沒有任何資訊在告訴你這組參數對「沒見過的資料」有沒有效。

數學特徵:in-sample 誤差很低,out-of-sample 誤差爆炸
這是識別過擬合最直接的訊號。你在最佳化那段資料(in-sample)看到勝率 62%、 Sharpe 2.1;換到沒碰過的那段(out-of-sample),勝率掉到 48%、Sharpe 0.4—— 這種落差不是「運氣不好」,是曲線硬拉出來配這段歷史的直接證據。

第一關:把資料切開,最佳化只能碰 in-sample

最基本、也最常被跳過的動作:資料一開始就切兩塊。一塊給你隨便玩—— 參數怎麼調、指標怎麼加、規則怎麼改都可以;另一塊鎖起來,最佳化跑完那一刻才第一次 拿出來看。這塊不能參與任何選擇,一旦拿出來看過就報廢,不能再用。

70 / 30
常見比例,前 70% 給最佳化
80 / 20
資料短的話會這樣切
1 次
OOS 資料只能看 1 次,看過就報廢
6~12 個月
OOS 至少要涵蓋一個像樣的市場週期

切法沒有唯一正解,看你手上有多少年資料。(本文寫作時整理的常見基準)

這裡有個很容易騙自己的做法:你把 out-of-sample 拿出來看,發現不理想,回頭改參數, 再看一次。這個當下 OOS 就報廢了——它已經被最佳化流程間接碰過, 跟本來的 in-sample 沒有本質差別。看第二次的 OOS 不叫 out-of-sample,叫另一段 in-sample。

想避開這個陷阱,可以再切第三塊叫 hold-out:整個開發過程完全不碰, 策略要交付給實盤那天才第一次看。這塊小一點沒關係(15% 到 20%),它的作用是給你 「這組參數在真的沒見過的資料上長什麼樣」一個誠實的參考。

第二關:walk-forward — 讓「最佳化」變成一直發生的事

切一次 in-sample/out-of-sample 有個弱點:你只驗證了「用前 70% 挑的參數, 在後 30% 上還有效」這一個切點。市場如果換了個模式,你這組挑三年前資料調出來的 參數,可能三年來都在慢慢失效,你只是還沒發現。

walk-forward 的想法很單純:把資料切成很多小段,每段都跑一次「用前面 N 個月調參數、 用接下來 M 個月驗證」,然後把「驗證段」全部拼起來當成一條連續的樣本外曲線。 這條曲線比較接近「真的照這個流程做的話,這幾年會拿到什麼」。

單次切樣本外walk-forward
驗證了幾個時間點?1 個切點很多個滾動視窗
對「市場換模式」的抵抗力低(用一段舊資料挑)高(每個視窗都重新挑)
設定複雜度簡單要決定視窗長度與滾動步長
運算成本跑 1 次最佳化跑 N 次最佳化
最像實盤的行為不太像接近你會怎麼定期重調

兩種驗證方式的取捨。walk-forward 較貴,但更接近「策略要定期重調」的現實。

walk-forward 有個副產品同樣重要:每個視窗挑到的「最佳參數」是什麼?如果十個視窗挑到十組差很多的值,那不是這個策略敏感——是這個策略沒有真的規律, 只是每次都在配當下那段雜訊。反過來,十個視窗挑到差不多的參數,那才是真的抓到什麼。

這裡的取捨要自己拍板
視窗要切多長?滾動步長要多大?官方沒有標準答案,選擇會影響結果。一個常見的起點是 「訓練窗 = 6 個月、測試窗 = 1~2 個月、每次前進一個測試窗」,但拿加密資料還是股票、 日線還是 1 小時線,都要重挑。這是由概念推導出的建議,不是官方白紙黑字的 規則——照做前先確認符合你的策略頻率。

第三關:參數敏感度 — 你挑到的是山峰還是山脊?

同樣一組回測拿到 Sharpe 2.1,可能是兩種很不一樣的東西:山峰—— 你剛好挑到那唯一的高點,任何一個參數挪一格數字就掉到 Sharpe 0.5;山脊—— 你周圍一片參數都在 Sharpe 1.8~2.1,挪一格還是差不多。第一種是過擬合的教科書範例, 第二種才是可以搬上實盤的東西。

1
把「最佳」那組參數的每個維度都 ±10% 掃一遍,Sharpe 掉多少?
掉 50% 以上 →山峰。這組參數大概率是配這段歷史的雜訊,不要搬上實盤——回去檢查邏輯或縮小參數空間。
掉 20~40% →邊坡。可以繼續往下看,但用小部位測試。
掉 10% 以內 →山脊。這是你要找的形狀,可以進第三步。
2
把每個維度上「還過得去」的參數範圍畫出來,加總後有幾組能通過門檻?
只有那一組能過 →回去山峰那格處理。
有一整個連續區塊都能過 →就從那個區塊的中位數挑,不要挑最高點。中位數才是「你可以承受一點漂移」的位置。

把「參數 vs 績效」的 3D 熱圖畫出來看是最直觀的做法。真的有規律的策略,圖看起來會是 一片緩坡;過擬合的策略看起來是幾根尖刺。這一步不需要新工具,用你已經在跑的最佳化 結果自己畫。

順帶一提:資料量夠不夠支撐你調的參數個數

參數愈多,過擬合愈容易——這句話幾乎是常識,但少有人講具體門檻。這裡列一個粗略的 經驗值,來自機器學習的一般原則(不是交易獨有):每多一個要調的參數,你需要的獨立 樣本數會加倍成長。把「回測跑過的交易筆數」當成樣本數來估:

2 個參數
至少 100 筆交易
3 個參數
至少 200 筆交易
5 個參數
至少 500 筆交易
7 個以上
多半已經無藥可救

這是粗略的健康檢查值,不是精確門檻。策略愈複雜,數字要往上抓。

如果你的策略跑三年只成交 40 筆,卻在調 5 個參數,那不是「策略太挑」——是資料量根本 不夠讓你分辨「真的有效」與「剛好配到」。這種情況下,唯一有意義的動作是換更高頻的 timeframe、或把參數個數砍到 2 個以內。

三關都過了:實盤上線前的最後兩步

就算前面三關全過,也不建議直接開正常倉。上線之後的兩件事同樣關鍵:

  • 先開 1/3 或更小的部位跑一到兩個月。回測會漏算的東西——真實成交延遲、滑點、部分成交、交易所偶爾的拒單——只有實盤會告訴你。
  • 紀錄每一筆回測 vs 實盤的偏差。同一根 K 棒的訊號、實際成交價、以及最終 PnL 有沒有系統性偏離回測預期。
  • 設定一個停止線:實盤累積虧損超過 X% 或連續 N 筆偏離回測,就先停下來檢查——不要等到已經吃完 3 個月才發現不對。
  • 要把部位放大之前,用實盤這一到兩個月的資料再跑一次walk-forward驗證。這是最誠實的一份 out-of-sample 資料。

部位怎麼從小開始加大,跟策略邏輯是兩回事,屬於資金管理的問題。這一段可以另外看 Kelly 公式與部位大小 那篇,那邊有講「半 Kelly」為什麼是實務常用的折衷。

這三關都幫不了你的事

講完做得到什麼,也該講清楚做不到什麼——這是這篇最容易被誤解的地方。walk-forward 與參數敏感度都是「同一個市場環境」的驗證, 它們對付不了下面這幾種東西:

這幾件事只有實盤會告訴你
市場結構性變化:加密的 2021 牛市與 2023 盤整期是兩個不同的市場, 你用 2021 資料 walk-forward 出來的參數,換到 2023 一樣會失效。
執行成本被低估:多數回測工具預設的手續費、滑點都是理想值, 真實的做市商庫存、taker 手續費、部分成交都會啃掉一部分理論淨利。
訊號稀疏度:一年只觸發 10 次的策略,就算 walk-forward 過關, 也可能只是這 10 次剛好對——樣本太少,統計上沒有意義。
你自己會不會關掉它:一組回測看起來能扛 40% 回撤,實盤跌到 20% 你就 睡不著關掉了——這是行為問題,測不出來。

誠實的一段:把回測數字放在該有的位置

這篇本身沒有貼任何具體的策略回測數字,是刻意的——沒有標的、期間、參數、樣本外設定 一起附上的績效數字,不管數字多漂亮,讀者拿去做決策都是危險的。過去績效不代表未來表現,這句話在回測結果上尤其成立: 回測是模擬,不是實單紀錄。

如果你要在自己的文章、Twitter 或給付費訂閱者的訊號裡放回測結果,最低限度該附上: 標的(例如 BTCUSDT.P)、時間範圍(例如 2023-01 至 2025-12)、 參數組(不要只寫「經最佳化」)、有沒有 walk-forward、以及一句「這是模擬結果, 不代表實盤獲利」。少一個都會讓別人沒辦法判斷這份績效值不值得跟。

這也是為什麼建議在做量化之前先看 散戶怎麼開始做量化交易 那篇——裡面有一整段在講「年化 500% 不是 overfitting 就是還沒崩」,可以當這篇的姊妹篇。

常見問題

walk-forward 的每個視窗都要重新挑參數嗎?那不是等於一直在最佳化?
對,這正是重點。walk-forward 模擬的是「你會定期重新調參數」這個行為—— 它不是為了找一組永遠不動的最佳參數,是為了衡量「這個策略邏輯配上定期重調的流程」 能不能長期有效。實盤上真的要做的事,就是每隔一段時間用最新資料重跑一次最佳化。
為什麼參數敏感度要 ±10%,不是 ±20% 或 ±5%?
沒有標準答案,10% 是合理起點。真實動機是「參數在實盤上會漂移多少 仍然算穩定」。如果你的參數本來就是很粗的檔位(例如 EMA 只能是整數),改用 「±1 檔」跟「±2 檔」代替 ±10% 更合適。這是概念上的敏感度檢查,不是精確公式。
in-sample 表現太差,能不能回去換策略邏輯,再走一次流程?
可以,但你有一次算一次——每回頭改一次策略邏輯,資料就多被「看過」一次, 過擬合的風險就多疊一層。實務上常見的紀律是限制改的次數(例如三次為上限),並在最後把 hold-out 那塊拿出來做最後檢驗。多改幾次還是不行, 那可能是這個題目本身沒有規律,不是參數的問題。
什麼樣的策略最容易過擬合?
幾個高風險徵兆:參數個數多(五個以上)、訊號稀疏(一年少於幾十筆)、用複合條件(三個以上指標同時成立才進場)、時間框架短但只回測幾個月。四個占了兩個以上就要特別小心, 回測數字愈漂亮愈可疑。
工具面上,這三關要怎麼跑?
資料切法與參數敏感度大部分回測工具都做得到,關鍵是你要記得手動去切—— 不要按下「optimize」看到最佳結果就停手。walk-forward 有些平台有內建、有些要靠 Python (backtesting.py、vectorbt)自己組。先去自己工具的設定裡找 「walk-forward」或「rolling window」的選項,沒有的話就得把資料匯出到別的工具做。

Get started

想把今天學到的東西自動化跑起來?

TVSBot 是非託管的 TradingView → 交易所自動下單平台。把你驗過的策略接上 webhook,用你自己的 API key,先開 dry-run 或小部位跑一輪實盤——這是「三關通過之後」該接的下一段。

免費開始