回測與最佳化流程#

寫好策略只是第一步,回測(Backtesting)最佳化(Optimization) 才能驗證策略是否具有歷史優勢、找出穩健的參數區間,並評估上線實盤的可行性。本章說明 MultiCharts 完整的驗證流程,並指出最容易讓回測結果與實盤落差過大的設定陷阱。

流程用途對應功能
回測用歷史資料模擬策略下單,產生績效報告Strategy Performance Report
回測設定設定撮合假設、佣金、滑價、Look-Inside-BarStrategy Properties → Properties / Backtesting 分頁
最佳化找出最佳參數組合Optimize → Exhaustive / Genetic
前進測試驗證最佳化參數的穩健性,避免過度擬合Walk-Forward Optimization

回測#

回測指的是「將策略套用到歷史資料上,模擬如果當時依照策略下單會產生什麼結果」。在 MultiCharts,回測的執行步驟為:

  1. 開啟 Chart Window,載入要測試的商品與週期
  2. 從 Power Editor 編譯訊號(Signal)腳本
  3. Insert → Signal 將訊號加到圖表上
  4. 開啟 View → Strategy Performance Report 查看回測結果

回測的本質是「把每一根 K 棒當成已發生的事實,重新讓策略決策一次」。所有撮合行為都受 Backtest Settings 影響。

Strategy Performance Report 重要指標#

開啟 Strategy Performance Report 後,最該優先檢視的指標:

