利用回归衡量度评估 ONNX 模型(基础篇)
📘

利用回归衡量度评估 ONNX 模型(基础篇)

第 1/3 篇

用回归指标给 ONNX 模型打分

在 MT5 里跑 ONNX 推理模型做行情预测,光看预测曲线和真实价格贴不贴是不够的,得有量化误差手段。回归衡量度(Regression Measure)就是一套现成的尺子,能直接反映模型输出和真实值之间的偏离程度。 常用的几个指标里,MSE(均方误差)和 MAE(平均绝对误差)最直观:MSE 对大偏差更敏感,MAE 则更抗异常点。如果模型在样本外连续多根 K 线 MSE 持续走高,说明过拟合概率偏大,该回炉重训。 这篇示例发布于 2023 年 12 月 18 日,在 MetaQuotes 官方渠道获得 1688 次查看,说明用回归指标评估 ONNX 预测精度是实盘前绕不开的一步。打开 MT5 终端,接好你的 .onnx 模型,先把历史回测的误差分布打出来,再决定要不要上真金白银——外汇和贵金属杠杆高,模型飘了就是实亏。

「回归衡量度与损失函数的边界」

回归任务的本质,是用一组未标记样本去逼近某个连续真实值。最直观的例子是按克拉重量、色泽、净度等特征估算钻石价格——输出不是分类标签,而是一个数值。 在建模时容易混淆两个概念:损失函数和回归衡量度。前者出现在你把建模转成优化问题时,比如梯度下降要求它可微、凸性好;后者是站在模型之外的客观准则,只看预测值与真值的偏差,不依赖模型内部参数。 实操意义很直接:调参阶段盯损失函数,模型定型后必须用衡量度(如 RMSE、MAE)做横向比较。把优化目标当成品判据,可能选出在训练集上乖巧但样本外偏差大的模型。外汇与贵金属预测属高风险场景,历史衡量度优不代表未来概率占优。

◍ MQL5 自带的七种回归误差指标

在 MT5 的策略回测与模型验证里,MQL5 已经内置了七类回归衡量度,足以覆盖从线性拟合到百分比偏差的常见诊断需求:平均绝对误差(MAE)、均方误差(MSE)、均方根误差(RMSE)、R 平方(R2)、平均绝对百分比误差(MAPE)、均方百分比误差(MSPE)以及均方根对数误差(RMSLE)。 这些指标并非摆设。比如 RMSE 对异常值更敏感,适合排查少数极端预测;MAPE 以百分比呈现,跨品种对比模型偏差时比 MAE 更直观。外汇与贵金属波动结构差异大,用同一组衡量度横向比较不同品种模型,需警惕尺度误导,属高风险操作。 目前 MQL5 公开的回归衡量度数量为 7 个,官方预计后续版本还会扩充。写 EA 或指标时,直接调用内置函数比手搓误差计算更稳,也方便和小布盯盘的输出做交叉验证。

回归误差指标怎么选不踩坑

MAE 量的是预测值跟实际值差多少,单位和目标函数一致。看它不能脱离数值区间:目标在 1~1.5 之间时平均绝对误差 10 就是离谱,但目标在 10000~15000 时就还能接受;它不适合扩散很大的样本。 MSE 靠平方给大误差加权,预测和现实差得越远越显眼。RMSE 继承了 MSE 的优点,但单位回到原尺度更好读,对异常尖峰敏感。RMSE 永远 ≥ MAE,两者差得越大说明样本里独立误差扩散越广;若 RMSE = MAE,则所有误差幅度一致。 R2 看两个随机变量的关系强度,模型全中就是 1,泛泛模型是 0,比乱猜还差可能为负。MAPE 无量纲,MQL5 里是小数,0.1 即真实值 10% 偏差,适合看相对偏离但不给真实量纲任务用。MSPE 是 MSE 的反平方加权版,观测值越大误差权重越小;RMSLE 用于跨数量级且不能为负的实际值。 外汇与贵金属波动大、杠杆高,这些指标只对历史样本说话,实盘仍属高风险,开 MT5 把 VectorRegressionMetric.mqh 拉进来跑一遍最直观。

「EURUSD D1 的四个 ONNX 回归模型」

