English Русский 中文 Español Deutsch 日本語
preview
Negociando com o Calendário Econômico do MQL5 (Parte 3): Adicionando Filtros de Moeda, Importância e Tempo

Negociando com o Calendário Econômico do MQL5 (Parte 3): Adicionando Filtros de Moeda, Importância e Tempo

MetaTrader 5Negociação |
19 0
Allan Munene Mutiiria
Allan Munene Mutiiria

Introdução

Neste artigo, desenvolvemos sobre o nosso trabalho anterior no MetaQuotes Language 5 (MQL5) Economic Calendar, onde criamos um painel de notícias para exibir eventos econômicos em tempo real. Agora, vamos aprimorar esse painel implementando filtros específicos de moeda, importância e tempo, permitindo que os traders foquem apenas nos eventos mais relevantes para suas estratégias. Esses filtros fornecerão uma visão direcionada dos eventos que movimentam o mercado, ajudando a agilizar a tomada de decisão e a melhorar a eficiência das negociações. Os tópicos que iremos abordar incluem:

  1. Introdução
  2. Compreendendo os Tipos de Filtros em Calendários Econômicos
  3. Implementando os Filtros em MQL5
  4. Conclusão

Com essas adições, nosso painel se tornará uma ferramenta poderosa para monitorar e filtrar notícias econômicas dentro do ambiente MQL5, adaptada às necessidades dos traders por informações oportunas e relevantes.


Compreendendo os Tipos de Filtros em Calendários Econômicos

Para refinar a funcionalidade do nosso painel, devemos compreender o propósito e os benefícios de cada tipo de filtro: moeda, importância e tempo. O filtro de moeda nos permite visualizar eventos econômicos que afetam especificamente as moedas que estamos negociando, facilitando a identificação de eventos relevantes que podem impactar nossas posições em aberto. Esse filtro ajuda a simplificar o painel, reduzindo a sobrecarga de informações e focando apenas nas moedas da nossa carteira de negociação. No terminal de negociação, MetaTrader 5, podemos acessar e filtrar as notícias com base na moeda passando o mouse sobre a guia Calendário, clicando com o botão direito dentro dela e selecionando a moeda ou país desejado. Aqui está uma ilustração.

FILTRO DE MOEDA

O filtro de importância categoriza os eventos com base no impacto antecipado, normalmente definidos como baixa, média ou alta importância. Eventos de alto impacto, como anúncios de bancos centrais ou índices de desemprego, podem levar à volatilidade do mercado. Ao filtrar com base na importância, podemos avaliar rapidamente quais eventos podem ter o impacto mais significativo em nossas decisões de negociação, aumentando a capacidade de resposta. Para filtrar as notícias com base no nível de impacto, você pode novamente clicar com o botão direito na guia Calendário e selecionar pela prioridade. Aqui está uma ilustração.

FILTRO DE IMPORTÂNCIA

Por fim, o filtro de tempo nos permite especificar o período para os eventos econômicos relevantes, o que é particularmente útil para aqueles que negociam em sessões específicas ou se preparam para notícias futuras. Com esse filtro, podemos visualizar eventos que acontecerão dentro de um período definido — como a próxima hora, dia ou semana — fornecendo uma linha do tempo que se alinha às nossas estratégias de negociação e preferências de tempo. Juntos, esses filtros criam uma experiência personalizável que adapta os dados de notícias econômicas às necessidades individuais de negociação, formando a espinha dorsal de um painel MQL5 responsivo e eficiente.


Implementando os Filtros em MQL5

Para implementar os filtros em MQL5, o primeiro passo que precisamos dar é definir as variáveis booleanas em um escopo global. Essas variáveis controlarão se os filtros de moeda, importância e tempo estão ativados ou desativados. Ao defini-las globalmente, garantiremos que os filtros possam ser acessados e modificados em todo o código, proporcionando flexibilidade na forma como o painel de notícias opera. Esse passo estabelecerá a base para a implementação da lógica dos filtros e nos permitirá adaptar a funcionalidade do painel às nossas necessidades de negociação. Para isso, esta é a lógica que utilizamos.

