Leitfaden zum Testen und Optimieren von Expert Advisors in MQL5

15 Januar 2016, 11:08
Samuel Olowoyo
0
1 216

Einleitung

Sobald ein Entwickler einen Expert Advisor geschrieben hat, ist der Vorgang zur Sicherstellung, dass der Expert Advisor sein Ziel, nämlich gute Gewinne abzuwerfen, auch erreicht, meist anspruchsvoll und aufwendig. In diesem Beitrag sehen wir uns gemeinsam einige der wichtigsten Schritte an, die für das Testen und die Optimierung eines Expert Advisors notwendig sind, sodass wir beim Schreiben des Expert Advisors gewünschten Ziel auch möglichst nahe kommen.


1. Identifizierung und Korrektur von Fehlern im Code

Betrachten wir uns zunächst einige der häufigsten Fehler im Code, die normalerweise beim Schreiben eines Expert Advisor Codes auftreten. Meistens ist es für Anfänger immens schwer, wenn sie ihre Codes schreiben oder einen, von einem anderen Entwickler geschriebenen Code verändern, Fehler im Code zu identifizieren und zu beheben. In diesem Abschnitt zeigen wir, wie leicht der MQL5 Editor zur Identifizierung und Korrektur derartiger Fehler benutzt werden kann.

Sie haben den Code gerade fertig geschrieben, und es sieht so aus, als sollte alles funktionieren, da Sie sich fast sicher sind, dass der Code fehlerfrei ist. Oder der Code wurde von jemand anders geschrieben und Sie haben einige Veränderungen vorgenommen, doch leider wurden Ihnen, als Sie die Compile (Erstellen) Taste (oder F7) gedrückt haben, eine Reihe von Fehlern angezeigt, so wie im Error-Tab des MetaEditor Toolbox-Fensters gezeigt.

Erstellungsfehler in einem Expert Advisor Code

Abb. 1 Erstellungsfehler in einem Expert Advisor Code

Mann! 38 Fehler und 1 Warnung. Ihr Code mag zwar nicht nicht wirklich so viele Fehler haben wie hier gemeldet, doch wir sehen uns trotzdem all die verschiedenen Fehlerarten an, die bei der Erstellung Ihres Codes durchaus auftreten können, und auch wie wir sie beheben können. Erklären wir das obige Diagramm.

  • Abschnitt 1 zeigt die Beschreibung des Fehlers im Code. Hier erfahren wir, um welchen Fehler es sich handelt, wie er also aussieht..
  • Abschnitt 2 zeigt uns in welcher Datei der Fehler liegt. Das ist wichtig, wenn wir Dateien mit Fehlern mit aufgenommen haben. Hier erfahren wir, welche Datei wir auf den beschriebenen Fehler hin untersuchen müssen.
  • Abschnitt 3 zeigt uns in welcher Zeile und Spalte (auf der Zeile) in unserem Code sich der Fehler befindet. So wissen wir, welche bestimmte Zeile wir auf den beschrieben Fehler hin untersuchen müssen.
  • Abschnitt 4 zeigt uns die Zusammenfassung der Erstellungsfehler und Warnungen.

Versuchen wir jetzt einen Fehler nach dem anderen zu beheben. Scrollen wir zur ersten Zeile im Error-Tab, sodass wir am Anfang beginnen können.

Identifizierung und Behebung von Fehlern im Code-1

Abb. 2 Identifizierung und Behebung von Fehlern im Code

Das erste Problem wird beschrieben als: "Abbruch eines konstanten Wertes" und findet sich in Zeile 16, Spalte 20. Um die genaue Zeile in unserem Code zu finden, wählen Sie aus dem Edit-Menü des MetaEditors 'zu Zeile gehen' oder drücken die CTRL-G Taste.

Abb. 3 Finden der fehlerhaften Codezeilennummer

Abb. 3 Finden der fehlerhaften Codezeilennummer

Es erscheint ein Dialogfenster.

Abb. 4 Dialog: Finden der fehlerhaften Zeilennummer

Abb. 4 Dialog: Finden der fehlerhaften Zeilennummer

Der in der Dialog-Box angezeigte Zahlenbereich ist die Gesamtzahl der Zeilen des Codes. In unserem Fall (1-354) besitzt unser Code also 354 Zeilen.

Geben Sie die Zahl, die Sie prüfen wollen, in die Box ein und klicken dann OK. Sie gelangen so direkt zur entsprechenden Zeile im Code. Der Mauszeiger blinkt dann auf der entsprechenden Zeile.

Abb. 5 Cursor zeigt die Zahl der fehlerhaften Zeile

Abb. 5 Cursor zeigt die Zahl der fehlerhaften Zeile

Das Problem hier ist, dass wir einen Posten als eine ganzzahlige (int) Variable deklarieren, ihn aber mit einem double wert initialisieren (0,1). Zur Behebung verändern wir int zu double, speichern die Datei und klicken erneut auf COMPILE, um zu sehen, ob der Fehler behoben wurde.

Abb. 6 Code nach erfolgter Korrektur erstellen und speichern

Abb. 6 Code nach erfolgter Korrektur erstellen und speichern 

Durch erneutes Erstellen wurde das erste Problem behoben, doch wie unten gezeigt, gibt es noch weitere:

