人工藻类算法(Artificial Algae Algorithm,AAA)(基础篇)
📘

人工藻类算法(Artificial Algae Algorithm,AAA)(基础篇)

第 1/3 篇

◍ 人工藻类算法在 MT5 里的落地形态

人工藻类算法(Artificial Algae Algorithm,AAA)是一类受藻类群落生长与繁殖启发的群体智能优化方法,核心逻辑是用多个「藻细胞」在解空间里做趋光、繁殖与互食,逐步逼近最优参数组合。把它搬进 MetaTrader 5,意味着你可以不靠网格搜索硬跑,而是让 EA 在回测中自行调参。 这套思路在 MT5 社区里已有实装案例:2025 年 4 月 2 日有测试者(Andrey Dik)发布的相关内容获得 664 次查看、0 条评论,说明该方向还偏冷门但已被少数人验证可跑通。外汇与贵金属品种波动受杠杆与消息面驱动,用此类算法优化参数仍存在过拟合与实盘滑点风险,结论仅代表回测倾向。 典型实现会先定义藻细胞结构体,再在 OnTester 里写适应度函数,把策略的净值曲线或夏普比率作为光照强度。想验证的话,直接在 MT5 策略测试器载入带 AAA 逻辑的 EA,观察多代迭代后参数收敛是否稳定。

「从藻类群体到优化算法的映射」

藻类全球已记录超过 45,000 种,单细胞类型靠有丝分裂出新细胞仍相连结为群体,多细胞类型靠水中孢子传播萌发,也成群体。这种靠群体协作维持生存的机制,被 Uymaz、Tezel 和 Yel 在 2015 年抽成了人工藻类算法(AAA)——一类元启发式优化方法。 AAA 的核心不是拟态外形,而是把藻类向光移动、适应环境、靠分裂提质三项行为转成数学算子。算法锁定三个过程:螺旋运动模拟营养液里的三维寻优,进化过程让群体在优条件下繁殖以迭代解,适应性则把弱势群体拉向最大群体以免过早消亡。 对外汇与贵金属交易者而言,这类算法本质是参数空间搜索器,用在 MT5 上做参数寻优时,要清楚它只是概率倾向更优,不保证出金稳定,杠杆品种高风险依旧。

人工藻类算法的坐标与能量建模

人工藻类算法(AAA)把每个藻类群体映射成优化问题的一个候选解,群体里的细胞就是独立坐标,多个群体构成种群。群体大小直接反映解的质量,能量与大小、营养浓度成正比——大群体摩擦表面积也大,螺旋运动中减速更明显,反而利于局部搜索。 螺旋运动用三角方程更新坐标:x'i = xi + α·cos(θ)·τ(Xi)·p,其中 τ(Xi) 是第 i 个菌落的摩擦区域,由 τ(Xi)=2π·(3√(3·Gi)/(4π))² 算出,Gi 即菌落大小。α、θ∈[0,2π],p、r、v∈[-1,1] 为随机测量指标。运动耗能量,但抵达更好环境会恢复一半损失。 进化过程只做一件事:找最大群体 biggest=max(Gi),随机选一个细胞 m,把最小群体的同位置坐标替换为 biggest.xm。适应性则盯饥饿度——初始 Ai=0,没找到更优解的菌落 Ai=Ai+1;饥饿最高者 starving=max(Ai) 以 rand<Ap 的概率向最大群体坐标靠拢:starving.x += (biggest.x - starving.x)·rand。 竞争式选择不依赖适应度绝对值。实测 20 个个体原始大小为 20~1 时,选中概率从 9.76% 线性降到 0.25%:

0: 9.76%...

1: 9.24% 2: 8.74% ... 19: 0.25% 高效菌群优先但低效者也有机会,解多样性因此保持。每次选择需两次 MathRand() 调用,比之前改概率分布的函数略贵。 Monod 模型 μt=μtmax·St/(St+Kt) 用来算生长速率,底物浓度低时速率正比于浓度,高浓度封顶。把它接进 AAA,种群参数随资源变,比纯数学假设更贴近真实藻类动态。开 MT5 把上面方程 1–5 先写成脚本跑一遍,确认摩擦区域随 Gi 非线性放大,再决定后续调参方向。外汇/贵金属优化中套用此类元启发式须警惕过拟合与实盘高风险。

◍ 把选择机制跑成可见的分布

