群体优化算法:智能水滴(IWD)算法(基础篇)
📘

群体优化算法:智能水滴(IWD)算法(基础篇)

第 1/3 篇

◍ 用智能水滴算法给 MT5 找最优参数

智能水滴(IWD)属于群体优化算法的一类,思路是模拟水滴在河道中流动时「冲刷—沉积」的路径选择,用大量虚拟水滴的集体行为去逼近问题的较优解。在交易系统里,它常被拿来做参数寻优,替代网格遍历那种指数级爆炸的暴力搜索。 原文给出的示例发布于 2024 年 6 月 26 日,运行环境为 MetaTrader 5,截至记录时该示例获得 1 381 次查看与 6 条讨论。这个量级说明它更偏工程验证性质,不是被大规模实盘验证过的成熟方案。 该篇结构分为四块:概述、算法、修改版 SDSm、测试结果。想验证的人可以直接在 MT5 里新建 EA 骨架,把 IWD 的种群规模先设到 50~100 之间跑一轮,外汇与贵金属杠杆高、滑点随机,这类优化结果仅代表历史样本倾向,实盘存在显著回撤风险。

智能水滴怎么借河床找路

智能水滴优化(IWD)属于群体智能里的构造型算法,2007 年由伊朗科学家 Hamed Shah-Hosseini 提出,核心是把自然河流的侵蚀与沉积过程抽象成数学规则。河床在流水长期作用下不断改变起伏,弯道处冲刷出新路、留下牛轭湖,这种‘阻力最小处优先通行’的现象,正是算法要模拟的对象。 在 IWD 里,每一滴人造水滴对应一个候选解,水滴在搜索空间移动时会改变所在路径的‘土壤量’(即阻力参数),多滴之间靠共享环境状态逐步收敛到更优路径。它和蚁群、粒子群一样是群体算法,但偏重构造式逐步建解,而非在连续空间里漂移。 对外汇与贵金属交易者来说,这类元启发式可用于参数寻优,但实盘环境高波动、高杠杆,任何回测优解都只是概率倾向,不能直接当信号用。

「把河谷搬进优化器:IWD 水滴怎么挑路」

智能水滴(IWD)原本是找最短路径的算法:一滴水带走的泥土量跟自身速度挂钩,速度越快、清走的土越多,后方水滴就越通畅。最优路径就是土最少、速度能拉满的那条——自然河流也是这么被水滴群冲出来的,硬土段阻力大、软土段好走,土会从急流搬去缓流处沉淀。 直接套用原版 IWD 解不了我们关心的优化问题。原开发者拿它跑图搜索、旅行商,群体优化文章里的变种才能啃任意问题。关键改造是:不让土壤等价于适应度(像蚁群拿信息素当适应度那样),而是把坐标切成等宽区段,像把河谷划格子。某滴位置改善,就按它前后两次适应度的差值(最大减最小)去减相应区段的土量。 移动时,水滴按概率挑土最少的区段落下,概率与该区段土壤量成正比;选中后新坐标服从二次分布——离旧坐标近的命中率高,远的概率低,区段宽度由外部参数控。全局“河床”库存每个区段的最深坐标,迭代伪代码就是:随机生成水滴→算适应度→更新全局最佳→算高度变化→按区段刷土→概率选区段滴落→再算适应度,循环。 速度增量公式是 vel = vel(t-1) + Av / [Bv + Cv * soil^2(i,j)],土少的边速度涨得猛;过河时间 time(i,j,vel) = R / vel,带走的土 dSoil = As / [Bs + Cs * time],新土量 soil(i+1,j+1) = Po*soil(i,j) + Pn*dSoil(i,j)。这些非线性比例决定了水滴偏爱低土路径。 代码里 S_Drop 是单滴的载体:Init 按坐标数 coords 重分配 c 与 rSection 数组,适应度 f、fPrev 都预置为 -DBL_MAX,altChange 清零。rSection 记该坐标落在哪个区段,c 存实际坐标,后面 Moving 和 Revision 就靠这套结构刷河床。

