扩展 MQL5 标准库和重用代码

27 五月 2014, 13:26
Jordi Bassaganas
0
1 667

简介

MQL5 标准库是一个面向对象框架,由一组准备就绪的、让您作为一名开发人员的工作变得更容易的类组成。然而,它无法实现世界上所有开发人员的全部需求,所以,如果您觉得您需要更多的自定义程序,您可以对标准库进行进一步的扩展。本文指导您完成将 MetaQuotes 的峰谷技术指标集成至标准库。我们将从 MetaQuotes 的设计理念获得启发以实现我们的目标。

简而言之,MQL5 API 旨在让您从代码重用、可靠性、灵活性和易于维护中受益。这是从理论上而言,但除了这一切,如果您计划在 MQL5 中更进一步,开发出更复杂的工具,例如多货币“EA 交易”,首先您应该能够以标准库的方式来编写代码,以便您的应用程序保证成功。

随着您的 EA 和指标日趋复杂,掌握框架开发所涉及理念的必要性则愈加凸显。作为一个现实例子,开发一个复杂的多货币 EA 是我的个人需求,这决定了从头开始强化我的项目根基的需求。

图 1. 正多面体是完美的对象。它们很好地描绘了基于立体理念构建应用程序的方法。

图 1. 正多面体是完美的对象。它们很好地描绘了基于立体理念构建应用程序的方法

1. 峰谷指标下载

我们从下载 MetaQuotes 的峰谷指标开始,该指标在我们的 MetaTrader 5 终端的代码库中提供。这将创建 Indicators\zigzag.mq5Indicators\zigzag.ex5 文件。

图 2. 我们开始从我们的 MetaTrader 5 终端下载 MetaQuotes 的峰谷指标

图 2. 我们开始从我们的 MetaTrader 5 终端下载 MetaQuotes 的峰谷指标

在此,我附上了 Indicators\zigzag.mq5 中包含指标的输入参数、全局变量和 OnInit() 处理程序的那些代码行。之所以仅仅附上部分代码是因为整个文件有 298 行代码。这只是出于方便和帮助读者从整体上理解我们在下文中讨论内容的考虑。

//+------------------------------------------------------------------+
//|                                                       ZigZag.mq5 |
//|                        Copyright 2009, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "2009, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 3
#property indicator_plots   1
//---- plot Zigzag
#property indicator_label1  "Zigzag"
#property indicator_type1   DRAW_SECTION
#property indicator_color1  Red
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- input parameters
input int      ExtDepth=12;
input int      ExtDeviation=5;
input int      ExtBackstep=3;
//--- indicator buffers
double         ZigzagBuffer[];      // main buffer
double         HighMapBuffer[];     // highs
double         LowMapBuffer[];      // lows
int            level=3;             // recounting depth
double         deviation;           // deviation in points
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,ZigzagBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,HighMapBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(2,LowMapBuffer,INDICATOR_CALCULATIONS);

//--- set short name and digits   
   PlotIndexSetString(0,PLOT_LABEL,"ZigZag("+(string)ExtDepth+","+(string)ExtDeviation+","+(string)ExtBackstep+")");
   IndicatorSetInteger(INDICATOR_DIGITS,_Digits);
//--- set empty value
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
//--- to use in cycle
   deviation=ExtDeviation*_Point;
//---
   return(INIT_SUCCEEDED);
  }


2. 自顶向下简要概述

现在,让我们采用自顶向下的方法来考虑我们希望集成至 MQL5 标准库的新的面向对象的峰谷指标。这意味着我们首先必须审视整个系统,然后再分析它的局部。那么,我们为什么不编写几个虚拟 EA,以获得更全面的认知?让我们编写一个程序风格的“EA 交易”以及其面向对象版本。


2.1. “开箱即用”的峰谷指标

中级 MQL5 开发人员很可能会以如下方式在他们的 EA 中使用峰谷指标:

