跨平台智能交易系统: 停止位

Enrico Lambino | 11 十月, 2017


内容提要

  1. 概述
  2. COrder
  3. CStop
  4. CStops
  5. COrderStop
  6. COrderStops
  7. 停止位的图表表达
  8. 检查订单停止位
  9. 示例
  10. 结束语
  11. 文章中使用的程序
  12. 文章中列出的类文件


概述

如前一篇文章中所讨论的那样, 对于跨平台智能交易系统, 我们已创建了一个订单管理器 (COrderManager), 它负责处理 MQL4 和 MQL5 之间交易入场和离场的大部分差异。在两个版本中, 智能交易系统通过创建 COrder 的实例将交易信息保存在内存中。这些类对象实例的动态指针容器也可作为 COrderManager 的类成员 (当前和历史交易均可)。

订单管理器能够直接处理每笔交易的停止价位。但是, 这样做会有一些限制:

  • COrderManager 有很大可能需要扩展, 以便能够定制如何处理每笔交易的停止价位。
  • COrderManager 的现有方法只能处理主要交易的入场。

可以扩展 COrderManager, 以便它可以自行处理每笔交易的停止价位。不过, 这不仅限于实际价位的设置, 还涉及有关停止位监控的其它任务, 诸如修改和检查行情是否已触及预定价位。这些功能将致 COrderManager 更复杂, 而目前并未提及如何拆分实现它。

订单管理器仅处理主要交易的入场, 而 EA 执行其它交易操作时会需要一些停止价位, 例如放置挂单, 以及真实仓位的平仓。虽然订单管理器可以自行处理它, 但最好将其重点放在主要交易的入场上, 并让另一个类对象处理停止价位。

在本文中, 我们将研讨具体实现, 其中 COrderManager 将专门处理主要交易 (目前为止) 的入场和离场, 然后由另一个单独的类对象 (CStop) 处理停止价位的实施。

COrder

正如我们从前一篇文章 (参见 跨平台智能交易系统: 订单) 中了解到的那样, 在交易操作 (入场) 成功之后创建了一个 COrder 实例。对于 MetaTrader 4 和 MetaTrader 5, 关于止损和止盈的信息可以从经纪商的后台获取并保存。然而, 如果要对经纪商隐藏停止位或涉及多个停止位的情况下, 关于这些停止位的更多信息就应该被保存在本地。因此, 在后一种情况下, 在仓位成功入场后, 应首先创建 COrder 实例, 随后是代表其止损和止盈价位的对象实例。在早前的文章中, 我们已演示了如何在创建时将 COrder 实例添加到订单管理器中, 正如下图所示:


TradeOpen

停止价位以相同的方式添加。为此, 我们只需要在创建新的 COrder 实例之后, 并在将其添加到进行中交易列表 (COrders) 之前插入该方法。因此, 我们只需稍微修改以上示意图, 如下图所示:


TradeOpen - 含订单停止位

创建停止价位的一般操作如下图所示:

创建停止价位的一般操作

如前面两个流程图所示, 一旦交易成功入场, 将会创建一个新的 COrder 实例来表示它。此后, 将为每个已定义的止损和止盈价位创建 COrderStop 的实例。如果在智能交易系统的初始化中没有声明 CStop 实例, 则会跳过这一特定过程。另一方面, 如果创建了 COrderStop 的实例, 那么这些实例的指针将被存储在早前创建的 COrder 实例中。我们可以在 COrder 的 Init 方法中找到这个操作:

bool COrderBase::Init(COrders *orders,CStops *stops)
  {
   if(CheckPointer(orders))
      SetContainer(GetPointer(orders));
   if(CheckPointer(stops))
      CreateStops(GetPointer(stops));
   m_order_stops.SetContainer(GetPointer(this));
   return true;
  }

为了给 COrder 实例创建停止价位, 我们可以看到它调用了自身的 CreateStops 方法, 如下所示:

void COrderBase::CreateStops(CStops *stops)
  {
   if(!CheckPointer(stops))
      return;
   if(stops.Total()>0)
     {
      for(int i=0;i<stops.Total();i++)
        {
         CStop *stop=stops.At(i);
         if(CheckPointer(stop)==POINTER_INVALID)
            continue;
         m_order_stops.NewOrderStop(GetPointer(this),stop);
        }
     }
  }
该方法遍历 CStop 的所有可用实例, 该实例代表每对止损和止盈价位。这些 CStop 实例中的每一个都传递给 COrderStops 的实例, 其中 COrderStops 只是所有给定顺序的停止价位的容器。然后, 我们可以如下构造类对象的层次结构:


停止价位的层次

对于 COrder 的每个实例, 都有一个类型为 COrderStops 的成员。这个 COrderStops 实例是一个容器 (CArrayObj 的扩展), 它包含指向 COrderStop 实例的指针。每个 COrderStop 实例代表该特定交易 (COrder 实例) 的停止价位 (CStop)。

CStop

如前所述, 我们希望有一定的自由度来定制每笔交易的停止价位如何处理, 而无需修改订单管理器的源代码。这主要是由 CStop 类完成的。当中这个类的职责是:

  1. 定义止损和止盈价位
  2. 执行计算停止价位所需的计算
  3. 主要交易的止损和止盈价位实现
  4. 检查是否已触发停止价位
  5. 调整 MQL4 和 MQL5 之间实现止损和止盈价位的差异
  6. 定义如何随时间处理停止位 (例如, 盈亏平衡, 尾随等)

指针 #1-#5 将在本文中讨论, 而 #6 将在单独一篇文章中讨论。

类型

本文将讨论三种类型的停止位:

  1. 经纪商端停止位 – 停止位与交易请求一起发送给经纪商
  2. 挂单停止位 – 使用挂单作为停止位将令主仓位部分平仓或全部反向对冲平仓 (MetaTrader 4, MetaTrader 5 的对冲模式), 或从主仓位中相减 (MetaTrader 5 净持模式)。
  3. 虚拟停止位 (隐形停止位) – 对经纪商隐藏停止位, 由智能交易系统在本地进行管理。

在 MetaTrader 4 中, 经纪商端停止位是交易者最熟悉的止损和止盈。这些价格或停止价位与主要交易一起发送给经纪商。MetaTrader 5 版本的对冲模式使用与 MetaTrader 4 版本相同的机制。另一方面, 对于净持模式, 由于止损和止盈与 MT4 不同 (应用于品种或金融工具的整体持仓), 因此 CStop 将使用挂单停止位。

挂单停止位使用挂单以某种方式模拟经纪商端停止位。一旦挂单执行, EA 将执行交易操作 (OrderCloseBy) 以便用刚触发的挂单交易量来为主仓位平仓。对于 MetaTrader 4 和 MetaTrader 5 版本的对冲模式, 这是正确的。对于 MetaTrader 5 版本的净持模式, 主仓位的部分或全部仓量自动完成离场, 因为每个品种在任何给定时间只能保留一笔持仓。

主要停止位

主要停止位是触发整体仓位退出的停止价位。通常, 这是经纪商端的停止位。当经纪商端的止损或止盈触发时, 整体持仓离场, 无论 EA 是否打算为此进一步操作。然而, 如果有多个停止价位, 且无经纪商端的停止位, 那么让 EA 决定哪个是主要停止位可能是一个坏主意。在这种情况下, 程序员必须选择哪个 CStop 实例是交易的主要停止位。这对于某些依赖仓位的主要停止位的功能和特性尤为有用, 例如资金管理。由于主要停止位的止损会导致整体持仓的离场, 它代表入场交易的最大风险。已知主要停止位的实例, EA 将能够相应地计算手数。

值得注意的是, 当一个停止位被指定为主要停止位时, 其交易量将始终等于主要交易的初始交易量。对于经纪商端和虚拟停止位这将工作良好, 但不适用在基于挂单的停止位。有两个关联的问题会引出这种方法。

第一个原因是在 MetaTrader 4 中, 在挂单尚未触发前可以修改入场价格。在 MetaTrader 5 中, 这是不可能的, 因为必须维护交易操作的清晰足迹。必须放出新的挂单, 如果成功, 应删除旧订单, 然后智能交易系统应使用新挂单作为新的停止价位。

第二个问题是给经纪商发送替换挂单时, 旧的挂单可能被同时触发。由于 EA 对触发挂单没有控制权 (只有经纪商可以), 这会导致诸如孤立交易或一个停止价位超预期将更多持仓平仓等问题。

为了避免这些问题, 更简单的方法是在交易创建时分配挂单的交易量, 而非在主要交易的整个生存期内动态调整挂单的交易量。不过, 这就要求如果主停止位为挂单类型, 则不应有其它挂单停止位。

交易量

对于主停止位, 无需分配从主持仓扣除的手数, 一旦触发, 整体持仓应平仓。然而, 对于其它类型的停止价位, 必须考虑交易量, 因为它们通常仅用于主持仓的部分平仓。分配划分为四种不同类型:

  1. 固定 – 固定手数
  2. 剩余百分比 – 主要交易的剩余手数百分比
  3. 总体百分比 – 主要交易总手数 (初始交易量) 的百分比
  4. 剩余 – 主要交易的剩余交易量。

固定手数是最简单的交易量分配形式。然而, 如果智能交易系统为每笔仓位使用某种形式的动态手数计算, 那么这就不是最优操作。仅当智能交易系统在整个操作期间使用固定手数时, 才是理想的。

剩余百分比和剩余最好在主停止位为虚拟时使用。剩余将防止 EA 创建孤立交易, 譬如依据未平仓交易量或执行平仓的交易量大于主交易剩余交易量时。另一方面, 当智能交易系统并非基于初始交易量, 而是根据主交易当前剩余交易量进行平仓时, 使用剩余百分比。

总计百分比可用于经纪商端, 虚拟和挂单停止位。使用此方法计算是基于主要交易的初始交易量。

