种群优化算法:猴子算法(MA)(基础篇)
📘

种群优化算法:猴子算法(MA)(基础篇)

第 1/2 篇

猴子算法在 MT5 里的种群优化思路

猴子算法(Monkey Algorithm,MA)是一类受种群智能启发的全局优化方法,在 MQL5 的回测与参数寻优场景里,常被用来替代网格遍历,以降低计算开销。它的核心假设是:一组随机初始化的「猴子」在解空间里通过攀爬、观望、跳跃三类动作,逐步逼近更优参数组合。 在 MT5 内置的遗传优化器之外,手动实现 MA 能让你对收敛阈值和种群规模有完全控制权。一个常见设定是种群规模 30、最大迭代 200,在 EURUSD H1 上做均线周期寻优时,相比全网格搜索可节省约 60% 的回测时间,但存在早熟收敛倾向,需配合变异概率调节。 外汇与贵金属品种点差跳变频繁,用该类算法做优化属于高风险实验,实盘前务必在模拟环境复跑验证。

◍ 猴子算法怎么模拟爬山找食

猴子算法(MA)是 R. Zhao 和 W.Tang 在 2007 年提出的元启发式搜索方法,核心灵感来自猴子在山上移动跳跃找食物:山越高、山顶食物越多,于是把适应度函数地形当成山体,最高峰即全局最大化问题的解。 从当前位置起,每只猴子先持续向上爬直到登顶,这一步不断抬高目标函数值;随后向随机方向做局部跳跃,试图撞上更高的山头并再次攀爬。攀爬加局部跳跃循环若干次后,它认为附近地域已探明。 为避免困在本地最优,猴子会做一次长距离全局跳跃,去未知空间重新探索。整个“攀爬—局部跳—全局跳”按参数重复指定代数,种群见过的最高顶点即为输出解。MA 结构简单、可靠性较高,擅长抠出局部最优,但攀登阶段极耗算力。 它的时间主要消耗在攀爬寻局部解,而非像别的进化算法那样铺在广域搜索;这点既是优点也是瓶颈,下一节会拆到表示、初始化与跳跃的具体实现。

「猴子算法怎么在MT5里落地」

猴子算法(MA)的本质是一群代理在搜索空间里乱跳找最高适应度,伪代码里七步循环:随机撒点、测高、局部跳、更好就续跳、局部极限耗尽就全局跳、重复。真正决定收敛质量的不是局部跳,而是全局跳能不能把种群拽出局部极值——实测局部跳对收敛影响很小,全局跳才是脱困关键。 原始 MA 让猴子沿「当前位置—全群几何中心」连线跳,方向可朝中心也可反向。作者在实验中确认:反向跳有约 50% 概率远离全局最优,而跳出中心之外比不跳或反向更有利。团伙不时越过几何中心、整体朝富食区漂移,这种「团伙移动」在动画里清晰可见,原版没有这效果且结果更差。 代码层用 S_Monkey 结构装单只猴子:c[] 当前坐标、cB[] 最佳食物坐标、h/hB 当前与最高高度、lCNT 局部跳计数。C_AO_MA 类里 m[] 是猴群数组,不需要排序,所以方法体都很短。Init() 把最佳品质用最小双精度值初始化;Moving() 首次迭代随机撒点,算 cc[] 坐标中心(算术平均),局部跳半径由 bCoefficient 按维度重算。 全局跳坐标公式 m[monk].c[c] = cc[c] + v[c] * pow(r2, -2.0),r2 取 1~20,这其实是 Levy 飞行:中心附近命中概率高、远处低,平衡探索与开发。越界就折返映射。Revision() 在算完适应度后更新全局解,局部跳要查改善、全局跳不查直接续跳。开 MT5 把下面结构抄进 EA,调 bCoefficient 和猴子数就能跑自己的标的(外汇/贵金属波动大,参数过拟合风险高,建议先历史回测)。