//+----------------------------------------------------------------------+
//|                                            ExpertOriginalZigZag.mq5  |
//|                   Copyright © 2013, Laplacianlab - Jordi Bassagañas  | 
//+----------------------------------------------------------------------+
//--- EA properties
#property copyright     "Copyright © 2013, Laplacianlab - Jordi Bassagañas"
#property link          "https://www.mql5.com/en/articles"
#property version       "1.00"
#property description   "This dummy Expert Advisor is just for showing how to use the original MetaQuotes' ZigZag indicator."
//--- EA inputs
input ENUM_TIMEFRAMES   EAPeriod=PERIOD_H1;
input string            CurrencyPair="EURUSD";
//--- global variables
int      zigZagHandle;
double   zigZagBuffer[];
double   zigZagHigh[];
double   zigZagLow[];
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   zigZagHandle=iCustom(CurrencyPair,EAPeriod,"zigzag",12,5,3);
   ArraySetAsSeries(zigZagBuffer,true);
   ArraySetAsSeries(zigZagHigh,true);
   ArraySetAsSeries(zigZagLow,true);  
   return(0);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   IndicatorRelease(zigZagHandle);
   ArrayFree(zigZagBuffer);
   ArrayFree(zigZagHigh);
   ArrayFree(zigZagLow);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   //--- refresh data   
   if(CopyBuffer(zigZagHandle,0,0,2,zigZagBuffer)<0)
   {
      Print("Can't copy ZigZag buffer 0!");
      return;
   }
   if(CopyBuffer(zigZagHandle,1,0,2,zigZagHigh)<0)
   {
      Print("Can't copy ZigZag buffer 1!");
      return;
   }
   if(CopyBuffer(zigZagHandle,2,0,2,zigZagLow)<0)
   {
      Print("Can't copy ZigZag buffer 2!");
      return;
   }
   //--- print values
   if(zigZagBuffer[0]!=0) Print("zigZagBuffer[0]: ", zigZagBuffer[0]);
   if(zigZagHigh[0]!=0) Print("zigZagHigh[0]: ", zigZagHigh[0]);
   if(zigZagLow[0]!=0) Print("zigZagLow[0]: ", zigZagLow[0]);
  }
//+------------------------------------------------------------------+


2.2. 将峰谷指标集成至标准库

另一方面,高级 MQL5 开发人员会希望以使用标准库指标的既有方式来使用峰谷指标,方式如下:

//+----------------------------------------------------------------------+
//|                                                  ExpertOOZigZag.mq5  |
//|                   Copyright © 2013, Laplacianlab - Jordi Bassagañas  | 
//+----------------------------------------------------------------------+
#include <..\Include\Indicators\Custom\Trend.mqh>
//--- EA properties
#property copyright     "Copyright © 2013, Laplacianlab - Jordi Bassagañas"
#property link          "https://www.mql5.com/en/articles"
#property version       "1.00"
#property description   "This dummy Expert Advisor is just for showing how to use the object-oriented version of MetaQuotes' ZigZag indicator."
//--- EA inputs
input ENUM_TIMEFRAMES   EAPeriod=PERIOD_H1;
input string            CurrencyPair="EURUSD";
//--- global variables
CiZigZag *ciZigZag;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   ciZigZag=new CiZigZag;
   ciZigZag.Create(CurrencyPair,EAPeriod,12,5,3);
   return(0);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   delete(ciZigZag);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {   
   //--- refresh data
   ciZigZag.Refresh();
   //--- print values
   if(ciZigZag.ZigZag(0)!=0) Print("OO ZigZag buffer: ", ciZigZag.ZigZag(0));
   if(ciZigZag.High(0)!=0) Print("OO ZigZag high: ", ciZigZag.High(0));
   if(ciZigZag.Low(0)!=0) Print("OO ZigZag low: ",ciZigZag.Low(0));
  }
//+------------------------------------------------------------------+


2.3. 小结

第二个解决方案更好,因为它是面向对象的。一旦开发出面向对象类,可以很直观地看到与峰谷指标的面向对象的功能性的交互要比与其程序化版本的交互容易得多。然而,我们来简单回顾一下使用面向对象库的优势:

  • OOP 使问题建模变得容易。
  • OOP 使代码重用变得简单,反过来又会给成本、可靠性、灵活性及维护带来好处。
  • 此范式允许创建 ADT(抽象数据类型)。ADT 是所有编程语言中都存在的传统数据类型概念的一种抽象。

图 3. 正二十面体基于立体理念构建我们的应用程序是使我们的设计持久的质量保证。

图 3. 正二十面体基于立体理念构建我们的应用程序是使我们的设计持久的质量保证


3. 将我们的新的面向对象峰谷指标集成至 MQL5 标准库

