
Negociando com o Calendário Econômico do MQL5 (Parte 3): Adicionando Filtros de Moeda, Importância e Tempo
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:
- Introdução
- Compreendendo os Tipos de Filtros em Calendários Econômicos
- Implementando os Filtros em MQL5
- 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.
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.
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:
Depois da adição de 1 pixel:
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.
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
Aviso: Todos os direitos sobre esses materiais pertencem à MetaQuotes Ltd. É proibida a reimpressão total ou parcial.
Esse artigo foi escrito por um usuário do site e reflete seu ponto de vista pessoal. A MetaQuotes Ltd. não se responsabiliza pela precisão das informações apresentadas nem pelas possíveis consequências decorrentes do uso das soluções, estratégias ou recomendações descritas.





- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Você concorda com a política do site e com os termos de uso