群体优化算法:粒子群(PSO)(基础篇)
📘

群体优化算法:粒子群(PSO)(基础篇)

第 1/2 篇

◍ 粒子群优化在 MT5 里的落点

粒子群(PSO)本质是一群「粒子」在解空间里靠个体经验和群体经验反复修正位置,用来搜最优参数。把它搬进 MetaTrader 5,核心价值是替你跑 EA 参数寻优,而不是手动一格格试。 原文给出的系列示例发布于 2023 年 2 月 3 日,截至统计页显示阅读量 1413、评论 5 条,说明这套思路在 MQL5 社区属于低频但硬核的议题,不是大众向指标。 该小节只列了骨架:概述、算法原理、经典实现、修订版、测试结果。真正能开 MT5 验证的,是后续「经典实现」里的粒子位置更新代码与回测对比——外汇与贵金属杠杆高,PSO 搜出的参数过拟合概率不低,实盘前务必用样本外数据复核。

从科幻到粒子群:群体智能怎么进了优化算法

斯坦尼斯瓦夫·莱姆在《无敌》里写过一群没有集中控制的幸存机器人——最简单、数量最大的标本活了下来,复杂强大的反而淘汰。这种群体存活的逻辑,和自然界蚁群、蜂群、迁徙鸟群的自组织行为同源,后来直接催生了算法优化里的新思路。 群体智能模拟的是自组织系统的集体行为。J. Kennedy 和 R. Eberhart 在 1995 年给出规范版本,把 Reynolds 鸟群模型简化成无大小的“粒子”,种群叫“群体”。每次迭代里,粒子有位置和新速度矢量,按目标函数算值,再参考邻域最佳位置来更新自己。 常见的群算法包括粒子群、蚂蚁、蜜蜂、人工免疫系统、灰狼、蝙蝠、引力搜索、利他主义等。底层生物学假设很直白:群居生物平均生存概率更高,搜索和储存食物更高效,本质就是在用不同效率解优化问题(最大化食物、最小化捕食损失)。 粒子群自创世起就是最流行的优化算法之一,不少实现声称能有效优化多参数复杂函数,甚至能训神经网络。但经典版有个硬限制:目标函数必须平滑连续,碰离散函数直接失效。本系列会做修改,让算法不挑函数平滑性、参数步长也无限制,至少能在交易类问题里跑起来。外汇和贵金属市场高波动高风险,这类算法实盘前务必用 MT5 历史数据回测验证。

「PSO 与 MT5 程序的两种耦合方式」

上一节聊了优化世界,但没说主程序(EA、脚本、指标)和优化算法核心到底怎么相交。这点必须弄清,否则你读代码时总会困惑:为何算法和示例程序要写成这副样子。现有优化算法版本都把一个适应度函数当外部对象引用,算法本身是可执行主程序。 图例 1 那种结构里,算法把参数扔给适应度函数、再取回评估值,系统并不方便解决交易者的问题——比如你没法直接调测试器跑完整历史。图例 2 就灵活多了:优化算法退化为一个“黑匣子”模块,只向外暴露每个参数的最小、最大、步长;MQL 程序按请求收参数、回吐适应度值。这种结构能从 EA 内自动优化一路扩展到自定义优化管理器。 对所有优化算法(AO),调用流都能归纳成同一张图:Initialization_AO_0 做初始化;迭代周期里依次跑 Method_AO_1、取各参数变体的适应度值、再跑 Method_AO_2。只暴露这三个公开方法,就足以在任意复杂度项目里挂上优化。 PSO 本身的工作流很直白:随机撒粒子→算每个粒子适应度→算全局适应度→调速度→断点或回第二步。群体里没中央控制器,粒子只守三条简单规则:别互相撞、跟着周围速度调自己、跟环境保持近距离。初始化后算适应度、更新个体与全局最优、再更新速度和位置,解空间里的点就是粒子位置,速度带方向和步长。 速度坐标迭代的数学式就两行: v(t+1) = w * v(t) + c1 * rp * (p(t) – x(t)) + c2 * rg * (g(t) – x(t)) x(t+1) = x(t) + v(t+1) 第一项 w*v(t) 是惯性,w 为常数;第二项 c1*rp*(p(t)-x(t)) 里 rp 取 [0,1] 随机,p(t) 是粒子自身历史最优位;第三项 c2*rg*(g(t)-x(t)) 里 rg 同样 [0,1] 随机,g(t) 是群体已知最优位。算完新速度才推新位置。外汇与贵金属市场高波动,拿这套做参数寻优时,过拟合历史的概率不低,上 MT5 回测请控制代数。

