English Русский 中文 Español Deutsch 日本語
preview
De Iniciante a Especialista: Depuração Colaborativa em MQL5

De Iniciante a Especialista: Depuração Colaborativa em MQL5

MetaTrader 5Exemplos |
16 8
Clemence Benjamin
Clemence Benjamin

Conteúdo principal: 


Introdução

Normalmente, todo autor busca abordar um problema específico do início ao fim de um artigo. Nosso título hoje é “Depuração”, mas recomendo que não o leve de forma superficial, pois vamos explorar muito mais do que apenas o básico do processo. Vou compartilhar as técnicas que utilizei ao longo dos anos em vários projetos de sucesso. Em todas as áreas da programação de software, depuração é um tópico que não pode ser negligenciado. Notei que muitos autores se concentram em apresentar um produto final polido sem compartilhar as dificuldades enfrentadas para fazer o código funcionar corretamente.

Seja em sistemas de redes neurais, inteligência artificial ou outras áreas de software relacionadas, a depuração é essencial. Acredito que a habilidade mais valiosa que você pode desenvolver é a capacidade de resolver problemas à medida que eles surgem, e essa habilidade se torna parte integrante de você para desafios futuros de natureza semelhante. Assim, a resolução de problemas pode construir um conjunto sólido de habilidades, transformando gradualmente alguém em um especialista.

Depuração Colaborativa

Depuração Colaborativa

Quando me comprometi a escrever este artigo, estava trabalhando em um projeto no qual encontrei vários erros ao tentar compilar o código. Às vezes, o depurador me apresentava 50 linhas de erros para corrigir. Por meio de tentativa e erro, desenvolvi uma rotina para lidar com bugs que me permite resolver problemas em apenas alguns minutos, ou até segundos, e fazer o programa rodar sem problemas.

Meu objetivo é conscientizá-lo sobre as tecnologias que podem acelerar o processo de depuração. Na minha experiência, uma das lições mais valiosas que aprendi é que dominar MQL5 pode ser rápido e eficaz quando você se envolve ativamente em projetos de depuração. Preservei um programa com erros que vamos analisar juntos e aperfeiçoar.

Um dos desafios mais persistentes é que muitas pessoas têm dificuldade em suportar a leitura dos longos livros de MQL5 disponíveis gratuitamente, mas isso não os torna menos valiosos. Esses livros contêm conhecimentos essenciais que vão desde conceitos básicos até avançados de programação em MQL5. Para alcançar os melhores resultados, é aconselhável participar de projetos ativos enquanto consulta esses livros para tópicos específicos relacionados ao seu trabalho em andamento. À medida que você conclui esses projetos, absorverá naturalmente uma grande quantidade de conhecimento.

Normalmente, nossos relatórios de erros são organizados em quatro colunas, conforme descrito na tabela abaixo.

Coluna (Nomes) Explicação:
Descrição Esta coluna fornece uma breve explicação do erro ou aviso encontrado no código. Ela pode descrever a natureza do problema, como erros de sintaxe, variáveis não declaradas, incompatibilidades de tipo ou outros erros de codificação. Compreender a descrição ajuda o programador a identificar rapidamente o problema.
Arquivo Aqui, é indicado o nome do arquivo onde ocorreu o erro (por exemplo, <código omitido>). No caso de vários arquivos em um projeto, saber qual arquivo contém o problema é crucial para uma depuração e correção eficazes.
Linha Especifica o número exato da linha dentro do arquivo indicado onde o erro foi encontrado. Essa precisão permite que o programador navegue rapidamente até a parte específica do código que requer atenção, reduzindo o tempo necessário para localizar o problema.
Coluna Indica o número exato da coluna na linha onde o erro foi detectado. Embora seja menos comum de ser referenciada do que as colunas anteriores, pode ser particularmente útil para identificar erros que ocorrem em instruções complexas ou quando a linha contém muitos elementos (como várias chamadas de função ou parâmetros).

Elas normalmente são organizadas da esquerda para a direita, como mostrado abaixo. Também incluímos o relatório completo de erros, que compreende 20 erros e 4 avisos (veja no final do trecho), para o programa que vamos depurar nesta discussão, logo abaixo do layout da tabela. Você achará fácil identificar as características do relatório. Se ler até o final, discutiremos como resolver os erros apresentados no trecho de código abaixo.

Descrição Arquivo Linha Coluna

'D1 PriceMarker.mq5'                    1
'ObjectDelete' - wrong parameters count D1 PriceMarker.mq5      70      5
   built-in: bool ObjectDelete(long,const string)       D1 PriceMarker.mq5      70      5
'ObjectDelete' - wrong parameters count D1 PriceMarker.mq5      71      5
   built-in: bool ObjectDelete(long,const string)       D1 PriceMarker.mq5      71      5
'ObjectDelete' - wrong parameters count D1 PriceMarker.mq5      72      5
   built-in: bool ObjectDelete(long,const string)       D1 PriceMarker.mq5      72      5
