![So können Sie Ihre eigenen Optimierungskriterien implementieren](https://c.mql5.com/i/articles/overlay.png)
So können Sie Ihre eigenen Optimierungskriterien implementieren
Einführung
Von Zeit zu Zeit hören wir die Meinung, dass es nötig sei, die Anzahl der Optimierungskriterien im MT4-Tester zu erhöhen. Aber Sie können sich sicherlich denken, dass es keine Rolle spielt, welche Kriterien die Entwickler auch hinzufügen, denn es wird immer Trader geben, die andere Kriterien benötigen. Kann man dieses Problem innerhalb von MQL4 und MetaTrader lösen? Ja, das ist möglich. Dieser Artikel zeigt, wie man einen individuell entworfenes Optimierungskriterium implementieren kann hierzu benutzen wir das Beispiel des standardisierten Expert Advisors des Gleitenden Durchschnittes. Das Kriterium steht hierbei in Relation zum Gewinn/Verlust.
Expert Advisor
Lassen Sie uns mit dem Optimierungskriterium beginnen. Für seine Berechnung müssen wir während der Testphase den maximalen Kontostand und den Verlust bestimmen. Um nicht auf die Logik der Expert Advisor-Operation angewiesen zu sein, werden wir die bereits existierenden Code-Strings ganz zu Anfang der Startfunktion hinzufügen ().
if (AccountEquity() > MaxEqu) MaxEqu = AccountEquity(); if (MaxEqu-AccountEquity() > MaxDD) MaxDD = MaxEqu-AccountEquity();
Um den letzten Tick zu berechnen, sollten Sie in deinit() repliziert werden. Danach können wir den Wert des Optimierungskriteriums berechnen
Criterion = (AccountBalance()-StartBalance)/MaxDD;
Jetzt können wir mit dem Hauptteil beginnen: Die Überarbeitung des Optimierungsprozesses. Wir haben aber zunächst ein Problem: MQL4 verfügt über keinerlei eingebaute Mittel, um das Ende des Optimierungsprozesses zu bestimmen. Der einzige Ausweg aus diesem Dilemma, der mir bekannt ist, ist die sogenannte " Optimierung über einen Zähler ". Die Bedeutung hiervon ist die Folgende: Der einzige veränderbare Parameter des Expert Advisors ist der spezielle externe Variablenzähler. Hierbei gibt es aber immer noch eine schwerwiegende Konsequenz: Wir verlieren damit die Möglichkeit, die realen Parameter des Expert Advisors in einer standardisierten Art und Weise zu verändern, und wir müssen dies also selbst erledigen. Ein weiterer Nachteil besteht darin, dass der Optimierungs-Cache sich von unserem Freund in einen Feind verwandelt. Aber der Zweck rechtfertigt die Mittel, und daher wollen wir weitermachen.
Fügen wir also die externen Variablen hinzu :
extern int Counter = 1; // Counter of the tester's running extern int TestsNumber = 200; // he check digit - total number of runs extern int MovingPeriodStepsNumber = 20; // Number of optimization steps for MovingPeriod extern int MovingShiftStepsNumber = 10; // Number of optimization steps for MovingShift extern double MovingPeriodLow = 150; // Lower limit of the optimization range for MovingPeriod extern double MovingShiftLow = 1; // Lower limit of the optimization range for MovingShift extern double MovingPeriodStep = 1; // Optimization step for MovingPeriod extern double MovingShiftStep = 1; // Optimization step for MovingShift
Als erstes kommt der Zähler. Die nächste Variable ist der Check Eins (und die Informationen). Dann ordnen wir die Anzahl der Schritte, das untere Limit und die Optimierungsschritte für die zwei eingebauten Variablen des Gleitenden Durchschnittes zu, den wir dadurch optimieren wollen. Sie können hier einige Unverhältnismögligkeit sehen: Wenn wir die vollständige Analyse durchführen möchten (und wir werden genau das tun), dann sollte das Produkt von MovingPeriodStepsNumber und MovingShiftStepsNumber identisch sein mit der TestsNumber.
Nach jedem Testlauf beendet der Expert Advisor seine Arbeit vollständig, und der nächste Durchgang kann als eine Reinkarnation des vorhergehenden Testlaufs angesehen werden. Wir verfügen über zwei Möglichkeiten zur Organisation " der genetischen Datenbank ": Globale Variablen und eine separate Datei. Wir werden beide benutzen.
Lassen Sie uns die Funktion init() modifizieren:
int init() { if (IsTesting() && TestsNumber > 0) { if (GlobalVariableCheck("FilePtr")==false || Counter == 1) { FilePtr = 0; GlobalVariableSet("FilePtr",0); } else { FilePtr = GlobalVariableGet("FilePtr"); } MovingPeriod = MovingPeriodLow+((Counter-1)/MovingShiftStepsNumber)*MovingPeriodStep; MovingShift = MovingShiftLow+((Counter-1)%MovingShiftStepsNumber)*MovingShiftStep; StartBalance = AccountBalance(); MaxEqu = 0; MaxDD = 0; } return(0); }
Unser hinzugefügter Code befindet sich innerhalb der Operationskonditionen lediglich im Tester und bei der Nicht-Null TestsNumber. Daher wird der Task TestsNumber=0 den Expert Advisor in einen standardisierten Gleitenden Durchschnitt (Englisch: "Moving Average") verwandeln. Während wir den Prozess der Optimierungen diskutieren, müssen wir jede Möglichkeit nutzen, um den Prozess schneller ablaufen zu lassen. Das ist auch der Grund dafür, weshalb der Code mit der Bedingung startet, einen through (durch die Testläufe hindurch) file pointer zu verwenden, unter der Benutzung einer globalen Variable. Dann kalkulieren wir die Werte der veränderbaren Parameter und initialisieren die Variablen, die für die Kalkulation der Optimierungskriterien benötigt werden.
Die Hauptarbeit sollte in der Funktion deinit() erledigt werden. Sobald wir die Testresultate haben, werden wir die Werte davon in einer Textdatei für das Optimierungskriterium, die Werte der optimierten Parameter und die Anzahl der Testläufe abspeichern. Nach dem Ende der Optimierung werden diese Ergebnisse dann sortiert werden, in Abhängigkeit vom Optimierungskriterium, und sie werden daraufhin in derselben Datei abgespeichert werden. Wir müssen hierzu also drei Situationen durchspielen: Der erste Start, der letzte Start, und alle anderen. Lassen Sie uns den Testlauf-Zähler benutzen, um diese voneinander zu trennen.
Die Bearbeitung des ersten Starts :
if (Counter == 1) { // First run, create/initialize a datafile. h=FileOpen("test.txt",FILE_CSV|FILE_WRITE,';'); FileWrite(h,Criterion,MovingPeriod,MovingShift,Counter); // Remember the position of the file pointer after writing in the global variable FilePtr = FileTell(h); GlobalVariableSet("FilePtr",FilePtr); FileClose(h);
Die Besonderheit bei der Bearbeitung anderer Starts besteht darin, dass die neuen Daten in die Datei hinzugefügt werden:
} else { // After the first start is processed, the data are added into the file h=FileOpen("test.txt",FILE_CSV|FILE_READ|FILE_WRITE,';'); // It is time to use the file pointer written in the global variable FilePtr = GlobalVariableGet("FilePtr"); FileSeek(h,FilePtr, SEEK_SET); FileWrite(h,Criterion,MovingPeriod,MovingShift,Counter); // Remember the file pointer position once again FilePtr = FileTell(h); GlobalVariableSet("FilePtr",FilePtr);
Lassen Sie uns jetzt den letzten Start durchspielen:
if (Counter == TestsNumber) { ArrayResize(Data,TestsNumber); // Returns the file pointer to the beginning FileSeek(h,0,SEEK_SET); // Read from the file the results of all testings int i = 0; while (i<TestsNumber && FileIsEnding(h)== false) { for (int j=0;j<4;j++) { Data[i][j]=FileReadNumber(h); } i++; } // Sort the array according to our optimization criterion ArraySort(Data,WHOLE_ARRAY,0,MODE_DESCEND); // Now let us arrange the results. Reopen the file FileClose(h); h=FileOpen("test.txt",FILE_CSV|FILE_WRITE,' '); FileWrite(h," Criterion"," MovingPeriod"," MovingShift"," Counter"); for (i=0;i<TestsNumber;i++) { FileWrite(h,DoubleToStr(Data[i][0],10)," ",Data[i][1]," ",Data[i][2]," ",Data[i][3]); }
Die Matrix wurde vorläufig initialisiert als eine doppelte Data[][4]. Und das ist auch schon alles. Lassen Sie uns nun aufräumen:
GlobalVariableDel("FilePtr"); } FileClose(h); } }
Kompilieren, den Tester öffnen und Auswählen des Expert Advisors. Öffnen Sie dann die Eigenschaften-Seite des Expert Advisors, und überprüfen Sie vier Positionen:
-Das Produkt von MovingPeriodStepsNumber und MovingShiftStepsNumber MUSS identisch sein mit der TestsNumber.
- Die Optimierung darf NUR für den Zähler durchgeführt werden,
- Die Optimierungsspanne MUSS von 1 bis hin zu TestsNumber reichen, mit einer Schrittgröße von 1.
- Der genetische Algorithmus muss deaktiviert werden.
Starten Sie die Optimierung. Nach dem Abschluss gehen Sie zum Ordner [Meta Trader]\tester\files und sehen sich die Resultate in der Datei test.txt an. Der Autor hat diesen Prozess für EURUSD_H1 von der Mitte des Jahres 2004 ab für die Eröffnungspreise durchgeführt, und er hat die folgenden Ergebnisse erhalten :
Und jetzt werde ich Ihnen erklären, weshalb ich oben das Statement abgegeben habe, dass der Cache unser Feind sei. Die Sache ist nämlich die, dass, wenn wir die Testergebnisse aus dem Cache entnehmen, die Funktionen init() und deinit() nicht gestartet werden. Infolgedessen sind beim Neustart der Optimierung alle Varianten oder Teile unserer Varianten nicht berücksichtigt. Darüber hinaus gilt, dass die tatsächliche Anzahl der Testläufe geringer sein wird als die TestsNumber, und die Matrix Data wird daher einige Nullen enthalten. Der Autor schlägt zwei Lösungsansätze vor, um den " Cache-Effekt " zu eliminieren: Die Neukompilierung eines Expert Advisors, oder die Schließung/Pausierung/erneute Öffnung des Testerfensters.
Die Cache-Interferenz kann entdeckt werden, indem man eine unabhängige Zählung der Testläufe vornimmt.
Es gibt drei kommentierte Einfügungen für die Organisation eines solchen Zählers, bei dem eine spezielle globale Variable zum Einsatz kommt,
wie man sie beispielhaft in dem angefügten EA-Code nachlesen kann
// Code of the independent counter if (GlobalVariableCheck("TestsCnt")==false || Counter == 1) { TestsCnt = 0; GlobalVariableSet("TestsCnt",0); } else { TestsCnt = GlobalVariableGet("TestsCnt"); }
// Code of the independent counter TestsCnt++; GlobalVariableSet("TestsCnt",TestsCnt);
// Code of the independent counter GlobalVariableDel("TestsCnt");
Und noch eine Schlussbemerkung: Der aufmerksame Leser hat mit Sicherheit die Tatsache entdeckt, dass wir auch auf die Variable FilePtr (und die damit einhergehende globale Variable) verzichten können die Daten werden am Ende der Datei eingefügt, und sie werden vom Anfang gelesen. Wofür dienen sie also? Die Antwort ist die folgende: Dieser Expert Advisor ist für die Demonstration der Optimierungs-/Wartungsmethode gedacht. Diese Methode erlaubt es, die Operation im fliegenden Betrieb durchzuführen, zusammen mit den Resultaten von vorhergehenden Testlä#252;r Tasks, die es erforderlich machen, mit vorherigen Resultaten im fliegenden Betrieb zu arbeiten, können wir beispielsweise das Management von out-of-sample-Testläufen anführen, sowie die Implementierung von selbsterstellten genetischen Algorithmen.
Fazit
Der Grund für das besondere Interesse an diesem Problem waren Themen aus dem Forum http://forum.mql4.com.
Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/1498
![Der Objekt-Ansatz in MQL](https://c.mql5.com/2/15/499_6.gif)
![MQL4 Sprache für Einsteiger. Einführung](https://c.mql5.com/2/14/404_19.gif)
![Der Indikator Taichi - Eine simple Methode zur Formalisierung der Werte von Ichimoku Kinko Hyo.](https://c.mql5.com/2/15/509_25.gif)
![Strings: Tabelle mit ASCII Zeichen und ihre Verwendung](https://c.mql5.com/2/14/457_10.png)
![MQL5 - Sprache von Handelsstrategien, eingebaut ins Kundenterminal MetaTrader 5](https://c.mql5.com/i/registerlandings/logo-2.png)
- Freie Handelsapplikationen
- Über 8.000 Signale zum Kopieren
- Wirtschaftsnachrichten für die Lage an den Finanzmärkte
Sie stimmen der Website-Richtlinie und den Nutzungsbedingungen zu.