Método para encontrar los errores en el código mediante comentarios
Introducción
Este artículo describe un algoritmo simple de búsqueda de errores en un código MQL. El problema durante la compilación debido a los errores en el código suelen producirse después de escribir un programa. Estos pueden ser todo tipo de errores, pero en cualquier caso es necesario reconocer rápidamente el bloque de código donde se ha cometido el error.
En la mayoría de casos, la gente dedica mucho tiempo y nervios a la búsqueda de algún corchete extraño. No obstante, hay un método para la localización rápida de errores que se basa en el uso de los comentarios. Por ello este es el método del que voy a hablar en este artículo.
El concepto
Escribir un código extenso sin errores es bastante placentero. Pero por desgracia esto no siempre ocurre. Hay incluso una broma según la cual no hay programas escritos sin errores. No voy a tener en cuenta los errores llevan a una ejecución incorrecta del código. Aquí la cuestión se centra en los errores que hacen que la compilación sea imposible.
Los errores más habituales son: insertar corchetes extraños en una condición compleja, falta de un corchete, no poner dos puntos, una coma (durante la declaración de las variables), etc. A menudo, podemos ver qué entrada contiene el error durante la compilación inmediatamente. Pero hay casos en los que encontrar este tipo de errores no es tan fácil. Ni el compilador ni un ojo avezado pueden ayudarnos a encontrar el error de inmediato. En este caso, los programadores novatos (y los que no lo son), por lo general, comienzan a revisar el código intentando detectar el error visualmente. Una y otra vez hasta que pierden los nervios y dicen: "¡Es más fácil escribirlo de nuevo!"
Sin embargo, MQL, al igual que otros lenguajes de programación, ofrece una increíble herramienta: los comentarios. Podemos "eliminar" y "deshabilitar" algunas partes del código usándolos. Normalmente, los comentarios se usan para insertar notas, a saber, o para deshabilitar las partes no usadas del código. El comentario puede usarse también con éxito para la búsqueda de errores.
Algoritmo de búsqueda de errores
La búsqueda de errores consiste por lo general en encontrar la parte del código donde se ha producido un error y luego este se busca visualmente. Creo que nadie dudará que es mucho más fácil y rápido examinar 5 a 10 entradas de código "a ojo" que 100 a 150 entradas.
El problema parece resolverse fácilmente cuando se usan los comentarios. En primer lugar, es necesario comentar distintas partes del código (algunas veces casi todo el código) "deshabilitándola", en consecuencia. Y luego se elimina el comentario de esta parte del código. Después de eliminar regularmente el comentario se realiza un intento de compilar el código. Si la compilación tiene éxito, el error no está en esa parte del código. Después de esto, se abre la siguiente parte del código y así sucesivamente. Cuando se encuentra la parte problemática del código, se busca visualmente y se soluciona. Se realiza de nuevo un intento de compilación. Si todo tiene lugar correctamente, se elimina el error.
En caso de que aparezcan nuevos errores, se repite el procedimiento hasta que sean eliminados. Este método es muy útil al escribir grandes programas y con frecuencia funciona cuando se escriben códigos relativamente pequeños.
Es muy importante determinar correctamente los bloques del código que deben comentarse. Si es una condición (u otra construcción lógica), esta debe comentarse completamente. Si comentamos un bloque en el que se declaran las variables, es importante no dejar abierto el bloque que alude a estas variables. Esto quiere decir que los comentarios deben usarse de acuerdo con la lógica de la programación. Incumplir este método provocará que aparezcan los mismos errores durante la compilación.
Ejemplo
Pondré un ejemplo de la búsqueda en la práctica de un error en el código. Supongamos que tenemos un código:
#property copyright "" #property link "" extern int Level1=6; extern int Level2=2; extern double Lots=0.1; extern int TP=7; extern int SL=5000; extern int Profit_stop=10; int start() { //+--------------------------------------------------------------------------------------------------+ //| search for opened orders by symbol int pos_sell=0; for (int i_op_sell=OrdersTotal()-1; i_op_sell>=0; i_op_sell--) { if (!OrderSelect(i_op_sell,SELECT_BY_POS,MODE_TRADES)) break; if (Symbol()==OrderSymbol()&&(OrderType()==OP_SELLSTOP||OrderType()==OP_SELL) &&(OrderComment()=="sar_ao")) { pos_sell=1; break; } } int pos_buy=0; for (int i_op_buy=OrdersTotal()-1; i_op_buy>=0; i_op_buy--) { if (!OrderSelect(i_op_buy,SELECT_BY_POS,MODE_TRADES)) break; if (Symbol()==OrderSymbol()&&(OrderType()==OP_BUYSTOP||OrderType()==OP_BUY) &&(OrderComment()=="sar_ao")) { pos_buy=1; break; } } //| search for opened orders by symbol | //+-------------------------------------------------------------------------------------------------+ //+-------------------------------------------------------------------------------------------------+ //| stop for break-even double stop_open; for (int ia=OrdersTotal()-1; ia>=0; ia--) { if (!OrderSelect(ia,SELECT_BY_POS,MODE_TRADES)) break; if ((OrderType()==OP_BUY)&&(Symbol()==OrderSymbol())&&(OrderComment()=="sar_ao")) { stop_open=OrderOpenPrice(); if (NormalizeDouble(Bid,Digits)-stop_open<=Profit_stop*Point) continue; OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()+1*Point,OrderTakeProfit(), OrderExpiration(),CLR_NONE); } if ((OrderType()==OP_SELL)&&(Symbol()==OrderSymbol())&&(OrderComment()=="sar_ao")) { stop_open=OrderOpenPrice(); if (stop_open-NormalizeDouble(Ask,Digits)<=Profit_stop*Point) continue; OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()-1*Point,OrderTakeProfit(), OrderExpiration(),CLR_NONE); } } //| stop for break-even | //+-------------------------------------------------------------------------------------------------+ int i; bool trend_UP=true,trend_DOWN=true; //+------------------------------------------------------------------------------- if(!pos_buy) { for(i=Level1; i>=0; i--) { if(Open[i]<iSAR(NULL,0,0.02,0.1,i)) { trend_UP=false; break; } } for(i=Level2*2; i>=0; i--) { if(i>Level2) { if(iAO(NULL, 0, i+1)<=iAO(NULL, 0, i)) { trend_UP=false; break; } } if(i<Level2) { if(iAO(NULL, 0, i+1)>=iAO(NULL, 0, i)) { trend_UP=false; break; } } } } else { trend_UP=false; } //*************************************************************************** if(!pos_sell) { for(i=Level1; i>=0; i--) { { if(Open[i]>iSAR(NULL,0,0.02,0.1,i)) { trend_DOWN=false; break; } } for(i=Level2*2; i>=0; i--) { if(i>Level2) { if(iAO(NULL, 0, i+1)>=iAO(NULL, 0, i)) { trend_DOWN=false; break; } } if(i<Level2) { if(iAO(NULL, 0, i+1)<=iAO(NULL, 0, i)) { trend_DOWN=false; break; } } } } else { trend_DOWN=false; } if(Open[0]>iSAR(NULL,0,0.02,0.2,0)) { ObjectDelete("sell"); } if(Open[0]<iSAR(NULL,0,0.02,0.2,0)) { ObjectDelete("buy"); } double MA_1; MA_1=iStochastic(NULL,0,5,3,3,MODE_SMA,0,MODE_SIGNAL,0); if(trend_UP && MA_1<50 && Open[1]<Close[1] && !pos_buy && ObjectFind("buy") != 0) { OrderSend(Symbol(),OP_BUY, Lots,Ask,2,Ask-SL*Point,Ask+TP*Point,"sar_ao",0,0,Blue); ObjectCreate("buy", OBJ_ARROW, 0, Time[0], Bid); ObjectSet("buy", OBJPROP_STYLE, STYLE_DOT); ObjectSet("buy", OBJPROP_ARROWCODE, SYMBOL_ARROWUP); ObjectSet("buy", OBJPROP_COLOR, LightSeaGreen); } if(trend_DOWN && MA_1>50 && Open[1]>Close[1] && !pos_sell && ObjectFind("sell") != 0) { OrderSend(Symbol(),OP_SELL, Lots,Bid,2,Bid+SL*Point,Bid-TP*Point,"sar_ao",0,0,Red); ObjectCreate("sell", OBJ_ARROW, 0, Time[0], Bid); ObjectSet("sell", OBJPROP_STYLE, STYLE_DOT); ObjectSet("sell", OBJPROP_ARROWCODE, SYMBOL_ARROWDOWN); ObjectSet("sell", OBJPROP_COLOR, Red); } //+------------------------------------------------------------------------------- //---- return(0); } //+------------------------------------------------------------------+
Vemos el siguiente mensaje de error durante la compilación:
Es imposible detectar rápidamente el bloque donde se ha producido el error. Volvemos de nuevo al comentario. Comentamos todas las construcciones lógicas:
#property copyright "" #property link "" extern int Level1=6; extern int Level2=2; extern double Lots=0.1; extern int TP=7; extern int SL=5000; extern int Profit_stop=10; int start() { /* //+-----------------------------------------------------------------------------------------------+ //| search for opened orders by symbol | int pos_sell=0; for (int i_op_sell=OrdersTotal()-1; i_op_sell>=0; i_op_sell--) { if (!OrderSelect(i_op_sell,SELECT_BY_POS,MODE_TRADES)) break; if (Symbol()==OrderSymbol()&&(OrderType()==OP_SELLSTOP||OrderType()==OP_SELL) &&(OrderComment()=="sar_ao")) { pos_sell=1; break; } } int pos_buy=0; for (int i_op_buy=OrdersTotal()-1; i_op_buy>=0; i_op_buy--) { if (!OrderSelect(i_op_buy,SELECT_BY_POS,MODE_TRADES)) break; if (Symbol()==OrderSymbol()&&(OrderType()==OP_BUYSTOP||OrderType()==OP_BUY) &&(OrderComment()=="sar_ao")) { pos_buy=1; break; } } //| search for opened orders by symbol | //+----------------------------------------------------------------------------------------------+ */ /* //+----------------------------------------------------------------------------------------------+ //| stop for break-even | double stop_open; for (int ia=OrdersTotal()-1; ia>=0; ia--) { if (!OrderSelect(ia,SELECT_BY_POS,MODE_TRADES)) break; if ((OrderType()==OP_BUY)&&(Symbol()==OrderSymbol())&&(OrderComment()=="sar_ao")) { stop_open=OrderOpenPrice(); if (NormalizeDouble(Bid,Digits)-stop_open<=Profit_stop*Point) continue; OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()+1*Point,OrderTakeProfit(), OrderExpiration(),CLR_NONE); } if ((OrderType()==OP_SELL)&&(Symbol()==OrderSymbol())&&(OrderComment()=="sar_ao")) { stop_open=OrderOpenPrice(); if (stop_open-NormalizeDouble(Ask,Digits)<=Profit_stop*Point) continue; OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()-1*Point,OrderTakeProfit(), OrderExpiration(),CLR_NONE); } } //| stop for break-even | //+---------------------------------------------------------------------------------------------+ */ /* int i; bool trend_UP=true,trend_DOWN=true; //+------------------------------------------------------------------------------- if(!pos_buy) { for(i=Level1; i>=0; i--) { if(Open[i]<iSAR(NULL,0,0.02,0.1,i)) { trend_UP=false; break; } } for(i=Level2*2; i>=0; i--) { if(i>Level2) { if(iAO(NULL, 0, i+1)<=iAO(NULL, 0, i)) { trend_UP=false; break; } } if(i<Level2) { if(iAO(NULL, 0, i+1)>=iAO(NULL, 0, i)) { trend_UP=false; break; } } } } else { trend_UP=false; } */ //*************************************************************************** /* if(!pos_sell) { for(i=Level1; i>=0; i--) { { if(Open[i]>iSAR(NULL,0,0.02,0.1,i)) { trend_DOWN=false; break; } } for(i=Level2*2; i>=0; i--) { if(i>Level2) { if(iAO(NULL, 0, i+1)>=iAO(NULL, 0, i)) { trend_DOWN=false; break; } } if(i<Level2) { if(iAO(NULL, 0, i+1)<=iAO(NULL, 0, i)) { trend_DOWN=false; break; } } } } else { trend_DOWN=false; } */ /* if(Open[0]>iSAR(NULL,0,0.02,0.2,0)) { ObjectDelete("sell"); } if(Open[0]<iSAR(NULL,0,0.02,0.2,0)) { ObjectDelete("buy"); } */ double MA_1; MA_1=iStochastic(NULL,0,5,3,3,MODE_SMA,0,MODE_SIGNAL,0); /* if(trend_UP && MA_1<50 && Open[1]<Close[1] && !pos_buy && ObjectFind("buy") != 0) { OrderSend(Symbol(),OP_BUY, Lots,Ask,2,Ask-SL*Point,Ask+TP*Point,"sar_ao",0,0,Blue); ObjectCreate("buy", OBJ_ARROW, 0, Time[0], Bid); ObjectSet("buy", OBJPROP_STYLE, STYLE_DOT); ObjectSet("buy", OBJPROP_ARROWCODE, SYMBOL_ARROWUP); ObjectSet("buy", OBJPROP_COLOR, LightSeaGreen); } */ /* if(trend_DOWN && MA_1>50 && Open[1]>Close[1] && !pos_sell && ObjectFind("sell") != 0) { OrderSend(Symbol(),OP_SELL, Lots,Bid,2,Bid+SL*Point,Bid-TP*Point,"sar_ao",0,0,Red); ObjectCreate("sell", OBJ_ARROW, 0, Time[0], Bid); ObjectSet("sell", OBJPROP_STYLE, STYLE_DOT); ObjectSet("sell", OBJPROP_ARROWCODE, SYMBOL_ARROWDOWN); ObjectSet("sell", OBJPROP_COLOR, Red); } */ //+------------------------------------------------------------------------------- //---- return(0); } //+------------------------------------------------------------------+
Podemos estar seguros fácilmente de que este código puede compilarse sin problemas. Esto significa que la parte del código donde estaba el error está "oculta". Abrimos las partes del código /* ... */ sucesivamente e intentamos compilarlas.
La compilación tendrá éxito hasta que alcancemos el siguiente bloque del código:
//*************************************************************************** if(!pos_sell) { for(i=Level1; i>=0; i--) { { if(Open[i]>iSAR(NULL,0,0.02,0.1,i)) { trend_DOWN=false; break; } } for(i=Level2*2; i>=0; i--) { if(i>Level2) { if(iAO(NULL, 0, i+1)>=iAO(NULL, 0, i)) { trend_DOWN=false; break; } } if(i<Level2) { if(iAO(NULL, 0, i+1)<=iAO(NULL, 0, i)) { trend_DOWN=false; break; } } } } else { trend_DOWN=false; }
Por tanto, el error está en esta construcción lógica. Podemos ver que ahí hay un paréntesis extraño en la construcción durante el examen detallado de esta parte del código:
for(i=Level1; i>=0; i--) { { if(Open[i]>iSAR(NULL,0,0.02,0.1,i)) { trend_DOWN=false; break; } }
Si la eliminamos, el código se compilará correctamente.
Nos aseguramos de que no hay otros errores en el código eliminando los restantes comentarios. Esto significa que logramos nuestro objetivo: encontramos el error en el código con la suficiente rapidez.
Conclusión
Se ha mostrado a través de un ejemplo práctico cómo usar este algoritmo para la búsqueda de errores. Se usó un código no muy pequeño (194 entradas) en este ejemplo, por lo que su "investigación" podría haber llevado un largo tiempo. La posibilidad de comentar permite ahorrar el tiempo suficiente a los programadores que se encuentran con el problema de la búsqueda de errores.
Traducción del ruso hecha por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/ru/articles/1547
- 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