您应该知道的 MQL5 向导技术(第 01 部分):回归分析·综合运用
📊

您应该知道的 MQL5 向导技术(第 01 部分):回归分析·综合运用

(3/3)· 前两步搭好类和求解器,这篇把回归信号塞进向导、跑测试、收束整个系列

案例拆解新手友好 第 3/3 篇
很多人以为向导只能套用自带指标信号,自定义统计模型就得从头写 EA 框架。其实把回归分析封装成信号类后,向导能直接拼装,少写几百行胶水代码。

◍ 用向导拼出 ATR 挂单与尾随止损

MQL5 向导能直接组装智能系统,但想做基于 ATR 的挂单和尾随,得自己重载信号类的几个函数。本文不碰目标止盈,只盯两件事:按品种 ATR 倍数挂单,以及用同一指标拖着止损走。 向导生成的 EA 自带输入 Signal_PriceLevel,默认 0。赋负值出破位单,正值出限价单,类型是 double。我们把它 reinterpret 成 ATR 点数的乘数——比如设 1.5,就是离市价 1.5 倍当前 ATR 点数挂单。 尾随类继承 CExpertTrailing,同样吃 ATR。里面的 m_atr_weight 和信号类的 m_price_level 都做成可优化参数,控制止损贴着价格的松紧度。 下面这段是 OpenLongParams / OpenShortParams 的重载核心。无通用信号时,取 Ask 或 Bid 作基准,减去或加上 m_price_level 乘 ATR 主值再乘单位,归一化后作为挂单价,sl/tp 清零,过期时间按周期累加。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Detecting the levels for buying                                |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">bool CSignalDUAL_RA::OpenLongParams(class="type">class="kw">double &price,class="type">class="kw">double &sl,class="type">class="kw">double &tp,class="type">class="kw">datetime &expiration)
  {
   CExpertSignal *general=(m_general!=-class="num">1) ? m_filters.At(m_general) : NULL;
class=class="str">"cmt">//---
   if(general==NULL)
     {
      m_ATR.Refresh(-class="num">1);
      class=class="str">"cmt">//--- if a base price is not specified explicitly, take the current market price
      class="type">class="kw">double base_price=(m_base_price==class="num">0.0) ? m_symbol.Ask() : m_base_price;
      
      class=class="str">"cmt">//--- price overload that sets entry price to be based on ATR
      price      =m_symbol.NormalizePrice(base_price-(m_price_level*(m_ATR.Main(class="num">0)/m_symbol.Point()))*PriceLevelUnit());
      
      sl         =class="num">0.0;
      tp         =class="num">0.0;
      expiration+=m_expiration*PeriodSeconds(m_period);
      class="kw">return(true);
     }
class=class="str">"cmt">//---
   class="kw">return(general.OpenLongParams(price,sl,tp,expiration));
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Detecting the levels for selling                               |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">bool CSignalDUAL_RA::OpenShortParams(class="type">class="kw">double &price,class="type">class="kw">double &sl,class="type">class="kw">double &tp,class="type">class="kw">datetime &expiration)
  {
   CExpertSignal *general=(m_general!=-class="num">1) ? m_filters.At(m_general) : NULL;
class=class="str">"cmt">//---
   if(general==NULL)
     {
      m_ATR.Refresh(-class="num">1);
      class=class="str">"cmt">//--- if a base price is not specified explicitly, take the current market price
      class="type">class="kw">double base_price=(m_base_price==class="num">0.0) ? m_symbol.Bid() : m_base_price;
      
      class=class="str">"cmt">//--- price overload that sets entry price to be based on ATR
      price      =m_symbol.NormalizePrice(base_price+(m_price_level*(m_ATR.Main(class="num">0)/m_symbol.Point()))*PriceLevelUnit());
      
      sl         =class="num">0.0;
      tp         =class="num">0.0;
      expiration+=m_expiration*PeriodSeconds(m_period);
      class="kw">return(true);
     }
class=class="str">"cmt">//---
   class="kw">return(general.OpenShortParams(price,sl,tp,expiration));
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Checking trailing stop and/or profit for class="type">long position.         |
class=class="str">"cmt">//+------------------------------------------------------------------+

「多空双向 ATR 拖止损的判定逻辑」

在 MT5 里用 ATR 做动态追踪止损,核心不是算指标本身,而是判定位是否合法。下面这段类方法同时覆盖了多单与空单的校验,直接决定了止损线会不会被推着走。 多单分支里,先拿 Bid 减去经纪商要求的 StopsLevel 点距得到 level,这是止损能放的最近边界。new_sl 以 level 为基准再减去 ATR 主值换算成点数乘权重,意味着波动越大、止损撤得越远。 base 的取法很关键:若持仓原止损为 0,就用开仓价当底线,否则用现有止损。只有 new_sl 严格大于 base 且低于 level 时,才把新止损写回 sl,避免回缩或穿价。 空单镜像处理,用 Ask 加 StopsLevel 得 level,new_sl 向上加 ATR 距离。判定改成 new_sl 小于 base 且大于 level 才生效。外汇与贵金属杠杆高,这类自动拖损在跳空时可能滑到边界外,实盘前务必用策略测试器跑几组极端点差验证。 把 m_atr_weight 从默认 1.0 调到 1.5,回测 EURUSD H1 会发现止损触发频率下降但单笔回撤扩大,参数倾向需按品种波动个性来定。

MQL5 / C++
class="type">bool CTrailingATR::CheckTrailingStopLong(CPositionInfo *position,class="type">class="kw">double &sl,class="type">class="kw">double &tp)
  {
class=class="str">"cmt">//--- check
   if(position==NULL)
       class="kw">return(class="kw">false);
class=class="str">"cmt">//---
   m_ATR.Refresh(-class="num">1);
   class="type">class="kw">double level =NormalizeDouble(m_symbol.Bid()-m_symbol.StopsLevel()*m_symbol.Point(),m_symbol.Digits());

   class=class="str">"cmt">//--- sl adjustment to be based on ATR
   class="type">class="kw">double new_sl=NormalizeDouble(level-(m_atr_weight*(m_ATR.Main(class="num">0)/m_symbol.Point())),m_symbol.Digits());

   class="type">class="kw">double pos_sl=position.StopLoss();
   class="type">class="kw">double base  =(pos_sl==class="num">0.0) ? position.PriceOpen() : pos_sl;
class=class="str">"cmt">//---
   sl=EMPTY_VALUE;
   tp=EMPTY_VALUE;
   if(new_sl>base && new_sl<level)
       sl=new_sl;
class=class="str">"cmt">//---
   class="kw">return(sl!=EMPTY_VALUE);
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Checking trailing stop and/or profit for class="type">class="kw">short position.          |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">bool CTrailingATR::CheckTrailingStopShort(CPositionInfo *position,class="type">class="kw">double &sl,class="type">class="kw">double &tp)
  {
class=class="str">"cmt">//--- check
   if(position==NULL)
       class="kw">return(class="kw">false);
class=class="str">"cmt">//---
   m_ATR.Refresh(-class="num">1);
   class="type">class="kw">double level =NormalizeDouble(m_symbol.Ask()+m_symbol.StopsLevel()*m_symbol.Point(),m_symbol.Digits());

   class=class="str">"cmt">//--- sl adjustment to be based on ATR
   class="type">class="kw">double new_sl=NormalizeDouble(level+(m_atr_weight*(m_ATR.Main(class="num">0)/m_symbol.Point())),m_symbol.Digits());

   class="type">class="kw">double pos_sl=position.StopLoss();
   class="type">class="kw">double base  =(pos_sl==class="num">0.0) ? position.PriceOpen() : pos_sl;
class=class="str">"cmt">//---
   sl=EMPTY_VALUE;
   tp=EMPTY_VALUE;
   if(new_sl<base && new_sl>level)
       sl=new_sl;
class=class="str">"cmt">//---
   class="kw">return(sl!=EMPTY_VALUE);
  }

用策略测试器跑通挂单与市价单对比

编译是 MQL5 向导组装后的必要动作,生成 ex5 智能系统文件并确认无语法错误;之后进策略测试器「输入」选项卡,把 Signal_TakeLevel 与 Signal_StopLevel 都置 0,因为本文离场只走尾随停止或 Signal_ThresholdClose,不靠这两个阈值。 优化最好用你实盘经纪商的真实报价。本文取 2018-01-01 至 2021-01-01 的 V 型区间、EURUSD、4 小时周期,跑两组:一组只用市价单,一组开挂单(取「开立」类,Signal_PriceLevel 从负到正参与优化;若只用市价单则该参数锁 0 不优化)。 回测结果指向一个现象:挂单版本在牺牲部分利润的代价下,回撤比纯市价单更小。测试时资金管采用固定保证金百分比、优化标准设「复杂标准」。外汇与贵金属属高风险品种,历史回测不代表未来;部署前应尽量用历史 tick 数据广测并做前向验证,这一块不在本文范围内。

◍ 把回归信号接进自己的武器库

回归分析里的共线性和判定系数不是摆设,把它们当过滤条件,能帮你在 MT5 向导里搭出更稳的信号底座。这一步做完,别急着上实盘,先拿历史报价跑广泛测试,看看信号在贵金属和外汇品种上的衰减速度——这两类市场高杠杆、跳空频繁,回测漂亮不代表 live 环境能复刻。 有读者在论坛反馈,用 SignalDUAL_RA.mqh 编译 EA 时报错,根因是 _a[r].Set(c,Data(r+c,close)) 把行引用当直接编辑用了;改成 _a.Set(r,c,Data(r+c,close)) 后编译通过。这种细节不自己踩一遍,向导生成的系统永远停在纸面。 向导式 EA 默认绑图表周期,想接多周期数据得动不少地方,不止 OnInit 一处。非固定周期输入若和图表周期冲突,OnInit 会静默返回非零码 1,没报错信息才最坑。下一步值得试的,是把这套回归信号和你经验里的形态或函数库内置信号配对,组合后样本外表现倾向更平滑,但是否适合你的交易节奏,只能你开 MT5 调参验证。

MQL5 / C++
class=class="str">"cmt">//--- 专家输入
input class="type">class="kw">string Expert_Title                        ="Regr2"; class=class="str">"cmt">// 文件名称
class="type">class="kw">ulong       Expert_MagicNumber                   =class="num">26034;   class=class="str">"cmt">//
class="type">bool        Expert_EveryTick                     =class="kw">false;   class=class="str">"cmt">//
input ENUM_TIMEFRAMES   timeframe                =PERIOD_M5;       class=class="str">"cmt">//时间框架
class=class="str">"cmt">//--- 主信号输入
.
.
.
.
class="type">int OnInit()
  {
class=class="str">"cmt">//--- 专家初始化
   if(!ExtExpert.Init(Symbol(),timeframe,Expert_EveryTick,Expert_MagicNumber))
     {
class=class="str">"cmt">//--- 失败
      printf(__FUNCTION__+": error initializing expert");
      ExtExpert.Deinit();
      class="kw">return(INIT_FAILED);
     }
class=class="str">"cmt">//--- 创建信号
.
.
.
.
把回归诊断交给小布盯盘
这些回归信号的样本外表现和残差诊断,小布盯盘的 AIGC 已内置,打开对应品种页即可看到,你只管判断参数要不要重估。

常见问题

外汇贵金属属高风险,向导产物先过策略测试器历史回测,样本外表现倾向参考而非保证,实盘前务必小仓位验证。
函数可能返回无解或近似解,需在信号类里加条件判断,跳过共线性过高的价格滞后项以免 EA 报错。
目前小布内置的是诊断与看板,装配仍按本文向导步骤在 MT5 本地完成,跑完把报告贴进小布即可比对。
贵金属美盘流动性高时滑点可能仅 1–2 点,新闻期扩大,测试里按经纪商历史tick建模更贴近概率分布。
本篇侧重组装与测试,β 求解细节见《您应该知道的 MQL5 向导技术(第 01 部分):回归分析·基础篇》