MQL5 向导:如何创建未平仓位的追踪模块·综合运用
🛰️

MQL5 向导:如何创建未平仓位的追踪模块·综合运用

(3/3)· 收尾篇把信号、资金、追踪三类打通,写出自带保护订单逻辑的 EA 骨架

新手友好 第 3/3 篇
很多人在向导里塞了自定义信号和资金管理,却仍用默认 trailing,结果保护单永远慢半拍。把追踪逻辑也拆出来重写,EA 才真正听你调度。外汇贵金属杠杆高,改仓位的时机差几点就可能吃掉当日利润。

「保本移损的类骨架怎么搭」

想把持仓止损搬到盈亏平衡,先得有个继承自 CExpertTrailing 的派生类。下面这段头文件声明了 CSampleTrailing,它只负责一件事:当浮盈达到阈值就把止损位推到开仓价,使头寸进入无亏损状态。 向导描述里写明了两个可调参数:Profit 默认 20(整数点),StopLevel 默认 0。也就是说,多单浮盈跑满 20 点后,系统倾向把止损挪到 entry 价位;StopLevel 为 0 代表不额外加止损缓冲距离。外汇与贵金属杠杆高,这种移损逻辑只降低回撤概率,不消除单边反向爆仓风险。 代码顶部用 #include <Expert\ExpertTrailing.mqh> 把基类拉进来,CSampleTrailing : public CExpertTrailing 这行就是继承关系本体。protected: 之后才是具体成员,本小节只亮出类外壳,后续再填移损判定函数。

MQL5 / C++
class=class="str">"cmt">//|                                                                 SampleTrailing.mqh |
class=class="str">"cmt">//|                     Copyright class="num">2010, MetaQuotes Software Corp. |
class=class="str">"cmt">//|                                              [MQL5官方文档] |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#class="kw">property copyright "Copyright class="num">2010, MetaQuotes Software Corp."
class="macro">#class="kw">property link      "[MQL5官方文档]
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| include files                                                                 |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#include <Expert\ExpertTrailing.mqh>
class=class="str">"cmt">// wizard description start
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Description of the class                                                      |
class=class="str">"cmt">//| Title=Moving a position to a lossless level                                  |
class=class="str">"cmt">//| Type=Trailing                                                                |
class=class="str">"cmt">//| Name=BreakEven                                                               |
class=class="str">"cmt">//| Class=CSampleTrailing                                                        |
class=class="str">"cmt">//| Page=                                                                         |
class=class="str">"cmt">//| Parameter=Profit,class="type">int,class="num">20                                                       |
class=class="str">"cmt">//| Parameter=StopLevel,class="type">int,class="num">0                                                     |
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">// wizard description end
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Class CSampleTrailing.                                                        |
class=class="str">"cmt">//| Purpose: Class for trailing of open positions                                |
class=class="str">"cmt">//|    by moving Stop order to a lossless level.                                 |
class=class="str">"cmt">//|    Is derived from the CExpertTrailing class.                                |
class=class="str">"cmt">//+------------------------------------------------------------------+
class CSampleTrailing : class="kw">public CExpertTrailing
  {
class="kw">protected:

◍ 移动止损类的参数骨架与默认值

写一个自定义移动止损模块,先把两个关键整型字段钉死:m_profit 作盈利阈值(单位通常是点),m_stop_level 作保本触发线。构造里直接给默认值 m_profit=20、m_stop_level=0,意味着不传参时按 20 点盈利才启动跟踪、0 点保本来跑。 对外暴露的设参接口就两个:Profit(int) 和 StopLevel(int),都是一行内联赋值,没有边界检查。真正拦参数的活放在 ValidationSettings() 里——它先判 m_symbol 是否为空(没 Init 就直接 false),再比对 (m_profit-m_stop_level)*m_adjusted_point 是否大于经纪商 StopsLevel()*Point(),否则返回 false。 虚函数 CheckTrailingStopLong / CheckTrailingStopShort 留作多空改仓信号生成口,入参是持仓信息和引用式的 sl、tp。你在 MT5 里把这段类壳建好,调一下 Profit(35) 就能把阈值从 20 改到 35 点,外汇和贵金属波动大,这类参数须结合品种点值手测,高风险。

MQL5 / C++
  class="type">int                m_profit;            class=class="str">"cmt">// threshold level of profit
  class="type">int                m_stop_level;        class=class="str">"cmt">// lossless level
class="kw">public:
                    CSampleTrailing();
  class=class="str">"cmt">//--- method of setting adjustable parameters
  class="type">void               Profit(class="type">int value)     { m_profit=value;     }
  class="type">void               StopLevel(class="type">int value)  { m_stop_level=value; }
  class=class="str">"cmt">//--- method of validation of adjustable settings
  class="kw">virtual class="type">bool       ValidationSettings();
  class=class="str">"cmt">//--- methods of generation of position modification signals
  class="kw">virtual class="type">bool       CheckTrailingStopLong(CPositionInfo* position,class="type">class="kw">double& sl,class="type">class="kw">double& tp);
  class="kw">virtual class="type">bool       CheckTrailingStopShort(CPositionInfo* position,class="type">class="kw">double& sl,class="type">class="kw">double& tp);
  };
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Constructor CSampleTrailing.                                      |
class=class="str">"cmt">//| INPUT:  no.                                                      |
class=class="str">"cmt">//| OUTPUT: no.                                                      |
class=class="str">"cmt">//| REMARK: no.                                                      |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void CSampleTrailing::CSampleTrailing()
  {
class=class="str">"cmt">//--- setting class="kw">default values
   m_profit    =class="num">20;
   m_stop_level=class="num">0;
  }
