中心引力优化(CFO)算法(基础篇)
📘

中心引力优化(CFO)算法(基础篇)

第 1/2 篇

「用中心引力优化给EA寻参」

中心引力优化(CFO)是一种受物理引力启发的群体智能寻参思路,在 MT5 的策略测试中可绕过传统的网格遍历,用较少评估次数逼近较优参数区。它把每个候选参数集看作一个带质量的粒子,质量由适应度(如净值或夏普)决定,粒子间按引力相互吸引并迭代更新位置。 在外汇与贵金属品种上跑 CFO 要清醒:这类市场高杠杆、跳空频繁,回测甜点参数在实盘可能迅速失效,任何优化结果都只是「概率上更优」,不是必胜解。 实际落地时,可在 MT5 的「智能交易系统测试器」里把优化模式切到对应算法(若构建版支持),先用小样本历史(例如 2024 年 1 月至 6 月 EURUSD M15)跑 50 代、种群 30,观察适应度曲线是否在 20 代内收敛;若未收敛,再考虑扩种群而非盲目加代。

◍ 把引力搬进优化空间

CFO(中心引力优化)把天体引力那套运动学直接搬进了数值优化。解空间里撒一批探测器,每个探测器带一个“质量”,质量正比于它所在点的目标函数值——好解就是大质量天体,差解是小质量天体,前者对后者产生虚拟引力场。 跟遗传、粒子群这类靠随机数翻滚的元启发式不同,CFO 核心循环是确定性的:加速度由其他探测器的合力决定,位移走牛顿运动学方程,不投骰子。这意味着同一起点同参数,跑出来结果可复现,方便在 MT5 策略优化器外先做离线条带对比。 外汇与贵金属品种波动率高、过拟合风险大,用这类确定性算法搜参数,仍要对不同年份样本做前向验证,不能默认历史引力轨迹代表未来。

把中心引力优化写成 MT5 类

中心引力优化(CFO)在 MT5 里落地时,核心是一个继承结构:S_CFO_Agent 结构体继承 S_AO_Agent,自动拿到坐标数组 c 与适应度 f,自己只补一个动态数组 a 存加速度。Init() 会按传入 coords 维度重设 c 与 a 的大小,把 a 清 0,并把 f 设成 DBL_MIN,保证任何真实评价值都能覆盖初始值。 C_AO_CFO 类包住整个种群与迭代逻辑。构造时写入 popSize、g、alpha、beta、initialFrep、finalFrep、noiseFactor;其中 frep 重定位因子从 initialFrep 起算,后面随代数线性降到 finalFrep。Init() 先调 StandardInit 校验参数区间,失败直接返 false,通过后才把 probe[] 扩到 popSize 并逐个体初始化。 Moving() 是每代主步:epochNow 自增,首次且 revision=false 时只做初始分布然后返回;之后把适应度拷到临时数组,调 UpdateRepFactor 与 CalculateAccelerations,再 UpdatePositions 并回写主数组。注意原始 CFO 是确定性算法——同初始分布跑两次结果一致,但作者在 UpdatePositions 里加了随 epoch 衰减的噪声偏移(currentNoiseFactor 从 noiseFactor 线性缩),用来躲局部极值,这让它偏离了纯确定性。 引力计算在 CalculateAccelerations 内:对每对 p、k,仅当 probe[k].f - probe[p].f > 0 才产生单向吸引;距离用 CalculateDistanceSquared 取平方省 sqrt,加速度累加公式为 probe[p].a[c] += g * MathPow(massDiff, alpha) * direction / MathPow(distance, beta),alpha 与 beta 原文默认都取 2。边界外位置由 UpdatePositions 里的 rangeMin/rangeMax 夹回,并可用 SeInDiSp 吸附到 rangeStep 倍数。外汇或贵金属参数寻优用这套高风险,实盘前务必在 MT5 策略测试器用历史数据复跑确认收敛行为。

「Revision 如何锁定群体最优解」