'ObjectDelete' - wrong parameters count D1 PriceMarker.mq5      73      5
   built-in: bool ObjectDelete(long,const string)       D1 PriceMarker.mq5      73      5
'ObjectDelete' - wrong parameters count D1 PriceMarker.mq5      74      5
   built-in: bool ObjectDelete(long,const string)       D1 PriceMarker.mq5      74      5
'ObjectDelete' - wrong parameters count D1 PriceMarker.mq5      75      5
   built-in: bool ObjectDelete(long,const string)       D1 PriceMarker.mq5      75      5
'ObjectDelete' - wrong parameters count D1 PriceMarker.mq5      76      5
   built-in: bool ObjectDelete(long,const string)       D1 PriceMarker.mq5      76      5
'ObjectDelete' - wrong parameters count D1 PriceMarker.mq5      77      5
   built-in: bool ObjectDelete(long,const string)       D1 PriceMarker.mq5      77      5
'ObjectCreate' - wrong parameters count D1 PriceMarker.mq5      15      9
   built-in: bool ObjectCreate(long,const string,ENUM_OBJECT,int,datetime,double,...)   D1 PriceMarker.mq5      15      9
'ObjectCreate' - wrong parameters count D1 PriceMarker.mq5      27      9
   built-in: bool ObjectCreate(long,const string,ENUM_OBJECT,int,datetime,double,...)   D1 PriceMarker.mq5      27      9
'ObjectSetText' - undeclared identifier D1 PriceMarker.mq5      37      5
',' - unexpected token  D1 PriceMarker.mq5      37      28
'labelName' - some operator expected    D1 PriceMarker.mq5      37      19
'+' - illegal operation use     D1 PriceMarker.mq5      37      36
',' - unexpected token  D1 PriceMarker.mq5      37      69
result of expression not used   D1 PriceMarker.mq5      37      43
',' - unexpected token  D1 PriceMarker.mq5      37      73
expression has no effect        D1 PriceMarker.mq5      37      71
',' - unexpected token  D1 PriceMarker.mq5      37      82
expression has no effect        D1 PriceMarker.mq5      37      76
')' - unexpected token  D1 PriceMarker.mq5      37      87
expression has no effect        D1 PriceMarker.mq5      37      84
'OBJPROP_Y' - undeclared identifier     D1 PriceMarker.mq5      41      36
'ObjectSetInteger' - no one of the overloads can be applied to the function call        D1 PriceMarker.mq5      41      5
could be one of 2 function(s)   D1 PriceMarker.mq5      41      5
   built-in: bool ObjectSetInteger(long,const string,ENUM_OBJECT_PROPERTY_INTEGER,long) D1 PriceMarker.mq5      41      5
   built-in: bool ObjectSetInteger(long,const string,ENUM_OBJECT_PROPERTY_INTEGER,int,long)     D1 PriceMarker.mq5      41      5
20 errors, 4 warnings           21      5

Aqui estão alguns termos comuns para entender ao discutir este tópico:

  • Sintaxe: refere-se ao conjunto específico de regras que determinam como programas (como algoritmos de negociação, indicadores e scripts) devem ser escritos para que a plataforma MetaTrader 5 os compreenda e execute corretamente.
  • Erro: refere-se a um equívoco ou problema no código que impede sua execução correta. Os erros podem ser classificados em vários tipos, como Erros de Sintaxe, Erros de Execução, Erros Lógicos, Erros de Tipo e Erros de Compilação.


O que é Depuração?

Tenho certeza de que a maioria de vocês está familiarizada com este termo vibrante, mas é essencial que os iniciantes compreendam o conceito em detalhes. Agora, vou definir um bug para que você possa entender melhor o processo de depuração.

  • Bug:

Um erro ou defeito em um programa ou sistema de computador que faz com que ele se comporte de maneira inesperada ou incorreta. 

  • Depuração:

É o processo de identificar, isolar e corrigir erros ou bugs em um programa ou sistema de computador com o objetivo de garantir que o programa se comporte conforme o esperado e produza os resultados corretos em diversas condições.

Depuração no Contexto da Programação MQL5

Aqui estão alguns aspectos da depuração especificamente relacionados ao MQL5:

 1. Tipos Comuns de Bugs em MQL5:

  • Erros de Sintaxe: Erros na estrutura do código MQL5 que impedem o script de ser compilado.

Este exemplo exibe um simples erro de sintaxe onde o parêntese de fechamento da função Print() está faltando. Como resultado, o script falhará na compilação, destacando a necessidade de verificar cuidadosamente a estrutura do código.

