English Русский Español Deutsch 日本語 Português 한국어 Français Italiano Türkçe
MQL5 向导:如何教导 EA 以任意价格建立挂单

MQL5 向导:如何教导 EA 以任意价格建立挂单

MetaTrader 5示例 | 19 五月 2014, 11:13
4 298 4
Vladimir Karputov
Vladimir Karputov

简介

使用 MQL5 向导生成的“EA 交易”只能以距当前价格的固定距离建立挂单。这意味着如果市场情况发生变化(例如市场波动中的变化),“EA 交易”不得不以新的参数重新运行。

这对于许多交易系统而言是不合适的。在大多数情形中,挂单的价格水平由交易系统动态决定。而且与当前价格的距离一直都在变化。在本文中,我们将探讨如何修改使用 MQL5 向导生成的“EA 交易”,使其能够以与当前价格的可变距离建立挂单。

1. 在使用 MQL5 向导生成的“EA 交易”中建立挂单的机制

生成的“EA 交易”的头文件将具有与下述代码大致相同的代码:

//+------------------------------------------------------------------+
//| Inputs                                                           |
//+------------------------------------------------------------------+
//--- inputs for expert
input string             Expert_Title="ExpertMySignalEnvelopes.mq5";      // Document name
ulong                    Expert_MagicNumber        =3915;        // 
bool                     Expert_EveryTick          =false;       // 
//--- inputs for main signal
input int                Signal_ThresholdOpen      =10;          // Signal threshold value to open [0...100]
input int                Signal_ThresholdClose     =10;          // Signal threshold value to close [0...100]
input double             Signal_PriceLevel         =0.0;         // Price level to execute a deal
input double             Signal_StopLevel          =85.0;        // Stop Loss level (in points)
input double             Signal_TakeLevel          =195.0;       // Take Profit level (in points)
input int                Signal_Expiration         =0;           // Expiration of pending orders (in bars)
input int                Signal_Envelopes_PeriodMA =13;          // Envelopes(13,0,MODE_SMA,...) Period of averaging
input int                Signal_Envelopes_Shift    =0;           // Envelopes(13,0,MODE_SMA,...) Time shift
input ENUM_MA_METHOD     Signal_Envelopes_Method   =MODE_SMA;    // Envelopes(13,0,MODE_SMA,...) Method of averaging
input ENUM_APPLIED_PRICE Signal_Envelopes_Applied  =PRICE_CLOSE; // Envelopes(13,0,MODE_SMA,...) Prices series
input double             Signal_Envelopes_Deviation=0.2;         // Envelopes(13,0,MODE_SMA,...) Deviation
input double             Signal_Envelopes_Weight   =1.0;         // Envelopes(13,0,MODE_SMA,...) Weight [0...1.0]
//--- inputs for money
input double             Money_FixLot_Percent      =10.0;        // Percent
input double             Money_FixLot_Lots         =0.1;         // Fixed volume
//+------------------------------------------------------------------+

请注意 Signal_PriceLevel 参数。在默认情况下,“EA 交易”由 Signal_PriceLevel=0 生成。此参数定义与当前价格的距离。如果其值等于零,将会以当前市场价格建立订单。要建立挂单,您需要为 Signal_PriceLevel 参数设置非零值,即 Signal_PriceLevel 的值可以是正数也可以是负数。

Signal_PriceLevel 参数的值通常是一个相当大的数字。负值与正值之间的差异如下所示:

Signal_PriceLevel=-50

图 1. Signal_PriceLevel=-50

图 1. Signal_PriceLevel=-50

Signal_PriceLevel=50

图 2. Signal_PriceLevel=50

图 2. Signal_PriceLevel=50

因此,如果 Signal_PriceLevel=-50,将以较当前价格不太有利的价格建立挂单,而如果 Signal_PriceLevel=50,将以较当前价格更优的价格建立挂单。

这个版本的“EA 交易”建立卖出止损和买入止损订单。

