Testen von Handelsstrategien

Die Idee des automatisierten Handels ist attraktiv, weil ein Handelsroboter unermüdlich 24/7 arbeiten kann. Der Roboter wird nicht müde, zweifelhaft und hat keine Angst, er ist völlig frei von irgendwelchen psychischen Problemen. Sie müssen nur klar die Handelsregeln formalisieren und sie in den Algorithmen implementieren, und der Roboter ist fertig zu arbeiten. Aber zuerst müssen Sie sicherstellen, dass die folgenden zwei wichtige Bedingungen erfüllt sind:

  • Der Expert Advisor führt Handelsoperationen in Übereinstimmung mit den Regeln des Handelssystems;
  • Die Handelsstrategie, die im EA implementiert ist, zeigt einen Gewinn aus der Geschichte.

Um Antworten auf diese Fragen zu bekommen, verwenden wir den Strategie-Tester, der ein Teil von MetaTrader 5 Client Terminal ist.

In diesem Abschnitt werden die Merkmale von Testen und Optimierung der Programme in der Strategie-Tester beschrieben:

 

Speicher- und Festplattenplatzbeschränkungen im MQL5 Cloud Network

Für Optimierungen, die im MQL5 Cloud Network ausgeführt werden, gilt folgende Einschränkung: Der Expert Advisor darf nicht mehr als 4 GB an Informationen auf die Festplatte schreiben oder mehr als 4 GB an RAM verwenden. Wird diese Grenze überschritten, kann der Netzwerk-Agent die Berechnung nicht korrekt abschließen, und Sie erhalten kein Ergebnis. Allerdings wird Ihnen die gesamte für die Berechnungen aufgewendete Zeit in Rechnung gestellt.

Wenn Sie Informationen aus jedem Optimierungsdurchlauf benötigen, senden Sie Frames ohne auf die Festplatte zu schreiben. Um die Verwendung von Dateioperationen in Expert Advisors während der Berechnungen im MQL5 Cloud Network zu vermeiden, können Sie die folgende Prüfung verwenden:

   int handle=INVALID_HANDLE;
   bool file_operations_allowed=true;
   if(MQLInfoInteger(MQL_OPTIMIZATION) || MQLInfoInteger(MQL_FORWARD))
      file_operations_allowed=false;
 
   if(file_operations_allowed)
     {
      ...
      handle=FileOpen(...);
      ...
     }

 

Beschränkungen für die Funktionen im Strategie-Tester #

Es gibt Beschränkungen für einige Funktionen im Strategie-Tester von Client Terminal.

Funktionen Comment(), Print() und PrintFormat() #

Um die Leistung während Optimierung der Parameter von Experten zu erhöhen, werden die Funktionen Comment(), Print() und PrintFormat() nicht ausgeführt. Die Ausnahme ist die Verwendung dieser Funktionen innerhalb des OnInit()-Handlers. Dies erleichtert es, die Ursachen von Fehlern zu suchen, wenn sie auftreten.

Funktionen Alert(), MessageBox(), PlaySound(), SendFTP, SendMail(), SendNotification(), WebRequest() #

Die Funktionen der Interaktion mit der "Außenwelt" Alert(), MessageBox(), PlaySound(), SendFTP(), SendMail(), SendNotification() und WebRequest() werden im Strategie-Tester nicht ausgeführt.

 

Modi Von Tick-Generierung #

Ein Expert Advisor auf MQL5 ist ein Programm, das jedes Mal als Reaktion auf eine äußere Einwirkung - Ereignis - läuft. Für jedes vordefinierte Ereignis hat der EA die Funktion, die diesem Ereignis entspricht - Event-Handler.  

Das wichtigste Ereignis für den Expert Advisor ist eine Preisänderung - NewTick, und deshalb, um Expert Advisors zu testen, müssen wir Tick-Sequenz generieren. Es gibt drei Modi von Tick-Generation im Strategie-Tester von MetaTrader 5 Client-Terminal:

  • Jeder Tick
  • 1 Minute OHLC (OHLC Preise mit 1 Minute-Balken)
  • Nur Eröffnungspreise

Die Grund- und detaillierteste ist der "Jeder Tick"-Modus. Sind die zwei anderen Modi die Vereinfachungen des basis Modus "Jeder Tick". Betrachten wir alle drei Modi, um die Unterschiede zwischen ihnen zu verstehen.

Jeder Tick

Die historische Preisdaten von Finanzinstrumenten werden aus dem Handelsserver an den MetaTrader 5 Client-Terminal in Form von sparsam verpackten Blöcke von 1-Minuten Balken übertragen. Für weitere Informationen über die Abfrage und Bauen der gewünschten Zeitrahmen lesen Sie bitte die Hilfethema Datenzugriff organisieren.

Das minimale Element der Preisgeschichte ist 1-Minute Balken, von dem Sie Informationen über die vier Werte der Preise bekommen können:

  • Open - Preis, zu dem der 1-Minute Balken eröffnet wurde;
  • High - das Maximum, das während dieses 1-Minute Balkens erreicht wurde;
  • Low - das Minimum, das während dieses 1-Minute Balkens erreicht wurde;
  • Close - Schlusspreis des Balkens.

Ein neue1 1-Minute-Balken öffnet nicht beim Start einer neuen Minute (Anzahl der Sekunden ist gleich 0), aber wenn ein Tick kommt - eine Preisänderung mindestens auf einen Punkt. Die Abbildung zeigt den ersten 1-Minute-Balken des neuen Handelswoche, der die Öffnungszeit des 2011.01.10 00:00 Uhr hat. Der Preisunterschied zwischen Freitag und Montag, den wir auf dem Chart sehen, ist weit verbreitet, da Wechselkurse schwankt auch am Wochenende als Reaktion auf eingehende Nachrichten.

new_bar_of_week

Für diesen Balken wir wissen nur, dass der 1-Minute-Balken auf 10 Januar 2011 in 00 Stunden 00 Minuten geöffnet wurde, aber wir wissen nichts über die Sekunden. Er könnte am 00.00.12 oder 00.00.36 (12 oder 36 Sekunden nach dem Start eines neuen Tages) oder jedem anderen Zeitpunkt innerhalb dieser Minute geöffnet worden sein. Aber wir wissen, dass der Open-Preis von EURUSD war 1,28940 bei der Eröffnung des neuen 1-Minute-Balkens.

Ebenso wissen wir nicht die Sekunde, wenn der Tick kamm, der den entsprechenden Schlusskurs dieses 1-Minute-Balkens entspricht. Wir wissen nur das es der letzte Preis auf diesem 1-Minute-Balken ist, der als Close-Preis aufgezeichnet wurde. Für diesen Minuten war der Preis 1,28958. Die Zeit des Auftretens von High- und Low-Preisen ist ebenfalls unbekannt, aber wir wissen, dass die maximalen und minimalen Preisen die Ebenen von 1,28958 und 1,28940 beziehungsweise besucht haben.

Um die Handelsstrategie zu testen, brauchen wir eine Folge von Ticks, auf der die Arbeit des Expert Advisors simuliert wird. Damit für jeden 1-Minute-Balken wissen wir die vier Kontrollpunkte, wo der Preis auf jeden Fall gewesen ist. Wenn der Balken nur 4 Ticks hat, dann sind diese Informationen ausreichend für Testen, aber in der Regel ist Tick-Volumen mehr als 4. Daher ist es notwendig, zusätzliche Kontrollpunkte für Ticks zu generieren, die zwischen den Preisen Open, High, Low und Close kam. Das Prinzip der Generierung von Ticks in der "Jeder Tick"-Modus wird in dem Artikel The Algorithm of Ticks’ Generation within the Strategy Tester of the MetaTrader 5 Terminal, beschrieben, eine Abbildung von denen unten gezeigt ist.

ideal_white_MQL5_2

Beim Testen im "Jeder Tick"-Modus, wird die Funktion OnTick() von EA an jedem Kontrollpunkt aufgerufen. Jeder Kontrollpunkt ist ein Tick vom generierten Sequenz. Der Expert Advisor erhält die Zeit un den Preis des simulierten Ticks, so wie es wäre, wenn Sie online arbeiten.

Wichtig: "Jeder Tick" ist der genauesten Test- Modus, aber zur gleichen Zeit nimmt er am meisten Zeit in Anspruch. Für die erste Auswertung der meisten Handelsstrategien ist in der Regel ausreichend, eine der beiden anderen Test-Modi zu verwenden.