正如我在本文简介部分中所述,我们在构建用于包装之前下载的峰谷指标的新的类组时受到 MetaQuotes 的面向对象风格的启发。这很简单,我们只需看一看 Include\Indicators 中的文件,学习和理解 MQL5 标准库背后的某些理念。当您查看 MetaQuotes 的 Trend.mqh 文件中的内容时,您很快会发现里面全是代表某些技术指标的类:ADX、布林带、SAR、移动平均线等。所有这些类都继承自 CIndicator。那么,让我们来实现这个方案。顺便一提,从 MQL5 的类 CiCustom 扩展新的面向对象指标是实现此练习的另一个备选方案。

我们从创建新的文件夹 Include\Indicators\Custom 开始,接下来创建新的文件 Include\Indicators\Custom\Trend.mqh,以便在其中编写我们自己的技术指标代码,正如 MetaQuotes 在其 Include\Indicators\Trend.mqh 中所做的那样。这是我们已实施的扩展文件 Include\Indicators\Custom\Trend.mqh。我将在下文中讨论一些编码所需的技术。

//+------------------------------------------------------------------+
//|                              Include\Indicators\Custom\Trend.mqh |
//|                  Copyright 2013, Laplacianlab - Jordi Bassagañas |
//|                     https://www.mql5.com/en/users/laplacianlab |
//+------------------------------------------------------------------+
#include <..\Include\Indicators\Indicator.mqh>
//+------------------------------------------------------------------+
//| Class CiZigZag.                                                  |
//| Purpose: Class of the "ZigZag" indicator.                        |
//|          Derives from class CIndicator.                          |
//+------------------------------------------------------------------+
class CiZigZag : public CIndicator
  {
protected:
   int               m_depth;
   int               m_deviation;
   int               m_backstep;

public:
                     CiZigZag(void);
                    ~CiZigZag(void);
   //--- methods of access to protected data
   int               Depth(void)          const { return(m_depth);      }
   int               Deviation(void)      const { return(m_deviation);  }
   int               Backstep(void)       const { return(m_backstep);   }
   //--- method of creation
   bool              Create(const string symbol,const ENUM_TIMEFRAMES period,
                            const int depth,const int deviation_create,const int backstep);
   //--- methods of access to indicator data
   double            ZigZag(const int index) const;
   double            High(const int index) const;
   double            Low(const int index) const;
   //--- method of identifying
   virtual int       Type(void) const { return(IND_CUSTOM); }

protected:
   //--- methods of tuning
   virtual bool      Initialize(const string symbol,const ENUM_TIMEFRAMES period,const int num_params,const MqlParam &params[]);
   bool              Initialize(const string symbol,const ENUM_TIMEFRAMES period,
                                const int depth,const int deviation_init,const int backstep);
  };
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CiZigZag::CiZigZag(void) : m_depth(-1),
                         m_deviation(-1),
                         m_backstep(-1)
  {
  }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CiZigZag::~CiZigZag(void)
  {
  }
//+------------------------------------------------------------------+
//| Create indicator "Zig Zag"                                       |
//+------------------------------------------------------------------+
bool CiZigZag::Create(const string symbol,const ENUM_TIMEFRAMES period,
                      const int depth,const int deviation_create,const int backstep)
  {
//--- check history
   if(!SetSymbolPeriod(symbol,period))
      return(false);
//--- create
   m_handle=iCustom(symbol,period,"zigzag",depth,deviation_create,backstep);
//--- check result
   if(m_handle==INVALID_HANDLE)
      return(false);
//--- indicator successfully created
   if(!Initialize(symbol,period,depth,deviation_create,backstep))
     {
      //--- initialization failed
      IndicatorRelease(m_handle);
      m_handle=INVALID_HANDLE;
      return(false);
     }
//--- ok
   return(true);
  }
//+------------------------------------------------------------------+
//| Initialize the indicator with universal parameters               |
//+------------------------------------------------------------------+
bool CiZigZag::Initialize(const string symbol,const ENUM_TIMEFRAMES period,const int num_params,const MqlParam &params[])
  {
   return(Initialize(symbol,period,(int)params[0].integer_value,(int)params[1].integer_value,(int)params[2].integer_value));
  }
