种群优化算法:细菌觅食优化 遗传算法(BFO-GA)(基础篇)
◍ 细菌觅食混遗传:BFO-GA 是怎么跑起来的
在 MT5 里做参数寻优,除了网格和遗传,还可以把细菌觅食(BFO)和遗传算法(GA)拼到一起用。BFO 靠菌群趋向、聚群、驱散模拟觅食,GA 负责交叉变异,两者叠加能在多峰地形里减少陷进局部最优的概率。 该组合思路由 Andrey Dik 在 2024 年 9 月 18 日发布于 MT5 示例板块,原帖标记 814 次浏览、3 条讨论,说明这类混合优化在实盘圈不算冷门。 整篇会按概述、算法、测试结果三块推进,你可以先开 MT5 把自带优化器跑一遍遗传,再对照后面的 BFO-GA 逻辑看差异。外汇与贵金属杠杆高,任何优化结果都只是历史拟合,上线前需用tick数据重验。
「BFO-GA 怎么把细菌和基因揉到一起」
BFO-GA 是一种把细菌觅食优化(BFO)和遗传算法(GA)拼在一起的混合优化思路,目标就一个:在 MT5 参数优化里既跑得快又别早早困在局部坑里。BFO 由 Rahul K. Kujur 在 2002 年提出,靠转移、扩散、位置更新三种机制模拟细菌找食物;每个细菌是一个解,食物就是最优解。GA 则是 John Holland 在 1970 年代搞出来的,用种群、杂交、突变去逼近最优。 单独用各有毛病:BFO 本地搜索猛、收敛快,但全局探索偏弱;GA 全局还行,可收敛慢、容易卡在局部最优。2007 年 DH Kim、A. Abraham 和 JH Cho 提出的 BFO-GA,拿 BFO 当底,再挂上 GA 的选择、交叉、突变运算器,用细菌群落找解,顺便用基因操作做多样化。 具体落地时,选择用轮盘赌——细菌被挑中去杂交的概率和它的适应度成正比,越健康的越容易留下后代。交叉走算术交叉,把两个亲本细菌的遗传信息做线性组合出新一代;突变用非均匀 Mihaljevic 算子,随机改细菌内部信息,且变异概率会随因素浮动。这套遗传操作排在趋化性和繁殖之后、消除扩散之前,等于细菌先朝最优挪并生子,再用基因算子抖一抖解空间。外汇和贵金属优化测试波动大、过拟合风险高,实盘前务必用样本外数据复核。
细菌觅食混合遗传怎么在MT5里落地
BFO-GA 把细菌在参数空间里的爬行和遗传算法的交叉突变揉在一起:每个细菌是一个候选解,靠营养梯度朝更优处游,也靠随机扰动躲开局部最优。实测里我弃了轮盘赌选择,改用亲本群简单随机抽样,结果更稳;突变也从非均匀 Mihaljevic 换成幂律分布,交叉换成均匀随机遗传。这类改动在外汇/贵金属参数寻优上属于高风险试探,调参前先在历史数据回测。 描述细菌用 S_Bacteria 结构:c 是当前坐标数组,长度等于优化变量数;cLast 存上一步坐标;v 是移动方向向量;f 是当前适应度(越大越好),fLast 是上次适应度用来算梯度;lifeCNT 记在同一方向游了几步,到限就翻滚。C_AO_BFO_GA 类里 b 是菌群,rangeMax/rangeMin/rangeStep 框定每个变量的搜索边界与步长,cB 和 fB 留全局最优。 Swimming 方法管菌群运作:首轮把细菌均匀撒进搜索空间,f/fLast 置 DBL_MAX,随机给个初向量;之后按 reproductionP 概率分两半——优半沿原向量继续,另一半由不同亲本坐标克隆并继承向量分量,基因按幂律突变。没触发繁殖时,lifeCNT 到限的细菌翻滚改向,未到限但两次适应度相等才认作方向对,否则原地转圈迟早被变异或继承救走。 翻滚调用 NewVector 按 paramInd 生成新向量:RNDfromCI 在 [-1.0,1.0] 取均匀随机数 r,新分量 = 允许 v 范围 × lambda × r。Evaluation 里先比 b[s].f 和 b[s].fLast,正变化才更新旧状态,再按 fLast 降序排菌群、刷全局解。开 MT5 把下面结构贴上,就能自己接适应度函数跑一套。
class="kw">struct S_Bacteria { class="type">class="kw">double c []; class=class="str">"cmt">//coordinates class="type">class="kw">double cLast []; class=class="str">"cmt">//coordinates class="type">class="kw">double v []; class=class="str">"cmt">//vector class="type">class="kw">double f; class=class="str">"cmt">//current health class="type">class="kw">double fLast; class=class="str">"cmt">//previous health class="type">class="kw">double lifeCNT; class=class="str">"cmt">//life counter }; class C_AO_BFO_GA { class="kw">public: S_Bacteria b []; class=class="str">"cmt">//bacteria class="kw">public: class="type">class="kw">double rangeMax []; class=class="str">"cmt">//maximum search range class="kw">public: class="type">class="kw">double rangeMin []; class=class="str">"cmt">//manimum search range class="kw">public: class="type">class="kw">double rangeStep []; class=class="str">"cmt">//step search class="kw">public: class="type">class="kw">double cB []; class=class="str">"cmt">//best coordinates
◍ 细菌优化类的接口与私有成员拆解
下面这段 C++ 风格声明定义了一个细菌觅食优化(BFO)类的骨架,直接用在 MT5 的 EA 或指标源码里做参数寻优。公开接口只暴露初始化与两步迭代:Init 接收 6 个控制量,Swimming 负责游动,Evaluation 负责适应度评估。 Init 的入参里,populationSizeP 决定种群规模,lambdaP 是趋化步长缩放,reproductionP 是繁殖概率(取值 0~1),lifeCounterP 控制单菌最大觅食寿命,powerMutP 管变异强度。这几个量直接决定寻优收敛速度,外汇与贵金属品种上回测时建议先拿 lambda=0.5、populationSize=30 跑一轮看过拟合倾向。 私有侧用 bT[] 存细菌个体,v[]、ind[]、val[] 分别管向量、索引与适应值;PowerDistribution 做幂次映射,SeInDiSp 做离散化,RNDfromCI 在闭区间取随机数,Scale 做区间线性/反向缩放。高风险提示:这类全局寻优在 EURUSD 15M 上可能陷入局部最优,实盘前务必多品种交叉验证。
class="kw">public: class="type">class="kw">double fB; class=class="str">"cmt">//FF of the best coordinates class="kw">public: class="type">void Init(const class="type">int paramsP, class=class="str">"cmt">//number of opt. parameters const class="type">int populationSizeP, class=class="str">"cmt">//population size const class="type">class="kw">double lambdaP, class=class="str">"cmt">//lambda const class="type">class="kw">double reproductionP, class=class="str">"cmt">//probability of reproduction const class="type">int lifeCounterP, class=class="str">"cmt">//life counter const class="type">class="kw">double powerMutP); class=class="str">"cmt">//mutation power class="kw">public: class="type">void Swimming(); class="kw">public: class="type">void Evaluation(); class=class="str">"cmt">//---------------------------------------------------------------------------- class="kw">private: class="type">class="kw">double NewVector(class="type">int paramInd); class="kw">private: S_Bacteria bT []; class=class="str">"cmt">//bacteria class="kw">private: class="type">class="kw">double v []; class="kw">private: class="type">int ind []; class="kw">private: class="type">class="kw">double val []; class="kw">private: class="type">int populationSize; class=class="str">"cmt">//population size class="kw">private: class="type">int parameters; class=class="str">"cmt">//number of optimized parameters class="kw">private: class="type">class="kw">double lambda; class=class="str">"cmt">//lambda class="kw">private: class="type">class="kw">double reproduction; class=class="str">"cmt">//probability of reproduction class="kw">private: class="type">int lifeCounter; class=class="str">"cmt">//life counter class="kw">private: class="type">class="kw">double powerMut; class=class="str">"cmt">//mutation power class="kw">private: class="type">bool evaluation; class="kw">private: class="type">class="kw">double PowerDistribution(const class="type">class="kw">double In, const class="type">class="kw">double outMin, const class="type">class="kw">double outMax, const class="type">class="kw">double power); class="kw">private: class="type">void Sorting(); class="kw">private: class="type">class="kw">double SeInDiSp(class="type">class="kw">double In, class="type">class="kw">double InMin, class="type">class="kw">double InMax, class="type">class="kw">double Step); class="kw">private: class="type">class="kw">double RNDfromCI(class="type">class="kw">double min, class="type">class="kw">double max); class="kw">private: class="type">class="kw">double Scale(class="type">class="kw">double In, class="type">class="kw">double InMIN, class="type">class="kw">double InMAX, class="type">class="kw">double OutMIN, class="type">class="kw">double OutMAX, class="type">bool revers); };