MQL5 / C++
class="kw">struct S_Drop
{
  class="type">void Init(class="type">int coords)
  {
    ArrayResize(c,          coords);
    ArrayResize(rSection,   coords);
    f        = -DBL_MAX;
    fPrev    = -DBL_MAX;
    altChange = class="num">0.0;
  }
  class="type">class="kw">double c            []; class=class="str">"cmt">//coordinates
  class="type">int    rSection     []; class=class="str">"cmt">//river section(number of cells: number of coordinates, cell value: sector index on the coordinate)

◍ 水滴寻优的类结构怎么搭

上面这段把智能水滴(IWD)算法的核心载体直接写成了一个 C_AO_IWDm 类,对外暴露的接口只有 Init、Moving、Revision 三个方法,其余全是私有成员。也就是说,你要在 MT5 里跑这套仿生寻优,真正需要外部调用的就这三步:初始化参数、让水滴移动、做迭代修正。 类里 public 区的 cB 和 fB 分别存「历史最优坐标」和「对应适应度」,p[] 是水滴群体,rangeMax/rangeMin/rangeStep 框定了每个维度的搜索上下界与步长。注意原文把 rangeMin 的注释拼错成 manimum,复制代码时别照抄这个笔误。 私有成员里 waterViscosity 要求 >= 1,这是算法里控制水滴「记忆衰减」的黏度系数;sectorsNumber 与 rb[](河床结构)配合,把搜索空间切成若干扇区并记录河床深度。Init 的入参固定为 coordsP(维度)、popSizeP(种群数)、sectorsNumberP(扇区数)、waterViscosityP(黏度),改这几个数就能直接调搜索粒度。 开 MT5 新建 EA 把这段类声明贴进头文件,先拿 coords=2、popSize=10、sectorsNumber=5、waterViscosity=1.0 做最小验证,能编译通过再扩维度。外汇与贵金属品种波动随机性强,这类优化仅用于参数探索,实盘前务必小资金验证风险。

MQL5 / C++
class="type">class="kw">double f;                 class=class="str">"cmt">//fitness
class="type">class="kw">double fPrev;              class=class="str">"cmt">//previous fitness
class="type">class="kw">double altChange;          class=class="str">"cmt">//change in altitude
};
class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————
class="kw">struct S_Riverbed class=class="str">"cmt">//riverbed
{
  class="type">class="kw">double riverbedDepth []; class=class="str">"cmt">//riverbed depth 
  class="type">class="kw">double coordOnSector []; class=class="str">"cmt">//coordinate on the sector
};
class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————
class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————
class C_AO_IWDm
{
  class=class="str">"cmt">//----------------------------------------------------------------------------
  class="kw">public: class="type">class="kw">double cB   [];      class=class="str">"cmt">//best coordinates
  class="kw">public: class="type">class="kw">double fB;           class=class="str">"cmt">//FF of the best coordinates
  class="kw">public: S_Drop p    [];      class=class="str">"cmt">//particles(drops)
  class="kw">public: class="type">class="kw">double rangeMax   []; class=class="str">"cmt">//maximum search range
  class="kw">public: class="type">class="kw">double rangeMin   []; class=class="str">"cmt">//manimum search range
  class="kw">public: class="type">class="kw">double rangeStep []; class=class="str">"cmt">//step search
  class="kw">public: class="type">void Init(const class="type">int      coordsP,            class=class="str">"cmt">//coordinates number
                                const class="type">int      popSizeP,          class=class="str">"cmt">//population size
                                const class="type">int      sectorsNumberP,    class=class="str">"cmt">//sectors number
                                const class="type">class="kw">double waterViscosityP);    class=class="str">"cmt">//water viscosity(>= class="num">1)
  class="kw">public: class="type">void Moving();
  class="kw">public: class="type">void Revision();
  class=class="str">"cmt">//----------------------------------------------------------------------------
  class="kw">private: class="type">int     coords;          class=class="str">"cmt">//coordinates number
  class="kw">private: class="type">int     popSize;         class=class="str">"cmt">//population size
  class="kw">private: class="type">int     sectorsNumber;   class=class="str">"cmt">//sectors number
  class="kw">private: class="type">class="kw">double  waterViscosity;  class=class="str">"cmt">//water viscosity
  class="kw">private: class="type">class="kw">double  sectorSpace [];  class=class="str">"cmt">//sector space
  class="kw">private: S_Riverbed      rb [];   class=class="str">"cmt">//riverbed
  class="kw">private: class="type">int     iterationCounter;
  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);
};

常见问题

IWD靠概率转移和土壤更新收敛更快,小样本下常比网格少跑60%以上无效组合,但仍需实盘前用历史数据回测验证。
河床矩阵初始化为全0,土壤值按路径长度倒数给初值;每条边土壤越大越不被选,迭代中成功路径减土壤、其余微增。
小布盯盘的AIGC已内置该类寻优诊断,打开对应品种页即可看到参数敏感与推荐区间,不必自己搭类结构。
θ取1~4、ρ取0.9~0.99较稳;θ过大易局部锁死,建议先跑几组短回测看分散度再定。
大概率土壤更新步长太小或初始群体过少;可把水滴数提到30+、调大soil更新系数,并加随机重启动避免陷谷。