Do iniciante ao especialista: criação de um EA animado para notícias em MQL5 (I)
Sumário:
Introdução
Hoje, buscamos eliminar uma limitação comum no acesso a notícias econômicas e eventos do calendário econômico no terminal MetaTrader 5, especialmente durante a análise de gráficos ativos.
No terminal MetaTrader 5, as abas "Notícias" (News) e "Calendário Econômico" (Economic Calendar) ficam disponíveis na janela Caixa de Ferramentas. Essas abas apresentam informações importantes obtidas de provedores de notícias confiáveis. No entanto, é muito importante entender a diferença entre elas:
- Aba "Notícias": exibe manchetes e atualizações que já foram publicadas.
- "Calendário Econômico": contém a programação dos próximos eventos econômicos, distribuídos por data, horário e importância, o que é útil para o planejamento futuro.
As duas ferramentas são essenciais para a análise de mercado. Traders experientes sabem que algumas notícias econômicas, como decisões sobre taxas de juros ou dados de emprego fora do setor agrícola, podem afetar significativamente o mercado. Com a preparação adequada, esses eventos abrem oportunidades lucrativas de negociação. No entanto, eles também envolvem risco considerável quando o resultado diverge do cenário esperado.

Acesso às notícias e ao Calendário Econômico no MetaTrader 5
Na captura de tela publicada anteriormente, é possível observar que o MetaTrader 5 oferece acesso tanto às "Notícias" quanto ao Calendário Econômico em um único ambiente integrado. No entanto, uma limitação importante se torna evidente: para visualizar qualquer uma dessas funções, o usuário precisa acessar manualmente a janela Caixa de Ferramentas.
Dentro da Caixa de Ferramentas, as informações são apresentadas em forma de tabela, com linhas e colunas que mostram diferentes notícias, eventos programados e seus respectivos detalhes. Os usuários podem percorrer o feed de notícias para ler as manchetes ou consultar o calendário para visualizar as próximas divulgações econômicas. Embora a Caixa de Ferramentas possa ser expandida para exibir mais conteúdo, isso reduz o tamanho da janela do gráfico, o que pode prejudicar a visualização do movimento do preço, dos indicadores ou dos objetos gráficos.
A solução que propomos elimina essa limitação ao exibir manchetes de notícias e eventos do Calendário Econômico diretamente no gráfico, preservando a visibilidade total, sem invadir a área do gráfico e sem interferir nos objetos de negociação. O objetivo é melhorar o acesso à informação e a consciência situacional, preservando ao mesmo tempo um ambiente gráfico limpo e funcional.
Nesta seção introdutória da nossa minissérie, vou começar me concentrando na implementação do Calendário Econômico do MQL5 para exibir manchetes dos próximos eventos do calendário. A solução se inspira na forma como manchetes costumam aparecer na parte inferior da tela da televisão e também no modo como anúncios são exibidos em vídeos de redes sociais.
Na seção seguinte, apresentaremos a abordagem que será usada para criar o EA "Manchetes de Notícias" usando MQL5. Vamos apresentar a estratégia de desenvolvimento, examinar as principais decisões de implementação e, em seguida, analisar a base de código em detalhes.
Por fim, na conclusão, apresentaremos os resultados dos testes e as observações, oferecendo uma visão completa do ciclo de desenvolvimento desse sistema de exibição de notícias em tempo real no MetaTrader 5.
Conceito
Para dar vida a essa ideia, usaremos a Biblioteca Padrão do MQL5, que fornece ferramentas confiáveis para o desenvolvimento de interface gráfica. Especificamente, usaremos a classe CCanvas, localizada no arquivo MQL5\Include\Canvas\Canvas.mqh. Essa classe nos permite criar superfícies gráficas retangulares e transparentes, ideais para sobrepor conteúdo dinâmico, como manchetes de notícias e atualizações de eventos econômicos, diretamente no gráfico.
Nossa implementação se baseia em uma faixa rolante de notícias, que exibe continuamente informações relevantes sem atrapalhar a análise dos gráficos. Esse conceito vem de interfaces reais vistas em telejornais, sites financeiros e até mesmo em conteúdos de vídeo de redes sociais, onde manchetes chamativas se movem pela tela, fornecendo atualizações em tempo real.