//+------------------------------------------------------------------+
//| Initialize indicator with the special parameters                 |
//+------------------------------------------------------------------+
bool CiZigZag::Initialize(const string symbol,const ENUM_TIMEFRAMES period,
                        const int depth,const int deviation_init,const int backstep)
  {
   if(CreateBuffers(symbol,period,3))
     {
      //--- string of status of drawing
      m_name  ="ZigZag";
      m_status="("+symbol+","+PeriodDescription()+","+
               IntegerToString(depth)+","+IntegerToString(deviation_init)+","+
               IntegerToString(backstep)+") H="+IntegerToString(m_handle);
      //--- save settings
      m_depth=depth;
      m_deviation=deviation_init;
      m_backstep=backstep;       
      //--- create buffers
      ((CIndicatorBuffer*)At(0)).Name("ZIGZAG");
      ((CIndicatorBuffer*)At(1)).Name("HIGH");
      ((CIndicatorBuffer*)At(2)).Name("LOW");
      //--- ok
      return(true);
     }
//--- error
   return(false);
  }
//+------------------------------------------------------------------+
//| Access to ZigZag buffer of "Zig Zag"                             |
//+------------------------------------------------------------------+
double CiZigZag::ZigZag(const int index) const
  {
   CIndicatorBuffer *buffer=At(0);
//--- check
   if(buffer==NULL)
      return(EMPTY_VALUE);
//---
   return(buffer.At(index));
  }
//+------------------------------------------------------------------+
//| Access to High buffer of "Zig Zag"                               |
//+------------------------------------------------------------------+
double CiZigZag::High(const int index) const
  {
   CIndicatorBuffer *buffer=At(1);
//--- check
   if(buffer==NULL)
      return(EMPTY_VALUE);
//---
   return(buffer.At(index));
  }
//+------------------------------------------------------------------+
//| Access to Low buffer of "Zig Zag"                                |
//+------------------------------------------------------------------+
double CiZigZag::Low(const int index) const
  {
   CIndicatorBuffer *buffer=At(2);
//--- check
   if(buffer==NULL)
      return(EMPTY_VALUE);
//---
   return(buffer.At(index));
  }
//+------------------------------------------------------------------+


3.1. 面向对象封装

面向对象封装是一个良好的编程实践,意味着对象的数据成员只能由为其定义的操作所修改。所有在 MetaQuotes 的 Trend.mqh 中定义的类均实施此理念,所以我们也在做着同样的事情。

一方面是 CiZigZag 的特定受保护属性:

protected:
   int               m_depth;
   int               m_deviation;
   int               m_backstep;

其后是 CiZigZag 的公共接口,用于从 CiZigZag 类型的给定对象的外部访问上文中定义的受保护属性:

public:
   //--- methods of access to protected data
   int               Depth(void)          const { return(m_depth);      }
   int               Deviation(void)      const { return(m_deviation);  }
   int               Backstep(void)       const { return(m_backstep);   }

这是用于隔离对象的一个安全措施。此封装防止不允许访问对象数据的人或物对数据进行的任意修改。


3.2. 访问峰谷指标的数据

正如本文的第一节所述,名为 zigzag.mq5 的源代码文件创建了三个缓冲区:

//--- indicator buffers mapping
   SetIndexBuffer(0,ZigzagBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,HighMapBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(2,LowMapBuffer,INDICATOR_CALCULATIONS);

通过面向对象封装,CiZigZag 的方法 ZigZag(const int index)High(const int index)Low(const int index) 返回之前在初始化方法中创建的指标缓冲区。需要重点强调的是,面向对象包装程序 CIndicatorBuffer 在 MQL5 的类 Include\Indicators\Indicator.mqh 中定义。CIndicatorBuffer 是这三种方法的核心部分。我们已完全处于 MQL5 API 环境中!

下面是访问 CiZigZag 的 High 缓冲区的代码,在此作为一个示例:

//+------------------------------------------------------------------+
//| Access to High buffer of "Zig Zag"                               |
//+------------------------------------------------------------------+
double CiZigZag::High(const int index) const
  {
   CIndicatorBuffer *buffer=At(1);
//--- check
   if(buffer==NULL)
      return(EMPTY_VALUE);
//---
   return(buffer.At(index));
  }


3.3.
多态性、方法重载和虚函数

在上一节中,我们简要讨论了封装,这是面向对象编程最重要的特性之一。好了,Include\Indicators\Indicator.mqh 和文件 Include\Indicators\Custom\Trend.mqh 中包含的类涉及 OOP 范式的其他两个方面 - 多态性和方法重载。

多态性具有通过相同接口访问不同方法的能力。如此一来,取决于其所处的上下文,给定标识符可采取多种形式。多态性需要继承机制,以便它可以被实现。另一方面,方法重载是另一个 OOP 特性,允许创建名称相同但具有不同参数声明的多个方法。

这是一个非常简短的介绍。本文没有足够的篇幅用于讨论这些主题,所以对这些主题的探究将留给读者作为练习。请阅读 MQL5 章节多态性重载。总之,我们可以看到,标准库实现了所有 OOP 特性,因此,我们越了解这些特性,我们越能更好地扩展 API 以满足我们的需求。

除了上面提到的,还有一件事情需要注意。MQL5 通过一种称之为虚函数的机制实现多态性。请再次阅读 MQL5 章节虚函数以了解它是如何工作的。

这就是我们通过下述方式编写 CiZigZag 的初始化方法的代码的原因:

//+------------------------------------------------------------------+
//| Initialize the indicator with universal parameters               |
//+------------------------------------------------------------------+
bool CiZigZag::Initialize(const string symbol,const ENUM_TIMEFRAMES period,const int num_params,const MqlParam &params[])
  {
   return(Initialize(symbol,period,(int)params[0].integer_value,(int)params[1].integer_value,(int)params[2].integer_value));
  }
//+------------------------------------------------------------------+
//| Initialize indicator with the special parameters                 |
//+------------------------------------------------------------------+
bool CiZigZag::Initialize(const string symbol,const ENUM_TIMEFRAMES period,
                        const int depth,const int deviation_init,const int backstep)
  {
   if(CreateBuffers(symbol,period,3))
     {
      //--- string of status of drawing
      m_name  ="ZigZag";
      m_status="("+symbol+","+PeriodDescription()+","+
               IntegerToString(depth)+","+IntegerToString(deviation_init)+","+
               IntegerToString(backstep)+") H="+IntegerToString(m_handle);
      //--- save settings
      m_depth=depth;
      m_deviation=deviation_init;
      m_backstep=backstep;       
      //--- create buffers
      ((CIndicatorBuffer*)At(0)).Name("ZIGZAG");
      ((CIndicatorBuffer*)At(1)).Name("HIGH");
      ((CIndicatorBuffer*)At(2)).Name("LOW");
      //--- ok
      return(true);
     }
//--- error
   return(false);
  }

4. 测试已在标准库中提供的新的面向对象峰谷指标

当然,在您的面向对象开发中使用您开发的扩展前,您应首先确保它们正常工作。建议对您新的自定义组件执行全面的测试。然而,为简便起见,我们现在将对 CiZigZag 的三个主要方法 - ZigZag(const int index)High(const int index)Low(const int index) 执行一个简单的测试。

我们将对 EA 的每次价格变动打印出上述三个方法计算得出的值,然后将虚拟程序化 EA ExpertOriginalZigZag.ex5 生成的结果与虚拟面向对象 EA ExpertOOZigZag.ex5 生成的结果进行比较。无论得到的两个结果是否相同,我们可以得出新扩展正常的结论,我们可以永久地将我们的面向对象峰谷指标集成至 MQL5 API。

图 4. 我们将 ExpertOriginalZigZag.ex5 生成的结果与 ExpertOOZigZag.ex5 生成的结果进行对比

图 4. 我们将 ExpertOriginalZigZag.ex5 生成的结果与 ExpertOOZigZag.ex5 生成的结果进行对比

因此,我们在策略测试程序中运行在本文开头提出的两个 EA ExpertOriginalZigZag.ex5ExpertOOZigZag.ex5,参数组如下所示:

  • 交易品种:EURUSD,H1
  • 日期:自定义周期,从 2013.08.01 至 2013.08.15
  • 执行:常规,一分钟指标柱 OHLC
  • 存款:10000 USD,1:100
  • 优化:无

由于两个自动交易打印的结果相同,我们可以得出 CiZigZag 良好实现的结论,因此从现在开始,我们可以将其用于我们的开发中。

ExpertOriginalZigZag.ex5 生成的日志:

DE      0       18:45:39        ExpertOriginalZigZag (EURUSD,H1)        2013.08.01 08:50:40   zigZagBuffer[0]: 1.32657
ML      0       18:45:39        ExpertOriginalZigZag (EURUSD,H1)        2013.08.01 08:50:40   zigZagLow[0]: 1.32657
FL      0       18:45:39        ExpertOriginalZigZag (EURUSD,H1)        2013.08.01 08:50:59   zigZagBuffer[0]: 1.32657
GE      0       18:45:39        ExpertOriginalZigZag (EURUSD,H1)        2013.08.01 08:50:59   zigZagLow[0]: 1.32657
KS      0       18:45:39        ExpertOriginalZigZag (EURUSD,H1)        2013.08.01 08:51:00   zigZagBuffer[0]: 1.32657
FR      0       18:45:39        ExpertOriginalZigZag (EURUSD,H1)        2013.08.01 08:51:00   zigZagLow[0]: 1.32657
GK      0       18:45:39        ExpertOriginalZigZag (EURUSD,H1)        2013.08.01 08:51:20   zigZagBuffer[0]: 1.32653
RJ      0       18:45:39        ExpertOriginalZigZag (EURUSD,H1)        2013.08.01 08:51:20   zigZagLow[0]: 1.32653
OR      0       18:45:39        ExpertOriginalZigZag (EURUSD,H1)        2013.08.01 08:51:40   zigZagBuffer[0]: 1.32653
FS      0       18:45:39        ExpertOriginalZigZag (EURUSD,H1)        2013.08.01 08:51:40   zigZagLow[0]: 1.32653
QJ      0       18:45:39        ExpertOriginalZigZag (EURUSD,H1)        2013.08.01 08:51:59   zigZagBuffer[0]: 1.32653
PH      0       18:45:39        ExpertOriginalZigZag (EURUSD,H1)        2013.08.01 08:51:59   zigZagLow[0]: 1.32653
JQ      0       18:45:39        ExpertOriginalZigZag (EURUSD,H1)        2013.08.01 08:52:00   zigZagBuffer[0]: 1.32653
KP      0       18:45:39        ExpertOriginalZigZag (EURUSD,H1)        2013.08.01 08:52:00   zigZagLow[0]: 1.32653
RH      0       18:45:39        ExpertOriginalZigZag (EURUSD,H1)        2013.08.01 08:52:20   zigZagBuffer[0]: 1.32653
GI      0       18:45:39        ExpertOriginalZigZag (EURUSD,H1)        2013.08.01 08:52:20   zigZagLow[0]: 1.32653
GP      0       18:45:39        ExpertOriginalZigZag (EURUSD,H1)        2013.08.01 08:52:40   zigZagBuffer[0]: 1.32614
// More data here!..

ExpertOOZigZag.ex5 生成的日志:

RP      0       18:48:02        ExpertOOZigZag (EURUSD,H1)      2013.08.01 08:50:40   OO ZigZag buffer(0): 1.32657
HQ      0       18:48:02        ExpertOOZigZag (EURUSD,H1)      2013.08.01 08:50:40   OO ZigZag low(0): 1.32657
DI      0       18:48:02        ExpertOOZigZag (EURUSD,H1)      2013.08.01 08:50:59   OO ZigZag buffer(0): 1.32657
RH      0       18:48:02        ExpertOOZigZag (EURUSD,H1)      2013.08.01 08:50:59   OO ZigZag low(0): 1.32657
QR      0       18:48:02        ExpertOOZigZag (EURUSD,H1)      2013.08.01 08:51:00   OO ZigZag buffer(0): 1.32657
GS      0       18:48:02        ExpertOOZigZag (EURUSD,H1)      2013.08.01 08:51:00   OO ZigZag low(0): 1.32657
IK      0       18:48:02        ExpertOOZigZag (EURUSD,H1)      2013.08.01 08:51:20   OO ZigZag buffer(0): 1.32653
GJ      0       18:48:02        ExpertOOZigZag (EURUSD,H1)      2013.08.01 08:51:20   OO ZigZag low(0): 1.32653
EL      0       18:48:02        ExpertOOZigZag (EURUSD,H1)      2013.08.01 08:51:40   OO ZigZag buffer(0): 1.32653
OD      0       18:48:02        ExpertOOZigZag (EURUSD,H1)      2013.08.01 08:51:40   OO ZigZag low(0): 1.32653
OE      0       18:48:02        ExpertOOZigZag (EURUSD,H1)      2013.08.01 08:51:59   OO ZigZag buffer(0): 1.32653
IO      0       18:48:02        ExpertOOZigZag (EURUSD,H1)      2013.08.01 08:51:59   OO ZigZag low(0): 1.32653
DN      0       18:48:02        ExpertOOZigZag (EURUSD,H1)      2013.08.01 08:52:00   OO ZigZag buffer(0): 1.32653
RF      0       18:48:02        ExpertOOZigZag (EURUSD,H1)      2013.08.01 08:52:00   OO ZigZag low(0): 1.32653
PP      0       18:48:02        ExpertOOZigZag (EURUSD,H1)      2013.08.01 08:52:20   OO ZigZag buffer(0): 1.32653
RQ      0       18:48:02        ExpertOOZigZag (EURUSD,H1)      2013.08.01 08:52:20   OO ZigZag low(0): 1.32653
MI      0       18:48:02        ExpertOOZigZag (EURUSD,H1)      2013.08.01 08:52:40   OO ZigZag buffer(0): 1.32614
// More data here!..

总结

作为一名开发人员,MQL5 标准库让您的工作变得更加容易。然而,它无法实现世界上所有开发人员的全部需求,所以总有一些地方需要您创建您的自定义程序。随着您的 EA 和指标日趋复杂,掌握框架开发所涉及理念的必要性则愈加凸显。扩展 MQL5 标准库是您的应用程序获得成功的质量保证。

通过首先从代码库中下载峰谷指标,我们充分利用了代码重用。一旦在我们的 MetaTrader 5 终端中可用,我们采用自顶向下的方法来考虑我们的新的面向对象峰谷指标。我们对整个系统有了整体印象,然后再继续分析。在开发的最初阶段,我们使用程序风格的峰谷指标来比较虚拟 EA 及其面向对象版本。

我们将峰谷指标包装在一个根据 MetaQuotes 的设计理念设计的面向对象类中,这与构建标准库是一样的。最后,我们运行了一些简单的测试,得出结论:我们已集成至 MQL5 API 的新的 CiZigZag 包装程序良好实现。


由MetaQuotes Software Corp.从英文翻译成
原始文章: https://www.mql5.com/en/articles/741

附加的文件 |
expertoozigzag.mq5 (2.03 KB)
trend.mqh (6.34 KB)
zigzag.mq5 (9.34 KB)
技术指标和数字滤波器 技术指标和数字滤波器

在本文中,技术指标被视为数字滤波器。本文对数字滤波器的操作原理和基本特性进行了说明。同时,本文还涉及在 MetaTrader 5 终端中接收滤波器内核以及与建立一个频谱分析程序一文中提出的现成频谱分析程序集成等实用方法。本文将典型数字滤波器的脉冲和频谱特性用作示例。

将您的线性交易系统提升为幂交易系统 将您的线性交易系统提升为幂交易系统

今天的文章为中级 MQL5 编程人员讲解如何通过轻松实施所谓的幂的技术从他们的线性交易系统(固定手数)中获利更多。这是因为结果资产净值曲线呈抛物线形式,以几何级数或指数增长。具体而言,我们将实施一个由 Ralph Vince 开发的固定分数仓位大小的实际 MQL5 变体。

MQL5 细则手册:MetaTrader 5 交易事件的声音通知 MQL5 细则手册:MetaTrader 5 交易事件的声音通知

在本文中,我们将考虑在“EA 交易”的文件中包含声音文件、从而为交易事件添加声音通知的事宜。将包含文件的事实意味着声音文件将位于“EA 交易”的内部。因此,在向其他用户提供编译后的“EA 交易”版本 (*.ex5) 时,您无需再提供声音文件并说明它们应予以保存的位置。

MQL5 细则手册:在单一窗口中监控多个时间表 MQL5 细则手册:在单一窗口中监控多个时间表

在 MetaTrader 5 中,有 21 个时间表可供分析。您可以利用能置于现有图表上的特殊图表对象,并在相应位置设置交易品种、时间表及其他属性。文章将对此类图表图形对象进行详细介绍:我们将使用控件(按钮)创建指标,以便同时在子窗口中建立多个图表对象。此外,图表对象将准确置于子窗口中,并随主图表或终端窗口的大小调整自动进行校正。