◍ 把粒子群塞进 MT5 类里跑起来

描述一组优化坐标的逻辑单元就是粒子,用结构 S_Particles 承载:c[] 是当前坐标,cB[] 是历史最优坐标,v[] 是每个维度的位移量,ff 是当前适应度,ffB 是历史最佳适应度。构造函数里 ff 和 ffB 都初始化为 -DBL_MAX,因为算法默认求最大值;想求最小值就在结果前加负号。 C_AO_PSO 类只暴露三个公开方法:InitPS() 做初始化,Preparation() 在每代开头调用,Dwelling() 在算完适应度后更新最优。私密方法里 GenerateRNDparticles() 按 rangeMin/rangeMax 随机撒粒子并赋随机速度,ParticleMovement() 按标准公式算各坐标位移并做边界钳制。 接测试台后能看到粒子群在热图上像云一样移动:黑圈是函数全局最优点,黑点是当前平均最佳坐标(高维时按坐标取平均)。基于 Skin 平滑函数,PSO 在仅优化 2 个变量时表现良好;但维度一上去,效率急剧下降。Forest 和 Megacity 这两个离散函数上,PSO 结果明显差于前篇的纯随机算法。 外汇与贵金属参数优化属高风险实验,回测优异不代表实盘概率占优,维度灾难可能让群智能直接失效。下一篇打算改 PSO 的惯性项,看能不能翻盘。

MQL5 / C++
class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————
class="kw">struct S_Particles
{
  class="kw">public:
    class="type">class="kw">double c  []; class=class="str">"cmt">//coordinates
    class="type">class="kw">double cB []; class=class="str">"cmt">//best coordinates
    class="type">class="kw">double v  []; class=class="str">"cmt">//velocity
    class="type">class="kw">double ff;    class=class="str">"cmt">//the value of the fitness function
    class="type">class="kw">double ffB;   class=class="str">"cmt">//best value fitness function
    S_Particles()
    {
      ff  = -DBL_MAX;
      ffB = -DBL_MAX;
    }
};
class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————
class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————
class C_AO_PSO
{
  class="kw">public:
  class=class="str">"cmt">//----------------------------------------------------------------------------
  S_Particles p       []; class=class="str">"cmt">//particles
  class="type">class="kw">double rangeMax   []; class=class="str">"cmt">//maximum search range
  class="type">class="kw">double rangeMin   []; class=class="str">"cmt">//manimum search range
  class="type">class="kw">double rangeStep []; class=class="str">"cmt">//step search
  class="type">class="kw">double cB         []; class=class="str">"cmt">//best coordinates
  class="type">class="kw">double ffB;            class=class="str">"cmt">//FF of the best coordinates
  class="type">void InitPS(const class="type">int      params,        class=class="str">"cmt">//number of opt. parameters
               const class="type">int      size,          class=class="str">"cmt">//swarm size
               const class="type">class="kw">double   inertiaP,      class=class="str">"cmt">//inertia
               const class="type">class="kw">double   selfBoostP,    class=class="str">"cmt">//boost
               const class="type">class="kw">double   groupBoostP);  class=class="str">"cmt">//group boost
  class="type">void Preparation();
  class="type">void Dwelling();
  class="kw">private:
  class=class="str">"cmt">//----------------------------------------------------------------------------
  class="type">int swarmSize; class=class="str">"cmt">//swarm size
  class="type">int parameters;class=class="str">"cmt">//number of optimized parameters
  class="type">class="kw">double inertia;
  class="type">class="kw">double selfBoost;
  class="type">class="kw">double groupBoost;
  class="type">bool  dwelling;

常见问题

用来替代网格遍历,让一群候选参数按历史表现互相靠拢,更快找到较优区间;适合EA参数粗筛,不保证盈利。
实盘诊断建议粒子数 20~50、迭代 100 代内;规模再大在普通电脑上会明显拖慢回测速度。
小布盯盘的 AIGC 已内置参数诊断,打开对应品种页可看候选区间,不必自己搭粒子群框架。
PSO 靠全局速度项不易卡死,但高维问题仍可能早熟;加惯性权重衰减能缓解,属概率改善。
随机初始化和适应度噪声都会造成波动;固定随机种子并多跑几轮取中位,可压低不稳定度。