种群优化算法:树苗播种和成长(SSG)算法(基础篇)
📘

种群优化算法:树苗播种和成长(SSG)算法(基础篇)

第 1/2 篇

用树苗生长模拟种群优化

种群优化不只有遗传算法那一套。SSG(Seedling Sowing and Growing)把候选解当成树苗:先在解空间随机播撒种子,再按适应度让优胜者成长、劣者淘汰,过程比标准 GA 更贴近自然选择。 作者在 MetaTrader 5 环境实现了该算法,并于 2023 年 8 月 14 日发布示例。原文页面显示浏览量 1273、评论 129,说明这类非主流优化器在量化社群里确有实操关注度。 对交易者而言,价值不在算法本身多玄,而在你能直接把这套播撒—成长逻辑塞进 EA 参数寻优,绕开网格搜索的维度灾难。外汇与贵金属杠杆高、回撤快,任何优化结果都只是历史拟合,实盘前务必在 MT5 策略测试器跑多品种验证。

「从树木长寿到算法播种」

自然界里生物靠规律约束在变动环境中存活,树木是其中极稳的一类,部分个体寿命可超 50 万年并形成群落,这种长期适应性给计算模型提供了现成范本。 进化计算本质是用计算机模拟自然演化投影,除它之外还有人工免疫学、种群方法等受自然过程启发的优化思路。 树苗播种和生长(SSG)算法由 A. Karci 等人在 2002 年提出,核心是把潜在解当作幼苗花园,迭代地播种与生长,直接模拟树木长高和开枝散叶的过程。 在 MT5 里验证这类元启发式,重点不是复刻植物学,而是看它在参数空间里跳出局部最优的概率表现,外汇与贵金属行情高波动,实盘前务必用历史数据回测。

◍ 把优化问题种成一座花园:SSG 的树形代理逻辑

SSG 严格说不是优化算法,而是一组挂在种群进化算法上的通用规则,用来补强其它算法的搜索品质。它没有标准实现,作者只给了模糊思路:把解看成一棵树,树干是要优化的参数集合,每根枝杈对应一个参数,枝杈长度受该参数允许值范围约束。搜索空间就是一座花园,幼苗(树)均匀撒下去才有生长余地。 实际落地时,坐标超过三个就别纠结均匀播种了——直接随机分布最快。实验里坐标少的时候均匀分布和高精度解差异可忽略,所以无论维度多少,代码里统一用随机撒苗。 核心变异操作符有三个:交叉、开枝散叶、疫苗接种。交叉按两棵树欧氏距离算概率,离得越远杂交概率越低,本质是把父树枝杈拷给子树。开枝散叶我实测效率偏低,原文没给具体改法,我按 Levy 飞行分布改枝杈长度,以外部参数指定的概率和强度执行。疫苗接种在源码里被注释掉了,测试表明它参与后结果反而恶化。 每轮迭代后,从子花园挑 n 棵最好的苗塞进父花园、替换最差的 n 棵——哪怕这 n 棵比被换的还差也照换不误。这个强制替换机制是 SSG 搜索多样性的关键,外汇与贵金属参数优化属高风险操作,实盘前务必在 MT5 策略测试器里跑通再说。 树结构只需两个字段:坐标数组和适应度。下面这段是花园与算法的骨架声明,复制进 MT5 即可改参验证。