一键取消其它 (OCO)

CStop 始终表达为一对数值, 每个数值表示止损或止盈。然而, 若其中任一值置为零, 可以实现单侧价位 (有止盈无止损, 反之亦然)。省缺情况下, 一个停止价位在被触发时, 关闭其它。唯一的例外是当 CStop 实例是主要停止位。

基类

CStop (CStopBase) 的基类显示在以下代码中:

class CStopBase : public CObject
  {
protected:
   //--- 停止订单参数   
   bool              m_active;
   bool              m_main;
   string            m_name;
   bool              m_oco;
   double            m_stoploss;
   string            m_stoploss_name;
   ENUM_STOP_TYPE    m_stop_type;
   double            m_takeprofit;
   string            m_takeprofit_name;
   int               m_delay;
   //--- 停止订单交易参数
   ENUM_VOLUME_TYPE  m_volume_type;
   double            m_volume;
   int               m_magic;
   int               m_deviation;
   string            m_comment;
   //--- 停止订单对象参数
   bool              m_entry_visible;
   bool              m_stoploss_visible;
   bool              m_takeprofit_visible;
   color             m_entry_color;
   color             m_stoploss_color;
   color             m_takeprofit_color;
   ENUM_LINE_STYLE   m_entry_style;
   ENUM_LINE_STYLE   m_stoploss_style;
   ENUM_LINE_STYLE   m_takeprofit_style;
   //--- 对象
   CSymbolManager   *m_symbol_man;
   CSymbolInfo      *m_symbol;
   CAccountInfo     *m_account;
   CTradeManager     m_trade_man;
   CExpertTradeX    *m_trade;
   CTrails          *m_trails;
   CEventAggregator *m_event_man;
   CStops           *m_stops;
public:
                     CStopBase(void);
                    ~CStopBase(void);
   virtual int       Type(void) const {return CLASS_TYPE_STOP;}
   //--- 初始化
   virtual bool      Init(CSymbolManager*,CAccountInfo*,CEventAggregator*);
   virtual bool      InitAccount(CAccountInfo*);
   virtual bool      InitEvent(CEventAggregator*);
   virtual bool      InitSymbol(CSymbolManager*);
   virtual bool      InitTrade(void);
   virtual CStops   *GetContainer(void);
   virtual void      SetContainer(CStops*);
   virtual bool      Validate(void) const;
   //--- 取值和赋值
   bool              Active(void);
   void              Active(const bool);
   bool              Broker(void) const;
   void              Comment(const string);
   string            Comment(void) const;
   void              Delay(int delay);
   int               Delay(void) const;
   void              SetDeviation(const int);
   int               SetDeviation(void) const;
   void              EntryColor(const color clr);
   void              EntryStyle(const ENUM_LINE_STYLE);
   void              EntryVisible(const bool);
   bool              EntryVisible(void) const;
   void              Magic(const int);
   int               Magic(void) const;
   void              Main(const bool);
   bool              Main(void) const;
   void              Name(const string);
   string            Name(void) const;
   void              OCO(const bool oco);
   bool              OCO(void) const;
   bool              Pending(void) const;
   void              StopLoss(const double);
   double            StopLoss(void) const;
   void              StopLossColor(const color);
   bool              StopLossCustom(void);
   void              StopLossName(const string);
   string            StopLossName(void) const;
   void              StopLossVisible(const bool);
   bool              StopLossVisible(void) const;
   void              StopLossStyle(const ENUM_LINE_STYLE);
   void              StopType(const ENUM_STOP_TYPE);
   ENUM_STOP_TYPE    StopType(void) const;
   string            SymbolName(void);
   void              TakeProfit(const double);
   double            TakeProfit(void) const;
   void              TakeProfitColor(const color);
   bool              TakeProfitCustom(void);
   void              TakeProfitName(const string);
   string            TakeProfitName(void) const;
   void              TakeProfitStyle(const ENUM_LINE_STYLE);
   void              TakeProfitVisible(const bool);
   bool              TakeProfitVisible(void) const;
   bool              Virtual(void) const;
   void              Volume(double);
   double            Volume(void) const;
   void              VolumeType(const ENUM_VOLUME_TYPE);
   ENUM_VOLUME_TYPE  VolumeType(void) const;
   //--- 停止订单检查
   virtual bool      CheckStopLoss(COrder*,COrderStop*);
   virtual bool      CheckTakeProfit(COrder*,COrderStop*);
   virtual bool      CheckStopOrder(ENUM_STOP_MODE,COrder*,COrderStop*)=0;
   virtual bool      DeleteStopOrder(const ulong)=0;
   virtual bool      DeleteMarketStop(const ulong)=0;
   virtual bool      OrderModify(const ulong,const double);
   //--- 停止订单对象创建
   virtual CStopLine *CreateEntryObject(const long,const string,const int,const double);
   virtual CStopLine *CreateStopLossObject(const long,const string,const int,const double);
   virtual CStopLine *CreateTakeProfitObject(const long,const string,const int,const double);
   //--- 停止订单价格计算   
   virtual bool      Refresh(const string);
   virtual double    StopLossCalculate(const string,const ENUM_ORDER_TYPE,const double);
   virtual double    StopLossCustom(const string,const ENUM_ORDER_TYPE,const double);
   virtual double    StopLossPrice(COrder*,COrderStop*);
   virtual double    StopLossTicks(const ENUM_ORDER_TYPE,const double);
   virtual double    TakeProfitCalculate(const string,const ENUM_ORDER_TYPE,const double);
   virtual double    TakeProfitCustom(const string,const ENUM_ORDER_TYPE,const double);
   virtual double    TakeProfitPrice(COrder*,COrderStop*);
   virtual double    TakeProfitTicks(const ENUM_ORDER_TYPE,const double);
   //--- 尾随   
   virtual bool      Add(CTrails*);
   virtual double    CheckTrailing(const string,const ENUM_ORDER_TYPE,const double,const double,const ENUM_TRAIL_TARGET);
protected:
   //--- 对象创建
   virtual CStopLine *CreateObject(const long,const string,const int,const double);
   //--- 停止订单价格计算
   virtual double    LotSizeCalculate(COrder*,COrderStop*);
   //--- 停止订单入场   
   virtual bool      GetClosePrice(const string,const ENUM_ORDER_TYPE,double&);
   //--- 停止订单离场
   virtual bool      CloseStop(COrder*,COrderStop*,const double)=0;
   //--- 逆初始化
   virtual void      Deinit(void);
   virtual void      DeinitSymbol(void);
   virtual void      DeinitTrade(void);
   virtual void      DeinitTrails(void);
  };

对于基于点值或点数的止损和止盈价位, 至少需要记住四个类方法:

  1. 停止位类型 (经纪商端, 挂单或虚拟), 使用 StopType 方法
  2. 所用的交易量计算类型, 使用 VolumeType 方法
  3. 以点数为止损价位 (每当需要时), 使用 StopLoss 方法
  4. 以点数为止盈价位 (每当需要时), 使用 TakeProfit 方法

所有这些仅仅是类成员的赋值器, 所以没有必要详细说明这些方法。其余的大部分方法仅在类的内部计算中才需要。这些受保护方法当中最重要的是 StopLossCalculate 和 TakeProfitCalculate 方法, 其代码如下所示:

double CStopBase::StopLossCalculate(const string symbol,const ENUM_ORDER_TYPE type,const double price)
  {   
   if(!Refresh(symbol))
      return 0;
   if(type==ORDER_TYPE_BUY || type==ORDER_TYPE_BUY_STOP || type==ORDER_TYPE_BUY_LIMIT)
      return price-m_stoploss*m_symbol.Point();
   else if(type==ORDER_TYPE_SELL || type==ORDER_TYPE_SELL_STOP || type==ORDER_TYPE_SELL_LIMIT)
      return price+m_stoploss*m_symbol.Point();
   return 0;
  }

double CStopBase::TakeProfitCalculate(const string symbol,const ENUM_ORDER_TYPE type,const double price)
  {
   if(!Refresh(symbol))
      return 0;
   if(type==ORDER_TYPE_BUY || type==ORDER_TYPE_BUY_STOP || type==ORDER_TYPE_BUY_LIMIT)
      return price+m_takeprofit*m_symbol.Point();
   else if(type==ORDER_TYPE_SELL || type==ORDER_TYPE_SELL_STOP || type==ORDER_TYPE_SELL_LIMIT)
      return price-m_takeprofit*m_symbol.Point();
   return 0;
  }

这两种方法都取三个参数, 所有这些都与主要交易有关。该方法首先通过 Refresh 方法刷新品种, 该方法简单地更新要用到的品种管理器。一旦品种被刷新, 它将基于初始化期间提供给类实例的点数值返回止损或止盈价位。

CStops

CStops 类将作为 CStop 实例的容器。该类的实例必须作为其成员之一动态添加到订单管理器。以下代码显示了 CStopsBase, 它是 CStops 的基类:

class CStopsBase : public CArrayObj
  {
protected:
   bool              m_active;
   CEventAggregator *m_event_man;
   CObject          *m_container;
public:
                     CStopsBase(void);
                    ~CStopsBase(void);
   virtual int       Type(void) const {return CLASS_TYPE_STOPS;}
   //--- 初始化
   virtual bool      Init(CSymbolManager*,CAccountInfo*,CEventAggregator*);
   virtual CObject  *GetContainer(void);
   virtual void      SetContainer(CObject*);
   virtual bool      Validate(void) const;
   //--- 赋值和取值
   virtual bool      Active(void) const;
   virtual void      Active(const bool);
   virtual CStop    *Main(void);
   //--- 复原
   virtual bool      CreateElement(const int);
  };

这个类与本文中迄今为止描述的其它容器非常相似。

COrderStop

