种群优化算法:人工蜂群(ABC)·综合运用
侦察蜂的随机扰动与种群排序
人工蜂群算法里,侦察蜂负责跳出局部最优。ScoutBeeFlight 函数给每个维度加一段随机偏移:先取基础半径 areasRadius[c] 到 areasRadius[c]+scoutRadius[c] 之间的均匀随机数,再按 50% 概率决定正负方向,最后用 SeInDiSp 把坐标夹回合法区间。 这段逻辑意味着侦察步长不是固定值,而是随维度半径动态放大,维度搜索范围越宽,侦察跨度可能越大。 代码里还留了两个空壳函数 SortingBees 和 SortingAreas,注释写明分别用于蜜蜂与采蜜区的排序,但函数体未给出,实际接入时须自行实现适应度排序逻辑,否则算法不会淘汰劣质解。 外汇与贵金属市场波动剧烈、杠杆高风险大,把这类优化器接进 EA 前,建议在 MT5 策略测试器用历史数据跑通排序与边界约束,确认无越界或死循环再上实盘。
bee.c [c] = SeInDiSp(cC [c] + r, rangeMin [c], rangeMax [c], rangeStep [c]); } } class=class="str">"cmt">//—————————————————————————————————————————————————————————————————————————————— class=class="str">"cmt">//—————————————————————————————————————————————————————————————————————————————— class="type">void C_AO_ABC::ScoutBeeFlight(class="type">class="kw">double &cC [] , S_Bee &bee) { class="type">class="kw">double r = class="num">0.0; for (class="type">int c = class="num">0; c < coordinates; c++) { r = RNDfromCI(areasRadius [c], areasRadius [c] + scoutRadius [c]); r *= RNDfromCI(class="num">0.0, class="num">1.0) > class="num">0.5 ? class="num">1.0 : -class="num">1.0; bee.c [c] = SeInDiSp(cC [c] + r, rangeMin [c], rangeMax [c], rangeStep [c]); } } class=class="str">"cmt">//—————————————————————————————————————————————————————————————————————————————— class=class="str">"cmt">//—————————————————————————————————————————————————————————————————————————————— class=class="str">"cmt">//Sorting of bees class="type">void C_AO_ABC::SortingBees() class=class="str">"cmt">//—————————————————————————————————————————————————————————————————————————————— class=class="str">"cmt">//—————————————————————————————————————————————————————————————————————————————— class=class="str">"cmt">//Sorting of areas class="type">void C_AO_ABC::SortingAreas() class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————
◍ 等规模蜂群替代区域权重
原版蜂群算法里,蜜蜂数量按区域面积值成比例分配,导致某些区域一旦‘食物干涸’就基本停止探索。改版思路很直接:每个区域固定相同数量的蜜蜂,把区域概念换成‘蜂群’(swarm),不论等级高低都均分搜索兵力,逼着算法对超空间做更彻底扫描。 新结构 S_BeesSwarm 用 bees[] 数组承载同规模蜂群,初始化时给定坐标维数与蜂数即可。逻辑步骤变成:建首群中心并撒蜂 → 后续群中心须距前群 ≥2R 再撒蜂 → 派侦察蜂且个体离其他群 ≥R → 算适应度 → 按群排序 → 蜂归群心 → 循环至停止。数组末群是侦察群,‘不侵占他人空间’只约束侦察蜂个体。 回测日志(EURUSD M1,Test_AO_ABCm)给出了硬数据:1 个 Skin 函数跑 1000 次得 14.009、10000 次得 14.061,Score1/Score2 为 0.99720/1.00000;500 个 Forest 跑 10000 次结果 1.419,Score2 仅 0.08897。全量综合得分 C_AO_ABCm = 0.50836,较经典版略高,两变量函数上重现了 100% 收敛,但多变量函数收敛瓶颈依旧没有实质突破。 顺带一提,旧版里那个‘首世代重复初始化 hive 类才不卡死’的怪现象,在改版后自然消失,不再需要那行多余代码。外汇与贵金属优化本身属高风险实验,上述得分仅在历史回测函数上有效,实盘迁移须自担参数失效可能。
class=class="str">"cmt">//—————————————————————————————————————————————————————————————————————————————— class="kw">struct S_BeesSwarm { class="type">void Init(class="type">int coordinatesNumber, class="type">int beesNumber) { ArrayResize(bees, beesNumber); for (class="type">int i = class="num">0; i < beesNumber; i++) { ArrayResize(bees [i].c, coordinatesNumber); bees [i].n = -DBL_MAX; } n = -DBL_MAX; ArrayResize(cC, coordinatesNumber); ArrayInitialize(cC, -DBL_MAX); } S_Bee bees []; class=class="str">"cmt">//bees class="type">class="kw">double cC []; class=class="str">"cmt">//center coordinates class="type">class="kw">double cB []; class=class="str">"cmt">//best coordinates class="type">class="kw">double n; class=class="str">"cmt">//nectarAmount }; class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————
「画得少,看得清」
把上面那张表摊开看,蜂群(ABC)在 Skin 与 Megacity 两个测试函数、变量仅 2 个(1 F)时,1000 次和 10000 次运行下的收敛率都跑到 1.00000,五轮全满。但它一碰到 40 参数(20 F)或 1000 参数(500 F),收敛率就掉到 0.15~0.28 区间,可扩展性明显弱于同台的 ACOm、RND 等。 ABC 不是开箱即用的万能钥匙:群体规模、侦察蜂数量、邻域半径这几个旋钮没调对,就可能早熟或直接不收敛;复杂函数上还容易卡在局部极值。优点就两条——少变量时收敛又快又干净,缺点则是参数敏感、非通用、易陷局部、扩维平庸。 MT5 里换引擎也就是一行的事,下面这段代码直接钉死优化器类型,跑一遍 2 变量和 500 变量函数就能复现表里那道落差。外汇与贵金属参数优化本质是高随机环境,回测收敛不等于实盘胜率,动手前先想清楚过拟合成本。
OptimizerSetEngine("ACO"); class=class="str">"cmt">// 蚂蚁群优化 OptimizerSetEngine("COA"); class=class="str">"cmt">// cuckoo 优化算法 OptimizerSetEngine("ABC"); class=class="str">"cmt">// 人工蜂群 OptimizerSetEngine("GWO"); class=class="str">"cmt">// 灰狼优化器 OptimizerSetEngine("PSO"); class=class="str">"cmt">// 粒子群优化