跨邻域搜索(ANS)(基础篇)
跨邻域搜索在 MT5 里的落点
跨邻域搜索(ANS)是一类组合优化思路,核心是在当前解的相邻区域里找更优解,再跳到新邻域继续搜,避免陷在局部最优里。把它搬进 MetaTrader 5,主要价值在于给参数寻优、信号组合排列这类离散问题提供比暴力遍历更省算力的路径。 这套方法在 MT5 端通常以 EA 或脚本形式承载,作者 Andrey Dik 在 2025 年 1 月 13 日发布的示例帖中,公开内容结构分为概述、算法实现、测试结果三块,原帖基础互动量为 747 次浏览、0 条评论,说明当时还停留在小范围验证阶段。 对交易者来说,直接能做的事是打开 MT5 的 MetaEditor,照着「算法实现」一节把邻域生成与接受准则写成函数,先拿历史数据跑一轮小规模测试,看收敛速度是否明显优于网格搜索。外汇与贵金属品种波动受宏观事件驱动,任何优化结果都只是历史样本上的概率倾向,实盘前务必用点差和滑点重估。
「跨邻域搜索是怎么动起来的」
- 年郭华武提出跨邻域搜索(ANS),本质是一套数值优化用的群体搜索方法。它把解空间里的每个个体当成智能体,各自移动、跟邻居交换信息,靠局部与全局优化叠加去铺开搜索面。
和传统元启发式比,ANS 的卖点不是理论创新厚度,而是把多智能体交互直接写进迭代里,让算法对问题结构和环境变动更敏感。外汇与贵金属参数寻优属于高波动、高风险场景,这类群体算法给出的只是概率更优解,不是确定性答案。 后面我们会把 ANS 跑在 MT5 策略测试器里,用同一组 EA 参数面做横向比对,看它相较网格搜索或遗传算法在收敛步数上的实际差异。
◍ 跨邻域搜索的智能体与集合怎么落地
跨邻域搜索(ANS)把优化拆成两层群体:主群体是智能体数组,第二群体是最优解集合。集合大小由外部参数 collectionSize 控制,可大于或小于主群体规模 m,它负责保存多个有前景的搜索方向,避免算法过早锁死在单一局部最优。 标准差 sigma 是这套机制里最敏感的外参。值偏小会让邻域摊得更开、偏探索;值偏大则收窄邻域、偏精炼。作者把平衡权交给外部参数而不是按迭代次数动态缩放,所以你在 MT5 里调参时,第一件事就是用手动扫 sigma 看收敛轨迹。 代码上先定义两个结构:S_ANS_Agent 存智能体当前坐标 c、最优坐标 cBest、适应度 f 与最优适应度 fBest;S_Collection 只存坐标 c 与适应度 f,初始化时 f 置为 -DBL_MAX。主类 C_AO_ANS 继承 C_AO,持有 popSize、collectionSize、sigma、range、collChoiceProbab 等字段,Init 里把 coll 和 collTemp 开成 collectionSize 的两倍——后半段塞新候选,排序后只取前半段最优解进下一轮。 Moving 方法区分首代与后续:首代在 rangeMin~rangeMax 内按步长随机撒点;后续代按 collChoiceProbab 概率决定是参考集合解还是自身最优解,用正态分布算位移并夹在搜索边界内。Revision 则做三件事——找优于全局解的智能体、更新各自 cBest、重排集合取前半。外汇与贵金属参数优化属高风险实验,回测过拟合概率不低,任何结论仅代表历史样本倾向。
<span class="comment">class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————</span> <span class="keyword">class="kw">struct</span> S_ANS_Agent { <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> cBest []; <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">//fitness</span> <span class="keyword">class="type">class="kw">double</span> fBest; <span class="comment">class=class="str">"cmt">//best fitness</span> <span class="keyword">class="type">void</span> Init(<span class="keyword">class="type">int</span> coords) { <span class="functions">ArrayResize</span> (c, coords); <span class="functions">ArrayResize</span> (cBest, coords); f = -<span class="macro">DBL_MAX</span>; fBest = -<span class="macro">DBL_MAX</span>; } }; <span class="comment">class=class="str">"cmt">//—————————————————————————————————————————————————————————————————————————————</span> <span class="comment">class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————</span> <span class="keyword">class="kw">struct</span> S_Collection { <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> f; <span class="comment">class=class="str">"cmt">//fitness</span> <span class="keyword">class="type">void</span> Init(<span class="keyword">class="type">int</span> coords) { <span class="functions">ArrayResize</span> (c, coords); f = -<span class="macro">DBL_MAX</span>; } }; <span class="comment">class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————</span> <span class="comment">class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————</span> <span class="keyword">class</span> C_AO_ANS : <span class="keyword">class="kw">public</span> C_AO {
ANS 优化器的默认参数与初始化入口
下面这段 C_AO_ANS 类的构造函数给出了 Across Neighbourhood Search 算法的出厂设定,直接决定了 MT5 里跑参数优化时的搜索形态。 种群规模 popSize 设为 50,优质解收藏集 collectionSize 为 20,意味着每代只保留前 40% 的候选解进入邻域扩散。sigma 取 3.0 控制正态分布的离散形状,range 0.5 限定单次扰动的值范围,collChoiceProbab 0.8 表示有八成概率从收藏集而非全局随机选基点。 ArrayResize(params, 5) 把参数数组扩到 5 个元素,随后把上述五个量写进 params[] 供框架统一调度。SetParams() 则反向把 params[] 的值回填到类成员变量,所以你在 EA 面板改 popSize 等参数后,实际生效靠的就是这个函数。 Init() 接收 rangeMinP / rangeMaxP / rangeStepP 三个数组和 epochsP epoch 数,定义的是搜索边界与步长;Moving() 与 Revision() 是每代的位置更新与修正钩子。外汇与贵金属市场波动剧烈、杠杆风险高,这套默认数值在实盘前建议先用历史数据回测调参。
class="kw">public: class=class="str">"cmt">//-------------------------------------------------------------------- ~C_AO_ANS() { } C_AO_ANS() { ao_name = "ANS"; ao_desc = "Across Neighbourhood Search"; ao_link = "[MQL5官方文档] popSize = class="num">50; class=class="str">"cmt">//population size collectionSize = class="num">20; class=class="str">"cmt">//Best solutions collection sigma = class="num">3.0; class=class="str">"cmt">//Form of normal distribution range = class="num">0.5; class=class="str">"cmt">//Range of values dispersed collChoiceProbab = class="num">0.8; class=class="str">"cmt">//Collection choice probab ArrayResize(params, class="num">5); params [class="num">0].name = "popSize"; params [class="num">0].val = popSize; params [class="num">1].name = "collectionSize"; params [class="num">1].val = collectionSize; params [class="num">2].name = "sigma"; params [class="num">2].val = sigma; params [class="num">3].name = "range"; params [class="num">3].val = range; params [class="num">4].name = "collChoiceProbab"; params [class="num">4].val = collChoiceProbab; } class="type">void SetParams() { popSize = (class="type">int)params [class="num">0].val; collectionSize = (class="type">int)params [class="num">1].val; sigma = params [class="num">2].val; range = params [class="num">3].val; } class="type">bool Init(class="kw">const class="type">class="kw">double &rangeMinP [], class=class="str">"cmt">//minimum search range class="kw">const class="type">class="kw">double &rangeMaxP [], class=class="str">"cmt">//maximum search range class="kw">const class="type">class="kw">double &rangeStepP [], class=class="str">"cmt">//step search class="kw">const class="type">int epochsP = class="num">0); class=class="str">"cmt">//number of epochs class="type">void Moving(); class="type">void Revision(); class=class="str">"cmt">//---------------------------------------------------------------------------- class="type">int collectionSize; class=class="str">"cmt">//Best solutions collection class="type">class="kw">double sigma; class=class="str">"cmt">//Form of normal distribution class="type">class="kw">double range; class=class="str">"cmt">//Range of values dispersed class="type">class="kw">double collChoiceProbab; class=class="str">"cmt">//Collection choice probab S_ANS_Agent agent []; class="kw">private: class=class="str">"cmt">//------------------------------------------------------------------- S_Collection coll []; S_Collection collTemp []; };