1 minute OHLC

"Jeder Tick" ist ist der genaueste der drei Modi, aber zur gleichen Zeit, ist er der langsamste. Der Lauf der OnTick()-Handler erfolgt bei jedem Tick, während Tick-Volumen ziemlich groß sein können. Für eine Strategie, bei der die Ticksfolge von Kursbewegungen während des Balkens keine Rolle spielt, gibt es ein schneller und rauer Simulationsmodus - "1 Minute OHLC".

Im "1 minute OHLC"-Modus wird Tick-Sequenz nur auf der Basis von OHLC-Preisen von 1-Minute-Balken gebaut, wird die Anzahl der generierten Kontrollpunkte deutlich reduziert - damit die Testzeit auch reduziert. Der Start von OnTick()-Funktion wird auf alle Kontrollpunke gemacht, die auf die Preise OHLC von 1-Minute_Balken gebaut werden.

Die Weigerung, zusätzliche Ticks zwischen den Preisen von Open, High, Low und Close zu generieren, führt zu einer starren Determinismus in der Entwicklung des Preises vom Moment, wenn der Open-Preis bestimmt wird. Dies macht es möglich, einen "Gral des Tests" zu erstellen, der einen schönen aufsteigenden Bilanz-Chart für Tests zeigt. Ein Beispiel von solchem Gral ist in Code Base verfügbar - Grr-al.

graal_OHLC

Die Abbildung zeigt einen sehr attraktiven Chart von Testen dieses Expert Advisors. Wie wird es aufgenommen? Wir wissen 4 Preise für den 1-Minute-Balken, und wir wissen auch, dass der erste Preis ist Open, und der letzte ist Close. Zwischen ihnen sind High und Low, ist die Reihenfolge ihres Auftretens nicht bekannt, aber es ist bekannt, dass der Preis High größer als oder gleich zu Open ist (Low ist kleiner oder gleich dem Preis Open).

Ist ausreichend genug, die Zeit von Erhalt des Open-Preises zu ermitteln, und dann den nächsten Tick zu analysieren, um festzustellen, ob es High oder Low ist. Wenn der Preis liegt unter dem Open-Preis, dann haben wir den Low-Preis - kaufen wir auf diesem Tick, wird der nächste Tick dem High-Preis entsprechen, an denen wir schließen Buy und öffnen Sell. Der nächste Tick ist der letzte, er ist der Close-Preis, und wir schließen den Verkauf (Sell) auf ihn.

Wenn nach dem Preis wir einen Tick mit einem Preis größer als der Open-Preis erhalten, dann ist die Reihenfolge der Trades umgekehrt. Verarbeiten nun einen 1-Minute-Balken in diesem "Cheat"-Modus, und warten auf den nächsten. Bei der Prüfung eines solchen Expert Advisors auf die Geschichte läuft alles gut, aber wenn er online lauft, sehen wir die Wahrheit - die Linie der Balance ist immer noch glatt, aber es geht nach unten. Um diesen Trick zu entlarven, müssen wir einfach den EA in der "Jeder Tick"-Modus ausführen.

Wichtig: Wenn die Testergebnisse von EA in den rauen Test-Modi ("1 Minute OHLC" und "Nur Eröffnungspreise") zu gut scheinen, testen Sie ihn im "Jeder Tick"-Modus.

Nur Eröffnungspreise

In diesem Modus werden Ticks basierend auf den OHLC Preise vom Zeitraum, der für Testen ausgewählt ist, generiert. Die OnTick()-Funktion des Expert Advisors läuft nur am Anfang des Balkens auf dem Open-Preis. Aufgrund dieser Funktion Stopp-Ebenen und erledigten Aufträge können zu nicht angegebenem Preis aktiviert werden (vor allem beim Testen auf höheren Zeitrahmen). Im Gegenzug dafür sind wir in der Lage, einen Expert Advisor schnell zu testen.

Eine Ausnahme bei der Generierung von Ticks im "Nur Eröffnungspreise"-Modus ist die Perioden W1 und MN1: Zeitrahmen für diese Ticks sind für den OHLC Preise jeden Tages generiert, sondern nicht für OHLC Preise der Woche oder des Monats, jeweils.

