种群优化算法:细菌觅食优化  遗传算法(BFO-GA)(基础篇)
📘

种群优化算法:细菌觅食优化 遗传算法(BFO-GA)(基础篇)

第 1/2 篇

◍ 细菌觅食混遗传: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 把下面结构贴上,就能自己接适应度函数跑一套。

MQL5 / C++
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 上可能陷入局部最优,实盘前务必多品种交叉验证。

MQL5 / C++
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);
};

常见问题

单独细菌觅食容易陷在局部最优,加遗传算法的交叉变异能跳出坑;BFO-GA 用菌群游动找大致方向,再用基因重组撒网,适合多峰参数寻优。
趋化步长先取参数空间的 5%~10% 试跑,变异概率 0.01~0.1 之间调;步长太大菌群散架,太小收敛慢,靠回测曲线反推。
小布可替你批量跑 BFO-GA 寻优并标出稳定参数区,你直接看诊断页的收敛图和敏感带,不用自己手写迭代循环。
细菌淘汰按单次适应度删弱者,遗传选择按代际排名留种;前者管局部存活,后者管种群进化,顺序上通常先趋化后选择。
大概率是变异概率过低或步长衰减太快,菌群早挤一团;把变异概率翻倍或加随机游动项,观察是否重新分散。