大气云模型优化(ACMO):实战(基础篇)
📘

大气云模型优化(ACMO):实战(基础篇)

第 1/3 篇

「大气云模型优化在 MT5 里的实战落点」

大气云模型优化(ACMO)是一套把大气云图的空间分布逻辑迁移到价格序列上的算法思路,在 MetaTrader 5 中以独立 EA 或指标脚本形式运行。2025 年 5 月 26 日有测试者在 MT5 社区贴出实测记录,该帖截至统计时获得 582 次浏览与 2 条跟评,说明这类非线性模型在零售交易者圈子里仍属小众验证阶段。 从工程链路看,ACMO 的落地分三层:概述定调、算法实现、测试结果。概述部分交代云模型如何将高维气象变量降维映射为价格扰动因子;算法实现负责在 MQL5 里把映射关系写成可回测代码;测试结果则用历史报价跑样本外检验。外汇与贵金属市场高杠杆、高波动,任何模型都只代表概率倾向,不代表方向确定性。 想验证这套东西是否对你的品种有用,直接开 MT5 建个测试工程,把云模型参数从默认态往激进档调一档,看回测曲线会不会出现过度拟合尖峰——这是最快辨别它有没有实战含金量的动作。

云模型跑完了一半,下一步该下雨了

上一节我们已经把大气云模型优化(ACMO)的骨架搭起来了:搜索空间被切成若干区域,每个区域的初始湿度、压力都已赋值,模型参数也定了——初始熵、超熵、云生成阈值湿度都在列。 类里实现了云的生成与移动:挑湿度高的区域聚成云,算出云中心、熵和超熵,再按低压方向推着云走,沿途刷新区域的湿度和压力,最后让云消散。到这一步,算法只完成了“天气酝酿”,还没产生任何解更新。 接下来要补的是降雨环节:在云内随机撒水滴并做分布,靠降雨把候选解写回全局最优。测试函数上跑不同参数组合,才能看出收敛精度和稳定性。 外汇与贵金属优化问题里套这套元启发式,参数敏感度高、易过拟合,属高风险实验;建议先在 MT5 策略测试器用固定种子复现再上实盘逻辑。

◍ 云优化算法的类方法拆解

把气象过程转成可执行代码,核心落在 C_AO_ACMO 这一个类里。Moving 方法只做两件事:调 MoveClouds 按气压梯度推云,再调 RainProcess 按湿度降水滴,revision 参数决定是随机撒云还是基于已探明的低压区迁移。 MoveClouds 在 rev=false 时于给定区间用 RNDfromCI 随机定云心,经 SeInDiSp 规范化后由 GetRegionIndex 落区,并写入初始熵与超熵;rev=true 时先扫全坐标找最低压区索引 lHind 与归一压 normP,再逐云计算 β=deltaP/normP 得到移动速度 VC 更新中心,同时按压力变化增减熵、把超熵限制在 8 以内。 RainProcess 先用 DropletsDistribution 依各云湿度占总和的比例分水滴,余数全压给最干那朵云以保持种群规模恒定;随后对每滴按正态分布采 x,越界就用 RNDfromCI 拉回并 SeInDiSp 规范化。GenerateClouds 则按 CalculateHumidityThreshold(HT=H_min+λ*(H_max-H_min))收集合格区,熵超 5*EnM0_t 或湿度低于 dMin 的云消散,缺额在最湿区补新云并调 CalculateNewEntropy 重算熵。 新云熵随迭代推进的公式很具体:En = EnM0 / (1 + 2.72^(-(8 - 16*(t/maxT)))),超熵 He = HeM0 / (1 + 2.72^((8 - 16*(t/maxT))))。在 MT5 里把 maxT 调小,能明显看到前中期云团更活跃、后期收敛更快,外汇与贵金属参数寻优属高风险实验,结果仅具概率倾向。

