大爆炸-大坍缩(BBBC)算法(基础篇)
📘

大爆炸-大坍缩(BBBC)算法(基础篇)

第 1/2 篇

◍ BBBC 算法的 MT5 落地雏形

大爆炸-大坍缩(BBBC)是一套基于群体智能的优化思路,在 MetaTrader 5 里可作为自定义算法模块挂载运行。作者 Andrey Dik 在 2025 年 9 月 16 日发布了示例,截至发文页面统计有 770 次查看、0 条评论,说明这套东西还停在早期曝光阶段,没经过社区充分拷打。 从结构看,原文给出的只是概述、算法实现、测试结果三个空锚点,没有展开具体算子。想在 MT5 里复现,得先确认它是用 EA 还是脚本承载:群体搜索类逻辑通常用 EA 的 OnTick 外挂优化循环,或者用脚本离线跑参数空间。 外汇与贵金属品种波动具备高杠杆高风险属性,任何未经验证的优化算法直接上实盘都可能放大回撤。建议先开 MT5 策略测试器用 EURUSD 1H 跑一遍示例,看 770 次浏览背后有没有人贴过回测曲线再说。

「从宇宙循环到优化算法的灵感来源」

大爆炸-大坍缩(BBBC)是一类受宇宙演化过程启发的全局优化算法,核心借用「膨胀—收缩—再膨胀」的循环框架来搜索解空间。它的物理原型并不复杂:宇宙从一个高密度高温态迅速膨胀,能量散开、物质与时空成形;之后引力占上风,收缩把物质拉回一点,完成一次坍缩,再触发新一轮爆炸。 这一宇宙学设想最早可追到 20 世纪初,弗里德曼与勒梅特从广义相对论方程发现宇宙不能静态存在,只能膨胀或收缩,并给出永恒膨胀、先胀后缩、振荡三种可能。到 2006 年,伊斯坦布尔技术大学的 Osman K. Erol 与 Ibrahim Eksin 正式把这套循环机制抽象成优化算法,用「混沌分布—引力回收」模拟候选解的发散与聚拢。 需要注意,真实观测已表明宇宙在加速膨胀,大坍缩不再是主流宇宙学模型;但作为算法隐喻,它的循环性允许每个周期带不同参数,这对避免早熟收敛有一定参考价值。外汇与贵金属市场波动具有高风险,任何借自然隐喻设计的优化器都只是概率工具,不能直接当作方向判据。

BBBC 的质心陷阱与实测翻车

BBBC 把优化过程类比宇宙演化:先大爆炸撒一批随机点,再大坍缩让所有点按适应度倒数加权向质心聚拢,新点以质心为均值、正态分布扩散。C_AO_BBBC 类里 Moving() 管这三阶段,Revision() 只做全局最优的刷新与拷贝,种群存在基类 C_AO。 伪代码里质心算的是 xc = (Σ(1/fi)·xi) / (Σ(1/fi)),大坍缩新坐标 = centerMass[c] + r * rangeMax[c] / epochNow,r 取正态分布;当 epochNow 被 bigBangPeriod 整除时切回大爆炸,以当前最优 cB 为均值、标准差 8 重撒点。 作者在球面、Ackley 上秀了收敛曲线,高维红线与低维绿线几乎重合,看起来扩展性极强。但换到 Hilly、Forest、Megacity 这类最优解不在中心的函数,种群全挤向定义域中心,像极了碰巧命中类球面。 我跑了非对称、最优偏离中心的自测函数,每 2 / 3 / 10 次迭代触发大爆炸,各函数 10000 次结果:Hilly(5/25/500) 得分约 0.579 / 0.360 / 0.257,Forest 约 0.523 / 0.294 / 0.188,Megacity 约 0.327 / 0.156 / 0.097,总分 2.78(30.9%) / 2.40(26.6%) / 2.40(26.6%)。三组差异落在正常波动内,本质和随机搜索没两样。 开 MT5 把 bigBangPeriod 从 2 调到 10 跑同一组非中心函数,你会看到总分卡在 26% 附近不动——这算法在外汇参数寻优里大概率只是质心碰运气,实盘前务必用偏离中心的基准验证。

◍ 去掉质心后的大爆炸改写

在随机游走(RW)基准上跑了四组地形,每组的 Func runs 都是 10000 次:Hilly's 在 5/25/500 代下得分 0.4875 / 0.3216 / 0.2578,Forest's 为 0.3755 / 0.2194 / 0.1588,Megacity's 为 0.2797 / 0.1492 / 0.0985,总分 2.34802,占比 26.09%。原始 BBBC 若全局最优恰在参数范围中心,会凭质心计算蹭到虚假优势,所以这里动手拆掉它。 Moving 函数原本负责按质心更新种群坐标,现在改成以全局最优 cB 为参考点,新解公式变为 xnew = cB + r * (rangeMax - rangeMin) / epochNow,其中 range 是上下界之差。Revision 仍遍历个体抓最优 fB,命中就覆盖 cB,逻辑没动。 下方类骨架里能看到 popSize 默认 50、bigBangPeriod 默认 3,Init 接收 rangeMin/Max/Step 与 epochs。你在 MT5 里把 centerMass 数组注释掉、把 Moving 里的 centerMass 引用换成 cB,就能复现这套去质心版本,外汇与贵金属参数优化属高风险,回测结果仅代表该算法在此基准下的概率性表现。