COrderStop 表示特定交易的 CStop 的实现。对于给定的仓位, CStop 最多可以创建一个 COrderStop。但是, 任意数量的 COrderStop 实例可以共享相同的 CStop 实例。因此, 如果智能交易系统有 3 个不同的 CStop 实例, 通常我们希望每个COrder 实例具有相同数量的 COrderStop 实例。如果智能交易系统已经进行了 1000 笔交易, 则创建的 COrderStop 实例数量将为 1000 * 3 = 3000, 而创建的 CStop 实例数仍为 3。

COrderStop 基于 COrderStopBase 的定义如下所示:

class COrderStopBase : public CObject
  {
protected:
   bool              m_active;
   //--- 停止位参数
   double            m_volume;
   CArrayDouble      m_stoploss;
   CArrayDouble      m_takeprofit;
   ulong             m_stoploss_ticket;
   ulong             m_takeprofit_ticket;
   bool              m_stoploss_closed;
   bool              m_takeprofit_closed;
   bool              m_closed;
   ENUM_STOP_TYPE    m_stop_type;
   string            m_stop_name;
   //--- 主订单对象
   COrder           *m_order;
   //--- 停止位对象
   CStop            *m_stop;
   CStopLine        *m_objentry;
   CStopLine        *m_objsl;
   CStopLine        *m_objtp;
   COrderStops      *m_order_stops;
public:
                     COrderStopBase(void);
                    ~COrderStopBase(void);
   virtual int       Type(void) const {return CLASS_TYPE_ORDERSTOP;}
   //--- 初始化
   virtual void      Init(COrder*,CStop*,COrderStops*);
   virtual COrderStops *GetContainer(void);
   virtual void      SetContainer(COrderStops*);
   virtual void      Show(bool);
   //--- 取值和赋值  
   bool              Active(void) const;
   void              Active(bool active);
   string            EntryName(void) const;
   ulong             MainMagic(void) const;
   ulong             MainTicket(void) const;
   double            MainTicketPrice(void) const;
   ENUM_ORDER_TYPE   MainTicketType(void) const;
   COrder           *Order(void);
   void              Order(COrder*);
   CStop            *Stop(void);
   void              Stop(CStop*);
   bool              StopLoss(const double);
   double            StopLoss(void) const;
   double            StopLoss(const int);
   void              StopLossClosed(const bool);
   bool              StopLossClosed(void);
   double            StopLossLast(void) const;
   string            StopLossName(void) const;
   void              StopLossTicket(const ulong);
   ulong             StopLossTicket(void) const;
   void              StopName(const string);
   string            StopName(void) const;
   bool              TakeProfit(const double);
   double            TakeProfit(void) const;
   double            TakeProfit(const int);
   void              TakeProfitClosed(const bool);
   bool              TakeProfitClosed(void);
   double            TakeProfitLast(void) const;
   string            TakeProfitName(void) const;
   void              TakeProfitTicket(const ulong);
   ulong             TakeProfitTicket(void) const;
   void              Volume(const double);
   double            Volume(void) const;
   //--- 检查   
   virtual void      Check(double&)=0;
   virtual bool      Close(void);
   virtual bool      CheckTrailing(void);
   virtual bool      DeleteChartObject(const string);
   virtual bool      DeleteEntry(void);
   virtual bool      DeleteStopLines(void);
   virtual bool      DeleteStopLoss(void);
   virtual bool      DeleteTakeProfit(void);
   virtual bool      IsClosed(void);
   virtual bool      Update(void) {return true;}
   virtual void      UpdateVolume(double) {}
   //--- 逆初始化 
   virtual void      Deinit(void);
   //--- 复原
   virtual bool      Save(const int);
   virtual bool      Load(const int);
   virtual void      Recreate(void);
protected:
   virtual bool      IsStopLossValid(const double) const;
   virtual bool      IsTakeProfitValid(const double) const;
   virtual bool      Modify(const double,const double);
   virtual bool      ModifyStops(const double,const double);
   virtual bool      ModifyStopLoss(const double) {return true;}
   virtual bool      ModifyTakeProfit(const double){return true;}
   virtual bool      UpdateOrderStop(const double,const double){return true;}
   virtual bool      MoveStopLoss(const double);
   virtual bool      MoveTakeProfit(const double);
  };

COrderStop 包含在 COrderStops 中 (将在下一节中讨论), COrderStop 则由 COrder 包含。在 EA 的实际开发中, 不需要再声明一个 COrderStop 的实例。这是由 COrder 根据 CStop 的特定实例自动创建的。

COrderStops

class COrderStopsBase : public CArrayObj
  {
protected:
   bool              m_active;
   CArrayInt         m_types;
   COrder           *m_order;
public:
                     COrderStopsBase(void);
                    ~COrderStopsBase(void);
   virtual int       Type(void) const {return CLASS_TYPE_ORDERSTOPS;}
   void              Active(bool);
   bool              Active(void) const;
   //--- 初始化
   virtual CObject *GetContainer(void);
   virtual void      SetContainer(COrder*);
   virtual bool      NewOrderStop(COrder*,CStop*)=0;
   //--- 检查
   virtual void      Check(double &volume);
   virtual bool      CheckNewTicket(COrderStop*);
   virtual bool      Close(void);
   virtual void      UpdateVolume(const double) {}
   //--- 隐藏和显示停止位指示线
   virtual void      Show(const bool);
   //--- 复原
   virtual bool      CreateElement(const int);
   virtual bool      Save(const int);
   virtual bool      Load(const int);
  };


就像 CStop, 这看起来只是一个典型的容器。不过, 它包含了一些方法来镜像对象方法, 其指针用于存储 (COrderStop)。

停止位的图表表达

CStopLine 是 CStop 的类成员, 其主要职责是在图表上表述停止价位的图形。在智能交易系统中有三个核心函数:

  1. 在 COrder 实例初始化时显示停止价位
  2. 在更改其中一个或两个停止价位的情况下在事件中更新停止价位
  3. 一旦主要交易离场, 立即删除停止位指示线

所有这些函数都通过 CStop 类实现。

作为 CStopLine 基类的 CStopLineBase 定义如下所示:

class CStopLineBase : public CChartObjectHLine
  {
protected:
   bool              m_active;
   CStop            *m_stop;
public:
                     CStopLineBase(void);
                    ~CStopLineBase(void);
   virtual int       Type(void) const {return CLASS_TYPE_STOPLINE;}
   virtual void      SetContainer(CStop*);
   virtual CStop    *GetContainer(void);
   bool              Active(void) const;
   void              Active(const bool);
   virtual bool      ChartObjectExists(void) const;
   virtual double    GetPrice(const int);
   virtual bool      Move(const double);
   virtual bool      SetStyle(const ENUM_LINE_STYLE);
   virtual bool      SetColor(const color);
  };

在旧版本的 MetaTrader 4 中, 止损和止盈价位不能通过拖动进行修改。这些价位必须通过订单窗口或通过智能交易系统和脚本进行修改。然而, 显示这些价位的图形表述可能仍然有用, 特别是在处理虚拟停止位时。

检查订单停止位

对于给定仓位成功创建停止价位之后, 下一步将是检查行情是否达到给定的停止价位。对于经纪商端的停止位, 该过程不是必需的, 因为平仓操作在服务器端完成。然而, 对于虚拟和挂单停止位, 在大多数情况下, 由智能交易系统自身执行平仓操作。

对于虚拟停止位, 智能交易系统完全负责监控行情走势, 并检查行情是否达到给定停止价位。以下示意图展现了一般操作。一旦行情触及停止价位, 智能交易系统就会执行相应的平仓操作。

OrderStop 检查 (虚拟)

对于挂单停止位, 该过程稍微复杂一点。被触发的停止价位将导致挂单被触发, 即变为一笔持仓。这在经纪商一端自动完成。因此, 智能交易系统有责任检测给定的挂单是否仍在等待或已经入场。如果挂单已经被触发, 那么智能交易系统负责按照刚触发的挂单交易量将主要仓位平仓 - 一笔交易通过操作平仓。

COrderStop 检查 (挂单停止位)

在所有情况下, 一旦给定的订单停止价位被触发, 停止价位被标记为关闭。这是为了防止给定的停止价位被执行一次以上。

示例

示例 #1: 使用 Heiken Ashi 和移动平均线的 EA, 具有单一停止价位 (主要停止位)

在大多数智能交易系统中, 一个止损和一个止盈通常就足够了。我们现在将扩展前一篇文章中的示例 (请参阅 跨平台智能交易系统: 时间过滤器), 在源代码当中添加止损和止盈。为此, 我们首先创建一个新的容器实例 (CStops)。然后创建一个 CStop 的实例, 然后将其指针添加到容器。之后, 最终将指向容器的指针添加到订单管理器中。代码如下所示:

int OnInit()
  {
//--- 其它代码

   CStops *stops=new CStops();

   CStop *main=new CStop("main");
   main.StopType(stop_type_main);
   main.VolumeType(VOLUME_TYPE_PERCENT_TOTAL);
   main.Main(true);
   main.StopLoss(stop_loss);
   main.TakeProfit(take_profit);
   stops.Add(GetPointer(main));
   
   order_manager.AddStops(GetPointer(stops));     
//--- 其它代码
  }

在 MetaTrader 4 上测试经纪商端停止位, 结果如下表所示。这就是交易者通常期望的由平台上的智能交易系统执行的交易。

# 时间 类型 订单 手数 价格 止损 止盈 盈利 余额
1 2017.01.03 10:00 sell 1 0.30 1.04597 1.05097 1.04097
2 2017.01.03 11:34 t/p 1 0.30 1.04097 1.05097 1.04097 150.00 3150.00
3 2017.01.05 11:00 sell 2 0.30 1.05149 1.05649 1.04649
4 2017.01.05 17:28 s/l 2 0.30 1.05649 1.05649 1.04649 -150.00 3000.00

