人工原子算法(A3)
内容
引言
在算法交易领域,核心任务之一便是对交易策略参数进行优化。交易者每天都需要调试大量变量:指标周期、止盈止损点位、仓位规模、时间过滤器,以及数十项其他参数。这些参数的不同组合都可能显著改变策略表现。因此业界始终在寻找高效优化算法,力求在合理时间内找到最优参数组合。
本文将介绍另一种优化算法 —— 人工原子算法(A3),这是一种以化学反应为灵感构建的元启发式优化算法。该算法由土耳其学者提出,于 2018 年首次向学术界公开。
算法实现
在研究该算法时,我发现原始文献存在多处表述模糊的问题。部分运算算子描述不够详尽,难以直接用于编程实现。对此,下文会完整引用原始算法定义,但最终代码实现由我自主设计 —— 结合个人开发经验,以及同类智能优化算法通用架构思路完成。原始文献存在明显信息缺口,留给开发者极大的自主解读空间。除此之外,开发过程中我还对基础父类进行了修改,在介绍基础算法逻辑后,我会展开说明相关改动。
该算法通过模拟原子与电子的相互作用寻找最优解。核心单元为原子,每一个原子代表问题的一组候选解。电子表示决策变量。共价键算子负责保存、复制当前最优解;离子键算子用于探索搜索空间,助力算法搜寻全局最优。
算法流程:首先随机生成一组原子种群,通过目标函数评估每个原子对应的解质量;随后调用共价键、离子键算子迭代优化候选解(遗憾的是原始文献并未说明两种算子的具体执行方式)。下一步需要评估电子带来的影响。同样,文献并未给出具体实现方案。文中还要求对电子、原子进行排序。我们可以对原子(候选解)排序,但如何对电子排序完全没有可供参考的逻辑 —— 好比试图把人的四肢排序,区分左右手、左右腿,本身不存在合理依据。之后重复迭代,直至满足终止条件。常言道,巧妇难为无米之炊,但现有资料有限,只能基于现有内容开展工作。我们需要依托原作者提出的核心思想,搭建完整算法框架。
下文给出我修订完善后的 A3 算法伪代码:
初始化输入参数:
popSize — 原子种群数量(默认值:10)
covalentRate — 共价键系数(默认值:0.1)
rangeMin []、rangeMax [] — 各变量搜索上下限
rangeStep [] — 变量离散步长
预计算:
计算精英原子数量:
covalentCount = floor (popSize × covalentRate)
约束条件:最小值 1,最大值不超过 popSize - 1
创建规模为 popSize 的原子种群
对每个原子执行初始化:
坐标数组 c []
局部最差解坐标 cW []
适应度 f,局部最差适应度 fW
基本优化循环:
步骤 1:首次迭代(revision = false)
遍历所有原子 i(0 ~ popSize-1):
遍历每一个维度坐标 j(0 ~ 维度总数 - 1):
在区间 [rangeMin [j], rangeMax [j]] 内生成随机数值
按照 rangeStep [j] 执行离散化处理
存入原子 a [i].c [j]
将 revision 标记置为 true
本步骤结束
步骤 2:更新原子位置(移动算子)
遍历所有原子 i(0 ~ popSize-1):
若 i ≤ covalentCount(当前原子属于精英原子):
遍历每一个维度坐标 c(0 ~ 维度总数 - 1):
若 random() < covalentRate(10% 概率):
// 向全局最优解靠近
步长 step = random() × (cB [c] - a [i].c [c]) × covalentCount
a [i].c [c] = a [i].c [c] + step
否则(90% 概率):
// 基于幂分布,以全局最优解为中心生成新坐标
a[i]. c[c] = PowerDistribution(center=cB [c], min=rangeMin [c], max=rangeMax [c], degree=20)
对 a [i].c [c] 执行离散化
否则(非精英原子):
遍历每一个维度坐标 c(0 ~ 维度总数 - 1):
// 随机选取一个精英原子作为参考样本
ind = 随机整数 (0, covalentCount)
// 从自身局部最差位置向精英原子位置移动
移动方向 direction = a [ind].c [c] − a [i].cW [c]
步长 step = random () × direction × (1.0 − covalentCount)
a [i].c [c] = a [i].c [c] + step
对 a [i].c [c] 执行离散化
步骤 3:适应度计算
遍历每个原子 i:
通过目标函数计算 a [i].f(原子适应度)
步骤 4:记忆更新与种群排序(修正阶段)
// 更新每个原子记录的局部最差解
遍历原子 i(0 ~ popSize-1):
若 a [i].f < a [i].fW:
a [i].fW = a [i].f
将 a [i].c 复制至 a [i].cW
更新全局最差适应度 fW
// 按适应度降序对种群排序
依据适应度字段 f,将原子数组 a [] 从最优到最差排序
// 更新全局最优解
若 a [0].f > fB:
fB = a [0].f
将 a [0].c 复制至全局最优坐标 cB
// 更新全局最差解
若 a [popSize-1].f < fW:
fW = a [popSize-1].f
将 a [popSize-1].c 复制至全局最差坐标 cW
步骤 5:终止条件判断
若迭代次数达到最大迭代上限:
算法结束
否则:
跳转至步骤 2 继续循环
接下来我们进入代码实操实现环节。我们将编写一个类,实现基于原子与化学键隐喻的人工原子系统算法。该类继承基础优化父类 C_AO,并且结合 A3 算法特性进行功能扩展。
参数配置方法:SetParams (),读取参数数组中的数值并赋值给内部变量。这将方便算法运行前灵活地自定义参数。初始化方法:Init (),完成参数与数据结构初始化,接收变量取值区间、离散步长以及迭代轮数。算法核心运算:Moving ()、Revision () 方法分别实现原子位置移动、种群信息更新两大阶段,对应最优解搜索流程。核心参数说明:
- popSize — 原子种群规模,即种群内候选解数量。
- covalentRate — 表征原子之间成键概率的系数。
- covalentCount — 内部变量,参与成键运算的精英原子数量(内部计算使用)。
该类整体目标:模拟原子系统及其相互作用,依靠上述参数与成员方法完成建模。基于这套原子交互逻辑,即可搭建完整的搜索与优化框架。
//———————————————————————————————————————————————————————————————————— class C_AO_A3 : public C_AO { public: //---------------------------------------------------------- ~C_AO_A3 () { } C_AO_A3 () { ao_name = "A3"; ao_desc = "Artificial Atom Algorithm"; ao_link = "https://www.mql5.com/en/articles/18958"; popSize = 10; // number of atoms (m) covalentRate = 0.1; // covalent bond coefficient (β) ArrayResize (params, 2); params [0].name = "popSize"; params [0].val = popSize; params [1].name = "covalentRate"; params [1].val = covalentRate; } void SetParams () { popSize = (int)params [0].val; covalentRate = params [1].val; } bool Init (const double &rangeMinP [], // minimum values const double &rangeMaxP [], // maximum values const double &rangeStepP [], // step change const int epochsP = 0); // number of epochs void Moving (); void Revision (); //------------------------------------------------------------------ double covalentRate; // covalent bond coefficient (β) private: //--------------------------------------------------------- int covalentCount; // number of atoms for covalent bond }; //————————————————————————————————————————————————————————————————————
Init () 方法是启动算法前至关重要的准备环节。其核心任务是:在优化流程正式开始前,完成全部必要参数与数据结构的初始化工作。该方法接收四项输入参数:
- rangeMinP [] — 算法待优化各变量的下限。
- rangeMaxP [] — 各变量的上限。
- rangeStepP [] — 各变量的变化步长。步长用于变量离散化,同时决定搜索精度。
- epochsP — 算法执行的迭代轮数(世代数)。
函数会优先调用基类 C_AO 的 StandardInit () 方法,执行所有优化算法通用的初始化流程。若 StandardInit () 执行成功,函数继续计算人工原子算法专属参数。主要计算 covalentCount,即参与成共价键的原子数量。计算公式为种群总原子数量 popSize 乘以共价键系数 covalentRate。计算结果向下取整(MathFloor),保证原子数量为整数。随后执行合法性校验,确保 covalentCount 取值逻辑有效。如果所有初始化步骤顺利完成,方法返回 true,代表算法就绪,可以启动优化。
综上,Init 方法同时完成通用优化参数与这套 “原子 - 化学键” 模型专属参数的初始化,保障人工原子算法可以完整投入运行。
/———————————————————————————————————————————————————————————————————— //--- Initialization bool C_AO_A3::Init (const double &rangeMinP [], const double &rangeMaxP [], const double &rangeStepP [], const int epochsP = 0) { if (!StandardInit (rangeMinP, rangeMaxP, rangeStepP)) return false; //------------------------------------------------------------------ covalentCount = (int)MathFloor (popSize * covalentRate); if (covalentCount < 1) covalentCount = 1; if (covalentCount >= popSize) covalentCount = popSize - 1; return true; } //————————————————————————————————————————————————————————————————————
C_AO_A3 类中的 Moving () 方法是人工原子算法核心步骤之一,实现原子在搜索空间内的 “移动”,也就是位置更新逻辑。该方法模拟原子种群的演化行为,目的是搜寻最优解。每次调用 Moving () 时,首先检查 revision 标记。该标记用于标识种群是否已经完成初始化。
初始化阶段(revision = false)代表首次调用或者算法重置后调用,原子种群尚未初始化。此时程序遍历全部 popSize 个原子、遍历搜索空间所有维度 coords。针对每个原子的每一维坐标,在指定区间内生成随机位置。首次调用完成初始化后,将 revision 设置为 true;后续调用Moving()将执行主体移动逻辑,不再重复初始化,首次调用结束后函数直接返回。
原子主体移动流程(revision = true)种群初始化完成后,Moving 方法开始更新原子位置,模拟原子运动。依据原子索引 i 与 covalentCount 的大小关系,原子被划分为两组。
第一组:参与共价键作用的原子(i <= covalentCount)组内每一个原子、每一维坐标都会生成随机数;若随机数小于共价键系数,原子按照公式更新坐标,模拟原子向当前最优解 cB [c] 吸引、相互作用;其中 cB 代表种群当前找到的全局最优坐标,计算过程引入 covalentCount。
若随机数大于或等于 covalentRate,则调用 PowerDistribution 函数更新坐标。该函数生成偏向 cB [c] 的随机值,同时保留一定随机扰动、实现更具随机性的搜索或“散射”效果。
无论采用哪种方式更新坐标,都会调用 u.SeInDiSp 函数做后处理,把坐标约束到合法区间,并对齐离散网格。
第二组:不参与共价键作用的原子(i > covalentCount)针对组内每个原子的每一维坐标,在区间 [0, covalentCount] 随机选取一个索引 ind。这意味着非成键原子会与某一个成键原子产生交互。
原子坐标完成更新,模拟原子与选中成键原子之间的吸引或排斥作用,并参考自身历史局部最差位置;更新完成后同样调用 u.SeInDiSp 处理坐标,满足取值约束。
Moving () 方法是整个搜索流程的核心。基于物理模型构建随机位置更新规则。参与共价键的原子倾向向已知最优解靠拢;其余原子持续探索空间,与成键原子产生交互。
//———————————————————————————————————————————————————————————————————— //--- The main step of the algorithm void C_AO_A3::Moving () { // Initial population setup if (!revision) { for (int i = 0; i < popSize; i++) { for (int j = 0; j < coords; j++) { a [i].c [j] = u.RNDfromCI (rangeMin [j], rangeMax [j]); a [i].c [j] = u.SeInDiSp (a [i].c [j], rangeMin [j], rangeMax [j], rangeStep [j]); } } revision = true; return; } //------------------------------------------------------------------ int ind = 0; for (int i = 0; i < popSize; i++) { if (i <= covalentCount) { for (int c = 0; c < coords; c++) { if (u.RNDprobab () < covalentRate) { a [i].c [c] = a [i].c [c] + u.RNDprobab () * (cB [c] - a [i].c [c]) * covalentCount;//(1.0 - covalentCount); } else { a [i].c [c] = u.PowerDistribution (cB [c], rangeMin [c], rangeMax [c], 20); } a [i].c [c] = u.SeInDiSp (a [i].c [c], rangeMin [c], rangeMax [c], rangeStep [c]); } } else { for (int c = 0; c < coords; c++) { ind = u.RNDintInRange (0, covalentCount); a [i].c [c] = a [i].c [c] + u.RNDprobab () * (a [ind].c [c] - a [i].cW [c]) * (1.0 - covalentCount);//covalentCount; a [i].c [c] = u.SeInDiSp (a [i].c [c], rangeMin [c], rangeMax [c], rangeStep [c]); } } } } //————————————————————————————————————————————————————————————————————
C_AO_A3 类的 Revision () 方法负责在算法单次迭代中,更新原子种群内最优解与最差解相关信息。这一步十分关键:全局、个体层面的最优、最差适应度信息,将指导下一轮搜索。首先更新每个原子各自记录的局部最差解。调用 u.Sorting () 函数,依据适应度 f 对全部原子种群数组 a 完成排序。
排序完成后,数组首位原子 a [0] 即为当前种群最优个体。使用 a [0].f 更新全局最优适应度 fB,同时将 a [0].c 坐标复制至全局最优坐标 cB。数组末尾原子 a [popSize - 1] 是排序后种群最差个体。将 a [popSize - 1].f 与全局最差适应度 fW 对比;若该适应度更差,则更新 fW,并把 a [popSize - 1].c 复制到全局最差坐标 cW。
Revision 方法持续系统性追踪优化进展:该方法维护种群的全局最优/最差状态,并更新各原子记录的局部最差历史状态。
//———————————————————————————————————————————————————————————————————— //--- Update the best and worst solutions void C_AO_A3::Revision () { // Update the local worst solution for (int i = 0; i < popSize; i++) { if (a [i].f < a [i].fW) { fW = a [i].f; ArrayCopy (a [i].cW, a [i].c, 0, 0, WHOLE_ARRAY); } } static S_AO_Agent aT []; ArrayResize (aT, popSize); u.Sorting (a, aT, popSize); if (a [0].f > fB) { fB = a [0].f; ArrayCopy (cB, a [0].c, 0, 0, WHOLE_ARRAY); } if (a [popSize - 1].f < fW) { fW = a [popSize - 1].f; ArrayCopy (cW, a [popSize - 1].c, 0, 0, WHOLE_ARRAY); } } //————————————————————————————————————————————————————————————————————
最终实现代码结构十分精简。接下来我们介绍所有优化算法所继承的基类。上文提到,基类代码经过修改,下面对该基类进行说明。
用于存放算法参数的简易结构体。支持动态管理任意优化算法的配置参数。
//—————————————————————————————————————————————————————————————————————————————— struct S_AlgoParam { double val; string name; }; //——————————————————————————————————————————————————————————————————————————————
S_AO_Agent 结构体用于描述单个智能体,一个智能体代表优化问题的一组候选解,在多维搜索空间中移动。S_AO_Agent结构体内部字段分为三大类:1. 坐标信息(搜索空间位置):
- c — 智能体当前坐标数组。存储智能体当前位置。
- cP — 智能体上一轮坐标数组。用于追踪运动轨迹。
- cB — 该智能体历史到达过的最优坐标。智能体依靠该信息 “记住” 最优位置,可回退或以此为基准继续搜索。
- cW — 智能体历史最差坐标。
2. 适应度(解质量):
- f — 智能体当前适应度。基于当前坐标 c 计算得到目标函数值。
- fP — 上一轮适应度。与 cP 配套,用于观测适应度变化。
- fB — 该智能体历史最优适应度。对应坐标 cB。
- fW — 该智能体历史最差适应度。对应坐标 cW。
3. 辅助变量:cnt — 整型计数器。
结构体内置公开 Init () 方法,用于智能体初始化。入参 coords 为整数,代表搜索空间维度,即智能体拥有的坐标数量。
调用 Init () 时执行以下操作:动态调整坐标数组(c、cP、cB、cW)长度至 coords。保证智能体维度匹配具体优化问题。初始化适应度:f、fP、fB 赋值为 -DBL_MAX(双精度最小值);fW 赋值为 DBL_MAX(双精度最大值)。这是最大化优化问题的标准初始化范式:f、fP、fB 初始值设为极小值,后续计算值几乎必然大于初始值;fW 初始值设为极大值,任意首次计算结果都会优于初始值。计数器 cnt 初始化为 0。
整体而言,S_AO_Agent 为种群优化算法中的每一个个体提供完整数据结构,同时记录个体当前状态与历史优劣轨迹。
//—————————————————————————————————————————————————————————————————————————————— struct S_AO_Agent { double c []; //coordinates double cP []; //previous coordinates double cB []; //best coordinates double cW []; //worst coordinates double f; //fitness double fP; //previous fitness double fB; //best fitness double fW; //worst fitness int cnt; //counter void Init (int coords) { ArrayResize (c, coords); ArrayResize (cP, coords); ArrayResize (cB, coords); ArrayResize (cW, coords); f = -DBL_MAX; fP = -DBL_MAX; fB = -DBL_MAX; fW = DBL_MAX; cnt = 0; } }; //——————————————————————————————————————————————————————————————————————————————
下面介绍基类 C_AO。C_AO 总体结构。公有成员。公有成员为类外部可访问的字段与方法。
全局最优 / 最差解状态数据:
- cB [] — 算法全局最优解坐标数组;
- cW [] — 算法全局最差解坐标数组;
- fB — 全局最优解对应的适应度(与 cB 匹配);
- fW — 全局最差解对应的适应度(与 cW 匹配)。
注意区分:此处为全局最优 / 最差,S_AO_Agent 内部 fB、fW 仅属于单个智能体。
种群与参数相关数据:
- a [] — S_AO_Agent 数组。代表智能体种群,每个智能体对应一组候选解;
- params [] — S_AlgoParam 数组。存放算法自定义参数(影响系数、概率等),支持外部配置。
- revision — 状态标记,用于控制迭代更新流程。
- SetParams () — 参数配置方法;派生类内部填充 params 参数数组。
- Init () — 算法主初始化方法。接收搜索区间、步长、迭代轮数。初始化成功返回 true。
- Moving () — 实现智能体在搜索空间移动、演化逻辑。它是算法核心。
- Revision () — 算法状态更新、校验阶段。
- Injection () — 向指定智能体的坐标注入指定数值。
搜索空间参数:
- rangeMin [] — 每一维坐标下限;
- rangeMax [] — 每一维坐标上限;
- rangeStep [] — 每一维坐标步长;适用于离散搜索空间,决定搜索粒度。
算法内部参数组:
- coords — 搜索空间维度数量。
- popSize — 种群规模(智能体总数)。
辅助工具对象:u — 工具类实例,封装通用函数,如随机数生成、数学运算等。
受保护标准初始化方法:StandardInit () 供所有派生算法调用,执行通用初始化流程。以系统当前时间作为随机数种子初始化随机生成器;将全局最优适应度 fB 初始化为负无穷、全局最差适应度 fW 初始化为正无穷,用于后续持续追踪最优、最差解;还将 revision 标记置为 false,校验并设置维度数量 coords;根据维度扩容 rangeMin、rangeMax、rangeStep、cB、cW 数组;根据种群规模 popSize 扩容智能体数组 a;逐个调用智能体自身 Init (),初始化内部坐标数组。它将传入的搜索区间拷贝至内部变量;初始化成功返回 true,数组长度不匹配等异常场景返回 false。
C_AO 作为所有优化算法具体实现的基类。每一款新优化算法(AO 派生实现)都继承自 C_AO,并重写 SetParams、Init、Moving、Revision、Injection 等虚方法,实现专属搜索逻辑,而 StandardInit () 封装通用初始化流程,避免大量重复代码。
//—————————————————————————————————————————————————————————————————————————————— class C_AO { public: //-------------------------------------------------------------------- C_AO () { } ~C_AO () { } double cB []; //best coordinates double cW []; //worst coordinates double fB; //FF of the best coordinates double fW; //FF of the worst coordinates S_AO_Agent a []; //agents S_AlgoParam params []; //algorithm parameters bool revision; virtual void SetParams () { } virtual bool Init (const double &rangeMinP [], //minimum search range const double &rangeMaxP [], //maximum search range const double &rangeStepP [], //step search const int epochsP = 0) //number of epochs { return false;} virtual void Moving () { } virtual void Revision () { } virtual void Injection (const int popPos, const int coordPos, const double value) { } string GetName () { return ao_name;} string GetDesc () { return ao_desc;} string GetLink () { return ao_link;} string GetParams () { string str = ""; for (int i = 0; i < ArraySize (params); i++) { str += (string)params [i].val + "|"; } return str; } protected: //----------------------------------------------------------------- string ao_name; //ao name; string ao_desc; //ao description string ao_link; //ao link double rangeMin []; //minimum search range double rangeMax []; //maximum search range double rangeStep []; //step search int coords; //coordinates number int popSize; //population size C_AO_Utilities u; //auxiliary functions bool StandardInit (const double &rangeMinP [], //minimum search range const double &rangeMaxP [], //maximum search range const double &rangeStepP []) //step search { int seed = (int)GetTickCount64 (); MathSrand (seed); //reset of the generator fB = -DBL_MAX; fW = DBL_MAX; revision = false; coords = ArraySize (rangeMinP); if (coords == 0 || coords != ArraySize (rangeMaxP) || coords != ArraySize (rangeStepP)) return false; ArrayResize (rangeMin, coords); ArrayResize (rangeMax, coords); ArrayResize (rangeStep, coords); ArrayResize (cB, coords); ArrayResize (cW, coords); ArrayResize (a, popSize); for (int i = 0; i < popSize; i++) a [i].Init (coords); ArrayCopy (rangeMin, rangeMinP, 0, 0, WHOLE_ARRAY); ArrayCopy (rangeMax, rangeMaxP, 0, 0, WHOLE_ARRAY); ArrayCopy (rangeStep, rangeStepP, 0, 0, WHOLE_ARRAY); return true; } }; //——————————————————————————————————————————————————————————————————————————————
测试结果
现在让我们看看A3算法的运行结果。小规模种群下的平均结果。
A3|人工原子算法|30.0|0.2|
=============================
5 Hilly's;函数运行次数:10000;结果:0.7074464987418227
25 Hilly's;函数运行次数:10000;结果:0.49461443027863367
500 Hilly's;函数运行次数:10000;结果:0.27674325929370214
=============================
5 Forest's;函数运行次数:10000;结果:0.8910275237236067
25 Forest's;函数运行次数:10000;结果:0.43888040941642725
500 Forest's;函数运行次数:10000;结果:0.17553299655770818
=============================
5 Megacity's;函数运行次数:10000;结果:0.5323076923076923
25 Megacity's;函数运行次数:10000;结果:0.3270769230769231
500 Megacity's;函数运行次数:10000;结果:0.11430769230769337
=============================
总得分:3.95794 (43.98%)
可视化结果显示,在低维函数上结果分布较为分散(绿色线条所示),值得注意的是,这些解对搜索空间的覆盖较好。