//--- Define flags to enable/disable filters
bool enableCurrencyFilter = true;  // Set to 'true' to enable currency filter, 'false' to disable
bool enableImportanceFilter = true; // Set to 'true' to enable importance filter, 'false' to disable
bool enableTimeFilter = true; // Set to 'true' to enable time filter, 'false' to disable

Aqui, definimos três variáveis boolean, chamadas "enableCurrencyFilter", "enableImportanceFilter" e "enableTimeFilter", que usaremos para controlar se os respectivos filtros de moeda, importância e tempo estão habilitados ou desabilitados. Cada variável é definida com o valor padrão "true", significando que, por padrão, todos os filtros estarão ativos. Ao alterar esses valores para "false", podemos desabilitar qualquer um dos filtros que não desejamos usar, permitindo personalizar a funcionalidade do painel de notícias com base em nossas preferências de negociação.

A partir daqui, na lógica de inicialização ao contar os eventos de notícias válidos, começaremos com o filtro de moeda. Primeiro, precisamos definir os códigos de moeda aos quais desejamos aplicar o filtro. Assim, vamos defini-los como abaixo.

string curr_filter[] = {"AUD","CAD","CHF","EUR","GBP","JPY","NZD","USD"};
int news_filter_count = 0;

Aqui, definimos o array "curr_filter" do tipo "string", que contém uma lista de pares de moedas — "AUD", "CAD", "CHF", "EUR", "GBP", "JPY", "NZD" e "USD" — que queremos usar para filtrar as notícias com base em moedas específicas. Esse array nos ajudará a restringir os eventos de notícias exibidos no painel, focando apenas naqueles que são relevantes para as moedas selecionadas. Também definimos a variável "news_filter_count", que usamos para acompanhar o número de eventos de notícias filtrados que correspondem aos critérios selecionados, garantindo que exibamos apenas as informações mais pertinentes. Então podemos avançar para a lógica de filtro conforme abaixo.

//--- Check if the event’s currency matches any in the filter array (if the filter is enabled)
bool currencyMatch = false;
if (enableCurrencyFilter) {
   for (int j = 0; j < ArraySize(curr_filter); j++) {
      if (country.currency == curr_filter[j]) {
         currencyMatch = true;
         break;
      }
   }
   
   //--- If no match found, skip to the next event
   if (!currencyMatch) {
      continue;
   }
}

Aqui, verificamos se a moeda do evento corresponde a alguma moeda no array "curr_filter", mas somente se o filtro de moeda estiver habilitado, conforme indicado pela flag "enableCurrencyFilter". Se o filtro estiver habilitado, percorremos o array "curr_filter" usando um for loop, e a cada iteração comparamos a moeda do evento com as moedas do filtro.

Se uma correspondência for encontrada, definimos a flag "currencyMatch" como verdadeira e usamos break para sair do loop. Se nenhuma correspondência for encontrada (significando que "currencyMatch" permanece falso), usamos a instrução continue para ignorar o evento atual e passar para o próximo, garantindo que apenas eventos relevantes sejam processados. Em seguida, usamos a mesma lógica para filtrar os eventos com base na importância.

//--- Check importance level if importance filter is enabled
bool importanceMatch = false;
if (enableImportanceFilter) {
   for (int k = 0; k < ArraySize(allowed_importance_levels); k++) {
      if (event.importance == allowed_importance_levels[k]) {
         importanceMatch = true;
         break;
      }
   }
   
   //--- If importance does not match the filter criteria, skip the event
   if (!importanceMatch) {
      continue;
   }
}

Aqui, verificamos o nível de importância do evento em relação ao array pré-definido "allowed_importance_levels", mas somente se o filtro de importância estiver habilitado, conforme indicado pela flag "enableImportanceFilter". Se o filtro estiver habilitado, percorremos o array "allowed_importance_levels" usando um for loop, comparando a importância do evento com os níveis no array.

Se uma correspondência for encontrada, definimos a flag "importanceMatch" como verdadeira e usamos break para sair do loop. Se nenhuma correspondência for encontrada (significando que "importanceMatch" permanece falso), usamos a instrução continue para ignorar o evento atual, garantindo que apenas eventos com o nível de importância desejado sejam processados. Usamos outro array para definir os níveis de importância conforme abaixo:

// Define the levels of importance to filter (low, moderate, high)
ENUM_CALENDAR_EVENT_IMPORTANCE allowed_importance_levels[] = {CALENDAR_IMPORTANCE_LOW, CALENDAR_IMPORTANCE_MODERATE, CALENDAR_IMPORTANCE_HIGH};

Aqui, adicionamos todos os níveis de importância, o que significa que tecnicamente permitimos todas as notícias com base na prioridade, mas você pode escolher aquelas que melhor se encaixam em suas decisões de negociação. Em seguida, precisamos definir os intervalos do filtro de tempo.

//--- Define time range for filtering news events based on daily period
datetime timeRange = PeriodSeconds(PERIOD_D1);
datetime timeBefore = TimeTradeServer() - timeRange;
datetime timeAfter = TimeTradeServer() + timeRange;

Definimos um intervalo de tempo para filtrar eventos de notícias com base no período diário. Usamos a função PeriodSeconds com a constante PERIOD_D1 para determinar o número de segundos em um dia, que então atribuímos à variável "timeRange" do tipo datetime. As variáveis "timeBefore" e "timeAfter" são definidas para calcular o intervalo de tempo em torno da hora atual do servidor, obtida usando a função TimeTradeServer, subtraindo e somando "timeRange", respectivamente. Isso garante que apenas os eventos que caem dentro do intervalo especificado (até um dia antes ou depois da hora atual do servidor) sejam considerados para processamento. Certifique-se de ajustar isso de acordo com suas necessidades. Com essa lógica em mãos, podemos então aplicar o filtro de tempo.

//--- Apply time filter and set timeMatch flag (if the filter is enabled)
bool timeMatch = false;
if (enableTimeFilter) {
   datetime eventTime = values[i].time;
   
   if (eventTime <= TimeTradeServer() && eventTime >= timeBefore) {
      timeMatch = true;  //--- Event is already released
   }
   else if (eventTime >= TimeTradeServer() && eventTime <= timeAfter) {
      timeMatch = true;  //--- Event is yet to be released
   }
   
   //--- Skip if the event doesn't match the time filter
   if (!timeMatch) {
      continue;
   }
}

Aqui, aplicamos o filtro de tempo verificando se o horário do evento está dentro do intervalo especificado, e usamos a flag "timeMatch" para acompanhar se o evento atende aos critérios. Se "enableTimeFilter" for verdadeiro, primeiro obtemos o horário do evento da variável "values[i].time". Em seguida, verificamos se o horário do evento está no passado (entre a hora atual do servidor e "timeBefore") ou no futuro (entre a hora atual do servidor e "timeAfter"). Se o horário do evento estiver dentro de um dos intervalos, a flag "timeMatch" é definida como verdadeira, indicando que o evento corresponde ao filtro de tempo. Se nenhuma correspondência for encontrada, ignoramos o evento usando a instrução continue.

Isso é tudo para os filtros. Se chegarmos aqui, significa que passamos por todos os testes e temos alguns eventos de notícias. Assim, atualizamos a contagem do filtro de notícias em mais um.

//--- If we reach here, the currency matches the filter
news_filter_count++; //--- Increment the count of filtered events

Agora é com os dados da contagem do filtro de notícias que usamos para criar as seções de armazenamento de dados, porque não estamos considerando todos os eventos selecionados desta vez. Isso garante que criemos apenas a quantidade necessária de armazenadores de dados que sejam relevantes para nós no painel.

//--- Set alternating colors for each data row holder
color holder_color = (news_filter_count % 2 == 0) ? C'213,227,207' : clrWhite;

//--- Create rectangle label for each data row holder
createRecLabel(DATA_HOLDERS+string(news_filter_count),62,startY-1,716,26+1,holder_color,1,clrNONE);

Aqui, definimos cores alternadas para cada armazenador de linha de dados para melhorar a distinção visual entre as linhas. A "holder_color" é determinada usando um ternary operator, onde se "news_filter_count" for par (ou seja, "news_filter_count % 2 == 0"), a cor será definida para um tom de verde claro (C'213,227,207'), e se for ímpar, a cor será branca. Isso garante que cada linha alterne de cor, tornando os dados mais fáceis de ler.

