请 [注册] 或 [登录]  | 返回主站

量化交易吧 /  量化策略 帖子:3364704 新帖:25

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

外汇工厂发表于:4 月 17 日 16:56回复(1)

简介

使用 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 类方法的方式。我相信本文对于使用挂单交易的交易人员而言会有所帮助。

全部回复

0/140

量化课程

    移动端课程