void OnStart()
{
    Print("Hello, World!" // Missing closing parenthesis
}
  • Erros Lógicos: Problemas em que o código compila e executa, mas produz sinais de negociação incorretos ou se comporta de forma inesperada.

Aqui está um erro lógico em que as condições acionam incorretamente uma ordem de compra. O programador pretendia aplicar uma lógica mais complexa que dependesse das condições de mercado, mas a implementação atual leva a negociações desnecessárias.

void OnTick()
{
    double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);
    double targetPrice = currentPrice + 100; // Intended to use a different logic

    // Mistakenly placing a buy when conditions aren't right
    if (currentPrice < targetPrice) // Logic Error
    {
        OrderSend(_Symbol, OP_BUY, 0.1, currentPrice, 3, 0, 0, "Buy order", 0, 0, clrGreen);
    }
}
  • Erros de Execução (Runtime Errors): Erros que ocorrem durante a execução, como tentar acessar um índice fora dos limites de um array ou não tratar corretamente ordens de negociação.
Neste exemplo, é feita uma tentativa de acessar o sexto elemento de um array que possui apenas cinco índices válidos. Isso resultará em um erro de execução, o que ilustra a importância de verificar limites ao trabalhar com arrays.
void OnStart()
{
    double prices[5];
    
    // Attempt to access out-of-range index (e.g., index 5)
    double value = prices[5]; // Runtime error: Array out of range
}

2. Ferramentas de Depuração no MQL5:

  • MetaEditor: É o ambiente de desenvolvimento integrado (IDE) do MQL5. Ele oferece realce de sintaxe, preenchimento automático de código e indicação de erros que ajudam a identificar rapidamente erros de sintaxe.
O código abaixo permite definir um ponto de interrupção (breakpoint) no cálculo da variável result . Ao depurar no MetaEditor, você pode inspecionar variáveis nesse ponto para confirmar se estão definidas como esperado, facilitando a execução passo a passo para analisar o fluxo do programa.
void OnStart()
{
    double startValue = 10.0;

    // Set a breakpoint here to inspect value
    double result = startValue * 2;

    Print("Result: ", result); // Check the value of result
}
  • Instruções Print: Usar a função Print() para exibir valores de variáveis e logs do fluxo de execução no log de Experts. Essa é uma maneira simples de rastrear problemas.
Neste trecho de código de exemplo, usamos a função Print() para registrar os preços atuais de compra (bid) e venda (ask). Essa abordagem é útil para rastrear valores de variáveis durante a execução e pode ajudar a diagnosticar erros lógicos comparando valores esperados e reais.
void OnTick()
{
    double bidPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);
    double askPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
    
    // Logging prices for debugging
    Print("Bid: ", bidPrice, ", Ask: ", askPrice);
}
  • Comentar Código: Desativar temporariamente trechos de código para isolar a área problemática.
Neste exemplo, uma linha de código é comentada para focar na lógica alternativa. Essa técnica é útil para isolar bugs e testar diferentes partes do código sem removê-las completamente.
void OnTick()
{
    // double result = SomeFunction(); // Temporarily disabling this line
    
    // Run alternate logic while debugging
    Print("Running alternative logic.");
}
3. Usando o Depurador no MetaEditor:

O MetaEditor inclui um depurador interno que permite:
  • Breakpoints (Pontos de Interrupção): Definir breakpoints no seu código permite pausar a execução em linhas específicas e inspecionar os valores das variáveis.
  • Execução Passo a Passo: Você pode percorrer o código linha por linha para observar como as variáveis mudam e como o fluxo lógico se desenvolve.
  • Expressões de Observação (Watch Expressions): Monitorar os valores de variáveis específicas durante toda a execução do código.
 4. Testes e Otimização:
  • Testador de Estratégia (Strategy Tester): O MQL5 fornece um Testador de Estratégia que permite realizar backtests de estratégias de negociação usando dados históricos. Ele ajuda a simular negociações e analisar o desempenho, o que pode revelar bugs ocultos.
  • Otimização: É possível otimizar parâmetros para melhorar o desempenho do seu algoritmo de negociação, o que também pode evidenciar potenciais erros de lógica ou execução.
 5. Tratamento de Erros:
  • Lidar com códigos de erro específicos do MQL5, como verificar os valores de retorno de funções relacionadas a operações de negociação. Funções comuns incluem funções de execução de ordens (OrderSend, OrderClose, etc.), onde o tratamento adequado de erros pode evitar falhas ou resultados indesejados.

Boas Práticas para Depuração em MQL5:

1. Modularidade de Código: Escreva código modular dividindo-o em funções. Isso facilita testar e depurar componentes individuais. 2. Documentação do Código: Comente seu código para explicar o que cada parte faz, o que ajuda ao revisitar o código depois de algum tempo. 3. Testes Regulares: Teste o código com frequência durante o desenvolvimento, em vez de esperar até que tudo esteja concluído. Isso ajuda a identificar bugs cedo.


Implementação da Depuração em MQL5

Há pouco tempo, meu amigo e eu criamos um rascunho simples de um script para desenhar linhas de preço rotuladas referentes ao candle diário (D1) anterior, marcando níveis críticos como Máxima, Mínima, Abertura e Fechamento. Esta é a versão que reservei para este artigo. 