A3 在Hilly测试函数上的表现

A3 在Forest测试函数上的表现

A3 在Megacity测试函数上的表现
本文的算法评级表仅作信息参考,不构成结论性评价。
| # | 算法 | 说明 | Hilly | Hilly 最终结果 | Forest | Forest 最终结果 | Megacity (离散) | Megacity 最终结果 | 最终 结果 | % of MAX | ||||||
| 10 p (5 F) | 50 p (25 F) | 1000 p (500 F) | 10 p (5 F) | 50 p (25 F) | 1000 p (500 F) | 10 p (5 F) | 50 p (25 F) | 1000 p (500 F) | ||||||||
| 1 | ANS | 交叉邻近搜索 | 0.94948 | 0.84776 | 0.43857 | 2.23581 | 1.00000 | 0.92334 | 0.39988 | 2.32323 | 0.70923 | 0.63477 | 0.23091 | 1.57491 | 6.134 | 68.15 |
| 2 | CLA | 代码锁定算法(JOO) | 0.95345 | 0.87107 | 0.37590 | 2.20042 | 0.98942 | 0.91709 | 0.31642 | 2.22294 | 0.79692 | 0.69385 | 0.19303 | 1.68380 | 6.107 | 67.86 |
| 3 | AMOm | 动物迁徙优化M | 0.90358 | 0.84317 | 0.46284 | 2.20959 | 0.99001 | 0.92436 | 0.46598 | 2.38034 | 0.56769 | 0.59132 | 0.23773 | 1.39675 | 5.987 | 66.52 |
| 4 | (P+O)ES | (P+O) 进化策略 | 0.92256 | 0.88101 | 0.40021 | 2.20379 | 0.97750 | 0.87490 | 0.31945 | 2.17185 | 0.67385 | 0.62985 | 0.18634 | 1.49003 | 5.866 | 65.17 |
| 5 | CTA | 彗尾算法(JOO) | 0.95346 | 0.86319 | 0.27770 | 2.09435 | 0.99794 | 0.85740 | 0.33949 | 2.19484 | 0.88769 | 0.56431 | 0.10512 | 1.55712 | 5.846 | 64.96 |
| 6 | TETA | 时间演化旅行算法(JOO) | 0.91362 | 0.82349 | 0.31990 | 2.05701 | 0.97096 | 0.89532 | 0.29324 | 2.15952 | 0.73462 | 0.68569 | 0.16021 | 1.58052 | 5.797 | 64.41 |
| 7 | SDSm | 随机扩散搜索 M | 0.93066 | 0.85445 | 0.39476 | 2.17988 | 0.99983 | 0.89244 | 0.19619 | 2.08846 | 0.72333 | 0.61100 | 0.10670 | 1.44103 | 5.709 | 63.44 |
| 8 | BOAm | 台球优化算法 M | 0.95757 | 0.82599 | 0.25235 | 2.03590 | 1.00000 | 0.90036 | 0.30502 | 2.20538 | 0.73538 | 0.52523 | 0.09563 | 1.35625 | 5.598 | 62.19 |
| 9 | AAm | 射箭算法 M | 0.91744 | 0.70876 | 0.42160 | 2.04780 | 0.92527 | 0.75802 | 0.35328 | 2.03657 | 0.67385 | 0.55200 | 0.23738 | 1.46323 | 5.548 | 61.64 |
| 10 | ESG | 社会群体的进化(JOO) | 0.99906 | 0.79654 | 0.35056 | 2.14616 | 1.00000 | 0.82863 | 0.13102 | 1.95965 | 0.82333 | 0.55300 | 0.04725 | 1.42358 | 5.529 | 61.44 |
| 11 | SIA | 模拟各向同性退火(JOO) | 0.95784 | 0.84264 | 0.41465 | 2.21513 | 0.98239 | 0.79586 | 0.20507 | 1.98332 | 0.68667 | 0.49300 | 0.09053 | 1.27020 | 5.469 | 60.76 |
| 12 | EOm | 极值优化算法_M | 0.76166 | 0.77242 | 0.31747 | 1.85155 | 0.99999 | 0.76751 | 0.23527 | 2.00277 | 0.74769 | 0.53969 | 0.14249 | 1.42987 | 5.284 | 58.71 |
| 13 | BBO | 基于生物地理学的优化算法 | 0.94912 | 0.69456 | 0.35031 | 1.99399 | 0.93820 | 0.67365 | 0.25682 | 1.86867 | 0.74615 | 0.48277 | 0.17369 | 1.40261 | 5.265 | 58.50 |
| 14 | ACS | 人工协同搜索 | 0.75547 | 0.74744 | 0.30407 | 1.80698 | 1.00000 | 0.88861 | 0.22413 | 2.11274 | 0.69077 | 0.48185 | 0.13322 | 1.30583 | 5.226 | 58.06 |
| 15 | DA | 辩证算法 | 0.86183 | 0.70033 | 0.33724 | 1.89940 | 0.98163 | 0.72772 | 0.28718 | 1.99653 | 0.70308 | 0.45292 | 0.16367 | 1.31967 | 5.216 | 57.95 |
| 16 | BHAm | 黑洞算法 M | 0.75236 | 0.76675 | 0.34583 | 1.86493 | 0.93593 | 0.80152 | 0.27177 | 2.00923 | 0.65077 | 0.51646 | 0.15472 | 1.32195 | 5.196 | 57.73 |
| 17 | ASO | 无政府社会优化 | 0.84872 | 0.74646 | 0.31465 | 1.90983 | 0.96148 | 0.79150 | 0.23803 | 1.99101 | 0.57077 | 0.54062 | 0.16614 | 1.27752 | 5.178 | 57.54 |
| 18 | RFO | 皇家同花顺优化算法 (JOO) | 0.83361 | 0.73742 | 0.34629 | 1.91733 | 0.89424 | 0.73824 | 0.24098 | 1.87346 | 0.63154 | 0.50292 | 0.16421 | 1.29867 | 5.089 | 56.55 |
| 19 | AOSm | 原子轨道搜索 M | 0.80232 | 0.70449 | 0.31021 | 1.81702 | 0.85660 | 0.69451 | 0.21996 | 1.77107 | 0.74615 | 0.52862 | 0.14358 | 1.41835 | 5.006 | 55.63 |
| 20 | TSEA | 龟壳进化算法(JOO) | 0.96798 | 0.64480 | 0.29672 | 1.90949 | 0.99449 | 0.61981 | 0.22708 | 1.84139 | 0.69077 | 0.42646 | 0.13598 | 1.25322 | 5.004 | 55.60 |
| 21 | BSA | 回溯搜索算法 | 0.97309 | 0.54534 | 0.29098 | 1.80941 | 0.99999 | 0.58543 | 0.21747 | 1.80289 | 0.84769 | 0.36953 | 0.12978 | 1.34700 | 4.959 | 55.10 |
| 22 | DE | 差分进化 | 0.95044 | 0.61674 | 0.30308 | 1.87026 | 0.95317 | 0.78896 | 0.16652 | 1.90865 | 0.78667 | 0.36033 | 0.02953 | 1.17653 | 4.955 | 55.06 |
| 23 | SRA | 成功餐饮经营者算法(joo) | 0.96883 | 0.63455 | 0.29217 | 1.89555 | 0.94637 | 0.55506 | 0.19124 | 1.69267 | 0.74923 | 0.44031 | 0.12526 | 1.31480 | 4.903 | 54.48 |
| 24 | CRO | 化学反应优化 | 0.94629 | 0.66112 | 0.29853 | 1.90593 | 0.87906 | 0.58422 | 0.21146 | 1.67473 | 0.75846 | 0.42646 | 0.12686 | 1.31178 | 4.892 | 54.36 |
| 25 | BIO | 血缘遗传优化算法 (JOO) | 0.81568 | 0.65336 | 0.30877 | 1.77781 | 0.89937 | 0.65319 | 0.21760 | 1.77016 | 0.67846 | 0.47631 | 0.13902 | 1.29378 | 4.842 | 53.80 |
| 26 | BSA | 鸟群算法 | 0.89306 | 0.64900 | 0.26250 | 1.80455 | 0.92420 | 0.71121 | 0.24939 | 1.88479 | 0.69385 | 0.32615 | 0.10012 | 1.12012 | 4.809 | 53.44 |
| 27 | DEA | 海豚回声定位算法 | 0.75995 | 0.67572 | 0.34171 | 1.77738 | 0.89582 | 0.64223 | 0.23941 | 1.77746 | 0.61538 | 0.44031 | 0.15115 | 1.20684 | 4.762 | 52.91 |
| 28 | HS | 和声搜索算法 | 0.86509 | 0.68782 | 0.32527 | 1.87818 | 0.99999 | 0.68002 | 0.09590 | 1.77592 | 0.62000 | 0.42267 | 0.05458 | 1.09725 | 4.751 | 52.79 |
| 29 | SSG | 树苗播种和生长算法 | 0.77839 | 0.64925 | 0.39543 | 1.82308 | 0.85973 | 0.62467 | 0.17429 | 1.65869 | 0.64667 | 0.44133 | 0.10598 | 1.19398 | 4.676 | 51.95 |
| 30 | BCOm | 细菌趋化优化算法M | 0.75953 | 0.62268 | 0.31483 | 1.69704 | 0.89378 | 0.61339 | 0.22542 | 1.73259 | 0.65385 | 0.42092 | 0.14435 | 1.21912 | 4.649 | 51.65 |
| 31 | ABO | 非洲水牛优化 | 0.83337 | 0.62247 | 0.29964 | 1.75548 | 0.92170 | 0.58618 | 0.19723 | 1.70511 | 0.61000 | 0.43154 | 0.13225 | 1.17378 | 4.634 | 51.49 |
| 32 | (PO)ES | (PO) 进化策略 | 0.79025 | 0.62647 | 0.42935 | 1.84606 | 0.87616 | 0.60943 | 0.19591 | 1.68151 | 0.59000 | 0.37933 | 0.11322 | 1.08255 | 4.610 | 51.22 |
| 33 | FBA | 基于分形的算法 | 0.79000 | 0.65134 | 0.28965 | 1.73099 | 0.87158 | 0.56823 | 0.18877 | 1.62858 | 0.61077 | 0.46062 | 0.12398 | 1.19537 | 4.555 | 50.61 |
| 34 | TSm | 禁忌搜索优化算法 | 0.87795 | 0.61431 | 0.29104 | 1.78330 | 0.92885 | 0.51844 | 0.19054 | 1.63783 | 0.61077 | 0.38215 | 0.12157 | 1.11449 | 4.536 | 50.40 |
| 35 | BSO | 头脑风暴优化 | 0.93736 | 0.57616 | 0.29688 | 1.81041 | 0.93131 | 0.55866 | 0.23537 | 1.72534 | 0.55231 | 0.29077 | 0.11914 | 0.96222 | 4.498 | 49.98 |
| 36 | WOAm | 鲸鱼优化算法M | 0.84521 | 0.56298 | 0.26263 | 1.67081 | 0.93100 | 0.52278 | 0.16365 | 1.61743 | 0.66308 | 0.41138 | 0.11357 | 1.18803 | 4.476 | 49.74 |
| 37 | AEFA | 人工电场算法 | 0.87700 | 0.61753 | 0.25235 | 1.74688 | 0.92729 | 0.72698 | 0.18064 | 1.83490 | 0.66615 | 0.11631 | 0.09508 | 0.87754 | 4.459 | 49.55 |
| 38 | AEO | 基于人工生态系统的优化算法 | 0.91380 | 0.46713 | 0.26470 | 1.64563 | 0.90223 | 0.43705 | 0.21400 | 1.55327 | 0.66154 | 0.30800 | 0.28563 | 1.25517 | 4.454 | 49.49 |
| 39 | CAm | 骆驼算法 M | 0.78684 | 0.56042 | 0.35133 | 1.69859 | 0.82772 | 0.56041 | 0.24336 | 1.63149 | 0.64846 | 0.33092 | 0.13418 | 1.11356 | 4.444 | 49.37 |
| 40 | ACOm | 蚁群优化 M | 0.88190 | 0.66127 | 0.30377 | 1.84693 | 0.85873 | 0.58680 | 0.15051 | 1.59604 | 0.59667 | 0.37333 | 0.02472 | 0.99472 | 4.438 | 49.31 |
| 41 | CMAES | 协方差矩阵自适应进化策略 | 0.76258 | 0.72089 | 0.00000 | 1.48347 | 0.82056 | 0.79616 | 0.00000 | 1.61672 | 0.75846 | 0.49077 | 0.00000 | 1.24923 | 4.349 | 48.33 |
| 42 | BFO-GA | 细菌觅食优化 - ga | 0.89150 | 0.55111 | 0.31529 | 1.75790 | 0.96982 | 0.39612 | 0.06305 | 1.42899 | 0.72667 | 0.27500 | 0.03525 | 1.03692 | 4.224 | 46.93 |
| 43 | SOA | 简单优化算法 | 0.91520 | 0.46976 | 0.27089 | 1.65585 | 0.89675 | 0.37401 | 0.16984 | 1.44060 | 0.69538 | 0.28031 | 0.10852 | 1.08422 | 4.181 | 46.45 |
| 44 | ABHA | 人工蜂巢算法 | 0.84131 | 0.54227 | 0.26304 | 1.64663 | 0.87858 | 0.47779 | 0.17181 | 1.52818 | 0.50923 | 0.33877 | 0.10397 | 0.95197 | 4.127 | 45.85 |
| 45 | ACMO | 大气云层模型优化 | 0.90321 | 0.48546 | 0.30403 | 1.69270 | 0.80268 | 0.37857 | 0.19178 | 1.37303 | 0.62308 | 0.24400 | 0.10795 | 0.97503 | 4.041 | 44.90 |
| A3 | 人工原子算法 | 0.70744 | 0.49461 | 0.27674 | 1.47879 | 0.89102 | 0.43888 | 0.17553 | 1.50543 | 0.53230 | 0.32707 | 0.11431 | 0.97368 | 3.958 | 43.98 | |
| RW | 随机游走 | 0.48754 | 0.32159 | 0.25781 | 1.06694 | 0.37554 | 0.21944 | 0.15877 | 0.75375 | 0.27969 | 0.14917 | 0.09847 | 0.52734 | 2.348 | 26.09 | |
总结
本文完成了人工原子算法 A3 基于 MQL5 语言的实现,可用于解决交易策略参数优化问题。尽管原论文作者对算法理论描述存在内容缺失,我们仍然完成了一套可正常运行的工程实现版本。测试结果表明,A3 算法在运行速度与解的质量之间取得了良好平衡。该算法仅设置两个可调参数,极大简化了针对具体任务的调参工作,这对于对并非优化专家的交易者而言尤为重要。
A3 算法可能会在优化方法中占据一定的应用位置。人工原子算法证明:即便结构相对简单的元启发式算法,只要针对特定领域合理适配,依然可能相当有效。兼具原理简洁、计算高效、解质量可靠等优势,让 A3 成为算法交易者工具箱中实用的优化工具。
算法源代码以及应用示例附于文章附录,感兴趣的读者可自行验证该算法的运行效率,并开展相关实验。

