
Erweiterung der MQL5-Standardbibliothek und Wiederverwendung von Code
Einleitung
Die MQL5-Standardbibliothek ist ein objektorientiertes Framework aus gebrauchsfertigen Klassen, die Ihnen das Leben als Entwickler erleichtern. Dennoch geht sie nicht auf die Bedürfnisse aller Entwickler auf der Welt ein. Wenn Sie also das Gefühl haben, dass Sie mehr benutzerdefinierte Funktionen brauchen, können Sie einen Schritt weitergehen und die Bibliothek erweitern. Dieser Beitrag begleitet Sie durch die Integration des technischen Indikators ZigZag von MetaQuotes in die Standardbibliothek. Wir lassen uns durch die Designphilosophie von MetaQuotes inspirieren, um unser Ziel zu erreichen.
Kurz gesagt, ist die MQL5-API dafür vorgesehen, Sie in den Genuss von wiederverwendbaren Codes, Zuverlässigkeit, Flexibilität und einfacher Wartung kommen zu lassen. Soweit die Theorie. Doch darüber hinaus müssen Sie dazu in der Lage sein, Codes auf die Art der Standardbibliothek zu schreiben, sodass der Erfolg Ihrer Anwendungen garantiert werden kann, wenn Sie Ihre MQL5-Kenntnisse erweitern und ausgeklügeltere Anwendungen entwickeln möchten, beispielsweise mehrwährungsfähige Expert Advisors.
Mit der steigenden Komplexität Ihrer EAs und Indikatoren wird es immer wichtiger, die Konzepte hinter der Entwicklung eines Frameworks vollständig zu begreifen. Ein konkretes Beispiel ist mein persönliches Bestreben, einen komplexen, mehrwährungsfähigen EA zu entwickeln, das mich dazu zwingt, die Grundlagen meines Projekts von Grund auf durchzudenken.
Abbildung 1. Regelmäßige Polyeder sind perfekte Objekte und veranschaulichen die Idee hinter der Ausarbeitung von Anwendungen auf Basis eines soliden Konzepts
1. Download von ZigZag
Wir fangen mit dem Download des ZigZag-Indikators von MetaQuotes an, der über das MetaTrader 5 Terminal in der Code Base zur Verfügung steht. Dabei werden die Dateien Indicators\zigzag.mq5 und Indicators\zigzag.ex5 erstellt.Abbildung 2. Download von ZigZag über das MetaTrader 5 Terminal
Ich führe an dieser Stelle jene Zeilen von Indicators\zigzag.mq5 auf, die die Eingabeparameter des Indikators, globale Variablen und den Handler OnInit() beinhalten. Ich beschränke mich deshalb auf diesen Teil, weil die vollständige Datei aus 298 Zeilen Code besteht. Dies dient nur der Bequemlichkeit und dem Verständnis des großen Ganzen, das wir im weiteren Verlauf besprechen werden.
//+------------------------------------------------------------------+ //| 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. Kurzübersicht – von oben nach unten
Wenden wir nun einen Top-down-Ansatz an, um über unseren neuen objektorientierten Indikator ZigZag nachzudenken, den wir in die MQL5-Standardbibliothek integrieren wollen. Das bedeutet, dass wir erst das Gesamtsystem betrachten und anschließend seine Bestandteile analysieren müssen. Schreiben wir also ein paar Dummy-EAs, um das Gesamtbild zu erkennen. Lassen Sie uns einen verfahrensorientierten Expert Advisor zusammen mit einer objektorientierten Version davon schreiben.
2,1. Standardindikator ZigZag
Der durchschnittliche MQL5-Entwickler nutzt den ZigZag-Indikator vermutlich etwa so in seinen EAs:
//+----------------------------------------------------------------------+ //| ExpertOriginalZigZag.mq5 | //| Copyright © 2013, Laplacianlab - Jordi Bassagañas | //+----------------------------------------------------------------------+ //--- EA properties #property copyright "Copyright © 2013, Laplacianlab - Jordi Bassagañas" #property link "https://www.mql5.com/de/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. ZigZag in der Standardbibliothek
Andererseits arbeiten erfahrene MQL5-Entwickler mit dem ZigZag-Indikator wahrscheinlich genauso wie sie es bereits mit den Indikatoren aus der Standardbibliothek tun:
//+----------------------------------------------------------------------+ //| 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/de/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. Fazit
Die zweite Lösung ist besser, weil sie objektorientiert ist. Nach der Ausarbeitung der objektorientierten Klassen lässt sich beobachten, dass es viel einfacher ist, mit der objektorientierten Funktionalität von ZigZag zu interagieren, als mit seinem verfahrensorientierten Gegenstück zu arbeiten. Rufen wir uns allerdings kurz die Vorteile der Arbeit mit einer objektorientierten Bibliothek ins Gedächtnis:
- OOP ermöglicht eine einfache Modellierung von Aufgaben.
- OOP macht es einfach, Codes wiederzuverwenden, was sich wiederum positiv auf Kosten, Zuverlässigkeit, Flexibilität und Wartungsfreundlichkeit auswirkt.
Dieses Paradigma ermöglicht die Erschaffung von ADTs (abstrakten Datentypen). Ein ADT ist eine Abstraktion des herkömmlichen Konzepts von Datentypen, die in allen Programmiersprachen vorkommen.
Abbildung 3. Regulärer Ikosaeder. Der Aufbau unserer Anwendungen auf Basis solider Konzepte ist eine Qualitätsgarantie, die sicherstellt, dass unsere Konzepte die Zeit überdauern
3. Integration des neuen objektorientierten ZigZag in die MQL5-Standardbibliothek
Wie ich in der Einleitung dieses Beitrags erwähnt habe, lassen wir uns beim Aufbau unseres neuen Satzes von Klassen zum Verpacken des ZigZag vom objektorientierten Stil von MetaQuotes inspirieren. Das ist einfach – wir müssen uns nur die Dateien in Include\Indicators ansehen und einige Ideen hinter der MQL5-Standardbibliothek studieren und verstehen. Wenn Sie sich ansehen, was sich innerhalb von Trend.mqh von MetaQuotes befindet, werden Sie schnell feststellen, dass die Datei voller Klassen ist, die eine Reihe von technischen Indikatoren darstellen: ADX, Bollinger Bands, SAR, gleitende Mittelwerte usw. All diese Klassen sind Erben von CIndicator. Wenden wir also dieses Schema an. Übrigens, eine Erweiterung des neuen objektorientierten Indikators aus der MQL5-Klasse CiCustom wäre eine weitere Alternative für diese Übung.
Fangen wir an, indem wir den neuen Ordner Include\Indicators\Custom und gleich danach die neue Datei Include\Indicators\Custom\Trend.mqh erstellen, sodass wir dort unsere eigenen technischen Indikatoren schreiben können, genauso, wie MetaQuotes es in seiner Datei Include\Indicators\Trend.mqh tut. Hier ist unsere erweiterte Datei Include\Indicators\Custom\Trend.mqh bereits implementiert. Nachfolgend werde ich auf einige technische Aspekte für ihre Ausarbeitung eingehen.
//+------------------------------------------------------------------+ //| Include\Indicators\Custom\Trend.mqh | //| Copyright 2013, Laplacianlab - Jordi Bassagañas | //| https://www.mql5.com/de/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. Objektorientierte Kapselung
Die objektorientierte Kapselung ist eine bewährte Praxis in der Programmierung, die bedeutet, dass Datenbestandteile von Objekten nur durch Operationen modifiziert werden können, die speziell für sie definiert sind. Alle in Trend.mqh von MetaQuotes definierten Klassen setzen diese Idee um, also tun wir das Gleiche.
Auf der anderen Seite gibt es die speziellen geschützten Eigenschaften von CiZigZag:
protected: int m_depth; int m_deviation; int m_backstep;
Somit verfügt CiZigZag über ein offenes Interface für den Zugriff auf die oben definierten geschützten Eigenschaften von außerhalb eines bestimmten Objektes des Typen 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); }
Dabei handelt es sich um eine Sicherheitsmaßnahme zum Isolieren von Objekten. Diese Kapselung verhindert willkürliche Veränderungen durch Personen oder Faktoren, denen der Zugriff auf die Daten des Objekts nicht gestattet ist.
3,2. Zugriff auf die Daten von ZigZag
Wie es im ersten Abschnitt dieses Beitrags gezeigt wurde, erstellt der Quellcode mit dem Namen zigzag.mq5 drei Puffer:
//--- indicator buffers mapping SetIndexBuffer(0,ZigzagBuffer,INDICATOR_DATA); SetIndexBuffer(1,HighMapBuffer,INDICATOR_CALCULATIONS); SetIndexBuffer(2,LowMapBuffer,INDICATOR_CALCULATIONS);
Durch die objektorientierte Kapselung geben die Methoden ZigZag(const int index), High(const int index) und Low(const int index) von CiZigZag die Indikatorpuffer aus, die vorher in der Initialisierungsmethode erstellt wurden. Es muss festgehalten werden, dass der objektorientierte Wrapper CIndicatorBuffer in der MQL5-Klasse Include\Indicators\Indicator.mqh definiert ist. CIndicatorBuffer ist das Herzstück dieser drei Methoden. Und schon sind wir in die MQL5-API eingetaucht!
Als Beispiel sehen Sie hier den Code für den Zugriff auf den High-Puffer von CiZigZag:
//+------------------------------------------------------------------+ //| 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. Polymorphismus, Überladen von Methoden und virtuelle Funktionen
Im vorhergehenden Abschnitt sind wir kurz auf das Thema Kapselung eingegangen, die eine der wichtigsten Funktionen in der objektorientierten Programmierung darstellt. Die Klassen in Include\Indicators\Indicator.mqh und in Include\Indicators\Custom\Trend.mqh decken zwei weitere Aspekte des OOP-Paradigmas ab, Polymorphismus und das Überladen von Methoden.
Der Polymorphismus bietet eine Möglichkeit, über ein und dasselbe Interface auf eine Bandbreite verschiedener Methoden zuzugreifen. Auf diese Art kann ein bestimmter Identifikator verschiedene Formen annehmen, je nach Kontext, in dem er sich befindet. Für die Umsetzung des Polymorphismus muss ein Vererbungsmechanismus vorhanden sein. Ein weiteres Merkmal der OOP ist das Überladen von Methoden, das die Erstellung mehrerer Methoden mit dem gleichen Namen, aber mit unterschiedlichen Deklarierungen von Parametern ermöglicht.
Dies ist nur eine kurze Einführung. Dieser Beitrag bietet nicht genügend Raum, um diese Themen im Detail zu besprechen, also liegt es an Ihnen, sich mit ihnen zu befassen. Bitte lesen Sie die MQL5-Abschnitte über Polymorphismus und Überladen. In jedem Fall sehen wir, dass die Standardbibliothek alle OOP-Möglichkeiten umsetzt. Somit können wir die API besser nach unseren Bedürfnissen erweitern, je besser wir sie kennen.
Eines muss noch festgehalten werden. MQL5 setzt den Polymorphismus mithilfe virtueller Funktionen um. Bitte lesen Sie den MQL5-Abschnitt über virtuelle Funktionen, um zu verstehen, wie das funktioniert.
Deshalb setzen wir die Initialisierungsmethode von CiZigZag auf folgende Weise um:
//+------------------------------------------------------------------+ //| 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. Testen des neuen, in der Standardbibliothek bereits verfügbaren objektorientierten ZigZag
Bevor Sie die von Ihnen entwickelten Erweiterungen verwenden, müssen Sie natürlich zuerst gewährleisten, dass sie funktionieren, wie geplant. Es wird empfohlen, einen vollständigen Satz von Tests auf Ihren neuen benutzerdefinierten Komponenten durchzuführen. Der Einfachheit halber führen wir jetzt allerdings einen einfachen Test auf den drei Hauptmethoden von CiZigZag aus, also ZigZag(const int index), High(const int index) und Low(const int index).
Wir drucken die durch diese drei Methoden für den Tick jedes EAs berechneten Werte und vergleichen die Ergebnisse von ExpertOriginalZigZag.ex5, dem verfahrensorientierten Dummy-EA, mit dem Ergebnis von ExpertOOZigZag.ex5, dem objektorientierten Dummy-EA. Immer, wenn beide Ergebnisse gleich sind, können wir schlussfolgern, dass die neue Erweiterung in Ordnung ist und wir unseren in die MQL5-API integrierten objektorientierten ZigZag nutzen können.
Abbildung 4. Wir vergleichen das Ergebnis von ExpertOriginalZigZag.ex5 mit dem Ergebnis von ExpertOOZigZag.ex5
Also führen wir ExpertOriginalZigZag.ex5 und ExpertOOZigZag.ex5, die beiden am Anfang dieses Beitrags vorgestellten EAs, mit den folgenden Parametern im Strategietester aus:
- Symbol: EURUSD, H1
- Datum: Benutzerdefinierte Periode, von 2013.08.01 bis 2013.08.15
- Ausführung: Normal, 1-minütiger OHLC
- Einlage: 10000 USD, 1:100
- Optimierung: keiner
Da beide Roboter zu den gleichen Ergebnissen führen, schlussfolgern wir, dass unsere CiZigZag gut umgesetzt wurde und wir sie ab jetzt in unseren Programmen nutzen können.
Log von 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!..
Log von 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!..
Fazit
Die MQL5-Standardbibliothek erleichtert Ihnen das Leben als Entwickler. Dennoch kann sie nicht auf die Bedürfnisse aller Entwickler auf der ganzen Welt eingehen, also wird es immer einen Punkt geben, an dem Sie benutzerdefinierte Elemente erschaffen müssen. Mit der steigenden Komplexität Ihrer EAs und Indikatoren wird es immer wichtiger, die Konzepte hinter der Entwicklung eines Frameworks vollständig zu begreifen. Die Erweiterung der MQL5-Standardbibliothek ist eine Qualitätsgarantie, die sicherstellt, dass Ihre Anwendungen erfolgreich sind.
Indem wir den ZigZag-Indikator zuerst aus der Code Base heruntergeladen haben, haben wir von der Wiederverwendung von Code profitiert. Nach dem Laden im MetaTrader 5 Terminal wandten wir einen Top-down-Ansatz an, um über unseren neuen objektorientierten ZigZag-Indikator nachzudenken. Wir haben uns einen Überblick über das Gesamtsystem verschafft und dann mit der Analyse weitergemacht. In der ersten Entwicklungsphase haben wir einen Dummy-EA unter Benutzung des verfahrensorientierten ZigZag-Indikators mit dessen objektorientiertem Gegenstück verglichen.
Wir haben den ZigZag-Indikator in einer objektorientierten Klasse verpackt, die in Übereinstimmung mit der Designphilosophie von MetaQuotes gestaltet wurde, die auch für den Aufbau der Standardbibliothek angewendet wurde. Und zu guter Letzt haben wir einige einfache Tests durchgeführt und geschlussfolgert, dass unser neuer, bereits in der MQL5-API integrierter Wrapper CiZigZag gut umgesetzt wurde.
Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/741





- Freie Handelsapplikationen
- Über 8.000 Signale zum Kopieren
- Wirtschaftsnachrichten für die Lage an den Finanzmärkte
Sie stimmen der Website-Richtlinie und den Nutzungsbedingungen zu.