Revision 收尾会调用 EvolutionProcess 与 AdaptationProcess,前者把健壮度最低的智能体坐标替换成随机智能体坐标,后者在满足 adaptationProbability 时让最饥饿智能体向最高者借坐标并回满能量。这两步加上 CalculateEnergy 的饱和生长模型,构成了种群动态的主循环,但光看逻辑还不够——选择压力是否真的偏向高健壮度,要用 TournamentSelection 单独验证。 下面这段代码不依赖前面整套类结构,直接在 OnStart 里造了一个长度为 50 的pop数组,值从 50 递减到 1,然后做 1000000 次两两随机抽签,谁大谁累计胜场。跑完把每个个体的胜率打印成字符直方图,你能直接看到序号越小(值越大)的个体胜率越高,分布明显右偏。 input int PopSize = 50; input int Count = 1000000; input int BarWidth = 50; // Histogram width in characters void OnStart() { int pop[]; ArrayResize(pop, PopSize); for(int i = 0; i < PopSize; i++) pop[i] = PopSize - i; Print("Original population:"); ArrayPrint(pop); int tur[]; ArrayResize(tur, PopSize); ArrayInitialize(tur, 0); int ind1 = 0, ind2 = 0; for(int i = 0; i < Count; i++) { ind1 = MathRand() % PopSize; ind2 = MathRand() % PopSize; if(pop[ind1] > pop[ind2]) tur[ind1]++; else tur[ind2]++; } Print("Probability distribution (in %):"); double maxPercentage = 0; double percentages[]; ArrayResize(percentages, PopSize); for(int i = 0; i < PopSize; i++) { percentages[i] = (double)tur[i] / Count * 100; if(percentages[i] > maxPercentage) maxPercentage = percentages[i]; } for(int i = 0; i < PopSize; i++) { int barLength = (int)((percentages[i] / maxPercentage) * BarWidth); string bar = ""; 代码逐行拆:PopSize=50 是种群规模,Count=1000000 是锦标赛抽签总次数,BarWidth=50 控制直方图字符宽。OnStart 里先建 pop 并赋递减值,tur 记录胜场;核心循环用 MathRand()%PopSize 抽两个索引,比较 pop 值累加胜场。之后把胜场除以 Count 乘 100 得百分比,再按占最大值比例生成 barLength 画条。 把这段贴进 MT5 脚本跑一次,若把 pop[i] 改成随机浮点再比大小,分布形状会变化但偏向高值的趋势仍在——这印证了 TournamentSelection 的概率倾斜。外汇与贵金属行情里套这类机制做参数进化时,记住模拟分布不等于实盘胜率,杠杆品种高风险,回测偏倚可能放大。

MQL5 / C++
class="kw">input class="type">int      PopSize = class="num">50;
class="kw">input class="type">int      Count   = class="num">1000000;
class="kw">input class="type">int      BarWidth = class="num">50; class=class="str">"cmt">// Histogram width in characters
class="type">void OnStart()
{
  class="type">int pop[];
  ArrayResize(pop, PopSize);
  for(class="type">int i = class="num">0; i < PopSize; i++) pop[i] = PopSize - i;
  Print("Original population:");
  ArrayPrint(pop);
  class="type">int tur[];
  ArrayResize(tur, PopSize);
  ArrayInitialize(tur, class="num">0);
  class="type">int ind1 = class="num">0, ind2 = class="num">0;
  for(class="type">int i = class="num">0; i < Count; i++)
  {
    ind1 = MathRand() % PopSize;
    ind2 = MathRand() % PopSize;
    if(pop[ind1] > pop[ind2]) tur[ind1]++;
    else                      tur[ind2]++;
  }
  Print("Probability distribution(in %):");
  class="type">class="kw">double maxPercentage = class="num">0;
  class="type">class="kw">double percentages[];
  ArrayResize(percentages, PopSize);
  for(class="type">int i = class="num">0; i < PopSize; i++)
  {
    percentages[i] = (class="type">class="kw">double)tur[i] / Count * class="num">100;
    if(percentages[i] > maxPercentage) maxPercentage = percentages[i];
  }
  for(class="type">int i = class="num">0; i < PopSize; i++)
  {
    class="type">int barLength = (class="type">int)((percentages[i] / maxPercentage) * BarWidth);
    class="type">class="kw">string bar = "";

常见问题

每个藻细胞就是一组候选解,维度对应参数个数,位置即参数取值,直接映射进搜索空间。
能量由适应度函数归一化得到,能量越高代表该藻细胞越优,用于后续繁殖和淘汰的概率加权。
可以,小布能读取你的算法输出,把藻细胞位置和能量分布做成可视面板,省去自己写绘图代码。
正常,这是收敛表现;若过早聚集可能陷入局部最优,可调大初始种群分散度缓解。
当解空间多峰且需兼顾全局探索时更稳,粒子群快但容易早熟,可先小样本对比再定。