种群优化算法:和弦搜索(HS)(基础篇)
📘

种群优化算法:和弦搜索(HS)(基础篇)

第 1/2 篇

◍ 和弦搜索怎么在 MT5 里跑起来

和弦搜索(Harmony Search,HS)是一类受音乐即兴启发的种群优化算法,核心是把一组解当成「乐手」,靠记忆库、音高微调、随机扰动三类动作迭代逼近最优。它在 MT5 里常被塞进 EA 的参数寻优环节,替代网格搜索去躲局部极值。 算法每代先建一个 Harmony Memory(HM),存当前若干较优解;新解以 HMCR 概率从记忆里挑、以 PAR 概率做邻域微调,剩下情况纯随机。这套机制让种群既有 exploitation 也有 exploration,参数少、易落地。 原文示例发布于 2023-07-17 10:57,累计浏览 1015 次,作者 Andrey Dik,原文仅列了「概述 / 算法 / 测试结果」三段骨架,未给可复跑代码。想验证可自己在 MT5 用 CTrade+自写 HM 类做最小化回测,先调 HM 大小与 PAR,看曲线收敛速度。外汇与贵金属杠杆高,回测顺不等于实盘稳,参数敏感期可能快速回撤。

「把调音过程当成寻优模型」

音乐里和弦不是装饰那么简单,它是一组同时或依次发声的频率组合,决定了作品的完整度与表现力。没有和弦支撑的旋律就像缺了色的线稿,结构在但张力出不来。

  • 年 Z. W. Geem 提出的调和搜索(HS)算法,直接拿音乐即兴找和弦的过程当优化框架:乐手在音域内试音、记好听的组合、后续段落往更优和声靠,这对应着在多维空间里探全局极值。

HS 在即兴阶段满足三条之一——完全随机取声、从记忆里抽已有和弦、或取记忆中相邻和弦向量。它既能跑连续优化也能跑离散优化,核心卖点是结构简单且勘探/开发两阶段稳定性高,过去十年已被塞进不少复杂问题里验证过。 对外汇或贵金属交易者来说,这类元启发式思路可借来调参数组合,但市场高波动下任何“最优解”都只是历史样本里的倾向,实盘仍需人工把关。

把优化问题听成一首曲子:HS 算法的和弦逻辑

和弦搜索(HS)算法把参数优化类比成音乐家凑和弦:随机拨出一组音,听着顺耳就记进记忆,不顺就改音或借别的曲子里的音。绿色条代表一个参数维度上的可选音阶,蓝色条是一整首作品即一组候选解;记忆里存多首蓝色条变体,这就是种群。图例 1 用八音阶离散示例讲机制,实盘里参数可以是任意连续音阶加半音过渡,正确参数对应作品里的正确音符。 创作从乐器可重复频率内的随机声音开始,先生成多首曲子变体,再对每个变体里的音符做三种操作之一:随机换一个音、从别的版本按序号抄一个音、抄完再微调高低。新变体算完适应度,比原位置旧的强就覆盖,不排序种群,只做同位置替换——这点像遗传算法里的适者生存,但不用全局排名。 输入参数只有四个且直观:Population_P=50 是记忆中作品变体数;Eh_P=0.9 是从记忆借和弦的频率,越高组合性越强;Ep_P=0.1 是借来后微调音高的概率;Range_P=0.2 表示不借时编辑幅度为乐器范围的 20%。 弦乐更新公式为 h[har].c[c] = h[har].c[c] + r * B * frequency[c],其中 r 是 [-1,1] 随机数,B 随迭代衰减:B = ((maxIter-iter)/maxIter)*(maxB-minB)+minB。图例 2 显示 B 在优化末期趋小,相当于把发现的极值做精细优调。Revision() 里仅当 h>hB 才更新全局最优,和经典 HS 替换最差和弦不同,实测这种只替最佳的实现效率更高。外汇与贵金属参数优化属高风险,回测优异不代表实盘概率占优。 别把正态当圣经 HS 借用了均匀重组、均匀突变等旧思路,新颖点在音乐动机与思路组合。想把它从进化算法里单列出来,得真去啃音乐创作理论而非只调 Ep_P。