Em seguida, criamos um rótulo de retângulo para cada armazenador de linha de dados usando a função "createRecLabel", que coloca um retângulo colorido nas coordenadas especificadas. O rótulo é identificado de forma única ao combinar "DATA_HOLDERS" com a representação em string de "news_filter_count", para garantir que cada linha tenha um nome único, e as dimensões do retângulo são ajustadas para caber no conteúdo. A borda do retângulo é definida com espessura 1, enquanto a cor de preenchimento é definida para a "holder_color" alternada, e a cor da borda é definida como "clrNONE" para não ter cor de borda.

No entanto, observe que adicionamos 1 pixel ao deslocamento em y dos armazenadores, destacado em cor amarela, para eliminar as bordas. Aqui está um resultado comparativo.

Antes da adição de 1 pixel:

ANTES DA MUDANÇA

Depois da adição de 1 pixel:

APÓS A MUDANÇA

Isso foi um sucesso. A próxima coisa que precisamos fazer é atualizar o total de notícias exibidas no painel quando os filtros são aplicados.

updateLabel(TIME_LABEL,"Server Time: "+TimeToString(TimeCurrent(),
           TIME_DATE|TIME_SECONDS)+"   |||   Total News: "+
           IntegerToString(news_filter_count)+"/"+IntegerToString(allValues));

Aqui, usamos a função "updateLabel" para atualizar o rótulo que exibe a hora atual do servidor e o número total de eventos de notícias filtrados. Atualizamos o rótulo identificado por "TIME_LABEL" com uma nova string que combina a hora atual do servidor e a contagem de eventos de notícias. Para obter a hora atual do servidor, usamos a função TimeCurrent e a formatamos usando a função TimeToString com as flags "TIME_DATE | TIME_SECONDS".

Em seguida, exibimos o número total de eventos de notícias filtrados, armazenados em "news_filter_count", ao lado do número total de eventos de notícias disponíveis, representado por "allValues". Ao atualizar esse rótulo, fornecemos informações em tempo real sobre a hora do servidor e o status do filtro de notícias, ajudando-nos a nos manter informados sobre as notícias de mercado atuais que são importantes para nós.

O trecho de código da função personalizada que usamos para atualizar o rótulo é o seguinte.

//+------------------------------------------------------------------+
//|     Function to create text label                                |
//+------------------------------------------------------------------+

bool updateLabel(string objName,string txt) {
    // Reset any previous errors
    ResetLastError();

    if (!ObjectSetString(0,objName,OBJPROP_TEXT,txt)) {
        Print(__FUNCTION__, ": failed to update the label! Error code = ", _LastError);
        return (false);
    }

    ObjectSetString(0, objName, OBJPROP_TEXT, txt); // Text displayed on the label

    // Redraw the chart to display the label
    ChartRedraw(0);

    return (true); // Label creation successful
}

Aqui, definimos a função "updateLabel", que usamos para atualizar um rótulo existente no gráfico. <segmento 0376 ¶> A função recebe dois parâmetros: "objName" (o nome do objeto rótulo) e "txt" (o texto a ser exibido no rótulo). Começamos redefinindo quaisquer erros anteriores usando a função ResetLastError para garantir um ambiente limpo. Em seguida, tentamos atualizar o texto do rótulo com a string fornecida "txt" usando a função ObjectSetString. Se a atualização falhar, imprimimos uma mensagem de erro usando a função Print junto com o código de erro recuperado de _LastError e retornamos "false".

Se a atualização do rótulo for bem-sucedida, chamamos a função ChartRedraw para atualizar o gráfico e exibir o rótulo atualizado, e finalmente retornamos "true" para indicar que a operação foi bem-sucedida. Essa é a função que nos permite atualizar dinamicamente o conteúdo dos rótulos no gráfico, fornecendo um método flexível para exibir informações como a hora do servidor ou a contagem de eventos de notícias. Ao executar o programa, é isso que temos.

NOTÍCIAS ATUALIZADAS

Com a implementação, agora temos certeza de que apenas consideramos as notícias que são relevantes para nós e ignoramos as demais. Também exibimos o total de notícias aprovadas em relação a todas as notícias selecionadas, mostrando tanto os eventos de notícias disponíveis quanto os considerados. O trecho completo do código de inicialização responsável pela aplicação dos filtros está abaixo.

