群体算法的混合 -顺序结构和并行结构·进阶篇
◍ 混合灰狼与协方差算法的种群迁移
这段实现把 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 代附近适应度曲线斜率变化——大概率来自优化器主导权交接。外汇与贵金属参数寻优属高风险实验,回测优不代表实盘能复现。
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,你会看到信号明显变少但单笔持仓时间拉长——这就是调参数能立刻观察到的直观差异。
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 把混合逻辑拆开,自己改一处代理交换频率,跑一遍优化报告,比盲信排名表更有用。外汇与贵金属市场高波动,任何算法组合都只是概率工具。