使用Python和MQL5进行交易策略的自动参数优化·综合运用
🐍

使用Python和MQL5进行交易策略的自动参数优化·综合运用

(3/3)· 接前两篇铺垫,本篇用均线交叉EA跑通暴力/随机搜索并对照开优化前后的净值曲线

案例拆解 第 3/3 篇
把没调过参的EA直接丢进实盘,前期飘红很容易让人误以为策略成了,随后市场一变就连续回撤。缺乏自优化的系统会对噪声过度反应,信号真假难分,风险敞口完全不可控。外汇与贵金属杠杆高,这类盲目运行可能迅速吃掉本金。

◍ 双均线参数遍历与信号抓取的代码骨架

换一种优化思路,核心就是改这段双层循环里的周期起止与步长,把 fast/slow 的 MA 周期组合全跑一遍,再用回测函数挑出当前准则下更优的那组参数。 指标句柄不释放,图形窗口迟早被堆满,这是 MT5 跑批量优化时最容易踩的坑,EA 里记得在退出前用 IndicatorRelease 清掉。 下面这段是实盘信号部分的骨架:先按当前最优周期建 iMA 句柄,用 CopyBuffer 取最近两根 K 的快慢线数值,再做穿越判断。注意 CopyBuffer 第三个参数填 0、长度填 2,意味着拿到的是 [0] 当前与 [1] 前一根的序列值(因 ArraySetAsSeries 设为 true)。 买入判定写得很直白——前一根快线在慢线下方、当前快线翻到上方,即视为金叉;进场前先扫一遍 PositionsTotal 平掉已有空单。外汇与贵金属杠杆高,这类交叉信号在历史中胜率可能仅四成到六成,实盘前务必用策略测试器按品种校准周期步长。

MQL5 / C++
  for(class="type">int fastPeriod = FastMAPeriodStart; fastPeriod <= FastMAPeriodStop; fastPeriod += FastMAPeriodStep)
    {
      for(class="type">int slowPeriod = SlowMAPeriodStart; slowPeriod <= SlowMAPeriodStop; slowPeriod += SlowMAPeriodStep)
      {
       class="type">class="kw">double criterionValue = PerformBacktest(fastPeriod, slowPeriod, startBar);
       if(IsNewOptimal(criterionValue, bestCriterionValue, OptimizationCriterion))
         {
          bestCriterionValue = criterionValue;
          bestFastPeriod = fastPeriod;
          bestSlowPeriod = slowPeriod;
         }
      }
    }
class="type">class="kw">double fastMA_curr[];
  class="type">class="kw">double slowMA_curr[];
  class="type">class="kw">double fastMA_prev[];
  class="type">class="kw">double slowMA_prev[];
  ArraySetAsSeries(fastMA_curr, true);
  ArraySetAsSeries(slowMA_curr, true);
  ArraySetAsSeries(fastMA_prev, true);
  ArraySetAsSeries(slowMA_prev, true);
  class="type">int fastMA_current = iMA(_Symbol, class="num">0, FastMAPeriod, class="num">0, MODE_SMA, PRICE_CLOSE);
  class="type">int fastMA_previous = iMA(_Symbol, class="num">0, FastMAPeriod, class="num">1, MODE_SMA, PRICE_CLOSE);
  class="type">int slowMA_current = iMA(_Symbol, class="num">0, SlowMAPeriod, class="num">0, MODE_SMA, PRICE_CLOSE);
  class="type">int slowMA_previous = iMA(_Symbol, class="num">0, SlowMAPeriod, class="num">1, MODE_SMA, PRICE_CLOSE);
  CopyBuffer(fastMA_current, class="num">0, class="num">0, class="num">2, fastMA_curr);
  CopyBuffer(slowMA_current, class="num">0, class="num">0, class="num">2, slowMA_curr);
  CopyBuffer(fastMA_previous, class="num">0, class="num">0, class="num">2, fastMA_prev);
  CopyBuffer(slowMA_previous, class="num">0, class="num">0, class="num">2, slowMA_prev);
  class="type">class="kw">double fastMA_previousFF = fastMA_prev[class="num">0];
  class="type">class="kw">double slowMA_previousSS = slowMA_prev[class="num">0];
  class="type">class="kw">double fastMA_currentFF = fastMA_curr[class="num">0];
  class="type">class="kw">double slowMA_currentSS = slowMA_curr[class="num">0];