MQL5 / C++
class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————
class="kw">struct S_Harmony class=class="str">"cmt">//musical composition
{
  class="type">class="kw">double c  []; class=class="str">"cmt">//chords
  class="type">class="kw">double cB []; class=class="str">"cmt">//best chords
  class="type">class="kw">double h;     class=class="str">"cmt">//harmony quality
  class="type">class="kw">double hB;    class=class="str">"cmt">//best harmony quality
};
class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————
class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————
class C_AO_HS
{
  class=class="str">"cmt">//----------------------------------------------------------------------------
  class="kw">public: S_Harmony h        []; class=class="str">"cmt">//harmonies matrix
  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">class="kw">double cB         []; class=class="str">"cmt">//best chords
  class="kw">public: class="type">class="kw">double hB;            class=class="str">"cmt">//best harmony quality
  class="kw">public: class="type">void Init(const class="type">int      chordsNumberP,     class=class="str">"cmt">//chords number
                                const class="type">int      harmoniesNumberP,   class=class="str">"cmt">//harmonies number

◍ 和声搜索类的私有字段与初始化入口

这段声明把和声搜索(HS)优化器的状态都收进了一个 C_AO_HS 类里。对外只暴露 Moving(iter) 和 Revision() 两个方法,真正的随机选频概率 Eh、步长调整概率 Ep、搜索范围 range 以及最大迭代次数都藏在 private 段,避免外部逻辑误改导致寻优发散。 初始化函数 Init 接收 chordsNumber(和声数量)、harmoniesNumber(记忆库规模)、EhP、EpP、rangeP 与 maxIterationsP 六个参数。实盘里若把 chordsNumber 设到 50 以上,MT5 回测 EURUSD M15 时单代计算耗时可能从 0.3 ms 跳到 2 ms 级,参数维度多时要先压这个数。 几个私有工具函数值得留意:SeInDiSp 做带步长的离散化映射,RNDfromCI 在闭区间取均匀随机数,Scale 则把内部 [InMIN,InMAX] 线性拉伸到 [OutMIN,OutMAX],revers 为真时反转方向。复制下面代码到 MT5 头文件,就能直接挂到自己的指标寻优框架上。

MQL5 / C++
const class="type">class="kw">double EhP,                class=class="str">"cmt">//random selection frequency
const class="type">class="kw">double EpP,                class=class="str">"cmt">//frequency of step-by-step adjustment
const class="type">class="kw">double rangeP,             class=class="str">"cmt">//range
const class="type">int    maxIterationsP);    class=class="str">"cmt">//max Iterations
class="kw">public: class="type">void Moving(class="type">int iter);
class="kw">public: class="type">void Revision();
class=class="str">"cmt">//----------------------------------------------------------------------------
class="kw">private: class="type">int    chordsNumber;       class=class="str">"cmt">//chords number
class="kw">private: class="type">int    harmoniesNumber;    class=class="str">"cmt">//harmonies number
class="kw">private: class="type">class="kw">double Eh;                 class=class="str">"cmt">//random selection frequency
class="kw">private: class="type">class="kw">double Ep;                 class=class="str">"cmt">//frequency of step-by-step adjustment
class="kw">private: class="type">class="kw">double range;              class=class="str">"cmt">//range
class="kw">private: class="type">int    maxIterations;
class="kw">private: class="type">class="kw">double frequency [];       class=class="str">"cmt">//frequency range
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_HS::Init(const class="type">int    chordsNumberP,     class=class="str">"cmt">//chords number
                    const class="type">int    harmoniesNumberP,  class=class="str">"cmt">//harmonies number
                    const class="type">class="kw">double EhP,               class=class="str">"cmt">//random selection frequency
                    const class="type">class="kw">double EpP,               class=class="str">"cmt">//frequency of step-by-step adjustment
                    const class="type">class="kw">double rangeP,            class=class="str">"cmt">//range

常见问题

它把参数组合想象成一段和弦,靠随机微调找更优解;你可以用它自动搜EA参数,少手动试错。
基础篇建议先取种群规模10~30之间,记忆库比例0.7~0.9,跑多次看稳定性再调。
小布可读取你的优化结果并标记高风险品种,提醒你先做模拟验证,再决定是否上实盘。
大概率是无随机种子导致;初始化里固定随机种子并多跑几轮取中值可缓解波动。
HS结构更轻、调参少,倾向适合维度低的外汇问题;高维复杂面仍可能不如遗传算法稳。