图 1. 各算法在对应测试下的色彩渐变图。

图 2. 算法测试结果直方图(比例从 0 到 100,越高越好,其中 100 是最大可能的理论结果,存档中有一个用于计算评级表的脚本)
A3 算法的优点和缺点
优点:
- 速度快。
- 参数少。
缺点:
- 收敛精度低。
文章附件中附带包含最新版算法代码的压缩包。作者不对文中经典算法描述的绝对准确性承担责任。其中许多算法均经过修改,以提升搜索能力。文章中表述的结论和论断是基于实验的结果。
本文使用的程序
| # | 名称 | 类型 | 说明 |
|---|---|---|---|
| 1 | #C_AO.mqh | 库 | 种群优化算法的父类 |
| 2 | #C_AO_enum.mqh | 库 | 种群优化算法枚举 |
| 3 | TestFunctions.mqh | 库 | 测试函数库 |
| 4 | TestStandFunctions.mqh | 库 | 测试台函数库 |
| 5 | Utilities.mqh | 库 | 辅助函数库 |
| 6 | CalculationTestResults.mqh | 库 | 用于计算对比表中结果的脚本 |
| 7 | Testing AOs.mq5 | 脚本 | 所有种群优化算法的统一测试平台 |
| 8 | Simple use of population optimization algorithms.mq5 | 脚本 | 一个不包含可视化功能的种群优化算法使用示例 |
| 9 | Test_AO_A3.mq5 | 脚本 | A3 测试平台 |
本文由MetaQuotes Ltd译自俄文
原文地址: https://www.mql5.com/ru/articles/18958
注意: MetaQuotes Ltd.将保留所有关于这些材料的权利。全部或部分复制或者转载这些材料将被禁止。
本文由网站的一位用户撰写,反映了他们的个人观点。MetaQuotes Ltd 不对所提供信息的准确性负责,也不对因使用所述解决方案、策略或建议而产生的任何后果负责。
从基础到中级:对象(三)
精通日志记录(第十部分):通过抑制机制避免日志重复输出
神经网络实践:熟能生巧
我也是,第一次读的时候确实有点难懂,哈哈。这个想法听起来很有意思,但当共价键/离子键的规则以及电子分配的规则不太明确时,很难正确评估这个算法。
对我来说,最有用的部分应该是一个简单的分步示例,比如包含2个原子和几个变量,然后具体展示一次迭代如何改变解。如果没有这些,这更像是一个概念,而不是交易员能够真正理解或测试的内容。
真是个疯狂的概念。接下来请写写“大爆炸理论”的优化概念吧
我的评价
试想一下,有100个孩子 正在公园里寻找一个藏起来的玩具。
每个孩子从不同的位置出发。
算法是这样运行的:
每当有孩子试图走出公园时,算法就会说:
最终,由于所有孩子都会向那些找到更好路径的孩子学习,整个群体便会越来越接近那个玩具。
简而言之:
真是个疯狂的概念。下次请写写关于大爆炸理论优化的概念吧
;D
https://www.mql5.com/zh/articles/16963