Zum Beispiel testen wir einen Expert Advisor auf EURUSD H1 im "Nur Eröffnungspreise"-Modus. In diesem Fall ist die Gesamtzahl von Ticks (Kontrollpunkte) nicht mehr als 4*Anzahl der 1-Stunde-Balken, die in der Testenintervall sind. Aber gleichzeitig wird OnTick()-Handler nur an der Öffnung von 1-Stunde-Balken aufgerufen. Auf der anderen (""versteckt" aus dem Expert Advisor) Ticks laufen Prüfungen, die für korrekten Testen notwendig sind:

  • Berechnung der Margin-Anforderungen;
  • Auslösen von Stop Loss und Take Profit Ebenen;
  • Auslösen von erledigten Aufträge;
  • Löschen von abgelaufenen erledigten Aufträge.

Wenn es keine offenen Positionen oder erledigten Aufträge gibt, brauchen wir nicht diese Prüfungen auf versteckten Ticks, und Performance-Gewinn kann erheblich sein. Dieser Modus "Nur Eröffnungspreise" ist gut zum Testen von Strategien, die Deals nur auf der Eröffnung von Balken machen und erledigten Aufträge nicht verwenden, und auch verwenden sie nicht StopLoss, TakeProfit. Für die Klasse solcher Strategien bleibt alle notwendigen Genauigkeit von Tests.

Verwenden wir Moving Average Expert Advisor aus dem Standard-Paket als ein Beispiel für einen EA, die in jedem Modus getestet werden kann. Die Logik dieses EAs ist so, dass alle Entscheidungen bei der Eröffnung des Balkens und Deals werden sofort ausgeführt, ohne die Verwendung von erledigten Aufträge gemacht. Starten wir Testen auf EURUSD H1 im Intervall von 2010.01.09 bis 2010.31.12 un vergleichen wir die Charts. Die Abbildung zeigt Bilanz-Charts aus dem Tester-Bericht für alle drei Modi.

Chart des Testens von Moving Average.mq5 aus dem Standard-Paket abhängt nicht von Testentyp.

Wie Sie sehen können Charts auf den verschiedenen Modi des Tests sind die gleichen für den EA Moving Average.

Es gibt mehrere Einschränkungen des Modes "Nur Eröffnungspreise":

  • Sie können nicht Handelsregime "zufällige Verzögerung " verwenden;
  • Im EA können Sie die Daten am Zeitrahmen, der niedriger als der für die Tests/Optimierung eingesetzte Zeitrahmen ist, nicht verwenden. Zum Beispiel, wenn der Test / Optimierung auf Zeitraum H1 durchgeführt wird, können Sie Zugriff auf die Daten von H2, H3, H4, etc. haben, nicht aber auf die Daten M30, M20, M10, etc. Darüber hinaus älteren Zeiträumen, die aufgerufen sind, müssen ein Vielfaches des Test-Zeitrahmens sein. Zum Beispiel, wenn beim Testen auf M20 können Sie nict M30 zugreifen, aber die Daten aus H1 sind verfügbar. Diese Einschränkungen sind aufgrund der Unfähigkeit, Daten von unteren und nicht multiplen Zeitrahmen von die Balken, die während des Test/der Optimierung generiert werden, zu erhalten.
  • Einschränkungen beim Zugriff auf Daten anderer Zeitrahmen auch auf andere Symbole, deren Daten im Expert Advisor verwendet werden, gelten. In diesem Fall ist die Begrenzung für jedes Symbol von dem ersten Zeitrahmen abhängig, der während des Tests/der Optimierung aufgetreten ist. Z. B. die wir testen auf das Symbol und die Periode EURUSD H1, der EA greift Daten von GBPUSD M20 für das erste Mal. In diesem Fall ist der EA in der Lage, weitere Daten EURUSD H1, H2, usw. zu verwenden, sowie GBPUSD M20, H1, H2 usw.

Wichtig: "Nur Eröffnungspreise"-Modus ist der schnellste, aber er kann nicht für alle Trading-Strategien verwendet sein. Wählen Sie den gewünschten Test-Modus basiert auf die Eigenschaften des Handelssystems.

Am Ende des Abschnitts über die Modellierung Modi geben wir einen visuellen Vergleich der verschiedenen Arten der Generierung von Ticks für EURUSD für zwei Balken M15 auf dem Intervall 2011.01.11 21:00:00 - 2011.01.11 21.30.00. Die Ticks wurden in verschiedene Dateien mit Hilfe vom Expert Advisor WriteTicksFromTester.mq5 gespeichert, und das Ende der Namen dieser Dateien sind in input-Parametern filenamEveryTick, filenameOHLC und filenameOpenPrice angegeben.

EA_inputs_in_tester

Um drei Dateien mit drei Tick-Sequenzen (für jeden der Modi "Jeder Tick", "1 Minute OHLC" und "Nur Eröffnungspreise") zu erhalten, wurde der Expert Advisor dreimal in den etsprechenden Modi mit der einzelnen Läufe gestartet. Dann wurden die Daten aus diesen drei Dateien mit Indikator TicksFromTester.mq5 auf dem Chart gezeigt. Indikator-Code wird an diesem Artikel angebracht.

three_tick_series

Standardmäßig werden alle Dateioperationen in MQL5 Sprache innerhalb von "Datei-Sandbox" gemacht, und beim Testen kann der Expert Advisor nur eigene "Dateisystem-Sandbox" zugreifen. Um der Indikator und der EA beim Test mit Dateien von einem Ordner arbeiten könnten, verwendeten wir die Flagge FILE_COMMON. Ein Beispiel-Code aus dem EA:

//--- Datei öffnen
   file=FileOpen(filename,FILE_WRITE|FILE_CSV|FILE_COMMON,";");
//--- Den Erfolg der Operation überprüfen
   if(file==INVALID_HANDLE)
     {
      PrintFormat("Datei %s konnte nicht für Schreiben geöffnet werden. Fehlercode=%d",filename,GetLastError());
      return;
     }
   else
     {
      //--- Informieren wir über das Schreiben in den Ordner von allen Client-Terminals, und auch seinen Speicherort
      PrintFormat("Die Datei wird im Ordner %s geschrieben",TerminalInfoString(TERMINAL_COMMONDATA_PATH));
     }

Im Indikator beim Datenlesen haben wir auch Flagge FILE_COMMON verwendet. Dies erlaubte uns, manuelle Übertragung der notwendigen Dateien von einem Ordner zum anderen zu vermeiden.

//--- Datei öffnen
   int file=FileOpen(fname,FILE_READ|FILE_CSV|FILE_COMMON,";");
//--- Den Erfolg der Operation überprüfen
   if(file==INVALID_HANDLE)
     {
      PrintFormat("Datei %s konnte nicht für Lesen geöffnet werden. Fehlercode=%d",fname,GetLastError());
      return;
     }
   else
     {
      //--- Informieren über den Speicherort des freigegebenen Ordners von allen Client-Terminals
      PrintFormat("Die Datei wird aus dem Ordner %s gelesen werden",TerminalInfoString(TERMINAL_COMMONDATA_PATH));
     }

Simulation von Spread #

Die Differenz zwischen den Preisen Bid und Ask wird Spread genannt. Beim Testen wird der Spread nicht modelliert, sondern wird er aus historischen Daten genommen. If the spread is less than or equal to zero in the historical data, then the last known (at the moment of generation) spread  of is used by testing agent.

Im Tester ist Spread immer schwimmend. D.h. SymbolInfoInteger(symbol, SYMBOL_SPREAD_FLOAT) gibt immer true zurück.

Darüber hinaus werden in historische Daten Werte von Tick- und Handelsvolumen gespeichert. Für das Speichern und Abrufen von Daten verwenden wir eine spezielle MqlRates:

struct MqlRates
  {
   datetime time;         // Balken Öffnungszeit
   double   open;         // Open-Preis
   double   high;         // High-Preis
   double   low;          // Low-Preis
   double   close;        // Close-Preis
   long     tick_volume;  // Tick-Volumen
   int      spread;       // Spread
   long     real_volume;  // Markt-Volumen
  };

Verwendung realer Ticks beim Testen #

Das Testen und die Optimierung anhand realer Ticks sind besonders nah an den realen Bedingungen. Statt der anhand Minutendaten generierten Ticks werden reale Ticks verwendet, die vom Broker gespeichert wurden. Dies sind die Ticks von Börsen und Liquiditätsanbietern.

Um maximale Genauigkeit beim Testen zu gewährleisten, werden auch Minutenbalken im Modus "Anhand realer Ticks" verwendet. Anhand der dieser Balken werden die Tickdaten überprüft und korrigiert. Darüber hinaus kann man auf solche Weise Abweichungen der Charts im Tester und im Kundenterminal voneinander vermeiden.

Der Tester überprüft die Übereinstimmung der Tickdaten mit den Parametern eines Minutenbalkens: der Tick darf nicht die High/Low Levels des Balkens überschreiten; der Tick, der eine Minute eröffnet und schließt, muss mit den Open/Close Preisen des Balkens übereinstimmen. Die Volumina werden auch miteinander verglichen. Wenn eine Unstimmigkeit festgestellt wird, werden alle Ticks, die diesem Minutenbalken entsprechen, fortgelassen. Statt dieser Ticks werden erzeugte Ticks verwendet (wie im "Alle Ticks" Modus).

Wenn in der Historie eines Symbols ein Minutenbalken vorhanden ist, die Tickdaten für diese Minute aber nicht vorliegen, generiert der Strategietester die Ticks im Modus "Alle Ticks". Dies erlaubt es, einen korrekten Chart im Falle unvollständiger Tickdaten zu zeichnen.

Wenn in der Historie eines Symbols kein Minutenbalken vorhanden ist, die Tickdaten für diese Minute aber vorliegen, können sie im Strategietester verwendet werden. Die Balken von Börsensymbolen werden zum Beispiel nach Last Preisen gebildet. Wenn vom Server nur Ticks mit Bid/Ask Preisen ohne Last Preis eintreffen, wird der Balken nicht gebildet. Der Strategietester wird diese Tickdaten verwenden, weil sie den Minutendaten nicht widersprechen.

Die Tickdaten können aus unterschiedlichen Gründen nicht mit den Minutenbalken übereinstimmen. Zum Beispiel infolge einer Unterbrechung der Verbindung oder anderer Störungen bei der Übertragung der Daten von einer Quelle ins Kundenterminal. Beim Testen gelten Minutenbalken als genauer und verlässlicher.

Beim Testen anhand realer Ticks sind die folgenden Besonderheiten zu berücksichtigen:

  • Beim Starten eines Tests werden nicht nur Tickdaten, sondern auch Minutendaten eines Symbols synchronisiert.
  • Die Ticks werden im Cache des Symobols im Tester gespeichert. Die Cache-Größe beträgt max. 128 000 Ticks. Beim Eintreffen neuer Ticks werden die ältesten Ticks aus dem Cache entfernt. Allerdings kann man mithilfe der CopyTicks Funktions auch die Ticks erhalten, die außerhalb des Cache liegen (nur beim Testen anhand realer Ticks). In diesem Fall werden die Daten aus der Datenbank von Ticks im Strategietester abgerufen, die mit der jeweiligen Datenbank im Kundenterminal übereinstimmt. In der Datenbank werden keine Korrekturen anhand der Minutenbalken vorgenommen. Aus diesem Grund können sich diese Ticks von den Ticks im Cache unterscheiden.

Globale Variablen des Client-Terminals #

Beim Testen werden globale Variablen, des Client-Terminals auch emuliert, aber sie werden nicht mit echten globalen Variablen des Terminals, die können im Terminal auf der Taste F3 gesehen werden, verbunden. Dies bedeutet, dass alle Operationen mit globalen Variablen beim Testen ausserhalb des Terminals hergestellt werden (in der Test-Agent).

Berechnung von Indikatoren beim Testen #

Im Echtzeitmodus werden die Indikatorwerte bei jedem Tick berechnet.

Im Strategietester werden die Indikatoren nur dann berechnet, wenn auf die Daten zugegriffen wird, d.h. wenn Indikatorpufferwerte angefordert werden. Die einzigen Ausnahmen sind nutzerdefinierte Indikatoren mit der Direktive #property tester_everytick_calculate. In diesem Fall wird bei jedem Tick eine Neuberechnung durchgeführt.

Im visuellen Testmodus werden alle Indikatoren beim Eintreffen eines neuen Ticks bedingungslos neu berechnet, um im visuellen Testchart korrekt angezeigt zu werden.

Der Indikator wird einmal pro Tick berechnet. Alle nachfolgenden Anfragen nach Indikatordaten führen erst dann zu einer Neuberechnung, wenn ein neuer Tick eintrifft. Wenn also der Timer in einem EA über die Funktion EventSetTimer() aktiviert ist, werden die Indikatordaten ab dem letzten Tick vor jedem Aufruf von OnTimer() angefordert. Wenn der Indikator zum letzten Tick noch nicht berechnet wurde, werden die Berechnungen der Indikatorwerte gestartet. Wurden die Daten bereits vorbereitet, werden sie ohne Neuberechnung bereitgestellt.

Somit werden alle Indikatorberechnungen auf die ressourcenschonendste Art und Weise durchgeführt — wenn der Indikator zu einem bestimmten Tick bereits berechnet wurde, werden seine Daten "wie sie sind" bereitgestellt. Es wird keine Neuberechnung gestartet.

Herunterladen von Geschichte beim Testen #

Die Geschichte eines getesteten Symbols wird vor dem Testprozess synchronisiert und durch das Terminal aus dem Handel-Server geladen. In der ersten Zeit, lädt das Terminal alle verfügbaren Geschichte eines Symbols. Weiterhin werden nur die neuen Daten geladen.

Test-Agent erhält Geschichte des getesteten Symbols vom Terminal unmittelbar nach dem Start von Testen. Wenn Daten von anderen Instrumenten in den Testprozess verwendet werden (zum Beispiel, es ist ein Multi-Currency-Expert Advisor), dann erfordert der Test-Agent Geschichte aus dem Terminal beim ersten Anruf zu solchen Daten. Wenn historische Daten zur Verfügung am Terminal sind, wurden sie sofort an die Test-Agenten übertragen. Wenn Daten nicht verfügbar sind, lädt das Terminal sie vom Server und dann übergibt sie an Agenten.

Daten von zusätzlichen Instrumenten werden auch zur Berechnung von Cross-Rates für den Handelsoperationen erforderlich. Zum Beispiel, wenn beim Testen einer Strategie auf EURCHF mit Depot-Währung in USD, vor der Verarbeitung des ersten Handeloperation fordert der Agent historische Daten von EURUSD und USDCHF aus dem Terminal, obwohl die Strategie enthält keine direkten Aufruf von diesen Symbolen.

Vor dem Testen einer Multi-Currency-Strategie, empfiehlt es sich, alle notwendigen historischen Daten auf dem Terminal herunter zu laden. Dies wird dazu beitragen, Verzögerungen von Tests/Optimierung auf Grund des Download der erforderlichen Daten zu vermeiden. Zum Beispiel können Sie die Geschichte durch das Öffnen des entsprechenden Charts und Scrollen ihn zu Beginn der Geschichte herunterladen. Ein Beispiel für gezwungenen Download der Geschichte in Terminal ist in der MQL5 Dokumentationabschnitt Datenzugriffsanordnung gegeben.

Test-Agenten empfangen Geschichte vom Terminal in der verpackten Form. Während des nächsten Testen, lädt Tester nicht Geschichte aus dem Terminal, weil die erforderlichen Daten seit dem letzten Lauf des Testers verfügbar sind.

  • Das Terminal lädt die Geschichte aus dem Handelsserver nur einmal, wenn der Agent die Geschichte für das testierte Symbol aus dem Terminal zum ersten Mal anfordert. Die Geschichte wird in gepackter Form geladen, um den Verkehr zu reduzieren.
  • Ticks werden nicht über das Netzwerk gesendet, werden sie auf Tester-Agenten generiert.

Multi-Currency-Testen #

Mit dem Tester können Sie Strategien, die auf mehreren Instrumenten handeln, auf der Geschichte überprüfen. Diese Experten werden herkömmlicherweise als Multi-Währungs-EA bezeichnet, da in den vorherigen Plattformen Test für nur ein Instrument durchgeführt wurde. MetaTrader 5 Tester kann auch Handel Handel über alle verfügbaren Instrumente simulieren.

Geschichte der verwendeten Instrumente wird vom Tester aus dem Client-Terminal (nicht aus dem Handelsserver!) automatisch beim ersten Aufruf an das Instrument heruntergeladen.

Der Agent lädt nur fehlende Geschichte mit einer geringen Marge, um die notwendigen Daten über die Geschichte für die Berechnung von Indikatoren zu Beginn des Tests zu haben. Die minimale Geschichten beim Download aus dem Handelsserver für Zeitrahmen D1 und weniger ist ein Jahr. Wenn daher das Testen auf dem Intervall  2010.11.01-2010.12.01 (mit jeweils einem Monat als Intervall)  mit der Periode von M15 (jede Bar ist gleich 15 Minuten) gestartet wird, wird die Geschichte des Instrumentes von dem Terminal für das gesamte Jahr 2010 angefordert. Für den Zeitrahmen Weekly wird die Geschichte von 100 Bars angefordert, die ungefähr zwei Jahre ist (52 Wochen pro Jahr). Für das Testen auf einer monatlichen Zeitrahmen Monthly wird der Agent die Geschichte für 8 Jahre (12 Monate * 8 Jahre = 96 Jahre) anfordern.

Wenn aus irgendwelchen Gründen die für das Testen notwendige Reserve der Bars vor dem Anfang des Testens nicht versorgt werden kann, wird das Anfangsdatum des Testens von der Vergangenheit bis zur Gegenwart automatisch geschoben, um solche Reserve zu gewährleisten.

Beim Testen wird auch "Markt Durchsicht" emuliert, in der man die Informationen über Instrumente erhalten kann. Standardmäßig gibt es am Anfang des Testens nur ein Symbol im "Markt Durchsicht" Tester - das Symbol, auf dem das Testen gestartet wurde. Alle notwendigen Symbole werden zum "Markt Durchsicht" Tester (nicht Terminal!) automatisch beim Zugriff verbunden.

Vor dem Anfang des Testens eines Multi-Currency-Expert Advisors ist es notwendig die für das Testen erforderlichen Instrumente im " Markt Durchsicht" des Terminals auszuwählen und die erforderlichen Daten zu laden. Wenn Sie zum ersten Mal auf das fremde Symbol zugreifen, wird Daten dieses Symbols zwischen dem Test-Agenten und dem Client-Terminal automatisch synchronisiert. Das "fremde" Symbol - ist ein Symbol, das anders ist als dasjenige, auf dem das Testen gestartet wurde.

Der Zugriff auf das Daten des fremden Symbols erfolgt in den folgenden Fällen:

  • Anforderung an Zeitreihen nach Symbol/Zeitrahmen durch die Funktionen:

Wenn Sie zum ersten Mal auf das fremde Symbol zugreifen, wird der Prozess des Testens gestoppt und die Geschichte von Symbol/Zeitrahmen vom Terminal auf dem Test-Agenten heruntergeladen. Gleichzeitig wird die Generierung einer Folge von Ticks für dieses Symbol aktiviert.

Für jedes Instrument wird seine eigene Folge von Ticks in Übereinstimmung mit dem gewählten Modus der Generierung von Ticks generiert. Ausserdem können Sie auch die Geschichte für die notwendigen Symbolen durch den Aufruf von der Funktion SymbolSelect () im Handler OnInit () anfordern - Die Geschichte wird unmittelbar vor dem Testen des Expert Advisors geladen.

Um das Multi-Currency-Testen im Client-Terminal MetaTrader 5 zu durchführen, ist es nicht erforderlich zusätzliche Anstrengungen zu unternehmen. Wir müssen nur die Charts der entsprechenden Instrumente im Client-Terminal öffnen. Die Geschichte der notwendigen Symbole wird automatisch vom Hadels-Server geladen, sofern die Daten darauf sind.

Simulation der Zeit im Tester #

Beim Testen ist die lokale Zeit TimeLocal() immer gleich der Server-Zeit TimeTradeServer(). Im Gegenzug ist die Server-Zeit immer gleich der Zeit, die der GMT - TimeGMT()entspricht. Somit zeigen alle diese Funktionen beim Testen die gleiche Zeit.

Das Fehlen der Unterschied zwischen GMT, lokale und Server Zeit wurde in dem Tester bewusst gemacht, weil die Verbindung zum Server nicht immer hergestellt werden kann. Und die Ergebnisse des Testens sollen identisch sein, unabhängig davon, ob es die Verbindung gibt oder nicht. Information über die Zeit der Server wird nicht lokal aufbewahren, sondern wird vom Server geholt.

Grafische Objekte beim Testen #

Während des Testens / Optimierung wird die Konstruktion von grafischen Objekten nicht ausgeführt. Wenn man auf die Eigenschaften des geschaffenen Objektes während des Testens / Optimierung zugreift, erhält der Expert Advisor einen Nullwert.

Diese Einschränkung gilt nicht für das Testen im visuellen Modus.

OnTimer()-Funktion im Tester #

MQL5 bietet die Möglichkeit die Ereignisse des Timers zu bearbeiten. Der Handler OnTimer() wird unabhängig von Modus des Testens aufgerufen. Dies bedeutet, dass, wenn das Testen im Modus "Nur Eröffnungspreise" auf den Zeitraum H4 gestartet wird und innerhalb des Expert Advisors wird einen Timer gestellt, der jede Sekunde aufruft, dann wird der Handler onTick () auf der Eröffnung jedes H4 Balkens einmal aufgerufen und der Handler OnTimer () wird während des Balkens 14.400-mal (3600 Sekunden * 4.00 Stunden ) aufgerufen. Soviel die Zeit des Testens des Expert Advisors dabei zunehmen wird, hängt von der Logik des Expert Advisors ab.

Um die Abhängigkeit der Zeit des Testens von der vorgegebenen Frequenz des Timers zu überprüfen, wurde ein einfacher Expert Advisor ohne Handelsoperationen geschrieben.

//--- input parameters
input int      timer=1;              // Timerwert, Sek
input bool     timer_switch_on=true; // Timer ist aktiviert
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- Timer läuft wenn  timer_switch_on==true
   if(timer_switch_on)
     {
      EventSetTimer(timer);
     }
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- stoppen den Timer
   EventKillTimer();
  }