对于挂单停止位, 停止位预先放置在标准止损/止盈中, 不过是以挂单的形式。一旦挂单被触发, 智能交易系统将执行一个平仓操作, 依据触发的挂单交易量将主交易平仓。然而, 与标准止损/止盈不同, 智能交易系统在客户端执行此操作。除非交易平台是实时的, 且 EA 正在图表上运行, 否则不会执行。

# 时间 类型 订单 手数 价格 止损 止盈 盈利 余额
1 2017.01.03 10:00 sell 1 0.30 1.04597 0.00000 0.00000
2 2017.01.03 10:00 buy stop 2 0.30 1.05097 0.00000 0.00000
3 2017.01.03 10:00 buy limit 3 0.30 1.04097 0.00000 0.00000
4 2017.01.03 11:34 buy 3 0.30 1.04097 0.00000 0.00000
5 2017.01.03 11:34 close by 1 0.30 1.04097 0.00000 0.00000 150.00 3150.00
6 2017.01.03 11:34 close by 3 0.00 1.04097 0.00000 0.00000 0.00 3150.00
7 2017.01.03 11:34 delete 2 0.30 1.05097 0.00000 0.00000
8 2017.01.05 11:00 sell 4 0.30 1.05149 0.00000 0.00000
9 2017.01.05 11:00 buy stop 5 0.30 1.05649 0.00000 0.00000
10 2017.01.05 11:00 buy limit 6 0.30 1.04649 0.00000 0.00000
11 2017.01.05 17:28 buy 5 0.30 1.05649 0.00000 0.00000
12 2017.01.05 17:28 close by 4 0.30 1.05649 0.00000 0.00000 -150.00 3000.00
13 2017.01.05 17:28 close by 5 0.00 1.05649 0.00000 0.00000 0.00 3000.00
14 2017.01.05 17:28 delete 6 0.30 1.04649 0.00000 0.00000


虚拟停止位不会发送任何有关主要交易的停止位。在 EA 执行平仓订单的时刻, 经纪商才会被通知。下表显示了使用虚拟停止位的 EA 行为。在此, 一旦触发停止价位的目标价格, EA 就会向服务器发送交易请求, 将主要交易平仓。

# 时间 类型 订单 手数 价格 止损 止盈 盈利 余额
1 2017.01.03 10:00 sell 1 0.30 1.04597 0.00000 0.00000
2 2017.01.03 11:34 close 1 0.30 1.04097 0.00000 0.00000 150.00 3150.00
3 2017.01.05 11:00 sell 2 0.30 1.05149 0.00000 0.00000
4 2017.01.05 17:28 close 2 0.30 1.05649 0.00000 0.00000 -150.00 3000.00


现在, 我们移步到 MetaTrader 5。MetaTrader 5 中的对冲模式在最终结果方面更接近 MetaTrader 4。下表显示了经纪商端停止位的测试结果。在此, 我们可以清楚地看到主要交易各自列内的止损和止盈价位。













订单
开单时间 订单 品种 类型 交易量 价格 止损 止盈 时间 状态 注释
2017.01.03 10:00:00 2 EURUSD sell 0.30 / 0.30 1.04597 1.05097 1.04097 2017.01.03 10:00:00 filled
2017.01.03 11:34:38 3 EURUSD buy 0.30 / 0.30 1.04097

2017.01.03 11:34:38 filled tp 1.04097
2017.01.05 11:00:00 4 EURUSD sell 0.30 / 0.30 1.05149 1.05649 1.04649 2017.01.05 11:00:00 filled
2017.01.05 17:28:37 5 EURUSD buy 0.30 / 0.30 1.05649

2017.01.05 17:28:37 filled sl 1.05649

成交
时间 成交 品种 类型 方向 交易量 价格 订单 佣金 掉期利率 盈利 余额 注释
2017.01.01 00:00:00 1
balance



0.00 0.00 3 000.00 3 000.00
2017.01.03 10:00:00 2 EURUSD sell in 0.30 1.04597 2 0.00 0.00 0.00 3 000.00
2017.01.03 11:34:38 3 EURUSD buy out 0.30 1.04097 3 0.00 0.00 150.00 3 150.00 tp 1.04097
2017.01.05 11:00:00 4 EURUSD sell in 0.30 1.05149 4 0.00 0.00 0.00 3 150.00
2017.01.05 17:28:37 5 EURUSD buy out 0.30 1.05649 5 0.00 0.00 -150.00 3 000.00 sl 1.05649

0.00 0.00 0.00 3 000.00

在对冲模式下, 挂单的工作方式基本上与 MetaTrader 4 相同, 所以当挂单被触发时, EA 也会执行平仓操作。














订单
开单时间 订单 品种 类型 交易量 价格 止损 止盈 时间 状态 注释
2017.01.03 10:00:00 2 EURUSD sell 0.30 / 0.30 1.04597

2017.01.03 10:00:00 filled
2017.01.03 10:00:00 3 EURUSD buy stop 0.30 / 0.00 1.05097

2017.01.03 11:34:38 canceled
2017.01.03 10:00:00 4 EURUSD buy limit 0.30 / 0.30 1.04097

2017.01.03 11:34:38 filled
2017.01.03 11:34:38 5 EURUSD close by 0.30 / 0.30 1.04097

2017.01.03 11:34:38 filled close #2 by #4
2017.01.05 11:00:00 6 EURUSD sell 0.30 / 0.30 1.05149

2017.01.05 11:00:00 filled
2017.01.05 11:00:00 7 EURUSD buy stop 0.30 / 0.30 1.05649

2017.01.05 17:28:37 filled
2017.01.05 11:00:00 8 EURUSD buy limit 0.30 / 0.00 1.04649

2017.01.05 17:28:37 canceled
2017.01.05 17:28:37 9 EURUSD close by 0.30 / 0.30 1.05649

2017.01.05 17:28:37 filled close #6 by #7

成交
时间 成交 品种 类型 方向 交易量 价格 订单 佣金 掉期利率 盈利 余额 注释
2017.01.01 00:00:00 1
balance



0.00 0.00 3 000.00 3 000.00
2017.01.03 10:00:00 2 EURUSD sell in 0.30 1.04597 2 0.00 0.00 0.00 3 000.00
2017.01.03 11:34:38 3 EURUSD buy in 0.30 1.04097 4 0.00 0.00 0.00 3 000.00
2017.01.03 11:34:38 4 EURUSD buy out by 0.30 1.04097 5 0.00 0.00 150.00 3 150.00 close #2 by #4
2017.01.03 11:34:38 5 EURUSD sell out by 0.30 1.04597 5 0.00 0.00 0.00 3 150.00 close #2 by #4
2017.01.05 11:00:00 6 EURUSD sell in 0.30 1.05149 6 0.00 0.00 0.00 3 150.00
2017.01.05 17:28:37 7 EURUSD buy in 0.30 1.05649 7 0.00 0.00 0.00 3 150.00
2017.01.05 17:28:37 9 EURUSD sell out by 0.30 1.05149 9 0.00 0.00 0.00 3 150.00 close #6 by #7
2017.01.05 17:28:37 8 EURUSD buy out by 0.30 1.05649 9 0.00 0.00 -150.00 3 000.00 close #6 by #7

0.00 0.00 0.00 3 000.00

使用虚拟停止位, 我们通常不会在 MetaTrader 4 中看到 "close" 标签。相反, 平仓操作使用与主要交易相反的类型, 但我们可以在成交历史中查看它们是否为买/卖、进/出。














订单
开单时间 订单 品种 类型 交易量 价格 止损 止盈 时间 状态 注释
2017.01.03 10:00:00 2 EURUSD sell 0.30 / 0.30 1.04597

2017.01.03 10:00:00 filled
2017.01.03 11:34:38 3 EURUSD buy 0.30 / 0.30 1.04097

2017.01.03 11:34:38 filled
2017.01.05 11:00:00 4 EURUSD sell 0.30 / 0.30 1.05149

2017.01.05 11:00:00 filled
2017.01.05 17:28:37 5 EURUSD buy 0.30 / 0.30 1.05649

2017.01.05 17:28:37 filled

成交
时间 成交 品种 类型 方向 交易量 价格 订单 佣金 掉期利率 盈利 余额 注释
2017.01.01 00:00:00 1
balance



0.00 0.00 3 000.00 3 000.00
2017.01.03 10:00:00 2 EURUSD sell in 0.30 1.04597 2 0.00 0.00 0.00 3 000.00
2017.01.03 11:34:38 3 EURUSD buy out 0.30 1.04097 3 0.00 0.00 150.00 3 150.00
2017.01.05 11:00:00 4 EURUSD sell in 0.30 1.05149 4 0.00 0.00 0.00 3 150.00
2017.01.05 17:28:37 5 EURUSD buy out 0.30 1.05649 5 0.00 0.00 -150.00 3 000.00

0.00 0.00 0.00 3 000.00

对于净持模式, 由于 MetaTrader 5 在此模式下使用全局止损和止盈 (适用于整个仓位), 因此 EA 必须使用挂单, 以使交易有明显的止损和止盈价位。如前所述, 在对冲模式下, 经纪商端停止位将基于挂单停止位操作, 如下表所示:













订单
开单时间 订单 品种 类型 交易量 价格 止损 止盈 时间 状态 注释
2017.01.03 10:00:00 2 EURUSD sell 0.30 / 0.30 1.04597

2017.01.03 10:00:00 filled
2017.01.03 10:00:00 3 EURUSD buy stop 0.30 / 0.00 1.05097

2017.01.03 11:34:38 canceled
2017.01.03 10:00:00 4 EURUSD buy limit 0.30 / 0.30 1.04097

