人工蜂巢算法(ABHA):测试与结果(基础篇)
📘

人工蜂巢算法(ABHA):测试与结果(基础篇)

第 1/2 篇

「ABHA 算法的 MT5 实测起点」

人工蜂巢算法(ABHA)在 MetaTrader 5 上的实现进入实测阶段,由测试者于 2025 年 3 月 6 日 08:55 提交首轮记录,原始线程获 784 次浏览、4 条反馈。 该轮测试并未给出收益曲线,重点在于验证算法在 MT5 策略测试器中的可运行性与稳定性,属于「继续算法实现」后的第一轮落地检验。 外汇与贵金属品种波动剧烈、杠杆风险极高,ABHA 的任何回测结果都仅代表历史样本,实盘表现可能偏离。打开 MT5 的「文件→打开数据文件夹→MQL5→Experts」即可准备放入后续 EA 文件做复验。

ABHA 智能体模型的核心约束

ABHA 把每只蜜蜂建模为独立智能体,行为由四种状态调节:新手、有经验、搜索、食物源。同一套规则集对所有蜜蜂生效,但空间位置不同导致感知环境不同,行为分支自然分化。 单只蜜蜂在任一时刻的动作,由可获得的内部与外部信息加上动机状态共同决定,符合一组固定规则。这意味着你跑回测时,不同初始坐标的 agent 即使参数一致,轨迹也会明显分叉。 蜜蜂会依据觅食经验或动机状态切换行为模式,所以模型本质是一组随个体特征与环境自适应的规则集合,而非单一全局寻优函数。外汇与贵金属市场高频跳空多,直接套该模型做价格寻优须警惕过拟合风险。

◍ ABHA 各阶段行为方法的实现逻辑

ABHA 算法把蜂群拆成新手、经验蜂、搜索蜂、食物源蜂四类,各自由 C_AO_ABHA 类里不同的 Stage 与 ChangingState 方法驱动。新手靠 StageActivityNovice 决定每一步是随机搜还是跟舞:用 u.RNDprobab() 出的随机数比 randomSearchProbability 小就调 ActionRandomSearch,否则调 ActionFollowingDance(c, val),遍历 coords 个维度逐坐标更新。 经验蜂的 StageActivityExperienced 多了一层停留逻辑:rnd ≤ agent.p_srs 随机搜,p_srs < rnd ≤ agent.p_rul 跟舞,其余情况调 ActionHiveVicinity(c, agent.bestPosition[c]) 留在已知最优位附近,策略比新手更复杂。 ActionFollowingDance 用轮盘赌选舞者——先累加所有经验蜂的 p_si 得 totalProbability,归一化随机值后命中即选该蜂,新位置 = val + (选中蜂最佳位−val) + 噪声,没选中则退回随机搜。ActionMovingDirection 让智能体按 agent.direction[coordInd] 走 agent.stepSize,走完步长乘 stepSizeReductionFactor 衰减,逼出精细收敛。 状态切换里有个硬阈值:当前 cost 比群体 avgCost 高 20% 时,经验蜂或搜索蜂直接进 stateSource 且 pab 置 1;搜索蜂若 searchCounter 触到 maxSearchAttempts 仍无突破,则降回 stateNovice 重来。外汇与贵金属参数优化属高风险实验,这套概率切换在 MT5 里跑前应先以小样本回测验证收敛倾向。 ChangingStateForSource 给食物源蜂留了退出通道:cost 低于 avgCost 时按 abandonmentRate 削 pab,一旦 u.RNDprobab() 超出现 pab 就弃源转搜索并重置方向与步长;若 cost 破 bestCost 则升经验蜂并锁 pab=1,准备向群体播报优质源。

「蜜蜂行为的概率分流与坐标更新」

