Oi, pessoal! Hoje vamos falar sobre como integrar eventos de alto impacto do ForexFactory.com ao seu Expert Advisor (EA) para o MetaTrader 4. Estou desenvolvendo um EA focado em Petróleo Bruto e Brent e precisava saber exatamente quando sairia o relatório de 'Inventário de Petróleo'. Normalmente, esse relatório é divulgado às quartas-feiras às 10h30 (horário de Brasília), mas, em feriados, a data pode mudar. Para garantir que meu EA esteja sempre atualizado, a melhor solução foi usar um serviço online para validar a data de lançamento.
A primeira coisa que você precisa fazer é adicionar o site nas configurações do seu EA. Vá até a aba OPÇÕES | EXPERT ADVISOR e insira o endereço http://www.forexfactory.com/ (veja a imagem abaixo).

Agora, vamos definir uma estrutura no seu código para armazenar os eventos. Você pode colocar isso no topo do código, declarando DailyEvents como uma variável global, com o número máximo de eventos armazenados definido pela variável MaxDailyEvents.
// Definindo a estrutura dos eventos struct EVENTOS { string time; string title; string currency; bool displayed; }; #define MaxDailyEvents 20 // Aumente este número se você espera mais de 20 eventos de alto impacto. EVENTOS DailyEvents[MaxDailyEvents];
Em seguida, precisamos recuperar o código HTML do ForexFactory.com e analisá-lo. Se você não entende de código HTML, não se preocupe, vou te guiar por isso :)
Primeiro, vamos construir a URL para o WebRequest. Como só quero o calendário para hoje, vamos definir o parâmetro day da requisição para a data de hoje e enviar a requisição.
string url="http://www.forexfactory.com/calendar.php?day="; url += MthName(Month()) + DoubleToStr(Day(), 0) + "." + DoubleToStr(Year(), 0);
Depois, enviamos a requisição, verificamos o código de erro (se houver) e convertemos o array de caracteres retornado em uma string. Isso facilita a análise do código HTML.
// Enviando a requisição web ResetLastError(); res = WebRequest("GET", url, cookie, NULL, timeout, post, 0, result, headers); // Verificando erros if(res == -1) { Print("Erro na WebRequest. Código de erro = ", GetLastError()); MessageBox("Adicione o endereço 'http://forexfactory.com/' na lista de URLs permitidas na" + " aba 'Expert Advisors'", "Erro", MB_ICONINFORMATION); return(false); }
Se não houver erro, convertemos o array de caracteres result em uma string para facilitar a análise.
// Convertendo array de caracteres para string HTML = CharArrayToString(result);
Agora que temos uma string, podemos usar a função StringFind para localizar elementos HTML. O primeiro passo é garantir que o HTML retornado seja realmente da data de hoje e cortar qualquer coisa antes dessa tag HTML. A função GetHTMLElement é usada para analisar o código HTML e retornar o valor entre as tags HTML especificadas. Veja abaixo a sua definição.
// Calendário carregado, certifique-se de que seja para a data de hoje int i = StringFind(HTML, "<span class=\"date\">"); if(i == -1) return(false); HTML = StringSubstr(HTML, i); string date = GetHTMLElement(HTML, "<span>", "</span>"); if(date != MthName(Month()) + " " + DoubleToStr(Day(), 0)) return(false);
Agora que garantimos que o calendário retornado é para a data de hoje, vamos começar a analisar cada linha da tabela e extrair os elementos que precisamos: horário do evento, moeda, impacto e título do evento. Faremos isso para cada linha da tabela até o final do calendário ou até que o MaxDailyEvents seja alcançado.
Uma vez que os dados de cada linha tenham sido extraídos, adicionamos à estrutura DailyEvents.
// Agora, obtenha as linhas da tabela para cada evento lasttime = NULL; cnrt = 0; date = DoubleToStr(Year(), 0) + "." + DoubleToStr(Month(), 0) + "." + DoubleToStr(Day(), 0) + " "; do { // Obtendo informações do evento time = GetHTMLElement(HTML, "<td class=\"calendar__cell calendar__time time\">", "</td>"); if(StringFind(time, "<a name=\"upnext\"") == 0) time = GetHTMLElement(time, "class=\"upnext\">", "</span>"); if(StringLen(time) != 0) lasttime = time; if(StringLen(time) == 0) time = lasttime; time = date + time; currency = GetHTMLElement(HTML, "<td class=\"calendar__cell calendar__currency currency\">", "</td>"); impact = GetHTMLElement(HTML, "<span title=\"", "\" class=\""); i = StringFind(impact, " Impact"); if(i != -1) impact = StringSubstr(impact, 0, i); title = GetHTMLElement(HTML, "\"calendar__event-title\">", "</span>"); // Este é um evento de alto impacto? if(StringFind(Symbol(), currency) != -1 && impact == "High") { // Adicionando à estrutura de eventos diários DailyEvents[cntr].displayed = false; DailyEvents[cntr].time = time; DailyEvents[cntr].title = title; DailyEvents[cntr++].currency = currency; } // Cortando a string HTML para a próxima linha da tabela i = StringFind(HTML, "</tbody> </table> </td> </tr> "); if(i != -1) HTML = StringSubstr(HTML, i+30); if(StringFind(HTML, "</table> <div class=\"foot\">") == 0) i = -1; } while(i != -1 || cntr == MaxDailyEvents);
Após analisarmos todas as linhas da tabela e chegarmos ao final do calendário, precisamos exibir os eventos no gráfico. Se o evento for no futuro, quero que uma linha vertical seja exibida, e se for no passado, nada será exibido.
// Exibindo os eventos de alto impacto, se houver lasttime = NULL; for(cntr = 0; cntr < MaxDailyEvents; cntr++) { if(StringLen(DailyEvents[cntr].time) == 0) break; // Criando o marcador do evento no gráfico se o último mercado não for o mesmo horário if(lasttime != DailyEvents[cntr].time) { res = cntr; // Se tivermos um 'pm' na string, adicione 12 horas ao tempo if(StringFind(DailyEvents[cntr].time, "pm") != -1) DailyEvents[cntr].time = TimeToStr(StrToTime(DailyEvents[cntr].time) + 43200); if(ObjectCreate(0, Event + cntr, OBJ_EVENT, 0, StrToTime(DailyEvents[cntr].time), 0)) { ObjectSetString(0, Event + cntr, OBJPROP_TEXT, DailyEvents[cntr].title + " (" + DailyEvents[cntr].currency + ")"); ObjectSetInteger(0, Event + cntr, OBJPROP_COLOR, Red); ObjectSetInteger(0, Event + cntr, OBJPROP_WIDTH, 2); ObjectSetInteger(0, Event + cntr, OBJPROP_BACK, true); ObjectSetInteger(0, Event + cntr, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, Event + cntr, OBJPROP_SELECTED, false); ObjectSetInteger(0, Event + cntr, OBJPROP_HIDDEN, true); ObjectSetString(0, Event + cntr, OBJPROP_TOOLTIP, DailyEvents[cntr].title + " (" + DailyEvents[cntr].currency + ")"); } // Criando a linha vertical se o evento for no futuro if(TimeCurrent() < TimeOffset(DailyEvents[cntr].time, 0)) { if(ObjectCreate(0, VLine + cntr, OBJ_VLINE, 0, TimeOffset(DailyEvents[cntr].time, 0), 0)) { ObjectSetInteger(0, VLine + cntr, OBJPROP_COLOR, Red); ObjectSetInteger(0, VLine + cntr, OBJPROP_WIDTH, 1); ObjectSetInteger(0, VLine + cntr, OBJPROP_BACK, true); ObjectSetInteger(0, VLine + cntr, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, VLine + cntr, OBJPROP_SELECTED, false); ObjectSetInteger(0, VLine + cntr, OBJPROP_HIDDEN, true); ObjectSetString(0, VLine + cntr, OBJPROP_TOOLTIP, DailyEvents[cntr].title + " (" + DailyEvents[cntr].currency + ")"); } } else DailyEvents[cntr].displayed = true; } else { title = ObjectGetString(0, Event + res, OBJPROP_TOOLTIP); title += "\n" + DailyEvents[cntr].title + " (" + DailyEvents[cntr].currency + ")"; ObjectSetString(0, Event + res, OBJPROP_TOOLTIP, title); if(TimeCurrent() < TimeOffset(DailyEvents[cntr].time, 0)) ObjectSetString(0, VLine + res, OBJPROP_TOOLTIP, title); } lasttime = DailyEvents[cntr].time; }
Se os eventos estiverem no futuro, quero notificar o usuário sobre um evento que está prestes a acontecer, se estiver dentro de 5 minutos do horário atual, e remover a linha vertical. Isso é feito adicionando um código na sua função start() do EA ou indicador.
//+------------------------------------------------------------------+ //| Função de início do Expert | //+------------------------------------------------------------------+ void start() { string event = NULL; // Existe um evento de alto impacto nos próximos 5 minutos? for(int i = 0; i < MaxDailyEvents; i++) { if(StringLen(DailyEvents[i].time) == 0) break; if(TimeCurrent() >= StrToTime(DailyEvents[i].time) - 300 && TimeCurrent() < StrToTime(DailyEvents[i].time) && !DailyEvents[i].displayed) { // Evento em 5 minutos... event += DailyEvents[i].title + " (" + DailyEvents[i].currency + "), "; DailyEvents[i].displayed = true; // Deletando a linha vertical associada ao evento if(ObjectFind("VLine" + DoubleToStr(i, 0)) >= 0) ObjectDelete("VLine" + DoubleToStr(i, 0)); } } // Algo para exibir? if(StringLen(event) != 0) { event += "em 5 minutos."; Alert(event); } }
E finalmente, precisamos obter os eventos diários. Isso é feito adicionando uma linha na sua função OnInit().
//+------------------------------------------------------------------+ //| Função de inicialização do Expert | //+------------------------------------------------------------------+ int OnInit() { // Obtendo os eventos de hoje GetHighImpactEvents(); return(INIT_SUCCEEDED); }
Simples assim! Você pode, claro, modificar o código para exibir todos os eventos para o par de moedas ou adicionar parâmetros de entrada ao seu indicador ou EA para especificar qual impacto exibir (alto, médio ou baixo) e, claro, adicionar um controle para a virada da meia-noite para obter uma nova lista de eventos diários, mas vou deixar você brincar com isso :)
Um abraço!
- Claude.
Publicações relacionadas
- MACD Sample: Um Guia Prático para o Expert Advisor no MetaTrader 5
- Baixe Todo o Histórico de Ticks de um Símbolo no MetaTrader 5
- Análise do The MasterMind 3 (Edição Campeonato) para MetaTrader 4
- MAMACD: Uma Análise do Sistema de Trading para MetaTrader 5
- MasterMind 2: O Robô de Trading para MetaTrader 4 que Você Precisa Conhecer