群体优化算法:混合蛙跳算法(SFL)(基础篇)
📘

群体优化算法:混合蛙跳算法(SFL)(基础篇)

第 1/3 篇

用混合蛙跳给参数寻优

混合蛙跳算法(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 策略测试器做样本外验证。

MQL5 / C++
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() 分别负责位移与越界修正。外汇与贵金属参数寻优属高风险实验,回测拟合优不等于实盘概率占优,请用历史数据先验证。

MQL5 / C++
   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

常见问题

按适应度排序后轮流放进固定数量的组,每组内部做局部寻优,模因指组内经验传递,避免全局乱跳。
实战中种群30~50、迭代100~200较稳,太小搜不到、太大易拟合噪声,建议先小范围跑通再扩。
小布可接管重复寻优流程,你只需给目标函数和边界,它跑完把候选参数和回测摘要推给你。
至少存位置向量、适应度值、组号;可选存历史最优,方便局部更新和越界重置。
步长超允许范围会剪到边界,经验取搜索域的10%~30%,太大发散、太小收敛慢。