string curr_filter[] = {"AUD","CAD","CHF","EUR","GBP","JPY","NZD","USD"};
int news_filter_count = 0;

// Define the levels of importance to filter (low, moderate, high)
ENUM_CALENDAR_EVENT_IMPORTANCE allowed_importance_levels[] = {CALENDAR_IMPORTANCE_LOW, CALENDAR_IMPORTANCE_MODERATE, CALENDAR_IMPORTANCE_HIGH};

//--- Loop through each calendar value up to the maximum defined total
for (int i = 0; i < valuesTotal; i++){

   MqlCalendarEvent event; //--- Declare event structure
   CalendarEventById(values[i].event_id,event); //--- Retrieve event details by ID

   MqlCalendarCountry country; //--- Declare country structure
   CalendarCountryById(event.country_id,country); //--- Retrieve country details by event's country ID

   MqlCalendarValue value; //--- Declare calendar value structure
   CalendarValueById(values[i].id,value); //--- Retrieve actual, forecast, and previous values
   
   
   //--- Check if the event’s currency matches any in the filter array (if the filter is enabled)
   bool currencyMatch = false;
   if (enableCurrencyFilter) {
      for (int j = 0; j < ArraySize(curr_filter); j++) {
         if (country.currency == curr_filter[j]) {
            currencyMatch = true;
            break;
         }
      }
      
      //--- If no match found, skip to the next event
      if (!currencyMatch) {
         continue;
      }
   }
   
   //--- Check importance level if importance filter is enabled
   bool importanceMatch = false;
   if (enableImportanceFilter) {
      for (int k = 0; k < ArraySize(allowed_importance_levels); k++) {
         if (event.importance == allowed_importance_levels[k]) {
            importanceMatch = true;
            break;
         }
      }
      
      //--- If importance does not match the filter criteria, skip the event
      if (!importanceMatch) {
         continue;
      }
   }
   
   //--- Apply time filter and set timeMatch flag (if the filter is enabled)
   bool timeMatch = false;
   if (enableTimeFilter) {
      datetime eventTime = values[i].time;
      
      if (eventTime <= TimeTradeServer() && eventTime >= timeBefore) {
         timeMatch = true;  //--- Event is already released
      }
      else if (eventTime >= TimeTradeServer() && eventTime <= timeAfter) {
         timeMatch = true;  //--- Event is yet to be released
      }
      
      //--- Skip if the event doesn't match the time filter
      if (!timeMatch) {
         continue;
      }
   }
   
   //--- If we reach here, the currency matches the filter
   news_filter_count++; //--- Increment the count of filtered events
   
   //--- Set alternating colors for each data row holder
   color holder_color = (news_filter_count % 2 == 0) ? C'213,227,207' : clrWhite;

   //--- Create rectangle label for each data row holder
   createRecLabel(DATA_HOLDERS+string(news_filter_count),62,startY-1,716,26+1,holder_color,1,clrNONE);

   //--- Initialize starting x-coordinate for each data entry
   int startX = 65;
   
   //--- Loop through calendar data columns
   for (int k=0; k<ArraySize(array_calendar); k++){
         
      //--- Print event details for debugging
      //Print("Name = ",event.name,", IMP = ",EnumToString(event.importance),", COUNTRY = ",country.name,", TIME = ",values[i].time);
   
      //--- Skip event if currency does not match the selected country code
      // if (StringFind(_Symbol,country.currency) < 0) continue;
   
      //--- Prepare news data array with time, country, and other event details
      string news_data[ArraySize(array_calendar)];
      news_data[0] = TimeToString(values[i].time,TIME_DATE); //--- Event date
      news_data[1] = TimeToString(values[i].time,TIME_MINUTES); //--- Event time
      news_data[2] = country.currency; //--- Event country currency
   
      //--- Determine importance color based on event impact
      color importance_color = clrBlack;
      if (event.importance == CALENDAR_IMPORTANCE_LOW){importance_color=clrYellow;}
      else if (event.importance == CALENDAR_IMPORTANCE_MODERATE){importance_color=clrOrange;}
      else if (event.importance == CALENDAR_IMPORTANCE_HIGH){importance_color=clrRed;}
   
      //--- Set importance symbol for the event
      news_data[3] = ShortToString(0x25CF);
   
      //--- Set event name in the data array
      news_data[4] = event.name;
         
      //--- Populate actual, forecast, and previous values in the news data array
      news_data[5] = DoubleToString(value.GetActualValue(),3);
      news_data[6] = DoubleToString(value.GetForecastValue(),3);
      news_data[7] = DoubleToString(value.GetPreviousValue(),3);         
      
      //--- Create label for each news data item
      if (k == 3){
         createLabel(ARRAY_NEWS+IntegerToString(i)+" "+array_calendar[k],startX,startY-(22-12),news_data[k],importance_color,22,"Calibri");
      }
      else {
         createLabel(ARRAY_NEWS+IntegerToString(i)+" "+array_calendar[k],startX,startY,news_data[k],clrBlack,12,"Calibri");
      }
   
      //--- Increment x-coordinate for the next column
      startX += buttons[k]+3;
   }
   //--- Increment y-coordinate for the next row of data
   startY += 25;
   //Print(startY); //--- Print current y-coordinate for debugging
}