2017.01.03 11:34:38 filled
2017.01.05 11:00:00 5 EURUSD sell 0.30 / 0.30 1.05149

2017.01.05 11:00:00 filled
2017.01.05 11:00:00 6 EURUSD buy stop 0.30 / 0.30 1.05649

2017.01.05 17:28:37 filled
2017.01.05 11:00:00 7 EURUSD buy limit 0.30 / 0.00 1.04649

2017.01.05 17:28:37 canceled

成交
时间 成交 品种 类型 方向 交易量 价格 订单 佣金 掉期利率 盈利 余额 注释
2017.01.01 00:00:00 1
balance



0.00 0.00 3 000.00 3 000.00
2017.01.03 10:00:00 2 EURUSD sell in 0.30 1.04597 2 0.00 0.00 0.00 3 000.00
2017.01.03 11:34:38 3 EURUSD buy out 0.30 1.04097 4 0.00 0.00 150.00 3 150.00
2017.01.05 11:00:00 4 EURUSD sell in 0.30 1.05149 5 0.00 0.00 0.00 3 150.00
2017.01.05 17:28:37 5 EURUSD buy out 0.30 1.05649 6 0.00 0.00 -150.00 3 000.00

0.00 0.00 0.00 3 000.00

下表显示基于挂单停止位的结果。出于前述原因, 这应与前一张表相同。













订单
开单时间 订单 品种 类型 交易量 价格 止损 止盈 时间 状态 注释
2017.01.03 10:00:00 2 EURUSD sell 0.30 / 0.30 1.04597

2017.01.03 10:00:00 filled
2017.01.03 10:00:00 3 EURUSD buy stop 0.30 / 0.00 1.05097

2017.01.03 11:34:38 canceled
2017.01.03 10:00:00 4 EURUSD buy limit 0.30 / 0.30 1.04097

2017.01.03 11:34:38 filled
2017.01.05 11:00:00 5 EURUSD sell 0.30 / 0.30 1.05149

2017.01.05 11:00:00 filled
2017.01.05 11:00:00 6 EURUSD buy stop 0.30 / 0.30 1.05649

2017.01.05 17:28:37 filled
2017.01.05 11:00:00 7 EURUSD buy limit 0.30 / 0.00 1.04649

2017.01.05 17:28:37 canceled

成交
时间 成交 品种 类型 方向 交易量 价格 订单 佣金 掉期利率 盈利 余额 注释
2017.01.01 00:00:00 1
balance



0.00 0.00 3 000.00 3 000.00
2017.01.03 10:00:00 2 EURUSD sell in 0.30 1.04597 2 0.00 0.00 0.00 3 000.00
2017.01.03 11:34:38 3 EURUSD buy out 0.30 1.04097 4 0.00 0.00 150.00 3 150.00
2017.01.05 11:00:00 4 EURUSD sell in 0.30 1.05149 5 0.00 0.00 0.00 3 150.00
2017.01.05 17:28:37 5 EURUSD buy out 0.30 1.05649 6 0.00 0.00 -150.00 3 000.00

0.00 0.00 0.00 3 000.00

下表显示在 MetaTrader 5 净持模式下使用虚拟停止位。净持模式中的虚拟停止位也许与对冲模式相似, 但内部运作方式不同。














订单
开单时间 订单 品种 类型 交易量 价格 止损 止盈 时间 状态 注释
2017.01.03 10:00:00 2 EURUSD sell 0.30 / 0.30 1.04597

2017.01.03 10:00:00 filled
2017.01.03 11:34:38 3 EURUSD buy 0.30 / 0.30 1.04097

2017.01.03 11:34:38 filled
2017.01.05 11:00:00 4 EURUSD sell 0.30 / 0.30 1.05149

2017.01.05 11:00:00 filled
2017.01.05 17:28:37 5 EURUSD buy 0.30 / 0.30 1.05649

2017.01.05 17:28:37 filled

成交
时间 成交 品种 类型 方向 交易量 价格 订单 佣金 掉期利率 盈利 余额 注释
2017.01.01 00:00:00 1
balance



0.00 0.00 3 000.00 3 000.00
2017.01.03 10:00:00 2 EURUSD sell in 0.30 1.04597 2 0.00 0.00 0.00 3 000.00
2017.01.03 11:34:38 3 EURUSD buy out 0.30 1.04097 3 0.00 0.00 150.00 3 150.00
2017.01.05 11:00:00 4 EURUSD sell in 0.30 1.05149 4 0.00 0.00 0.00 3 150.00
2017.01.05 17:28:37 5 EURUSD buy out 0.30 1.05649 5 0.00 0.00 -150.00 3 000.00

0.00 0.00 0.00 3 000.00

示例 #2: 一款使用 Heiken Ashi 和 移动平均线的 EA, 有三个停止价位

更复杂的智能交易系统通常需要一个以上的止损和止盈。我们使用与上个示例相同的方法来添加额外的停止价位, 即名为 "stop1" 和 "stop2" 的停止价位:

int OnInit()
  {
//--- 其它代码
  
   CStops *stops=new CStops();

   CStop *main=new CStop("main");
   main.StopType(stop_type_main);
   main.VolumeType(VOLUME_TYPE_PERCENT_TOTAL);
   main.Main(true);
   main.StopLoss(stop_loss);
   main.TakeProfit(take_profit);
   stops.Add(GetPointer(main));
   
   CStop *stop1=new CStop("stop1");
   stop1.StopType(stop_type1);
   stop1.VolumeType(VOLUME_TYPE_PERCENT_TOTAL);
   stop1.Volume(0.35);
   stop1.StopLoss(stop_loss1);
   stop1.TakeProfit(take_profit1);
   stops.Add(GetPointer(stop1));
   
   CStop *stop2=new CStop("stop2");
   stop2.StopType(stop_type2);
   stop2.VolumeType(VOLUME_TYPE_PERCENT_TOTAL);
   stop2.Volume(0.35);
   stop2.StopLoss(stop_loss2);
   stop2.TakeProfit(take_profit2);
   stops.Add(GetPointer(stop2));
   
   order_manager.AddStops(GetPointer(stops));

//--- 其它代码
  }

下表显示了 MetaTrader 4 上的测试结果:

# 时间 类型 订单 手数 价格 止损 止盈 盈利 余额
1 2017.01.03 10:00 sell 1 0.30 1.04597 1.05097 1.04097
2 2017.01.03 10:00 buy stop 2 0.11 1.04847 0.00000 0.00000
3 2017.01.03 10:00 buy limit 3 0.11 1.04347 0.00000 0.00000
4 2017.01.03 10:21 buy 3 0.11 1.04347 0.00000 0.00000
5 2017.01.03 10:21 close by 1 0.11 1.04347 1.05097 1.04097 27.50 3027.50
6 2017.01.03 10:21 sell 4 0.19 1.04597 1.05097 1.04097
7 2017.01.03 10:21 close by 3 0.00 1.04347 0.00000 0.00000 0.00 3027.50
8 2017.01.03 10:21 delete 2 0.11 1.04847 0.00000 0.00000
9 2017.01.03 10:34 close 4 0.11 1.04247 1.05097 1.04097 38.50 3066.00
10 2017.01.03 10:34 sell 5 0.08 1.04597 1.05097 1.04097
11 2017.01.03 11:34 t/p 5 0.08 1.04097 1.05097 1.04097 40.00 3106.00
12 2017.01.05 11:00 sell 6 0.30 1.05149 1.05649 1.04649
13 2017.01.05 11:00 buy stop 7 0.11 1.05399 0.00000 0.00000
14 2017.01.05 11:00 buy limit 8 0.11 1.04899 0.00000 0.00000
15 2017.01.05 12:58 buy 8 0.11 1.04899 0.00000 0.00000
16 2017.01.05 12:58 close by 6 0.11 1.04899 1.05649 1.04649 27.50 3133.50
17 2017.01.05 12:58 sell 9 0.19 1.05149 1.05649 1.04649
18 2017.01.05 12:58 close by 8 0.00 1.04899 0.00000 0.00000 0.00 3133.50
19 2017.01.05 12:58 delete 7 0.11 1.05399 0.00000 0.00000
20 2017.01.05 16:00 close 9 0.19 1.05314 1.05649 1.04649 -31.35 3102.15
21 2017.01.05 16:00 buy 10 0.30 1.05314 1.04814 1.05814
22 2017.01.05 16:00 sell stop 11 0.11 1.05064 0.00000 0.00000
23 2017.01.05 16:00 sell limit 12 0.11 1.05564 0.00000 0.00000
24 2017.01.05 17:09 sell 12 0.11 1.05564 0.00000 0.00000
25 2017.01.05 17:09 close by 10 0.11 1.05564 1.04814 1.05814 27.50 3129.65
26 2017.01.05 17:09 buy 13 0.19 1.05314 1.04814 1.05814
27 2017.01.05 17:09 close by 12 0.00 1.05564 0.00000 0.00000 0.00 3129.65
28 2017.01.05 17:09 delete 11 0.11 1.05064 0.00000 0.00000
29 2017.01.05 17:28 close 13 0.11 1.05664 1.04814 1.05814 38.50 3168.15
30 2017.01.05 17:28 buy 14 0.08 1.05314 1.04814 1.05814
31 2017.01.05 17:40 t/p 14 0.08 1.05814 1.04814 1.05814 40.00 3208.15


如上表所示, 所有三个停止价位均被第一笔交易触发。对于虚拟停止位, EA 按预期在主要交易中执行部分平仓。对于使用挂单的停止位, 一旦挂单执行, EA 将执行平仓操作, 从主交易中扣除挂单交易量。最后, 对于主要停止位, 这是一个经纪商端停止位, 主要交易已离场, 剩余交易量为 0.08 手。

下表显示了 MetaTrader 5 对冲模式下的测试结果:














