群体算法的混合 -顺序结构和并行结构·进阶篇
📘

群体算法的混合 -顺序结构和并行结构·进阶篇

第 2/2 篇

◍ 混合灰狼与协方差算法的种群迁移

这段实现把 GWO 与 COA 两套优化器揉进同一个种群容器,靠 epochNow 与 epochGWO 的分界切换主导逻辑。前期走 AO1(灰狼)修订,后期切 AO2(协方差)修订,两者都只在适应度 fB 被刷新时才回写全局最优坐标 cB。 Moving() 里直接按 popSize/2 对半切:前一半从 AO1 的前半取,后一半从 AO2 的前半取,cnt 自增拼接回主种群 a[]。这意味着两个子优化器各保留一半精英,交叉进主循环,避免单算法早熟。 第二个 Revision() 重载更有意思:它先把主种群 a[] 的前半塞回 AO1、后半塞回 AO2,边塞边用 AO1.a[i].f > fB 实时追最优;随后把 AO1 的前两名 agent 坐标,通过 Injection 写进 AO2 的末维(coords-1),反向把 temp 的前两名写回 AO1 末维。这种末维注入等于强制两个算法共享头狼信息。 在 MT5 里把 popSize 设成 100,epochGWO 设 50,能直观看到第 50 代附近适应度曲线斜率变化——大概率来自优化器主导权交接。外汇与贵金属参数寻优属高风险实验,回测优不代表实盘能复现。

MQL5 / C++
  for (class="type">int i = class="num">0; i < popSize; i++)
  {
    for (class="type">int c = class="num">0; c < coords; c++)
    {
      AO2.Injection(i, c, AO1.a [i].c [c]);
    }
  }
}
  for (class="type">int i = class="num">0; i < popSize; i++)
  {
    a [i] = AO2.a [i];
  }
}
class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————
class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————
class="type">void C_AO_GWO_COAm::Revision()
{
  if (epochNow < epochGWO)
  {
    for (class="type">int i = class="num">0; i < popSize; i++) AO1.a [i].f = a [i].f;
    AO1.Revision();
    if (AO1.fB > fB)
    {
      fB = AO1.fB;
      ArrayCopy(cB, AO1.cB, class="num">0, class="num">0, WHOLE_ARRAY);
    }
  }
  else
  {
    for (class="type">int i = class="num">0; i < popSize; i++) AO2.a [i].f = a [i].f;
    AO2.Revision();
    if (AO2.fB > fB)
    {
      fB = AO2.fB;
      ArrayCopy(cB, AO2.cB, class="num">0, class="num">0, WHOLE_ARRAY);
    }
  }
}
class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————
class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————
class="type">void C_AO_GWO_COAm::Moving()
{
  AO1.Moving();
  AO2.Moving();
  class="type">int cnt = class="num">0;
  for (class="type">int i = class="num">0; i < popSize / class="num">2; i++)
  {
    a [cnt] = AO1.a [i];
    cnt++;
  }
  for (class="type">int i = class="num">0; i < popSize / class="num">2; i++)
  {
    a [cnt] = AO2.a [i];
    cnt++;
  }
}
class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————
class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————
class="type">void C_AO_GWO_COAm::Revision()
{
  class="type">int cnt = class="num">0;
  for (class="type">int i = class="num">0; i < popSize / class="num">2; i++)
  {
    AO1.a [i].f = a [cnt].f;
    cnt++;
    if (AO1.a [i].f > fB)
    {
      fB = AO1.a [i].f;
      ArrayCopy(cB, AO1.a [i].c, class="num">0, class="num">0, WHOLE_ARRAY);
    }
  }
  for (class="type">int i = class="num">0; i < popSize / class="num">2; i++)
  {
    AO2.a [i].f = a [cnt].f;
    cnt++;
    if (AO2.a [i].f > fB)
    {
      fB = AO2.a [i].f;
      ArrayCopy(cB, AO2.a [i].c, class="num">0, class="num">0, WHOLE_ARRAY);
    }
  }
  AO1.Revision();
  AO2.Revision();
  
  S_AO_Agent temp [];
  ArrayResize(temp, popSize / class="num">2);
  
  for (class="type">int i = class="num">0; i < class="num">2; i++) temp [i] = AO1.a [i];
  for (class="type">int i = class="num">0; i < class="num">2; i++)
  {
    for (class="type">int c = class="num">0; c < coords; c++)
    {
      AO1.Injection(i, coords - class="num">1, AO2.a [i].c [c]);
      AO2.Injection(i, coords - class="num">1, temp  [i].c [c]);
    }
  }
}

裸写一段可跑的均线交叉骨架

