种群优化算法:蚁群优化(ACO)(基础篇)
「用蚁群算法给 MT5 找参数组合」
蚁群优化(ACO)本质是把「蚂蚁找最短路径」的群体行为搬进数值优化:一群虚拟蚂蚁在解空间里乱走,留下信息素,后续蚂蚁倾向跟着浓信息素走,迭代几代后路径收敛到较优解。在 MT5 里,这适合替交易者搜 EA 的参数组合,而不是手动一格格试。 外汇与贵金属杠杆高、滑点跳空频繁,ACO 搜出的参数只在历史样本内「倾向」更稳,实盘仍可能失效,别当圣杯。 原文示例文章发布于 2023-02-14,累计浏览 2284 次,作者 Andrey Dik 把它拆成四块:概述、算法原理、改编版、测试结果。你可以直接开 MT5 搜同名脚本,先跑概述里的 demo 看信息素矩阵怎么更新。
◍ 蚁群怎么靠信息素找出最短路
- 年 Marco Dorigo 在博士论文里把蚁群集体智慧写成数学模型,后来叫蚁群优化(ACO)。核心机制是 stigmergy(信源动作):个体不直接对话,而是改环境留痕迹,后来者读痕迹做决策。蚂蚁用的痕迹就是信息素。
具体过程很直白:蚂蚁找食会在地面留信息素,发现食物后往回走继续 deposit,量和食物多少、品质挂钩。路上信息素越浓,下一只蚂蚁选这条道的概率越高;走的人多,浓的更浓,正反馈就起来了。 给个可验证的思想实验:两道从巢到食物,初始都没信息素,选率各 50%。假设甲走短道、乙走长道,短道那只先到食先回巢,沿途留素。第三只出门看浓度,自然挑短道。来回几轮后,短道信息素积累更快,蚁群基本收敛到短路径。这跟 MT5 里优化参数时「好解周围样本更密」的思路同源。 ACO 本质是种群随机搜索,靠信息素挥发+沉积做动态权衡:浓则趋之,挥发则避免陷局部。外汇/贵金属这种高噪声、高风险市场若套用,只适合做参数空间探索的辅助,别当信号源。
蚁群怎么在图里找最短环
ACO 把优化问题先转成加权图上的最佳路径搜索:一组软件蚂蚁(agent)在图上随机游走,逐步拼出解。游走不是纯随机,而是受信息素模型牵引——挂在边线或节点上的参数,运行过程中被蚂蚁不断改写。 以旅行推销员问题(TSP)为例:N 个城市、已知两两距离,目标是找一条只进每城一次、总长最短的闭合路径。构造图是完全连通图,顶点数 = 城市数,边线长度正比于城市距离,边线上同时挂信息素值 τ 和启发式值 η。 单只蚂蚁从随机顶点出发,每步按概率选下一条未访问顶点的边;选中的概率随 τ·η 增大而升高。走完所有顶点即得到一个解。一轮里所有蚂蚁走完后,全局边线信息素先按百分比蒸发,再按蚂蚁所走路径长短追加沉积——短路径补得多。 一个可当场验证的几何测试用例:把所有点摆成一个正圆,最短环永远就是那个圆周。在 MT5 里若用 ACO 优化参数组合,可先拿这种圆点布局跑通,确认算法收敛到理论最短,再换真实样本外数据。 外汇/贵金属参数优化属高风险,历史回测最优不代表实盘稳健,ACO 给出的只是概率倾向更优的解。
「把信息素撒在坐标点上而非路径上」
经典 ACO 的几种变体(AS、ACS、精英蚂蚁、MMAS、Asrank、PACO、COAC、递归蚁群)都是为图节点优化设计的,依赖固定坐标和顺序通路。交易品种优化里坐标不固定、甚至高度相似,直接套用会卡死——原文明确说这类算法「不适用于我们的任务」,得另起一套连续空间蚁群。 新思路是把信息素标在蚂蚁所在的点,而不是走过的边。适应度函数值就是该点的信息素量,蚂蚁倾向往信息素多的坐标挪;但所有蚂蚁若全挤到一个点,那个点未必是函数极值,所以还要算当前位置到目标点的距离,距离越短越优先。 光有「信息素量」和「距离」两个准则,蚂蚁仍沿假想边线移动、没有进展。于是引入 PheromoneRadius_P 作为信息素感知半径,让蚂蚁能「溜过」目标点获得自由度;再用 PathDeviation_P 允许沿任意坐标偏离位移矢量,正负增量和模长都可不同,多维探索才算放开。 一次迭代的步序是:随机布蚁 → 算各点信息素(适应度)→ 算蚁间距离 → 选首选移动点 → 算 AR 矢量上落点概率 → 算新坐标 → 回到第二步直到停止。三维里 BR = AB × PheromoneRadius_P,AR 上更靠近 B 的概率更高,n 维同理。 代码层先用结构描述单只蚂蚁:c 是当前坐标,cLast 为上一代坐标,cB 是所有代最佳坐标,f 为当前信息素,fB 为历史最大信息素;构造函数里 f 和 fB 都初始化成 -DBL_MAX,保证任何真实适应度都能覆盖。蚁群存为 ants[] 数组,配对距离放 S_Paths 结构,主类 C_AO_ACO 公开 InitAnts()、Preparation()、Dwelling() 三个方法,私密含 GenerateRNDants() 与 AntsMovement()。
<span class="comment">class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————</span> <span class="keyword">class="kw">struct</span> S_Ants { <span class="keyword">class="type">class="kw">double</span> cLast []; <span class="comment">class=class="str">"cmt">//last coordinates</span> <span class="keyword">class="type">class="kw">double</span> c []; <span class="comment">class=class="str">"cmt">//coordinates</span> <span class="keyword">class="type">class="kw">double</span> cB []; <span class="comment">class=class="str">"cmt">//best coordinates</span> <span class="keyword">class="type">class="kw">double</span> f; <span class="comment">class=class="str">"cmt">//pheromone of the current coordinates</span> <span class="keyword">class="type">class="kw">double</span> fB; <span class="comment">class=class="str">"cmt">//pheromone of the best coordinates</span> S_Ants() { f = -<span class="macro">DBL_MAX</span>; fB = -<span class="macro">DBL_MAX</span>; } }; <span class="comment">class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————</span> <span class="keyword">class="kw">struct</span> S_Paths { <span class="keyword">class="type">class="kw">double</span> a []; }; <span class="comment">class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————</span> <span class="keyword">class</span> C_AO_ACO { <span class="keyword">class="kw">public</span>: <span class="comment">class=class="str">"cmt">//----------------------------------------------------------------------------</span> S_Ants ants []; <span class="comment">class=class="str">"cmt">//ants</span> <span class="keyword">class="type">class="kw">double</span> rangeMax []; <span class="comment">class=class="str">"cmt">//maximum search range</span> <span class="keyword">class="type">class="kw">double</span> rangeMin []; <span class="comment">class=class="str">"cmt">//manimum search range</span> <span class="keyword">class="type">class="kw">double</span> rangeStep []; <span class="comment">class=class="str">"cmt">//step search</span> <span class="keyword">class="type">class="kw">double</span> cB []; <span class="comment">class=class="str">"cmt">//best coordinates</span> <span class="keyword">class="type">class="kw">double</span> fB; <span class="comment">class=class="str">"cmt">//pheromone of the best coordinates</span>