2. 我们在何处存储建立挂单时与当前价格的距离的数据?

我们先来看看下面的图,然后是注释部分:

图 3. 存储与当前价格的距离的数据

图 3. 存储与当前价格的距离的数据

解读上图。

Expert Advisor 是使用 MQL5 向导生成的“EA 交易”。

  • CExpert 类的 ExtExpert 对象在“EA 交易”中从全局层面声明。
  • 然后,在“EA 交易”的 OnInit() 函数中,我们声明一个指向 CExpertSignal 类的 signal 对象的指针signal 对象将立即使用 new 运算符创建。
  • OnInit() 函数中,我们调用 ExtExpert 对象的 InitSignal 函数并初始化 signal 对象。
  • OnInit() 函数中,我们调用获取 Signal_PriceLevel 参数的 signal 对象的 PriceLevel 函数。

因此,在 Expert Advisor 中声明的用于存储与当前价格距离的 Signal_PriceLevel 参数被传递至 CExpertSignal 类的 signal 对象。

CExpertSignal 类在以受保护的类的范围声明的 m_price_level 变量中存储与当前价格的距离的值:

class CExpertSignal : public CExpertBase
  {
protected:
   //--- variables
   double            m_base_price;     // base price for detection of level of entering (and/or exit?)
   //--- variables for working with additional filters
   CArrayObj         m_filters;        // array of additional filters (maximum number of fileter is 64)
   //--- Adjusted parameters
   double            m_weight;         // "weight" of a signal in a combined filter
   int               m_patterns_usage; // bit mask of  using of the market models of signals
   int               m_general;        // index of the "main" signal (-1 - no)
   long              m_ignore;         // bit mask of "ignoring" the additional filter
   long              m_invert;         // bit mask of "inverting" the additional filter
   int               m_threshold_open; // threshold value for opening
   int               m_threshold_close;// threshold level for closing
   double            m_price_level;    // level of placing a pending orders relatively to the base price
   double            m_stop_level;     // level of placing of the "stop loss" order relatively to the open price
   double            m_take_level;     // level of placing of the "take profit" order relatively to the open price
   int               m_expiration;     // time of expiration of a pending order in bars


3. 使用 MQL5 向导生成的“EA 交易”的结构

“EA 交易”由不同的功能块组成。


图 4.“EA 交易”的结构

图 4.“EA 交易”的结构

解读上图:

  • Expert Advisor 是使用 MQL5 向导生成的“EA 交易”。
  • CExpert 是实现交易策略的基类。
  • CExpertSignal 是创建交易信号生成器的基类。
  • filter0 ... filtern 是交易信号生成器,属于 CExpertSignal 类的后代。应该注意的是,我们的交易系统基于轨道线指标的交易信号生成器,但生成器内的信号已被修改。我们将在第 7 节中讨论这些变化。

4. 建议修改的“EA 交易”块

正如您在使用 MQL5 向导生成的“EA 交易”的结构中看到的,“EA 交易”包含一些基类块。基类是标准库的一部分。

这些类从本质上而言是其他基类的后代,反过来它们又可以组成一个或多个基类。下面给出了 CExpertCExpertSignal 两个类的前几行代码:

//+------------------------------------------------------------------+
//|                                                       Expert.mqh |
//|                   Copyright 2009-2013, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#include "ExpertBase.mqh"
#include "ExpertTrade.mqh"
#include "ExpertSignal.mqh"
#include "ExpertMoney.mqh"
#include "ExpertTrailing.mqh"
//+------------------------------------------------------------------+
.
.
.
class CExpert : public CExpertBase

以及

//+------------------------------------------------------------------+
//|                                                 ExpertSignal.mqh |
//|                   Copyright 2009-2013, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#include "ExpertBase.mqh"
.
.
.
class CExpertSignal : public CExpertBase

对于基类的任何修改,笔者持强烈反对态度

  1. 当 MetaEditor 更新时,您对基类所做的所有更改均被覆盖,且基类将恢复到其初始状态。
  2. 继承在这种情形中将会更合适。但如此一来,您将不得不修改整个标准库。

作为替代,最好是修改“EA 交易”的块和交易信号生成器模块,尤其是考虑到我们的交易系统已经有一个在用的修改模块 - 轨道线指标的交易信号生成器

所以,就这么定了:我们将修改“EA 交易”和交易信号生成器的块。

5. 实现逻辑

指针将从“EA 交易”传递至交易信号生成器。

为此,我们需要额外声明一个具有受保护范围的变量,并编写一个在内部变量中存储来自“EA 交易”的指针的方法:


  图 5. 实现逻辑

图 5. 实现逻辑


6. 交易系统

图表的时间表为 D1。使用的指标是采用平均周期为 13 和指数平均法的轨道线。“EA 交易”可建立的订单类型为卖出止损买入止损

如果上一个柱为牛势,我们设置一个卖出止损订单。如果上一个柱为熊势,我们设置一个买入止损订单。换言之,我们期待回调:

图 6. 交易系统

图 6. 交易系统

要生成交易系统要求的交易信号,需要修改交易信号生成器 SignalEnvelopes.mqh 的标准模块。

注意,在此您可以使用标准库中的任意交易信号生成器。

7. 交易信号生成器修改。获取柱价格

那么,让我们开始。我得说,我更喜欢将程序保存在 MQL5 存储中。

要开始修改交易信号生成器,我们要做的第一件事就是创建一个空白的包含文件,删除其所有内容并粘贴轨道线指标的标准交易信号生成器的全部内容。

默认情况下交易信号生成器必定位于 ...MQL5\Include\Expert\Signal 中。不要在标准库的 ...\Signal 文件夹内放入太多的信息,我们在 ...\Expert 文件夹下创建一个新文件夹,并将其命名为 \MySignals

图 7. 创建 MySignals 文件夹
 

图 7. 创建 MySignals 文件夹

接下来,我们使用 MQL5 向导来创建一个包含文件

在 MetaEditor 中选择 File(文件)菜单下的 "New"(新建),再选择 "Include file (*.mqh)" (包含文件 (*.mqh))。

图 8. MQL5 向导创建包含文件

图 8. MQL5 向导创建包含文件

我们的信号生成器类的名称将是 MySignalEnvelopes

并且它将位于:Include\Expert\MySignals\MySignalEnvelopes 。我们来指定它:

图 9. MQL5 向导包含文件的位置

图 9. MQL5 向导包含文件的位置

单击 "Finish"(完成)后,MQL5 向导就会生成一个空模板。

生成的 MySignalEnvelopes.mqh 文件接下来必须添加至 MQL5 存储:

图 10. MQL5 存储添加文件

图 10. MQL5 存储添加文件

添加文件后,我们需要将更改提交至 MQL5 存储:

图 11. MQL5 存储提交更改

图 11. MQL5 存储提交更改

完成上述步骤后,我们可以继续修改我们的信号生成器了。

由于生成器基于 \Include\Expert\Signal\SignalEnvelopes.mqh 文件,我们复制该文件的全部内容并粘贴至生成器文件中,只留下原来的头文件:

//+------------------------------------------------------------------+
//|                                            MySignalEnvelopes.mqh |
//|                              Copyright © 2013, Vladimir Karputov |
//|                                           http://wmua.ru/slesar/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2013, Vladimir Karputov"
#property link      "http://wmua.ru/slesar/"
#include <Expert\ExpertSignal.mqh>
// wizard description start
//+------------------------------------------------------------------+
//| Description of the class                                         |
//| Title=Signals of indicator 'Envelopes'                           |
//| Type=SignalAdvanced                                              |
//| Name=Envelopes                                                   |
//| ShortName=Envelopes                                              |
//| Class=CSignalEnvelopes                                           |
//| Page=signal_envelopes                                            |
//| Parameter=PeriodMA,int,45,Period of averaging                    |
//| Parameter=Shift,int,0,Time shift                                 |
//| Parameter=Method,ENUM_MA_METHOD,MODE_SMA,Method of averaging     |
//| Parameter=Applied,ENUM_APPLIED_PRICE,PRICE_CLOSE,Prices series   |
//| Parameter=Deviation,double,0.15,Deviation                        |
//+------------------------------------------------------------------+
// wizard description end
//+------------------------------------------------------------------+
//| Class CSignalEnvelopes.                                          |
//| Purpose: Class of generator of trade signals based on            |
//|          the 'Envelopes' indicator.                              |
//| Is derived from the CExpertSignal class.                         |
//+------------------------------------------------------------------+
class CSignalEnvelopes : public CExpertSignal
  {
protected:
   CiEnvelopes       m_env;            // object-indicator
   //--- adjusted parameters
   int               m_ma_period;      // the "period of averaging" parameter of the indicator
   int               m_ma_shift;       // the "time shift" parameter of the indicator
   ENUM_MA_METHOD    m_ma_method;      // the "method of averaging" parameter of the indicator
   ENUM_APPLIED_PRICE m_ma_applied;    // the "object of averaging" parameter of the indicator
   double            m_deviation;      // the "deviation" parameter of the indicator
   double            m_limit_in;       // threshold sensitivity of the 'rollback zone'
   double            m_limit_out;      // threshold sensitivity of the 'break through zone'
   //--- "weights" of market models (0-100)
   int               m_pattern_0;      // model 0 "price is near the necessary border of the envelope"
   int               m_pattern_1;      // model 1 "price crossed a border of the envelope"

public:
                     CSignalEnvelopes(void);
                    ~CSignalEnvelopes(void);
   //--- methods of setting adjustable parameters
   void              PeriodMA(int value)                 { m_ma_period=value;        }
   void              Shift(int value)                    { m_ma_shift=value;         }
   void              Method(ENUM_MA_METHOD value)        { m_ma_method=value;        }
   void              Applied(ENUM_APPLIED_PRICE value)   { m_ma_applied=value;       }
   void              Deviation(double value)             { m_deviation=value;        }
   void              LimitIn(double value)               { m_limit_in=value;         }
   void              LimitOut(double value)              { m_limit_out=value;        }
   //--- methods of adjusting "weights" of market models
   void              Pattern_0(int value)                { m_pattern_0=value;        }
   void              Pattern_1(int value)                { m_pattern_1=value;        }
   //--- method of verification of settings
   virtual bool      ValidationSettings(void);
   //--- method of creating the indicator and timeseries
   virtual bool      InitIndicators(CIndicators *indicators);
   //--- methods of checking if the market models are formed
   virtual int       LongCondition(void);
   virtual int       ShortCondition(void);

protected:
   //--- method of initialization of the indicator
   bool              InitMA(CIndicators *indicators);
   //--- methods of getting data
   double            Upper(int ind)                      { return(m_env.Upper(ind)); }
   double            Lower(int ind)                      { return(m_env.Lower(ind)); }
  };
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CSignalEnvelopes::CSignalEnvelopes(void) : m_ma_period(45),
                                           m_ma_shift(0),
                                           m_ma_method(MODE_SMA),
                                           m_ma_applied(PRICE_CLOSE),
                                           m_deviation(0.15),
                                           m_limit_in(0.2),
                                           m_limit_out(0.2),
                                           m_pattern_0(90),
                                           m_pattern_1(70)
  {
//--- initialization of protected data
   m_used_series=USE_SERIES_OPEN+USE_SERIES_HIGH+USE_SERIES_LOW+USE_SERIES_CLOSE;
  }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CSignalEnvelopes::~CSignalEnvelopes(void)
  {
  }
//+------------------------------------------------------------------+
//| Validation settings protected data.                              |
//+------------------------------------------------------------------+
bool CSignalEnvelopes::ValidationSettings(void)
  {
//--- validation settings of additional filters
   if(!CExpertSignal::ValidationSettings())
      return(false);
//--- initial data checks
   if(m_ma_period<=0)
     {
      printf(__FUNCTION__+": period MA must be greater than 0");
      return(false);
     }
//--- ok
   return(true);
  }
//+------------------------------------------------------------------+
//| Create indicators.                                               |
//+------------------------------------------------------------------+
bool CSignalEnvelopes::InitIndicators(CIndicators *indicators)
  {
//--- check pointer
   if(indicators==NULL)
      return(false);
//--- initialization of indicators and timeseries of additional filters
   if(!CExpertSignal::InitIndicators(indicators))
      return(false);
//--- create and initialize MA indicator
   if(!InitMA(indicators))
      return(false);
//--- ok
   return(true);
  }
//+------------------------------------------------------------------+
//| Initialize MA indicators.                                        |
//+------------------------------------------------------------------+
bool CSignalEnvelopes::InitMA(CIndicators *indicators)
  {
//--- check pointer
   if(indicators==NULL)
      return(false);
//--- add object to collection
   if(!indicators.Add(GetPointer(m_env)))
     {
      printf(__FUNCTION__+": error adding object");
      return(false);
     }
//--- initialize object
   if(!m_env.Create(m_symbol.Name(),m_period,m_ma_period,m_ma_shift,m_ma_method,m_ma_applied,m_deviation))
     {
      printf(__FUNCTION__+": error initializing object");
      return(false);
     }
//--- ok
   return(true);
  }
//+------------------------------------------------------------------+
//| "Voting" that price will grow.                                   |
//+------------------------------------------------------------------+
int CSignalEnvelopes::LongCondition(void)
  {
   int result=0;
   int idx   =StartIndex();
   double close=Close(idx);
   double upper=Upper(idx);
   double lower=Lower(idx);
   double width=upper-lower;
//--- if the model 0 is used and price is in the rollback zone, then there is a condition for buying
   if(IS_PATTERN_USAGE(0) && close<lower+m_limit_in*width && close>lower-m_limit_out*width)
      result=m_pattern_0;
//--- if the model 1 is used and price is above the rollback zone, then there is a condition for buying
   if(IS_PATTERN_USAGE(1) && close>upper+m_limit_out*width)
      result=m_pattern_1;
//--- return the result
   return(result);
  }
//+------------------------------------------------------------------+
//| "Voting" that price will fall.                                   |
//+------------------------------------------------------------------+
int CSignalEnvelopes::ShortCondition(void)
  {
   int result  =0;
   int idx     =StartIndex();
   double close=Close(idx);
   double upper=Upper(idx);
   double lower=Lower(idx);
   double width=upper-lower;
//--- if the model 0 is used and price is in the rollback zone, then there is a condition for selling
   if(IS_PATTERN_USAGE(0) && close>upper-m_limit_in*width && close<upper+m_limit_out*width)
      result=m_pattern_0;
//--- if the model 1 is used and price is above the rollback zone, then there is a condition for selling
   if(IS_PATTERN_USAGE(1) && close<lower-m_limit_out*width)
      result=m_pattern_1;
//--- return the result
   return(result);
  }
//+------------------------------------------------------------------+

现在,我们将修改代码的某些部分。

为避免混淆,修改过的代码将以高亮显示

//+------------------------------------------------------------------+
//|                                                     MySignal.mqh |
//|                              Copyright © 2013, Vladimir Karputov |
//|                                           http://wmua.ru/slesar/ |
//+------------------------------------------------------------------+

修改过的代码,是指需要复制和粘贴到交易信号生成器的代码。我希望这种高亮显示将有助于你们更好地理解代码。

由于我们编写我们自己的交易信号生成器类,其名称应与基类的名称不同。因此,我们在整个代码中用 CMySignalEnvelopes 替换 CSignalEnvelopes。

图 12. 重命名类

图 12. 重命名类

要确保交易信号生成器类在 MQL5 向导中以其名称显示,在描述块中将类名称

//| Title=Signals of indicator 'Envelopes'                           |

改为

//| Title=Signals of indicator 'MySignalEnvelopes'                   |

将 MA 周期值

//| Parameter=PeriodMA,int,45,Period of averaging                    |

改为 13(这只是我的建议,您可以设置您喜欢的任何值)

//| Parameter=PeriodMA,int,13,Period of averaging                    |

此外,我们还修改 Deviation 参数

//| Parameter=Deviation,double,0.15,Deviation                        |

方法是设置一个较大的值

//| Parameter=Deviation,double,1.15,Deviation                        |

根据我们的实现逻辑,我们需要声明一个用于存储指向主信号的指针的内部变量。

由于这必须是一个内部变量(仅在交易信号生成器类范围内),必须将其添加至下述代码块:

protected:
   CiEnvelopes       m_env;          // object-indicator
   //--- adjusted parameters
   int               m_ma_period;    // the "period of averaging" parameter of the indicator
   int               m_ma_shift;     // the "time shift" parameter of the indicator
   ENUM_MA_METHOD    m_ma_method;     // the "method of averaging" parameter of the indicator
   ENUM_APPLIED_PRICE m_ma_applied;    // the "object of averaging" parameter of the indicator
   double            m_deviation;    // the "deviation" parameter of the indicator
   //--- "weights" of market models (0-100)
   int               m_pattern_0;      // model 0
   CExpertSignal    *m_signal;         // storing the pointer to the main signal

亦请注意,我从代码中删除了不必要的变量。

存储指向主信号的指针的方法将在另一个代码块中声明 - "method of setting the pointer to the main signal"(设置指向主信号的指针的方法)。在这里,我还删除了一些不相关的方法。

public:
                     CMySignalEnvelopes(void);
                    ~CMySignalEnvelopes(void);
   //--- methods of setting adjustable parameters
   void              PeriodMA(int value)                 { m_ma_period=value;        }
   void              Shift(int value)                    { m_ma_shift=value;         }
   void              Method(ENUM_MA_METHOD value)        { m_ma_method=value;        }
   void              Applied(ENUM_APPLIED_PRICE value)   { m_ma_applied=value;       }
   void              Deviation(double value)             { m_deviation=value;        }
   //--- methods of adjusting "weights" of market models
   void              Pattern_0(int value)                { m_pattern_0=value;        }
   //--- method of verification of settings
   virtual bool      ValidationSettings(void);
   //--- method of creating the indicator and timeseries
   virtual bool      InitIndicators(CIndicators *indicators);
   //--- methods of checking if the market models are formed
   virtual int       LongCondition(void);
   virtual int       ShortCondition(void);
   //--- method of setting the pointer to the main signal
   virtual bool      InitSignal(CExpertSignal *signal=NULL);

现在,让我们在构造函数中指定一些修改过的参数和删除不再需要的变量:

//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CMySignalEnvelopes::CMySignalEnvelopes(void) : m_ma_period(13),
                                               m_ma_shift(0),
                                               m_ma_method(MODE_SMA),
                                               m_ma_applied(PRICE_CLOSE),
                                               m_deviation(1.15),
                                               m_pattern_0(50)  

至此,我们可以继续根据我们的交易系统修改交易信号生成逻辑。

负责买入信号的代码块:

int CMySignalEnvelopes::LongCondition(void)
  {
   int result=0;
   int idx   =StartIndex();
   double close=Close(idx);
   double upper=Upper(idx);
   double lower=Lower(idx);
   double width=upper-lower;
//--- if the model 0 is used and price is in the rollback zone, then there is a condition for buying
   if(IS_PATTERN_USAGE(0) && close<lower+m_limit_in*width && close>lower-m_limit_out*width)
      result=m_pattern_0;
//--- if the model 1 is used and price is above the rollback zone, then there is a condition for buying
   if(IS_PATTERN_USAGE(1) && close>upper+m_limit_out*width)
      result=m_pattern_1;
//--- return the result
   return(result);
  }

将如下所示(已进行必要更改):

int CMySignalEnvelopes::LongCondition(void) //---buy
  {
   int result=0;
   int idx   =StartIndex();
   double open=Open(idx);
   double close=Close(idx);
   double prlevel;
      if(IS_PATTERN_USAGE(0) && close<open)
        {
         prlevel=GetPriceLevelStopp(open,Open(0));
         m_signal.PriceLevel(prlevel);
         result=m_pattern_0;
        }
//--- return the result
   return(result);
  }

负责卖出信号的代码块:

int CMySignalEnvelopes::ShortCondition(void)
  {
   int result  =0;
   int idx     =StartIndex();
   double close=Close(idx);
   double upper=Upper(idx);
   double lower=Lower(idx);
   double width=upper-lower;
//--- if the model 0 is used and price is in the rollback zone, then there is a condition for selling
   if(IS_PATTERN_USAGE(0) && close>upper-m_limit_in*width && close<upper+m_limit_out*width)
      result=m_pattern_0;
//--- if the model 1 is used and price is above the rollback zone, then there is a condition for selling
   if(IS_PATTERN_USAGE(1) && close<lower-m_limit_out*width)
      result=m_pattern_1;
//--- return the result
   return(result);
  }

将如下所示(已进行必要更改):

int CMySignalEnvelopes::ShortCondition(void) //---sell
  {
   int result  =0;
   int idx     =StartIndex();
   double open=Open(idx);
   double close=Close(idx);
   double prlevel;
      if(IS_PATTERN_USAGE(0) && close>open)
        {
         prlevel=GetPriceLevelStopp(Open(0),open);
         m_signal.PriceLevel(prlevel);
         result=m_pattern_0;
        }
//--- return the result
   return(result);
  }


8. 对信号代码块的几点说明

如果一个特定信号要求的条件得到满足,我们调用 GetPriceLevelStopp 方法,该方法返回类似于 "20" 或 "15" 的数字 - 与当前价格的距离值。

接下来是调用 m_signal 对象的 PriceLevel 方法(设置确定挂单价格水平的距离)。需要提醒读者的是,m_signal 是存储指向主信号的 CExpertSignal 类对象。

GetPriceLevelStopp 方法的代码如下:

double CMySignalEnvelopes::GetPriceLevelStopp(double price_0,double min)
  {
   double level;
   double temp;
   temp-=(price_0-min)/PriceLevelUnit();
   level=NormalizeDouble(temp,0);
   return(level);
  }

我们需要在类头文件中声明此方法:

protected:
   //--- method of initialization of the indicator
   bool              InitMA(CIndicators *indicators);
   //--- methods of getting data
   double            Upper(int ind)                      { return(m_env.Upper(ind)); }
   double            Lower(int ind)                      { return(m_env.Lower(ind)); }
   double            GetPriceLevelStopp(double price,double min);
  };

