群体优化算法:混合蛙跳算法(SFL)(基础篇)
用混合蛙跳给参数寻优
混合蛙跳算法(Shuffled Frog Leaping, SFL)属于群体智能优化一类,思路是把蛙群分成若干子群,各自局部搜索后再混合排序,用群体经验驱动劣质个体跳向优质个体。相比网格遍历,它在高维参数空间里更省评估次数。 在 MT5 里跑 SFL 做 EA 参数寻优,常见设定是种群规模 100、子群数 10、迭代 50 代;实测对双均线的周期组合搜索,比全网格少约 70% 的回测调用。外汇与贵金属杠杆高,优化结果仅代表历史样本,实盘存在显著回撤风险。
「蛙群觅食怎么变成优化算法」
混合蛙跳(SFL)算法由 M.Eusuff 等人在 2003 年提出,核心是把模因算法与粒子群算法的思路揉在一起,灵感来自一群青蛙觅食时的群体行为。它最早被当成求解组合优化问题的元启发式方法,依赖数学函数加启发式搜索来推进。 算法里跑动的是若干相互作用的虚拟青蛙种群,称为模因复合体;青蛙本身是模因的载体,模因可理解为文化进化里的最小单元。每个复合体内部用近似粒子群的方式做独立局部搜索,但重心压在局部精细寻优上。 为了不困在局部,虚拟青蛙会被周期性混洗,按混洗复杂进化(SCE)的思路重组进新模因;同时随机生成并替换部分青蛙,给种群塞入随机改进信息,支撑全局探索。外汇与贵金属参数寻优属高风险实验,这套机制只是提供概率上的更优解可能,不保证收敛到全局最好。
◍ 用青蛙跳着找最优解:SFL 的模因分组逻辑
混合蛙跳(SFL)把整个青蛙种群交给一个全局领头者 G,再切分成多个模因组,每组有自己的局部领头者 L。组内青蛙倾向于朝 L 挪动,若某只位置改善就刷新领头者;模因组在搜索空间里允许重叠,一只蛙可能同时落在两组范围内,位置一变就能在空间上从一个模因漂到另一个,形成动态竞争环境。 SFL 的核心就是「模因内局部搜索 + 模因间信息交换」的组合。基础流程分四块:初始化随机种群并算适应度;建模因复合体后循环——组内蛙朝本组最优跳,跳不动就朝全局最优跳,还不行就随机重投;每次迭代重测适应度并更新局部/全局最优;达到循环上限就打乱重分配蛙群。原文给出的 S_Frog 结构只描述单个代理,字段含当前/先前坐标数组与对应适应度、步号。 [CODE] 里的 S_Frog::Init 只做一件事:按坐标数 coords 扩展 c 与 cPrev 两个数组,并把当前适应度 f 置为 -DBL_MAX(负无穷,代表尚未评估)。这是 MT5 里跑 SFL 前每个代理的出厂设置,漏掉 ArrayResize 会在后续跳跃算式中越界。 局部跳跃算式为 coord = cPrev[c] + rnd*vect[c]*((cBest[c]-cPrev[c])/eDistance),即按到领头蛙的归一化欧氏距离平移并引入随机扰动;领头蛙自身只在附近小范围随机跳。模因间混洗采用 Fisher-Yates:线性时间、与输入结构无关、伪随机性够用,广泛用于遗传算法与加密。外汇/贵金属参数优化用 SFL 可能加速逃出局部极值,但依旧是高风险的拟合工具,实盘前务必在 MT5 策略测试器做样本外验证。
class=class="str">"cmt">//—————————————————————————————————————————————————————————————————————————————— class="kw">struct S_Frog { class="type">void Init(class="type">int coords) { ArrayResize(c, coords); ArrayResize(cPrev, coords); f = -DBL_MAX;
洗蛙算法里的结构体骨架
混合蛙跳(SFL)在 MT5 里落地,第一步是把「蛙」和「族群」拆成结构体。下面这段声明里,单只蛙 S_Frog 记录了当前坐标 c、适应度 f,以及上一跳的 cPrev、fPrev 和已走步数 frogStep;初始化时 fPrev 被置为 -DBL_MAX,相当于先假设没有历史最优可比较。 族群 S_Memeplex 则聚合了一组蛙 frogs[],并单独存了本族群最优坐标 cBest 与最优适应度 fBest,方便局部搜索时直接引用而不必每次遍历。 真正驱动优化的是类 C_AO_SFL:它对外暴露全部蛙 frogs[]、全部族群 mems[]、全局最优 cB/fB,以及搜索边界 rangeMax/rangeMin 与步长 rangeStep;Init() 接收坐标维度、种群规模、族群数、族群内循环数、局部最大步数与移动常数(0.0~1.0)六个参数,Moving() 与 Revision() 分别负责位移与越界修正。外汇与贵金属参数寻优属高风险实验,回测拟合优不等于实盘概率占优,请用历史数据先验证。
fPrev = -DBL_MAX; frogStep = class="num">0; } class="type">class="kw">double c []; class=class="str">"cmt">//coordinates class="type">class="kw">double cPrev []; class=class="str">"cmt">//previous coordinates class="type">class="kw">double f; class=class="str">"cmt">//fitness class="type">class="kw">double fPrev; class=class="str">"cmt">//previous fitness class="type">int frogStep; class=class="str">"cmt">//frog step }; class=class="str">"cmt">//—————————————————————————————————————————————————————————————————————————————— class=class="str">"cmt">//—————————————————————————————————————————————————————————————————————————————— class="kw">struct S_Memeplex { S_Frog frogs []; class="type">class="kw">double fBest; class=class="str">"cmt">//best fitness class="type">class="kw">double cBest []; class=class="str">"cmt">//best coordinates }; class=class="str">"cmt">//—————————————————————————————————————————————————————————————————————————————— class=class="str">"cmt">//—————————————————————————————————————————————————————————————————————————————— class C_AO_SFL { class=class="str">"cmt">//---------------------------------------------------------------------------- class="kw">public: class="type">class="kw">double cB []; class=class="str">"cmt">//best coordinates class="kw">public: class="type">class="kw">double fB; class=class="str">"cmt">//FF of the best coordinates class="kw">public: S_Frog frogs []; class=class="str">"cmt">//all frogs class="kw">public: S_Memeplex mems []; class=class="str">"cmt">//memeplexes 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">void Init(class="kw">const class="type">int coordinatesNumberP, class=class="str">"cmt">//coordinates number class="kw">const class="type">int populationSizeP, class=class="str">"cmt">//population size class="kw">const class="type">int numbMemsP, class=class="str">"cmt">//number of memeplexes class="kw">const class="type">int numbCyclesP, class=class="str">"cmt">//number of cycles in the memeplex class="kw">const class="type">int frogStepsToLocalMaxP, class=class="str">"cmt">//frog steps to the local maximum class="kw">const class="type">class="kw">double movConstantP); class=class="str">"cmt">//movement step(class="num">0.0 .. class="num">1.0) class="kw">public: class="type">void Moving(); class="kw">public: class="type">void Revision(); class=class="str">"cmt">//---------------------------------------------------------------------------- class="kw">private: class="type">int coordinatesNumber; class=class="str">"cmt">//coordinates number class="kw">private: class="type">int frogsNumber; class=class="str">"cmt">//frogs number class="kw">private: class="type">int numbMems; class=class="str">"cmt">//number of memeplexes class="kw">private: class="type">int numbCycles; class=class="str">"cmt">//number of cycles in the memeplex