class=class="str">"cmt">//+------------------------------------------------------------------+
class=class="str">"cmt">//| Check of adjustable parameters.                                  |
class=class="str">"cmt">//| INPUT:  no.                                                      |
class=class="str">"cmt">//| OUTPUT: true if the parameters are correct, class="kw">false if not.        |
class=class="str">"cmt">//| REMARK: no.                                                      |
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">bool CSampleTrailing::ValidationSettings()
  {
class=class="str">"cmt">//--- what if the Init has not been called?
   if(m_symbol==NULL) class="kw">return(class="kw">false);
class=class="str">"cmt">//--- check of parameters
   if((m_profit-m_stop_level)*m_adjusted_point<=m_symbol.StopsLevel()*m_symbol.Point() && m_profit!=class="num">0.0)
     {

多空仓位止损移动的判断分支

trailing 逻辑的落地靠两个对称函数:CheckTrailingStopLong 管多单,CheckTrailingStopShort 管空单。两者都先挡掉空指针和 m_profit 为 0 的无效状态,否则直接返回 false,避免在无盈利阈值时乱改止损。 多单分支里,若持仓止损已大于等于开仓价,说明单子已进无亏损区,函数返回 false 不再处理。只有当 Bid 与开仓价之差超过 m_profit*m_adjusted_point 时,才把 sl 算成开仓价加上 m_stop_level 个微调点并归一化,否则 sl 保持 EMPTY_VALUE,函数返回 false。 空单逻辑完全镜像:止损已小于等于开仓价就退出;当开仓价减 Ask 大于 m_profit*m_adjusted_point 时,sl 设为开仓价减去 m_stop_level 个微调点。外汇与贵金属杠杆高,这类自动移动止损在滑点行情中可能失效,参数需在 MT5 策略测试器按品种点值校准。 下面两段是可直接贴进 EA 类的原始实现,注意 m_adjusted_point 与 m_symbol.NormalizePrice 的配合使用,否则跨品种可能算出非法价格。

MQL5 / C++
class="type">bool CSampleTrailing::CheckTrailingStopLong(CPositionInfo* position,class="type">class="kw">double& sl,class="type">class="kw">double& tp)
  {
class=class="str">"cmt">//--- check of pointer
   if(position==NULL) class="kw">return(class="kw">false);
class=class="str">"cmt">//--- check of parameters
   if(m_profit==class="num">0.0)  class="kw">return(class="kw">false);
class=class="str">"cmt">//--- already in a lossless zone?
   class="type">class="kw">double open=position.PriceOpen();
   if(position.StopLoss()>=open) class="kw">return(class="kw">false);
class=class="str">"cmt">//--- check of profit
   sl=EMPTY_VALUE;
   tp=EMPTY_VALUE;
   if(m_symbol.Bid()-open>m_profit*m_adjusted_point)
      sl=m_symbol.NormalizePrice(open+m_stop_level*m_adjusted_point);
class=class="str">"cmt">//---
   class="kw">return(sl!=EMPTY_VALUE);
  }

class="type">bool CSampleTrailing::CheckTrailingStopShort(CPositionInfo* position,class="type">class="kw">double& sl,class="type">class="kw">double& tp)
  {
class=class="str">"cmt">//--- check of pointer
   if(position==NULL) class="kw">return(class="kw">false);
class=class="str">"cmt">//--- check of parameters
   if(m_profit==class="num">0.0)  class="kw">return(class="kw">false);
class=class="str">"cmt">//--- already in a lossless zone?
   class="type">class="kw">double open=position.PriceOpen();
   if(position.StopLoss()<=open) class="kw">return(class="kw">false);
class=class="str">"cmt">//--- check of profit
   sl=EMPTY_VALUE;
   tp=EMPTY_VALUE;
   if(open-m_symbol.Ask()>m_profit*m_adjusted_point)
      sl=m_symbol.NormalizePrice(open-m_stop_level*m_adjusted_point);
class=class="str">"cmt">//---
   class="kw">return(sl!=EMPTY_VALUE);
  }

「空小节无内容可拆解」

本小节原文未提供任何技术正文或 MQL5 代码,仅残留一个注释片段的截断标记,无法提取可验证数据点。 若需补全该节,应回到原始材料确认第 4/5 节是否含价格行为逻辑或指标代码片段,再交由蒸馏重写。

◍ 总结

MQL5 向导的 交易策略生成器 极大简化了交易理念的检验过程。生成的 EA 交易的代码基于标准库的 交易策略类 ,用于实现某些交易信号类、资金和风险管理类以及持仓支持类。 本文介绍了如何编写自己的未平仓位管理类,以及如何将其连接至 MQL5 向导 的交易策略生成器;当价格呈持仓方向移动时,该类可将止损水平移入无损区域,从而在交易过程中减少亏损。本文还介绍了为 MQL5 向导创建的类的说明的结构和格式。 本文由MetaQuotes Ltd译自俄文 原文地址: [MQL5官方文档] 附加的文件 | 下载ZIP sampletrailing.mqh (6.46 KB) 注意: MetaQuotes Ltd.将保留所有关于这些材料的权利。全部或部分复制或者转载这些材料将被禁止。 MetaQuotes MetaQuotes 塞浦路斯 317269 www.metaquotes.net MetaQuotes MetaQuotes Ltd是一家软件开发公司。我们其中的一款产品就是MetaTrader 5交易平台,其意于在不同的金融市场进行交易。 使用以下链接下载软件的最新版本: •  MetaTrader 5 客户端- https://download.terminal.free/cdn/web/metaquotes.ltd/mt5/mt5setup.exe •  MetaTrader 5 iPhone版 - https://download.terminal.free/cdn/mobile/mt5/ios •  MetaTrader 5 Android版 - https://download.terminal.free/cdn/mobile/mt5/android 该作者的其他文章 MQL5 Algo Forge 入门 在 HarmonyOS NEXT 上安装 MetaTrader 5 和其他 MetaQuotes 应用程序 MacOS 上的 MetaTrader 5 如何在自由职业者服务中通过完成交易员的订单来赚钱 MacOS 上的 MetaTrader 4 在 ONNX 模型中使用 float16 和 float8 格式 首次启动MetaTrader VPS:分步说明 最近评论 | 前往讨论 (18) Vladimir Karputov |

  • 9月 2017 在 07:26

Andy : 使用文章中指定的模块时,在将智能交易系统加载到图表时,会在智能交易系统日志中产生错误:

  • 09.06 00:28:29.873 1 (EURUSD,M5) OnInit: 错误初始化指标
  • 09.06 00:31:20.256 1 (EURUSD,M5) CExpertBase::SetPriceSeries: 禁止更改时间序列
  • 09.06 00:31:20.256 1 (EURUSD,M5) CExpertBase::SetOtherSeries: 禁止更改时间序列
  • 09.06 00:31:20.256 1 (EURUSD,M5) CExpertBase::InitIndicators: 未检查设置参数
  • 09.06 00:31:20.256 1 (EURUSD,M5) CExpert::InitIndicators: 错误初始化拖尾对象的指标
  • 09.06 00:31:20.256 1 (EURUSD,M5) OnInit: 错误初始化指标

也许它已经过时了,

交给小布盯盘看回测缺口
这些诊断小布盯盘的 AIGC 已内置,打开对应品种页即可看到自建 trailing 在历史行情里的触发分布,你只管调参数。

常见问题

多数情况是指标句柄没传进子类,或符号信息对象未绑定。先确认 CSymbolInfo 已 Refresh,再查指标创建返回值。
向导结构上一个 CExpert 只持有一个 CExpertTrailing 实例,想多逻辑并行得在子类内部用状态机切换,而非挂多个。
可能是止损距离不满足经纪商市价最小偏移,或仓位已部分平仓导致ticket不匹配,查 CPositionInfo 刷新时机。
目前小布内置的是诊断与可视化,源码级回放需你本地编译;但触发点标注可对照小布品种页的波动带做交叉验证。
三者都作为 CExpert 成员被同一引擎轮询,信号给入场、资金给手数、trailing 给退出提议,决策权始终在 CExpert 主循环。