Weitere Fehler im Code müssen behoben werden

Abb. 7 Nach der Erstellung erscheinen noch weitere Fehler im Code

Wir machen nun das gleiche wie oben und gehen zu Zeile 31. Doch diesmal gehen wir mit Rechtsklick auf den Fehler im Error-Tab und wählen 'zu Zeile gehen'

Eine andere Möglichkeit, die fehlerhafte Codezeile zu finden

Abb. 8 Eine andere Möglichkeit, die fehlerhafte Codezeile zu finden 

Sie können auch den Fehler auswählen und die Eingabe-Taste drücken. Sie gelangen sofort auf Codezeile 31.

Der Mauszeiger blinkt auf Zeile 31, und sie ist auch durch eine rote Schaltfläche (Fehler-Icon) markiert.

Finden der fehlerhaften Codezeile

Abb. 9a Finden der fehlerhaften Codezeile

Sollte es sich jedoch um eine Warnmeldung handeln, wie bei Zeile 16, die wir vorhin schon korrigiert haben, erscheint ein gelbes Dreieck (Warn-Icon):

Warnzeichen

Abb. 9b Finden der fehlerhaften Codezeile

Es ist offensichtlich, dass wir in Zeile 31 keine Probleme mehr haben, doch die Fehlerbeschreibung sagt trotzdem: "'STP' - unexpected token" .

Also müssen wir die Zeile davor (Zeile 30) prüfen, um zu sehen, was evtl. schiefgegangen ist. Wenn wir genau hinsehen, sehen wir, dass nach "double ccminb = -95,0000" in Zeile 30 ein Strichpunkt fehlt, und deshalb haben wir den Fehler in Zeile 31. Fehler also korrigieren und nach -95,0000 also den Strichpunkt eingeben und den Code anschließend neu erschließen.

Die Fehler in Zeile 31 sind beseitigt. Als Nächstes wird uns Zeile 100 angezeigt (vgl. unten):

Der Code hat immer noch Fehler

Abb. 10 Der Code hat immer noch Fehler

Hey Olowsam, müssen wir echt nach jeder Korrektur den Code erneut erstellen? Warum gehen wir nicht alle Zeilen auf einmal durch, und wenn wir alle Fehler behoben haben, erstellen den Code dann ein einziges Mal neu, anstatt das mühsam nach jeder Korrektur machen zu müssen?

Haben Sie gerade diese Frage gestellt?

Sie haben hier zwar Recht, aber ich rate davon ab. Probleme löst man immer Schritt für Schritt- eins nach dem anderen. Jeder Versuch, Probleme zusammen zu schmeißen und sie in einem Rutsch zu lösen, kann zu 'ner Menge Kopfweh führen. Sie werden bald verstehen warum… Haben Sie einfach ein bisschen Geduld.

Zurück zu unserem Problem. Wir prüfen Zeile 100 auf den nächsten Fehler Der Fehler besagt: "'if' - Ausdrücke auf einem globalem Umfang nicht erlaubt". Und ich bin sicher, dass das 'wenn' in Zeile 100 nicht auf einem globalen Umfang ist. also warum dann diese Meldung? Gehen wir zu Zeile 100

Abb. 11  Den Fehler im Code finden

Abb. 11  Den Fehler im Code finden

In Zeile 100 gibt es kein Problem. Und da wir ja gerade Zeile 31 korrigiert haben, muss der Fehler wohl irgendwo zwischen Zeile 32 und 99 liegen. Also hoch zu Zeile 99 (da steht ein Kommentar, kann also nicht der Fehler sein). Auch die Deklarierungen weiter oben (MqlTick, MqlTradeRequest und MqlTradeResult) sind korrekt deklariert und mit Satzzeichen versehen.

Sehen wir uns mal den Code für den if-Ausdruck vor diesen Deklarierungs-Codezeilen an und prüfen, ob der Ausdruck in Ordnung ist.  Aha: das 'wenn' hat eine schließende Klammer, aber keine öffnende.

Abb. 12 Prüfung oberhalb der fehlerhaften Zeilennummer, um Fehler zu finden

Abb. 12 Prüfung oberhalb der fehlerhaften Zeilennummer, um Fehler zu finden

Also öffnende Klammer hinzufügen und Code erneut erstellen.

//--- Do we have enough bars to work with
   int Mybars=Bars(_Symbol,_Period);
   if(Mybars<60) // if total bars is less than 60 bars
    {
      Alert("We have less than 60 bars, EA will now exit!!");
      return;
     }

Ist dies geschehen, sind die Fehler in Zeilen 100, 107, 121, 126, 129 usw. verschwunden. Doch es erscheinen immer noch neue. Verstehen Sie jetzt, warum das schrittweise Vorgehen am besten ist? 

Der Code zeigt noch mehr Fehler

Abb. 13 Der Code zeigt noch mehr Fehler

Als Nächstes kommt Zeile 56 dran, sie hat zwei Fehler: "'cciVal1' - Parameter-Konvertierung nicht zugelassen" und "'cciVal1' - Array erforderlich"

Bei genauerem Hinsehen zeigt sich, dass in Zeile 56 cciVal1 als ein Array hätte deklariert werden müssen. Könnte es wohl sein, dass wir cciVal1 nicht als Array deklariert haben, es aber jetzt als solchen verwenden wollen? Sehen wir uns den Deklarierungsabschnitt an, um dies herauszufinden, denn nur dann wissen wir, war wir als nächstes tun müssen.