实盘里接 ONNX 做日线收盘预测,这套方案用的是 4 个回归模型,输入都是 EURUSD 日线前一根已收盘的柱线,输出是当天收盘价预估。模型文件已经训好,命名对应不同窗口或结构:model.eurusd.D1.10、model.eurusd.D1.30、model.eurusd.D1.52、model.eurusd.D1.63,都随文打包在 zip 的对应目录里。 训练脚本放在 Python 子文件夹,想复训改参直接跑就行;外汇 EURUSD 波动受宏观与流动性影响,模型输出只是概率倾向,实盘前务必在 MT5 用历史数据回测验证。 之前几篇已经拆过 MQL5 里包装和调用 ONNX 的具体写法,这一节不重复训练规则,重点是把现成模型接进 EA 跑通日线级信号。

◍ 给 ONNX 包装类加上任意时间点预测能力

把推理从“只能看当前柱”解放出来,关键改动在基类的 PredictPrice 和 PredictClass 方法里塞进一个 datetime 参数。这样一来,预测向量既能用实时行情拼,也能拿历史某根 K 线的时间戳去回测,验证模型在过往时点的输出倾向。 下面这段头文件骨架定义了 CModelSymbolPeriod 基类,它按品种和时间周期绑定训练数据。注意 m_next_bar 只认柱开头,m_class_delta 默认 0.0001,用来在回归模型里界定“价格近似不变”的区间,外汇和贵金属波动下这个阈值可能要按点值重调。 代码里 PRICE_UP、PRICE_SAME、PRICE_DOWN 分别宏定义为 0、1、2,是分类模型的三态输出约定。构造函数接收 symbol、period 和 class_delta,析构直接调 Shutdown 释放模型会话句柄,避免 MT5 端会话泄漏。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//|                                                                 ModelSymbolPeriod.mqh |
class=class="str">"cmt">//|                                         Copyright class="num">2023, MetaQuotes Ltd. |
class=class="str">"cmt">//|                                                     [MQL5官方文档] |
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//--- price movement prediction
class="macro">#define PRICE_UP    class="num">0
class="macro">#define PRICE_SAME class="num">1
class="macro">#define PRICE_DOWN class="num">2
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Base class for models based on trained symbol and period               |
class=class="str">"cmt">//+------------------------------------------------------------------+
class CModelSymbolPeriod
  {
class="kw">protected:
   class="type">class="kw">string            m_name;            class=class="str">"cmt">// model name
   class="type">long              m_handle;          class=class="str">"cmt">// created model session handle
   class="type">class="kw">string            m_symbol;          class=class="str">"cmt">// symbol of trained data
   ENUM_TIMEFRAMES   m_period;          class=class="str">"cmt">// timeframe of trained data
   class="type">class="kw">datetime          m_next_bar;        class=class="str">"cmt">// time of next bar(we work at bar begin only)
   class="type">class="kw">double            m_class_delta;     class=class="str">"cmt">// delta to recognize "price the same" in regression models
class="kw">public:
   class=class="str">"cmt">//+------------------------------------------------------------------+
   class=class="str">"cmt">//| Constructor                                                      |
   class=class="str">"cmt">//+------------------------------------------------------------------+
   CModelSymbolPeriod(class="kw">const class="type">class="kw">string symbol,class="kw">const ENUM_TIMEFRAMES period,class="kw">const class="type">class="kw">double class_delta=class="num">0.0001)
     {
      m_name="";
      m_handle=INVALID_HANDLE;
      m_symbol=symbol;
      m_period=period;
      m_next_bar=class="num">0;
      m_class_delta=class_delta;
     }
   class=class="str">"cmt">//+------------------------------------------------------------------+
   class=class="str">"cmt">//| Destructor                                                       |
   class=class="str">"cmt">//+------------------------------------------------------------------+
   ~CModelSymbolPeriod(class="type">void)
     {
      Shutdown();
     }
   class=class="str">"cmt">//+------------------------------------------------------------------+

常见问题

优先看 RMSE 和 MAE 的相对大小,RMSE 对大误差更敏感,MAE 更直观;两者差距过大说明模型有偶发极端预测,需排查。
不是。损失函数用于反向传播优化,衡量度只做离线评估;评估指标不能直接当损失用,否则优化方向可能失真。
可以。小布能读取你导出的预测与真实值序列,直接算出七种回归指标并排展示,省去手写脚本。
先看样本外 RMSE 稳定性,再比 MAPE 是否低于 5%;差异在 1% 内优先选推理更快的模型。
检查时间索引对齐和特征滞后窗口,多数错位来自预测时刻取了未来特征;用已知日期回测校准一次即可。