Normalmente, ao escrever como especialista, o MetaEditor fornece modelos e sugestões de parâmetros para auxiliar os desenvolvedores e ajudar a reduzir as chances de erros, desde que os detalhes sejam inseridos conforme a sintaxe correta da linguagem. No entanto, há casos em que você pode receber um código de um fórum, repleto de erros. Abaixo está um trecho do nosso script com problemas:

//+------------------------------------------------------------------+
//|                                               D1 PriceMarker.mq5 |
//|                                Copyright 2024, Clemence Benjamin |
//|             https://www.mql5.com/en/users/billionaire2024/seller |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, Clemence Benjamin"
#property link      "https://www.mql5.com/en/users/billionaire2024/seller"
#property version   "1.00"
#property strict

// Function to create a price line with a label
void CreatePriceLine(string name, double price, color clr, string label)
{
    // Create a horizontal line
    if(!ObjectCreate(name, OBJ_HLINE, 0, 0, price))
    {
        Print("Failed to create line: ", GetLastError());
        return;
    }
    
    // Set line properties
    ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
    ObjectSetInteger(0, name, OBJPROP_WIDTH, 2);

    // Create a label for the price
    string labelName = name + "_label";
    if(!ObjectCreate(labelName, OBJ_LABEL, 0, 0, 0))
    {
        Print("Failed to create label: ", GetLastError());
        return;
    }

    // Set label properties
    ObjectSetInteger(0, labelName, OBJPROP_XSIZE, 70);
    ObjectSetInteger(0, labelName, OBJPROP_FONTSIZE, 10);
    ObjectSetInteger(0, labelName, OBJPROP_COLOR, clr);
    ObjectSetText(labelName, label + ": " + DoubleToString(price, 2), 10, "Arial", clr);

    // Position the label
    double yPos = price; // Positioning along the price axis
    ObjectSetInteger(0, labelName, OBJPROP_Y, yPos);
    ObjectSetInteger(0, labelName, OBJPROP_XDISTANCE, 5);
}

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
void OnInit()
{
    // Get the previous D1 candle's open, high, low, and close prices
    datetime prevCandleTime = iTime(NULL, PERIOD_D1, 1);
    double openPrice = iOpen(NULL, PERIOD_D1, 1);
    double highPrice = iHigh(NULL, PERIOD_D1, 1);
    double lowPrice = iLow(NULL, PERIOD_D1, 1);
    double closePrice = iClose(NULL, PERIOD_D1, 1);

    // Draw labeled price lines for open, high, low, and close prices
    CreatePriceLine("PrevCandle_Open", openPrice, clrBlue, "Open");
    CreatePriceLine("PrevCandle_High", highPrice, clrRed, "High");
    CreatePriceLine("PrevCandle_Low", lowPrice, clrGreen, "Low");
    CreatePriceLine("PrevCandle_Close", closePrice, clrOrange, "Close");
}

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
    // Remove the drawn price lines and labels upon indicator deinitialization
    ObjectDelete("PrevCandle_Open");
    ObjectDelete("PrevCandle_High");
    ObjectDelete("PrevCandle_Low");
    ObjectDelete("PrevCandle_Close");
    ObjectDelete("PrevCandle_Open_label");
    ObjectDelete("PrevCandle_High_label");
    ObjectDelete("PrevCandle_Low_label");
    ObjectDelete("PrevCandle_Close_label");
}

//+------------------------------------------------------------------+                                                                                                            

(i) Localizando um Bug

Acho o depurador interno do MetaEditor bastante intuitivo quando tento compilar um programa com erros. A maioria dos bugs é detectada quando você clica no botão Compile ou Real-time Profiling no MetaEditor. Porém, há erros de desempenho que não impedem a compilação; estes só podem ser identificados na plataforma ou no testador ao tentar executar o programa.

Um desenvolvedor pode escrever todo o programa do zero e depois depurá-lo, ou simplesmente depurar um programa já existente. Na imagem abaixo, aproveitamos o compilador e depurador integrados do MetaEditor para obter um resumo dos erros (veja a parte inferior da janela da caixa de ferramentas na imagem). Ao clicar duas vezes em uma linha de erro, o cursor se move e destaca a linha de código correspondente ao problema. Raramente percebo erros no código até pressionar o botão Compile, momento em que o depurador relata as ocorrências.

Localizando erros

Localizando Erros no MetaEditor

Às vezes, o programa compila com sucesso, mas não produz o resultado desejado. Nesses casos, é aconselhável identificar possíveis erros verificando os logs de Experts e o Journal disponíveis na caixa de ferramentas da plataforma MetaTrader 5. Esses logs podem fornecer informações valiosas sobre o que pode estar dando errado durante a execução, ajudando a diagnosticar e corrigir problemas de forma eficaz.

(ii) 3 Técnicas de Depuração

