大爆炸-大坍缩(BBBC)算法(基础篇)
◍ 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,就能复现这套去质心版本,外汇与贵金属参数优化属高风险,回测结果仅代表该算法在此基准下的概率性表现。
<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 { <span class="keyword">class="kw">public</span>: <span class="comment">class=class="str">"cmt">//--------------------------------------------------------------------</span> ~C_AO_BBBC() { } C_AO_BBBC() { ao_name = <span class="class="type">class="kw">string">"BBBC"</span>; ao_desc = <span class="class="type">class="kw">string">"Big Bang - Big Crunch Algorithm"</span>; ao_link = <span class="class="type">class="kw">string">"[MQL5官方文档] popSize = <span class="number">class="num">50</span>; bigBangPeriod = <span class="number">class="num">3</span>; ArrayResize(<span class="keyword">params</span>, <span class="number">class="num">2</span>); <span class="keyword">params</span> [<span class="number">class="num">0</span>].name = <span class="class="type">class="kw">string">"popSize"</span>; <span class="keyword">params</span> [<span class="number">class="num">0</span>].val = popSize; <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; } <span class="keyword">class="type">void</span> SetParams() { popSize = (<span class="keyword">class="type">int</span>)<span class="keyword">params</span> [<span class="number">class="num">0</span>].val; bigBangPeriod = (<span class="keyword">class="type">int</span>)<span class="keyword">params</span> [<span class="number">class="num">1</span>].val; } <span class="keyword">class="type">bool</span> Init(<span class="keyword">const</span> <span class="keyword">class="type">class="kw">double</span> &rangeMinP [], <span class="comment">class=class="str">"cmt">// minimum search range</span> <span class="keyword">const</span> <span class="keyword">class="type">class="kw">double</span> &rangeMaxP [], <span class="comment">class=class="str">"cmt">// maximum search range</span> <span class="keyword">const</span> <span class="keyword">class="type">class="kw">double</span> &rangeStepP [], <span class="comment">class=class="str">"cmt">// search step</span> <span class="keyword">const</span> <span class="keyword">class="type">int</span> epochsP = <span class="number">class="num">0</span>); <span class="comment">class=class="str">"cmt">// number of epochs</span> <span class="keyword">class="type">void</span> Moving (); <span class="keyword">class="type">void</span> Revision(); <span class="comment">class=class="str">"cmt">//----------------------------------------------------------------------------</span> <span class="keyword">class="type">int</span> bigBangPeriod; <span class="comment">class=class="str">"cmt">// Big Bang periodicity</span> <span class="keyword">class="kw">private</span>: <span class="comment">class=class="str">"cmt">//-------------------------------------------------------------------</span> <span class="keyword">class="type">int</span> epochs; <span class="comment">class=class="str">"cmt">// total number of epochs</span> <span class="keyword">class="type">int</span> epochNow; <span class="comment">class=class="str">"cmt">// current epoch</span> <span class="keyword">class="type">class="kw">double</span> centerMass []; <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> &rangeMinP [], <span class="keyword">const</span> <span class="keyword">class="type">class="kw">double</span> &rangeMaxP [], <span class="keyword">const</span> <span class="keyword">class="type">class="kw">double</span> &rangeStepP [], <span class="keyword">const</span> <span class="keyword">class="type">int</span> epochsP = <span class="number">class="num">0</span>) {