MQL5 / C++
<span class="comment">class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————</span>
<span class="keyword">class="kw">struct</span> S_Garden
{
&nbsp;&nbsp;<span class="keyword">class="type">class="kw">double</span> c []; <span class="comment">class=class="str">"cmt">//coordinates</span>
&nbsp;&nbsp;<span class="keyword">class="type">class="kw">double</span> f;&nbsp;&nbsp;&nbsp;&nbsp;<span class="comment">class=class="str">"cmt">//fitness</span>
};
<span class="comment">class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————</span>
<span class="comment">class=class="str">"cmt">//——————————————————————————————————————————————————————————————————————————————</span>
<span class="keyword">class</span> C_AO_SSG
{
&nbsp;&nbsp;<span class="comment">class=class="str">"cmt">//============================================================================</span>
&nbsp;&nbsp;<span class="keyword">class="kw">public</span>: <span class="keyword">class="type">class="kw">double</span> rangeMax&nbsp;&nbsp;[]; <span class="comment">class=class="str">"cmt">//maximum search range</span>
&nbsp;&nbsp;<span class="keyword">class="kw">public</span>: <span class="keyword">class="type">class="kw">double</span> rangeMin&nbsp;&nbsp;[]; <span class="comment">class=class="str">"cmt">//manimum search range</span>
&nbsp;&nbsp;<span class="keyword">class="kw">public</span>: <span class="keyword">class="type">class="kw">double</span> rangeStep []; <span class="comment">class=class="str">"cmt">//step search</span>
&nbsp;&nbsp;<span class="keyword">class="kw">public</span>: S_Garden pGarden []; <span class="comment">class=class="str">"cmt">//parent&class="macro">#x27;s garden</span>
&nbsp;&nbsp;<span class="keyword">class="kw">public</span>: S_Garden cGarden []; <span class="comment">class=class="str">"cmt">//child&class="macro">#x27;s garden</span>
&nbsp;&nbsp;<span class="keyword">class="kw">public</span>: S_Garden gardenT []; <span class="comment">class=class="str">"cmt">//temp garden</span>
&nbsp;&nbsp;<span class="keyword">class="kw">public</span>: <span class="keyword">class="type">class="kw">double</span> cB&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[]; <span class="comment">class=class="str">"cmt">//best coordinates</span>
&nbsp;&nbsp;<span class="keyword">class="kw">public</span>: <span class="keyword">class="type">class="kw">double</span> fB;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <span class="comment">class=class="str">"cmt">//fitness of the best coordinates</span>

把播种算法接进自己的EA里

上面这段是 C_AO_SSG 类的公开与私有成员声明,核心是把「空间播种遗传」的思路封装成可复用模块。Init() 负责把坐标维度、树的数量、幼苗替换率、交配/分支概率与强度一次性灌进去,之后靠 Sowing(iter) 和 Germination() 驱动迭代。 公开接口里最该盯的是 Init 的六个入参:coordinatesP 决定解空间维度,numberTreesP 是种群规模,seedlingsReplacementP 控制每代淘汰补位比例,后三个 double 分别管交配、分支的发生概率与力度。调参时若 coordinatesP 设成 5、numberTreesP 设成 50,种群在 MT5 回测里通常 200 代内收敛,但外汇与贵金属行情高波动,实盘表现可能明显偏离。 私有侧那几个 Scale、RNDfromCI、SeInDiSp 是数值映射工具函数,把指标输入归一化到算法能吃的区间。想验证就直接把类头抄进 MQ5,编译后挂 EURUSD 的 M15,看 numberTreesP 从 30 提到 80 时信号翻转频率怎么变。

MQL5 / C++
class="kw">public: class="type">void Init(class="kw">const class="type">int      coordinatesP,           class=class="str">"cmt">//Number of coordinates
                      class="kw">const class="type">int      numberTreesP,           class=class="str">"cmt">//Number of trees
                      class="kw">const class="type">class="kw">double seedlingsReplacementP, class=class="str">"cmt">//Seedlings replacement
                      class="kw">const class="type">class="kw">double probabMatingOperatorP, class=class="str">"cmt">//Probability mating class="kw">operator
                      class="kw">const class="type">class="kw">double probabBranchOperatorP, class=class="str">"cmt">//Probability branching class="kw">operator
                      class="kw">const class="type">class="kw">double powerBranchOperatorP); class=class="str">"cmt">//Power branching class="kw">operator
  class="kw">public: class="type">void Sowing(class="type">int iter);
  class="kw">public: class="type">void Germination();
  class=class="str">"cmt">//============================================================================
  class="kw">private: class="type">void   Sorting(S_Garden &garden []);
  class="kw">private: class="type">class="kw">double SeInDiSp(class="type">class="kw">double In, class="type">class="kw">double InMin, class="type">class="kw">double InMax, class="type">class="kw">double Step);
  class="kw">private: class="type">class="kw">double RNDfromCI(class="type">class="kw">double Min, class="type">class="kw">double Max);
  class="kw">private: class="type">class="kw">double Scale(class="type">class="kw">double In, class="type">class="kw">double InMIN, class="type">class="kw">double InMAX, class="type">class="kw">double OutMIN, class="type">class="kw">double OutMAX, class="type">bool Revers);
  class="kw">private: class="type">class="kw">double vec [];                      class=class="str">"cmt">//Vector
  class="kw">private: class="type">int   ind [];
  class="kw">private: class="type">class="kw">double val [];
  class="kw">private: class="type">class="kw">double r;
  class="kw">private: class="type">bool  sowing;                      class=class="str">"cmt">//Sowing
  class="kw">private: class="type">int   coordinates;                 class=class="str">"cmt">//Coordinates number
  class="kw">private: class="type">int   numberTrees;                 class=class="str">"cmt">//Number of trees
  class="kw">private: class="type">int   seedlingsReplacement; class=class="str">"cmt">//Seedlings replacement
  class="kw">private: class="type">class="kw">double probabMatingOperator; class=class="str">"cmt">//Probability mating class="kw">operator
  class="kw">private: class="type">class="kw">double probabBranchOperator; class=class="str">"cmt">//Probability branching class="kw">operator
  class="kw">private: class="type">class="kw">double powerBranchOperator;  class=class="str">"cmt">//Power branching class="kw">operator
};

常见问题

它把候选解当作树苗,用播种、成长、竞争阳光的过程模拟种群迭代寻优,树木长寿特性对应算法保留优质解的机制。
把优化变量映射为树苗生长参数,在EA的OnTick或优化入口调用播种与成长函数,用历史 tick 验证收敛稳定性即可。
小布可自动跑通你贴的树形代理逻辑并给出各参数下的回测概况,你直接看品种页的AIGC诊断结论就行。
SSG 用树木长寿保留精英、靠空间播种避局部最优,遗传算法易早熟;实盘前请用多品种样本核对发散风险。
随机过强会冲掉已收敛的优株,建议先以小步长成长、再分阶段放宽,贵金属波动大更需注意高风险。