您应当知道的 MQL5 向导技术(第 08 部分):感知器·进阶篇
📘

您应当知道的 MQL5 向导技术(第 08 部分):感知器·进阶篇

第 2/2 篇

多层感知机类的成员与训练分支

这个类把归一化、基网络、训练器全部塞进 protected 区:m_norm 做数据标准化,m_base 负责建网,m_train 与 m_trainer 管训练循环,m_network 是最终的多层感知机实例。对外只暴露 ReadWeights / WriteWeights 和 Process,权重可落盘复用,避免每次重启 MT5 都重训。 建网时按 m_hidden 走不同分支:0 层隐藏层调 MLPCreateC0,1 层调 MLPCreateC1(需给 m_hidden_1_size),2 层调 MLPCreateC2(需两个隐藏层尺寸)。若 m_hidden 不在 0~2 之间,直接 printf 报错并返回 false,不会悄悄用默认结构。 数据先过 DSNormalize 算出 _means 和 _sigmas 再做训练集注入;MLPSetDataset 绑定样本数 m_training_points。训练态由 m_in_training 标记:首次 false 走 MLPStartTraining 并置真,后续命中 true 则 while 循环 MLPContinueTraining 跑到收敛。外汇与贵金属波动非线性强,这套网络仅作概率侧辅助,实盘前务必用历史数据回测验证过拟合风险。

MQL5 / C++
class="type">class="kw">double m_output_bias; class=class="str">"cmt">//
class="kw">public:
...
class="kw">protected:
  CBdSS m_norm;
  CMLPBase m_base;
  CMLPTrain m_train;
  CMatrixDouble m_xy;
  CMLPReport m_report;
  CMLPTrainer m_trainer;
  CMultilayerPerceptron m_network;

  class="type">bool m_in_training;

  class="type">int m_inputs;
  class="type">int m_outputs;

  class="type">class="kw">double m_last_long_y;
  class="type">class="kw">double m_last_short_y;

  class="type">bool ReadWeights();
  class="type">bool WriteWeights(CRowDouble &Export);

  class="type">void Process(class="type">class="kw">double &Y);
};
  m_train.MLPCreateTrainerCls(m_inputs,m_outputs,m_trainer);
  if(m_hidden==class="num">0)
  {
    m_base.MLPCreateC0(m_inputs,m_outputs,m_network);
  }
  else if(m_hidden==class="num">1)
  {
    m_base.MLPCreateC1(m_inputs,m_hidden_1_size,m_outputs,m_network);
  }
  else if(m_hidden==class="num">2)
  {
    m_base.MLPCreateC2(m_inputs,m_hidden_1_size,m_hidden_2_size,m_outputs,m_network);
  }
  else if(m_hidden>class="num">2||m_hidden<class="num">0)
  {
    printf(__FUNCSIG__+" invalid number of hidden layers should be class="num">0, class="num">1, or class="num">2. ");
    class="kw">return(false);
  }
    class=class="str">"cmt">//normalise data
    CRowDouble _means,_sigmas;
    m_norm.DSNormalize(m_xy,m_training_points,m_inputs,_info,_means,_sigmas);
    m_train.MLPSetDataset(m_trainer,m_xy,m_training_points);
    class=class="str">"cmt">//
    if(!m_in_training)
    {
       m_train.MLPStartTraining(m_trainer,m_network,false);
       m_in_training=true;
    }
    else if(m_in_training)
    {
      while(m_train.MLPContinueTraining(m_trainer,m_network))
      {
        class=class="str">"cmt">//
      }
    }

「把感知机信号塞进 EA 骨架」

在 MT5 里写自动化策略,第一步往往是借用标准库里的 CExpert 骨架,而不是从零造轮子。上面这段预处理指令就是把感知机信号模块挂到 EA 主流程里的关键接线。 #include <Expert\Expert.mqh> 拉入了核心交易类,#include <Expert\Signal\My\SignalPerceptron.mqh> 才是我们自定义的那层——把感知机输出转成多空信号。TrailingNone 表示这版先不跟自适应 trailing,MoneyFixedMargin 则按固定保证金下注,适合先跑通逻辑再调仓控。 你在 MT5 的 MQL5/Include/Expert/Signal/My 目录下丢进 SignalPerceptron.mqh 后,编译这套 include 链就能直接生成不带止损跟踪的初版 EA。外汇与贵金属杠杆高,固定保证金模式在极端波动下可能快速放大回撤,上真仓前务必用策略测试器跑至少三年 tick 数据。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Include                                                                 |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#include <Expert\Expert.mqh>
class=class="str">"cmt">//--- available signals
class="macro">#include <Expert\Signal\My\SignalPerceptron.mqh>
class=class="str">"cmt">//--- available trailing
class="macro">#include <Expert\Trailing\TrailingNone.mqh>
class=class="str">"cmt">//--- available money management
class="macro">#include <Expert\Money\MoneyFixedMargin.mqh>

◍ 把信号类打包成EA并跑回溯

在 MT5 的 EA 向导里,可以直接把写好的自定义信号类拖进智能系统框架,无需手写交易循环就能编译出可运行 EA。 先在不动参数的情况下对编译产物做历史回测,得到基准报告;再开“向前漫游窗口”做优化,相当于用滚动样本训练感知器并导出权重。 我们实测该网络在样本内有一定前景,但外汇与贵金属属高风险品种,权重仅代表训练集匹配度。更稳的做法是用内置交叉验证,或看回测报告的均方根误差(RMSE)挑较优权重存盘,后续接经纪商实时报价做更长观测再下结论。

Alglib 封装的取舍边界

用 Alglib 代码类把感知器跑起来,最直观的收益是代码量和测试耗时都被压到最低,常规化数据集、导出可调参数这些杂活都由辅助代码包办。 但封装带来便利的同时也锁死了定制空间,最硬的限制是隐藏层不能超过 2 层;碰到需要多层抽象建模的复杂行情数据,这就会成为瓶颈。 外汇与贵金属杠杆高、回撤快,直接拿现成封装做实盘前,建议先在 MT5 用历史数据跑通 2 隐藏层上限下的泛化表现,再决定是否值得自己改写底层。

常见问题

必须重写类似 train、predict、save/load 这几个成员,把权重矩阵和偏置项存好,EA 骨架才能每根 K 线调 predict 取信号。
先确认信号类头文件里没有和 EA 同名的全局变量,再把 OnTick 里的特征拼接顺序和信号类预期输入维度对齐即可过编。
可以。小布盯盘的 AIGC 能读取你的信号类结构,自动生成 EA 封装代码并跑历史回溯,你只需核对特征窗口参数。
封装层会隐藏学习率和迭代终止条件,实盘前必须手动暴露这些参数,否则训练分支在样本偏移时不会报警。
把训练集按时间切两段做滚动验证,若两段 AUC 差超 0.15 就弃用,外汇贵金属本身高风险,信号仅作概率参考。