循环跑完之后,距离计算函数交回的是两点间距平方的累加值(sum),这个量在 CFO 里只是引力评估的底料,真正决定进化方向的是 Revision() 对全局最优的接管。 Revision 方法会挨个扫一遍 popSize 个代理,默认群体规模是 30。对每个代理 p,只要 a[p].f 比当前记录的 fB 更大,就把 fB 刷新成该代理的适应度,同时把它的坐标 cB 拷进全局缓存。 这么做的直接后果是:只要某一代理在本次迭代里把结果往前推了一点,全局参数立刻跟进,不会漏掉中途出现的局部峰值。你在 MT5 里把 popSize 从 30 调到 60,Revision 的扫描成本翻倍,但错过优解的概率倾向降低,外汇与贵金属参数优化属高风险操作,实盘前请用历史数据验证。 代理结构体里 f 初始化为 -DBL_MAX,意味着第一个被评估的合法解必然上位,不用额外写“首解保护”逻辑。

MQL5 / C++
class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————
class=class="str">"cmt">//--- CFO probe structure
class="kw">struct S_CFO_Agent : class="kw">public S_AO_Agent
{
    class="type">class="kw">double a []; class=class="str">"cmt">// acceleration vector
    class="type">void Init(class="type">int coords)
    {
        ArrayResize(c, coords);   class=class="str">"cmt">// coordinates
        ArrayResize(a, coords);   class=class="str">"cmt">// acceleration
        ArrayInitialize(a, class="num">0.0);  class=class="str">"cmt">// reset accelerations
        f = -DBL_MAX;              class=class="str">"cmt">// fitness function value
    }
};
class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————
class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————
class=class="str">"cmt">//--- Main class of the CFO algorithm
class C_AO_CFO : class="kw">public C_AO
{
  class="kw">public: class=class="str">"cmt">//--------------------------------------------------------------------
  ~C_AO_CFO() { }
  C_AO_CFO()
  {
    ao_name = "CFO";
    ao_desc = "Central Force Optimization";
    ao_link = "[MQL5官方文档]
    popSize      = class="num">30;             class=class="str">"cmt">// number of probes
    g            = class="num">1.0;            class=class="str">"cmt">// gravitational constant
    alpha        = class="num">0.1;            class=class="str">"cmt">// mass power
    beta         = class="num">0.1;            class=class="str">"cmt">// degree for distance
    initialFrep = class="num">0.9;             class=class="str">"cmt">// initial repositioning factor
    finalFrep   = class="num">0.1;             class=class="str">"cmt">// final repositioning factor
    noiseFactor = class="num">1.0;             class=class="str">"cmt">// random noise factor
    frep         = initialFrep;    class=class="str">"cmt">// current repositioning factor
    ArrayResize(params, class="num">7);
    params [class="num">0].name = "popSize";      params [class="num">0].val = popSize;
    params [class="num">1].name = "g";            params [class="num">1].val = g;
    params [class="num">2].name = "alpha";        params [class="num">2].val = alpha;
    params [class="num">3].name = "beta";         params [class="num">3].val = beta;
    params [class="num">4].name = "initialFrep";  params [class="num">4].val = initialFrep;
    params [class="num">5].name = "finalFrep";    params [class="num">5].val = finalFrep;
    params [class="num">6].name = "noiseFactor";  params [class="num">6].val = noiseFactor;
  }
  class="type">void SetParams()
  {
    popSize      = (class="type">int)MathMax(class="num">1, params [class="num">0].val);
    g            = params [class="num">1].val;

常见问题

可用中心引力优化(CFO)这类群体智能算法让参数在搜索空间里互相吸引迭代,比网格遍历省时间,直接在EA里接一个优化类跑就行。
把当前群体里表现最好的解当作引力中心,其余个体按与中心的距离和自身质量计算加速度向中心靠拢,质量通常由适应度决定。
小布盯盘的AIGC可内置这类寻参逻辑,打开对应品种页就能让它替你跑CFO流程并标出高概率参数区,你只管确认。
Revision负责每代把群体最优解强制写回中心,相当于锁定历史最好点,一般不会丢,反而能防群体发散。
不用,只初始化一次群体和随机位置,之后每代更新速度和位置即可,重复初始化会破坏已收敛的搜索状态。