Method of Determining Errors in Code by Commenting

Eryomin Sergey | 22 August, 2008

Introduction

This article describes a simple algorithm of searching the errors in an MQL code. The problems during the compilation due to the errors in the code often occur after writing a program. These can be all sorts of errors, but any way it is necessary to quickly recognize the code block where the error is committed.

As often as not, people spend a lot of time and nerves on searching some odd bracket. However, there is a method of fast location of errors that is based on the usage of commenting. So it is the method I'll tell you about in this article.

Conception

Writing a large code without any mistakes is quiet pleasant. But unfortunately this happens not always. There is even a joke that there was no programs written without any mistakes. I do not consider here the mistakes that bring to wrong execution of a code. Here the question is about the errors that make the compilation impossible.

The highly widespread errors are: inserting an odd bracket in a complex condition, lack of a bracket, not putting a colon, a comma (during variables declaration), etc. Often we can see which entry contains the error during the compilation at once. But there are cases when finding such kind of mistakes is not so easy. Neither the compiler nor a sharp-sighted eye can't help us to find the mistake at once. In this case the apprentice (and not) programmers, as a rule, begin to go through all code trying to detect the error visually. Again and again until the nerves run dry and its said: "It is easier to write newly"!

However, the MQL just the same as the other programming languages offers an incredible tool - commenting. You can "remove", "disable" some parts of the code using it. Usually the commentation is used for inserting the comments, namely, or for disabling the unused parts of the code. The commentation can also be successfully used for errors searching.

Algorithm of Errors Searching

The search for errors usually comes to determining the part of the code where the error was made, and then the error is visually searched for in it. I think that none will doubt that it is much easier and faster to examine 5-10 code entries "by the eye" than 100-150 entries.

The problem appears to be easily solved when using the commenting. First of all it is necessary to comment some differnet parts of the code (sometimes almost the whole code) "disabling" it, thereby. And then the commentation is removed from that parts of the code. After a regular comment removing a try to compile the code is performed. If the compilation succeeded than the error is not in that part of the code. After that the next part of the code is opened and so on. When the problem part of the code is found the error is visually searched and cured. A try to compile is performed again. If everything passed successfully than the error is eliminated.

In case of new errors appearance the procedure is repeated until they will be eliminated. This approach is very useful when writing the large programs, and not infrequently it works when writing relatively small codes.

It is very important to correctly determine the blocks of the code that are to be commented. If it is a condition (or another logical construction) then it should be fully commented. If you comment a block where the variables are declared then it is important not to leave open the block that adverts to these variables. That is to say the commentation should be used by the logic of programming. Infringing this approach will cause the new misinforming errors to appear during the compilation.

Example

I will exemplify the practical search of an error in code. Suppose we have a code:

#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);
  }
//+------------------------------------------------------------------+

We see the following error message during the compilation:


It is impossible to detect quickly the block where the error was made. We fall back upon the commenting. Comment all logical constructions:

#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);
  }
//+------------------------------------------------------------------+

You can easily make sure that this code can be compiled without problems. It means that the part of the code where the error was made is "hidden". Open the parts of the code /* ... */ by turns and try to compile it.

The compilation will be successful until we reach the following block of the code:

//***************************************************************************
 
 
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; 
 }

Therefore, the error is in this logical construction. We can see that there is an odd round bracket in the construction during the detailed examination of this part of the code:

   for(i=Level1; i>=0; i--)
  {
   {
    if(Open[i]>iSAR(NULL,0,0.02,0.1,i))
    {
     trend_DOWN=false; break;
    }
    
   }

If we remove it, the code will be successfully compiled.

We will make sure that there are no other errors in the code by removing the remain comments. It means that we attained our aim - the error in the code was found sufficiently quickly.

Conclusion

It was shown on a practice example how to use this algorithm for searching the errors. Not a small code (194 entries) was used in this example, so its "investigation" could take a long time. The possibility of commenting itself save sufficiently enough time for programmers that come across with the problem of errors searching.