订单
开单时间 订单 品种 类型 交易量 价格 止损 止盈 时间 状态 注释
2017.01.03 10:00:00 2 EURUSD sell 0.30 / 0.30 1.04597 1.05097 1.04097 2017.01.03 10:00:00 filled
2017.01.03 10:00:00 3 EURUSD buy stop 0.11 / 0.00 1.04847

2017.01.03 10:21:32 canceled
2017.01.03 10:00:00 4 EURUSD buy limit 0.11 / 0.11 1.04347

2017.01.03 10:21:32 filled
2017.01.03 10:21:32 5 EURUSD close by 0.11 / 0.11 1.04347

2017.01.03 10:21:32 filled close #2 by #4
2017.01.03 10:33:40 6 EURUSD buy 0.11 / 0.11 1.04247

2017.01.03 10:33:40 filled
2017.01.03 11:34:38 7 EURUSD buy 0.08 / 0.08 1.04097

2017.01.03 11:34:38 filled tp 1.04097
2017.01.05 11:00:00 8 EURUSD sell 0.30 / 0.30 1.05149 1.05649 1.04649 2017.01.05 11:00:00 filled
2017.01.05 11:00:00 9 EURUSD buy stop 0.11 / 0.00 1.05399

2017.01.05 12:58:27 canceled
2017.01.05 11:00:00 10 EURUSD buy limit 0.11 / 0.11 1.04899

2017.01.05 12:58:27 filled
2017.01.05 12:58:27 11 EURUSD close by 0.11 / 0.11 1.04896

2017.01.05 12:58:27 filled close #8 by #10
2017.01.05 16:00:00 12 EURUSD buy 0.19 / 0.19 1.05307

2017.01.05 16:00:00 filled
2017.01.05 16:00:00 13 EURUSD buy 0.30 / 0.30 1.05307 1.04807 1.05807 2017.01.05 16:00:00 filled
2017.01.05 16:00:00 14 EURUSD sell stop 0.11 / 0.00 1.05057

2017.01.05 17:09:40 canceled
2017.01.05 16:00:00 15 EURUSD sell limit 0.11 / 0.11 1.05557

2017.01.05 17:09:40 filled
2017.01.05 17:09:40 16 EURUSD close by 0.11 / 0.11 1.05557

2017.01.05 17:09:40 filled close #13 by #15
2017.01.05 17:28:47 17 EURUSD sell 0.11 / 0.11 1.05660

2017.01.05 17:28:47 filled
2017.01.05 17:29:15 18 EURUSD sell 0.08 / 0.08 1.05807

2017.01.05 17:29:15 filled tp 1.05807

成交
时间 成交 品种 类型 方向 交易量 价格 订单 佣金 掉期利率 盈利 余额 注释
2017.01.01 00:00:00 1
balance



0.00 0.00 3 000.00 3 000.00
2017.01.03 10:00:00 2 EURUSD sell in 0.30 1.04597 2 0.00 0.00 0.00 3 000.00
2017.01.03 10:21:32 3 EURUSD buy in 0.11 1.04347 4 0.00 0.00 0.00 3 000.00
2017.01.03 10:21:32 4 EURUSD buy out by 0.11 1.04347 5 0.00 0.00 27.50 3 027.50 close #2 by #4
2017.01.03 10:21:32 5 EURUSD sell out by 0.11 1.04597 5 0.00 0.00 0.00 3 027.50 close #2 by #4
2017.01.03 10:33:40 6 EURUSD buy out 0.11 1.04247 6 0.00 0.00 38.50 3 066.00
2017.01.03 11:34:38 7 EURUSD buy out 0.08 1.04097 7 0.00 0.00 40.00 3 106.00 tp 1.04097
2017.01.05 11:00:00 8 EURUSD sell in 0.30 1.05149 8 0.00 0.00 0.00 3 106.00
2017.01.05 12:58:27 9 EURUSD buy in 0.11 1.04896 10 0.00 0.00 0.00 3 106.00
2017.01.05 12:58:27 10 EURUSD buy out by 0.11 1.04896 11 0.00 0.00 27.83 3 133.83 close #8 by #10
2017.01.05 12:58:27 11 EURUSD sell out by 0.11 1.05149 11 0.00 0.00 0.00 3 133.83 close #8 by #10
2017.01.05 16:00:00 12 EURUSD buy out 0.19 1.05307 12 0.00 0.00 -30.02 3 103.81
2017.01.05 16:00:00 13 EURUSD buy in 0.30 1.05307 13 0.00 0.00 0.00 3 103.81
2017.01.05 17:09:40 14 EURUSD sell in 0.11 1.05557 15 0.00 0.00 0.00 3 103.81
2017.01.05 17:09:40 16 EURUSD buy out by 0.11 1.05307 16 0.00 0.00 0.00 3 103.81 close #13 by #15
2017.01.05 17:09:40 15 EURUSD sell out by 0.11 1.05557 16 0.00 0.00 27.50 3 131.31 close #13 by #15
2017.01.05 17:28:47 17 EURUSD sell out 0.11 1.05660 17 0.00 0.00 38.83 3 170.14
2017.01.05 17:29:15 18 EURUSD sell out 0.08 1.05807 18 0.00 0.00 40.00 3 210.14 tp 1.05807

0.00 0.00 210.14 3 210.14

如上表所示, EA 在 MetaTrader 5 对冲模式中的工作方式类似。对于三种类型的停止位, 其机制与 MetaTrader 4 中的相同。

下表显示了 MetaTrader 5 净持模式的测试结果:














订单
开单时间 订单 品种 类型 交易量 价格 止损 止盈 时间 状态 注释
2017.01.03 10:00:00 2 EURUSD sell 0.30 / 0.30 1.04597

2017.01.03 10:00:00 filled
2017.01.03 10:00:00 3 EURUSD buy stop 0.30 / 0.00 1.05097

2017.01.03 11:34:38 canceled
2017.01.03 10:00:00 4 EURUSD buy limit 0.30 / 0.30 1.04097

2017.01.03 11:34:38 filled
2017.01.03 10:00:00 5 EURUSD buy stop 0.11 / 0.00 1.04847

2017.01.03 10:21:32 canceled
2017.01.03 10:00:00 6 EURUSD buy limit 0.11 / 0.11 1.04347

2017.01.03 10:21:32 filled
2017.01.03 10:33:40 7 EURUSD buy 0.11 / 0.11 1.04247

2017.01.03 10:33:40 filled
2017.01.05 11:00:00 8 EURUSD sell 0.30 / 0.30 1.05149

2017.01.05 11:00:00 filled
2017.01.05 11:00:00 9 EURUSD buy stop 0.30 / 0.00 1.05649

2017.01.05 16:00:00 canceled
2017.01.05 11:00:00 10 EURUSD buy limit 0.30 / 0.00 1.04649

2017.01.05 16:00:00 canceled
2017.01.05 11:00:00 11 EURUSD buy stop 0.11 / 0.00 1.05399

2017.01.05 12:58:27 canceled
2017.01.05 11:00:00 12 EURUSD buy limit 0.11 / 0.11 1.04899

2017.01.05 12:58:27 filled
2017.01.05 16:00:00 13 EURUSD buy 0.19 / 0.19 1.05307

2017.01.05 16:00:00 filled
2017.01.05 16:00:00 14 EURUSD buy 0.30 / 0.30 1.05307

2017.01.05 16:00:00 filled
2017.01.05 16:00:00 15 EURUSD sell stop 0.30 / 0.00 1.04807

2017.01.05 17:29:15 canceled
2017.01.05 16:00:00 16 EURUSD sell limit 0.30 / 0.30 1.05807

2017.01.05 17:29:15 filled
2017.01.05 16:00:00 17 EURUSD sell stop 0.11 / 0.00 1.05057

2017.01.05 17:09:40 canceled
2017.01.05 16:00:00 18 EURUSD sell limit 0.11 / 0.11 1.05557

2017.01.05 17:09:40 filled
2017.01.05 17:28:47 19 EURUSD sell 0.11 / 0.11 1.05660

2017.01.05 17:28:47 filled

成交
时间 成交 品种 类型 方向 交易量 价格 订单 佣金 掉期利率 盈利 余额 注释
2017.01.01 00:00:00 1
balance



0.00 0.00 3 000.00 3 000.00
2017.01.03 10:00:00 2 EURUSD sell in 0.30 1.04597 2 0.00 0.00 0.00 3 000.00
2017.01.03 11:34:38 5 EURUSD buy in/out 0.30 1.04097 4 0.00 0.00 40.00 3 040.00
2017.01.03 10:21:32 3 EURUSD buy out 0.11 1.04347 6 0.00 0.00 27.50 3 067.50
2017.01.03 10:33:40 4 EURUSD buy out 0.11 1.04247 7 0.00 0.00 38.50 3 106.00
2017.01.05 11:00:00 6 EURUSD sell in/out 0.30 1.05149 8 0.00 -0.61 231.44 3 336.83
2017.01.05 12:58:27 7 EURUSD buy in/out 0.11 1.04896 12 0.00 0.00 20.24 3 357.07
2017.01.05 16:00:00 8 EURUSD buy in 0.19 1.05307 13 0.00 0.00 0.00 3 357.07
2017.01.05 16:00:00 9 EURUSD buy in 0.30 1.05307 14 0.00 0.00 0.00 3 357.07
2017.01.05 17:29:15 12 EURUSD sell out 0.30 1.05807 16 0.00 0.00 157.11 3 514.18
2017.01.05 17:09:40 10 EURUSD sell out 0.11 1.05557 18 0.00 0.00 30.11 3 544.29
2017.01.05 17:28:47 11 EURUSD sell out 0.11 1.05660 19 0.00 0.00 41.44 3 585.73

0.00 -0.61 586.34 3 585.73

