骆驼算法(CA)(基础篇)
◍ 骆驼算法在 MT5 里的落地起点
骆驼算法(Camel Algorithm,CA)是一套基于元启发式的优化思路,被移植进 MetaTrader 5 后主要用于EA参数寻优与信号过滤。它不像网格或马丁那样直接押注价格方向,而是把解空间当成「地形」去爬,适合多参数组合下的非凸问题。 该系列首篇发布于 2026 年 5 月 18 日 14:59(MT5 社区时间),作者 Andrey Dik,原文节点显示 302 次浏览、0 条评论——说明这套实现当时还停留在「丢出来看有人测没」的阶段,没经过大规模实盘讨论。 从工程视角看,CA 在 MT5 的落点分三块:引言里的动机说明、算法实现的核心代码、以及脱敏后的回测结果。接下来要做的,是打开 MT5 的 MetaEditor,把它的寻优循环和你的品种参数接上,先跑一轮离线优化看收敛曲线再谈别的。外汇与贵金属杠杆品种波动剧烈,任何算法优化结果都只是历史概率,实盘前必须用策略测试器做样本外验证。
骆驼算法从哪来、模了什么
- 年,穆罕默德·哈立德·易卜拉欣与拉姆齐·萨利姆·阿里两位学者正式发表了骆驼算法(CA)。它属于生物启发式优化算法的一类,思路是把骆驼在沙漠里的存活与移动策略变成数学搜索规则。
CA 建模的核心机制包括:温度对行动的影响、水与食物在群体中的调配、个体耐力上限、绿洲效应(对应解空间里的高潜力区),以及驼队之间的协同交互。这些机制共同决定算法在迭代中怎么探点和避坑。 按本系列惯例,这一篇会拆原版 CA 的内部逻辑,再做一版改进,然后在标准测试函数上跑两个版本。跑完的结果会进我们的智能优化算法综合排名表,方便你横向比性能。外汇与贵金属市场波动剧烈、杠杆风险高,这类算法仅作策略研究参考,实盘须自行验证。
「把驼队寻源写成可跑的 C++ 类」
骆驼算法(CA)的寻源逻辑落到 MT5,就是一只继承 C_AO 的 C_AO_CAm 类。它把温度、供给、耐力做成每匹骆驼的独立数组,规模由 popSize 决定;Tmin/Tmax 框定温度随机区间,omega 控供给衰减,dyingRate 管淘汰,alpha 调绿洲可见度。这些都能在构造或 SetParams 里改,不用重编译。 Init 先调标准初始化锁住变量范围和步长,失败就直接返 false;随后按种群规模给 temperature[]、supply[]、endurance[] 开内存,initialSupply 与 initialEndurance 通常取 1.0,traveledSteps 清零、totalSteps 接迭代轮数。种群初始化不是堆随机点就完事——InitializePopulation 在可行域均匀撒点后,会把坐标舍到最接近步长,保证离散约束不被破。 每步 Moving 里先 traveledSteps++,再串起四件事:UpdateFactors 算 journeyRatio=traveledSteps/totalSteps,温度在 [Tmin,Tmax] 随机,supply[i] 乘 (1-omega*journeyRatio),endurance[i] 再乘 (1-temp/Tmax)*(1-journeyRatio);UpdatePositions 让骆驼朝最优解偏移并叠 [-1,1] 随机游走;ApplyOasisEffect 在随机数>1-alpha 且新适应度更优时,把 supply 和 endurance 重置回初始值;最后 Revision 扫一遍种群更新 fB 与 cB。 改进版有个实打实的改动值得在 MT5 里验证:原始版对整只骆驼统一判消亡、完全随机重生;CAm 改成逐维独立判消亡,并用 GaussDistribution 以全局最优解为中心生成新位置。这意味着你把 dyingRate 调高时,种群不会整匹消失,而是围绕 cB 做高斯扰动,局部开发更聚焦。外汇与贵金属参数优化属高风险场景,回测过拟合概率不低,建议先用历史段跑 popSize=30、omega=0.1 的默认组对照。
class=class="str">"cmt">//—————————————————————————————————————————————————————————————————————————————— class C_AO_CAm : class="kw">public C_AO {
◍ 骆驼算法类的初始化与参数绑定
这段 C_AO_CAm 构造函数把「骆驼算法 M」的整套可调旋钮在实例化时就写死了:种群规模 popSize=50 表示驼队数量,温度区间 Tmin=50、Tmax=100 控制搜索激进程度,omega=0.8 是补给负载因子,dyingRate=0.01 为骆驼淘汰率,alpha=0.9 管绿洲可见度。 构造函数里用 ArrayResize(params,6) 开出一个 6 元参数数组,再把上面 6 个变量名和值逐一塞进 params[0]~params[5]。SetParams() 则是反向操作——从 params 数组读回数值赋给类成员,意味着外部 UI 改了 params 后调一次 SetParams 就能热更新算法参数,不用重新 new 对象。 Init() 声明接收区间最小值、最大值、步长三个 double 引用数组,外加默认 0 的 epochs 迭代轮数;Moving() 和 Revision() 留作种群移动与淘汰的公开接口。外汇与贵金属市场波动剧烈、杠杆风险高,这类启发式优化器仅用于离线调参或策略研究,实盘前务必在 MT5 策略测试器里用历史数据回测验证稳定性。
class="kw">public: class=class="str">"cmt">//-------------------------------------------------------------------- ~C_AO_CAm() { } C_AO_CAm() { ao_name = "CA"; ao_desc = "Camel Algorithm M"; ao_link = "[MQL5官方文档] popSize = class="num">50; class=class="str">"cmt">// population size(camel caravan) Tmin = class="num">50; class=class="str">"cmt">// minimum temperature Tmax = class="num">100; class=class="str">"cmt">// maximum temperature omega = class="num">0.8; class=class="str">"cmt">// load factor for &class="macro">#x27;supply&class="macro">#x27; dyingRate = class="num">0.01; class=class="str">"cmt">// camels&class="macro">#x27; "death" rate alpha = class="num">0.9; class=class="str">"cmt">// visibility parameter for the oasis effect ArrayResize(params, class="num">6); params [class="num">0].name = "popSize"; params [class="num">0].val = popSize; params [class="num">1].name = "Tmin"; params [class="num">1].val = Tmin; params [class="num">2].name = "Tmax"; params [class="num">2].val = Tmax; params [class="num">3].name = "omega"; params [class="num">3].val = omega; params [class="num">4].name = "dyingRate"; params [class="num">4].val = dyingRate; params [class="num">5].name = "alpha"; params [class="num">5].val = alpha; } class="type">void SetParams() { popSize = (class="type">int)params [class="num">0].val; Tmin = params [class="num">1].val; Tmax = params [class="num">2].val; omega = params [class="num">3].val; dyingRate = params [class="num">4].val; alpha = params [class="num">5].val; } class="type">bool Init(class="kw">const class="type">class="kw">double &rangeMinP [], class=class="str">"cmt">// minimum values class="kw">const class="type">class="kw">double &rangeMaxP [], class=class="str">"cmt">// maximum values class="kw">const class="type">class="kw">double &rangeStepP [], class=class="str">"cmt">// step change class="kw">const class="type">int epochsP = class="num">0); class=class="str">"cmt">// number of epochs class="type">void Moving(); class="type">void Revision(); class=class="str">"cmt">//---------------------------------------------------------------------------- class="type">class="kw">double Tmin; class=class="str">"cmt">// minimum temperature class="type">class="kw">double Tmax; class=class="str">"cmt">// maximum temperature class="type">class="kw">double omega; class=class="str">"cmt">// load factor for &class="macro">#x27;supply&class="macro">#x27; class="type">class="kw">double dyingRate; class=class="str">"cmt">// camels&class="macro">#x27; "death" rate