Programmierung von EA-Modi mit Hilfe des Objekt-orientierten Ansatzes
Einleitung
In diesem Beitrag erörtern wir die Programmierungs-Modi, in denen ein MQL5 EA arbeiten kann. Das Ziel dieses Beitrags ist, das Konzept zu beschreiben, dass "jeder Modus auf seine eigene Weise implementiert werden kann". Der Verfasser ist der Meinung, dass mit diesem Ansatz die Ausführung von Aufgaben in verschiedenen Entwicklungsphasen eines EAs weitaus effizienter vonstatten geht.
Zuerst betrachten wir uns, aus welchen einzelnen Etappen die Entwicklung eines EAs eigentlich besteht. Danach werden die Modi, in denen ein EA in MetaTrader 5 arbeiten kann, sowie seine Hilfsanwendungen untersucht. Und zum Schluss sehen wir uns die Entwicklung der Klassen-Hierarchie zur Implementierung des o. g. Konzepts an.
1. Entwicklungsphasen
Die Entwicklung eines Handelsroboters (EA) ist ein Prozess mit mehreren Aspekten. Die wichtigsten Blöcke hierbei sind die "Algorithmisierung" des Konzepts und sein Test. Es sei darauf hingewiesen, dass sowohl die Handelslogik des EAs als auch der Code-Algorithmus getestet werden.
Schematisch dargestellt sehen die Phasen dieses Prozesses folgendermaßen aus (Abb. 1).
Abb. 1 Entwicklungsphasen und Implementierung eines EAs
Die fünfte Phase "Algorithmisches Handeln" bildet die Arbeit der Entwickler, Programmierer, Analysten und anderer an diesem Prozess beteiligter Spezialisten ab. Es kommt nicht selten vor, dass all diese Rollen von einer einzigen Person ausgefüllt werden - angenommen, ein Händler-Programmierer.
Dieses Schema kann selbstverständlich aktualisiert und erweitert werden. Meiner Meinung nach bildet es die wichtigsten Etappen in der Entwicklung eines EAs gut ab. Aufgrund des zyklischen Musters dieses Schemas kann der Code des EAs während seiner gesamten Lebensdauer ständig verbessert und modifiziert werden.
Hier sei jedoch angemerkt, dass jede Phase gewisse Tools, Know-How und Fähigkeiten erfordert.
Meiner Meinung nach stößt der Entwickler auf die folgende, einfache Variantenmatrix (Abb. 2).
Abb. 2 Variantenmatrix
Es sollte klar sein, dass es nur der Roboter, der eine gewinnbringenden Handelsstrategie mit einem qualitativ hochwertigen Code implementiert, bis zu fünften Etappe "Algorithmisches Handeln schafft".
2. Die Expert Advisor-Modi in MQL5
Die MQL5 Umgebung gestattet die Arbeit mit einem EA in verschiedenen Modi - nämlich insgesamt sieben. Weiter unten sehen wir uns jeden einzelnen Modus genauer an.
Vom Blickwinkel des Typs der Programmdatei kann man zwei Gruppen unterscheiden:
- Modi, die die Datei mit dem Quellcode und die ausführbare Datei brauchen und
- Modi, die nur die ausführbare Datei brauchen.
Modi zur Fehlersuche und Profilerstellung gehören zur ersten Gruppe.
Ein weiteres Kriterium zur Klassifizierung von Modi ist die Arbeit eines EAs in einem Strom echter oder historischer Notierungen. Alle Test-Modi sind mit historischen Notierungen verknüpft.
Die Programmierung definiert sechs Modi. Auf Grundlage der Ergebnisse kann man schlussfolgern, ob ein EA im Standardmodus (Freigabe) oder nicht arbeitet. Ein fertiges Programm (die Datei mit der *.ex5 Erweiterung), das für eine Arbeit in Finanzmärkten kodiert wurde. soll genau in diesem Modus arbeiten. Gleichzeitig ermöglicht ein fertiges Programm auch die Verwendung anderer Modi im Strategietester.
Erzeugen wir zunächst einmal eine Aufzählung, namens ENUM_MQL_MODE, der betrieblichen Modi des MQL-Programms:
//+------------------------------------------------------------------+ //| MQL Mode | //+------------------------------------------------------------------+ enum ENUM_MQL_MODE { MQL_MODE_RELEASE=0, // Release MQL_MODE_DEBUG=1, // Debugging MQL_MODE_PROFILER=2, // Profiling MQL_MODE_TESTER=3, // Testing MQL_MODE_OPTIMIZATION=4, // Optimization MQL_MODE_VISUAL=5, // Visual testing MQL_MODE_FRAME=6, // Gathering frames };
Diese brauchen wir später dann zur Erkennung des Modus-Typs, in dem der EA arbeitet.
2.1 Funktion zur Identifizierung und Prüfung des Modus
Schreiben Sie eine einfache Funktion, die alle Modi durchgeht und Informationen ins Logbuch druckt.
//+------------------------------------------------------------------+ //| Checking all MQL modes | //+------------------------------------------------------------------+ void CheckMqlModes(void) { //--- if it is debug mode if(MQLInfoInteger(MQL_DEBUG)) Print("Debug mode: yes"); else Print("Debug mode: no"); //--- if it is code profiling mode if(MQLInfoInteger(MQL_PROFILER)) Print("Profile mode: yes"); else Print("Profile mode: no"); //--- if it is test mode if(MQLInfoInteger(MQL_TESTER)) Print("Tester mode: yes"); else Print("Tester mode: no"); //--- if it is optimization mode if(MQLInfoInteger(MQL_OPTIMIZATION)) Print("Optimization mode: yes"); else Print("Optimization mode: no"); //--- if it is visual test mode if(MQLInfoInteger(MQL_VISUAL_MODE)) Print("Visual mode: yes"); else Print("Visual mode: no"); //--- if it is frame gathering optimization result mode if(MQLInfoInteger(MQL_FRAME_MODE)) Print("Frame mode: yes"); else Print("Frame mode: no"); }
Die Arbeit dieser Funktion in jedem Modus wird geprüft und kann im OnInit() Ereignis-Handler aufgerufen werden.
Zum Zweck unseres Tests, erzeugen wir ein Template des EA mit dem Namen Test1_Modes_EA.mq5.
In den Eingabeparametern wird eine Option zur Festlegung des Modus, in dem der EA arbeiten soll, aktiviert. Es ist wichtig, sicherzustellen, dass der richtige Modus benannt wird, ansonsten wird die Information nicht exakt sein. Und das ist passiert.
Unten finden Sie den Freigabe-Modus.
CL 0 17:20:38.932 Test1_Modes_EA (EURUSD.e,H1) Current mode: MQL_MODE_RELEASE QD 0 17:20:38.932 Test1_Modes_EA (EURUSD.e,H1) Debug mode: no KM 0 17:20:38.932 Test1_Modes_EA (EURUSD.e,H1) Profile mode: no EK 0 17:20:38.932 Test1_Modes_EA (EURUSD.e,H1) Tester mode: no CS 0 17:20:38.932 Test1_Modes_EA (EURUSD.e,H1) Optimization mode: no RJ 0 17:20:38.932 Test1_Modes_EA (EURUSD.e,H1) Visual mode: no GL 0 17:20:38.932 Test1_Modes_EA (EURUSD.e,H1) Frame mode: no
Im Freigabe-Modus wurden die Marker aller anderen Modi genullt. Die Funktion hat also festgestellt, dass es sich weder um den Fehlersuch-Modus (Debug-Modus: Nein), noch den Profilerstellungs-Modus (Profil-Modus: Nein), usw. handelte. Mit Hilfe der Negationsmethode kamen wir also zum Schluss, dass wir im Freigabe-Modus arbeiten.
Jetzt sehen wir uns an, wie der Fehlersuch-Modus identifiziert wurde.
HG 0 17:27:47.709 Test1_Modes_EA (EURUSD.e,H1) Current mode: MQL_MODE_DEBUG LD 0 17:27:47.710 Test1_Modes_EA (EURUSD.e,H1) Debug mode: yes RS 0 17:27:47.710 Test1_Modes_EA (EURUSD.e,H1) Profile mode: no HE 0 17:27:47.710 Test1_Modes_EA (EURUSD.e,H1) Tester mode: no NJ 0 17:27:47.710 Test1_Modes_EA (EURUSD.e,H1) Optimization mode: no KD 0 17:27:47.710 Test1_Modes_EA (EURUSD.e,H1) Visual mode: no RR 0 17:27:47.710 Test1_Modes_EA (EURUSD.e,H1) Frame mode: no
Dieser Modus wurde korrekt erkannt.
Jedes Programmier-Handbuch enthält Informationen dazu, dass ein Fehlersuchprogramm (oder Modus) die Suche und das Finden von Fehlern im Code erleichtert und zudem die Besonderheiten des Programms hervorhebt. Mehr Einzelheiten zur Fehlersuche in der MQL5-Umgebung finden Sie den dem Beitrag "Fehlersuche in MQL5 Programmen".
Dieser Modus wird in den Formalisierungs- und Konstruktionsphasen des Algorithmus eines Handelskonzepts am häufigsten eingesetzt.
Beim Programmieren wird die Fehlersuche entweder mittels der IS_DEBUG_MODE Makros oder der MQLInfoInteger() Funktion mit dem MQL_DEBUG Identifikator aktiviert.
Kommen wir jetzt zum Modus 'Profilerstellung'.
GS 0 17:30:53.879 Test1_Modes_EA (EURUSD.e,H1) Current mode: MQL_MODE_PROFILER OR 0 17:30:53.879 Test1_Modes_EA (EURUSD.e,H1) Debug mode: no GE 0 17:30:53.879 Test1_Modes_EA (EURUSD.e,H1) Profile mode: yes QM 0 17:30:53.879 Test1_Modes_EA (EURUSD.e,H1) Tester mode: no CE 0 17:30:53.879 Test1_Modes_EA (EURUSD.e,H1) Optimization mode: no FM 0 17:30:53.879 Test1_Modes_EA (EURUSD.e,H1) Visual mode: no GJ 0 17:30:53.879 Test1_Modes_EA (EURUSD.e,H1) Frame mode: no
Die Funktion hat richtig eingeschätzt, dass der Profiler beteiligt war.
In diesem Modus kann geprüft werden, wie schnell das Programm arbeitet. Der Profiler überträgt die Information zum Zeitaufwand an die Programmblöcke. Dieses Instrument soll die Engpässe eines Algorithmus finden und aufzeigen. Diese Engpässe kann man zwar nicht immer komplett loswerden, doch ist eine diesbezügliche Information sehr hilfreich.
Profilerstellung wird entweder durch die IS_PROFILE_MODE Makros oder die MQLInfoInteger() Funktion mit dem MQL_PROFILER Identifikator aktiviert.
Sehen wir uns nun den Testmodus an. Diese Information taucht in der Registerkarte "Logbuch" des Strategietesters auf.
EG 0 17:35:25.397 Core 1 2014.11.03 00:00:00 Current mode: MQL_MODE_TESTER OS 0 17:35:25.397 Core 1 2014.11.03 00:00:00 Debug mode: no GJ 0 17:35:25.397 Core 1 2014.11.03 00:00:00 Profile mode: no ER 0 17:35:25.397 Core 1 2014.11.03 00:00:00 Tester mode: yes ED 0 17:35:25.397 Core 1 2014.11.03 00:00:00 Optimization mode: no NL 0 17:35:25.397 Core 1 2014.11.03 00:00:00 Visual mode: no EJ 0 17:35:25.397 Core 1 2014.11.03 00:00:00 Frame mode: no
Auch dieser Modus wurde korrekt erkannt.
Er ist der standardmäßig eingestellte Modus des EAs, wenn der Strategietester geöffnet wird.
Für diesen Modus gibt es keine Makros, daher können wir ihn in MQL5 nur mittels der MQLInfoInteger() Funktion mit dem MQL_TESTER Identifikator festlegen.
Als nächstes kommt die Optimierung. Ein Logbuch mit Einträgen wird im Ordner des Agenten gespeichert. In meinem Fall lautet sein Pfad folgendermaßen: %Program Files\MetaTrader5\tester\Agent-127.0.0.1-3000\logs
OH 0 17:48:14.010 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Current mode: MQL_MODE_OPTIMIZATION KJ 0 17:48:14.010 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Debug mode: no NO 0 17:48:14.010 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Profile mode: no FI 0 17:48:14.010 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Tester mode: yes KE 0 17:48:14.010 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Optimization mode: yes LS 0 17:48:14.010 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Visual mode: no QE 0 17:48:14.010 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Frame mode: no
Ist der Optimierungsmodus aktiv, wird standardmäßig der Testmodus aktiviert.
Im Strategietester ist der Optimierungsmodus aktiv, wenn das Feld "Optimierung" in der Registerkarte "Einstellungen" nicht deaktiviert ist.
Um herauszufinden, ob der EA im Optimierungsmodus in MQL5 getestet wird, kann man die MQLInfoInteger() Funktion mit dem MQL_OPTIMIZATION-Identifikator aufrufen.
Als nächstes kommen wir zum Visualisierungsmodus.
JQ 0 17:53:51.485 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Current mode: MQL_MODE_VISUAL JK 0 17:53:51.485 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Debug mode: no KF 0 17:53:51.485 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Profile mode: no CP 0 17:53:51.485 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Tester mode: yes HJ 0 17:53:51.485 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Optimization mode: no LK 0 17:53:51.485 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Visual mode: yes KS 0 17:53:51.485 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Frame mode: no
Hier können wir sehen, dass die Modi 'visuelles Testen und 'Standard-Test' beteiligt sind.
Der EA arbeitet im Strategietester in diesem Modus, wenn das Feld "Visualisierung" in der Registerkarte "Einstellungen" angemarkert ist.
Das Testen eines MQL5-Programms im visuellen Testmodus geschieht, in dem man die MQLInfoInteger() Funktion mit dem MQL_VISUAL_MODE-Identifikator verwendet.
Der letzte Modus hat mit dem Umgang von Rahmen zu tun.
HI 0 17:59:10.177 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Current mode: MQL_MODE_FRAME GR 0 17:59:10.177 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Debug mode: no JR 0 17:59:10.177 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Profile mode: no JG 0 17:59:10.177 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Tester mode: yes GM 0 17:59:10.177 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Optimization mode: yes HR 0 17:59:10.177 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Visual mode: no MI 0 17:59:10.177 Test1_Modes_EA (EURUSD.e,H1) 2014.11.03 00:00:00 Frame mode: no
Interessanterweise erkannte die Funktion nur den Test- und Optimierungsmodus, da der Marker der Rahmen genullt war. Wird der Aufruf der Funktion an den OnTesterInit()-Handler übertragen, dann enthält das "Experts" Logbuch die folgenden Einträge
IO 0 18:04:27.663 Test1_Modes_EA (EURUSD.e,H1) Current mode: MQL_MODE_FRAME GE 0 18:04:27.663 Test1_Modes_EA (EURUSD.e,H1) Debug mode: no ML 0 18:04:27.663 Test1_Modes_EA (EURUSD.e,H1) Profile mode: no CJ 0 18:04:27.663 Test1_Modes_EA (EURUSD.e,H1) Tester mode: no QR 0 18:04:27.663 Test1_Modes_EA (EURUSD.e,H1) Optimization mode: no PL 0 18:04:27.663 Test1_Modes_EA (EURUSD.e,H1) Visual mode: no GS 0 18:04:27.663 Test1_Modes_EA (EURUSD.e,H1) Frame mode: yes
Jetzt wird effektiv nur der erfassende Rahmenmodus entdeckt.
Dieser Modus wird im Strategietester verwendet, wenn das Feld "Optimierung" in der Registerkarte "Einstellungen" nicht deaktiviert ist. Wie die Erfahrung gezeigt hat, wird dieser Modus im Korpus der OnTesterInit(), OnTesterPass() und OnTesterDeinit()-Handler festgelegt.
Die MQLInfoInteger() Funktion mit dem MQL_FRAME_MODE-Identifikator kann die Identifizierung der Tatsache des Testens eines EAs im erfassenden Rahmenmodus erleichtern.
Unten steht der Code der Dienstfunktion MqlMode(), die automatisch den Modus festlegt, in dem EA arbeitet.
//+------------------------------------------------------------------+ //| Identify the current MQL mode | //+------------------------------------------------------------------+ ENUM_MQL_MODE MqlMode(void) { ENUM_MQL_MODE curr_mode=WRONG_VALUE; //--- if it is debug mode if(MQLInfoInteger(MQL_DEBUG)) curr_mode=MQL_MODE_DEBUG; //--- if it is code profiling mode else if(MQLInfoInteger(MQL_PROFILER)) curr_mode=MQL_MODE_PROFILER; //--- if it is visual test mode else if(MQLInfoInteger(MQL_VISUAL_MODE)) curr_mode=MQL_MODE_VISUAL; //--- if it is optimization mode else if(MQLInfoInteger(MQL_OPTIMIZATION)) curr_mode=MQL_MODE_OPTIMIZATION; //--- if it is test mode else if(MQLInfoInteger(MQL_TESTER)) curr_mode=MQL_MODE_TESTER; //--- if it is frame gathering optimization result mode else if(MQLInfoInteger(MQL_FRAME_MODE)) curr_mode=MQL_MODE_FRAME; //--- if it is release mode else curr_mode=MQL_MODE_RELEASE; //--- return curr_mode; }
Da Standardtests im Optimierungs- und visuellen Testmodus identifiziert werden, muss nach dem Optimierungs- und Visualisierungsmodus natürlich auch der Standard-Testmodus angekreuzt werden.
Wenn wir einen Blick auf die Arbeit der Funktion im zweiten Template des Test2_Modes_EA.mq5 EAs werfen, erkennen wir deutlich, dass beim Start des Templates im Logbuch ein neuer Eintrag auftaucht. So wurde z.B. für den Profilerstellungs-Modus der unten stehende Eintrag gemacht:
HG 0 11:23:52.992 Test2_Modes_EA (EURUSD.e,H1) Current mode: MQL_MODE_PROFILER
Jetzt haben wir die Einzelheiten der betrieblichen Modi des MQL5 Experts zur Erzeugung von Klassenmodellen entsprechend eines spezifischen Modus besprochen. Ihn werden nun im nächsten Abschnitt des Beitrags implementieren.
3. Template des EAs, der für die Arbeit in unterschiedlichen Modi konzipiert wurde
Ich schlage vor, wir gehen die Entwicklungsphasen eines EAs nochmal kurz durch.
In der Algorithmisierungs-Phase beschäftigt sich ein Programmierer am häufigsten mit Fehlersuche und Profilerstellung. Zum Testen der historischen Daten probiert er alle Modi des Strategietesters aus. Der Abschlussmodus (Freigabe-Modus) wird dann im Online-Handel verwendet.
Ich bin der Meinung, dass ein EA mehrere Facetten besitzen muss, und zwar in dem Sinn, dass die Anforderung der Entwicklungs- und Testphasen ins einem Code abgebildet werden müssen.
Hier wird dann der hauptsächliche Algorithmus bewahrt, sodass sich der EA, infolge dieses Algorithmus, in unterschiedlichen Modi auch unterschiedlich verhält. Das Set an Objekt-orientierten Programmierungs-Tools eignet sich perfekt zur Umsetzung dieses Gedankens.
Abb. 3 Klassenhierarchie des EA, der für die Arbeit in unterschiedlichen Modi konzipiert wurde
Abb. 3 zeigt die Klassenhierarchie mit der Implementierung verschiedener Modi.
Die Basisklasse CModeBase, die alle gemeinsamen Dinge einschließt, besitzt zwei direkte Nachkommen: die CModeRelease und CModeTester Klassen. Die erste Klasse ist die übergeordnete Klasse der Fehlersuch-Klassen, und die zweite ist die übergeordnete Klasse für alle Klassen, die mit dem Test des EAs auf historischen Daten zusammenhängt.
Entwickeln wir den Gedanken der Kombination des prozeduralen und modularen Ansatzes bei der Entwicklung von Klassenmethoden im Modus-Kontext weiter. Betrachten wir uns diesbezüglich als Beispiel die folgende Handelslogik:
- Auf einem Signal öffnen, falls es keine offene Position gibt;
- Auf dem Signal schließen, falls es eine offene Position gibt;
- Trailing Stop bei offener Position.
Das Handelssignal wird vom Standard-Indikator MACD entdeckt, sobald ein neuer Bar auftaucht.
Ein Signal für Kaufen erscheint, wenn die Hauptlinie ansteigt und das Signal 1 im Negativbereich des MACD-Indikators kreuzt (Abb. 4).
Abb. 4 Signal für Kaufen
Ein Signal für Verkaufen erscheint, wenn die Hauptlinie abfällt und das Signal 1 im Positivbereich des MACD-Indikators kreuzt (Abb. 5).
Abb. 5 Signal für Verkaufen
Die Position wird geschlossen, entweder wenn das gegensätzliche Signal auftaucht oder per Stop Loss, der dann platziert wird, wenn der Modus der Positions-Stützung aktiviert ist.
Die Definition der Basisklasse CModeBase lautet dann folgendermaßen:
//+------------------------------------------------------------------+ //| Class CModeBase | //| Purpose: a base class for MQL-modes | //+------------------------------------------------------------------+ class CModeBase { //--- === Data members === --- private: //--- a macd object & values CiMACD m_macd_obj; double m_macd_main_vals[2]; double m_macd_sig_vals[2]; protected: long m_pos_id; bool m_is_new_bar; uint m_trailing_stop; uint m_trail_step; //--- trade objects CSymbolInfo m_symbol_info; CTrade m_trade; CPositionInfo m_pos_info; CDealInfo m_deal_info; //--- mql mode ENUM_MQL_MODE m_mql_mode; //--- a new bar object CisNewBar m_new_bar; //--- current tick signal flag bool m_is_curr_tick_signal; //--- close order type ENUM_ORDER_TYPE m_close_ord_type; //--- === Methods === --- public: //--- constructor/destructor void CModeBase(); void ~CModeBase(void){}; //--- initialization virtual bool Init(int _fast_ema,int slow_ema,int _sig,ENUM_APPLIED_PRICE _app_price); virtual void Deinit(void){}; //--- Modules virtual void Main(void){}; //--- Procedures virtual void Open(void){}; virtual void Close(void){}; virtual void Trail(void){}; //--- Service static ENUM_MQL_MODE CheckMqlMode(void); ENUM_MQL_MODE GetMqlMode(void); void SetMqlMode(const ENUM_MQL_MODE _mode); void SetTrailing(const uint _trailing,const uint _trail_step); protected: //--- Functions ENUM_ORDER_TYPE CheckOpenSignal(const ENUM_ORDER_TYPE _open_sig); ENUM_ORDER_TYPE CheckCloseSignal(const ENUM_ORDER_TYPE _close_sig); ENUM_ORDER_TYPE CheckTrailSignal(const ENUM_ORDER_TYPE _trail_sig,double &_sl_pr); //--- double GetMacdVal(const int _idx,const bool _is_main=true); private: //--- Macros bool RefreshIndicatorData(void); //--- Normalization double NormalPrice(double d); double NormalDbl(double d,int n=-1); double NormalSL(const ENUM_ORDER_TYPE _ord_type,double op,double pr, uint SL,double stop); double NormalTP(const ENUM_ORDER_TYPE _ord_type,double op,double pr, uint _TP,double stop); double NormalLot(const double _lot); };
Eine Basisklasse kann alles mögliche beinhalten, solange es in den "ererbten" Klassen verwendet wird.
Die MACD-Daten sind für Nachkommen nicht verfügbar, da sie durch private Mitglieder dargestellt werden.
Hier sei darauf hingewiesen, dass es unter diesen Methoden auch virtuelle gibt: Main(), Open(), Close(), Trail(). Ihre Implementierung hängt in großem Maße vom Modus ab, in dem der EA aktuell arbeitet. Diese Methoden bleiben für die Basisklasse leer.
Darüber hinaus umfasst die Basisklasse Methoden, die dieselbe Handelslogik für alle MQL-Modi haben können. Zu ihnen gehören alle Signal-Modi:
- CModeBase::CheckOpenSignal(),
- CModeBase::CheckCloseSignal(),
- CModeBase::CheckTrailSignal().
Man sollte nicht vergessen, dass es in diesem Beitrag nicht um das Schreiben eines Codes für alle MQL-Modusarten geht. Als Beispiel seien der Standard- und der visuelle Testmodus angeführt.
3.1 Testmodus
Nachdem der Algorithmus kodiert und erstellt worden ist, probiere ich die Strategie meistens auf historischen Daten im Strategietester aus, um zu sehen, ob alles so funktioniert, wie gedacht.
Am häufigsten muss man hierbei überprüfen wie exakt das System Handelssignale implementiert. Auf jeden Fall ist das grundlegende Ziel in dieser Phase, dass der EA gestartet wird und zu handeln beginnt.
Die CModeTester Klasse für reguläre Tests kann folgendermaßen Implementiert werden:
//+------------------------------------------------------------------+ //| Class CModeTester | //| Purpose: a class for the tester mode | //| Derives from class CModeBase. | //+------------------------------------------------------------------+ class CModeTester : public CModeBase { //--- === Methods === --- public: //--- constructor/destructor void CModeTester(void){}; void ~CModeTester(void){}; //--- Modules virtual void Main(void); //--- Procedures virtual void Open(void); virtual void Close(void); virtual void Trail(void); };
Das Hauptmodul wird so implementiert:
//+------------------------------------------------------------------+ //| Main module | //+------------------------------------------------------------------+ void CModeTester::Main(void) { //--- 1) closure this.Close(); //--- 2) opening this.Open(); //--- 3) trailing stop this.Trail(); }
Erstellen Sie für den Modus 'reguläres Testen' eine Möglichkeit, Informationen über Handelssignale in das Logbuch drucken zu können.
Fügen Sie auch Strings mit Indikatorwerten hinzu, die als die Quelle des Handelssignals betrachtet werden.
Nachfolgend finden Sie einen Auszug aus dem Logbuch über ein Signal zum Öffnen einer Position, gefolgt von einem Signal zum Schließen.
HE 0 13:34:04.118 Core 1 2014.11.14 22:15:00 ---=== Signal to open: SELL===--- FI 0 13:34:04.118 Core 1 2014.11.14 22:15:00 A bar before the last one, main: 0.002117; signal: 0.002109 DL 0 13:34:04.118 Core 1 2014.11.14 22:15:00 The last bar, main: 0.002001; signal: 0.002118 LO 0 13:34:04.118 Core 1 2014.11.14 22:15:00 market sell 0.03 EURUSD.e (1.25242 / 1.25251 / 1.25242) KH 0 13:34:04.118 Core 1 2014.11.14 22:15:00 deal #660 sell 0.03 EURUSD.e at 1.25242 done (based on order #660) GE 0 13:34:04.118 Core 1 2014.11.14 22:15:00 deal performed [#660 sell 0.03 EURUSD.e at 1.25242] OD 0 13:34:04.118 Core 1 2014.11.14 22:15:00 order performed sell 0.03 at 1.25242 [#660 sell 0.03 EURUSD.e at 1.25242] IK 0 13:34:04.118 Core 1 2014.11.14 22:15:00 CTrade::OrderSend: market sell 0.03 EURUSD.e [done at 1.25242] IL 0 13:34:04.118 Core 1 2014.11.17 13:30:20 CJ 0 13:34:04.118 Core 1 2014.11.17 13:30:20 ---=== Signal to close: SELL===--- GN 0 13:34:04.118 Core 1 2014.11.17 13:30:20 A bar before the last one, main: -0.001218; signal: -0.001148 QL 0 13:34:04.118 Core 1 2014.11.17 13:30:20 The last bar, main: -0.001123; signal: -0.001189 EP 0 13:34:04.118 Core 1 2014.11.17 13:30:20 market buy 0.03 EURUSD.e (1.25039 / 1.25047 / 1.25039) FG 0 13:34:04.118 Core 1 2014.11.17 13:30:20 deal #661 buy 0.03 EURUSD.e at 1.25047 done (based on order #661) OJ 0 13:34:04.118 Core 1 2014.11.17 13:30:20 deal performed [#661 buy 0.03 EURUSD.e at 1.25047] PD 0 13:34:04.118 Core 1 2014.11.17 13:30:20 order performed buy 0.03 at 1.25047 [#661 buy 0.03 EURUSD.e at 1.25047] HE 0 13:34:04.118 Core 1 2014.11.17 13:30:20 CTrade::OrderSend: market buy 0.03 EURUSD.e [done at 1.25047]
Beachten Sie bitte, dass es im Strategietester das bekannte Logbuch "Experts" nicht gibt. Alle Informationen findet man in der Registerkarte "Logbuch", die alle Einträge über Aktivitäten enthält, die während des Tests und der Optimierung des Strategietesters ausgeführt wurden.
Und deshalb muss man nach den benötigten Strings suchen. Muss die Einstiegsinformation getrennt vermerkt werden, kann sie in eine Datei geschrieben werden.
Die Strategie für Standard-Tests ist im Code des TestMode_tester.mq5 EA implementiert.
3.2 Visueller Testmodus
Manchmal muss man sich eines Live-Charts bedienen, um herauszufinden, wie ein EA eine aktuelle Situation verarbeitet.
Einfache Visualisierung erlaubt hier nicht nur, zu erkennen, wie das Handelssystem auf Kursschwankungen reagiert, sondern gestattet auch einen Vergleich am Ende des Tests von ähnlichen Kursmodellen.
Die Definition der CModeVisual Klasse für visuelle Tests kann z.B. so aussehen:
//+------------------------------------------------------------------+ //| Class CModeVisual | //| Purpose: a class for the tester mode | //| Derived from class CModeBase. | //+------------------------------------------------------------------+ class CModeVisual : public CModeTester { //--- === Data members === --- private: CArrayObj m_objects_arr; double m_subwindow_max; double m_subwindow_min; //--- === Methods === --- public: //--- constructor/destructor void CModeVisual(void); void ~CModeVisual(void); //--- Procedures virtual void Open(void); virtual void Close(void); private: bool CreateSignalLine(const bool _is_open_sig,const bool _is_new_bar=true); bool CreateRectangle(const ENUM_ORDER_TYPE _signal); void RefreshRectangles(void); };
Die Klasse enthält verborgene Mitglieder. Ein Mitglied der m_objects_arr Klasse implementiert ein dynamisches Array des Typs CArrayObj. Hierhin gehören z.B. graphische Objekte wie Linien und Rechtecke. Zwei andere Klassenmitglieder (m_subwindow_max, m_subwindow_min) kontrollieren die Maximal- und Minimalgröße des Unterfenster des Indikators.
Private Methoden sind für die Arbeit mit graphischen Objekten zuständig.
Diese Klasse enthält nicht die Main() und die Trail() Methoden. Es werden ihre übergeordneten analogen Methoden CModeTester::Main() bzw. CModeTester::Trail() aufgerufen.
Im virtuellen Testmodus können graphische Objekte erzeugt werden. Dies ist in keinem anderen Modus des Strategietesters möglich.
So kann z.B. jedes Mal, wenn ein Signal zum Einstieg auftaucht, dies auf dem Chart als rote senkrechte Linie gezeichnet werden und analog, als blaue senkrechte Linie, sobald ein Signal zum Ausstieg auftaucht. Und der Platz zwischen dem Einstieg- und Ausstiegspunkt kann mit einem Rechteck entsprechender Färbung im Unterfester des Indikators gefüllt werden.
So ist z.B. bei einer Long Position das Rechteck hellblau - und bei einer Short Position rosa (Abb. 6).
Abb. 6 Graphische Objekte im visuellen Testmodus
Die Höhe des Rechtecks hängt von den Maximal- und Minimalwerten des Unterfensters des Charts zum Zeitpunkt der Erzeugung des Rechtecks ab. Damit alle Rechtecke die gleiche Größe haben, sollte der Code um einen Block zur Änderung der Rechteck-Koordinaten ergänzt werden, für den Fall nämlich, dass sich die Koordinaten des Chart-Unterfensters ändern.
Im Unterfenster des MACD-Indikators erhalten wir also folgende Bereiche: ohne Farbe (keine Position), rosa (Short Position), hellblau (Long Position).
Die Strategie für den regulären Testmodus wird im Code desTestMode_visual_tester.mq5 EAs implementiert.
Fazit
Ich habe in diesem Beitrag versucht, die Modus-Fähigkeiten des MetaTrader 5 Terminals und der MQL5-Sprache zu veranschaulichen. In diesem Zusammenhang sei darauf hingewiesen, dass ein Multi-Modus Ansatz beim Programmieren eines Handels-Algorithmus einerseits Mehrkosten bedeutet, und andererseits dadurch aber auch jede einzelne Entwicklungsphase nacheinander separat betrachtet werden kann. Die Objekt-orientierte Programmierung stellt in diesem Fall eine einfallsreiche Hilfe für Programmierer dar.
Auf die Modi 'Optimierung' und 'Rahmen sammelnd' wird in weiteren Beiträgen zu den statistischen Eigenschaften eines Handelssystems noch im Einzelnen eingegangen.
Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/1246
- 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.