English Русский 中文 Español Deutsch 日本語
Método de determinação de erros no código por comentários

Método de determinação de erros no código por comentários

MetaTrader 4Exemplos | 8 fevereiro 2016, 12:18
425 0
Eryomin Sergey
Eryomin Sergey

Introdução

O artigo descreve um algoritmo simples de busca de erros em um código MQL. Os problemas durante a compilação devido aos erros no código ocorrem com frequência depois de escrever um programa. Eles podem ser de todo tipo, mas de qualquer forma é necessário reconhecer rapidamente o bloco do código em que o erro foi cometido.

Com ou sem frequência, as pessoas gastam muito tempo e nervos na busca por um colchete sem par. Entretanto, há um método de rápida localização de erros que é baseado no uso de comentários. Então, é o método que explicarei para você neste artigo.

Concepção

Escrever um código grande sem nenhum erro é bem prazeroso. Mas, infelizmente, isso não acontece sempre. Há até uma piada sobre não ter programas escritos sem erros. Não considero aqui os erros que levam a execução errada de um código. Aqui, a questão é sobre os erros que tornam a compilação possível.

Os erros altamente propagados são: inserir um colchete sem par em uma condição complexa, ausência de um colchete, não colocar dois pontos, uma vírgula (durante a declaração de variáveis) etc. Com frequência, podemos ver imediatamente quais entradas contêm o erro durante a compilação. Mas há casos em que encontrar tal tipo de erros não é tão fácil. Nem o compilador ou um olho de águia podem nos ajudar a encontrar o erro logo de cara. Nesse caso, os programadores aprendizes (ou não), como regra, começam a revisar todo o código tentando detectar o erro visualmente. Uma vez e outra até que os nervos acabem e seja concluído: “É mais fácil escrever um novo!"

No entanto, o MQL, como outras linguagens de programação, oferece uma ferramenta incrível - os comentários. É possível "remover", "desabilitar" algumas partes do código usando eles. Normalmente, os comentários são usados para inserir comentários, especificamente, ou para desabilitar as partes não usadas do código. O comentário também pode ser usado com sucesso para os erros de busca.

Algoritmo de busca de erros

A busca de erros normalmente vem para determinar a parte do código em que o erro foi feito, e depois o erro é buscado visualmente nele. Acho que ninguém duvidará que é muito mais fácil e rápido examinar de 5 a 10 entradas de código "com os olhos" que de 100 a 150 entradas.

O problema parece ser resolvido facilmente quando usamos os comentários. Primeiro, é necessário comentar em algumas partes diferentes do código (às vezes, em quase todo o código), "desabilitando" ele, dessa forma. E depois, o comentário é removido dessas partes do código. Depois de um comentário regular de remoção, uma tentativa de compilar o código é feita. Se a compilação foi bem-sucedida, então o erro não está naquela parte do código. Depois disso, a próxima parte do código é aberta e assim por diante. Quando a parte do problema do código for encontrada, o erro será visualmente buscado e curado. Uma nova tentativa de compilar é feita. Se tudo passar, então o erro foi eliminado.

No caso de novos erros aparecerem, o procedimento é repetido até que eles sejam eliminados. Essa abordagem é muito útil ao escrever programas grandes, e não é pouco frequente que funcione ao escrever código relativamente pequenos.

É muito importante determinar corretamente os blocos de código que devem ser comentados. Caso seja uma condição (ou outra construção lógica), então, ele deve ser comentado por inteiro. Se você comentou um bloco em que as variáveis são declaradas, então é importante não deixar o bloco que adverte essas variáveis aberto. Isso quer dizer que o comentário deve ser usado pela lógica de programação. A infração dessa abordagem fará com que novos erros de informação errada apareçam durante a compilação.

Exemplo

Exemplificarei a busca prática por um erro em um código. Suponhamos que temos um 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);
  }
//+------------------------------------------------------------------+

Veremos a seguinte mensagem de erro durante a compilação:


É impossível detectar rapidamente o bloco em que o erro foi feito. Voltaremos para os comentários. Comente em todas as construções 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);
  }
//+------------------------------------------------------------------+

É possível se certificar facilmente de que esse código pode ser compilado sem problemas. Isso significa que a parte do código em que o erro foi feito está "oculta". Abra as partes do código /* ... */ em turnos e tente compilá-lo.

O compilador será bem-sucedido até que alcancemos o seguinte bloco de 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; 
 }

Assim, o erro está na sua construção lógica. Podemos ver que há um parêntese sem par na construção durante o exame detalhado dessa parte do código:

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

Se o removermos, o código será compilado sem problemas.

Vamos nos certificar de que não há outros erros no código removendo os comentários restantes. Isso significa que alcançamos nosso objetivo - o erro no código foi encontrado com rapidez suficiente.

Conclusão

Foi mostrado em um exemplo prático como usar esse algoritmo para buscar os erros. Não foi usado um código pequeno (194 entradas) nesse exemplo, então sua "investigação" poderia levar um bom tempo. A possibilidade de comentar nele mesmo economizou tempo suficiente de programadores que se depararam com o problema de busca de erros.

Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/1547

Visão de Análise técnica no contexto de sistemas de controle automático (ACS) ou "Visão reversa" Visão de Análise técnica no contexto de sistemas de controle automático (ACS) ou "Visão reversa"
O artigo demonstra uma visão alternativa de análise técnica, que é baseada nos princípios da teoria de controle automático moderna e da própria teoria de análise técnica. O artigo é introdutório, representando a teoria com algumas aplicações práticas da mesma.
A ociosidade é o estímulo do progresso ou como trabalhar com gráficos de maneira interativa A ociosidade é o estímulo do progresso ou como trabalhar com gráficos de maneira interativa
Um indicador de trabalho interativo com linhas de tendência, níveis Fibo, ícones impostos manualmente em um gráfico. Ele permite que você desenhe as zonas coloridas dos níveis Fibo, mostre os momentos em que o preço cruzou a linha de tendência, gerencia o objeto "etiqueta de preço".
A ociosidade é o estímulo do progresso. Marcação semiautomática de um modelo A ociosidade é o estímulo do progresso. Marcação semiautomática de um modelo
Entre as dezenas de exemplos de como trabalhar com gráficos, há um método de marcação manual de um modelo. Linhas de tendência, canais, níveis de suporte/resistência etc. são impostos em um gráfico. Com certeza, há alguns programas especiais para esse tipo de trabalho. Todo mundo decide sobre qual método usar. Neste artigo, ofereço uma opção para você considerar de métodos de marcação manual com a automatização subsequente de alguns elementos das ações de rotina repetidas.
Como escrever ZigZags rápidos que não são redesenhados Como escrever ZigZags rápidos que não são redesenhados
É proposta uma abordagem um tanto universal para escrever indicadores do tipo ZigZag. O método inclui uma parte significativa de ZigZags já descritos e permite que você crie novos de forma relativamente fácil.