返回《給 CFD 交易者的 MetaTrader 5 與 MQL5》
第一部分

輸入參數與策略測試器

把魔術數字變成輸入參數、把它們分組,然後讓測試器去搜尋數值,而不是你自己來。

初學閱讀時間約 7 分鐘初學 → 進階第 05 / 17 堂
在 MetaEditor 實際跑一次
分組的輸入參數與一個 enum 驅動的移動平均線

存成 MQL5/Indicators/Lesson5Inputs.mq5。打開輸入對話框看分組與下拉選單;然後在策略測試器裡最佳化 Period。

//+------------------------------------------------------------------+
//| Lesson 5 - Grouped inputs, enum inputs, optimisation             |
//+------------------------------------------------------------------+
#property copyright "Strategist Academy"
#property version   "1.00"

#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots   1
#property indicator_type1   DRAW_LINE
#property indicator_width1  2

input group "Moving average"
input int                Period    = 50;          // Period
input ENUM_APPLIED_PRICE Applied   = PRICE_CLOSE; // Applied price

input group "Display"
input color              LineColor = clrOrange;   // Line colour

double Buffer[];

int OnInit()
{
   if(Period < 2) return(INIT_FAILED);

   SetIndexBuffer(0, Buffer, INDICATOR_DATA);
   PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, Period - 1);
   PlotIndexSetInteger(0, PLOT_LINE_COLOR, 0, LineColor);
   PlotIndexSetString(0, PLOT_LABEL, "MA(" + IntegerToString(Period) + ")");
   IndicatorSetString(INDICATOR_SHORTNAME, "Lesson 5 MA(" + IntegerToString(Period) + ")");
   return(INIT_SUCCEEDED);
}

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{
   if(rates_total < Period) return(0);

   // Pick the source array based on the enum input.
   // (Applied price handling is simplified here; built-in iMA does this properly
   //  and is covered in Part 4.)
   int start = (prev_calculated == 0) ? Period - 1 : prev_calculated - 1;
   if(start < Period - 1) start = Period - 1;

   for(int i = start; i < rates_total && !IsStopped(); i++)
   {
      double sum = 0.0;
      for(int k = 0; k < Period; k++)
         sum += close[i - k];
      Buffer[i] = sum / Period;
   }
   return(rates_total);
}
如何執行
  1. 1. 從 MT5 開啟 MetaEditor(按 F4), 選擇這支程式該放的資料夾——ExpertsIndicators Scripts
  2. 2. 開新檔案、把這段程式貼上去,然後按 F7 編譯。Errors 分頁顯示的錯誤 都修掉。
  3. 3. 回到 MT5,把它拖到圖表上——如果是 EA,就打開 Strategy Tester

input 與 const 的差別

const 在編譯時就固定了。input 會出現在程式的對話框裡——而且關鍵是——策略測試器可以對它做迭代。任何你合理上會想調整的東西都應該是 input

分組讓對話框還能用

一旦一個 EA 有二十個參數,對話框就會變得很難用。用 input group "..." 把它們分段。這不花任何代價,卻能救你免於誤點自己的風險設定。

用 enum 當輸入

把一個 input 宣告成 ENUM_*,使用者就會看到下拉選單而不是自由文字框。在時間週期、均線方法、套用價格與下單成交模式上都用它。

最佳化既是工具也是陷阱

測試器可以暴力跑過你所有輸入參數的每一種組合。它永遠會找到一條漂亮的曲線——在歷史資料上。一個只在你最佳化的那段精確窗口上有效的參數組,沒有任何預測價值。如果一個結果看起來太好,縮小最佳化窗口、在最佳化器從沒看過的資料上重測,並檢查獲勝值的鄰居是否也賺錢。參數空間裡一根尖銳的尖峰是曲線配適;一片寬廣的高原才是真實效果。

這堂課要改什麼

載入那個指標,打開它的對話框,注意那些分好組的輸入。然後在測試器裡跑它,把週期這個 input 設成從 10 最佳化到 200——看看在過去資料上生出一個漂亮結果有多容易。

你剛完成了什麼

給 CFD 交易者的 MetaTrader 5 與 MQL5》的第 05 / 17 堂課。跑完範例或讀完這段之後, 把它勾起來,然後進下一堂課。