//--- Other parameters
int maHandle;               // handle for our Moving Average indicator
int cciHandle1,cciHandle2;  // handle for our CCI indicator
double maVal[];             // Dynamic array to hold the values of Moving Average for each bars
double cciVal1,cciVal2[];   // Dynamic array to hold the values of CCI for each bars
double p1_close,p2_close;   // Variable to store the close value of Bar 1 and Bar 2 respectively

Wir haben anscheinend versehentlich cciVal1 als ein doppeltes anstatt ein dynamisches Array deklariert, da wir die eckigen Klammern vergessen haben ([]). Also eckige Klammern dazu (genauso wie bei cciVal2[]), und dann Code erstellen.

//--- Other parameters
int maHandle;               // handle for our Moving Average indicator
int cciHandle1,cciHandle2;  // handle for our CCI indicator
double maVal[];             // Dynamic array to hold the values of Moving Average for each bars
double cciVal1[],cciVal2[]; // Dynamic array to hold the values of CCI for each bars
double p1_close,p2_close;   // Variable to store the close value of Bar 1 and Bar 2 respectively

Fehler im Code bereits erheblich reduziert

Abb. 14 Fehler im Code bereits erheblich reduziert

Unglaublich! So viele Fehler weniger. Wir haben nur den für Zeile 56 gemeldeten Fehler behoben und automatisch wurden einige andere Fehler einfach korrigiert. Klar, denn der Fehler in Zeile 56 war für diese anderen Fehler verantwortlich. Deshalb ist es gut bei der Fehlerbehebung in Ihrem Code wirklich Schritt für Schritt vorzugehen.

Gehen wir jetzt zum nächsten gemeldeten Fehler - in Zeile 103: "'GetLastError' - nicht deklarierter Identifikator"  Moment... GetLastError soll doch eine Funktion sein! Also in Zeile 103 nachsehen und das Problem suchen.

//--- Get the last price quote using the MQL5 MqlTick Structure
   if(!SymbolInfoTick(_Symbol,latest_price))
     {
      Alert("Error getting the latest price quote - error:",GetLastError,"!!");    // line 103
      return;
     }

Und das Problem findet sich in der Tat in Zeile 103. GetLastError ist eine Funktion und jede Funktion braucht für seine Eingabeparameter ein Paar Klammern. Also geben wir ein leeres Klammerpaar ein und erstellen dann den Code. Das leere Klammerpaar zeigt an, dass die Funktion keine Begründungen oder Parameter aufnimmt.

//--- Get the last price quote using the MQL5 MqlTick Structure
   if(!SymbolInfoTick(_Symbol,latest_price))
     {
      Alert("Error getting the latest price quote - error:",GetLastError(),"!!");  // line 103
      return;
     }