//Print("Final News = ",news_filter_count);
updateLabel(TIME_LABEL,"Server Time: "+TimeToString(TimeCurrent(),
           TIME_DATE|TIME_SECONDS)+"   |||   Total News: "+
           IntegerToString(news_filter_count)+"/"+IntegerToString(allValues));

Isso foi um sucesso. No final, queremos remover o painel do gráfico quando o programa for removido, deixando um ambiente limpo. Para conseguir isso de forma fácil e mais profissional, podemos definir uma função onde adicionamos toda a lógica de controle.

//+------------------------------------------------------------------+
//|      Function to destroy the Dashboard panel                     |
//+------------------------------------------------------------------+

void destroy_Dashboard(){

   //--- Delete main rectangle panel
   ObjectDelete(0, MAIN_REC);
   
   //--- Delete first sub-rectangle in the dashboard
   ObjectDelete(0, SUB_REC1);
   
   //--- Delete second sub-rectangle in the dashboard
   ObjectDelete(0, SUB_REC2);
   
   //--- Delete header label text
   ObjectDelete(0, HEADER_LABEL);
   
   //--- Delete server time label text
   ObjectDelete(0, TIME_LABEL);
   
   //--- Delete label for impact/importance
   ObjectDelete(0, IMPACT_LABEL);

   //--- Delete all objects related to the calendar array
   ObjectsDeleteAll(0, ARRAY_CALENDAR);
   
   //--- Delete all objects related to the news array
   ObjectsDeleteAll(0, ARRAY_NEWS);
   
   //--- Delete all data holder objects created in the dashboard
   ObjectsDeleteAll(0, DATA_HOLDERS);
   
   //--- Delete all impact label objects
   ObjectsDeleteAll(0, IMPACT_LABEL);
   
   //--- Redraw the chart to update any visual changes
   ChartRedraw(0);
}

Aqui, definimos a função personalizada "destroy_Dashboard", que usaremos para lidar com a remoção completa de todos os elementos criados para nosso painel no gráfico, retornando-o ao estado inicial. Isso envolve excluir cada objeto, rótulo e armazenador usados dentro do painel. Primeiro, excluímos o retângulo principal do painel chamando a função ObjectDelete em "MAIN_REC", que representa o contêiner primário do painel. Em seguida, prosseguimos para remover quaisquer sub-retângulos, como "SUB_REC1" e "SUB_REC2", que usamos para organizar várias seções do painel.

Após isso, excluímos os rótulos que exibem informações como o cabeçalho do painel ("HEADER_LABEL"), hora do servidor ("TIME_LABEL") e nível de impacto ("IMPACT_LABEL"). Cada um desses rótulos é removido para garantir que qualquer informação textual exibida no gráfico seja limpa. Em seguida, excluímos todos os objetos em "ARRAY_CALENDAR" e "ARRAY_NEWS", que armazenam informações sobre o calendário e os dados de notícias, respectivamente. Realizamos essa ação usando a função ObjectsDeleteAll, que nos permite limpar quaisquer objetos criados dinamicamente associados a esses arrays.

