基于分形的算法(FBA)·综合运用
子空间采样与变异的落地写法
种群初始化时,按各子空间 promisingRank 占 totalRank 的比例分配生成点数,再用 MathMin 卡住 popSize 上限,避免越界。 下面这段是子空间内均匀撒点的核心循环:先按区间随机,再 Snap 到离散网格。
class="type">int pointsToGenerate = (class="type">int)MathRound((subspaces[i].promisingRank / totalRank) * popSize); pointsToGenerate = MathMin(pointsToGenerate, popSize - points); for (class="type">int j = class="num">0; j < pointsToGenerate; j++) { for (class="type">int c = class="num">0; c < coords; c++) { a[points].c[c] = u.RNDfromCI(subspaces[i].min[c], subspaces[i].max[c]); a[points].c[c] = u.SeInDiSp(a[points].c[c], rangeMin[c], rangeMax[c], rangeStep[c]); } points++; if (points >= popSize) break; }
class="type">int pointsToGenerate = (class="type">int)MathRound((subspaces[i].promisingRank / totalRank) * popSize); pointsToGenerate = MathMin(pointsToGenerate, popSize - points); for (class="type">int j = class="num">0; j < pointsToGenerate; j++) { for (class="type">int c = class="num">0; c < coords; c++) { a[points].c[c] = u.RNDfromCI(subspaces[i].min[c], subspaces[i].max[c]); a[points].c[c] = u.SeInDiSp(a[points].c[c], rangeMin[c], rangeMax[c], rangeStep[c]); } points++; if (points >= popSize) break; }
「用快排给指标缓冲区位次重排」
在自研 AO 类里做排序,不要去动原始价格数组,而是排一个 indices 下标数组,这样既能拿到顺序又能回查原柱。上面这段 QuickSort 是个标准递归实现:当 low < high 时先切分,再对左右两段各自递归。 Partition 是核心。它取末位下标对应的值为轴点,遍历 low 到 high-1,按 ascending 决定是小于轴点还是大于轴点往前压;只交换 indices 不碰 values,最后把轴点归位并返回切分点。 实盘意义在于:排完 indices 后,indices[0] 就是最小(或最大)柱的原位置,做分形背离或聚类时直接按位次取,不用反复扫描。外汇与贵金属波动跳变多,排序前务必确认 size>1,否则递归会越界。 代码里 ascending 为 true 走升序、false 走降序,切换只需改入口参数,MT5 里编译后可在策略测试器用 Print(indices[0]) 验证首位是哪根 K。
if (size > class="num">1) QuickSort(values, indices, class="num">0, size - class="num">1, ascending); } class=class="str">"cmt">//—————————————————————————————————————————————————————————————————————————————— class=class="str">"cmt">//+----------------------------------------------------------------------------+ class=class="str">"cmt">//| Quick sort algorithm | class=class="str">"cmt">//+----------------------------------------------------------------------------+ class="type">void C_AO_FBA::QuickSort(class="type">class="kw">double &values [], class="type">int &indices [], class="type">int low, class="type">int high, class="type">bool ascending) { if (low < high) { class="type">int pi = Partition(values, indices, low, high, ascending); QuickSort(values, indices, low, pi - class="num">1, ascending); QuickSort(values, indices, pi + class="num">1, high, ascending); } } class=class="str">"cmt">//—————————————————————————————————————————————————————————————————————————————— class=class="str">"cmt">//+----------------------------------------------------------------------------+ class=class="str">"cmt">//| Partition function for QuickSort | class=class="str">"cmt">//+----------------------------------------------------------------------------+ class="type">int C_AO_FBA::Partition(class="type">class="kw">double &values [], class="type">int &indices [], class="type">int low, class="type">int high, class="type">bool ascending) { class="type">class="kw">double pivot = values [indices [high]]; class="type">int i = low - class="num">1; for (class="type">int j = low; j < high; j++) { class="type">bool condition = ascending ? (values [indices [j]] < pivot) : (values [indices [j]] > pivot); if (condition) { i++; class=class="str">"cmt">// Exchange values class="type">int temp = indices [i]; indices [i] = indices [j]; indices [j] = temp; } } class=class="str">"cmt">// Exchange values class="type">int temp = indices [i + class="num">1]; indices [i + class="num">1] = indices [high]; indices [high] = temp; class="kw">return i + class="num">1; } class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————
◍ 分形算法在基准函数上的实测表现
把 FBA(基于分形的搜索算法)丢进三组标准测试函数跑了一遍:Hilly、Forest、Megacity,每组各取 5 / 25 / 500 个峰值的地形,函数调用次数统一锁在 10000。低维(5 峰)下寻优率最高,Hilly 拿到 0.790、Forest 0.872、Megacity 0.611;一旦拉到 500 峰高维,三项分别跌到 0.290、0.189、0.124,衰减非常陡。 横向排进 40 个算法的榜单,FBA 总分 4.555(相当于满分项的 50.61%),卡在第 29 位。榜首 ANS 跨邻域搜索是 6.134(68.15%),两者差距约 1.58 分;紧挨在前的 (PO)ES 是 4.610,身后的禁忌搜索 4.536——这个区段算法互相只差零点零几,实战替换意义不大。 可视化里能看清 FBA 的套路:把搜索空间递归切小,靠分形结构保持低维时的多样性。但高维一上来,细分带来的覆盖盲区就放大了。做 MT5 上的参数寻优时,它适合当 5~25 维问题的备胎,别指望直接啃 500 维的黑盒优化。
优化器横向跑分里藏着的实盘信号
上面这组对照把 11 个优化器的三目标结果摊开了:CGO 混沌博弈优化在第三目标拿到 0.19028,综合得分 3.902、耗时 43.35,而 RW 神经 Boid 优化算法 2 综合仅 2.348、耗时 26.09。数字本身不预言涨跌,但能看出一点——跑得快的算法未必综合强,RW 耗时砍掉近 40% 却丢了三分之一分数。 做 MT5 参数寻优时,别只盯最终回测收益。像 CROm 珊瑚礁优化 M 在第二目标 0.86688 领先,但第三目标 1.00703 偏厚,说明它容易把止损区间撑大,贵金属这种高波动品种上可能放大滑点风险。 拿去验证的方法很简单:把 EA 的 optimization 模式切到对应算法,固定 gen 数与种群规模,跑完导出的 csv 直接比对第三列标准差。哪组数值收敛更紧,哪组参数在 live 账户上踩坑概率倾向更低。
「画得少,看得清」
变异版 FBA 把原始效率翻了一倍,综合评分 2.33696(折算 25.97%),在 5/25/500 组 Hilly、Forest、Megacity 地形各跑 10000 次函数求值里,结果从 0.478 一路掉到 0.098,说明维度越高它越能咬住前景解。核心改动是弃用纯随机变异,改用搜索中积累的空间分布信息引导扰动,让全局探索和局部开发的比例更顺。 中高维函数上它表现稳,但低维结果离散度偏大,底层理念仍偏轻量。MT5 里直接挂 Test_FBA.mq5 或 Simple use of population optimization algorithms.mq5 就能复现那张直方图,调 popSize 和变异引导系数看曲线怎么塌。 外汇与贵金属算法回测和实盘偏差大、杠杆风险高,任何优化结论都只是概率倾向,别把 25.97% 当保本线。跑完把渐变图截下来比对,比读长篇描述更快知道这版值不值得继续改。