珊瑚礁优化算法(CRO)(基础篇)
「珊瑚礁优化在 MT5 里的落地起点」
珊瑚礁优化算法(CRO)把种群搜索类比成珊瑚虫在礁区的繁殖与杂交,用「水播 / 碎播」两种扩张模拟全局与局部探索。相比网格或遗传的单一交叉,它靠礁体占用率动态压竞争,适合多峰参数面。 在 MT5 中它不走内置遗传优化器,而是以 EA 形式外接:把待优参数写进输入组,每代把种群状态通过全局变量回写终端。作者 Andrey Dik 于 2026-04-17 发布的实现帖获 440 次查看、0 条跟评,说明该思路在中文圈还偏冷门。 想验证可行性,直接开 MT5 加载其 EA,把历史品种切到 XAUUSD 的 H1,跑 200 代看参数收敛带宽度;外汇与贵金属杠杆高,回测顺滑不等于实盘稳健,结论仅作概率参考。
用珊瑚礁博弈改写优化搜索
- 年 S. Salcedo-Sanz 等人提出的珊瑚礁优化(CRO)算法,把珊瑚繁殖、空间竞争和弱势死亡搬进了数学搜索框架。它模拟群体产卵、体内受精、无性繁殖三类机制,让解在有限「礁石空间」里互相挤占,弱解消亡、强解留存,从而在不规则搜索空间里找到近优解。
标准 CRO 靠自然平衡维持全局探索与局部开发,但收敛节奏偏慢。我们改出一版 CROm:在最优解邻域用逆幂律分布生成新解,淘汰机制不再均匀随机,而是长尾式偏向高潜力区。这样探索能力不丢,锁定的搜索区域更准,收敛速度可能更快。 在经典基准函数上跑过广泛测试,CROm 对多模态目标和复杂空间结构的问题提升尤其明显,对比原版 CRO 与若干现代元启发式都有概率优势。外汇与贵金属参数寻优属高风险场景,这类算法只降低盲搜成本,不保证实盘收益。
◍ 把珊瑚礁竞争写成 MT5 优化类
CRO 把优化解看成礁石上的珊瑚,礁石是 N×M 二维网格,每个格子空或被占。初始占用率 ρ₀∈(0,1),实际放珊瑚数是 ⌊ρ₀×N×M⌋,且受 popSize 限制;图例里给过一组可调值:ρ₀=0.6、群体产卵 Fb=0.9、无性 Fa=0.1、淘汰 Fd=0.1 且 Pd=0.05、幼虫尝试 k=3。 在 MT5 里落地时,作者建了 C_AO_CRO 类继承 C_AO。关键参数直接暴露成字段:reefRows/reefCols 定网格,rho0 定起始密度,Fb/Fa/Fd/Pd/attemptsNum 控繁殖与淘汰。SetParams() 吃 params 数组,能在跑的过程中热改参数,不用重编译。 Init() 先调基类 StandardInit,再算 totalReefSize、initialPopSize,清 occupied[] 和 reefIndices[],交 InitReef() 随机占格并离散化坐标(u.SeInDiSp 按 rangeStep 控步长)。Moving() 不直接算适应度,只扫 occupied 里有效 idx 并置 revision=true,保证每轮只触发一次评估;Revision() 才找更优解、生 larvae、跑 BroadcastSpawning/Brooding/LarvaSettling/AsexualReproduction/Depredation。 LarvaSettling 是核心:幼虫最多 attemptsNum 次随机选格,空格就占、被占且 f(幼虫)>f(原主) 就替换,全失败返回 -1。BroadcastSpawning 按 Fb 选占格珊瑚两两平均坐标加微扰;Brooding 对剩余 1-Fb 做变异;AsexualReproduction 按 Fa 克隆最优点;Depredation 以 Pd 概率删最差 Fd 比例。外汇/贵金属参数优化用这套,过拟合风险高,建议拿历史段先回测再上实盘。
class=class="str">"cmt">//—————————————————————————————————————————————————————————————————————————————— class C_AO_CRO : class="kw">public C_AO {
「珊瑚礁优化算法的初始化参数怎么配」
在 MT5 里用珊瑚礁优化(CRO)做指标或 EA 的底层寻优时,构造函数里先把种群结构和繁殖销毁比例钉死,是后续跑通的前提。下面这段就是该类默认初始化的核心:种群规模 50,礁盘按 20×20 排布,初始占用率 rho0 设 0.2,意味着开局只有约 80 个珊瑚位被占。 广播产卵比例 Fb=0.99、无性繁殖 Fa=0.01,说明算法几乎靠交叉扩散找解,自我复制极少;淘汰率 Fd=0.8 配销毁概率 Pd=0.9,代表每轮大概率清掉八成旧珊瑚,搜索抖动很猛。 SetParams 负责把外部参数数组回写进成员变量,注意 rho0 到 Pd 都是 double,popSize/reefRows/reefCols 则强转 int。你在 MQ5 里改这些数前,先想清楚:外汇和贵金属杠杆高、滑点乱,这种高淘汰率优化在实盘可能过拟合,调参后务必用历史数据验证。
class="kw">public: class=class="str">"cmt">//-------------------------------------------------------------------- ~C_AO_CRO() { } C_AO_CRO() { ao_name = "CRO"; ao_desc = "Coral Reef Optimization"; ao_link = "[MQL5官方文档] popSize = class="num">50; class=class="str">"cmt">// population size reefRows = class="num">20; class=class="str">"cmt">// reef height reefCols = class="num">20; class=class="str">"cmt">// reef width rho0 = class="num">0.2; class=class="str">"cmt">// initial reef occupancy Fb = class="num">0.99; class=class="str">"cmt">// fraction of corals for broadcast spawning Fa = class="num">0.01; class=class="str">"cmt">// fraction of corals for asexual reproduction Fd = class="num">0.8; class=class="str">"cmt">// fraction of corals to remove Pd = class="num">0.9; class=class="str">"cmt">// probability of destruction attemptsNum = class="num">20; class=class="str">"cmt">// number of attempts for larvae to settle ArrayResize(params, class="num">9); params [class="num">0].name = "popSize"; params [class="num">0].val = popSize; params [class="num">1].name = "reefRows"; params [class="num">1].val = reefRows; params [class="num">2].name = "reefCols"; params [class="num">2].val = reefCols; params [class="num">3].name = "rho0"; params [class="num">3].val = rho0; params [class="num">4].name = "Fb"; params [class="num">4].val = Fb; params [class="num">5].name = "Fa"; params [class="num">5].val = Fa; params [class="num">6].name = "Fd"; params [class="num">6].val = Fd; params [class="num">7].name = "Pd"; params [class="num">7].val = Pd; params [class="num">8].name = "attemptsNum"; params [class="num">8].val = attemptsNum; } class="type">void SetParams() { popSize = (class="type">int)params [class="num">0].val; reefRows = (class="type">int)params [class="num">1].val; reefCols = (class="type">int)params [class="num">2].val; rho0 = params [class="num">3].val; Fb = params [class="num">4].val; Fa = params [class="num">5].val; Fd = params [class="num">6].val;
珊瑚礁优化器的类成员与私有结构
这段声明把珊瑚礁优化(CRO)算法的核心状态都压进了一个类里。reefRows 与 reefCols 决定礁盘网格的高宽,totalReefSize 即两者乘积,是私有成员里实际参与寻址的总容量。 公开的 rho0、Fb、Fa、Fd、Pd、attemptsNum 分别对应初始占用率、有性广播比例、无性繁殖比例、清除比例、破坏概率和幼虫定居尝试次数;其中 Pd 与 attemptsNum 由外部参数数组下标 7 和 8 注入,说明调参入口固定在 params[7]、params[8]。 Init 方法接收 rangeMinP、rangeMaxP、rangeStepP 和 epochsP,明确了搜索区间与步长走构造函数式注入,而不是硬编码。 私有侧用 occupied[] 标记网格占用,reefIndices[] 做占用单元到 agent 数组的映射,避免了每次遍历全网格。辅助方法如 LarvaSettling、BroadcastSpawning、Brooding、AsexualReproduction、Depredation 把一代繁殖—破坏循环拆得很细,在 MT5 里照这个类骨架改 Fb/Fd 比值,可能直接改变收敛速度与全局逃逸能力。外汇与贵金属品种上跑这类元启发式优化,仍属高风险,参数过拟合概率不低。
Pd = params [class="num">7].val; attemptsNum = (class="type">int)params [class="num">8].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">// search step 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 reefRows; class=class="str">"cmt">// reef height class="type">int reefCols; class=class="str">"cmt">// reef width class="type">class="kw">double rho0; class=class="str">"cmt">// initial reef occupancy class="type">class="kw">double Fb; class=class="str">"cmt">// fraction of corals for broadcast spawning class="type">class="kw">double Fa; class=class="str">"cmt">// fraction of corals for asexual reproduction class="type">class="kw">double Fd; class=class="str">"cmt">// fraction of corals to remove class="type">class="kw">double Pd; class=class="str">"cmt">// probability of destruction class="type">int attemptsNum; class=class="str">"cmt">// number of attempts for larvae to settle class="kw">private: class=class="str">"cmt">//------------------------------------------------------------------- class="type">int totalReefSize; class=class="str">"cmt">// total reef size class="type">bool occupied []; class=class="str">"cmt">// flags of reef cell occupancy class="type">int reefIndices []; class=class="str">"cmt">// agent indices in a[] corresponding to occupied cells class=class="str">"cmt">// Auxiliary methods class="type">void InitReef(); class="type">int LarvaSettling(S_AO_Agent &larva); class="type">void BroadcastSpawning(S_AO_Agent &larvae [], class="type">int &larvaCount); class="type">void Brooding(S_AO_Agent &larvae [], class="type">int &larvaCount); class="type">void AsexualReproduction(); class="type">void Depredation(); class="type">int GetReefCoordIndex(class="type">int row, class="type">int col); class="type">void SortAgentsByFitness(class="type">int &indices [], class="type">int &count); };