Fragmento da definição de manchete da Google search.
Neste ponto, você pode estar se perguntando por que chamamos especificamente este EA de "Manchetes de Notícias". O termo "manchete" se refere a um título curto e visualmente destacado que resume as informações principais, concebido para ser fácil de ver e rápido de entender. No nosso caso, trata-se de uma forma compacta de transmitir dados de mercado relevantes, como notícias ou divulgações econômicas, em um formato acessível e visualmente atraente.

Conceito: extrair dados do Calendário Econômico usando a API MQL5 e exibir os próximos eventos diretamente no gráfico com a ajuda do nosso EA personalizado "Manchetes de Notícias".
Para simplificar esta etapa do desenvolvimento, começaremos nos concentrando em dois componentes principais:
- Entender e usar a classe CCanvas em MQL5, o que permite desenhar elementos gráficos personalizados no gráfico.
- Implementar o Calendário Econômico do MQL5 usando funções nativas para buscar eventos futuros e exibi-los com um efeito de rolagem horizontal.
Esse formato de rolagem horizontal foi concebido especificamente para preservar espaço vertical valioso no gráfico e fornecer uma exibição integrada e discreta das informações relevantes.
Como aprimoramento futuro, também planejamos integrar uma API externa de notícias. Isso nos permitirá exibir notícias do mercado em tempo real em uma faixa rolante separada abaixo dos eventos do calendário. Por enquanto, vamos estabelecer a base inserindo um indicador placeholder para representar o feed de notícias.
Em um primeiro momento, o trader que usar esse sistema poderá:- Identificar instantaneamente eventos importantes futuros.
- Acompanhar quanto tempo falta para que eles ocorram, por exemplo, em horas ou minutos.
- Reconhecer o nível esperado de impacto, o que permite ao trader adotar uma estratégia mais cautelosa ou mais bem fundamentada.
Depois de examinar os principais conceitos, passamos a analisar com mais detalhes a implementação.
Implementação
Dominando a manchete com Canvas
A classe CCanvas em MQL5 é um utilitário poderoso e versátil, projetado para criar interfaces gráficas personalizadas e elementos visuais diretamente nos gráficos do MetaTrader 5, bem como gerenciá-los. Em sua essência, a CCanvas permite que os desenvolvedores criem superfícies de bitmap na memória, que são exibidas por meio de objetos do gráfico, como OBJ_BITMAP e OBJ_BITMAP_LABEL. Isso permite exibir dinamicamente conteúdo gráfico, incluindo linhas, formas, polígonos e texto, sobre os gráficos, sem interferir no funcionamento dos elementos nativos do gráfico. A classe oferece controle de baixo nível sobre a renderização por meio do buffer de pixels (m_pixels[]), além de funções como CreateBitmapLabel() para inicialização e Update() para atualizar a saída visual.
CCanvas oferece gestão eficiente de recursos: os desenvolvedores podem carregar ou salvar imagens bitmap, vincular ou desvincular áreas Canvas dos gráficos e manipular pixels diretamente com PixelSet() ou PixelGet(), o que a torna ideal para aplicações sensíveis ao desempenho. Sua flexibilidade se estende aos formatos de cor (ARGB, XRGB com transparência), à renderização de polígonos (incluindo preenchimentos não convexos) e a interfaces gráficas multicamadas.
Na prática, CCanvas abre caminho para o desenvolvimento sofisticado de interfaces personalizadas no MetaTrader 5. Ela é comumente usada para criar indicadores personalizados, como sobreposições suavizadas ou sombreadas, ferramentas interativas, como linhas de tendência com extremidades personalizadas, painéis de visualização de trading e painéis gráficos completos com botões, controles deslizantes ou até mesmo uma faixa rolante de notícias. Embora a renderização limitada à CPU restrinja os recursos gráficos em cenários de resolução extremamente alta, a precisão em nível de pixel e a personalização completa a tornam indispensável para interfaces gráficas avançadas.
Dominando a aba Calendário Econômico
Ao trabalhar com o Calendário Econômico do MetaTrader 5, a primeira coisa a entender é que cada evento está vinculado a um país específico (ou a uma união econômica) por meio de um identificador único de país. Em MQL5, isso é representado pela estrutura MqlCalendarCountry, que inclui campos como id (código ISO 3166-1), nome do país, código de duas letras, código e símbolo da moeda, e até um nome do país adequado para URL. Ao consultar uma única vez a lista de registros MqlCalendarCountry no Calendário Econômico, você obtém acesso a todos os atributos necessários para filtrar ou agrupar eventos por região. Em seguida, cada evento do Calendário Econômico faz referência ao seu país por meio do campo country_id na estrutura MqlCalendarEvent.
Essa estrutura descreve as características gerais de um tipo de evento recorrente: seu nome, importância, setor da economia (PIB, mercado de trabalho, preços etc.), periodicidade (diária, mensal, trimestral) e as unidades de medida em que seus valores são apresentados. É importante observar que ela não representa uma ocorrência isolada, mas sim um "modelo" ou uma definição de evento, por exemplo, "divulgação do índice de preços ao consumidor dos EUA", que o serviço do Calendário Econômico pode programar várias vezes ao longo do histórico publicado.
As ocorrências efetivamente programadas desses tipos de evento, com timestamps, valores divulgados e previstos, além de eventuais revisões, são armazenadas em uma tabela separada de estruturas MqlCalendarValue. Cada registro MqlCalendarValue contém event_id (referência ao modelo em MqlCalendarEvent), o horário e o período exatos, além de quatro campos numéricos (actual_value, forecast_value, prev_value, revised_prev_value), que podem já estar preenchidos ou ainda não. Métodos auxiliares, como HasActualValue() e GetActualValue(), simplificam a verificação e a extração dos valores divulgados, automaticamente escalonados a partir da representação interna em "ppm" usada pelo calendário.
Essa estrutura relacional, composta por países, tipos de evento e seus respectivos valores, garante que os dados nunca sejam duplicados sem necessidade: por exemplo, todos os registros trimestrais do índice de preços ao consumidor apontam para uma única definição desse índice, que contém o nível de importância, as unidades de medida e a frequência. Ao entender essas estruturas e como elas se relacionam entre si, podemos filtrar, formatar e exibir com precisão apenas os próximos eventos que nos interessam, mantendo ao mesmo tempo a eficiência e a facilidade de manutenção do nosso código.
EA "Manchetes de Notícias"
Configuração de controles personalizados
Primeiro, decidimos quais parâmetros os traders devem poder configurar. Expomos a velocidade de rolagem de cada faixa de importância (InpSpeedHigh, InpSpeedMed, InpSpeedLow), a velocidade de rolagem de notícias (InpNewsSpeed) e o intervalo entre quadros (InpTimerMs). Também permitimos que o usuário escolha se o ticker ficará na parte superior ou inferior (InpPositionTop), a que distância ele deve ficar da borda do gráfico (InpTopOffset) e quais faixas serão exibidas (ShowHigh, ShowMed, ShowLow). Ao reunir tudo isso em um bloco organizado de "Entradas do usuário" (User Inputs), qualquer pessoa pode ajustar rapidamente o comportamento sem precisar entrar nos detalhes da implementação.
//+------------------------------------------------------------------+ //| 1) USER INPUTS | //+------------------------------------------------------------------+ input int InpSpeedHigh = 4; // px/frame for High-impact lane input int InpSpeedMed = 2; // px/frame for Medium-impact lane input int InpSpeedLow = 1; // px/frame for Low-impact lane input int InpNewsSpeed = 5; // px/frame for news ticker row input int InpTimerMs = 50; // ms between frames (~20 fps) input bool InpPositionTop = true; // true=top, false=bottom input int InpTopOffset = 50; // px offset from chart edge input bool ShowHigh = true; // toggle High lane input bool ShowMed = true; // toggle Medium lane input bool ShowLow = true; // toggle Low lane
Definição das constantes de layout
Em seguida, definimos as regras de espaçamento fixo que determinam o layout visual: quantos pixels separam o rótulo com o tempo restante do da sigla da moeda (GapTimeToSym), quais espaçamentos mantemos ao redor de nossa caixa de importância integrada (GapSymToRect, GapRectToName) e o tamanho desse campo (RectSize). Ao agrupar esses valores, podemos ajustar com precisão a aparência em um único lugar, em vez de alterar a rotina de desenho.
//+------------------------------------------------------------------+ //| 2) DEVELOPER CONSTANTS | //+------------------------------------------------------------------+ static const int GapTimeToSym = 10; // px gap after “[1h]” static const int GapSymToRect = 5; // px gap before inline box static const int RectSize = 8; // width & height of inline box static const int GapRectToName= 10; // px gap after inline box
Preservação do estado e dos buffers de renderização
Em seguida, declaramos variáveis globais para armazenar as dimensões do gráfico (canvW), a altura da linha (lineH), o texto de preenchimento da faixa de notícias e o timestamp usado para evitar consultas repetidas ao Calendário Econômico (lastReloadDay). Também instanciamos dois objetos CCanvas, um para as três faixas de eventos e outro para a faixa rolante de notícias. Por fim, definimos nossa classe CEvent e três arrays dinâmicos (highArr, medArr, lowArr) para armazenar os eventos recebidos do Calendário Econômico por importância. O deslocamento atual de rolagem de cada faixa (offHigh etc.) define o estado que mantemos durante a execução do EA.
//+------------------------------------------------------------------+ //| 3) GLOBALS | //+------------------------------------------------------------------+ int lineH = 16; // row height in px int canvW; // chart width string placeholder = // news ticker text "News feed coming soon – stay tuned with the calendar"; datetime lastReloadDay = 0; // daily reload guard CCanvas eventsCanvas, newsCanvas; // two layers // Event struct and arrays class CEvent : public CObject { public: datetime time; string sym, name; int imp; CEvent(datetime t,const string &S,const string &N,int I) { time=t; sym=S; name=N; imp=I; } }; CEvent *highArr[], *medArr[], *lowArr[]; int offHigh, offMed, offLow, offNews;
Funções auxiliares de posicionamento e ordenação
Para manter nossa lógica principal limpa, separamos duas pequenas funções auxiliares. A função SetCanvas() posiciona o objeto canvas na parte superior ou inferior do gráfico, de acordo com as configurações do usuário. SortArr() é um bubble sort simples que organiza cada array de importância pelo horário do evento, garantindo que nossas faixas sempre exibam os próximos eventos na sequência correta.
//+------------------------------------------------------------------+ //| Helper: position a canvas label | //+------------------------------------------------------------------+ void SetCanvas(string name,bool top,int yDist) { ObjectSetInteger(0,name,OBJPROP_CORNER, top?CORNER_LEFT_UPPER:CORNER_LEFT_LOWER); ObjectSetInteger(0,name,OBJPROP_XDISTANCE, 0); ObjectSetInteger(0,name,OBJPROP_YDISTANCE, yDist); } //+------------------------------------------------------------------+ //| Helper: sort events by time | //+------------------------------------------------------------------+ void SortArr(CEvent* &arr[]) { int n=ArraySize(arr); for(int i=0;i<n-1;i++) for(int j=i+1;j<n;j++) if(arr[i].time > arr[j].time) { CEvent *tmp=arr[i]; arr[i]=arr[j]; arr[j]=tmp; } }
Obtenção dos eventos de hoje
A função ReloadEvents() ocupa uma posição central na forma como extraímos e filtramos os dados. Ela consulta o Calendário Econômico do MetaTrader em busca de eventos programados da meia-noite de hoje até 24 horas depois. Ignoramos qualquer evento cujo timestamp já tenha ficado para trás. Cada evento válido é empacotado em um objeto CEvent e depois colocado no array high/medium/low de acordo com sua importância. No final, ordenamos cada faixa para que o evento mais próximo apareça primeiro na rolagem dessa faixa.
//+------------------------------------------------------------------+ //| ReloadEvents: load only *future* events for *today* | //+------------------------------------------------------------------+ void ReloadEvents() { datetime srv = TimeTradeServer(); // midnight today MqlDateTime dt; TimeToStruct(srv, dt); MqlDateTime m0 = {dt.year, dt.mon, dt.day,0,0,0}; datetime today = StructToTime(m0); if(today == lastReloadDay) return; lastReloadDay = today; // clear previous for(int i=0;i<ArraySize(highArr);i++) delete highArr[i]; for(int i=0;i<ArraySize(medArr); i++) delete medArr[i]; for(int i=0;i<ArraySize(lowArr); i++) delete lowArr[i]; ArrayResize(highArr,0); ArrayResize(medArr,0); ArrayResize(lowArr,0); // fetch events [today, today+24h) MqlCalendarValue vals[]; int cnt = CalendarValueHistory(vals, today, today+86400); for(int i=0;i<cnt;i++) { if(vals[i].time <= srv) continue; // skip past MqlCalendarEvent e; if(!CalendarEventById(vals[i].event_id, e)) continue; MqlCalendarCountry c; if(!CalendarCountryById(e.country_id, c)) continue; string sym = "[" + c.currency + "]"; CEvent *ev = new CEvent(vals[i].time, sym, e.name, e.importance); // classify if(e.importance==CALENDAR_IMPORTANCE_HIGH) { int s=ArraySize(highArr)+1; ArrayResize(highArr,s); highArr[s-1]=ev; } else if(e.importance==CALENDAR_IMPORTANCE_MODERATE) { int s=ArraySize(medArr)+1; ArrayResize(medArr,s); medArr[s-1]=ev; } else { int s=ArraySize(lowArr)+1; ArrayResize(lowArr,s); lowArr[s-1]=ev; } } SortArr(highArr); SortArr(medArr); SortArr(lowArr); }
Em mais detalhes, quando a função ReloadEvents() é executada, ela extrai a lista completa dos registros de hoje do Calendário Econômico por meio de CalendarValueHistory(), mas cada registro bruto informa apenas event_id e country_id. Ao combiná-los com a tabela MqlCalendarEvent, na qual cada tipo de evento contém seu nome, frequência, setor e, acima de tudo, sua importância, podemos apresentar apenas os eventos realmente relevantes para o mercado. A estrutura MqlCalendarCountry garante que rotulemos cada manchete com a moeda correta, por exemplo, [USD] para os Estados Unidos, com base em seu código ISO e símbolo. Essa busca em duas etapas (valor → tipo de evento → país) permite que nosso EA se atualize rapidamente, extraindo apenas o necessário, e seja preciso, já que nunca deixamos informações sobre país ou evento fixas no código, mas confiamos no próprio banco de dados do MetaTrader, mantida constantemente sincronizada.
As constantes de importância (CALENDAR_IMPORTANCE_HIGH, ..._MODERATE, ..._LOW) formam a base da nossa lógica de montagem das faixas. Ao escolher os níveis de importância que serão incluídos (ShowHigh/ShowMed/ShowLow) e colorir cada caixa de importância integrada em vermelho, laranja ou branco, damos ao trader um sinal visual imediato: em vermelho, marcamos as divulgações de maior impacto, por exemplo, decisões do Fed sobre taxas de juros e dados de emprego fora do setor agrícola; em laranja, as divulgações de impacto médio, como Índice de Preços ao Consumidor e vendas no varejo; e, em branco, as menos importantes, como pronunciamentos de menor relevância e dados de menor relevância.
Na prática, isso ajuda o trader a identificar imediatamente se precisa aumentar a distância dos stops ou até pausar estratégias automáticas conforme um evento importante se aproxima. Sem esse filtro e essa marcação por cor, baseada no campo de importância em MqlCalendarEvent, uma lista em rolagem com dezenas de registros rapidamente se transformaria em ruído, e não em sinal.
Renderização da faixa de rolagem
DrawLane() encapsula a lógica de uma única faixa horizontal. Escolhemos uma fonte monoespaçada ("Courier New") para que todos os caracteres, incluindo colchetes e números, tenham a mesma largura, garantindo um alinhamento limpo. Em seguida, desenhamos:
- Rótulo do tempo restante (horas ou minutos).
- Símbolo da moeda.
- Caixa de importância integrada (colorida em vermelho/laranja/branco).
- Nome do evento, seguido de um separador caso haja outros eventos depois dele.
Por fim, reduzimos o deslocamento da faixa pelo valor da velocidade da faixa e, se a linha inteira já tiver passado pela borda esquerda, nós a reposicionamos à direita.
//+------------------------------------------------------------------+ //| DrawLane: scroll one lane with inline importance box | //+------------------------------------------------------------------+ void DrawLane(CEvent* &arr[], int &offset, int y, int speed) { int n=ArraySize(arr); if(n==0) return; // monospaced for alignment eventsCanvas.FontNameSet("Courier New"); eventsCanvas.FontSizeSet(-100); int x = offset; datetime srv = TimeTradeServer(); for(int i=0;i<n;i++) { CEvent *e = arr[i]; // time-left “[1h]” or “[45m]” long diff = (long)e.time - (long)srv; string tl = (diff>=3600 ? IntegerToString(diff/3600)+"h" : IntegerToString(diff/60)+"m"); string part = "[" + tl + "]"; eventsCanvas.TextOut(x,y,part,XRGB(255,255,255),ALIGN_LEFT); x += eventsCanvas.TextWidth(part) -20; // symbol “[USD]” eventsCanvas.TextOut(x,y,e.sym,XRGB(255,255,255),ALIGN_RIGHT); x += eventsCanvas.TextWidth(e.sym) + GapSymToRect; // inline importance box uint col = (e.imp==CALENDAR_IMPORTANCE_HIGH ? XRGB(255,0,0) : e.imp==CALENDAR_IMPORTANCE_MODERATE? XRGB(255,165,0): XRGB(255,255,255)); eventsCanvas.FillRectangle(x, y + (lineH-RectSize)/2, x+RectSize, y + (lineH-RectSize)/2 + RectSize, col); x += RectSize + GapRectToName; // event name + separator eventsCanvas.TextOut(x,y,e.name,XRGB(255,255,255),ALIGN_RIGHT); x += eventsCanvas.TextWidth(e.name)+60; if(i+1<n) { eventsCanvas.TextOut(x,y,"|",XRGB(180,180,180),ALIGN_RIGHT); x += eventsCanvas.TextWidth("|") + 20; } } // scroll + wrap int totalW = x - offset; offset -= speed; if(offset + totalW < 0) offset = canvW; }
Montagem de todas as faixas e da linha de notícias
Em DrawAll(), posicionamos verticalmente as três faixas de eventos e depois colocamos o texto de preenchimento de notícias abaixo delas (ou acima, dependendo da posição). Depois de exibir os eventos em eventsCanvas, chamamos a função Update(false) para atualizar o conteúdo no objeto gráfico. O feed de notícias usa seu próprio newsCanvas, com uma exibição mais simples apenas de texto, seguida de Update(true) para atualização síncrona.
//+------------------------------------------------------------------+ //| DrawAll: render lanes + news row | //+------------------------------------------------------------------+ void DrawAll() { // clear events eventsCanvas.Erase(ARGB(180,0,0,0)); int y=0; if(ShowHigh) { DrawLane(highArr, offHigh, y, InpSpeedHigh); y += lineH; } if(ShowMed) { DrawLane(medArr, offMed, y, InpSpeedMed); y += lineH; } if(ShowLow) { DrawLane(lowArr, offLow, y, InpSpeedLow); y += lineH; } eventsCanvas.Update(false); // news placeholder newsCanvas.Erase(ARGB(170,0,0,0)); newsCanvas.FontNameSet("Tahoma"); newsCanvas.FontSizeSet(-120); int yOff = (lineH - newsCanvas.TextHeight(placeholder)) / 2; newsCanvas.TextOut(offNews, yOff, placeholder, XRGB(255,255,255), ALIGN_LEFT); offNews -= InpNewsSpeed; if(offNews + newsCanvas.TextWidth(placeholder) < -20) offNews = canvW; newsCanvas.Update(true); }
Inicialização, timer e limpeza
Por fim, em OnInit(), criamos e configuramos nossos objetos Canvas, chamamos ReloadEvents() pela primeira vez, definimos todos os deslocamentos como canvW e posicionamos os dois canvases com base em InpPositionTop e InpTopOffset. Em seguida, desenhamos o primeiro quadro e iniciamos o timer em milissegundos.
OnTimer() apenas reposiciona os canvases (para que os usuários possam alternar InpPositionTop em tempo real), recarrega os eventos uma vez por dia, ajusta o tamanho do gráfico e chama DrawAll() novamente. OnDeinit() limpa os canvases e remove todos os objetos CEvent alocados.
//+------------------------------------------------------------------+ //| OnInit: setup canvases, initial load & position | //+------------------------------------------------------------------+ int OnInit() { // force reload Today lastReloadDay = 0; // clear arrays ArrayResize(highArr,0); ArrayResize(medArr,0); ArrayResize(lowArr,0); // chart width canvW = (int)ChartGetInteger(0,CHART_WIDTH_IN_PIXELS); // create events canvas (4 rows tall) eventsCanvas.CreateBitmapLabel("EvCanvas",0,0,canvW,4*lineH,COLOR_FORMAT_ARGB_RAW); eventsCanvas.TransparentLevelSet(150); // create news canvas (1 row tall) newsCanvas.CreateBitmapLabel("NwCanvas",0,0,canvW,lineH,COLOR_FORMAT_ARGB_RAW); newsCanvas.TransparentLevelSet(0); // load data + init offsets ReloadEvents(); offHigh = offMed = offLow = offNews = canvW; // initial positioning { int rows = (ShowHigh?1:0)+(ShowMed?1:0)+(ShowLow?1:0); int yOff = InpTopOffset + (InpPositionTop ? 0 : rows*lineH); SetCanvas("EvCanvas", InpPositionTop, InpTopOffset); SetCanvas("NwCanvas", InpPositionTop, yOff + (InpPositionTop ? rows*lineH : 0)); } // first draw & timer DrawAll(); EventSetMillisecondTimer(InpTimerMs); return INIT_SUCCEEDED; } //+------------------------------------------------------------------+ //| OnTimer: reposition, daily reload, redraw | //+------------------------------------------------------------------+ void OnTimer() { // reposition every tick int rows = (ShowHigh?1:0)+(ShowMed?1:0)+(ShowLow?1:0); if(InpPositionTop) { SetCanvas("EvCanvas", true, InpTopOffset); SetCanvas("NwCanvas", true, InpTopOffset + rows*lineH); } else { SetCanvas("EvCanvas", false, InpTopOffset); SetCanvas("NwCanvas", false, InpTopOffset + lineH); } // reload once per day ReloadEvents(); // adapt width int wNew = (int)ChartGetInteger(0,CHART_WIDTH_IN_PIXELS); if(wNew != canvW) { canvW = wNew; ObjectSetInteger(0,"EvCanvas",OBJPROP_WIDTH,canvW); ObjectSetInteger(0,"NwCanvas",OBJPROP_WIDTH,canvW); } // redraw DrawAll(); } //+------------------------------------------------------------------+ //| OnDeinit: cleanup | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { EventKillTimer(); eventsCanvas.Destroy(); ObjectDelete(0,"EvCanvas"); newsCanvas.Destroy(); ObjectDelete(0,"NwCanvas"); for(int i=0;i<ArraySize(highArr);i++) delete highArr[i]; for(int i=0;i<ArraySize(medArr); i++) delete medArr[i]; for(int i=0;i<ArraySize(lowArr); i++) delete lowArr[i]; }
Com esta etapa concluída, podemos começar a testar nosso código no gráfico. Durante o desenvolvimento, corrigi muitos erros de compilação, resultando em uma versão final limpa e bem estruturada. Depois de compilar os componentes listados acima, obtivemos um EA "Manchetes de Notícias" totalmente funcional, pronto para ser anexado ao gráfico. Veja minha experiência de teste na próxima seção.
Testes
No terminal MetaTrader 5, acesse a seção "EAs" e arraste o EA "Manchetes de Notícias" para o gráfico. Após ser adicionado com sucesso, o EA é exibido por padrão na parte superior do gráfico, com um deslocamento vertical de 50 pixels. Esse deslocamento evita a sobreposição dos botões Depth of Market (Book de Ofertas) e Trade Panel (painel de negociação), bem como do nome do EA no canto superior direito.
Você pode ajustar esse deslocamento para posicionar a área Canvas das manchetes em qualquer posição vertical desejada no gráfico. O EA conta com quatro faixas, cada uma com uma velocidade otimizada para a visualização das manchetes e operando a 20 quadros por segundo. As próximas notícias são exibidas como retângulos coloridos, indicando seu grau de importância.

