Download MetaTrader 5

Method of Determining Errors in Code by Commenting

22 August 2008, 08:40
Eryomin Sergey
2
535

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.

Translated from Russian by MetaQuotes Software Corp.
Original article: https://www.mql5.com/ru/articles/1547

Last comments | Go to discussion (2)
Bogdan Caramalac
Bogdan Caramalac | 23 Aug 2008 at 10:57

Nice article, I do the same way to find errors, especially the ones about parentheses :)) 

Sometimes I also move some of the code in open notepad windows.

MQL4 Comments
MQL4 Comments | 23 Aug 2008 at 13:00

HI

Yes this is the way I have been debugging code for the 40 years I have been programming. I thought it was what we all did.

Ross

Step on New Rails: Custom Indicators in MQL5 Step on New Rails: Custom Indicators in MQL5

I will not list all of the new possibilities and features of the new terminal and language. They are numerous, and some novelties are worth the discussion in a separate article. Also there is no code here, written with object-oriented programming, it is a too serous topic to be simply mentioned in a context as additional advantages for developers. In this article we will consider the indicators, their structure, drawing, types and their programming details, as compared to MQL4. I hope that this article will be useful both for beginners and experienced developers, maybe some of them will find something new.

Here Comes the New MetaTrader 5 and MQL5 Here Comes the New MetaTrader 5 and MQL5

This is just a brief review of MetaTrader 5. I can't describe all the system's new features for such a short time period - the testing started on 2009.09.09. This is a symbolical date, and I am sure it will be a lucky number. A few days have passed since I got the beta version of the MetaTrader 5 terminal and MQL5. I haven't managed to try all its features, but I am already impressed.

Using text files for storing input parameters of Expert Advisors, indicators and scripts Using text files for storing input parameters of Expert Advisors, indicators and scripts

The article describes the application of text files for storing dynamic objects, arrays and other variables used as properties of Expert Advisors, indicators and scripts. The files serve as a convenient addition to the functionality of standard tools offered by MQL languages.

How to create an indicator of non-standard charts for MetaTrader Market How to create an indicator of non-standard charts for MetaTrader Market

Through offline charts, programming in MQL4, and reasonable willingness, you can get a variety of chart types: "Point & Figure", "Renko", "Kagi", "Range bars", equivolume charts, etc. In this article, we will show how this can be achieved without using DLL, and therefore such "two-for-one" indicators can be published and purchased from the Market.