//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
//---
// unternehmen wir nichts,der Körper des Handlers ist leer
  }
//+------------------------------------------------------------------+

Die Zeit des Testens wurde bei verschiedenen Werten des Parameter von Timer (Periodizität des Ereignisses Timer) gemessen. Auf den erhaltenen Daten ist der Chart der Abhängigkeit der Zeit des Testens T von der Wert der Periodizität Period gebaut.

Time_Dependence

Es ist deutlich zu erkennen, je geringer der Parameter Timer bei der Initialisierung durch Funktion EventSetTimer(Timer) ist, desto weniger ist der Zeitraum (Period) zwischen den Aufrufen der Handler OnTimer (), und desto mehr ist die Zeit des Testens T unter den gleichen anderen Bedingungen.

Sleep()-Funktion im Tester #

Die Funktion Sleep() ermöglicht es Ihnen, im Expert Advisor oder Script die Ausführung des mql5-Programms für eine Zeitlang bei der Arbeit auf dem Chart auszusetzen. Dies kann nützlich sein wenn Sie irgendwelche Daten, die zum Zeitpunkt der Anfrage noch nicht verfügbar sind, anfordern und Sie müssen warten, bis sie bereit sind. Das ausführliche Beispiel der Nutzung der Funktion Sleep () können Sie im Abschnitt Datenzugriff organisieren finden.

