Automatisierte Optimierung eines EAs mit dem MetaTrader 5
BPASoftware Thai Co. Ltd | 23 Oktober, 2018
Einführung
Unser EA BuddyIlan verwendet 4 Hauptparameter, die jede Woche automatisch optimiert werden sollen, um die beste Einstellung für den Markt zu finden.
Diese Parameter sind:
- SL,
- TP,
- STOFilter,
- STOTimeFrameFilter.
Es ist unrealistisch, diese Art von Prozess jede Woche manuell zu starten, also haben wir nach einem bestehenden Mechanismus gesucht, um wiederholte Aufgaben durchzuführen, aber ohne Erfolg (für MetaTrader 5), also haben wir diesen selbst entwickelt.
Vielen Dank an Igor Malcev, der den Artikel "Automatisierte Optimierung eines Handelsroboters in Realem Handel" für MetaTrader 4 geschrieben hat.
Prinzip
Die erste Instanz des MetaTrader 5, auf der der EA BuddyIlan läuft, läuft rund um die Uhr. Der EA, an dem wir heute arbeiten werden (Optimizer EA) und der die Optimierung durchführt, startet auf einer zweiten Instanz des MetaTrader 5.
Am Ende des Prozesses weist der Optimizer EA die optimierten Werte globalen Variablen zu, die vom laufenden EA BuddyIlan gelesen werden.
Die Optimierung wird jeden Samstag ohne weiteren manuellen Eingriff durchgeführt.
Kopieren der Daten
Wie bereits erwähnt, benötigen wir zwei Instanzen des MetaTrader 5.
Die erste Instanz des MetaTrader 5 ist für das Kopieren von Konfigurationen, Parametern und Berichtsdateien zwischen den beiden Instanzen verantwortlich.
Aus Sicherheitsgründen ist der Zugriff auf Dateien außerhalb einer Sandbox unter MetaTrader 5 nicht möglich, daher werden wir den DOS-Befehl "xcopy" verwenden, um die Daten zwischen den beiden Umgebungen zu kopieren.
Um dies zu tun, müssen wir eine Windows-basierte DLL verwenden, die wir wie folgt deklarieren werden:
#import "shell32.dll" int ShellExecuteW(int hwnd,string Operation,string File,string Parameters,string Directory,int ShowCmd); #import
Der Aufruf dieser Funktion geschieht folgendermaßen:
string PathIniFile = sTerminalTesterDataPath + "\\config\\common.ini"; string PathTester=TerminalInfoString(TERMINAL_DATA_PATH)+"\\MQL5\\Files\\Optimiser\\"; int ret=ShellExecuteW(0,"Open","xcopy","\""+PathIniFile+"\" \""+PathTester+"\" /y","",0);
Dies Funktion wird auch für den Start der Optimierung aufgerufen, z.B.:
int start = ShellExecuteW(0, "Open", sTerminalTesterPath + "\\terminal64.exe", "/config:" + TerminalInfoString(TERMINAL_DATA_PATH) + "\\MQL5\\Files\\Optimiser\\optimise.ini", "", 0); if(start<32) { Print("Failed starting Tester"); return false; }
Der DLL-Import muss für den EA erlaubt werden:
Automatisierte Optimierung
MetaTrader 5 kann über Online-Befehle gestartet werden (siehe: Handelsplattform starten), auch automatische Aufgaben können auf diese Weise gestartet werden.
Beispielsweise kann man in der Standardkonfigurationsdatei (common.ini) einen Abschnitt "[Tester]" hinzufügen, um eine automatische Optimierung beim Start von MetaTrader 5 zu starten.
Das ist es, was wir tun werden.
Umsetzung
Der Optimizer EA muss die Pfade der Instanz des MetaTrader 5 Testers kennen, sie werden als Parameter eingegeben.
input string sTerminalTesterPath = "C:\\Program Files\\ForexTime MT5"; input string sTerminalTesterDataPath="C:\\Users\\BPA\\AppData\\Roaming\\MetaQuotes\\Terminal\\5405B7A2ED87FF45712A041DEF45780";
Wir haben ein Arbeitsverzeichnis definiert: "MQL5\Files\Optimiser" in der ersten MetaTrader 5 Instanz.
Unter der Funktion "CopyAndMoveCommonIni()" wird die Standardkonfigurationsdatei "common.ini" der MetaTrader 5 Tester-Instanz in unser Arbeitsverzeichnis kopiert und in "optimise.ini" umbenannt.
bool CopyAndMoveCommonIni() { string PathIniFile= sTerminalTesterDataPath+"\\config\\common.ini"; string PathTester = TerminalInfoString(TERMINAL_DATA_PATH)+"\\MQL5\\Files\\Optimiser\\"; int ret=ShellExecuteW(0,"Open","xcopy","\""+PathIniFile+"\" \""+PathTester+"\" /y","",0); // warten bis Datei kopiert wurde Sleep(2500); if(ret<32) { Print("Failed copying ini file"); return false; } // Wir arbeiten jetzt in der Sandbox, wir können die normalen Dateibefehle von MetaTrader 5 verwenden string IniFileName="Optimiser\\common.ini"; string CopyTo="Optimiser\\optimise.ini"; return FileMove( IniFileName, 0, CopyTo, 0 ); }
Interessierte finden unter dieser Adresse weitere Informationen zur Funktion "ShellExecuteW": ShellExecuteW. Diese Funktion wartet nicht auf die Rückkehr der Ausführung des DOS-Befehls, sondern nutzt die Verzögerung (Sleep 2500).
Wir fügen nun den Abschnitt "Tester" in diese Datei ein:
bool AddTesterStanza() { int filehandle=FileOpen("Optimiser\\Optimise.ini",FILE_READ|FILE_WRITE|FILE_TXT); if(filehandle!=INVALID_HANDLE) { FileSeek(filehandle,0,SEEK_END); FileWrite(filehandle,"[Tester]\n", "Expert=BuddyIlan\\BuddyIlan\n", "ExpertParameters=BuddyIlanTester.set\n", "Symbol="+_Symbol+"\n", "Period=M15\n", "Login=\n", "Model=4\n", "ExecutionMode=0\n", "Optimization=2\n", "OptimizationCriterion=0\n", "FromDate="+TimeToString(TimeGMT()-InpTesterPeriod*86400,TIME_DATE)+"\n", "ToDate="+TimeToString(TimeGMT(),TIME_DATE)+"\n", "ForwardMode=0\n", "Report=MQL5\\Files\\Reports\\BuddyIlanReport\n", "ReplaceReport=1\n", "ShutdownTerminal=1\n", "Deposit=10000\n", "Currency=EURUSD\n", "Leverage=1:100\n", "UseLocal=1\n", "UseRemote=0\n", "UseCloud=0\n", "Visual=1\n"); FileClose(filehandle); } else { Print("FileOpen, error ",GetLastError()); return false; } return true; }
In diesem Codeblock definieren wir den zu optimierenden Experten ("BuddyIlan") - dieser EA muss in der zweiten Umgebung vorhanden sein - und die Datei ExpertParameters als "BuddyIlanTester.set" (achten Sie darauf, nicht den Namen des EA zu verwenden), wir setzen den Zeitraum (FromDate - ToDate) und alle für die Optimierung benötigten Parameter.
Wir haben "ShutdownTerminal=1" eingestellt, was bedeutet, dass das Terminal am Ende der Optimierung heruntergefahren wird.
Der Bericht wird in der Datei "Files\Reports\BuddyIlanReport" generiert - die Erweiterung ".xlm" wird von der Plattform hinzugefügt.
Wenn Ihre EAs auf einem virtuellen Server mit geringen CPU-Kapazitäten laufen, können Sie einige Remote- oder Cloud-Agenten (siehe "UseRemote" oder "UseCloud") für den Optimierungsprozess verwenden.
Parameterdatei
Jetzt müssen wir die oben definierte Parameterdatei (BuddyIlanTester.set) erstellen, die die Werte jedes Parameters des EA (BuddyIlan) enthält, den wir optimieren wollen.
Die Standardwerte dieser Parameter werden vom Benutzer festgelegt (definiert als Parameter):
input _TradingMode TradingMode = Dynamic; // Konstantes oder dynamisches Volumen input double InpIlanFixedVolume = 0.1; // Konstantes Volumen (falls gesetzt) input int InpNCurrencies=1; // Anzahl von Instanzen von BuddyIlan auf diesem Konto input double LotExponent = 1.4; input bool DynamicPips = true; input int DefaultPips = 15; input int Glubina=24; // Anzahl der Bars zu Berechnung der Volatilität input int DEL=3; input int TakeProfit = 40.0; // Take Profit (Point) input int Stoploss = 1000.0; // Stop Loss (Point) input bool InpIlanTrailingStop = true; // Trailing Stop aktivieren input int InpIlanDistanceTS = 5; // Trailing Stop Abstand (Point) input int MaxTrades=10; input int InpDeviation=10; // Max. erlaubte Preisabweichung (Points) input bool bSTOFilter = true; // dynamischer Trendfilter input bool bSTOTimeFrameFilter = false; // dynamischer Zeitfilter input int InpMaxTf = 60; // Max. Zeitrahmen
Die folgende Funktion akzeptiert 8 Argumente, die ersten 4 entsprechen den zu optimierenden Parametern (SL, TP, STOFilter und STOTimeFrameFilter), wenn wahr (true), wird ein "Y" ans Ende der entsprechenden Parameterzeile gestellt. Die folgenden 4 Argumente entsprechen den bereits optimierten Werten, die wir bei der nächsten Optimierung berücksichtigen wollen.
Wie der Name schon sagt, kopiert diese Funktion auch die Parameterdatei in das Ad-hoc-Verzeichnis (MQL5\Profiles\Tester) der MetaTrader 5 Tester-Instanz.
bool CreateAndCopyParametersFile( bool SL, bool TP, bool STOFilter, bool STOTimeFrameFilter, int SLValue, int TPValue, bool STOFilterValue, bool STOTimeFrameFilterValue ) { int filehandle=FileOpen("Optimiser\\BuddyIlanTester.set",FILE_WRITE|FILE_TXT); if(filehandle!=INVALID_HANDLE) { FileWrite(filehandle, "_EA_IDENTIFIER=Buddy Ilan\n", "_EA_MAGIC_NUMBER=1111||0||1||10||N\n", StringFormat("TradingMode=%d||0||0||0||N\n",TradingMode), StringFormat("InpIlanFixedVolume=%lf||0.0||0.000000||0.000000||N\n",InpIlanFixedVolume), StringFormat("InpNCurrencies=%d||0||1||10||N\n",InpNCurrencies), StringFormat("LotExponent=%lf||0.0||0.000000||0.000000||N\n",LotExponent), StringFormat("DynamicPips=%s||false||0||true||N\n",(DynamicPips==true)?"true":"false"), StringFormat("DefaultPips=%d||0||1||10||N\n",DefaultPips), StringFormat("Glubina=%d||0||1||10||N\n",Glubina), StringFormat("DEL=%d||0||1||10||N\n",DEL), StringFormat("TakeProfit=%d||30||10||70||%s\n",(TPValue==0)?30:TPValue,(TP==true)?"Y":"N"), StringFormat("Stoploss=%d||500||250||1500||%s\n",(SLValue==0)?1000:SLValue,(SL==true)?"Y":"N"), StringFormat("InpIlanTrailingStop=%s||false||0||true||N\n",(InpIlanTrailingStop==true)?"true":"false"), StringFormat("InpIlanDistanceTS=%d||0||1||10||N\n",InpIlanDistanceTS), StringFormat("MaxTrades=%d||0||1||10||N\n",MaxTrades), StringFormat("InpDeviation=%d||0||1||10||N\n",InpDeviation), StringFormat("bSTOFilter=%s||false||0||true||%s\n",(STOFilterValue==true)?"true":"false",(STOFilter==true)?"Y":"N"), StringFormat("bSTOTimeFrameFilter=%s||false||0||true||%s\n",(STOTimeFrameFilterValue==true)?"true":"false",(STOTimeFrameFilter==true)?"Y":"N"), StringFormat("InpMaxTf=%d||0||1||10||N\n",InpMaxTf)); FileClose(filehandle); } else { Print("FileOpen BuddyIlanTester.set, error ",GetLastError()); return false; } Sleep(1500); string PathTester=TerminalInfoString(TERMINAL_DATA_PATH)+"\\MQL5\\Files\\Optimiser\\BuddyIlanTester.set"; string PathProfile=sTerminalTesterDataPath+"\\MQL5\\Profiles\\Tester\\"; // kopieren der Ini-Date in das Verzeichnis des Testers int ret=ShellExecuteW(0,"Open","xcopy","\""+PathTester+"\" \""+PathProfile+"\" /y","",0); // warten bis Datei kopiert wurde Sleep(2500); if(ret<32) { Print("Failed copying parameters file"); return false; } return true; }
Start der Optimierung
Die folgende Funktion startet die Instanz des MetaTrader 5 Testers, die Optimierung wird automatisch mit den von uns angegebenen Parametern gestartet. Diese zweite Instanz erzeugt die Ergebnisdatei und fährt dann herunter.
bool StartOptimizer() { // Löschen des vorherigen Berichts FileDelete("Optimiser\\BuddyIlanReport.xml"); // Löschen des vorherigen Berichts (zweite Instanz des MetaTrader 5) string PathReport=sTerminalTesterDataPath+"\\MQL5\\Files\\Reports\\BuddyIlanReport.xml"; ShellExecuteW(0,"Open","cmd.exe"," /C del "+PathReport,"",0); Sleep(2500); string sTerminalPath=TerminalInfoString(TERMINAL_PATH); // Start der Optimierung int start=ShellExecuteW(0,"Open",sTerminalTesterPath+"\\terminal64.exe","/config:"+TerminalInfoString(TERMINAL_DATA_PATH)+"\\MQL5\\Files\\Optimiser\\optimise.ini","",0); if(start<32) { Print("Failed starting Tester"); return false; } Sleep(15000); return true; }
Für die erste Instanz des MetaTrader 5 ist es am einfachsten herauszufinden, ob die Optimierung abgeschlossen ist, zu überprüfen, ob die Berichtsdatei vorhanden ist.
Wenn die Berichtsdatei erstellt wird, kopieren wir sie in unser Arbeitsverzeichnis.
bool CopyReport() { int nTry=0; // Warten und kopieren der Berichtsdatei while(nTry++<500) // Timeout : 2 Stunden { string PathReport = sTerminalTesterDataPath + "\\MQL5\\Files\\Reports\\BuddyIlanReport.xml"; string PathTarget = TerminalInfoString(TERMINAL_DATA_PATH) + "\\MQL5\\Files\\Optimiser\\"; int ret=ShellExecuteW(0,"Open","xcopy","\""+PathReport+"\" \""+PathTarget+"\" /y","",0); if(ret<32) { PrintFormat("Waiting generation report (%d) ...",nTry); Sleep(15000); } else { if(FileIsExist("Optimiser\\BuddyIlanReport.xml")==true) { PrintFormat("Report found (ret=%d) ...",ret); Sleep(2500); return true; } else { PrintFormat("Waiting report (%d) ...",nTry); Sleep(15000); } } } return false; }
Ergebnisauswertung
Die Berichtsdatei ist im XML-Format. Glücklicherweise schrieb Paul van Hemmen eine Bibliothek für MetaTrader 5, um auf diese Datenform zuzugreifen; diese Bibliothek ist unter folgender Adresse verfügbar: https://www.mql5.com/de/code/1998 - ihm sei herzlich gedankt.
Wir laden diese Bibliothek in unseren EA wie folgt:
#include <EasyXML\EasyXml.mqh>
Tatsächlich verwenden wir die Funktion unten und modifizierten ein paar Dinge in dieser Bibliothek, um sie unserer Berichtsdatei anzupassen (siehe in den beigefügten Dateien).
//+------------------------------------------------------------------+ //| Laden von XML durch die angegebene Datei | //+------------------------------------------------------------------+ bool CEasyXml::loadXmlFromFullPathFile(string pFilename) { string sStream; int iStringSize; Print("Loading XML File ",pFilename); int hFile=FileOpen(pFilename,FILE_ANSI|FILE_READ,0,CP_UTF8); if(hFile==INVALID_HANDLE) { Err=EASYXML_ERR_CONNECTION_FILEOPEN; PrintFormat("[%s] Err=%d",pFilename,GetLastError()); return(Error()); } while(!FileIsEnding(hFile)) { iStringSize = FileReadInteger(hFile, INT_VALUE); sStream += FileReadString(hFile, iStringSize); } FileClose(hFile); return(loadXmlFromString(sStream)); }
Der Zugriff auf die Daten ist ziemlich einfach, mehrere Funktionen erlauben die Analyse der Ergebnisse und das Lesen der Daten, die uns interessieren.
bool LoadResults( OptimisationType eType ) { // Init-Variable BetterProfit=0.0; // Laden der Ergebnisse CEasyXml EasyXmlDocument; EasyXmlDocument.setDebugging(false); if(EasyXmlDocument.loadXmlFromFullPathFile("Optimiser\\BuddyIlanReport.xml")==true) { str=""; CEasyXmlNode *RootNode=EasyXmlDocument.getDocumentRoot(); for(int j=0; j<RootNode.Children().Total(); j++) { CEasyXmlNode *ChildNode=RootNode.Children().At(j); for(int i=0; i<ChildNode.Children().Total(); i++) { CEasyXmlNode *cNode=ChildNode.Children().At(i); if(cNode.getName() == "Worksheet" ) { switch(eType) { case _SL : DisplayNodesSL(cNode); PrintFormat("-> SL=%d (Profit=%.2lf)",BetterSL,BetterProfit); break; case _TP : DisplayNodesTP(cNode); PrintFormat("-> TP=%d (Profit=%.2lf DD=%lf)",BetterTP,BetterProfit,BetterDD); break; case _STO : DisplayNodesSTO(cNode); PrintFormat("-> STOFilter=%s STOTimeFrameFilter=%s (Profit=%.2lf)",(BetterSTOFilter==true)?"true":"false",(BetterSTOTimeFrameFilter==true)?"true":"false",BetterProfit); break; } break; } } } } else PrintFormat("Error found"); return true; }
Da wir mehrere Parameter optimieren wollen, analysieren wir das Ergebnis in nicht nur einer Weise, wir brauchen daher spezifischen Funktionen für die Optimierung. (P SL, TP und STO). Diese Funktionen sind rekursiv.
Unten ist diejenige für die Analyse der Ergebnisse der Optimierung von SL:
void DisplayNodesSL( CEasyXmlNode *Node ) { for(int i=0; i<Node.Children().Total(); i++) { CEasyXmlNode *ChildNode=Node.Children().At(i); if(ChildNode.Children().Total()==0) { str+=ChildNode.getValue()+","; } else { DisplayNodesSL(ChildNode); if(Node.getName()=="Table" && ChildNode.getName()=="Row") { string res[]; StringSplit(str,',',res); // Übergehen der Spaltentitel if(StringCompare(res[0],"Pass",true)!=0) { double profit=StringToDouble(res[2]); int sl=(int) StringToInteger(res[10]); PrintFormat("[%s] Profit=%.2lf StopLoss=%d DD=%s",str,profit,sl,res[8]); if(profit>BetterProfit || (profit==BetterProfit && sl<BetterSL)) { BetterProfit=profit; BetterSL=sl; } } } if(Node.getName()=="Table") str=""; } } }
Diese Funktion wird für jede Zeile und jede Zelle aufgerufen.
Wenn ein Knoten (node) keinen Nachfolger (child) hat, bedeutet das, dass er Daten enthält und wir speichern sie in einer Zeichenkette, die wir später am Ende der Zeile wieder aufspalten werden.
if( ChildNode.Children().Total() == 0 ) { str+=ChildNode.getValue()+","; }
Damit befinden sich die Wert jeder Spalte im Array "res[]" und wir können die Ergebnisse nach unseren Wünschen auswählen.
Der Hauptteil des EAs
Wir haben jetzt alle notwendigen Bausteine, um die 4 Parameter zu optimieren, die beste Einstellung auszuwählen und die Werte den entsprechenden globalen Variablen zuzuweisen, die dann vom laufenden EA gelesen werden können.
void OnTimer() { MqlDateTime dt; datetime now=TimeLocal(dt); // Am Samstag if(dt.day_of_week!=6) { bOptimisationDone=false; return; } // Um 6:00 früh if(dt.hour<6) return; // Fertig ? if(bOptimisationDone==true) return; // Löschen der vorherigen "optimise.ini" FileDelete("Optimiser\\Optimise.ini"); // Konfig.-Datei des EAs erstellen und in \MQL5\Profiles\Test (Tester Instance) kopieren. if(CreateAndCopyParametersFile(true,false,false,false,0,0,true,false)==false) return; // Kopieren von common.ini -> optimise.ini if(CopyAndMoveCommonIni()==false) return; // Ergänzen des Abschnitts [Tester] in optimise.ini - https://www.metatrader5.com/de/terminal/help/start_advanced/start if(AddTesterStanza()==false) return; Print("=======================\nOptimization SL-1"); // Start der ersten Optimierung SL StartOptimizer(); // Kopieren der Berichtsdatei in das Arbeitsverzeichnis if(CopyReport()==false) return; // Bericht mit der Analyse if(LoadResults(_SL)==false) return; Print("=======================\nOptimization STO"); // Erstellen der Parameterdatei für die Optimierung von STO (2 Parameter zugleich optimiert) if(CreateAndCopyParametersFile(false,false,true,true,BetterSL,0,true,false)==false) return; // Beginn der Optimierung von STO StartOptimizer(); // Kopieren der Berichtsdatei in das Arbeitsverzeichnis if(CopyReport()==false) return; if(LoadResults(_STO)==false) return; Print("=======================\nOptimization SL-2"); // Erstellen der Parameterdatei für die zweite Optimierung von SL (Neuberechnung mit den neuen Parameterwerten von STO) if(CreateAndCopyParametersFile(true,false,false,false,0,0,BetterSTOFilter,BetterSTOTimeFrameFilter)==false) return; // Beginn der Optimierung StartOptimizer(); if(CopyReport()==false) return; if(LoadResults(_SL)==false) return; Print("=======================\nOptimization TP"); // Erstellen der Parameterdatei für die Optimierung von TP if(CreateAndCopyParametersFile(false,true,false,false,BetterSL,0,BetterSTOFilter,BetterSTOTimeFrameFilter)==false) return; // Beginn der Optimierung StartOptimizer(); if(CopyReport()==false) return; if(LoadResults(_TP)==false) return; // Ende PrintFormat("=======================\nSL=%d TP=%d STOFilter=%s STOTimeFrameFilter=%s (Profit=%.2lf DD=%lf)\n=======================", BetterSL,BetterTP,(BetterSTOFilter==true)?"true":"false",(BetterSTOTimeFrameFilter==true)?"true":"false",BetterProfit,BetterDD); // Setzen der globalen Variablen - der laufende EA BuddyIlan wird sie lesen und verwenden // WQird eine Drawdown von mehr als 50% festgestellt, beendet der EA den Handel if(BetterDD>50.0 && GlobalVariableSet(gVarStop,1.0)==false) { PrintFormat("Error setting Global Variable [%s]",gVarStop); } if(GlobalVariableSet(gVarSL,BetterSL)==false) { PrintFormat("Error setting Global Variable [%s]=%d",gVarSL,BetterSL); } if(GlobalVariableSet(gVarTP,BetterTP)==false) { PrintFormat("Error setting Global Variable [%s]=%d",gVarTP,BetterTP); } if(GlobalVariableSet(gVarSTOFilter,(BetterSTOFilter==true)?1.0:0.0)==false) { PrintFormat("Error setting Global Variable [%s]=%.1lf",gVarSTOFilter,(BetterSTOFilter==true)?1.0:0.0); } if(GlobalVariableSet(gVarSTOTimeFrameFilter,(BetterSTOTimeFrameFilter==true)?1.0:0.0)==false) { PrintFormat("Error setting Global Variable [%s]=%.1lf",gVarSTOTimeFrameFilter,(BetterSTOTimeFrameFilter==true)?1.0:0.0); } bOptimisationDone=true; }
Die Namen der globalen Variablen werden in der Funktion OnInit() erstellt:
int OnInit() { // Globale Variable gVarStop="BuddyIlan."+_Symbol+".Stop"; gVarSL = "BuddyIlan." + _Symbol + ".SL"; gVarTP = "BuddyIlan." + _Symbol + ".TP"; gVarSTOFilter="BuddyIlan."+_Symbol+".STOFilter"; gVarSTOTimeFrameFilter="BuddyIlan."+_Symbol+".STOTimeFrameFilter";
Unten ist die ganze Optimierung:
2018.07.07 13:20:15.978 BuddyIlanOptimizer (EURGBP,M15) TERMINAL_PATH = C:\Program Files\MetaTrader 5 - ActivTrades 2018.07.07 13:20:15.978 BuddyIlanOptimizer (EURGBP,M15) TERMINAL_DATA_PATH = C:\Users\BPA\AppData\Roaming\MetaQuotes\Terminal\FE0E65DDB0B7B40DE125080872C34D61 2018.07.07 13:20:15.978 BuddyIlanOptimizer (EURGBP,M15) TERMINAL_COMMONDATA_PATH = C:\Users\BPA\AppData\Roaming\MetaQuotes\Terminal\Common 2018.07.07 13:20:32.586 BuddyIlanOptimizer (EURGBP,M15) ======================= 2018.07.07 13:20:32.586 BuddyIlanOptimizer (EURGBP,M15) Optimization SL-1 2018.07.07 13:20:50.439 BuddyIlanOptimizer (EURGBP,M15) Waiting report (1) ... 2018.07.07 13:21:05.699 BuddyIlanOptimizer (EURGBP,M15) Waiting report (2) ... 2018.07.07 13:21:20.859 BuddyIlanOptimizer (EURGBP,M15) Waiting report (3) ... 2018.07.07 13:21:35.952 BuddyIlanOptimizer (EURGBP,M15) Report found (ret=42) ... 2018.07.07 13:21:38.471 BuddyIlanOptimizer (EURGBP,M15) Loading XML File Optimiser\BuddyIlanReport.xml 2018.07.07 13:21:38.486 BuddyIlanOptimizer (EURGBP,M15) [0,11032.2600,1032.2600,3.3406,1.7096,1.5083,0.1558,0,6.2173,309,500,] Profit=1032.26 StopLoss=500 DD=6.2173 2018.07.07 13:21:38.487 BuddyIlanOptimizer (EURGBP,M15) [2,11463.8000,1463.8000,4.7837,2.0386,0.8454,0.1540,0,15.4222,306,1000,] Profit=1463.80 StopLoss=1000 DD=15.4222 2018.07.07 13:21:38.487 BuddyIlanOptimizer (EURGBP,M15) [4,11444.1000,1444.1000,4.7348,2.0340,0.8340,0.1529,0,15.4493,305,1500,] Profit=1444.10 StopLoss=1500 DD=15.4493 2018.07.07 13:21:38.487 BuddyIlanOptimizer (EURGBP,M15) [1,11297.1900,1297.1900,4.2392,1.8414,0.8180,0.1400,0,14.1420,306,750,] Profit=1297.19 StopLoss=750 DD=14.1420 2018.07.07 13:21:38.487 BuddyIlanOptimizer (EURGBP,M15) [3,11514.0800,1514.0800,4.9158,2.3170,1.4576,0.2055,0,9.3136,308,1250,] Profit=1514.08 StopLoss=1250 DD=9.3136 2018.07.07 13:21:38.487 BuddyIlanOptimizer (EURGBP,M15) -> SL=1250 (Profit=1514.08) 2018.07.07 13:21:38.487 BuddyIlanOptimizer (EURGBP,M15) ======================= 2018.07.07 13:21:38.487 BuddyIlanOptimizer (EURGBP,M15) Optimization STO 2018.07.07 13:22:02.660 BuddyIlanOptimizer (EURGBP,M15) Waiting report (1) ... 2018.07.07 13:22:17.768 BuddyIlanOptimizer (EURGBP,M15) Waiting report (2) ... 2018.07.07 13:22:32.856 BuddyIlanOptimizer (EURGBP,M15) Waiting report (3) ... 2018.07.07 13:22:47.918 BuddyIlanOptimizer (EURGBP,M15) Waiting report (4) ... 2018.07.07 13:23:02.982 BuddyIlanOptimizer (EURGBP,M15) Report found (ret=42) ... 2018.07.07 13:23:05.485 BuddyIlanOptimizer (EURGBP,M15) Loading XML File Optimiser\BuddyIlanReport.xml 2018.07.07 13:23:05.499 BuddyIlanOptimizer (EURGBP,M15) [0,11463.5000,1463.5000,4.4483,2.0614,0.8452,0.1540,0,15.4267,329,false,false,] Profit=1463.50 false false DD=15.4267 2018.07.07 13:23:05.499 BuddyIlanOptimizer (EURGBP,M15) [1,11444.1000,1444.1000,4.7348,2.0340,0.8340,0.1529,0,15.4493,305,true,false,] Profit=1444.10 true false DD=15.4493 2018.07.07 13:23:05.499 BuddyIlanOptimizer (EURGBP,M15) [2,11430.5300,1430.5300,5.1090,2.1548,0.8917,0.1717,0,14.4493,280,false,true,] Profit=1430.53 false true DD=14.4493 2018.07.07 13:23:05.499 BuddyIlanOptimizer (EURGBP,M15) [3,11470.7100,1470.7100,6.2851,1.8978,0.8146,0.1288,0,17.3805,234,true,true,] Profit=1470.71 true true DD=17.3805 2018.07.07 13:23:05.499 BuddyIlanOptimizer (EURGBP,M15) -> STOFilter=true STOTimeFrameFilter=true (Profit=1470.71) 2018.07.07 13:23:05.500 BuddyIlanOptimizer (EURGBP,M15) ======================= 2018.07.07 13:23:05.500 BuddyIlanOptimizer (EURGBP,M15) Optimization SL-2 2018.07.07 13:23:29.921 BuddyIlanOptimizer (EURGBP,M15) Waiting report (1) ... 2018.07.07 13:23:45.043 BuddyIlanOptimizer (EURGBP,M15) Waiting report (2) ... 2018.07.07 13:24:00.170 BuddyIlanOptimizer (EURGBP,M15) Waiting report (3) ... 2018.07.07 13:24:15.268 BuddyIlanOptimizer (EURGBP,M15) Waiting report (4) ... 2018.07.07 13:24:30.340 BuddyIlanOptimizer (EURGBP,M15) Report found (ret=42) ... 2018.07.07 13:24:32.854 BuddyIlanOptimizer (EURGBP,M15) Loading XML File Optimiser\BuddyIlanReport.xml 2018.07.07 13:24:32.872 BuddyIlanOptimizer (EURGBP,M15) [0,9269.9000,-730.1000,-2.7760,0.7328,-0.3644,-0.0532,0,19.4241,263,500,] Profit=-730.10 StopLoss=500 DD=19.4241 2018.07.07 13:24:32.872 BuddyIlanOptimizer (EURGBP,M15) [4,11470.7100,1470.7100,6.2851,1.8978,0.8146,0.1288,0,17.3805,234,1500,] Profit=1470.71 StopLoss=1500 DD=17.3805 2018.07.07 13:24:32.872 BuddyIlanOptimizer (EURGBP,M15) [3,11475.9500,1475.9500,6.2806,1.8995,0.8175,0.1290,0,17.3718,235,1250,] Profit=1475.95 StopLoss=1250 DD=17.3718 2018.07.07 13:24:32.872 BuddyIlanOptimizer (EURGBP,M15) [2,11400.7500,1400.7500,5.8609,1.8442,0.7759,0.1292,0,17.3805,239,1000,] Profit=1400.75 StopLoss=1000 DD=17.3805 2018.07.07 13:24:32.872 BuddyIlanOptimizer (EURGBP,M15) [1,10662.5500,662.5500,2.8807,1.3618,0.3815,0.0862,0,16.7178,230,750,] Profit=662.55 StopLoss=750 DD=16.7178 2018.07.07 13:24:32.873 BuddyIlanOptimizer (EURGBP,M15) -> SL=1250 (Profit=1475.95) 2018.07.07 13:24:32.873 BuddyIlanOptimizer (EURGBP,M15) ======================= 2018.07.07 13:24:32.873 BuddyIlanOptimizer (EURGBP,M15) Optimization TP 2018.07.07 13:24:57.175 BuddyIlanOptimizer (EURGBP,M15) Waiting report (1) ... 2018.07.07 13:25:12.311 BuddyIlanOptimizer (EURGBP,M15) Waiting report (2) ... 2018.07.07 13:25:27.491 BuddyIlanOptimizer (EURGBP,M15) Waiting report (3) ... 2018.07.07 13:25:42.613 BuddyIlanOptimizer (EURGBP,M15) Waiting report (4) ... 2018.07.07 13:25:57.690 BuddyIlanOptimizer (EURGBP,M15) Report found (ret=42) ... 2018.07.07 13:26:00.202 BuddyIlanOptimizer (EURGBP,M15) Loading XML File Optimiser\BuddyIlanReport.xml 2018.07.07 13:26:00.219 BuddyIlanOptimizer (EURGBP,M15) [1,11768.5700,1768.5700,8.2259,2.4484,1.1024,0.2233,0,14.1173,215,40,] Profit=1768.57 TakeProfit=40 DD=14.117300 2018.07.07 13:26:00.219 BuddyIlanOptimizer (EURGBP,M15) [4,12343.5200,2343.5200,13.5464,2.5709,1.3349,0.2519,0,15.0389,173,70,] Profit=2343.52 TakeProfit=70 DD=15.038900 2018.07.07 13:26:00.219 BuddyIlanOptimizer (EURGBP,M15) [0,11243.4600,1243.4600,5.2913,1.6399,0.6887,0.1039,0,17.3805,235,30,] Profit=1243.46 TakeProfit=30 DD=17.380500 2018.07.07 13:26:00.219 BuddyIlanOptimizer (EURGBP,M15) [3,12292.3500,2292.3500,11.8162,2.5837,0.9257,0.2538,0,20.4354,194,60,] Profit=2292.35 TakeProfit=60 DD=20.435400 2018.07.07 13:26:00.219 BuddyIlanOptimizer (EURGBP,M15) [2,12146.3900,2146.3900,11.0639,2.4416,1.2226,0.2292,0,15.0772,194,50,] Profit=2146.39 TakeProfit=50 DD=15.077200 2018.07.07 13:26:00.219 BuddyIlanOptimizer (EURGBP,M15) -> TP=70 (Profit=2343.52 DD=15.038900) 2018.07.07 13:26:00.219 BuddyIlanOptimizer (EURGBP,M15) ======================= 2018.07.07 13:26:00.219 BuddyIlanOptimizer (EURGBP,M15) SL=1250 TP=70 STOFilter=true STOTimeFrameFilter=true (Profit=2343.52 DD=15.038900) 2018.07.07 13:26:00.219 BuddyIlanOptimizer (EURGBP,M15) =======================
Schlussfolgerung
Die Implementierung dieses Prozesses erfordert ein Minimum an Kenntnissen über MetaTrader 5, seine Optimierungsmechanismen und die Programmierung.
Anbei die Quellen dieses EA, die XML-Parser-Dateien von Paul van Hemmen und die modifizierte Datei "EasyXml.mqh".
Ich hoffe, es hilft.