Erros podem surgir de erros de digitação ou uso incorreto de termos, e o depurador geralmente fornece explicações e pistas parciais para a solução. Se você compreender essas mensagens, normalmente é simples revisar o código e fazer as correções necessárias. No entanto, há situações mais complexas, difíceis de diagnosticar, que podem exigir conhecimento aprofundado obtido em livros de referência ou ajuda da comunidade.

Na minha experiência, costumo aplicar algumas estratégias para depurar problemas complexos. Eu categorizo essas etapas em três abordagens principais, embora esta lista não seja exaustiva; ela foi preparada especificamente para esta discussão. Vou explicar cada passo do procedimento em detalhes.

1. Revisitar a Documentação:

Ajuda muito na depuração de programas MQL5, oferecendo clareza sobre sintaxe, uso de funções e mensagens de erro. Traz explicações detalhadas e exemplos que ajudam a identificar implementações incorretas e melhorar a compreensão das funções integradas. Além disso, a documentação frequentemente inclui informações sobre erros comuns, boas práticas e soluções alternativas, permitindo que desenvolvedores solucionem problemas com eficácia e otimizem seu código para melhor desempenho. Para este projeto, veja na imagem abaixo como acessamos facilmente a documentação.

Revisitar a Documentação:

Revisitar a Documentação:

Relatório de Erro:

'ObjectDelete' - número incorreto de parâmetros D1 PriceMarker.mq5 70 5

Dica de Solução:

   built-in: bool ObjectDelete(long,const string)       D1 PriceMarker.mq5      70      5

Situação atual:

   ObjectDelete("PrevCandle_Open");

Pela dica de solução, fica claro que a função ObjectDelete espera dois parâmetros, mas atualmente estamos fornecendo apenas um. Essa discrepância indica onde está o problema e como corrigi-lo. Segundo a documentação, a função ObjectDelete no MQL5 exige dois parâmetros:

  1. Name: Nome do objeto a ser excluído, especificado como string.
  2. Chart_id: ID do gráfico de onde o objeto deve ser excluído, especificado como inteiro. Se omitido, a função utiliza o gráfico atual como padrão.