Im Tester halten die Aufrufe Sleep () den Prozess des Testens nicht auf. Beim Aufruf von Sleep() werden die generierten Ticks innerhalb der angegebenen Verzögerung "gespielt", infolgedessen können offene Aufträge, Stops usw auslösen. Nach dem Aufruf Sleep () verlängert sich die im Tester simulierte Zeit in einem Intervall, das im Parameter der Funktion Sleep angegeben ist.

Wenn als Ergebnis der Ausführung der Funktion Sleep () die aktuelle Zeit im Tester über den Zeitraum des Testens hinausgeht, dann erhalten Sie eine Fehlermeldung ' Endlosschleife in Sleep '. Wenn Sie diese Fehlermeldung erhalten, die Ergebnisse des Testens nicht abgelehnt werden. Alle Berechnungen werden in ihrem vollen Umfang (die Anzahl der Deals, Drawdown, etc.) durchgeführt und die Ergebnisse dieses Tests werden auf dem Terminal weitergegeben.

Die Funktion Sleep () wird in OnDeinit () nicht funktionieren, da nach ihrem Aufruf die Zeit des Testens das Intervall des Testens garantiert übertreffen wird .

Das Schema der Verwendung von Funktion Sleep () im Tester des Terminals MetaTrader 5.

Verwenden des Testers für Optimierungsprobleme in mathematischen Berechnungen #

Der Tester im MetaTrader 5-Terminal kann nicht nur für das Testen der Handelsstrategien, sondern auch für mathematische Berechnungen verwendet werden. Dafür muss man in den Einstellungen den entsprechenden Modus wählen:

math_calculations

Wenn Sie den Modus "Mathematische Berechnungen" wählen, wird der Test-Agent "leer" laufen. Der leerer Lauf bedeutet, dass Generierung der Ticks und Herunterladen der Geschichte nicht durchgeführt werden. Bei solchem Lauf werden nur drei Funktionen aufgerufen: OnInit(), OnTester(), OnDeinit().

Wenn das Enddatum des Testens kleiner oder gleich dem Anfangsdatum des Testens ist, so bedeutet es, dass die Testens im Modus "Matematische Berechnungen" durchgeführt werden.

Wenn der Tester für Lösung der mathematischen Aufgaben verwendet wird, wird die Geschichte nicht heruntergeladen und die Ticks werden nicht generiert.

Eine typische mathematische Aufgabe für die Lösung im Tester MetaTrader 5 - die Suche nach einem Extremum einer Funktion mit vielen Variablen. Um sie zu lösen, müssen Sie folgendes tun:

  • Legen Sie einen Berechnungsblock der Funktionswerten von mehreren Variablen in OnTester() und geben Sie den berechneten Wert durch return(Wert_der Funktion) zurück;
  • Übertragen Sie die Parameter der Funktion auf die globalen Reichweite des Programms als input-Variablen;

Kompilieren wir den Expert Advisor, öffnen wir das Fenster "Tester". Auf der Registerkarte "Eingabeparameter" wählen wir die erforderlichen Input Variablen und definieren wir für sie die Reihe von Parameterwerten und den Schritt für das Durchprobieren.

Wählen wir den Typ der Optimierung - "Langsam( vollständige Suche der Parameter)" oder - "Schnell (genetischer Algorithmus)". Für eine einfache Suche des Extremums der Funktion ist es besser die schnelle Optimierung zu wählen, aber wenn man die Werte für die ganze Reihe von Variablen ausrechnen muss, dann ist es am besten die langsame Optimierung zu verwenden.

Wählen wir den Modus "Mathematische Berechnungen" und klicken wir auf "Start" um den Optimierungsprozess zu starten. Beachten Sie, dass bei der Optimierung immer das lokale Maximum des Wertes von der Funktion OnTester gesucht wird. Für die Suche lokalen Minimums kann man das Inverse des ausgerechneten Wertes der Funktion aus der Funktion OnTester zurückgeben:

return(1/Wert_der Funktion);

Dabei muss man selbständig überprüfen, dass der Wert_der Funktion null nicht gleich ist, sonst man kritischen Fehler der Division durch Null erhalten kann. Es gibt noch eine andere Option, die bequemer ist und verzerrt die Ergebnisse der Optimierung nicht, sie wurde von den Lesern des Artikels vorgeschlagen:

return(-Wert_der Funktion);

In dieser Option muss man der Wert_der Funktion auf Gleichheit mit Null nicht überprüfen und die Oberfläche der Optimierungsergebnisse in 3D-Darstellung selbst hat die gleiche Form, die nur von der ersten Option gespiegelt ist.

Verwenden wir die Funktion sink() als Beispiel:

sink_formula

Stellen wir den Code des Expert Advisors für die Suche des Extremums dieser Funktion in OnTester():