在此, 我们遇到了一个问题。如同前两次测试中观察到的那样, 在最后的停止价位平仓 0.30 手, 而非 0.08 手。

如早前讨论的那样, MetaTrader 5 净持模式中的标准止损和止盈与前两者不同。因此, EA 会将经纪商端停止位转换为挂单停止位。然而, 通过这种设置, EA 已经有两个基于挂单的停止价位, 其中一个是主要停止位。还是如前所述, 这将导致孤立交易。最终或主要停止价位总是等于主交易的初始交易量。而且由于还有其它的停止价位, 因此可能会导致主要停止价位在平仓时超过主要仓位的剩余交易量。

为了解决这个问题, 一种方法是将主停止位设置为虚拟来代替, 而不是经纪商端或基于挂单的方式。利用这个新设置, EA 现在有 2 个停止位, 一个是虚拟的, 而另一个停止位则基于挂单。使用此新设置的测试结果如下所示。














订单
开单时间 订单 品种 类型 交易量 价格 止损 止盈 时间 状态 注释
2017.01.03 10:00:00 2 EURUSD sell 0.30 / 0.30 1.04597

2017.01.03 10:00:00 filled
2017.01.03 10:00:00 3 EURUSD buy stop 0.11 / 0.00 1.04847

2017.01.03 10:21:32 canceled
2017.01.03 10:00:00 4 EURUSD buy limit 0.11 / 0.11 1.04347

2017.01.03 10:21:32 filled
2017.01.03 10:33:40 5 EURUSD buy 0.11 / 0.11 1.04247

2017.01.03 10:33:40 filled
2017.01.03 11:34:38 6 EURUSD buy 0.08 / 0.08 1.04097

2017.01.03 11:34:38 filled
2017.01.05 11:00:00 7 EURUSD sell 0.30 / 0.30 1.05149

2017.01.05 11:00:00 filled
2017.01.05 11:00:00 8 EURUSD buy stop 0.11 / 0.00 1.05399

2017.01.05 12:58:27 canceled
2017.01.05 11:00:00 9 EURUSD buy limit 0.11 / 0.11 1.04899

2017.01.05 12:58:27 filled
2017.01.05 16:00:00 10 EURUSD buy 0.19 / 0.19 1.05307

2017.01.05 16:00:00 filled
2017.01.05 16:00:00 11 EURUSD buy 0.30 / 0.30 1.05307

2017.01.05 16:00:00 filled
2017.01.05 16:00:00 12 EURUSD sell stop 0.11 / 0.00 1.05057

2017.01.05 17:09:40 canceled
2017.01.05 16:00:00 13 EURUSD sell limit 0.11 / 0.11 1.05557

2017.01.05 17:09:40 filled
2017.01.05 17:28:47 14 EURUSD sell 0.11 / 0.11 1.05660

2017.01.05 17:28:47 filled
2017.01.05 17:29:15 15 EURUSD sell 0.08 / 0.08 1.05807

2017.01.05 17:29:15 filled

成交
时间 成交 品种 类型 方向 交易量 价格 订单 佣金 掉期利率 盈利 余额 注释
2017.01.01 00:00:00 1
balance



0.00 0.00 3 000.00 3 000.00
2017.01.03 10:00:00 2 EURUSD sell in 0.30 1.04597 2 0.00 0.00 0.00 3 000.00
2017.01.03 10:21:32 3 EURUSD buy out 0.11 1.04347 4 0.00 0.00 27.50 3 027.50
2017.01.03 10:33:40 4 EURUSD buy out 0.11 1.04247 5 0.00 0.00 38.50 3 066.00
2017.01.03 11:34:38 5 EURUSD buy out 0.08 1.04097 6 0.00 0.00 40.00 3 106.00
2017.01.05 11:00:00 6 EURUSD sell in 0.30 1.05149 7 0.00 0.00 0.00 3 106.00
2017.01.05 12:58:27 7 EURUSD buy out 0.11 1.04896 9 0.00 0.00 27.83 3 133.83
2017.01.05 16:00:00 8 EURUSD buy out 0.19 1.05307 10 0.00 0.00 -30.02 3 103.81
2017.01.05 16:00:00 9 EURUSD buy in 0.30 1.05307 11 0.00 0.00 0.00 3 103.81
2017.01.05 17:09:40 10 EURUSD sell out 0.11 1.05557 13 0.00 0.00 27.50 3 131.31
2017.01.05 17:28:47 11 EURUSD sell out 0.11 1.05660 14 0.00 0.00 38.83 3 170.14
2017.01.05 17:29:15 12 EURUSD sell out 0.08 1.05807 15 0.00 0.00 40.00 3 210.14

0.00 0.00 210.14 3 210.14

取自停止价位的总交易量现在等于主要交易的初始交易量。

示例 #3: 停止位与资金管理

在之前的文章 (参见 跨平台智能交易系统: 资金管理) 中, 曾讨论过一些基于某个停止价位的资金管理方法 (止盈也是可能的, 但一般使用止损)。诸如固定分数, 固定风险, 以及每点数/点值的固定风险等等的资金管理方法, 往往需要有限的停止价位。不设置这个价位意味着非常大甚或无限的风险, 因此, 交易量计算也会非常大。为了展示使用本文中提到的类对象实现的带有资金管理能力的智能交易系统, 我们将修改第一个示例, 如此一来先前注释掉的代码行将包含在编译中。

首先, 我们删除在 OnInit 函数中的资金管理方法代码行上的注释标签, 如下面的代码所示:

int OnInit()
  {
//--- 其它代码
   order_manager=new COrderManager();
   money_manager= new CMoneys();
   CMoney *money_fixed=new CMoneyFixedLot(0.05);
   CMoney *money_ff=new CMoneyFixedFractional(5);
   CMoney *money_ratio=new CMoneyFixedRatio(0,0.1,1000);
   CMoney *money_riskperpoint=new CMoneyFixedRiskPerPoint(0.1);
   CMoney *money_risk=new CMoneyFixedRisk(100);

   money_manager.Add(money_fixed);
   money_manager.Add(money_ff);
   money_manager.Add(money_ratio);
   money_manager.Add(money_riskperpoint);
   money_manager.Add(money_risk);
   order_manager.AddMoneys(money_manager);
//--- 其它代码
  }

然后, 在源代码的顶部, 我们声明一个自定义枚举, 以便我们可以创建一个外部参数, 这将允许我们按照源代码中提供的顺序选择要使用的资金管理方法:

enum ENUM_MM_TYPE
  {
   MM_FIXED=0,
   MM_FIXED_FRACTIONAL,
   MM_FIXED_RATIO,
   MM_FIXED_RISK_PER_POINT,
   MM_FIXED_RISK
  };

之后, 我们为此枚举声明一个新的输入参数:

input ENUM_MM_TYPE mm_type=MM_FIXED_FRACTIONAL;

最后, 我们必须将该参数与 OnTick 函数中实际选择的资金管理方法挂钩:

void OnTick()
  {
//---   
   manage_trades();
   if(symbol_info.RefreshRates())
     {
      signals.Check();
      if(signals.CheckOpenLong())
        {
         close_last();
         if(time_filters.Evaluate(TimeCurrent()))
           {
            Print("Entering buy trade..");
            money_manager.Selected((int)mm_type); //use mm_type, cast to 'int' type
            order_manager.TradeOpen(Symbol(),ORDER_TYPE_BUY,symbol_info.Ask());
           }
        }
      else if(signals.CheckOpenShort())
        {
         close_last();
         if(time_filters.Evaluate(TimeCurrent()))
           {
            Print("Entering sell trade..");
            money_manager.Selected((int)mm_type); //use mm_type, cast to 'int' type
            order_manager.TradeOpen(Symbol(),ORDER_TYPE_SELL,symbol_info.Bid());
           }
        }
     }
  }

由于资金管理方法只进行纯粹的计算, 所以对于 MQL4 和 MQL5 之间的兼容性没有任何问题。前两个示例已经展示了停止价位在两个平台上的工作方式。下表显示了 MetaTrader 5 对冲模式下的测试结果。

下表显示了使用固定分数资金管理的测试结果。编码设置为帐户的 5% 风险。初始本金 3000 美元, 我们预计该数值将达到约 150 美元。由于止损和止盈具有相同的数值 (500 点), 那么我们预计交易如果触及止盈则可以赚取 150 美元。














订单
开单时间 订单 品种 类型 交易量 价格 止损 止盈 时间 状态 注释
2017.01.03 10:00:00 2 EURUSD sell 0.30 / 0.30 1.04597 1.05097 1.04097 2017.01.03 10:00:00 filled
2017.01.03 11:34:38 3 EURUSD buy 0.30 / 0.30 1.04097

2017.01.03 11:34:38 filled tp 1.04097
2017.01.05 11:00:00 4 EURUSD sell 0.32 / 0.32 1.05149 1.05649 1.04649 2017.01.05 11:00:00 filled
2017.01.05 16:00:00 5 EURUSD buy 0.32 / 0.32 1.05307

2017.01.05 16:00:00 filled
2017.01.05 16:00:00 6 EURUSD buy 0.31 / 0.31 1.05307 1.04807 1.05807 2017.01.05 16:00:00 filled
2017.01.05 17:29:15 7 EURUSD sell 0.31 / 0.31 1.05807

2017.01.05 17:29:15 filled tp 1.05807

成交
时间 成交 品种 类型 方向 交易量 价格 订单 佣金 掉期利率 盈利 余额 注释
2017.01.01 00:00:00 1
balance