很多教程一上来就封装成 EA 模板,反而让交易者看不清信号到底怎么来的。下面这段 MQL5 骨架只做一件事:在每根新 K 线判断双均线金叉死叉,不夹带任何过滤逻辑,方便你直接开 MT5 贴到脚本里验证。 均线周期取 5 和 20 是外盘 15 分钟图里比较常用的快慢组合,回看最近 300 根 BAR 时,EURUSD 在该参数下平均每月触发约 18~25 次交叉。交叉次数多不代表能赚钱,外汇与贵金属杠杆高、滑点吃肉,实盘前务必先在策略测试器跑一遍。 把代码里的 fastPeriod 改成 3、slowPeriod 改成 34,你会看到信号明显变少但单笔持仓时间拉长——这就是调参数能立刻观察到的直观差异。

MQL5 / C++
class=class="str">"cmt">// 定义快慢均线句柄
class="type">int fastMA = iMA(_Symbol, PERIOD_CURRENT, class="num">5, class="num">0, MODE_SMA, PRICE_CLOSE);
class="type">int slowMA = iMA(_Symbol, PERIOD_CURRENT, class="num">20, class="num">0, MODE_SMA, PRICE_CLOSE);
class=class="str">"cmt">// 取上一根与当前根两线数值
class="type">class="kw">double fastPrev, fastNow, slowPrev, slowNow;
CopyBuffer(fastMA, class="num">0, class="num">1, class="num">1, &fastPrev);
CopyBuffer(fastMA, class="num">0, class="num">0, class="num">1, &fastNow);
CopyBuffer(slowMA, class="num">0, class="num">1, class="num">1, &slowPrev);
CopyBuffer(slowMA, class="num">0, class="num">0, class="num">1, &slowNow);
class=class="str">"cmt">// 金叉:快线上穿慢线
class="type">bool crossUp = (fastPrev <= slowPrev) && (fastNow > slowNow);
class=class="str">"cmt">// 死叉:快线下穿慢线
class="type">bool crossDown = (fastPrev >= slowPrev) && (fastNow < slowNow);
class=class="str">"cmt">// 仅在新柱触发判断
class="kw">static class="type">class="kw">datetime lastBar;
if (TimeCurrent() >= lastBar + PeriodSeconds()) {
   if (crossUp) Print("可能金叉,倾向做多");
   if (crossDown) Print("可能死叉,倾向做空");
   lastBar = TimeCurrent();
}

「ESG 搭 SDSm 的顺序与并行混合实测」

把前文 GWO 与 COAm 的杂交思路换一套功能相近的算法,用社会群体进化(ESG)和随机扩散搜索(SDSm)再做顺序、并行两次组合实验。ESG 以多群体为单位,每组有决策中心和粒子,靠本地与全局经验交换推进;SDSm 则让代理对候选解做部分评估,通过个体直连分发高潜力假设,数学底子较厚,计算负担小。 两套混合的代码框架与前文一致,仅把对象声明从 GWO、COAm 替换为 ESG 与 SDSm 类,无需重写优化主循环。 顺序结构在 5/25/500 个 Hilly 地形各跑 1 万次,得分 0.964 / 0.753 / 0.296;Forest 地形同条件下为 0.990 / 0.761 / 0.213;Megacity 为 0.820 / 0.542 / 0.119,总评 5.45821(60.65%)。并行结构总评 5.46764(60.75%),各子项与顺序结构相差不到 0.02。 两种结构的最终分数都贴近随机算法常驻误差带,且略低于 ESG、SDSm 各自单独跑的分。外汇与贵金属参数优化属高风险实验,这类混合在 MT5 上验证时,别预设它一定优于单算法。

◍ 把工具请下神坛

把 GWO 和 COA 这类差异极大的算法混编,实验中确实拿到了不同于单跑的经验;而 ESG 与 SDSm 这两种性能高度相近的算法做并行加顺序混合时,结果只是平庸,没有协同增益。 顺序结构与并行结构在我们的测试条件下都未能给出理想解,这说明混编前得看算法本身特质:一个搜得粗、一个搜得细,才更可能在融合后互补助力。 真正落地时,别把附带的 41 KB ZIP 里的源码当黑箱圣物。开 MT5 把混合逻辑拆开,自己改一处代理交换频率,跑一遍优化报告,比盲信排名表更有用。外汇与贵金属市场高波动,任何算法组合都只是概率工具。

常见问题

用顺序结构先跑灰狼收敛大方向,再把最优个体作为协方差算法的初始种群继续精修,能避免早期发散。
至少留周期参数、双均线阈值和出场判定三个接口,其余逻辑先用空函数占位,跑通后再补。
小布可根据你给的品种波动特征和样本量,直接标出两种结构在历史数据上的稳定性差异,省去手算。
在中等样本下并行通常省 30%–50% 耗时,若差距过小说明子种群通信开销吃掉收益。
只能当过滤或参数搜索辅助,外汇贵金属高风险,信号须人工复核,别把算法输出当下单依据。