class=class="str">"cmt">// Check for buy signal(fast MA crosses above slow MA)
  if(fastMA_previousFF < slowMA_previousSS && fastMA_currentFF > slowMA_currentSS)
   {
    class=class="str">"cmt">// Close any existing sell positions
    if(PositionsTotal() > class="num">0)
     {
      for(class="type">int i = PositionsTotal() - class="num">1; i >= class="num">0; i--)
       {
        if(PositionSelectByTicket(i))
         {
          if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
           {

「双均线死叉时的平仓与反手逻辑」

当快线前一根高于慢线、当前根跌破慢线,系统判定为做空信号。此时先扫一遍持仓池,把所有 BUY 单按 ticket 逐个平掉,再以 SYMBOL_BID 市价开 SELL。 平仓循环用 PositionsTotal()-1 倒序遍历,PositionSelectByTicket(i) 选中后检查 POSITION_TYPE 是否为 POSITION_TYPE_BUY,命中才打印并 ClosePosition。倒序是为了避免删除持仓导致索引错位。 开仓价取卖价而非买价,ATR 倍数沿用外部变量 ATRmultiplier,传给 OpenPosition 做止损距离计算。外汇与贵金属杠杆高,死叉反手可能在震荡市连续挨巴掌,参数需先在 MT5 策略测试器跑历史段验证。 信号处理完,四根指标句柄 fastMA_current / slowMA_current / fastMA_previous / slowMA_previous 都用 IndicatorRelease 释放,防止 EA 长期运行句柄泄漏拖慢终端。

MQL5 / C++
      Print("Closing sell position: Ticket ", PositionGetInteger(POSITION_TICKET));
      ClosePosition(PositionGetInteger(POSITION_TICKET));
     }
    }
   }
  }
  class=class="str">"cmt">// Open a buy position
  class="type">class="kw">double openPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
  class="type">class="kw">double atrMultiplier = ATRmultiplier;
  OpenPosition(ORDER_TYPE_BUY, openPrice, atrMultiplier);
  }
class=class="str">"cmt">// Check for sell signal(fast MA crosses below slow MA)
  else
   if(fastMA_previousFF > slowMA_previousSS && fastMA_currentFF < slowMA_currentSS)
    {
    class=class="str">"cmt">// Close any existing buy positions
    if(PositionsTotal() > class="num">0)
     {
     for(class="type">int i = PositionsTotal() - class="num">1; i >= class="num">0; i--)
      {
      if(PositionSelectByTicket(i))
       {
       if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
        {
        Print("Closing buy position: Ticket ", PositionGetInteger(POSITION_TICKET));
        ClosePosition(PositionGetInteger(POSITION_TICKET));
        }
       }
      }
     }
    class=class="str">"cmt">// Open a sell position
    class="type">class="kw">double openPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);
    class="type">class="kw">double atrMultiplier = ATRmultiplier;
    OpenPosition(ORDER_TYPE_SELL, openPrice, atrMultiplier);
    }
  IndicatorRelease(fastMA_current);
  IndicatorRelease(slowMA_current);
  IndicatorRelease(fastMA_previous);
  IndicatorRelease(slowMA_previous);
}

EURUSD 一个月实跑:自优化开与关的差距

拿 EURUSD 做对照,取 2024 年 4 月 20 日至 5 月 20 日这一段,时间间隔固定为 1 天,分别跑启用与未启用自优化的同一套逻辑。 未开自优化时,这 30 天里账户没有任何成交——策略在样本内完全沉默,等于空转。 开了自优化的那一份,起始先做一次自优化拟合,随后在 40 天周期节点上触发重新优化(该重优化点落在所研究时段之外)。从结果看,自优化版本明显更可能持续产出信号,关掉则大概率全程零交易。外汇与贵金属属高杠杆品种,这种对照仅说明机制差异,不预示任何收益。

◍ 把工具请下神坛

EA 自优化的核心价值不在「自动赚钱」,而在把参数维护从手工苦力变成可复现流程。前面几节给出的 MA 交叉案例中,用 Python 做 grid / random search 回测,再借 MQL5 把重优化周期写进 EA——评论区有人照搬参数却没交易,作者点出是重优化天数设成了 22 天而样例该用 16 天,这种细节只能自己跑一遍 MT5 才锁得住。 外汇与贵金属自带高杠杆与跳空风险,自优化降低的是「参数过期」的概率,不是消除账户回撤的可能。把这套机制当校验器而非印钞机,才接近原文里说的「信心与安心」。 下次开 MT5 载入 Brute-Force_0031.mq5,先把重新优化间隔改成 16 天跑一轮 2023 年 EURUSD 数据,看 equity 曲线和裸跑版本的差值,比读十篇综述都实在。

把回测比对交给小布盯盘
这些优化前后的曲线对照与参数扫描结果,小布盯盘的AIGC看板已内置模板,打开对应品种页就能直接加载历史数据跑一遍,你只管看分歧点。

常见问题

暴力适合参数少、组合可穷举的场景,随机搜索在维度高时更快出近似解;实务上先用随机粗筛再暴力细搜更稳。
趋势市收益明显,震荡市优化只能降低假信号频率,无法根除;概率上仍可能连续止损,需配合风控。
目前看板支持导入参数区间做可视化扫描与开闭优化对照,自动化调度需自行用脚本桥接,小布负责呈现与告警。
看样本外与样本内曲线背离度,若历史拟合极好而前向测试陡降,大概率过拟合,应收缩参数空间重跑。