Haltepunkte im Tester: Es ist möglich!

Christo Tsvetanov | 26 Januar, 2016

Einführung

Die einzige Sache, die ich bei MQL4 vermisse, ist ein normaler Debugger für Expert Advisors. Alle menschlichen Wesen haben menschliche Gefühle, so dass wir Fehler machen. Bei normaler Programmierung setzen wir Haltepunkte, starten das Programm, wenn die Ausführung einen Haltepunkt erreicht wird es angehalten. So können wir die Inhalte der Variablen ansehen, die wir ausüben.

Das Anzeigen von Debug-Daten ist nun möglich durch Funktionen wie Ausdrucken, Kommentar, usw. Manchmal möchten wir das Programm aber zeitweise an einem bestimmten Punkt anhalten, um die Situation zu bewerten. Hier gibt es einige Feinheiten. Das Programm wird in der Regel gestartet für das Trading in einem Demokonto oder einem Echtgeld-Konto. Das bedeutet, dass wir erst in einigen Monaten in der Lage sein werden die Ergebnisse zu sehen... Also ist der Debug-Modus nur sinnvoll im Testmodus von Expert Advisors (im Tester).


Wie Es Funktioniert

Seit ein "visueller Testmodus" im Tester erschien, wurde es möglich, die Reaktionen unseres EAs während einem Schnelldurchlauf des Programms durch den Tester zu verfolgen. Wenn wir die Ausführung zeitweise anhalten wollen, können wir "Pause" auf der Tastatur drücken, oder mit der Maustaste auf die gleichnamige Schaltfläche in der Toolbar des Testers klicken. Die Entwickler des Programms stellen eine WinUser32 genannte Bibliothek zur Verfügung, die einige sehr interessante Funktionen enthält. Eine von diesen ist keybd_event. Sie ermöglicht es jede Taste zu drücken, die wir möchten.

Es wurde die Idee aufgeworfen - wir können eine Funktion schreiben, die programmgesteuert Pause drückt und die erforderlichen Debug-Informationen ausdruckt. Da unser Expert Advisor DLL verwenden wird, sollten wir es zuerst für den EA ermöglichen. Drücken Sie Strg + O und aktivieren / deaktivieren sie Kontrollkästchen:

Dann müssen wir irgendwo am Anfang des Codes die Verwendung von WinUser32 deklarieren:

#include <WinUser32.mqh>

Diesem Vorgang folgt die Deklaration der Funktion BreakPoint selbst. Es gibt hier einige Feinheiten, aber die einfachste Realisierung übernimmt keine durchgelaufen/zurückgegeben (passed/returned) Parameter:

void BreakPoint()

Die Funktion darf nur im visuellen Testmodus auslösen, so dass wir eine Prüfung einbauen werden: Wenn der Tester nicht im visuellen Testmodus ist, brechen wir ab:

if (!IsVisualMode()) return(0);

Dann werden wir einige Daten visualisieren. Meiner Meinung nach, würde Comment () es am besten erklären. Nehmen wir an, wir benötigen nur Bid und Ask.

string Comm="";
Comm=Comm+"Bid="+Bid+"\n";
Comm=Comm+"Ask="+Ask+"\n";
   
Comment(Comm);

Das "/n" hier bedeutet, dass nachfolgende Daten im nächsten String angezeigt werden. Abschließend, lassen Sie uns Pause drücken.

keybd_event(19,0,0,0);
Sleep(10);
keybd_event(19,0,2,0);

Der erste String drückt die Taste, wohingegen der letzte sie freigibt. Die Sleep ist ebenfalls notwendig, da ein zu schnelles Drücken/Freigeben eventuell nicht ausgefüht wird. 19 ist ein virtueller Code für Pause, 2 im letzten String zeigt, dass das Freigeben emuliert werden muss.

Alles was wir nun tun müssen, ist den Haltepunkt im Code des Expert Advisor zu ersetzen, sagen wir unmittelbar nachdem die Long Position aus dem Artikel Expert Advisor Sample eröffnet wurde.

ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,3,0,Ask+TakeProfit*Point,"macd sample",16384,0,Green);
BreakPoint();

Unten ist der gesamte einzugebende Code:

//We will use a function, described in header file
#include 
 
//Breakpoint neither receive nor send back any parameters
void BreakPoint()
{
   //It is expecting, that this function should work
   //only in tester
   if (!IsVisualMode()) return(0);
   
   //Preparing a data for printing
   //Comment() function is used as 
   //it give quite clear visualisation
   string Comm="";
   Comm=Comm+"Bid="+Bid+"\n";
   Comm=Comm+"Ask="+Ask+"\n";
   
   Comment(Comm);
   
   //Press/release Pause button
   //19 is a Virtual Key code of "Pause" button
   //Sleep() is needed, because of the probability
   //to misprocess too quick pressing/releasing
   //of the button
   keybd_event(19,0,0,0);
   Sleep(10);
   keybd_event(19,0,2,0);
}


Was sollen wir tun, um lokale Variablen zu beobachten?

Das Problem liegt in der "Unsichtbarkeit" solcher Variablen außerhalb ihrer Deklarationen. In diesem Fall sollten die Daten durchlaufen. Nehmen wir an, wir möchten die Variable MacdCurrent aus dem Artikel beobachten. Hierzu werden wir die Funktion wie folgt ändern:

void BreakPoint(double MacdCurrent)
{
   if (!IsVisualMode()) return(0);
   
   Comment("MacdCurrent = ",MacdCurrent);


Optionale Haltepunkte

Manchmal wünschen wir uns vielleicht, dass das Programm nicht immer anhält, wenn es einen bestimmten String erreicht, aber nur, wenn einige zusätzliche Bedingungen erfüllt werden. Das passiert in der Regel in Schleifen. Zum Beispiel, wir wollen die Ausführung unterbrechen, wenn der Zähler einen bestimmten vordefinierten Wert erreicht hat. Dafür müssen wir eine zusätzliche Bedingung übergeben:

void BreakPoint(double MacdCurrent, bool Condition)
{
   if (!IsVisualMode() || (!Condition)) return(0);
   //Or - which is the same:
   //if (!(IsVisualMode()&&Condition)) return(0);
   
   Comment("MacdCurrent = ",MacdCurrent);

Wir werden es wie folgt aufrufen:

for(cnt=0;cnt<total;cnt++)     
   {
      OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
      BreakPoint(MacdCurrent, cnt==1);


Fazit

Also, warum erstellen wir nicht einfach eine Bibliothek, um sie mit dem Programm zu verbinden und dann zu verwenden? Die Sache dabei ist, dass es viele Variationen gibt, bei denen es besser wäre die Funktion BreakPoint zu ändern. Tatsächlich ist alles oben Geschriebene nur eine allgemeine Idee. Es kann auf viele verschiedene Arten implementiert werden.

Zum Abschluss möchte ich gerne Klot würdigen, der als Erster abgeschätzt hat, wie das programmgesteuerte Pause-Drücken zu realisieren ist