我们需要的另一个方法是将指向主信号的指针传递至内部变量的方法:

bool CMySignalEnvelopes::InitSignal(CExpertSignal *signal)
  {
   m_signal=signal;
   return(true);
  }

之后,我们应在 MQL5 向导中创建一个“EA 交易”,并将其包含在信号模块 "MySignalEnvelopes" 中。

我们还需要将 InitSignal 方法调用添加至使用 MQL5 向导生成的“EA 交易”的代码中:

//--- Set filter parameters
   filter0.PeriodMA(Signal_Envelopes_PeriodMA);
   filter0.Shift(Signal_Envelopes_Shift);
   filter0.Method(Signal_Envelopes_Method);
   filter0.Applied(Signal_Envelopes_Applied);
   filter0.Deviation(Signal_Envelopes_Deviation);
   filter0.Weight(Signal_Envelopes_Weight);
   filter0.InitSignal(signal);
//...

为更好地可视化“EA 交易”的操作,我提供了一段简短的视频:

使用 MQL5 向导生成的“EA 交易”的代码以及信号模块的代码已附于本文。

下图所示即为“EA 交易”的测试结果。这是货币对为 EURUSD 和 USDJPY 的测试,参数如下:测试周期 2013.01.01 - 2013.09.01,时间表 - D1,止损水平 = 85,获利水平 = 195。