//+------------------------------------------------------------------+
//|                                                         Sink.mq5 |
//|                        Copyright 2011, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
//--- input parameters
input double   x=-3.0; // start=-3, step=0.05, stop=3
input double   y=-3.0; // start=-3, step=0.05, stop=3
//+------------------------------------------------------------------+
//| Tester function                                                  |
//+------------------------------------------------------------------+
double OnTester()
  {
//---
   double sink=MathSin(x*x+y*y);
//---
   return(sink);
  }
//+------------------------------------------------------------------+

Durchführen wir eine Optimierung und stellen wir die Ergebnisse der Optimierung in Form von 2D Chart vor.

Die Ergebnisse der vollständigen Optimierung der Funktion sink(x*x+y*y) in Form von 2D Chart.

Je besser der Wert für ein angegebenes Paar von Parametern (x, y) ist, desto gesättigter ist die Farbe. Wie es aus der Sicht der Formel der Funktion sink() erwartet wurde, deren Wert konzentrische Kreise mit Mittelpunkt bei (0,0) bildet. Für die Funktion sink () existiert kein absolutes Extremum. Es ist bei der Anzeige der Ergebnisse der Optimierung im 3D-Modus gut sichtbar:

3d

Synchronization von Balken beim Testen in "Open Prices Only"-Modus #

Der Tester im MetaTrader 5 Client-Terminal ermöglicht es Ihnen so genannte "Multi-Currency" Expert Advisors zu überprüfen. Ein Multi-Currency-Expert Advisor ist ein Expert Advisor, der auf zwei oder mehr Symbole handelt.

Das Testen der Strategien, die auf einigen Instrumenten handeln, legt einige zusätzliche technische Anforderungen an den Tester:

  • Die Generierung der Ticks für diese Instrumenten;
  • Die Berechnung der Indikatorwerte für diese Instrumenten;
  • Berechnung der Margin-Anforderungen für diese Instrumenten;
  • Die Synchronization der generierten Ticksfolgen für alle Handelsinstrumenten.

Der Tester generiert und spielt eine Tick-Sequenz für jedes Instrument in Übereinstimmung mit dem ausgewählten Modus des Handels. Dabei wird eine neue Barfür jedes Instrument geöffnet, unabhängig davon, wie die Bar auf anderem Instrument geöffnet wurde. Dies bedeutet, dass beim Testen des Multi-Currency-Expert Advisors die Situation (meistens ist es der Fall)auftreten kann, wenn eine neue Bar für ein Instrument bereits geöffnet wurde und noch nicht für die anderen. So passiert alles beim Testen genauso wie im wirklichen Leben.

Solche authentische Simulation der Geschichte im Tester verursacht keine Probleme, solange die Modi "Jeder Tick" und "1 Minute OHLC" des Testens verwendet werden. Bei diesen Modi wird eine ausreichende Anzahl von Ticks innerhalb einer Kerze generiert, um den Moment der Synchronisation der Bars von verschiedenen Symbolen erwarten zu können. Aber wie kann man die Multi-Currency-Strategien im Modus "Nur Eröffnungspreise" testen, wenn die Bars auf Handelsinstrumente zwingend synchronisiert werden muss? In diesem Modus wird der Expert Advisor nur auf einen Tick aufgerufen, der der Öffnungszeit der Bar entspricht.

Wir erklären nun am Beispiel: Wenn wir den Expert Advisor auf das Symbol EURUSD testen, und auf EURUSD wurde eine neue stündliche Kerze geöffnet, dann erfahren wir leicht diese Tatsache - beim Testen im Modus "Nur Eröffnungspreise" entspricht das Ereignis NewTick dem Moment der Eröffnung der Bar auf den Zeitraum des Testens. Aber dabei gibt es keine Garantie, dass die neue Kerze nach dem Symbol GBPUSD geöffnet wurde, das im Expert Advisor verwendet wird.

Unter gewöhnlichen Umständen ist es ausreichend genug die Arbeit der Funktion OnTick() zu beenden und das Erscheinen einer neuen Bar auf USDJPY auf dem nächsten Tick zu überprüfen. Aber beim Testen im Modus "Nur Eröffnungspreise" wird es kein anderer Tick sein, und so mag es scheinen, dass dieses Modus für das Testen des Currency-Expert Advisors nicht passt. Aber das ist nicht so - vergessen Sie nicht, dass sich der Tester in MetaTrader 5 genauso wie im wirklichen Leben verhält. Sie können warten, bis eine neue Bar auf einem anderen Symbole mittels Funktion Sleep() geöffnet wird!

Der Code des Expert Advisors Synchronize_Bars_Use_Sleep.mq5, der ein Beispiel der Synchronization der Bars beim Testen im Modus "Nur Eröffnungspreise" zeigt.

//+------------------------------------------------------------------+
//|                                   Synchronize_Bars_Use_Sleep.mq5 |
//|                        Copyright 2011, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
//--- input parameters
input string   other_symbol="USDJPY";
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- nachprüfen wir das aktuelle Symbol
   if(_Symbol==other_symbol)
     {
      PrintFormat("Man muss ein anderes Symbol angeben oder starten Sie das Testen auf dem anderen Symbol!");
      //--- stoppen wir das Testen des Expert Advisors zwangsmäßig
      return(INIT_PARAMETERS_INCORRECT);
     }
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//--- statistische Variable für die Speicherung der Zeit der Öffnung der letzten Bar
   static datetime last_bar_time=0;
//---  das Merkmal der Synchronisation der Öffnungszeit der letzten Bar auf verschiedenen Symbolen ist synchronisiert
   static bool synchonized=false;
//--- wenn statische Variable ist nicht initialisiert
   if(last_bar_time==0)
     {
      //--- es ist ein erster Aufruf, speichern wir die Öffnungszeit und verlassen ihn
      last_bar_time=(datetime)SeriesInfoInteger(_Symbol,Period(),SERIES_LASTBAR_DATE);
      PrintFormat("Variable wird mit dem Wert %s initialisiert",TimeToString(last_bar_time));
     }
//--- erhalten wir die Öffnungszeit der letzten Bar nach unserem Symbol
   datetime curr_time=(datetime)SeriesInfoInteger(Symbol(),Period(),SERIES_LASTBAR_DATE);
//--- wenn die Zeit der Öffnung der aktuellen Bar ist nicht gleich der Zeit, die gespeichert in last_bar_time
   if(curr_time!=last_bar_time)
     {
      //--- speichern wir die Öffnungszeit der neuen Bar in statistischer Variable
      last_bar_time=curr_time;
      //--- nicht synchroniesiert
      synchonized=false;
      //--- geben wir die Meldung über dieses Ereignis aus
      PrintFormat("Auf dem Symbol %s wurde eine neue Bar in %s geöffnet",_Symbol,TimeToString(TimeCurrent()));
     }
//--- hier werden wir die Öffnungszeit der Bar auf dem fremden Symbol speichern
   datetime other_time;
//--- Schleife bis die Öffnungszeit des letzten Bars nach anderem Symbol wird gleich der curr_time
   while(!(curr_time==(other_time=(datetime)SeriesInfoInteger(other_symbol,Period(),SERIES_LASTBAR_DATE)) && !synchonized))
     {
      PrintFormat("Warten Sie 5 Sekunden..");
      //--- warten Sie 5 Sekunden und anfordern Sie noch einmal SeriesInfoInteger(other_symbol,Period(),SERIES_LASTBAR_DATE)
      Sleep(5000);
     }
//--- die Öffnungszeit der Bar ist gleich für beide Symbole
   synchonized=true;
   PrintFormat("Die Öffnungszeit der letzten Bar auf dem Symbol %s ist: %s",_Symbol,TimeToString(last_bar_time));
   PrintFormat("Die Öffnungszeit der letzten Bar auf dem Symbol %s ist: %s",other_symbol,TimeToString(other_time));
//--- TimeCurrent() passt nicht, verwenden wir TimeTradeServer() für
   Print("Die Bars wurden synchronisiert um,TimeToString(TimeTradeServer(),TIME_DATE|TIME_SECONDS));
  }
//+------------------------------------------------------------------+

Beachten Sie die letzte Zeile im Handler, die die aktuelle Zeit anzeigt, wenn die Tatsache der Synchronisation festgestellt wurde:

   Print("Die Bars wurden synchronisiert um ",TimeToString(TimeTradeServer(),TIME_SECONDS));