MQL5 / C++
<span class="comment">class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————</span>
<span class="keyword">class="kw">struct</span> S_Monkey
{
&nbsp;&nbsp;<span class="keyword">class="type">class="kw">double</span> c&nbsp;&nbsp;[]; <span class="comment">class=class="str">"cmt">//coordinates</span>
&nbsp;&nbsp;<span class="keyword">class="type">class="kw">double</span> cB []; <span class="comment">class=class="str">"cmt">//best coordinates</span>
&nbsp;&nbsp;<span class="keyword">class="type">class="kw">double</span> h;&nbsp;&nbsp;&nbsp;&nbsp; <span class="comment">class=class="str">"cmt">//height of the mountain</span>
&nbsp;&nbsp;<span class="keyword">class="type">class="kw">double</span> hB;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">class=class="str">"cmt">//best height of the mountain</span>
&nbsp;&nbsp;<span class="keyword">class="type">int</span>&nbsp;&nbsp;&nbsp;&nbsp;lCNT;&nbsp;&nbsp;<span class="comment">class=class="str">"cmt">//local search counter</span>
};
<span class="comment">class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————</span>
<span class="comment">class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————</span>
<span class="keyword">class</span> C_AO_MA
{
&nbsp;&nbsp;<span class="comment">class=class="str">"cmt">//----------------------------------------------------------------------------</span>
&nbsp;&nbsp;<span class="keyword">class="kw">public</span>: S_Monkey m&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; []; <span class="comment">class=class="str">"cmt">//monkeys</span>
&nbsp;&nbsp;<span class="keyword">class="kw">public</span>: <span class="keyword">class="type">class="kw">double</span> rangeMax&nbsp;&nbsp;[]; <span class="comment">class=class="str">"cmt">//maximum search range</span>
&nbsp;&nbsp;<span class="keyword">class="kw">public</span>: <span class="keyword">class="type">class="kw">double</span> rangeMin&nbsp;&nbsp;[]; <span class="comment">class=class="str">"cmt">//minimum search range</span>
&nbsp;&nbsp;<span class="keyword">class="kw">public</span>: <span class="keyword">class="type">class="kw">double</span> rangeStep []; <span class="comment">class=class="str">"cmt">//step search</span>
&nbsp;&nbsp;<span class="keyword">class="kw">public</span>: <span class="keyword">class="type">class="kw">double</span> cB&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[]; <span class="comment">class=class="str">"cmt">//best coordinates</span>
&nbsp;&nbsp;<span class="keyword">class="kw">public</span>: <span class="keyword">class="type">class="kw">double</span> hB;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="comment">class=class="str">"cmt">//best height of the mountain</span>
&nbsp;&nbsp;<span class="keyword">class="kw">public</span>: <span class="keyword">class="type">void</span> Init(<span class="keyword">class="kw">const</span> <span class="keyword">class="type">int</span>&nbsp;&nbsp;&nbsp;&nbsp;coordNumberP,&nbsp;&nbsp;&nbsp;&nbsp; <span class="comment">class=class="str">"cmt">//coordinates number</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="keyword">class="kw">const</span> <span class="keyword">class="type">int</span>&nbsp;&nbsp;&nbsp;&nbsp;monkeysNumberP,&nbsp;&nbsp; <span class="comment">class=class="str">"cmt">//monkeys number</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="keyword">class="kw">const</span> <span class="keyword">class="type">class="kw">double</span> bCoefficientP,&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">class=class="str">"cmt">//local search coefficient</span>

猴群算法的类成员与初始化落点

这套自适应移动平均的优化内核用了一个 C_AO_MA 类,把坐标维度、猴群规模、局部搜索与跳跃系数全部收进私有成员。coordNumber 决定解空间维度,monkeysNumber 是种群规模,bCoefficient 与 vCoefficient 分别控制局部搜索步长和全局跳跃强度,jumpsNumber 限定每次迭代的跳跃次数。 Init 函数承担参数注入和随机数种子重置。MathSrand((int)GetMicrosecondCount()) 用微秒级计时做种子,避免回测时每次跑出同一串伪随机序列;hB 初始化为 -DBL_MAX 表示尚未记录最优适应度,revision 置 false 代表首轮不触发修正逻辑。 数组 rangeMax、rangeMin、rangeStep、b 都按 coordNumber 用 ArrayResize 展开。这意味着你改 coordNumber 前必须确认调用 Init 时传入的维度一致,否则后面寻优会越界报错。外汇与贵金属市场波动剧烈,这类算法参数对过拟合敏感,实盘前建议在 MT5 用历史数据多周期验证。

MQL5 / C++
class="kw">const class="type">class="kw">double vCoefficientP,    class=class="str">"cmt">//jump coefficient
                    class="kw">const class="type">int     jumpsNumberP);    class=class="str">"cmt">//jumps number
  class="kw">public: class="type">void Moving();
  class="kw">public: class="type">void Revision();
  class=class="str">"cmt">//----------------------------------------------------------------------------
  class="kw">private: class="type">int     coordNumber;       class=class="str">"cmt">//coordinates number
  class="kw">private: class="type">int     monkeysNumber;     class=class="str">"cmt">//monkeys number
  class="kw">private: class="type">class="kw">double b [];               class=class="str">"cmt">//local search coefficient
  class="kw">private: class="type">class="kw">double v [];               class=class="str">"cmt">//jump coefficient
  class="kw">private: class="type">class="kw">double bCoefficient;       class=class="str">"cmt">//local search coefficient
  class="kw">private: class="type">class="kw">double vCoefficient;       class=class="str">"cmt">//jump coefficient
  class="kw">private: class="type">class="kw">double jumpsNumber;        class=class="str">"cmt">//jumps number
  class="kw">private: class="type">class="kw">double cc [];              class=class="str">"cmt">//coordinate center
  class="kw">private: class="type">bool   revision;
  class="kw">private: class="type">class="kw">double SeInDiSp(class="type">class="kw">double In, class="type">class="kw">double InMin, class="type">class="kw">double InMax, class="type">class="kw">double Step);
  class="kw">private: class="type">class="kw">double RNDfromCI(class="type">class="kw">double min, class="type">class="kw">double max);
  class="kw">private: class="type">class="kw">double Scale(class="type">class="kw">double In, class="type">class="kw">double InMIN, class="type">class="kw">double InMAX, class="type">class="kw">double OutMIN, class="type">class="kw">double OutMAX, class="type">bool revers);
};
class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————
class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————
class="type">void C_AO_MA::Init(class="kw">const class="type">int     coordNumberP,    class=class="str">"cmt">//coordinates number
                    class="kw">const class="type">int     monkeysNumberP,  class=class="str">"cmt">//monkeys number
                    class="kw">const class="type">class="kw">double bCoefficientP,    class=class="str">"cmt">//local search coefficient
                    class="kw">const class="type">class="kw">double vCoefficientP,    class=class="str">"cmt">//jump coefficient
                    class="kw">const class="type">int     jumpsNumberP)    class=class="str">"cmt">//jumps number
{
  MathSrand((class="type">int)GetMicrosecondCount()); class=class="str">"cmt">// reset of the generator
  hB        = -DBL_MAX;
  revision = class="kw">false;
  coordNumber   = coordNumberP;
  monkeysNumber = monkeysNumberP;
  bCoefficient  = bCoefficientP;
  vCoefficient  = vCoefficientP;
  jumpsNumber   = jumpsNumberP;
  ArrayResize(rangeMax,  coordNumber);
  ArrayResize(rangeMin,  coordNumber);
  ArrayResize(rangeStep, coordNumber);
  ArrayResize(b,         coordNumber);

常见问题

算法把每只猴子当作一个解,通过爬步在局部向更优值移动,再借望跳和翻跳跳出局部,类似猴群找食的搜索过程。
先定义种群规模与边界,再初始化每只猴子的随机落点,之后循环执行爬步、望跳、翻跳三步即可。
小布可自动跑种群优化类诊断,把参数搜索和落点分布可视化,你只需看结果调参,不用手写循环。
至少要有种群数量、维度上下界、步长与最大迭代,以及存每只猴子位置和适应度的数组。
纯随机可能扎堆或越界,建议按边界均匀撒点并做越界拉回,能让前期搜索更稳。