ABHA 算法里,ChangingStateForSource 决定单只蜜蜂是留守食物源还是另觅出路,判断时同时比对它自己的当前值和全局最优值。真正把「去哪」落地的,是 CalculateProbabilities:先扫一遍 popSize 只蜜蜂,把 maxCost 从最小可能值往上抬、minCost 从最大可能值往下压,求出 costRange 做归一化分母。 每只蜜蜂会算出三个动作概率——p_si 随成本走高而走高,p_srs 是预设的随机搜索概率,p_rul 是跟随舞蹈概率;留守概率 p_ab 等于自身 pab。三者求和后再分别除以总和,保证概率和恒为 1,这一步直接决定下一轮是乱飞、跟舞还是趴窝。 CalculateAverageCost 顺手把全群平均成本算出来,作为群体成功度的标尺,也喂给后续决策。下面这段 C_AO_ABHA 的方法把概率变成了实际坐标动作,新手蜂只看 randomSearchProbability 二分,老手蜂则严格按 p_srs、p_rul 区间切分三种行为。 外汇与贵金属市场波动剧烈、杠杆风险高,把这类群体算法接进 MT5 做信号过滤时,回测务必覆盖滑点与点差突变,否则蜂群再聪明也扛不住实盘噪声。

MQL5 / C++
class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————
class=class="str">"cmt">//Actions class="num">1 or class="num">2
class="type">void C_AO_ABHA::StageActivityNovice(S_ABHA_Agent &agent)
{
  class="type">class="kw">double val;
  for (class="type">int c = class="num">0; c < coords; c++)
  {
    val = agent.position [c];
    if (u.RNDprobab() < randomSearchProbability) agent.position [c] = ActionRandomSearch(c);
    else                                        agent.position [c] = ActionFollowingDance(c, val);
  }
}
class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————
class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————
class=class="str">"cmt">//actions class="num">1 or class="num">2 or class="num">4
class="type">void C_AO_ABHA::StageActivityExperienced(S_ABHA_Agent &agent)
{
  class="type">class="kw">double rnd = class="num">0;
  for (class="type">int c = class="num">0; c < coords; c++)
  {
    rnd = u.RNDprobab();
    class=class="str">"cmt">// random search probability
    if (rnd <= agent.p_srs)
    {
      agent.position [c] = ActionRandomSearch(c);
    }
    else
    {
      class=class="str">"cmt">// Probability of following the dance
      if (agent.p_srs < rnd && rnd <= agent.p_rul)
      {
        agent.position [c] = ActionFollowingDance(c, agent.position [c]);
      }
      class=class="str">"cmt">// Probability of remaining near the source
      else
      {
        agent.position [c] = ActionHiveVicinity(c, agent.bestPosition [c]);
      }
    }
  }
}
class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————
class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————
class=class="str">"cmt">//Actions class="num">3
class="type">void C_AO_ABHA::StageActivitySearch(S_ABHA_Agent &agent)
{
  for (class="type">int c = class="num">0; c < coords; c++)
  {
    agent.position [c] = ActionMovingDirection(agent, c);
  }
}
class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————
class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————
class=class="str">"cmt">//Actions class="num">4
class="type">void C_AO_ABHA::StageActivitySource(S_ABHA_Agent &agent)
{
  class="type">class="kw">double val = class="num">0;
  for (class="type">int c = class="num">0; c < coords; c++)
  {
    agent.position [c] = ActionHiveVicinity(c, agent.bestPosition [c]);
  }
}
class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————
class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————
class=class="str">"cmt">//class="num">1. Random search(random placement in a range of coordinates)
class="type">class="kw">double C_AO_ABHA::ActionRandomSearch(class="type">int coordInd)
{
  class="kw">return u.RNDfromCI(rangeMin [coordInd], rangeMax [coordInd]);
}
class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————
class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————
class=class="str">"cmt">//class="num">2. Follow the dance(move in the direction of the dancer)
class="type">class="kw">double C_AO_ABHA::ActionFollowingDance(class="type">int coordInd, class="type">class="kw">double val)
{

常见问题

先确认智能体模型的核心约束已写死,再从小样本历史数据回测起步,别直接上真实账户。
按探索、跟随、放弃三阶段分别写行为方法,用概率分流决定每只蜜蜂走哪条更新坐标的路径。
小布可读取你的品种页数据,自动跑ABHA基础回测并标出概率分流异常点,你只需看结果调参数。
大概率是无序阶段权重过高,先把跟随阶段概率调到0.5以上再观察三十根K线内的漂移。
贵金属波动大易过拟合,删掉极端行情样本重测,并限制蜜蜂最大移动步长再比一次曲线。