Um die aktuelle Uhrzeit anzuzeigen, verwendeten wir die Funktion TimeTradeServer(), und nicht TimeCurrent(). Es geht darum, dass die Funktion TimeCurrent () die Zeit des letzten Ticks zurückgibt, die sich nach der Verwendung von Sleep() auf keine Weise geändert hat. Starten Sie den Handler im Modus "Nur Eröffnungspreise" und Sie erhalten die Meldungen über Synchronization der Bars.

Synchronize_Bars_Use_Sleep_EA

Verwenden Sie die Funktion TimeTradeServer () anstelle von TimeCurrent (), wenn Sie die aktuelle Serverzeit und nicht die Eingangszeit des letzten Ticks erhalten möchten.

Es gibt einen anderen Weg die Bars zu synchronisieren - mit Hilfe eines Timers. Ein Beispiel solchen Expert Advisors ist Synchronize_Bars_Use_OnTimer.mq5, der dem Artikel beigefügt ist.

IndicatorRelease()-Funktion im Tester #

Nach dem Abschluss des einzelnen Testens wird ein Chart des Instrumentes automatisch geöffnet, auf dem die abgeschlossenen Deals und die Indikatoren angezeigt werden, die in Expert Advisor verwendet wurden. Das hilft die Momente des Eingangs und des Ausgangs optisch zu überprüfen und sie mit den Werten der Indikatoren zu vergleichen.

Hinweis: Die Indikatoren, die auf dem automatisch geöffneten Chart nach der Durchführung des Testens angezeigt werden, werden nach Beendigung des Testens neu berechnet. Auch wenn diese Indikatoren wurden in dem getesteten Expert-Advisor verwendet.

Aber in einigen Fällen benötigt der Programmierer die Informationen über die im Handelsalgorithmus mitwirkenden Indikatoren auszublenden. Zum Beispiel, wird der Code des Experten vermietet oder wird als Ausführungsdatei ohne Quellcode verkauft. Für diese Ziele ist die Funktion IndicatorRelease() geeignet.

Wenn im Terminal die Schablone mit dem Namen tester.tpl im Verzeichnis /profiles/templates des Client-Terminals angegeben wird, dann wird sie zum geöffneten Chart verwendet werden. In ihrer Abwesenheit wird die Standard-Schablone angewendet (default.tpl).

Die Funktion IndicatorRelease () wird für die Befreiung von Berechnungen des Indikators verwendet, wenn es nicht mehr nötig ist. So können Sie sowohl Speicherplatz als auch Prozessor-Ressourcen sparen, denn jeder Tick verursacht die Berechnung des Indikators. Ihr zweiter Zweck ist das Verbot der Anzeige des Indikators auf dem Chart des Testens nach dem einzelnen Lauf.

Um die Anzeige des Indikators auf dem Chart am Ende des Testens zu verbieten, rufen Sie IndicatorRelease () mit dem Handle des Indikators im Handler OnDeinit (). Die Funktion OnDeinit() wird immer nach dem Abschluss oder vor der Anzeige des Charts des Testens aufgerufen.

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   bool hidden=IndicatorRelease(handle_ind);
   if(hidden) Print("IndicatorRelease() erfolgreich abgeschlossen");
   else Print("IndicatorRelease() gab false zurück. Fehlercode ",GetLastError());
 }

Um die Anzeige des Indikators auf dem Chart nach dem Abschluss des einzelnen Testens zu verbieten, verwenden Sie die Funktion IndicatorRelease() im Handler OnDeinit().

Behandlung von Ereignissen im Tester #

Das Vorhandensein des Handlers OnTick() im Expert Advisor ist nicht obligatorisch, um ihn der Überprüfung auf die historischen Daten im Tester des MetaTrader 5 Terminals zu unterwerfen. Es ist ausreichend für den Expert Advisor wenigstens einen der folgenden Funktion-Handlers zu haben:

  • OnTick() - Event-Handler des Erhaltes neuen Ticks;
  • OnTrade() - Handler des Handelseregnisses;
  • OnTimer() - Event-Hanlder der Ankunft des Signals aus dem Timer;
  • OnChartEvent() - Handler der Benutzerereignisse.

Beim Testen kann man die Benutzerereignisse mit Hilfe der Funktion OnChartEvent() im Expert Advisor bearbeiten, aber in den Indikatoren wird diese Funktion im Tester nicht aufgerufen. Auch wenn der Indikator den Handler OnChartEvent() hat und dieser Indikator wird in dem getesteten Expert Advisor verwendet, wird der Indikator keine Benutzerereignisse bekommen.

Der Indikator kann beim Testen die Benutzerereignisse mittels Funktion EventChartCustom() generieren, und der Expert Advisor kann dieses Ereignis in OnChartEvent() bearbeiten.

Zusätzlich zu den obengenannten Ereignissen werden im Strategie-Tester die speziellen Ereignisse generiert, die mit dem Prozess des Testens und der Optimierung verbunden sind:

  • Tester - dieses Ereignis wird nach dem Testen des Expert Advisors auf historische Daten generiert. Das Ereigniss Tester wird durch die Funktion OnTester() bearbeitet. Diese Funktion kann nur in Experten beim Testen verwendet werden und dient Zuallererst für die Berechnung eines Wertes, der als Kriterium Custom max bei genetischer Optimierung der Eingabeparameter verwendet wird.
  • TesterInit - dieses Ereignis wird beim Start der Optimierung im Strategie-Tester vor dem ersten Durchlauf generiert. Bearbeitung des Ereignisses TesterInit wird durch die Funktion OnTesterInit() durchgeführt. Der Expert Advisor, der diesen Handler hat, wird beim Start der Optimierung automatisch auf einem gesonderten Chart des Terminals geladen mit dem Symbol und der Periode, die im Tester angegeben wurden, und ein Ereignis TesterInit empfängt. Die Funktion soll einen Expert Advisor vor Optimierung initialisieren um dann die Ergebnisse der Optimierung zu bearbeiten.
  • TesterPass - dieses Ereignis wird beim Empfang eines neuen Datenframes generiert. Bearbeitung des Ereignisses TesterInit wird durch die Funktion OnTesterPass() durchgeführt. Der Expert Advisor mit diesen Handler wird automatisch auf einem gesonderten Chart des Terminals geladen mit dem für ein Test angegebenen Symbol und der Periode, und erhält Ereignisse TesterPass beim Erhalten von einem Frame bei der Optimierung. Die Funktion wird für die dynamische Verarbeitung von Optimierungsergebnisse direkt "on the fly" ausgelegt, ohne für die Vollendung der Optimierung zu warten. Frames werden durch Funktion FrameAdd() hinzugefügt. Diese Funktion kann nach einem Durchgang im Handler OnTester() aufgerufen werden.
  • TesterDeinit - dieses Ereignis wird nach der Optimierung eines Expert Advisors generiert. Bearbeitung des Ereignisses TesterDeinit wird durch die Funktion OnTesterDeinit() durchgeführt. Der Expert Advisor mit diesem Handler wird automatisch auf dem Chart beim Start der Optimierung geladen, und erhält ein Ereignis TesterDeinit nach ihrer Fertigstellung. Die Funktion wird für die abschließende Bearbeitung aller Optimierungsergebnisse verwendet.

Testagenten #

Das Testen wird mit Hilfe der Testagenten im MetaTrader 5 Client-Terminal durchgeführt. Lokalen Agenten werden automatisch erstellt und aktiviert. Die Anzahl der lokalen Agenten entspricht standardmäßig der Anzahl der Kerne auf dem Computer.

Jeder Testagent hat seine eigene Kopie von globalen Variablen, die mit dem Client-Terminal nicht verbunden ist. Das Terminal ist ein Dispatcher, der die Aufgaben an die lokalen und Remote-Agenten verteilt. Wenn Sie die nächste Aufgabe des Testens des Expert Advisors mit den angegebenen Parametern ausgeführt haben, gibt der Agent dem Terminal die Ergebnisse zurück. Beim einzelnen Testen wird nur einen Agenten verwendet.

Der Agent speichert die vom Terminal erhaltenen Geschichte in den einzelnen Ordnern mit dem Namen des Instrumentes, das heisst die Geschichte für EURUSD in einem gesonderten Ordner mit dem Namen EURUSD aufbewahrt wird. Ausserdem wird die Geschichte des Instrumentes durch die Quellen geteilt. Die Struktur für die Speicherung der Geschichte ist wie folgt:

Verzeichnis_des Testers\Agent-IPaddress-Port\bases\Name_der Quelle\history\Name_des Instrumentes

Zum Beispiel kann die Geschichte der EURUSD von MetaQuotes-Demo-Server in einem Ordner Verzeichnis_des Testers \\ Agent-127.0.0.1-3000 \\ bases \\ MetaQuotes-Demo \\ EURUSD gespeichert werden.

Der lokale Agent befindet sich nach Beendigung des Testens im Bereitschaftsmodus und wartet auf die nächste Aufgabe im Laufe von 5 Minuten, um die Zeit mit dem Start bei den nächsten Aufrufen nicht zu verschwenden. Nur stellt nach Ablauf der Wartezeit der lokale Agent seine Arbeit ein und wird aus dem Speicher des Computers entladet.

Bei der vorzeitigen Beendigung des Testens seitens des Benutzers (Schaltfläche "Abbrechnen"), und auch bei der Schließung des Client-Terminals stellen alle lokalen Agenten ihre Arbeit sofort ein und werden aus dem Speicher entladet.

Der Datenaustausch zwischen dem Terminal und dem Agenten #

Beim Start des Testens bereitet das Terminal einige Parameter-Blöcke für das Senden an den Agenten vor:

  • Die Eingabeparameter des Testens (Simulationsmodus, das Intervall des Testens, Instrumente, Optimierungskriterium usw)
  • Liste der im "Markt Durchsicht" ausgewählten Instrumente
  • Die Spezifikation des getesteten Instrumentes (die Kontraktgröße, die zulässigen Margen vom Markt für die Einstellung von StopLoss und Takeprofit, usw)
  • Der getestete Expert-Advisor und die Werte seiner Eingabeparameter
  • Informationen über weitere Dateien (Bibliotheken, Indikatoren, Daten-Dateien - # Property tester_ ...)

tester_indicator

string

Name des Benutzerindikators im Format "Name_des Indikators.ex5." Die für Testen erforderliche Indikatoren werden automatisch aus Aufruf der Funktionen iCustom() bestimmt, wenn der entsprechende Parameter von der Konstantzeile vorgegeben ist. Für andere Fälle (Verwendung der Funktion IndicatorCreate() oder Verwendung einer nicht Konstantzeile im Parameter, der den Namen des Indikator vorgibt) ist diese Eigenschaft erforderlich

tester_file

string

Dateiname für Tester mit Angabe der Erweiterung, in Doppelanführungszeichen (als Konstantzeile). Die angegebene Datei wird dem Tester für Arbeit übertragen. Eingabeparameter für Testen müssen immer angegeben werden (wenn sie erforderlich sind).

tester_library

string

Name der Bibliothek mit Erweiterung in Doppelanführungszeichen. Bibliothek kann sowohl mit der Erweiterung dll, als auch mit der Erweiterung ex5 sein kann. Die für Testen erforderliche Bibliotheken werden automatisch bestimmt. Aber wenn eine Bibliothek vom Benutzerindikator verwendet wird, muss man diese Eigenschaft verwenden.

Für jedes Parameter-Block wird ein digitaler Fingerabdruck in Form von MD5-Hash erstellt, der an den Agenten gesendet wird. MD5-Hash ist einzigartig für jeden Satz, sein Volumen ist viel kleiner als die Informationsmenge, auf deren Grundlage er berechnet wurde.

Der Agent erhält Hashes von Blöcken und vergleicht sie mit denen, die er bereits hat. Wenn der Fingerabdruck dieses Parameter-Blocks dem Agenten fehlt, oder der empfangene Hash unterscheidet sich von der bestehenden, anfordert der Agent selbst das Parameter-Block. So wird der Verkehr zwischen dem Terminal und dem Agenten reduziert.

Nach der Durchführung des Testens gibt der Agent alle Ergebnisse des Laufs zurück. Sie werden auf der Registerkarten "Testergebnisse" und "Optimierungsergebnisse" angezeigt: Der Gewinn, die Anzahl der Deals, die Sharpe Ratio, das Ergebnis der Funktion OnTester (), etc.

Bei der die Optimierung verteilt das Terminals die Aufgaben für die Durchführung des Testens in kleine Pakete an die Agenten, jedes Paket enthält mehrere Aufgaben (jede Aufgabe bedeutet einzelnes Testen mit einem Satz von Eingabeparametern). Dies reduziert die Zeit des Austausches zwischen dem Terminal und dem Agenten.

Agenten werden die vom Terminal erhaltenen EX5-Dateien (Expert-Advisor, Indikatoren, Bibliotheken, etc.) aus Gründen der Sicherheit nie auf Ihrer Festplatte speichern, damit man die gesendeten Daten auf einem Computer mit laufendem Agenten nicht benutzen konnte. Alle übrigen Dateien, einschließlich DLL, werden in der "Sandbox" gespeichert. In der Remote-Agenten kann man die Experten unter Verwendung der DLL nicht testen.

Die Testergebnisse werden in einem speziellen Cache der Ergebnisse (der Ergebniscache) für den nachfolgenden schnellen Zugriff darauf sie, falls notwendig, aufbewahrt. Für jeden Satz von Parametern sucht das Terminals im Ergebniscache nach bereits vorliegenden Ergebnissen von den vorherigen Starts um den Neustart zu vermeiden. Wenn das Ergebnis mit einem solchen Satz von Parametern nicht gefunden wird, wird die Aufgaben für die Durchführung des Testens dem Agenten gegeben.

Der gesamte Verkehr zwischen dem Terminal und dem Agenten wird verschlüsselt.

Ticks werden nicht über das Netzwerk gesendet, werden sie auf Tester-Agenten generiert.

Verwendung von einen freigegebenen Ordner von allen Client-Terminals #

Alle Testagenten sind voneinander und von der Client-Terminal isoliert: jeder Agent hat einen eigenen Ordner, in dem seine Protokolle geschrieben werden. Ausserdem werden alle Dateioperationen beim Testen des Agenten im Ordner Name_des Agenten/MQL5/Files durchgeführt. Man kann jedoch die Wechselwirkung zwischen den lokalen Agenten und dem Client-Terminal über einen freigegebenen Ordner aller Client-Terminals zu verwirklichen, wenn Sie beim Öffnen der Datei das Flag FILE_COMMON angeben:

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- der freigegebene Ordner von allen Client-Terminals
   common_folder=TerminalInfoString(TERMINAL_COMMONDATA_PATH);
//--- geben wir den Namen dieses Ordners aus
PrintFormat("Öffnen wir die Datei in dem freigegebenen Ordner der Client-Terminals% s", Common_folder);
//--- öffnen wir eine Datei in dem freigegebenen Ordner (das Flag FILE_COMMON wird angegeben)
   handle=FileOpen(filename,FILE_WRITE|FILE_READ|FILE_COMMON);
  ... weitere Aktionen
//---
   return(INIT_SUCCEEDED);
  }

Verwendung von DLL #

Zur Beschleunigung der Optimierung kann man nicht nur lokalen sondern auch Remote-Agenten verwenden. Dabei gibt es einige Beschränkungen für Remote-Agenten . Erstens können die Remote-Agenten in ihren Protokollen die Ergebnisse der Ausführung der Funktion Print(), Nachrichten über das Öffnen und Schließen von Positionen nicht ausgeben. Im Protokoll werden Mindestinformationen ausgegeben, so dass die falsch geschriebenen Experten mit Nachrichten die Festplatte Ihres Computers nicht überlasten können.

Die zweite Einschränkung - das Verbot der Verwendung der DLL beim Testen von Experten. DLL-Aufrufe sind auf Remote-Agenten aus Sicherheitsgründen absolut verboten. Auf der lokalen Agenten können DLL-Aufrufe nur mit der entsprechenden Erlaubnis "DLL-Import erlauben" in getesteten Experten erlaubt werden.

Die Option "DLL-Import erlauben" in mql5-Programmen

Hinweis: Bei der Verwendung der von Expert Advisors erhaltenen (Skripts, Indikatoren), die die DLL-Aufrufe zu erlauben erfordern, sollten Sie sich der Risiken bewusst sein, die Sie übernehmen falls Sie diese Option in den Einstellungen des Terminals erlauben. Unabhängig davon, wie der Expert-Advisor verwendet wird - für das Testen oder für den Lauf auf dem Chart.