种群优化算法:杜鹃优化算法(COA)(基础篇)
◍ 用杜鹃迁徙逻辑给 EA 找参数
杜鹃优化算法(COA)把布谷鸟寄生孵卵的习性搬进参数搜索:每只鸟代表一组 EA 输入,巢被随机替换的概率 pa 控制探索与开发的平衡。在 MT5 里跑这套,本质是用群体智能替代网格遍历,样本显示 1794 次迭代可在中低维空间收敛到近似最优集。 算法核心依赖 Levy 飞行做步长跳跃,避免陷在局部平坦区。实际调参时,把 pa 设在 0.25 左右、 Levy 指数 β 取 1.5,往往比固定步长更快扫出可行域。外汇与贵金属市场高波动、高杠杆,任何优化结果都只是历史样本的概率拟合,实盘须以小资金验证。
「从寄生繁殖到优化算法」
杜鹃把蛋塞进别的鸟巢,让养父母替它喂雏,这种巢寄生在至少 80 种鸟里都存在,甚至蚂蚁、蜜蜂里也有雌性潜入他巢杀王产卵的类似操作。非洲坦噶尼喀湖的某些鲶鱼还会把卵甩给嘴孵鱼类代劳。 这类「让别人替自己养后代」的策略,被 Yang 和 Deb 在 2009 年抽象成了一种自然启发式优化算法——杜鹃搜索。它不像各向同性随机游走那样无方向乱撞,而是借 Levy 飞行的长尾步长跳脱局部,概率上更利于跳出劣质解。 做算法验证时,可在 MT5 的策略测试器里把这类步长逻辑写成自定义优化模块,对比默认遗传算法的收敛回合数,注意外汇与贵金属品种点差滑点会放大过拟合风险。
布谷鸟搜索怎么靠 levy 飞行找极值
布谷鸟优化(COA)把每个鸟巢里的蛋当成优化问题的一个候选解,杜鹃蛋则是迭代中产生的新解。算法从随机初始种群起步,靠生存竞争推进:每轮随机选一个巢,若杜鹃蛋质量高于宿主蛋就替换,否则保留原蛋,进化从幸存雏鸟继续。 核心移动靠 levy 飞行:xi(g+1) = xi(g) + α ⊕ levy(λ),g 为当前代,α>0 是步长,⊕ 为逐元素乘法。这是一条马尔可夫链,下一代位置只依赖当前位置和转移概率;levy(λ) ∼ g−λ(1<λ≤3),方差无限、均值无限。原提出者建议 λ 固定在 2.0 时整体结果最好,步长服从重尾幂律分布,比普通随机游走探得更远。 实际跑起来分两段:先按均匀分布抽随机方向,再按 levy 分布抽步长。新解适应度优于当前解才替换;同时以概率 pa 遗弃部分巢(宿主扔蛋或离巢),逼迫算法探索别处。pa 和 α 都得手调,终止条件常用「达到固定迭代代数」或「连续代无更优解」。 拿一维函数验证最直观:黑线函数在大部分定义域恒为 y=x 不变,仅小区间有峰值。从橙点出发,普通随机值容易落在平坦区白跑;levy 尾部的强跳跃直接落到绿点,再局部细化就逼近最大值。MT5 里写个单参数测试函数,把 λ 设 2.0 对比均匀随机游走,能看出收敛效率差异。外汇/贵金属参数优化属高风险实验,回测优不等于实盘可复制。
◍ 布谷鸟算法在 MT5 里的结构体与迭代骨架
COA 把解抽象成『杜鹃蛋』:一个带坐标数组 c[] 和适应度 e 的结构。鸟巢 S_Nest 用 Init 预分配坐标内存,并把 e 置为 -DBL_MAX,代表空巢没有合格蛋。 算法类 C_AO_COA 对外只暴露两个每次迭代必调的方法:CuckooFlight 负责按 Levy 飞行更新坐标,LayEggs 负责随机选巢、比蛋、按 koef_pa 概率淘汰。rangeMax/rangeMin/rangeStep 定义每个优化参数的搜索边界与步长。 Levy 步长核心句是 cuckoos[i].c[c] = cuckoos[i].c[c] + r1 * v[c] * pow(r2, -2.0):r1 取 ±1 定方向,v[c] 是 Init 里按各坐标范围预计算的位移向量,r2 取 0.0~20.0 的随机数,pow(r2,-2.0) 即 Levy 分布尾部的长跳跃。 我自己的对比测试表明,蛋被剔除后让巢空着、等下只杜鹃来产(不论蛋质量),比很多文献说的『随机重初始化坐标』收敛更快——探索由当前坐标往随机方向跳提供,总迭代数倾向更少。 外汇与贵金属参数优化属高风险,回测吻合不代表实盘概率稳定,上 MT5 跑前先锁死 rangeStep 再调 koef_pa。
class=class="str">"cmt">//—————————————————————————————————————————————————————————————————————————————— class="kw">struct S_Cuckoo { class="type">class="kw">double c []; class=class="str">"cmt">//coordinates(egg parameters) class="type">class="kw">double e; class=class="str">"cmt">//egg quality }; class=class="str">"cmt">//—————————————————————————————————————————————————————————————————————————————— class=class="str">"cmt">//—————————————————————————————————————————————————————————————————————————————— class="kw">struct S_Nest { class="type">void Init(class="type">int coordinates) { ArrayResize(c, coordinates); e = -DBL_MAX; } class="type">class="kw">double c []; class=class="str">"cmt">//coordinates(egg parameters) class="type">class="kw">double e; class=class="str">"cmt">//egg quality }; class=class="str">"cmt">//—————————————————————————————————————————————————————————————————————————————— class=class="str">"cmt">//—————————————————————————————————————————————————————————————————————————————— class C_AO_COA { class=class="str">"cmt">//============================================================================ 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: S_Cuckoo cuckoos []; class=class="str">"cmt">//all the cuckoos class="kw">public: class="type">class="kw">double cB []; class=class="str">"cmt">//best coordinates(egg parameters) class="kw">public: class="type">class="kw">double eB; class=class="str">"cmt">//best eggs quality class="kw">public: class="type">void Init(const class="type">int coordinatesP, class=class="str">"cmt">//number of opt. parameters const class="type">int cuckoosP, class=class="str">"cmt">//number of cuckoos const class="type">int nestsP, class=class="str">"cmt">//number of cuckoo nests const class="type">class="kw">double koef_paP, class=class="str">"cmt">//probability of detection of cuckoo eggs const class="type">class="kw">double koef_alphaP); class=class="str">"cmt">//step control value class="kw">public: class="type">void CuckooFlight(); class="kw">public: class="type">void LayEggs(); class=class="str">"cmt">//============================================================================ 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);