指標說明判讀重點
Net Profit總損益(已扣佣金與滑價)必須為正,且明顯高於 Buy & Hold
Profit Factor總獲利 / 總虧損> 1.5 為佳;< 1.2 邊際效益太低
Max Intraday Drawdown最大盤中回撤金額(Strategy Performance Report 實際欄位名)與資金規模對照,回撤超過 30% 通常難以實盤執行
Total Trades交易次數(報告中可能顯示為 Total # of Trades< 30 筆統計樣本不足;建議 > 100 筆
Avg Trade Net Profit平均每筆損益必須明顯大於「佣金 + 預期滑價」
Percent Profitable(亦顯示為 % Profitable勝率與 Ratio Avg Win:Avg Loss 搭配看,單看勝率沒意義
Ratio Avg Win:Avg Loss平均獲利 / 平均虧損趨勢策略通常 > 2,均值回歸策略可能 < 1

陷阱:只看 Net Profit 是新手常犯的錯誤。一條 Net Profit 漂亮但 Total Trades 只有 12 筆、Avg Trade 接近滑價金額的曲線,幾乎不可能在實盤複製。

回測設定(避免回測高估)#

回測結果與實盤落差的最大原因,是撮合假設過度樂觀。在 Chart Window 上對訊號右鍵 → Format Signals,於 Signals tab 點 Properties 開啟 Strategy Properties(即套用全部訊號),逐項調整下列設定。

佣金與滑價#

在 Strategy Properties 視窗的 Properties 分頁中找到 Costs/Capitalization 區塊:

欄位建議設定
Commission Rule透過規則表設定實際券商來回手續費(含期交稅)。台指期約 60 TWD/口/來回
Slippage至少 1 個 tick;流動性差的商品建議 2–3 ticks

Commission 欄位是 以 Rule 規則表設定(可依口數、金額階梯計算),不是單純填一個固定數字。

即使策略在零成本下表現亮眼,加入合理佣金與滑價後常常從正期望值跌到接近零。永遠先設好成本再評估策略

Bar Magnifier 與 Look-Inside-Bar#

在 Strategy Properties 視窗的 Backtesting 分頁中:

設定說明何時開啟
Use Bar Magnifier用更小週期的資料模擬主週期內部的價格走勢任何使用 Stop / Limit 進出場、或同根 K 棒內可能多次觸發停損的策略
Bar Magnifier Resolution通常設為 1 分鐘或 tick主週期越大,越需要打開

沒有 Bar Magnifier 時的撮合假設

MultiCharts 依「Open 比較靠近 High 還是 Low」決定 K 棒內部走勢順序(與多空方向無關):

  • 若 Open 靠近 Low → 假設走勢 Open → High → Low → Close
  • 若 Open 靠近 High → 假設走勢 Open → Low → High → Close

實盤實際走勢可能完全相反,導致回測中「停損沒打到」的單在實盤被掃出。

Price時間 →HighLowOpenClose1234OpenHighLowClose
情境 A:Open 靠近 Low
假設走勢 Open → High → Low → Close(先碰 High,止盈先觸發)
Price時間 →HighLowOpenClose1234OpenLowHighClose
情境 B:Open 靠近 High
假設走勢 Open → Low → High → Close(先碰 Low,停損先觸發)

實盤的真實走勢可能恰好相反 — 同一根 K 棒,Open 靠近 Low 不代表價格就一定先上後下。這就是為什麼 Stop/Limit 策略沒開 Bar Magnifier 時,回測常常「贏太多」。

Stop / Limit 撮合差異:MultiCharts 假設 Stop 單只要價格碰到就成交,但 Limit 單必須被穿越才視為成交(亦即「碰到 Limit 價位本身不算成交」)。實盤排隊順序差異可能造成 Limit 單未成交。

範例:日線策略內含 SetStopLoss(20 * BigPointValue)SetProfitTarget(40 * BigPointValue)

  • 未開啟 Bar Magnifier:依 Open 與 High/Low 的相對位置決定先觸發停損或止盈
  • 開啟 Bar Magnifier(1 分鐘):以實際 1 分鐘走勢判定哪個門檻先到

打開 Bar Magnifier 後常見現象:原本看起來大賺的策略 Net Profit 砍半,但這才是貼近實盤的數字。

Intra-Bar Order Generation (IOG)#

在 Strategy Properties 視窗的 Properties 分頁中(與 Max Bars Back 同一頁):

設定說明
Enable Intra-Bar Order Generation允許策略在 K 棒未收盤時就下單;每個 tick 都會重跑一次邏輯
模式適用情境注意
關閉 IOG(預設)策略只在 K 棒收盤時決策與實盤 Bar Close 模式一致,最容易對齊
開啟 IOG想做 tick-by-tick 反應、或盤中追價回測會慢非常多;實盤需用 OnBrokerData,否則會與回測不一致

常見陷阱:策略開了 IOG,但程式碼裡沒處理「同一根 K 棒內被重複觸發」的邏輯(例如 If Close > X Then Buy),結果回測一根 K 棒下了好幾次單。建議搭配 MarketPositionEntriesToday(Date) 檢查避免重複進場。

Maximum Bars Back#

在 Strategy Properties 視窗的 Properties 分頁中:

設定說明
Maximum number of bars study will reference策略需要回看的最大 K 棒數(例如 Average(Close, 200) 至少要 200)

設太低會導致策略在前段資料完全不執行;設太高浪費記憶體。建議:所有 lookback 中最大者 + 50 buffer。

最佳化#

最佳化是指「自動測試多組參數組合,找出績效最佳的設定」。從訊號右鍵 → Format Signals → 選定訊號 → Optimize

兩種最佳化演算法#

演算法原理適用情境
Exhaustive(窮舉)測試所有參數組合參數組合 < 10,000 時首選;結果完整可重現
Genetic(基因演算法)用演化方式逼近最佳解參數組合過大、窮舉跑不完時使用;結果為近似解

範例:策略有 3 個參數,每個 10 個值 → 1,000 組,用 Exhaustive;若 5 個參數每個 20 個值 → 3,200,000 組,必須用 Genetic。

最佳化目標函數#

不要用 Net Profit 作為最佳化目標 — 這會嚴重過度擬合到極少數高獲利交易。建議改用:

目標函數說明
Profit Factor平衡獲利能力與穩定性
Custom Fitness Value自訂目標,例如 NetProfit / MaxDrawdownSharpe Ratio

結果分析#

最佳化跑完後,不要直接挑 Net Profit 最高的參數。應該打開 3D 圖(Optimization Report → 3D Chart),檢查:

  • 參數高原 (Parameter Plateau):理想狀況是「相鄰多組參數績效都不錯」形成穩定高原。如果只有單一峰值,旁邊績效斷崖式下降,幾乎可確定是過度擬合
  • 參數穩定性:建議選擇位於高原中央、而非峰頂的參數組合

範例:均線參數從 18 → 22 都能維持 80% 以上的最高 Net Profit,則選 20 比選峰頂的 19 更穩健。

前進測試(Walk-Forward Optimization)#

前進測試是檢驗最佳化參數能否「在沒看過的資料上仍有效」的標準工具。流程:

[訓練段 IS] → 找最佳參數 → [驗證段 OOS 用這組參數跑] → 記錄 OOS 績效
       ↓ 視窗向前滾動
[訓練段 IS] → 找最佳參數 → [驗證段 OOS] → 記錄
       ↓
... 重複多輪 ...
  • IS (In-Sample):訓練段,用來最佳化找最佳參數
  • OOS (Out-of-Sample):驗證段,套用 IS 找出的參數,評估真實績效

在 MultiCharts 啟動: 訊號右鍵 → Optimize,於 Optimization 對話框中找到獨立的 Walk-Forward Optimization 區塊(不只是單一勾選框,而是含 IS/OOS 比例、Anchored/Rolling、Number of Runs 等設定的完整面板)進行設定。

關鍵設定#

設定建議
IS / OOS 比例常見為 4:1 或 3:1(例如 12 個月 IS + 3 個月 OOS)
Number of Runs至少 5 輪以上才有統計意義
Anchored vs RollingRolling 視窗較常見;Anchored 適用於商品行為穩定的市場

判讀 WFO 報告#

WFO 報告的關鍵指標是 WFE (Walk-Forward Efficiency):

WFE = (OOS 年化報酬) / (IS 年化報酬)
WFE 區間判讀
> 0.6策略可能具有真實優勢(業界常用較嚴格的 0.5–0.6 門檻,建議以 0.6 為準)
0.3 – 0.6邊際 — 需謹慎評估
< 0.3嚴重過度擬合,不建議實盤

WFE 不是越接近 1 越好。> 0.7 反而要懷疑是不是 IS 段也很糟(兩段都爛 WFE 也會接近 1)。要與絕對績效一起看。

常見陷阱#

Look-Ahead Bias(未來資訊洩漏)#

策略不小心用了「當下還不知道」的資訊。常見來源:

1
2
3
4
5
// ❌ 錯誤:用收盤價判斷後立刻當根進場(IOG 關閉時 MultiCharts 會延遲到 Next Bar,但若用 This Bar Close 就有問題)
If Close > Highest(High, 20)[1] Then Buy This Bar Close;

// ✅ 正確:訊號當根判斷,下一根開盤才執行
If Close > Highest(High, 20)[1] Then Buy Next Bar Market;

[1] 取的是「上一根 K 棒」的值。比較 Highest(High, 20)Highest(High, 20)[1] — 前者包含當根高點(同一根內未來資訊),後者不包含。

過度擬合#

過度擬合的徵兆:

  • 最佳化後績效曲線異常平滑
  • 參數高原非常窄
  • IS 和 OOS 績效差距巨大(WFE < 0.3)
  • 參數組合超過 4 個

緩解方式:

  1. 減少參數數量(< 4 個為佳)
  2. 用 Walk-Forward 驗證
  3. 在多個商品上驗證同一組參數
  4. 加入 OOS 段(最近 1–2 年資料留作完全沒看過的驗證)

倖存者偏差#

回測股票時,若資料來源只包含「目前還在交易的股票」,下市股票被排除,會嚴重高估策略績效。期貨商品較少此問題,但選股策略需特別注意。

訂單未成交假設#

MultiCharts 預設「Stop 單只要碰到就成交」、「Limit 單必須被穿越才成交」。實際盤中:

  • 大部位的 Limit 單可能只成交一部分,剩下排隊
  • 跳空開盤可能直接跳過 Limit 價格
  • 流動性低時 Stop 單滑價遠超預期

緩解:將 Slippage 設大一點,或用 Bar Magnifier 開啟逐 tick 模擬。

樣本數不足#

Total Trades < 30 的回測結果統計上沒有意義。緩解:

  • 拉長回測區間(建議覆蓋 2 個以上完整多空循環,至少 5–10 年)
  • 在多個商品上跑同一策略
  • 用較短週期的資料(例如從日線改 60 分線)

完整工作流程範例#

以一個簡單均線突破策略示範完整驗證流程:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
Inputs:
  fastLength(10),
  slowLength(30),
  stopPoints(50);

Variables: maFast(0), maSlow(0);

maFast = Average(Close, fastLength);
maSlow = Average(Close, slowLength);

// 訊號當根判斷,下一根開盤執行(避免 Look-Ahead)
If MarketPosition = 0 and maFast crosses above maSlow Then
  Buy("LE") 1 Contract Next Bar Market;

If MarketPosition = 1 and maFast crosses below maSlow Then
  Sell("LX") Next Bar Market;

SetStopLoss(stopPoints * BigPointValue);

驗證步驟:

  1. 回測設定:佣金 60 TWD、滑價 1 tick、開啟 Bar Magnifier (1 分鐘)、Maximum Bars Back = 100
  2. 單次回測:用預設參數跑一次,確認 Total Trades > 100、Avg Trade > 滑價
  3. 最佳化fastLength 5–20、slowLength 20–60、stopPoints 30–100,目標 = Profit Factor
  4. 檢視 3D 圖:找出參數高原,選擇高原中央的組合
  5. Walk-Forward:12 個月 IS + 3 個月 OOS,跑 6 輪,要求 WFE > 0.6
  6. 多商品驗證:用上述參數套到至少 2 個其他商品,績效不能崩盤
  7. 保留 OOS 區段:最近 6–12 個月資料完全不參與最佳化,最後跑一次驗證

通過上述每一關後,才考慮模擬交易(Paper Trading)一段時間。

注意事項#

回測與實盤永遠有落差#

即使做完所有檢查,回測也只能逼近實盤、無法等於實盤。原因包括: 撮合佇列、市場衝擊、交易所限制、網路延遲、行情訂閱差異。永遠先用模擬交易確認後再上實盤

重新編譯後重新回測#

修改策略後務必重新編譯(Power Editor → Compile),並對 Chart 上的訊號右鍵 → Recalculate,否則績效報告仍是舊版本。

最佳化參數會隨資料更新而失效#

市場結構會變化,半年到一年後建議重新跑一次最佳化與 WFO,但不要每週都重新最佳化(這本身就是過度擬合)。

最佳化結果儲存#

Optimization Report 可匯出為 CSV,方便用 Excel 或 Python 進一步分析(例如算 Sharpe、Sortino、Calmar)。

Reference#

https://www.multicharts.com/trading-software/index.php?title=Strategy_Performance_Report

https://www.multicharts.com/trading-software/index.php?title=Bar_Magnifier

https://www.multicharts.com/trading-software/index.php?title=Intra-Bar_Order_Generation

https://www.multicharts.com/trading-software/index.php?title=Optimization

https://www.multicharts.com/trading-software/index.php?title=Walk-Forward_Optimization