0.00 0.00 3 000.00 3 000.00
2017.01.03 10:00:00 2 EURUSD sell in 0.30 1.04597 2 0.00 0.00 0.00 3 000.00
2017.01.03 11:34:38 3 EURUSD buy out 0.30 1.04097 3 0.00 0.00 150.00 3 150.00 tp 1.04097
2017.01.05 11:00:00 4 EURUSD sell in 0.32 1.05149 4 0.00 0.00 0.00 3 150.00
2017.01.05 16:00:00 5 EURUSD buy out 0.32 1.05307 5 0.00 0.00 -50.56 3 099.44
2017.01.05 16:00:00 6 EURUSD buy in 0.31 1.05307 6 0.00 0.00 0.00 3 099.44
2017.01.05 17:29:15 7 EURUSD sell out 0.31 1.05807 7 0.00 0.00 155.00 3 254.44 tp 1.05807

0.00 0.00 254.44 3 254.44

请注意, 计算的交易量数值还将取决于经纪商规定的手数精度, 由最小手数和最小手数步长参数确定。我们不能指望智能交易系统总是做出精确的计算。有了这些限制, 智能交易系统也许会发现在某些点必须舍进该数值。资金管理的其它方法同样如此。

对于每点数固定风险的资金管理, 编码设置每个止损点数为 0.1 美元。止陨和止盈均设置为 500 点, 我们预计这样的盈利/亏损将达到 50 美元。














订单
开单时间 订单 品种 类型 交易量 价格 止损 止盈 时间 状态 注释
2017.01.03 10:00:00 2 EURUSD sell 0.10 / 0.10 1.04597 1.05097 1.04097 2017.01.03 10:00:00 filled
2017.01.03 11:34:38 3 EURUSD buy 0.10 / 0.10 1.04097

2017.01.03 11:34:38 filled tp 1.04097
2017.01.05 11:00:00 4 EURUSD sell 0.10 / 0.10 1.05149 1.05649 1.04649 2017.01.05 11:00:00 filled
2017.01.05 16:00:00 5 EURUSD buy 0.10 / 0.10 1.05307

2017.01.05 16:00:00 filled
2017.01.05 16:00:00 6 EURUSD buy 0.10 / 0.10 1.05307 1.04807 1.05807 2017.01.05 16:00:00 filled
2017.01.05 17:29:15 7 EURUSD sell 0.10 / 0.10 1.05807

2017.01.05 17:29:15 filled tp 1.05807

成交
时间 成交 品种 类型 方向 交易量 价格 订单 佣金 掉期利率 盈利 余额 注释
2017.01.01 00:00:00 1
balance



0.00 0.00 3 000.00 3 000.00
2017.01.03 10:00:00 2 EURUSD sell in 0.10 1.04597 2 0.00 0.00 0.00 3 000.00
2017.01.03 11:34:38 3 EURUSD buy out 0.10 1.04097 3 0.00 0.00 50.00 3 050.00 tp 1.04097
2017.01.05 11:00:00 4 EURUSD sell in 0.10 1.05149 4 0.00 0.00 0.00 3 050.00
2017.01.05 16:00:00 5 EURUSD buy out 0.10 1.05307 5 0.00 0.00 -15.80 3 034.20
2017.01.05 16:00:00 6 EURUSD buy in 0.10 1.05307 6 0.00 0.00 0.00 3 034.20
2017.01.05 17:29:15 7 EURUSD sell out 0.10 1.05807 7 0.00 0.00 50.00 3 084.20 tp 1.05807

0.00 0.00 84.20 3 084.20

对于固定风险资金管理, 编码设置为 100 美元风险。然后, EA 必须计算适合这种风险的交易量。结果如下所示.














订单
开单时间 订单 品种 类型 交易量 价格 止损 止盈 时间 状态 注释
2017.01.03 10:00:00 2 EURUSD sell 0.20 / 0.20 1.04597 1.05097 1.04097 2017.01.03 10:00:00 filled
2017.01.03 11:34:38 3 EURUSD buy 0.20 / 0.20 1.04097

2017.01.03 11:34:38 filled tp 1.04097
2017.01.05 11:00:00 4 EURUSD sell 0.20 / 0.20 1.05149 1.05649 1.04649 2017.01.05 11:00:00 filled
2017.01.05 16:00:00 5 EURUSD buy 0.20 / 0.20 1.05307

2017.01.05 16:00:00 filled
2017.01.05 16:00:00 6 EURUSD buy 0.20 / 0.20 1.05307 1.04807 1.05807 2017.01.05 16:00:00 filled
2017.01.05 17:29:15 7 EURUSD sell 0.20 / 0.20 1.05807

2017.01.05 17:29:15 filled tp 1.05807

成交
时间 成交 品种 类型 方向 交易量 价格 订单 佣金 掉期利率 盈利 余额 注释
2017.01.01 00:00:00 1
balance



0.00 0.00 3 000.00 3 000.00
2017.01.03 10:00:00 2 EURUSD sell in 0.20 1.04597 2 0.00 0.00 0.00 3 000.00
2017.01.03 11:34:38 3 EURUSD buy out 0.20 1.04097 3 0.00 0.00 100.00 3 100.00 tp 1.04097
2017.01.05 11:00:00 4 EURUSD sell in 0.20 1.05149 4 0.00 0.00 0.00 3 100.00
2017.01.05 16:00:00 5 EURUSD buy out 0.20 1.05307 5 0.00 0.00 -31.60 3 068.40
2017.01.05 16:00:00 6 EURUSD buy in 0.20 1.05307 6 0.00 0.00 0.00 3 068.40
2017.01.05 17:29:15 7 EURUSD sell out 0.20 1.05807 7 0.00 0.00 100.00 3 168.40 tp 1.05807

0.00 0.00 168.40 3 168.40

一定要记住, 订单管理器将始终把主要停止位运用在资金管理当中。如果没有声明主要停止位, 即使有其它停止位存在, 也不能使用基于止损的资金管理方法。

结束语

在本文中, 我们讨论了在跨平台智能交易系统中添加停止价位。这两个交易平台虽然拥有许多平行功能, 但在停止价位的实现方式上却有很大差异。本文提供了一种方法, 可以调和这些差异, 令智能交易系统可以兼容这两个平台。

文章中使用的程序

#
名称
类型
描述
1.
stops_ha_ma1.mqh
头文件
在第一个示例中用于智能交易系统的主要头文件
2.
stops_ha_ma1.mq4 智能交易系统
在第一个示例中用于 MQL4 智能交易系统的主要源文件
3.
stops_ha_ma1.mq5 智能交易系统 在第一个示例中用于 MQL5 智能交易系统的主要源文件
4.  stops_ha_ma2.mqh 头文件 在第二个示例中用于智能交易系统的主要头文件
5.  stops_ha_ma2.mq4 智能交易系统
在第二个示例中用于 MQL4 智能交易系统的主要源文件
6.  stops_ha_ma2.mq5 智能交易系统
在第二个示例中用于 MQL5 智能交易系统的主要源文件
7.  stops_ha_ma3.mqh 头文件 在第三个示例中用于智能交易系统的主要头文件
8.  stops_ha_ma3.mq4 智能交易系统
在第三个示例中用于 MQL4 智能交易系统的主要源文件
9.  stops_ha_ma3.mq5 智能交易系统
在第三个示例中用于 MQL5 智能交易系统的主要源文件

文章中的类文件

#
名称
类型
描述
1.
MQLx\Base\Stop\StopBase.mqh
头文件
CStop (基类)
2.
MQLx\MQL4\Stop\Stop.mqh 头文件 CStop (MQL4 版本)
3.
MQLx\MQL5\Stop\Stop.mqh 头文件 CStop (MQL5 版本)
4. MQLx\Base\Stop\StopsBase.mqh 头文件 CStops (CStop 容器, 基类)
5. MQLx\MQL4\Stop\Stops.mqh 头文件 CStops (MQL4 版本)
6. MQLx\MQL5\Stop\Stops.mqh 头文件 CStops (MQL5 版本)
7. MQLx\Base\Stop\StopLineBase.mqh 头文件 CStopLine (图形表述, 基类)
8. MQLx\MQL4\Stop\StopLine.mqh 头文件 CStopLine (MQL4 版本)
9. MQLx\MQL5\Stop\StopLine.mqh 头文件 CStopLine (MQL5 版本)
10.  MQLx\Base\Order\OrderStopBase.mqh 头文件 COrderStop (基类)
11.  MQLx\MQL4\Order\OrderStop.mqh 头文件 COrderStop (MQL4 版本)
12.  MQLx\MQL5\Order\OrderStop.mqh 头文件 COrderStop (MQL5 版本)
13.
 MQLx\Base\Order\OrderStopVirtualBase.mqh 头文件
COrderStopVirtual (虚拟停止价位, 基类)
14.  MQLx\Base\Order\OrderStopVirtual.mqh 头文件
COrderStopVirtual (MQL4 版本)
15.
 MQLx\Base\Order\OrderStopVirtual.mqh 头文件
COrderStopVirtual (MQL5 版本)
16.  MQLx\Base\Order\OrderStopPendingBase.mqh 头文件
COrderStopPending (挂单停止价位, 基类)
17.  MQLx\Base\Order\OrderStopPending.mqh 头文件
COrderStopPending (MQL4 版本)
18.
 MQLx\Base\Order\OrderStopPending.mqh 头文件
COrderStopPending (MQL5 版本)
19.
 MQLx\Base\Order\OrderStopBroker.mqh 头文件
COrderStopBroker (经纪商端停止价位, 基类)
20.  MQLx\Base\Order\OrderStopBroker.mqh 头文件
COrderStopBroker (MQL4 版本)
21.  MQLx\Base\Order\OrderStopBroker.mqh 头文件
COrderStopBroker (MQL5 版本)
22.  MQLx\Base\Order\OrderStopsBase.mqh 头文件
COrderStops (COrderStop 容器, 基类)
23.  MQLx\Base\Order\OrderStops.mqh 头文件
COrderStops (MQL4 版本)
24.  MQLx\Base\Order\OrderStops.mqh 头文件
COrderStops (MQL5 版本)