MQL5 / C++
<span class="comment">class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————</span>
<span class="keyword">class="type">void</span> C_AO_ACMO::Moving()
{
&nbsp;&nbsp;MoveClouds&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (revision);
&nbsp;&nbsp;RainProcess&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(revision);
}
<span class="comment">class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————</span>
<span class="comment">class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————</span>
<span class="keyword">class="type">void</span> C_AO_ACMO::MoveClouds(<span class="keyword">class="type">bool</span> &amp;rev)
{
&nbsp;&nbsp;<span class="comment">class=class="str">"cmt">//----------------------------------------------------------------------------</span>

「云团朝低压区漂移的实现细节」

这段逻辑处理两种情况:若 rev 为假,就直接批量生成随机中心的云团并退出,不进入后续寻优。每个云团在各坐标维度上先用 RNDfromCI 取随机中心,再用 SeInDiSp 按步长对齐到离散网格,同时记录所属区域索引与初始熵值,超熵统一设为 HeM0。 当 rev 为真时,算法先扫描每个坐标维度的所有区域,找出气压最低的区域索引存进 lHind,并统计该维度的气压极差 normP。这里用 DBL_MAX 作初值确保任何真实气压都能刷新最小界。 随后对每团云逐维度判断:若已在最低压区域则跳过;否则随机抽一个气压更低的目标区域,计算两区气压差 deltaP,归一化得 β,再乘区域中心距 d 得出云团速度 VC,最后把中心坐标加上 VC 完成一步漂移。外汇与贵金属市场受此隐喻驱动时波动可能加速,但属高随机系统,实盘验证须以 MT5 回测为先。 把下面代码贴进 EA 的对应函数,调 cloudsNumber 与 regionsNumber 就能观察云团聚拢低压区的频率,从而评估该类模型对区间突破的捕捉倾向。

MQL5 / C++
  if (!rev)
  {
    class=class="str">"cmt">//creating clouds with random centers---------------------------------------
    for (class="type">int i = class="num">0; i < cloudsNumber; i++)
    {
      for (class="type">int c = class="num">0; c < coords; c++)
      {
        clouds [i].center [c] = u.RNDfromCI(rangeMin [c], rangeMax [c]);
        clouds [i].center [c] = u.SeInDiSp(clouds [i].center [c], rangeMin [c], rangeMax [c], rangeStep [c]);
        clouds [i].regionIndex [c] = GetRegionIndex(clouds [i].center [c], c);
        clouds [i].entropy       [c] = entropy [c] * EnM0;
        clouds [i].entropyStart [c] = clouds [i].entropy [c];
      }
      clouds [i].hyperEntropy = HeM0;
    }
    class="kw">return;
  }
  class=class="str">"cmt">//search for the region with the lowest pressure------------------------------
  class="type">int targetRegion = class="num">0;
  class="type">int lHind []; class=class="str">"cmt">//lowest humidity index
  ArrayResize(lHind, coords);
  ArrayInitialize(lHind, class="num">0);
  class="type">class="kw">double normP [];
  ArrayResize(normP, coords);
  class="type">class="kw">double minP;
  class="type">class="kw">double maxP;
  for (class="type">int c = class="num">0; c < coords; c++)
  {
    minP =  DBL_MAX;
    maxP = -DBL_MAX;
    for (class="type">int r = class="num">0; r < regionsNumber; r++)
    {
      if (areas [c].regions [r].pressure < areas [c].regions [lHind [c]].pressure)
      {
        lHind [c] = r;
      }
      if (areas [c].regions [r].pressure < minP) minP = areas [c].regions [r].pressure;
      if (areas [c].regions [r].pressure > maxP) maxP = areas [c].regions [r].pressure;
    }
    normP [c] = maxP - minP;
  }
  class=class="str">"cmt">//moving the cloud to a region with less pressure-----------------------------
  class="type">int     clRegIND = class="num">0;
  class="type">class="kw">double  deltaP   = class="num">0.0;
  class="type">class="kw">double  α        = class="num">0.0; class=class="str">"cmt">// Entropy factor
  class="type">class="kw">double  β        = class="num">0.0; class=class="str">"cmt">// Atmospheric pressure factor
  class="type">class="kw">double  VC       = class="num">0.0; class=class="str">"cmt">// Cloud velocity
  class="type">class="kw">double  d        = class="num">0.0; class=class="str">"cmt">// Cloud direction
  for (class="type">int i = class="num">0; i < cloudsNumber; i++)
  {
    for (class="type">int c = class="num">0; c < coords; c++)
    {
      class=class="str">"cmt">//find a region with lower pressure---------------------------------------
      if (clouds [i].regionIndex [c] == lHind [c]) class="kw">continue;
      clRegIND = clouds [i].regionIndex [c];
      do targetRegion = u.RNDminusOne(regionsNumber);
      while (areas [c].regions [clRegIND].pressure < areas [c].regions [targetRegion].pressure);
      class=class="str">"cmt">//------------------------------------------------------------------------
      deltaP = areas [c].regions [clRegIND].pressure - areas [c].regions [targetRegion].pressure;
      β = deltaP / normP [c];
      d = areas [c].regions [targetRegion].x - areas [c].regions [clRegIND].centre;
      VC = β * d;
      clouds [i].center        [c] += VC;

常见问题

在算法对象里保留已生成的云团数据,重新调用优化入口并传入上次的快照,即可从断点继续而非重头再来。
重点看漂移步长与低压权重两个系数,步长调大云团收敛快但易跳过优区,权重过高会过早聚拢丧失探索性。
可以,小布盯盘的 AIGC 已内置云模型诊断,打开对应品种页就能看到云团分布与低压漂移提示,不用自己写循环。
把最优参数丢到邻近周期或不同品种做样本外回放,若收益衰减超30%大概率过拟合,需回炉调云团规模。
贵金属跳空多,云模型靠概率漂移更抗突变;网格在窄幅震荡成本低,但遇极端行情易全军覆没,外汇贵金属均属高风险。