扩展 MQL5 标准库和重用代码
简介
MQL5 标准库是一个面向对象框架,由一组准备就绪的、让您作为一名开发人员的工作变得更容易的类组成。然而,它无法实现世界上所有开发人员的全部需求,所以,如果您觉得您需要更多的自定义程序,您可以对标准库进行进一步的扩展。本文指导您完成将 MetaQuotes 的峰谷技术指标集成至标准库。我们将从 MetaQuotes 的设计理念获得启发以实现我们的目标。
简而言之,MQL5 API 旨在让您从代码重用、可靠性、灵活性和易于维护中受益。这是从理论上而言,但除了这一切,如果您计划在 MQL5 中更进一步,开发出更复杂的工具,例如多货币“EA 交易”,首先您应该能够以标准库的方式来编写代码,以便您的应用程序保证成功。
随着您的 EA 和指标日趋复杂,掌握框架开发所涉及理念的必要性则愈加凸显。作为一个现实例子,开发一个复杂的多货币 EA 是我的个人需求,这决定了从头开始强化我的项目根基的需求。
图 1. 正多面体是完美的对象。它们很好地描绘了基于立体理念构建应用程序的方法
1. 峰谷指标下载
我们从下载 MetaQuotes 的峰谷指标开始,该指标在我们的 MetaTrader 5 终端的代码库中提供。这将创建 Indicators\zigzag.mq5 和 Indicators\zigzag.ex5 文件。图 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. 将我们的新的面向对象峰谷指标集成至 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 ¶ms[]); 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 ¶ms[]) { 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 ¶ms[]) { 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 生成的结果进行对比
因此,我们在策略测试程序中运行在本文开头提出的两个 EA ExpertOriginalZigZag.ex5 和 ExpertOOZigZag.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 Ltd译自英文
原文地址: https://www.mql5.com/en/articles/741