Para corrigir esse problema, precisamos garantir que ambos os parâmetros sejam passados ao chamar ObjectDelete. Assim, alinhamos a chamada da função à sintaxe esperada e eliminamos o erro.

    Solução:

    ObjectDelete(0, "PrevCandle_Open");

    Agora, analisando o código principal, percebemos que há várias ocorrências da função ObjectDelete. Com as informações obtidas na pesquisa, podemos fazer os ajustes necessários em todas elas. Garantindo que fornecemos os dois parâmetros exigidos em cada caso, conseguimos resolver esses erros de forma eficaz.

    Veja na imagem abaixo como conseguimos reduzir o número total de erros em 10. Isso representa um progresso significativo na depuração do nosso script e mostra a importância de uma análise cuidadosa e de correções baseadas na documentação adequada.

    Função ObjectDelete corrigida

    Erro na função ObjectDelete resolvido

    Pronto! Ao encontrar um erro, é uma boa prática clicar no botão Compile após cada tentativa de correção. Isso permite verificar se o erro persiste e identificar rapidamente quaisquer outros problemas.

    Agora, vamos para o próximo erro.

    Relatório de Erro:

    'ObjectSetText' - undeclared identifier D1 PriceMarker.mq5      29      5
    'ObjectSetText' - undeclared identifier D1 PriceMarker.mq5      29      5
    ',' - unexpected token  D1 PriceMarker.mq5      29      28
    'labelName' - some operator expected    D1 PriceMarker.mq5      29      19
    '+' - illegal operation use     D1 PriceMarker.mq5      29      36
    ',' - unexpected token  D1 PriceMarker.mq5      29      69
    result of expression not used   D1 PriceMarker.mq5      29      43
    ',' - unexpected token  D1 PriceMarker.mq5      29      73
    expression has no effect        D1 PriceMarker.mq5      29      71
    ',' - unexpected token  D1 PriceMarker.mq5      29      82
    expression has no effect        D1 PriceMarker.mq5      29      76
    ')' - unexpected token  D1 PriceMarker.mq5      29      87
    expression has no effect        D1 PriceMarker.mq5      29      84

    Desta vez, reuni vários relatórios porque, ao verificar, percebi que os erros ocorrem na mesma linha. Isso normalmente indica um problema comum que precisa ser tratado nessa parte específica do código. Vamos analisar mais de perto essa linha para identificar o problema e definir as correções necessárias.

    Dica de Solução:

    Neste cenário, nos deparamos com os seguintes erros: identificador não declarado, operador esperado, expressão sem efeito e token inesperado.

    Situação atual:

    ObjectSetText(labelName, label + ": " + DoubleToString(price, 2), 10, "Arial", clr);
                
    

    Consultei a documentação e não encontrei referência a ObjectSetText. Mas, ao começar a digitar ObjectSet..., surgiram várias sugestões, sendo ObjectSetString a melhor opção. Essa função se mostrou a correta e funcionou conforme o esperado.

    Você pode ver nosso progresso nas imagens abaixo.

    ObjectSetText não disponível na documentação

    ObjectSetText não disponível na documentação


    ObjectSetString

    ObjectSetString

    Parâmetros da função ObjectSetString de acordo com a documentação:

    bool  ObjectSetString(
       long                            chart_id,          // chart identifier
       string                          name,              // object name
       ENUM_OBJECT_PROPERTY_STRING     prop_id,           // property
       int                             prop_modifier,     // modifier
       string                          prop_value         // value
       );

    Solução:

    Ao fazer os ajustes necessários, de forma semelhante ao que fizemos para o primeiro erro, conseguimos resolver quase todos os problemas. Agora, restam apenas algumas linhas para corrigir. Vamos focar nesses ajustes finais para eliminar completamente os erros restantes.

     ObjectSetString(0, labelName, OBJPROP_TEXT, label + ": " + DoubleToString(price, 2));

    Alguns bugs restantes:

    2 erros restantes

    2 erros remanescentes

    Finalmente, corrigindo os erros restantes:

    ObjectSetInteger(0, labelName, OBJPROP_YDISTANCE, price); // Position label at the price level

    Era para ser OBJPROP_YDISTANCE, e não OBJPROP_Y.

    Erros eliminados e o programa compila agora

    Depuração bem-sucedida com referência à Documentação

    Nosso código final limpo está aqui:

    //+------------------------------------------------------------------+
    //|                                               D1 PriceMarker.mq5 |
    //|                                Copyright 2024, Clemence Benjamin |
    //|             https://www.mql5.com/en/users/billionaire2024/seller |
    //+------------------------------------------------------------------+
    #property copyright "Copyright 2024, Clemence Benjamin"
    #property link      "https://www.mql5.com/en/users/billionaire2024/seller"
    #property version   "1.00"
    #property strict
    
    
    // Function to create a price line with a label
    void CreatePriceLine(string name, double price, color clr, string label)
    {
        // Create a horizontal line
        if(!ObjectCreate(0, name, OBJ_HLINE, 0, 0, price))
        {
            Print("Failed to create line: ", GetLastError());
            return;
        }
        
        // Set line properties
        ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
        ObjectSetInteger(0, name, OBJPROP_WIDTH, 2);
    
        // Create a label for the price
        string labelName = name + "_label";
        if(!ObjectCreate(0, labelName, OBJ_LABEL, 0, 0, 0))
        {
            Print("Failed to create label: ", GetLastError());
            return;
        }
    
        // Set label properties
        ObjectSetInteger(0, labelName, OBJPROP_XSIZE, 70);
        ObjectSetInteger(0, labelName, OBJPROP_FONTSIZE, 10);
        ObjectSetInteger(0, labelName, OBJPROP_COLOR, clr);
        ObjectSetInteger(0, labelName, OBJPROP_YDISTANCE, price); // Position label at the price level
        ObjectSetInteger(0, labelName, OBJPROP_XDISTANCE, 5);
        
        // Set the text of the label
        ObjectSetString(0, labelName, OBJPROP_TEXT, label + ": " + DoubleToString(price, 2));
    }
    
    //+------------------------------------------------------------------+
    //| Custom indicator initialization function                         |
    //+------------------------------------------------------------------+
    void OnInit()
    {
        // Get the previous D1 candle's open, high, low, and close prices
        datetime prevCandleTime = iTime(NULL, PERIOD_D1, 1);
        double openPrice = iOpen(NULL, PERIOD_D1, 1);
        double highPrice = iHigh(NULL, PERIOD_D1, 1);
        double lowPrice = iLow(NULL, PERIOD_D1, 1);
        double closePrice = iClose(NULL, PERIOD_D1, 1);
    
        // Draw labeled price lines for open, high, low, and close prices
        CreatePriceLine("PrevCandle_Open", openPrice, clrBlue, "Open");
        CreatePriceLine("PrevCandle_High", highPrice, clrRed, "High");
        CreatePriceLine("PrevCandle_Low", lowPrice, clrGreen, "Low");
        CreatePriceLine("PrevCandle_Close", closePrice, clrOrange, "Close");
    }
    
    //+------------------------------------------------------------------+
    //| Custom indicator deinitialization function                       |
    //+------------------------------------------------------------------+
    void OnDeinit(const int reason)
    {
        // Remove the drawn price lines and labels upon indicator deinitialization
        ObjectDelete(0, "PrevCandle_Open");
        ObjectDelete(0, "PrevCandle_High");
        ObjectDelete(0, "PrevCandle_Low");
        ObjectDelete(0, "PrevCandle_Close");
        ObjectDelete(0, "PrevCandle_Open_label");
        ObjectDelete(0, "PrevCandle_High_label");
        ObjectDelete(0, "PrevCandle_Low_label");
        ObjectDelete(0, "PrevCandle_Close_label");
    }
    
    //+------------------------------------------------------------------+

    D1 PriceMarker é um script em MQL5 que projetamos para aprimorar a análise técnica em um gráfico de negociação, desenhando linhas horizontais nos preços de máxima, mínima, abertura e fechamento do candle diário (D1) anterior. Ao ser inicializado, o script obtém esses quatro pontos de preço e utiliza uma função auxiliar para criar as linhas correspondentes em cores distintas (azul para abertura, vermelho para máxima, verde para mínima e laranja para fechamento), cada uma acompanhada por um texto com o valor do preço. Quando o script é removido do gráfico, ele automaticamente apaga todas as linhas e rótulos criados, garantindo um espaço de trabalho limpo para o trader.

    2. Depuração com IA:

    Entendo que todos queiram saber como utilizamos modelos de IA disponíveis, então vou falar brevemente sobre isso, deixando uma discussão mais aprofundada para depois. Temos a vantagem de que a maioria desses modelos consegue entender a sintaxe de forma mais rápida e precisa do que nós. No entanto, é importante notar que eles às vezes podem produzir resultados inesperados e podem exigir supervisão humana próxima para orientar os próximos passos. Ainda assim, são ferramentas excelentes quando usadas com sabedoria, e já resolvi muitos desafios de programação considerando cuidadosamente suas sugestões.

    Basicamente, ao criar um prompt para a IA, você deve começar fornecendo o programa que deseja depurar. Em seguida, utilizando a capacidade de copiar as linhas de erro do relatório do MetaEditor, é possível colar essas linhas no prompt, permitindo que a IA auxilie no processo de depuração. Embora esse método possa gerar bons resultados, ele também pode levar a complicações adicionais, então é essencial pensar criticamente e ir além do que a IA sugere. Os resultados que obtivemos anteriormente são consistentes com o que outras ferramentas de depuração produziriam, desde que sejam usadas de forma eficaz.

    Copiar Erros

    Copiando erros para prompts de IA

    3. Visitando o fórum:

    Assim como fizemos acima, os membros do fórum precisam de informações para oferecer boas sugestões de depuração. Participar de discussões sobre desafios de programação é uma ótima maneira de aprender com outros especialistas. Ao enviar seu programa, você convida outras pessoas a compartilhar sugestões e soluções valiosas. Essa abordagem colaborativa não apenas ajuda a resolver seus problemas, mas também amplia o conhecimento e as habilidades de todos.

    Programa no MetaTrader 5:

    D1 PriceMarker

    Script D1 PriceMarker 


    Conclusão

    O trabalho em equipe na programação MQL5 se mostra uma prática essencial para aprimorar o desenvolvimento de algoritmos de negociação robustos, como ilustramos em toda nossa jornada na criação do script D1 PriceMarker. O processo de depuração contou fortemente com os relatórios de erros e a documentação completa de referência do MQL5, permitindo identificar e corrigir sistematicamente os problemas encontrados durante o desenvolvimento.

    Esse método facilitou a resolução de erros específicos e proporcionou um entendimento mais profundo do ambiente de programação. Além disso, abordamos brevemente o potencial de aproveitar a inteligência artificial como um recurso futuro na depuração, destacando sua capacidade de fornecer insights e recomendações que podem agilizar o processo.

    O suporte da comunidade, especialmente por meio do fórum MQL5, desempenha um papel inestimável, permitindo buscar conselhos e compartilhar conhecimento com outros desenvolvedores experientes. Ao adotar essas abordagens colaborativas e orientadas a recursos, podemos aumentar significativamente a eficácia dos esforços de depuração, levando ao desenvolvimento de soluções de negociação mais confiáveis e inovadoras no competitivo cenário do trading algorítmico. Boas negociações, colegas!

    Traduzido do Inglês pela MetaQuotes Ltd.
    Artigo original: https://www.mql5.com/en/articles/15325

    Arquivos anexados |
    D1_PriceMarker.mq5 (3.31 KB)
    Últimos Comentários | Ir para discussão (8)
    Clemence Benjamin
    Clemence Benjamin | 13 out. 2024 em 04:52
    Alain Verleyen #:

    Bom artigo para iniciantes, mas um pouco prolixo em minha opinião. Algumas observações:

    • Você deve dizer claramente que, quando tiver uma lista de erros, SEMPRE precisará começar a verificar o primeiro no topo da lista. Essa é a maneira mais eficiente de lidar com os erros e evitar a perda de tempo com erros secundários.
    • Você deve fornecer a versão "com erros" do "D1_PriceMarker.mq5", para que as pessoas possam praticar seguindo seu artigo.

    • Esse é claramente um erro lógico, uma 'Y_DISTANCE' é um valor inteiro (posição de pixel na tela) e você forneceu um 'price' duplo.
    • Quase nunca o vi ativo no fórum, seja para fazer ou responder perguntas.
    • Não estou entendendo. Onde está a "parte colaborativa"? Será que perdi alguma coisa?

    Obrigado por seus comentários, Alain Verleyen! Aprecio muito suas percepções, especialmente como moderador, e concordo que a clareza é essencial, especialmente para iniciantes.

    1. Você está absolutamente certo sobre a importância de abordar o primeiro erro da lista.
    2. Essa é uma excelente sugestão! Embora eu não tenha incluído o arquivo de origem no artigo, os leitores podem encontrar e copiar a versão "com erros" do " D1_PriceMarker.mq5" neste link.
    3. Obrigado por apontar o erro lógico em relação ao Y_DISTANCE.
    4. Com relação ao aspecto colaborativo, minha intenção era incentivar os leitores a interagir uns com os outros nos comentários ou no fórum para compartilhar suas próprias experiências e soluções de depuração .

    Eu realmente valorizo suas críticas construtivas e seu envolvimento! Discussões como essa são vitais para nosso crescimento e aprimoramento coletivo.

    Gerard William G J B M Dinh Sy
    Gerard William G J B M Dinh Sy | 13 out. 2024 em 08:52

    Bom dia

    O que os operadores de algoritmos talvez não percebam.

    É que eles gastarão muito pouco tempo codificando indicadores milagrosos ou EAs prodigiosamente lucrativos.

    A realidade é que eles gastarão principalmente tempo corrigindo, melhorando seus códigos e, portanto, depurando.

    Se não tiverem ferramentas poderosas, eles passarão rapidamente dias, que já seriam bons, procurando erros em seus códigos.

    Bazarbay83 Jumaev
    Bazarbay83 Jumaev | 16 mai. 2025 em 10:05
    Olá a todos, qual ferramenta vocês consideram poderosa?
    Vitaly Muzichenko
    Vitaly Muzichenko | 16 mai. 2025 em 11:16
    Bazarbay83 Jumaev #:
    Olá a todos, qual instrumento você considera poderoso?

    Kit de bateria.

    Vinicius Pereira De Oliveira
    Vinicius Pereira De Oliveira | 18 ago. 2025 em 12:15
    Bazarbay83 Jumaev #Olá a todos, qual ferramenta vocês consideram poderosa?

    Olá, bem-vindo ao fórum MQL5! Com relação a sua pergunta, recomendações de produtos do mercado não são permitidas. Você deverá fazer suas próprias pesquisas. Boa sorte! 😊

    Consultor Especialista Auto-Otimizável com MQL5 e Python (Parte V): Modelos de Markov Profundos Consultor Especialista Auto-Otimizável com MQL5 e Python (Parte V): Modelos de Markov Profundos
    Nesta discussão, aplicaremos uma Cadeia de Markov simples sobre um indicador RSI, para observar como o preço se comporta após o indicador atravessar níveis-chave. Concluímos que os sinais de compra e venda mais fortes no par NZDJPY são gerados quando o RSI está nas faixas de 11-20 e 71-80, respectivamente. Vamos demonstrar como você pode manipular seus dados para criar estratégias de trading ideais aprendidas diretamente a partir dos dados que possui. Além disso, mostraremos como treinar uma rede neural profunda para aprender a utilizar a matriz de transição de forma otimizada.
    Simplificando a negociação com base em notícias (Parte 4): Aumentando o desempenho Simplificando a negociação com base em notícias (Parte 4): Aumentando o desempenho
    Neste artigo, serão apresentados métodos para melhorar o desempenho do EA no testador de estratégias, além da implementação de um código para dividir o horário dos eventos de notícias em categorias por hora. O acesso a esses eventos será permitido apenas no horário especificado para cada um. Isso permite que o EA gerencie operações de maneira eficiente com base nos eventos, tanto em condições de alta quanto de baixa volatilidade.
    Reimaginando Estratégias Clássicas (Parte IX): Análise de Múltiplos Time-Frames (II) Reimaginando Estratégias Clássicas (Parte IX): Análise de Múltiplos Time-Frames (II)
    Na discussão de hoje, examinamos a estratégia de análise de múltiplos time-frames para descobrir em qual time-frame nosso modelo de IA apresenta melhor desempenho. Nossa análise nos levou a concluir que os time-frames Mensal e de 1 Hora produzem modelos com taxas de erro relativamente baixas no par EURUSD. Usamos isso a nosso favor e criamos um algoritmo de negociação que faz previsões de IA no time-frame Mensal e executa suas negociações no time-frame de 1 Hora.
    Como criar um diário de negociações com MetaTrader e Google Sheets Como criar um diário de negociações com MetaTrader e Google Sheets
    Crie um diário de negociações usando o MetaTrader e o Google Sheets! Você aprenderá como sincronizar seus dados de negociação via HTTP POST e recuperá-los usando requisições HTTP. Ao final, você terá um diário de negociações que ajudará a acompanhar suas operações de forma eficaz e eficiente.