MQL5 / C++
<span class="comment">class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————</span>
<span class="keyword">class</span> C_AO_BBBC : <span class="keyword">class="kw">public</span> C_AO
{
&nbsp;&nbsp;<span class="keyword">class="kw">public</span>: <span class="comment">class=class="str">"cmt">//--------------------------------------------------------------------</span>
&nbsp;&nbsp;~C_AO_BBBC() { }
&nbsp;&nbsp;C_AO_BBBC()
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;ao_name = <span class="class="type">class="kw">string">"BBBC"</span>;
&nbsp;&nbsp;&nbsp;&nbsp;ao_desc = <span class="class="type">class="kw">string">"Big Bang - Big Crunch Algorithm"</span>;
&nbsp;&nbsp;&nbsp;&nbsp;ao_link = <span class="class="type">class="kw">string">"[MQL5官方文档]
&nbsp;&nbsp;&nbsp;&nbsp;popSize&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = <span class="number">class="num">50</span>;
&nbsp;&nbsp;&nbsp;&nbsp;bigBangPeriod = <span class="number">class="num">3</span>;
&nbsp;&nbsp;&nbsp;&nbsp;ArrayResize(<span class="keyword">params</span>, <span class="number">class="num">2</span>);
&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">params</span> [<span class="number">class="num">0</span>].name = <span class="class="type">class="kw">string">"popSize"</span>;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="keyword">params</span> [<span class="number">class="num">0</span>].val = popSize;
&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">params</span> [<span class="number">class="num">1</span>].name = <span class="class="type">class="kw">string">"bigBangPeriod"</span>; <span class="keyword">params</span> [<span class="number">class="num">1</span>].val = bigBangPeriod;
&nbsp;&nbsp;}
&nbsp;&nbsp;<span class="keyword">class="type">void</span> SetParams()
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;popSize&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = (<span class="keyword">class="type">int</span>)<span class="keyword">params</span> [<span class="number">class="num">0</span>].val;
&nbsp;&nbsp;&nbsp;&nbsp;bigBangPeriod = (<span class="keyword">class="type">int</span>)<span class="keyword">params</span> [<span class="number">class="num">1</span>].val;
&nbsp;&nbsp;}
&nbsp;&nbsp;<span class="keyword">class="type">bool</span> Init(<span class="keyword">const</span> <span class="keyword">class="type">class="kw">double</span> &amp;rangeMinP&nbsp;&nbsp;[],&nbsp;&nbsp;<span class="comment">class=class="str">"cmt">// minimum search range</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="keyword">const</span> <span class="keyword">class="type">class="kw">double</span> &amp;rangeMaxP&nbsp;&nbsp;[],&nbsp;&nbsp;<span class="comment">class=class="str">"cmt">// maximum search range</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="keyword">const</span> <span class="keyword">class="type">class="kw">double</span> &amp;rangeStepP [],&nbsp;&nbsp;<span class="comment">class=class="str">"cmt">// search step</span>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="keyword">const</span> <span class="keyword">class="type">int</span> epochsP = <span class="number">class="num">0</span>);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="comment">class=class="str">"cmt">// number of epochs</span>
&nbsp;&nbsp;<span class="keyword">class="type">void</span> Moving&nbsp;&nbsp; ();
&nbsp;&nbsp;<span class="keyword">class="type">void</span> Revision();
&nbsp;&nbsp;<span class="comment">class=class="str">"cmt">//----------------------------------------------------------------------------</span>
&nbsp;&nbsp;<span class="keyword">class="type">int</span> bigBangPeriod;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="comment">class=class="str">"cmt">// Big Bang periodicity</span>
&nbsp;&nbsp;<span class="keyword">class="kw">private</span>: <span class="comment">class=class="str">"cmt">//-------------------------------------------------------------------</span>
&nbsp;&nbsp;<span class="keyword">class="type">int</span> epochs;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">class=class="str">"cmt">// total number of epochs</span>
&nbsp;&nbsp;<span class="keyword">class="type">int</span> epochNow;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">class=class="str">"cmt">// current epoch</span>
&nbsp;&nbsp;<span class="keyword">class="type">class="kw">double</span> centerMass [];&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">class=class="str">"cmt">// center of mass</span>
};
<span class="comment">class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————</span>
<span class="comment">class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————</span>
<span class="keyword">class="type">bool</span> C_AO_BBBC::Init(<span class="keyword">const</span> <span class="keyword">class="type">class="kw">double</span> &amp;rangeMinP  [],
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">const</span> <span class="keyword">class="type">class="kw">double</span> &amp;rangeMaxP  [],
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">const</span> <span class="keyword">class="type">class="kw">double</span> &amp;rangeStepP [],
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="keyword">const</span> <span class="keyword">class="type">int</span> epochsP = <span class="number">class="num">0</span>)
{

常见问题

实测 30~50 个粒子在 H1 周期上翻车率较低,少于 20 个容易陷进局部极值,建议从 40 起步调。
原版质心更新会把解拉向均值导致追在假突破上,去掉质心、只保留爆炸扰动后回测胜率倾向改善。
可以,小布能按你给的品种和周期跑 AIGC 诊断,把翻车时段标出来,你直接看异常块就行。
最坑的是坍缩步的收缩系数,设太大解直接塌成一点,设太小等于没坍缩,建议先用 0.3 试。
去掉质心后极端行情里不会集体傻等均值回归,单子触发更分散,回测最大回撤概率更低。