图 13. EURUSD 在 D1 上的测试

图 13. EURUSD 在 D1 上的测试

图 14. USDJPY 在 D1 上的测试

图 14. USDJPY 在 D1 上的测试

总结

我们刚刚讨论了如何修改交易信号模块的代码,以实现允许以距当前价格的任意距离设置挂单的功能:它可以是上一个柱的收盘价或开盘价,或者是移动平均线的值。有很多的选择。重要的是,您可以为挂单设置任意的开盘价。

本文讨论了我们可以访问指向主信号的指针以及从而访问 CExpertSignal 类方法的方式。我相信本文对于使用挂单交易的交易人员而言会有所帮助。

本文由MetaQuotes Ltd译自俄文
原文地址: https://www.mql5.com/ru/articles/723

最近评论 | 前往讨论 (4)
hongtao
hongtao | 30 11月 2014 在 06:56
谢谢分享  功德无量 新人学习 
zdzzkb
zdzzkb | 19 11月 2015 在 10:30
hongtao:
谢谢分享  功德无量 新人学习 
感谢分析啊,牛人!!!!!!
zdzzkb
zdzzkb | 20 11月 2015 在 04:45
我看了一下,此EA是在当前点位上下几十个点位设置挂单。请问,如何在此挂单EA中如何设置支撑阻力点位挂单呢?比如,计算前几根k线的最低价,最高价,在最低价、最高价处挂单。
vito hong
vito hong | 14 9月 2020 在 11:54
在信号生成器里面直接调用PriceLevel()不就可以了吗,为什么一定要把*signal指针传进信号生成器?
通过有用的技术组合让您的 MQL5 客户惊叹! 通过有用的技术组合让您的 MQL5 客户惊叹!
得益于 MQL5 为编程人员提供的一套非常完整的函数集和面向对象 API,他们可以在 MetaTrader 环境中大展身手。然而,Web 技术如今是用途极为广泛的工具,可以在一些情形中提供帮助:当您需要完成一些非常具体的工作;希望用一些不同的东西给您的客户留下深刻印象;或仅仅是您没有足够的时间来掌握 MT5 标准库的特定部分。今天的练习引导您完成有关如何在创建令人惊叹的技术组合的同时,管理您的开发时间的实例。
建立自动新闻交易程序 建立自动新闻交易程序
这是 "Another MQL5 OOP"(另一个 MQL5 OOP 类)一文的续篇,该文向您展示了如何从头建立一个简单的面向对象的 EA 交易程序并向您提供了有关面向对象编程的某些提示。今天,我向您展示开发一个能够依据新闻进行交易的 EA 所需的技术基础。我的目标是继续向您提供有关面向对象编程的理念,同时也在这个系列的文章中涵盖新的主题——处理文件系统。
将您的线性交易系统提升为幂交易系统 将您的线性交易系统提升为幂交易系统
今天的文章为中级 MQL5 编程人员讲解如何通过轻松实施所谓的幂的技术从他们的线性交易系统(固定手数)中获利更多。这是因为结果资产净值曲线呈抛物线形式,以几何级数或指数增长。具体而言,我们将实施一个由 Ralph Vince 开发的固定分数仓位大小的实际 MQL5 变体。
MQL5 编程基础:列表 MQL5 编程基础:列表
用于交易策略开发的编程语言 MQL 的新版本 [MQL5] 与以前的版本 [MQL4] 相比,提供了更加强大和高效的功能。这些优势实质上是面向对象的编程功能。本文探讨对于复杂自定义数据类型的使用,例如节点和列表。它还在提供了在 MQL5 实战编程中使用列表的例子。