Weiter zu Zeile 159 : "'=' - l-Wert erforderlich"  plus  eine Warnung: "Ausdruck ist nicht Boolesch". Also auf zu Zeile 159 und nachsehen, was der Fehler bedeutet. 

      else if(PositionGetInteger(POSITION_TYPE) = POSITION_TYPE_SELL) // line 159
       {
            Sell_opened = true; // It is a Sell

Hier sehen wir, dass wir den Wert von POSITION_TYPE_SELL auf  PositionGetInteger(POSITION_TYPE) in der 'wenn'-Aussage zugewiesen haben und das wollen wir eben gerade nicht. Wir wollten stattdessen einen Vergleich haben. Also ändern wir den Ausdruck so, dass = Operator anstatt ==-Operator verwendet wird. (also ‘==’ anstelle von ‘=’). Korrigieren und Code erstellen.

      else if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) // line 159
       {
            Sell_opened = true; // It is a Sell

Prima! Einen Fehler haben wir noch. Gehen wir zu Zeile 292 und finden heraus, warum dort "'PositionsTotal' - nicht deklarierter Identifikator" steht. Moment mal, erinnern Sie sich? So einen Fehler hatten wir doch vorhin schon mal! ‘GetlastError’ in Zeile 103. Vielleicht haben wir das Klammerpaar für PositionsTotal hier auch vergessen, denn das ist ja eine Funktion. Auf zu Zeile 292 und nachsehen.

bool CheckTrade(string otyp)
{
   bool marker = false;
   for (int i=1; i<=PositionsTotal;i++)  // line 292
   {

Genau. Der Fehler liegt darin, dass wie vergessen haben, für die Funktion PositionsTotal das Klammerpaar hinzuzufügen Also korrigieren (PositionsTotal()) und den Code erstellen. Lassen Sie mich hier zudem sagen, dass wir diesen Fehler auch gemeldet bekommen, wenn wir tatsächlich eine Variable verwenden, die wir an anderer Stelle im Code nicht deklariert haben.

Abb. 15 Alle Erstellungsfehler wurden komplett behoben

Abb. 15 Alle Erstellungsfehler wurden komplett behoben

Großartig! Wir konnten also alle Erstellungsfehler beheben. Jetzt lassen wir das Fehlersuchprogramm durch unseren Code laufen und schauen mal, ob es zu Laufzeit-Fehlern kommt.  Diesen Schritt erklären wir jetzt nicht im Detail, da das Fehlersuchprogramm für Codes in diesem Beitrag bereits angesprochen wurde.

Während die Fehlersuche anläuft, bemerken wir einen weiteren Fehler:

Abb. 16 Laufzeit-Fehler während Fehlersuche im Code entdeckt

Abb. 16 Laufzeit-Fehler während Fehlersuche im Code entdeckt

Auf OK klicken und Sie erhalten die Codezeile, die diesen Fehler erzeugt.

Identifizierung der Codezeile, die den Laufzeit-Fehler erzeugt

Abb. 17 Identifizierung der Codezeile, die den Laufzeit-Fehler erzeugt

Wie die Abbildung oben zeigt, wird der Fehler von diesem Code in Zeile 172 erzeugt. Und da der Fehler ein "Array außerhalb des Bereichs" ist, heißt das, dass der Wert den uns das Array liefern soll, außerhalb der verfügbaren Array-Werte liegt. Also müssen wir jetzt in die Zeile, wo wir die Indikator-Buffer in die Arrays kopiert haben und dort nach dem Problem suchen.

//--- Copy the new values of our indicators to buffers (arrays) using the handle
   if(CopyBuffer(maHandle,0,0,3,maVal)<0)
     {
      Alert("Error copying MA indicator Buffers - error:",GetLastError(),"!!");
      return;
     }
   if(CopyBuffer(cciHandle1,0,0,3,cciVal1)<0 || CopyBuffer(cciHandle2,0,0,3,cciVal2)<0)
     {
      Alert("Error copying CCI indicator buffer - error:",GetLastError());
      return;
     }

Anhand der CopyBuffer Funktionen sehen wir, dass wir nur drei Werte kopiert haben (Bar 0, 1 und 2). Das bedeutet, dass wir nur auf Array-Werte von maVal[0],  maVal[1]  und maVal[2] sowie von cciVal1[0] , cciVal1[1]  und cciVal1[2] usw. zugreifen können. Doch in Zeile 172 unseres Codes wollten wir den Array-Wert für cciVal1[3]. erhalten. Un das ist der Grund für den Fehler.  Halten wir das Fehlersuchprogramm jetzt an und beheben den Fehler:

Abb. 18 Fehlersuchprogramm zur Korrektur des Fehlers im Code anhalten

Abb. 18 Fehlersuchprogramm zur Korrektur des Fehlers im Code anhalten

Um den Fehler zu beheben, müssen wir die Anzahl der von den Indikator-Buffern zu kopierenden Datensätze auf 5 erhöhen, damit wir so Array-Werte von cciVal1[0], cciVal1[1], cciVal1[2], cciVal1[3] und ggf. cciVal1[4] erhalten.

//--- Copy the new values of our indicators to buffers (arrays) using the handle
   if(CopyBuffer(maHandle,0,0,5,maVal)<0)
     {
      Alert("Error copying MA indicator Buffers - error:",GetLastError(),"!!");
      return;
     }
   if(CopyBuffer(cciHandle1,0,0,5,cciVal1)<0 || CopyBuffer(cciHandle2,0,0,5,cciVal2)<0)
     {
      Alert("Error copying CCI indicator buffer - error:",GetLastError());
      return;
     }

Den Code wie gezeigt korrigieren und dann das Fehlersuchprogramm erneut starten. Jetzt erscheinen keine weiteren Fehler mehr, während unser Expert Advisor Handelsaktionen durchführt

Abb. 19 Alle Fehler behoben. Expert Advisor führt Handel während Fehlersuche aus

Abb. 19 Alle Fehler behoben. Expert Advisor führt Handel während Fehlersuche aus

 

2. Den Expert Advisor testen

Sobald wir ganz sicher sind, dass unser Code fehlerfrei ist, können wir nun hergehen und den Expert Advisor testen, um die besten Einstellungen für die optimalsten Ergebnisse zu bekommen. Zur Durchführung des Tests verwenden wir den Strategie-Tester, ein in das MetaTrader  Terminal eingebautes Programm. Zum Starten des Strategie-Testers, zum View-Menü im Terminal gehen und Strategie-Tester auswählen.

Abb. 20 Strategie-Tester starten

Abb. 20 Strategie-Tester starten

2.1 Vorläufiger Test unseres Expert Advisors

Zu diesem Zeitpunkt möchten wir unseren Expert mit Hilfe der im Markt-Fenster vorhandene Symbole testen. Anhand dieses Ergebnisses können wir vermuten, für welches Währungspaar wir unseren Expert besser optimieren können. Vergewissern Sie sich, dass das Markt-Fenster die meisten der Währungen enthält, auf die Sie mit dem Expert abzielen.

Den Expert im Settings-Tab des Strategie-Testers wählen, beabsichtigten Zeitraum/Zeitrahmen auswählen (Sie können ihn natürlich auch für unterschiedliche Zeitrahmen testen) und dann im Optimierungsfeld 'Alle Symbole Ausgewählt in der MARKT-Beobachtung' wählen. Direkt vorne steht der Parameter der Optimierungsergebnisse, dort Saldo + max. Gewinnfaktor auswählen.

Abb. 34 Vorläufiger Test des Expert Advisors mit allen Symbolen im Markt-Beobachtungsfenster

Abb. 21 Vorläufiger Test des Expert Advisors mit allen Symbolen im Markt-Beobachtungsfenster 

1. Den Modus zur Tick-Erzeugung wählen – (bei jeder Preisänderung)

2. Optimierungsart wählen – (Alle Symbole in MARKT-Beboachtung ausgewählt)

3. Art des nach Optimierung erwarteten Ergebnisses wählen

Die Details der verschiedenen Optimierungsarten können Sie der Hilfe-Dokumentation des Terminals entnehmen. Wir leiten den Test nicht weiter, also Weiterleiten auf Nein stellen.

Für diesen Test werden die Hauptwerte/Parameter (grün unterlegt) im Inputs-Tab verwendet.

Abb. 35 Eingabeparameter des vorläufigen Tests

Abb. 35 Eingabeparameter des vorläufigen Tests

Sobald Sie hiermit fertig sind, wechseln Sie zum Settings-Tab und klicken auf Start. Ist der Test abgeschlossen, erscheint im Logbuch-Tab eine Meldung, die in etwa so aussieht:

Abb. 36 Vorläufiger Test abgeschlossen

Abb. 23 Vorläufiger Test abgeschlossen

Ist der Test abgeschlossen, gehen Sie für die Ergebnisse zum Optimierungsergebnisse-Tab.

Abb. 37 Optimierungsergebnisse des vorläufigen Tests

Abb. 24 Optimierungsergebnisse des vorläufigen Tests

Was uns interessiert, ist das Symbol, dasauf Grundlage unserer Einstellung – (Balance + max Profit Factor) das höchste Ergebnis bringt. Dazu müssen wir das Ergebnis sortieren und zwar durch Klicken auf die Überschrift Ergebnis, damit das Symbol mit dem höchsten Ergebnis ganz oben als erstes erscheint.

Abb. 38 Analyse des vorläufigen Optimierungsergebnisses

Abb. 25 Analyse des vorläufigen Optimierungsergebnisses

Anhand dieses Ergebnisses erkennen wir, dass unser Expert Advisor in dem von uns gewählten Zeitrahmen für die folgenden Symbole profitabel sein kann (EURUSD, EURJPY, AUDUSD).  Sie können diesen Test für einen anderen Zeitrahmen nochmals durchführen, sagen wir für 30 Minuten, und sehen was dann dabei herauskommt. Betrachten Sie diesen Hinweis als Ihre kleine 'Hausaufgabe' und lassen Sie uns die Ergebnisse wissen, damit wir alle was daraus lernen können.

Ausgehend vom vorläufigen Testergebnis entscheiden wir nun, für welches/e Symbol/e und Zeitrahmen wir unsren Expert Advisor optimieren wollen.

In unserem Beispiel ist das für EURUSD und den Zeitrahmen 1 Stunde.  Aus welchen Gründen haben wir uns für diese Optimierung entschieden?

  • Gewinnfaktor (Profit Factor):

Der Gewinnfaktor ist das Verhältnis von Gesamtgewinn zu Gesamtverlust in diesem Test. Je höher der Gewinnfaktor umso profitabler ist Ihre Handelsstrategie.

  • Inanspruchnahme (%) (Drawdown %):

Bezieht sich auf die relative Inanspruchnahme des Eigenkapitals oder des höchsten Verlusts (in%) vom maximalen Wert des Eigenkapitals. Je geringer die Inanspruchnahme (in%), umso besser die Strategie.

  • Erholungsfaktor (Recovery Factor):

Bezeichnet da Verhältnis von Gewinn zur maximalen Inanspruchnahme. Spiegelt den Risikograd der Handelsstrategie wider.

Wenn Sie das Symbol und den Zeitrahmen festgelegt haben, die Sie verwenden wollen, können Sie den Expert Advisor nun optimieren.

2.2 Den Expert Advisor optimieren

Die Optimierung ist nur ein Verfahren zur Feinabstimmung der Leistung unserer EA mittels Tests mit verschiedenen Faktoren (Parameter), zur Bestimmung der Effektivität der Profitabilität unserer, im EA codierten Strategie. Sein Ablauf ähnelt dem Testverfahren, doch anstatt unseren EA nur einmal zu testen, wird er nun viele Male getestet - je nach den im Input-Tab ausgewählten Parametern.

Wir gehen dazu zunächst zum Settings-Tab und aktivieren 'Optimierung'. Dann wählen wir die Art des Ergebnisses aus, das uns die Optimierung liefern soll.

Abb. 39 Optimierungseinstellungen für den Expert Advisor

Abb. 26 Optimierungseinstellungen für den Expert Advisor

1. Den Modus zur Tick-Erzeugung wählen – (bei jeder Preisänderung)

2. Optimierungsart wählen – (schneller genetisch-basierter Algorithmus)

3. Art des nach Optimierung erwarteten Ergebnisses wählen (hier: Saldo + max. Gewinnfaktor)

Die Details der verschiedenen Optimierungsarten können Sie der Hilfe-Dokumentation des Terminals entnehmen. Wir leiten den Test nicht weiter, also Weiterleiten auf Nein stellen. Wenn die Optimierungseigenschaften eingestellt sind, stellen wir im Inputs-Tab die für die Optimierung zu verwendenden Parameter ein.

Abb. 40 Eingabeparameter für Optimierung

Abb. 27 Eingabeparameter für Optimierung

Da wir ja optimieren wollen, konzentrieren wir uns nur auf die gelb unterlegten Bereiche. Zunächst muss jeder Parameter, den wir in der Optimierung nicht verwenden wollen, unangekreuzt bleiben. Wir kreuzen also nur die Parameter an, die wir in der Optimierung unseres EA auch verwenden wollen. Ich habe in unserem Fall daher fünf Parameter angekreuzt. doch Sie können auch nur einen oder zwei ankreuzen, je nach den Parametern, auf denen die Effektivität Ihrer Strategie beruht. Sie können z.B. nur den Gleitenden Mittelwert und die CCI-Zeiträume ankreuzen, sodass das Optimierungsergebnis Ihnen dann den besten Wert für jeden der Indikatoren angibt, die Ihrem EA die beste Leistung verleihen. Das ist die Hauptessenz der Optimierung.

Zudem legt die Menge der angekreuzten Parameter auch die Gesamtzahl der Tests fest, die Ihr EA durchlaufen muss. Sie werden gleich besser verstehen, was damit gemeint ist.

Die Werte einstellen

Start:

Startwert, der von der für die Optimierung ausgewählten, Variable benutzt wird.   Nehmen wir die Stop Loss Variable her und erklären kurz, wie man ihre Werte einrichtet. Für Stop Loss haben wir den Tester beauftragt, mit einem Wert von 30 zu beginnen Dies ist der Minimalwert, der während der Optimierung für Stop Loss verwendet wird.

Schritt:

Der inkrementelle Wert für Stop Loss. Setzen wir also einen 'Schritt' von 2, bedeutet das, dass wenn für Stop Loss im ersten Test ein Wert von 30 verwendet wird, im zweiten entweder 32, 36, 34 usw. verwendet wird. Es bedeutet nicht, dass zunächst 30 und dann jeweils 32, 34 usw. verwendet werden. Nein, die Werte werden zufällig gewählt, doch sie sind zwischen Start- und Stop-Wert stets Vielfache von 2 .

Stop:

Der Maximal- oder höchste für die Optimierung verwendete Wert. In unserem Fall mit 38 angegeben. Das heißt, dass die für den Test verwendeten Werte zwischen 30 und 38 liegen, doch Werte als Vielfache von 2 sind. Der Wert 40 oder jeder höhere Wert wird nicht hergenommen.

Die Gesamtzahl der ausgeführten Tests hängt von den Einstellungen in diesen drei Bereichen ab. In unserem Beispiel kombiniert der Tester insgesamt 5 Möglichkeiten für Stop Loss alleine, wie in der Schritte Spalte im Inputs-Tab gezeigt; er kombiniert insgesamt 8 Möglichkeiten für Take Profit, usw. Und angesichts all der anderen Variablen, kommen so Hunderttausende von Möglichkeiten zusammen (Tests/bestanden). Wenn Sie nicht Ewigkeiten warten möchten, um einen einzigen EA zu optimieren, dann sollten Sie nicht zu viele Variablen ankreuzen oder mit einschließen - vielleicht einfach nur zwei oder drei, von denen die Leistung Ihres EA wirklich abhängt (insb. die Indikator-Zeiträume, wenn Sie sie in Ihrem Code verwenden). Zudem müssen Sie darauf achten, dass Ihr Schritt-Wert nicht dazu führt, dass Sie zu viele Möglichkeiten (Tests) erhalten). Wenn wir z.B. 1 als den Schritt-Wert nehmen, haben wir die Zahl der Versuche für Stop Loss alleine bereits auf 10 erhöht Wie ich vorhin schon erwähnt habe, hängt die Gesamtzeit, die für eine Optimierungssitzung vonnöten ist, von der Gesamtzahl der vorhandenen Agents ab, die Sie in Ihrem System eingerichtet haben.

Das sollte als Erklärung genügen

Wenn wir mit der Einrichtung der Eingaben fertig sind, gehen wir zum Settings-Tab zurück und klicken auf Start.

Sobald eine Optimierung abgeschlossen ist, erscheinen die Details im Logbuch-Tab

Abb. 43 Optimierung abgeschlossen; Details im Logbuch-Tab angezeigt

Abb. 28 Optimierung abgeschlossen; Details im Logbuch-Tab angezeigt

Zur Ergebnisansicht während jeder Test bestanden oder abgeschlossen wurde, gehen wir zum Optimierungsergebnisse-Tab. Hier empfiehlt es sich, die Anzeigen nach Ergebnissen zu sortieren, damit wir die Einstellungen, die uns das beste Ergebnis auf Grundlage unserer Optimierungseinstellung liefern, auch klar erkennen können. Im Optimierungsergebnisse-Tab auf die Überschrift 'Ergebnisse' klicken, sodass die Ergebnisse entweder in auf- oder absteigender Reihenfolge angezeigt werden.

Abb. 44 Optimierungsbericht

Abb. 29 Optimierungsbericht

Wechseln Sie nun zum Optimierungs-Graph-Tab und sehen sich den entsprechenden Graphen an.

Abb. 45 Optimierungsgraph

Abb. 30 Optimierungsgraph

Sie verstehen nicht, was Ihnen da angezeigt wird? Keine Sorge, die Punkte, die Sie sehen, sind eine grafische Darstellung der Anzahl der Tests, die Ihr EA vor dem Hintergrund des Optimierungsergebnisses auf Grundlage seiner von Ihnen gewählten Art durchlaufen hat. In unserem Fall haben wir Saldo + max. Gewinnfaktor gewählt.

2.3 Interpretation des Ergebnisses

Für eine erfolgreiche Interpretation des Optimierungsberichts gehen wir zum Optimierungsergebnisse-Tab. Sie werden merken, das Sie einige Felder wie Gewinnfaktor, erwartete Auszahlung, Inanspruchnahme(%), usw. nicht sehen können. Dazu Rechtsklick irgendwo im Optimierungsergebnisse-Tab und anschließend, wie unten gezeigt, die Zusatzinformationen auswählen, die Sie haben möchten:

Abb. 46 Anzeige von Inanspruchnahme(%) im Optimierungsergebnis auswählen

Abb. 31 Anzeige von Inanspruchnahme(%) im Optimierungsergebnis auswählen

 Abb. 47 Anzeige von Gewinnfaktor im Optimierungsergebnis auswählen

Abb. 32 Anzeige von Gewinnfaktor im Optimierungsergebnis auswählen

Wenn wir diese zusätzlichen Berichte hinzugefügt haben, analysieren wir nun das Optimierungsergebnis, um die besten Einstellungen für unseren Expert Advisor festzulegen.

Analyse des Optimierungsberichts

Abb. 33 Analyse des Optimierungsberichts

In der obigen Abbildung weisen die hervorgehobenen Bereiche namens A und B die besten Ergebnisse für unseren Expert Advisor aus.  Wie Sie sich nun entscheiden, liegt ganz bei Ihnen. Es hängt ganz davon ab, was Ihr Ziel ist. In unserem Fall interessieren uns nicht nur die Einstellungen, die den höchsten Profit ergeben, sondern auch die mit einer geringeren Inanspruchnahme(%).

Wie Sie sehen hat Bereich A (gelb unterlegt) das beste Ergebnis (Balance + max Profit Factor) von 22381,71 mit einem Gewinn von 924,10. Bereich B hingegen (grün unterlegt) hat das zweitbeste Ergebnis mit 22159,25 doch mit einem höheren Gewinn von 936,55. Bereich A hat eine geringere Inanspruchnahme(%) von 1,78, während Bereich B eine höhere von 1,95 zeigt.

Der Strategie-Tester speichert die Optimierungsergebnisse im Order "<Client terminal data folder>\Tester\cache". In Ihrem Fall werden alle Optimierungsdaten in der cci_ma_ea.EURUSD.H1.0.xml Datei abgelegt.

Der Dateiname sieht so aus: ExpertName.SYMBOL.PERIOD.GenerationMode.xml,wobei:

  • ExpertName = Name des Expert Advisors;
  • Symbol = Symbol;
  • Period = Zeitrahmen (M1,H1,...)
  • GenerationMode = Erzeugungsmodus von Kursschwankungen (0-jede Schwankung, 1 - 60 Sekunden OHLC (Open-High-Low-Close), 2 - nur offene Kurse).

Die xml-Dateien können mit MS Excel geöffnet werden.

2.4 Das beste Ergebnis auswählen

Um schließlich das beste Ergebnis zu bekommen, müssen wir abermals einen Blick auf den Optimierungsgraph werfen. Also zum Optimierungsgraph wechseln.  Rechtsklick irgendwo im Graph und  1-D Graph auswählen.

1-D Graph im Optimierungsgraphen auswählen

Abb. 34 Eindimensionalen Graph (1-D) zur Ereignisanalyse wählen

Hier sehen wir ganz schnell die Werte jedes einzelnen Eingabeparameters, der das beste Ergebnis liefert.  Jetzt können Sie jeden Parameter auswählen, um den besten Wert zu sehen. Rechtsklick auf den Graph und X-Achse wählen und dann den Parameter, den Sie sich ansehen wollen. Das sieht dann so aus (für Stop Loss)

Abb. 50 Den besten Stop Loss-Wert aus dem Optimierungsergebnis erhalten

Abb. 35 Den besten Stop Loss-Wert aus dem Optimierungsergebnis erhalten

Aus dem Optimierungsergebnis lässt sich klar ablesen, dass der beste Stop Loss 34 ist, der beste Take Profit 78, und die beste CCI_Period1 62. Für die besten Werte der MAPeriod und CCI_Period2, beide jeweils wie oben auswählen

Abb. 51 Den besten Wert für den Gleitenden Mittelwertzeitraum aus dem Optimierungsergebnis erhalten

Abb. 36 Den besten Wert für den Gleitenden Mittelwertzeitraum aus dem Optimierungsergebnis erhalten

Der Graph zeigt einen Wert von 26 als MA_Period mit dem besten Ergebnis

Abb. 52 Den besten CCl_Period1 Wert aus dem Optimierungsergebnis erhalten

Abb. 37 Den besten CCl_Period1 Wert aus dem Optimierungsergebnis erhalten

Der Graph zeigt einen Wert von 62 als die CCI_Period1 mit dem besten Ergebnis.

Abb. 53 Den besten CCl_Period2 Wert aus dem Optimierungsergebnis erhalten

Abb. 38 Den besten CCl_Period2 Wert aus dem Optimierungsergebnis erhalten

Der Graph zeigt Werte von 28 oder 30 als die CCI_Period2 mit dem besten Ergebnis.

Da wir nun die besten Werte für jeden Parameter kennen, ist es an der Zeit unseren Expert Advisor dem Abschlusstest zu unterziehen.

2.5 Der Abschlusstest

Im Abschlusstest werden die besten Parameter für den Test des Expert Advisors kombiniert. In unserem Fall verwenden wir die besten Werte, die wir im EINGABE-Bereich des Strategie-Testers gefunden haben (vgl. unten).

Eingabewerte für den Abschlusstest

Abb. 39 Eingabeparameter des Abschlusstests

Im SETTINGS-Tab des Strategie-Testers deaktivieren wir nun, wie unten gezeigt, 'Optimierung'

Einstellungen für den Abschlusstest

Abb. 40 Einstellungen für den Abschlusstest

Danach klicken wir auf START, um mit dem Test zu beginnen. Sobald der Test abgeschlossen ist, werden uns die Ergebnisse, so wie unten gezeigt, im ERGEBNISSE-Tab präsentiert

Abb. 56 Ergebnisse des Abschlusstests

Abb. 41 Ergebnisse des Abschlusstests

Und im GRAPH-Tab steht uns der Abschlusstest ebenfalls als Graph zur Verfügung

Abb. 57 Graph der Ergebnisse des Abschlusstests

Abb. 42 Graph der Ergebnisse des Abschlusstests

Fazit

In diesem Beitrag wurden die verschiedenen Möglichkeiten erläutert, wie man Fehler im Code identifizieren und beheben kann und wie man einen Expert Advisor für das beste Symbol der Marktbeobachtung testen und optimieren kann.

Ich glaube, dass dieser Beitrag und seine Beschreibung der Fehlersuche im Code sowie die Optimierung und Tests des Expert Advisors mit Hilfe des Strategie-Testers das Schreiben eines besseren und profitableren Expert Advisor gestattet.

Übersetzt aus dem Englischen von MetaQuotes Software Corp.
Originalartikel: https://www.mql5.com/en/articles/156

Beigefügte Dateien |
cci_ma_ea.mq5 (14.23 KB)
Adaptive Handelssysteme und ihre Verwendung im MetaTrader 5 Client-Terminal Adaptive Handelssysteme und ihre Verwendung im MetaTrader 5 Client-Terminal

Dieser Beitrag möchte eine Variante eines adaptiven Systems vorstellen, die aus vielen Strategien besteht, von denen jede ihre eigenen "virtuellen" Handels-Operationen durchführt. Echter Handel wird in Übereinstimmung mit den Signalen der in diesem Augenblick gewinnbringendsten Strategie ausgeführt. Dank der Verwendung des Objekt-orientierten Ansatzes, der Klassen zur Arbeit mit Daten und der Handelsklassen der Standardbibliothek, macht die Architektur des Systems einen einfachen und aufrüstbaren Eindruck. Jetzt kann man leicht adaptive Systeme mit Hunderten von Handelsstrategien erzeugen und analysieren.

Expert Advisor auf Grundlage der New Trading Dimensions von Bill Williams Expert Advisor auf Grundlage der New Trading Dimensions von Bill Williams

In diesem Beitrag geht es um die Entwicklung des Expert Advisors, auf Grundlage des Buchs "New Trading Dimensions: How to Profit from Chaos in Stocks, Bonds, and Commodities" von Bill Williams. Die Strategie selbst ist wohl bekannt, ihre Anwendung jedoch unter Händlern immer noch umstritten. Dieser Beitrag behandelt die Handelssignale des Systems, die spezifischen Charakteristika seiner Implementierung und die Testergebnisse vor dem Hintergrund historischer Daten.

Orders, Positions und Abschlüsse in MetaTrader 5 Orders, Positions und Abschlüsse in MetaTrader 5

Einen robusten Handelsroboter zu erzeugen geht nicht ohne das Verständnis der Mechanismen des MetaTrader 5 Handelssystems. Der Client-Terminal erhält vom Handelsserver Informationen über die Positions, Orders und Abschlüsse. Um diese Daten mittels MQL5 entsprechend verarbeiten zu können, ist ein gutes Verständnis der Interaktion zwischen dem mql5-Programm und dem Client-Terminal unabdingbar.

Handelsereignisse in MetaTrader 5 Handelsereignisse in MetaTrader 5

Eine Überwachung des aktuellen Status eines Handels-Account bedeutet offene Positions und Order kontrollieren zu können. Bevor ein Handelssignal zu einem Abschluss wird, sollte es vom Client-Terminal als Anfrage zum Handels-Server geschickt werden, wo es in eine Order-Warteschlange gestellt wird und auf seine Bearbeitung wartet. Eine Anfrage vom Handels-Server annehmen, sie löschen, wenn sie abläuft oder auf ihrer Grundlage einen Abschluss ausführen - alle diese Handlungen haben Handelsereignisse zur Folge, und der Handels-Server informiert das Terminal entsprechend darüber.