La optimización automática de un Asesor Experto en el trading real
Introducción
Se supone que un Asesor Experto que tiene las entradas ajustadas al historial resultaría rentable la primera vez (en un tiempo bastante corto). Se puso en evidencia esta hipótesis después de haber observado el Campeonato de Trading Automatizado 2006. Al principio del campeonato, habían Asesores Expertos mucho más, pero más adelante, algunos ya no eran rentables. Por este motivo, supongo que la mayoría de estos Asesores Expertos no habían llegado hasta el final por estar ajustados al historial.
La idea de comprobar esta hipótesis en la práctica surgió en el foro en ruso de este sitio, en el apartado Sistemas ideales de trading automático. El principio de esta idea consiste en iniciar automáticamente la optimización de un Asesor Experto una vez al día y después analizar los resultados de la optimización y almacenarlos en las variables del Asesor Experto.
Para implementar esta idea hemos decidido utilizar el Asesor Experto ya hecho, el MACD Sample, del Terminal de cliente MetaTrader 4 e insertar nuestra propia función de optimización automática en él. Un poco después, ya estaba listo el código del optimizador automático y cargado en el mismo foro, en el apartado Optimizador automático. Después de algún tiempo, comenzó a confirmarse la idea en el apartado Optimizador automatico. Más adelante, se convirtió el optimizador en una librería mqh para una mayor facilidad de uso.
Instalación del optimizador automático
A continuación podemos ver lo que hay que hacer para llevar a cabo esta tarea:
- copiar MACD Sample_1.mq4 en la carpeta "expert" del Terminal de cliente MetaTrader 4 previamente instalado y conectado a Internet; y
- hacer una copia de la carpeta del Terminal de cliente MetaTrader ya instalado en una nueva ubicación.
Para mayor comodidad, llamaremos al terminal original "Terminal" y a la copia "Terminal-Tester". Realizaremos una prueba en EURUSD con el período de tiempo H1 mediante el Asesor Experto incluido en el Terminal, pero ligeramente modificado; MACD Sample_1.mq4.
Configuración de Terminal-Tester
No se olvide de compilar MACD Sample_1.mq4 en el Terminal-Tester. Pongamos en marcha primero el terminal de cliente y después la prueba de estrategias y hagamos los ajustes tal y como se muestra en la siguiente captura de pantalla.
Se llevará a cabo la optimización durante tres días. Esto es más que suficiente para probar el optimizador automático. Seleccionaremos la fecha de optimización "De" según la siguiente fórmula: la fecha actual menos tres días. Durante la optimización, hay que descargar el historial del símbolo (en nuestro caso, es el EURUSD) seleccionado.
Aquellos que realizan la optimización por primara vez pueden encontrar la descripción de los procedimientos necesarios en el menú Ayuda del Terminal de cliente MetaTrader 4: <Ayuda - Temas de ayuda F1 - Auto Trading - Expert Optimization - Setup>. O pueden leer el artículo Prueba de Asesores Expertos en el Terminal de cliente MetaTrader 4: Un vistazo desde fuera.
A continuación vamos a marcar las variables a optimizar tal y como se muestra en la siguiente captura de pantalla.
La optimización automática está limitada a 4 variables, pero basta con tener sólo tres para conseguir nuestro objetivo y ahorrar tiempo. Una vez seleccionadas las variables almacenamos los ajustes de la optimización en el archivo MACD Sample_1.set. Hay que guardar este archivo en la carpeta "tester" del Terminal-Tester. A continuación ejecutamos la pre-optimización y memorizamos la hora de inicio. Hace falta calcular el período de tiempo que requiere la optimización automática con los parámetros predefinidos. Una vez finalizada la optimización, calculamos el tiempo de espera necesario. A continuación tenemos que cerrar este terminal, de lo contrario no podremos ejecutarlo mediante la programación.
Configuración del Asesor Experto ubicado en el terminal
Para ello, vamos a abrir el Asesor Experto MACD Sample_1.mq4 en MetaEditor y hacer lo siguiente:
- establecer el tiempo de inicio de la optimización automática, por ejemplo, a las 00:01 cada día:
datetime SetHour = 0; // Optimization starting hour; datetime SetMinute = 1; // Optimization starting minute.
- establecer la duración de la optimización en días (tiene que coincidir con el número de días de la pre-optimización):
int TestDay = 3;
- establecer el tiempo de espera en minutos del fin de la optimización que hemos calculado antes, por ejemplo, 4 minutos:
int TimeOut = 4;
- introducir el nombre del Asesor Experto:
string NameMTS = "MACD Sample_1"; // EA's name
- introducir el nombre del archivo con los ajustes:
// Set-file name with the settings string NameFileSet = "MACD Sample_1.set";
- introducir el nombre de la ruta hacia la carpeta que contiene el Terminal-Tester instalado, por ejemplo:
// Path to the tester string PuthTester = "D:\Program Files\Forex Best Trade Station";
- establecer la prioridad del filtrado:
// Sorting by Maximal profit int Gross_Profit = 1; // Sorting by Maximal profit factor int Profit_Factor = 2; // Sorting by Maximal expected payoff int Expected_Payoff = 3;
- escribir los nombres de las variables a optimizar:
string Per1 = "FastEMA"; string Per2 = "SlowEMA"; string Per3 = "SignalSMA"; string Per4 = "";
- copiar el archivo adjunto auto_optimization.mqh en la carpeta "include";
- incluir el archivo de la librería en el Asesor Experto:
//--- Including the auto optimizer's library #include <auto_optimization.mqh>
- sólo falta copiar el siguiente código debajo del inicio de la función start() en su Asesor Experto. Ya está incluido en MACD Sample_1.mq4.
// Not to be launched at testing and optimizing if(!IsTesting() && !IsOptimization()) { // Compare the current hour with that preset for launching if(TimeHour(TimeLocal()) == SetHour) { // Protection against restarting if(!StartTest) { // Compare the minute range to the minute // preset for launching if(TimeMinute(TimeLocal()) > SetMinute - 1) { // the range is necessary, in case that for some reasons // no new tick is available for a long time if(TimeMinute(TimeLocal()) < SetMinute + 1) { // Flag of tester launching StartTest = true; TimeStart = TimeLocal(); Tester(TestDay, NameMTS, NameFileSet, PuthTester, TimeOut, Gross_Profit, Profit_Factor, Expected_Payoff, Per1, Per2, Per3, Per4); } } } } } FastEMA = GlobalVariableGet(Per1); SlowEMA = GlobalVariableGet(Per2); SignalSMA = GlobalVariableGet(Per3); TrailingStop = GlobalVariableGet(Per4); // If the tester launching is flagged if(StartTest) { // If more time has elapsed the launching than it was set // to be the test waiting time if(TimeLocal() - TimeStart > TimeOut*60) { // Zeroize the flag StartTest = false; } }
Eso es todo. Se puede ejecutar el optimizador automático después de volver a compilarlo, pero con el mismo símbolo y período de tiempo utilizados en la pre-optimización. En nuestro caso, es EURUSD en H1. Para probar el optimizador automático, puede insertar el siguiente código en la función init (), de modo que se ejecutará el optimizador nada más iniciar el Asesor Experto.
Tester(TestDay,NameMTS,NameFileSet,PuthTester,TimeOut, Gross_Profit,Profit_Factor, Expected_Payoff, Per1,Per2,Per3,Per4);
Cómo funciona el optimizador automático
El funcionamiento del optimizador automático se basa en el uso del Terminal-Tester para optimizar los parámetros del Asesor Experto adjunto al gráfico en el Terminal. Para ello, el programa envía al Terminal-Tester un archivo que contiene los parámetros de optimización (optimise.ini) y ejecuta el Terminal-Tester en el modo optimización. A continuación copia los resultados obtenidos de "FileReport........htm" en el Terminal y selecciona los mejores valores a partir de los mismos.
Más detalles acerca del funcionamiento del optimizador automático
A la hora predefinida, por ejemplo, a las 00:01, debe ponerse en marcha el optimizador automático. Hay que rellenar las variables con sus valores.
// Path to the terminal string PuthTerminal = TerminalPath() + "\experts\files"; // Name of the ini file for the tester string FileOptim = "optimise.ini"; string FileOptim1 = "\optimise.ini"; // Calculation of the starting date datetime DayStart = TimeLocal()-86400*TestDay; // Optimization starting date string DateStart = TimeToStr(DayStart,TIME_DATE); // Optimization ending date string DateStop = TimeToStr(TimeLocal(),TIME_DATE); // Tester report file name string FileReport = "FileReport_" + Symbol() + "_" + DateStop + ".htm"; string FileReport1 = "\FileReport_" + Symbol() + "_" + DateStop + ".htm"; // Limitation for the minimum amount of trades per day double MinTr = TestDay - 2; // Limitation for maximal amount of trades per day double MaxTr = (60 / Period()*TestDay) + 2; // The amount of attempts to copy the report file int KvoPptk = 10; // The amount of lines for sorting int StepRes = 12;
A continuación se almacenan los parámetros del archivo ini en una matriz de cadenas:
// Prepare the ini file for optimization ArrayOpttim[0] = ";optimise strategy tester"; // Enable/Disable Expert Advisors ArrayOpttim[1] = "ExpertsEnable = false"; // Name of the EA file ArrayOpttim[2] = "TestExpert=" + NameMTS; // Name of the file containing parameters ArrayOpttim[3] = "TestExpertParameters=" + NameFileSet; // Symbol ArrayOpttim[4] = "TestSymbol=" + Symbol(); // Timeframe ArrayOpttim[5] = "TestPeriod=" + Period(); // Modeling mode ArrayOpttim[6] = "TestModel=" + 0; // Recalculate ArrayOpttim[7] = "TestRecalculate=false"; // Optimization ArrayOpttim[8] = "TestOptimization=true"; // Use date ArrayOpttim[9] = "TestDateEnable=true"; // From ArrayOpttim[10] = "TestFromDate=" + DateStart; // To ArrayOpttim[11] = "TestToDate=" + DateStop; // Report file name ArrayOpttim[12] = "TestReport=" + FileReport; // Rewrite the report file ArrayOpttim[13] = "TestReplaceReport=true"; // Shut down the terminal upon completion ArrayOpttim[14] = "TestShutdownTerminal=true";
Se almacenan los parámetros desde la matriz en el archivo ini. También puede leer acerca de cómo crear un archivo ini en la ayuda del Terminal de cliente MetaTrader 4: <Ayuda - Temas de ayuda F1 - Tools - Configuration at Startup>.
// Write data into the ini file // Find out about the array size OptimArraySize = ArraySize(ArrayOpttim); // Open a file to write opttim = FileOpen(FileOptim, FILE_CSV|FILE_WRITE, 0x7F); if(opttim > 0) { for(int i = 0; i < OptimArraySize; i++) { // from the array into the variable ini = ArrayOpttim[i]; // from the variable into the file FileWrite(opttim, ini); } // close the file FileClose(opttim); } else { Print("Failed writing data into the ini file. Error No ", GetLastError()); return(0); }
Una vez almacenados los parámetros en el archivo ini, se conecta el archivo shell32.dll que se encuentra en la librería estándar de Windows y se ejecuta la función ShellExecuteA.
#import "shell32.dll" //Connect a dll (provided with Windows) int ShellExecuteA(int hwnd,string Operation,string File,string Parameters,string Directory,int ShowCmd); #import
Se enviará el archivo que contiene los parámetros a la carpeta del Terminal-Tester.
// copy the ini file into the tester folder copyini = ShellExecuteA(0,"Open","xcopy", "\"" + PuthTerminal + FileOptim1 + "\" \"" + PuthTester + "\" /y", "", 3); // wait until the file is copied Sleep(1200); if(copyini < 0) { Print("Failed copying ini file"); return(0); }
A continuación se ejecuta el probador y empieza a optimizar las variables predefinidas. El Asesor Experto está en modo de espera durante la optimización.
// Start Tester start = ShellExecuteA(0, "Open", "terminal.exe", FileOptim, PuthTester, 3); if(start < 0) { Print("Failed starting Tester"); return(0); } Comment("Wait until optimization is complete"); // wait until optimization is complete Sleep(60000*TimeOut);
Una vez finalizada la optimización, el probador almacenará automáticamente los resultados en el archivo de registro. Se copia este archivo en la carpeta del terminal.
for(Pptk = 0; Pptk < KvoPptk; Pptk++) { //Start a cycle attempting to compy the resport file Comment("Attempt # " + Pptk + " to copy the report file"); ShellExecuteA(0, "Open", "xcopy", "\"" + PuthTester + FileReport1 + "\" \"" + PuthTerminal + "\" /y", "", 3); // wait until the file is copied Sleep(1200); // Try to open the report file file = FileOpen(FileReport, FILE_READ, 0x7F); if(file < 0) { // if it fails to open, wait some more and try again Sleep(60000); } else break; } if(file < 0) { Print("Failed copying the report file"); return(0); }
A continuación se colocan los datos del archivo de registro en la matriz de cadenas para su posterior procesamiento.
// Read from file into the array // Cycle, until the file ends while(FileIsEnding(file) == false) { // Read a string from the report file FileLine = FileReadString(file); // Find the necessary string and set the reference point there index = StringFind(FileLine, "title", 20); if(index > 0) { // Increase the array in size ArrayResize(ArrayStrg, NumStr + 1); // Record the strings from the file in the array ArrayStrg[NumStr] = FileLine; NumStr++; } } // Close the file FileClose(file); // Delete the file in order not to produce too many copies FileDelete(FileReport); // Set the array size by the amount of data read from the file ArrayResize(ArrayData, NumStr);
Luego se seleccionan los valores relevantes de la matriz:
for(text = 0; text < NumStr; text++) { select = ArrayStrg[text]; //------------------------------------------------------------------------- // Reporting text processing (These are apples and oranges) | //------------------------------------------------------------------------- // Position Pass ClStep=StringFind(select, "; \">",20)+4; // Find the end of position ClStepRazm = StringFind(select, "td>", ClStep); // Read the value CycleStep = StringSubstr(select, ClStep, ClStepRazm - ClStep); // Position Profit // Find the beginning of the position GrProf = StringFind(select, "", ClStepRazm); // Find the end of position GrProfRazm = StringFind(select, "td>", GrProf); // Read value GrossProfit = StringSubstr(select, GrProf+4, GrProfRazm - (GrProf + 4)); // Position Total Trades // Find the beginning of position TotTrad = StringFind(select, "", GrProfRazm); // Find the end of position TotTradRazm = StringFind(select, "td>", TotTrad); // Read the value TotalTrades = StringSubstr(select, TotTrad+4, TotTradRazm - (TotTrad + 4)); // Position Profitability // Find the beginning of position ProfFact = StringFind(select, "", TotTradRazm); // Find the end of position ProfFactRazm = StringFind(select, "td>", ProfFact); // Read the value ProfitFactor = StringSubstr(select, ProfFact + 4, ProfFactRazm - (ProfFact + 4)); // Position Expected Payoff // Find the beginning of position ExpPay = StringFind(select, "", ProfFactRazm); // Find the dn of position ExpPayRazm=StringFind(select, "td>", ExpPay); // Read the value ExpectedPayoff = StringSubstr(select, ExpPay+4, ExpPayRazm - (ExpPay + 4)); // Variables' positions starting with the second one // Find the beginning of position P1 = StringFind(select, Per1, 20); // Find the end of position P1k = StringFind(select, ";", P1); // Read the Variable Perem1 = StringSubstr(select, P1 + StringLen(Per1) + 1, P1k - (P1 + 1 + StringLen(Per1))); // Find the beginning of position P2 = StringFind(select, Per2, 20); // Find the end of position P2k = StringFind(select, ";", P2); // Read the Variable Perem2 = StringSubstr(select, P2 + StringLen(Per2) + 1, P2k - (P2 + 1 + StringLen(Per2))); // Find the beginning of position P3 = StringFind(select, Per3, 20); // Find the end of position P3k = StringFind(select, ";", P3); // Read the Variable Perem3 = StringSubstr(select, P3 + StringLen(Per3) + 1, P3k - (P3 + 1 + StringLen(Per3))); // Find the beginning of position P4 = StringFind(select, Per4, 20); // Find the end of position P4k = StringFind(select, ";", P4); // Read the Variable Perem4 = StringSubstr(select, P4 + StringLen(Per4) + 1, P4k - (P4 + 1 + StringLen(Per4))); Comment("The obtained results are being analyzed");
Después de eso, y antes de transformarlos a un formato numérico, se filtran los resultados obtenidos mediante el número mínimo y máximo de operaciones. Se sustituye el valor cero de Profit_Factor por 1000 para corregir la clasificación y la posterior selección.
// Transform into number format TotalTradesTransit = StrToDouble(TotalTrades); GrossProfitTransit = StrToDouble(GrossProfit); ExpectedPayoffTran = StrToDouble(ExpectedPayoff); nodubl = true; if(MinTr < TotalTradesTransit && MaxTr > TotalTradesTransit) { // Filter by the amount of trades PrFactDouble = StrToDouble(ProfitFactor); // Replace 0 in the Profit_Factor for proper analysis if(PrFactDouble == 0) { PrFactDouble = 1000; }
A continuación se comprueban las duplicidades y se filtran.
// Filter data having identical values for(Dubl = 0; Dubl <= ResizeArayNew; Dubl++) { // Start the loop searching for identical values if(GrossProfitTransit == ArrayData[Dubl][1]) { // check whether the results for maximal profit coincide if(TotalTradesTransit == ArrayData[Dubl][2]) { // check whether the results for the amount of trades coincide if(PrFactDouble == ArrayData[Dubl][3]) { // check whether the results for Profit Factor coincide if(ExpectedPayoffTran == ArrayData[Dubl][4]) { // check whether the results for expected payoff coincide nodubl=false; // If everything coincides, flag it as coincided } } } } }
Luego se almacenan los valores que ya están listos para su clasificación en la matriz.
// Write the filtered data in the array if(nodubl) { ArrayData[text][1] = GrossProfitTransit; ArrayData[text][2] = TotalTradesTransit; ArrayData[text][3] = PrFactDouble; ArrayData[text][4] = ExpectedPayoffTran; ArrayData[text][5] = StrToDouble(Perem1); ArrayData[text][6] = StrToDouble(Perem2); ArrayData[text][7] = StrToDouble(Perem3); ArrayData[text][8] = StrToDouble(Perem4); ResizeArayNew++; }
Y al final se inicia el análisis de los datos en el orden de prioridad preestablecido. Se lleva a cabo el análisis de la siguiente manera:
- se inicia el bucle y en la primera pasada se clasifican los valores en función del primer parámetro, por ejemplo, en función del beneficio máximo (Maximal Profit); se seleccionan algunos de los mejores valores (12 por defecto), se descartan los otros valores.
- en la segunda pasada se clasifican los valores en función del segundo parámetro, por ejemplo, en función del factor de beneficio (Profit Factor); se seleccionan algunos de los mejores valores, la mitad después de la primera clasificación, y se descartan los otros valores.
- en la tercera pasada se lleva a cabo la última clasificación en función del tercer parámetro, por ejemplo, en función de la rentabilidad esperada (Expected Payoff); se selecciona la mitad de los valores después de la segunda clasificación, y se descartan los otros valores.
// Analyzer // Analyzing principle is the sequential checking of maximal // values according to the predefined filtering priority ArrayResize(ArrayTrans, ResizeArayNew - 1); for(int PrioStep = 1; PrioStep < 4; PrioStep++) { for(PrCycle = 0; PrCycle < ResizeArayNew; PrCycle++) { Sort = ArrayData[PrCycle][0]; Prior1 = ArrayData[PrCycle][1]; transit = ArrayData[PrCycle][2]; Prior2 = ArrayData[PrCycle][3]; Prior3 = ArrayData[PrCycle][4]; transit1 = ArrayData[PrCycle][5]; transit2 = ArrayData[PrCycle][6]; transit3 = ArrayData[PrCycle][7]; transit4 = ArrayData[PrCycle][8]; if(PrioStep == 1) { //Prepare for the 1st sorting if(Gross_Profit ==1) { SortTrans = Prior1; } if(Profit_Factor == 1) { SortTrans = Prior2; } if(Expected_Payoff == 1) { SortTrans = Prior3; } } if(PrioStep == 2) { // Restore if(Gross_Profit ==1) { Prior1 = Sort; } if(Profit_Factor == 1) { Prior2 = Sort; } if(Expected_Payoff == 1) { Prior3 = Sort; } //Prepare for the 2nd sorting if(Gross_Profit == 2) { SortTrans = Prior1; } if(Profit_Factor == 2) { SortTrans = Prior2; } if(Expected_Payoff == 2) { SortTrans = Prior3; } } if(PrioStep == 3) { // Restore if(Gross_Profit == 2) { Prior1 = Sort; } if(Profit_Factor == 2) { Prior2 = Sort; } if(Expected_Payoff == 2) { Prior3 = Sort; } //Prepare for the 3rd sorting if(Gross_Profit ==3) { SortTrans = Prior1; } if(Profit_Factor == 3) { SortTrans = Prior2; } if(Expected_Payoff == 3) { SortTrans = Prior3; } } ArrayTrans[PrCycle][0] = SortTrans; ArrayTrans[PrCycle][1] = Prior1; ArrayTrans[PrCycle][2] = transit; ArrayTrans[PrCycle][3] = Prior2; ArrayTrans[PrCycle][4] = Prior3; ArrayTrans[PrCycle][5] = transit1; ArrayTrans[PrCycle][6] = transit2; ArrayTrans[PrCycle][7] = transit3; ArrayTrans[PrCycle][8] = transit4; } ArraySort(ArrayTrans,StepRes, 0, MODE_DESCEND); // Sort the array ArrayResize(ArrayTrans, StepRes); // Cut off the unnecessary things for(int CopyAr = 0; CopyAr < StepRes; CopyAr++) { ArrayData[CopyAr][0] = ArrayTrans[CopyAr][0]; ArrayData[CopyAr][1] = ArrayTrans[CopyAr][1]; ArrayData[CopyAr][2] = ArrayTrans[CopyAr][2]; ArrayData[CopyAr][3] = ArrayTrans[CopyAr][3]; ArrayData[CopyAr][4] = ArrayTrans[CopyAr][4]; // Per1 Variable 1 ArrayData[CopyAr][5] = ArrayTrans[CopyAr][5]; // Per2 Variable 2 ArrayData[CopyAr][6] = ArrayTrans[CopyAr][6]; // Per3 Variable 3 ArrayData[CopyAr][7] = ArrayTrans[CopyAr][7]; // Per4 Variable 4 ArrayData[CopyAr][8] = ArrayTrans[CopyAr][8]; } StepRes = StepRes / 2; }
Se almacenan los valores filtrados de esta forma en las variables globales. Se sustituyen las variables del Asesor Experto a partir de los valores de las variables globales.
// Write the obtained results in variables double Peremen1 = ArrayTrans[0][5]; double Peremen2 = ArrayTrans[0][6]; double Peremen3 = ArrayTrans[0][7]; double Peremen4 = ArrayTrans[0][8]; // If the variable name is specified, write the result in // global variables if(Per1 != "") { GlobalVariableSet(Per1, Peremen1); } if(Per2 != "") { GlobalVariableSet(Per2,Peremen2); } if(Per3 != "") { GlobalVariableSet(Per3,Peremen3); } if(Per4 != "") { GlobalVariableSet(Per4,Peremen4); } Comment(Per1, " ", Peremen1, " | ", Per2, " ", Peremen2, " | ", Per3, " ", Peremen3, " | ", Per4, " ", Peremen4); Print(Per1, " ", Peremen1, " | ", Per2, " ", Peremen2, " | ", Per3, " ", Peremen3," | ",Per4," ",Peremen4); } // Function ends. That's all, automated optimization is complete.
Resultados del optimizador automático
Se pueden seguir los resultados del optimizador automático mediante los mensajes que aparecen en la esquina superior izquierda del gráfico, como se muestra en la siguiente captura de pantalla:
Tiempo estimado para finalizar la optimización.
Análisis de los valores obtenidos después de la optimización.
Resultados de las variables.
La aparición de los resultados de la optimización indica que esta última se ha completado y que los datos han sido recibidos.
Para hacer una evaluación del optimizador automático de un modo independiente, se puede echar un vistazo a todos los archivos guardados durante el proceso y que contienen datos intermedios. El probador almacena los datos en un archivo llamado "FileReport_EURUSD_2007.03. 12. htm", donde se sustituye el símbolo y la fecha del nombre del archivo por el símbolo seleccionado y la fecha de optimización. Se puede encontrar este archivo en la carpeta del Terminal-Tester. Estos archivos no se eliminan automáticamente de los registros y se pueden utilizar para realizar el seguimiento de cambio de los parámetros.
El siguiente archivo, FileTest1.csv, se guarda después del filtrado de los valores mediante el número de operaciones y el borrado de las duplicidades. Se guarda el archivo en: D:\Program Files\terminal_folder_ame\experts\files
Se almacenan los archivos obtenidos después de cada pasada en el archivo FileTest2.csv. Se guarda el archivo en esta carpeta también: D:\Program Files\terminal_folder_name\experts\files
Las tablas anteriores muestran cómo se filtran los valores obtenidos. Se ha establecido por defecto este orden de filtrado: 1- Gross_Profit, 2- Profit_Factor, 3- Expected_Payoff.
El optimizador automático incluye comentarios detallados y, si es necesario, se pueden elegir parámetros de variables más convenientes. Por ejemplo, quiere optimizar su Asesor Experto con un período de tiempo distinto a los últimos días, o tiene la intención de aumentar o disminuir el número de operaciones en el período de optimización. Para ello, sólo hay que cambiar las variables correspondientes en el propio auto_optimization.mqh.
// Limitation of minimal amount of trades per day double MinTr = TestDay - 2; // Limitation on maximal amount of trades per day double MaxTr = (60 / Period()*TestDay) + 2; // The amount of attempts to copy the report file int KvoPptk = 10; // The amount of strings to be sorted int StepRes = 12;
Conclusión
Este artículo no está destinado a enseñar los fundamentos de la optimización a los principiantes, por lo que es muy recomendable estudiar la optimización normal antes de configurar la optimización automática de su Asesor Experto. Es mejor utilizar el optimizador automático después de haber elegido las principales variables que afectan a su Asesor Experto de manera distinta y en distintos momentos. Es decir, es mejor utilizar este optimizador automático para ajustar los parámetros de las variables cuyos cambios afectan el funcionamiento del Asesor Experto más que los cambios de otras variables, dependiendo de la volatilidad del mercado.
Además, es mejor no establecer un período de optimización automática muy largo. Supongamos que el Asesor Experto se ha optimizado durante 6-12 horas cada día. Entonces surge la pregunta: ¿Cuándo va a operar? En otras palabras, la optimización no sirve de mucho por sí sola. Se recomienda establecer la periodicidad de la optimización (es decir, la periodicidad de ejecución del optimizador) teniendo en cuenta el período de tiempo en el cual se supone que está operando el Asesor Experto. Esto quiere decir que hay que tener en cuenta que los datos del historial serán transmitidos al iniciar el Terminal-Tester y es posible que el broker no dispone de los datos relevantes del historial para un determinado período de tiempo. Para comprobar la hipótesis descrita al inicio de este artículo, es necesario disponer de una conexión ininterrumpida y estable a Internet.
Los programas de optimización automático que se han desarrollado se encuentran en los archivos adjuntos: auto_optimization.mqh - la misma librería, MACD Sample_1.mq4 - el Asesor Experto incluido en el paquete estándar del Terminal de cliente MetaTrader 4, con una ligera modificación.
Traducción del ruso hecha por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/ru/articles/1467
- Aplicaciones de trading gratuitas
- 8 000+ señales para copiar
- Noticias económicas para analizar los mercados financieros
Usted acepta la política del sitio web y las condiciones de uso