Em seguida, excluímos todos os objetos relacionados a "DATA_HOLDERS", que representam linhas individuais ou contêineres exibindo pontos de dados no painel, seguido de outra chamada para excluir instâncias de "IMPACT_LABEL", garantindo que nenhum elemento visual permaneça.

Finalmente, chamamos a função ChartRedraw, que atualiza o gráfico e remove quaisquer vestígios do painel, fornecendo uma tela limpa para quaisquer atualizações futuras ou redefinições visuais necessárias após removermos o programa. Essa função essencialmente desmonta toda a exibição do painel, preparando o gráfico para novas atualizações ou outros elementos visuais conforme necessário. Por fim, apenas chamamos a função no manipulador de eventos OnDeinit para efetivar a remoção do painel.

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason){
//---

   destroy_Dashboard(); 
}

Após chamar a função personalizada no manipulador de eventos OnDeinit, garantimos a remoção do painel do gráfico. Isso é tudo o que é necessário para adicionar os filtros ao nosso painel.


Conclusão

Em conclusão, aprimoramos com sucesso nosso painel MQL5 Economic Calendar integrando recursos essenciais de filtragem, que usamos para visualizar apenas os eventos de notícias mais relevantes com base em moeda, importância e tempo. Esses filtros fornecem uma interface mais simplificada e focada, permitindo que nos concentremos em eventos econômicos que estejam alinhados com nossa estratégia e objetivos específicos de negociação.

Ao refinar o painel com esses filtros, tornamos a ferramenta mais poderosa e eficiente para a tomada de decisões informadas. Na próxima parte, ampliaremos essa base adicionando atualizações em tempo real à lógica do painel de calendário, permitindo que ele se atualize constantemente com as últimas notícias econômicas diretamente dentro do nosso painel MQL5.

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

Arquivos anexados |
Caminhe em novos trilhos: Personalize indicadores no MQL5 Caminhe em novos trilhos: Personalize indicadores no MQL5
Vou agora listar todas as possibilidades novas e recursos do novo terminal e linguagem. Elas são várias, e algumas novidades valem a discussão em um artigo separado. Além disso, não há códigos aqui escritos com programação orientada ao objeto, é um tópico muito importante para ser simplesmente mencionado em um contexto como vantagens adicionais para os desenvolvedores. Neste artigo vamos considerar os indicadores, sua estrutura, desenho, tipos e seus detalhes de programação em comparação com o MQL4. Espero que este artigo seja útil tanto para desenvolvedores iniciantes quanto para experientes, talvez alguns deles encontrem algo novo.
Dominando Registros de Log (Parte 1): Conceitos Fundamentais e Primeiros Passos em MQL5 Dominando Registros de Log (Parte 1): Conceitos Fundamentais e Primeiros Passos em MQL5
Bem-vindo ao início de mais uma jornada! Este artigo abre uma série especial onde criaremos, passo a passo, uma biblioteca para manipulação de logs, feita sob medida para quem desenvolve na linguagem MQL5.
Está chegando o novo MetaTrader 5 e MQL5 Está chegando o novo MetaTrader 5 e MQL5
Esta é apenas uma breve resenha do MetaTrader 5. Eu não posso descrever todos os novos recursos do sistema por um período tão curto de tempo - os testes começaram em 09.09.2009. Esta é uma data simbólica, e tenho certeza que será um número de sorte. Alguns dias passaram-se desde que eu obtive a versão beta do terminal MetaTrader 5 e MQL5. Eu ainda não consegui testar todos os seus recursos, mas já estou impressionado.
Criando um painel de administração de trading em MQL5 (Parte VII): Usuário confiável, recuperação e criptografia Criando um painel de administração de trading em MQL5 (Parte VII): Usuário confiável, recuperação e criptografia
Alertas de segurança, como aqueles que aparecem sempre que o gráfico é atualizado, uma nova par é adicionada ao chat do painel administrativo do EA ou o terminal é reiniciado, podem se tornar cansativos. Nesta discussão, vamos analisar e implementar uma função que rastreia o número de tentativas de login para identificar um usuário confiável. Após um determinado número de tentativas malsucedidas, o aplicativo passará para um procedimento avançado de login, que também facilita a recuperação de senha para usuários que possam tê-la esquecido. Além disso, veremos como é possível integrar de forma eficiente a criptografia no painel administrativo para aumentar a segurança.