Teste do News Headline EA.mq5
A imagem acima mostra a anexação bem-sucedida do EA "Manchetes de Notícias". Ele aparece exatamente como planejado, exibindo todas as próximas notícias com uma animação suave e fluida.
Conclusão
Com isso, encerramos mais uma etapa empolgante de desenvolvimento, que culminou em uma ferramenta prática e útil tanto para traders quanto para desenvolvedores. Conseguimos usar os recursos da classe Canvas para obter renderização eficiente e clareza visual, uma abordagem que também simplifica o desenvolvimento de interfaces.
Ao longo deste projeto, aprendemos a extrair dados do Calendário Econômico e exibi-los em um formato compreensível para o trader. O resultado é uma exibição clara e minimalista das próximas notícias diretamente no gráfico, ajudando a resolver um problema antigo das ferramentas de negociação orientadas por notícias.
Olhando adiante, a segunda versão deste EA implementará o acesso a uma API para obter notícias em tempo real, permitindo atualizações ainda mais dinâmicas. Além disso, o Canvas pode ser reaproveitado para exibir outros dados relevantes para a negociação, o que torna essa abordagem bastante versátil.
Com as notícias importantes claramente visíveis no gráfico, os traders podem tomar decisões mais bem fundamentadas, escolhendo se desejam participar do mercado ou permanecer de fora. Como boa prática, geralmente recomenda-se evitar negociar algumas horas antes e depois da divulgação de notícias importantes, para reduzir o risco e evitar picos bruscos de volatilidade.
Compartilhe suas ideias ou faça perguntas na seção de comentários abaixo. Você também pode encontrar os arquivos anexados logo abaixo deste artigo.
| Nome do arquivo | Descrição |
|---|---|
| NewsTicker.mq5 | Código-fonte principal do EA, que implementa o Calendário Econômico com rolagem em três faixas e um ticker de notícias de preenchimento diretamente no gráfico usando a classe CCanvas, com velocidade individual por faixa, caixas de importância integradas e contagem regressiva em tempo real. |
Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/18299
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.
Caminhe em novos trilhos: Personalize indicadores no MQL5
Desenvolvimento de um sistema personalizado de detecção do regime de mercado em MQL5 (Parte 1): Indicador
Está chegando o novo MetaTrader 5 e MQL5
Transferência de dados de ticks do MetaTrader para Python via sockets usando serviços MQL5
- 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