English Русский 中文 Deutsch 日本語
preview
Do iniciante ao especialista: criação de um EA animado para notícias em MQL5 (VI): Estratégia de trading pós-notícia

Do iniciante ao especialista: criação de um EA animado para notícias em MQL5 (VI): Estratégia de trading pós-notícia

MetaTrader 5Exemplos |
20 0
Clemence Benjamin
Clemence Benjamin

Conteúdo:


Introdução

A estratégia que examinamos no artigo anterior centrava-se no posicionamento de ordens pendentes pouco antes da divulgação de notícias importantes. O objetivo era extrair lucro das oscilações bruscas de preço que frequentemente seguem esse tipo de evento. Embora essa abordagem possa ser eficaz, existem cenários em que ela falha, como quando uma das ordens é acionada, mas não atinge o nível de take-profit e, no fim, aciona o stop-loss.

Felizmente, na nossa implementação anterior, incorporamos ao EA uma lógica de cancelamento automático da ordem pendente oposta quando uma ordem é acionada. Essa automação é decisiva, pois impede que ambas as ordens sejam ativadas durante um efeito serrote no mercado, o que, caso contrário, poderia resultar em prejuízo duplo. Ao usar a velocidade do algoritmo para tomar esse tipo de decisão em milissegundos, o EA oferece um nível de precisão praticamente impossível de alcançar manualmente.

No entanto, se o trader quiser evitar completamente esse risco, surge a necessidade de uma estratégia alternativa. Nesta discussão, vamos voltar nossa atenção para uma estratégia de trading após a publicação das notícias, isto é, operar depois de um evento de notícia importante, desenvolvida para complementar e expandir os recursos do EA "Manchetes de notícias".

Na próxima seção, examinaremos o plano de integração dessa estratégia e avaliaremos sua viabilidade por meio da análise de dados históricos dos gráficos e da implementação de uma lógica em tempo real.


Exploração do conceito da estratégia

Para nossos testes e nossa análise, planejamos usar dados históricos de gráficos para analisar o comportamento do mercado após eventos de notícias importantes, em particular a publicação dos dados da folha de pagamento não agrícola (NFP). Como os anúncios do NFP são divulgados regularmente em datas programadas, geralmente na primeira sexta-feira de cada mês, eles são fáceis de identificar e alinhar com datas conhecidas do calendário. Isso os torna ideais para estudar como o preço reage nos minutos e horas seguintes à divulgação das notícias.

Cruzando as datas do NFP no calendário econômico e observando gráficos detalhados em timeframes de um minuto associados a esses eventos, podemos obter insights valiosos sobre como diferentes instrumentos se comportam após a divulgação das notícias. Essa abordagem nos permite desenvolver e ajustar com precisão nossa ferramenta de trading 'Pós-impacto', que complementará a estratégia existente de ordens pendentes, oferecendo oportunidades de entrada assim que a volatilidade inicial se estabilizar e uma direção clara se formar.

Esse método de teste com dados históricos permite modelar e aprimorar a lógica de trading mesmo fora das condições de mercado em tempo real, tornando-se uma forma eficiente de validar nosso framework de execução pós-notícias e antes da implementação final. Mais detalhes são apresentados abaixo.

Análise do histórico do movimento do preço usando um EA personalizado

Nesta seção, desenvolveremos um EA em MQL5 que permite "viajar no tempo" pelos dados históricos do gráfico usando o testador de estratégias do MetaTrader 5. O objetivo é observar manualmente a variação dos preços logo após eventos econômicos de grande impacto, em particular depois da publicação dos dados da folha de pagamento não agrícola dos EUA (NFP), e reunir insights valiosos para desenvolver nossa estratégia de trading "pós-impacto".

Esta etapa oferece uma oportunidade de aprendizado prático para aprofundar nossa compreensão da programação em MQL5, além de entender melhor o funcionamento do testador de estratégias. Ao nos concentrarmos em eventos históricos específicos, podemos simular condições reais de mercado e analisar o comportamento do preço nos momentos posteriores a notícias importantes.

O conhecimento e as observações obtidos nesta etapa de testes nos ajudarão a confirmar nossas hipóteses de trading antes de avançarmos para a implementação final. Em última análise, isso serve de base para integrar a lógica de trading "pós-impacto" aprimorada ao EA principal "Manchetes de notícias", permitindo que ele se prepare para o evento de notícia e, depois, atue de forma inteligente.

O relatório da folha de pagamento não agrícola dos EUA (NFP) é um dos relatórios econômicos mais importantes para os mercados financeiros, especialmente para pares de moedas que incluem o dólar dos EUA (USD). Sua divulgação normalmente provoca oscilações de preço imediatas e muitas vezes bruscas, o que o torna um candidato ideal para estratégias de trading tanto antes quanto depois da divulgação das notícias. Para testes e desenvolvimento da estratégia, os instrumentos mais adequados são os pares principais com USD, como EURUSD, GBPUSD, USDJPY e USDCHF, pois eles reagem de forma mais consistente e significativa às publicações do NFP. Isso os torna ambientes de teste ideais para algoritmos voltados a explorar padrões de volatilidade associados às principais notícias econômicas.

Antes de entrar na lógica completa e na funcionalidade do EA NFP_Event_Replay.mq5, é importante entender como começar a programar uma ferramenta desse tipo. No MetaTrader 5, inicie o MetaEditor, acesse o menu File/New/Expert Advisor... (template) e especifique um nome, por exemplo, NFP_Event_Replay. Isso criará uma estrutura básica com as funções OnInit(), OnDeinit() e OnTick(). A partir daí, você pode começar a estruturar sua lógica, começando pela verificação do horário, pela identificação do dia de divulgação do evento e pelos recursos de desenho, transformando gradualmente esse esqueleto em um indicador plenamente funcional de eventos históricos, que examinaremos nas próximas seções.

Neste artigo, examinaremos cada parte do EA, ajudando desenvolvedores iniciantes e de nível intermediário em MQL5 a entender como exibir programaticamente eventos NFP passados em gráficos históricos usando retângulos, lógica baseada em tempo e cálculos com ajuste de fuso horário, uma forma poderosa de estudar visualmente e refinar estratégias de trading pós-notícias.

1. Metadados e dados de entrada do usuário

No início do EA, os metadados descrevem o autor, a versão e o propósito do EA. A principal característica dessa ferramenta é que ela ajuda os traders a reproduzir visualmente e estudar o comportamento do mercado em torno do NFP (relatório da folha de pagamento não agrícola) no testador de estratégias do MetaTrader 5. Dois parâmetros do usuário, MinutesBefore e MinutesAfter, permitem que o trader defina o tamanho da janela (em minutos) antes e depois do evento, dentro da qual a variação do preço será exibida. Isso permite ajustar os parâmetros de acordo com a intensidade da variação do preço associada ao evento de notícia que você deseja estudar.

input int MinutesBefore = 5;
input int MinutesAfter = 5;

2. Variáveis globais e inicialização

As variáveis globais são declaradas para gerenciar o nome do retângulo, acompanhar o ano e o mês atuais em que o desenho foi criado pela última vez e impedir alertas repetidos. Isso ajuda a controlar o fluxo de execução, garantindo que os retângulos não sejam desenhados novamente no mesmo dia e que a rotina de limpeza seja executada corretamente durante a inicialização e a desinicialização.

string rectName = "NFP_Event_Window";
int drawnYear = 0, drawnMonth = 0;
bool alertShown = false;

3. Cálculo da primeira sexta-feira

Um dos elementos principais da lógica é determinar a data da primeira sexta-feira de cada mês. Isso é importante porque o relatório NFP é publicado nessa data. O EA usa cálculos de calendário para determinar dinamicamente essa data com base no ano e no mês atuais, o que permite reutilizar o EA nos anos seguintes sem alterações.

//+------------------------------------------------------------------+
//| Calculate day of first Friday                                    |
//+------------------------------------------------------------------+
int GetFirstFriday(int year, int month)
{
    MqlDateTime dt = {0};
    dt.year = year;
    dt.mon = month;
    dt.day = 1;
    datetime first = StructToTime(dt);
    TimeToStruct(first, dt);
    
    // Calculate days to first Friday (5 = Friday)
    int daysToAdd = (5 - dt.day_of_week + 7) % 7;
    return 1 + daysToAdd;
}

4. Verificação IsFirstFriday

Esta função verifica se o valor datetime em processamento corresponde à primeira sexta-feira do mês. Ela se baseia na lógica descrita anteriormente para a primeira sexta-feira e compara o dia atual e o dia da semana para determinar se a data corresponde à condição. Essa verificação serve como filtro para evitar cálculos desnecessários ou o desenho de retângulos em dias não relacionados ao NFP.

//+------------------------------------------------------------------+
//| Check if date is first Friday                                    |
//+------------------------------------------------------------------+
bool IsFirstFriday(datetime time)
{
    MqlDateTime dt;
    TimeToStruct(time, dt);
    int firstFriday = GetFirstFriday(dt.year, dt.mon);
    return (dt.day_of_week == 5 && dt.day == firstFriday);
}

5. GetTimeGMTOffset

Esta função determina o deslocamento do horário local da corretora em relação ao GMT (UTC) com base no horário do servidor. Como os eventos NFP são anunciados no horário do Leste dos EUA, que pode ser UTC-4 ou UTC-5 dependendo do horário de verão, esse deslocamento é necessário para converter corretamente o timestamp do evento de acordo com o fuso horário da corretora e o horário no gráfico.

//+------------------------------------------------------------------+
//| Get UTC offset for a specific time                               |
//+------------------------------------------------------------------+
int GetTimeGMTOffset(datetime time)
{
    MqlDateTime dt;
    TimeToStruct(time, dt);
    datetime timeUTC = StructToTime(dt);
    return (int)(time - timeUTC);
}

6. Inicialização e rotina de limpeza do EA

Quando o EA é inicializado (OnInit), ele configura um timer de 1 segundo, que dispara uma verificação contínua se estamos na data correspondente ao NFP. Na desinicialização (OnDeinit), ele interrompe o timer e remove o objeto retangular, caso ele tenha sido desenhado. Isso garante que as sessões de teste comecem limpas e que não restem objetos gráficos residuais no gráfico.

//+------------------------------------------------------------------+
//| Program entry point                                              |
//+------------------------------------------------------------------+
int OnInit()
{
    EventSetTimer(1);
    return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Cleanup on exit                                                  |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
    EventKillTimer();
    ObjectDelete(0, rectName);
}

7. OnTimer: o coração do EA

A função OnTimer é o principal bloco executor, chamado pelo timer a cada segundo. Isso evita processamento excessivo verificando alterações no tempo atual do gráfico. Se o dia for uma primeira sexta-feira válida, ela calcula o timestamp de divulgação do NFP para o ano e o mês atuais, aplica qualquer ajuste de fuso horário necessário e, em seguida, verifica se o horário atual cai dentro da janela temporal definida pelo usuário. Se as condições forem atendidas e o retângulo do mês atual ainda não tiver sido criado, ela desenha o retângulo do evento. Além disso, para maior clareza durante os testes, são exibidas mensagens de depuração. Fora dos dias de publicação do NFP, o EA redefine as variáveis de acompanhamento e remove todos os objetos gráficos existentes.

//+------------------------------------------------------------------+
//| Timer handler - main logic                                       |
//+------------------------------------------------------------------+
void OnTimer()
{
    static datetime lastBarTime = 0;
    datetime now = TimeCurrent();
    
    if(now == lastBarTime) return;
    lastBarTime = now;
    
    MqlDateTime dtNow;
    TimeToStruct(now, dtNow);
    
    // Process only on first Fridays
    if(IsFirstFriday(now))
    {
        // Show alert once per day
        if(!alertShown)
        {
            Alert("NFP Day: Set tester replay speed to 70%");
            alertShown = true;
        }
        
        // Calculate exact NFP release time in UTC
        int releaseDay = GetFirstFriday(dtNow.year, dtNow.mon);
        datetime nfpUTC = GetNFPTimestamp(dtNow.year, dtNow.mon, releaseDay);
        
        // Convert to broker time (Zimbabwe CAT = UTC+2)
        int offset = GetTimeGMTOffset(now);
        datetime nfpBroker = nfpUTC + offset;
        
        // Calculate rectangle boundaries
        datetime startTime = nfpBroker - MinutesBefore*60;
        datetime endTime = nfpBroker + MinutesAfter*60;
        
        // Draw rectangle if in time window
        if(now >= startTime && now <= endTime)
        {
            if(drawnYear != dtNow.year || drawnMonth != dtNow.mon)
            {
                DrawEventWindow(startTime, endTime);
                drawnYear = dtNow.year;
                drawnMonth = dtNow.mon;
                
                // Debug output
                Print("NFP UTC Time: ", TimeToString(nfpUTC, TIME_MINUTES|TIME_SECONDS));
                Print("Broker Time: ", TimeToString(now, TIME_MINUTES|TIME_SECONDS));
                Print("NFP Broker Time: ", TimeToString(nfpBroker, TIME_MINUTES|TIME_SECONDS));
                Print("Event Window: ", TimeToString(startTime), " to ", TimeToString(endTime));
            }
        }
    }
    else
    {
        alertShown = false;
        if(drawnYear != 0 || drawnMonth != 0)
        {
            ObjectDelete(0, rectName);
            drawnYear = 0;
            drawnMonth = 0;
        }
    }
}

8. GetNFPTimestamp: NFP às 8:30 no horário do Leste

Esta função cria o timestamp UTC exato para a divulgação do NFP. Ela usa as regras do horário de verão dos EUA para determinar se o horário de divulgação deve ser considerado como 12:30 UTC (no verão) ou 13:30 UTC (no inverno). Esse timestamp preciso é necessário para sincronizar a janela do gráfico com o horário real do evento.

//+------------------------------------------------------------------+
//| Create precise UTC timestamp for NFP event                       |
//+------------------------------------------------------------------+
datetime GetNFPTimestamp(int year, int month, int day)
{
    MqlDateTime dt = {0};
    dt.year = year;
    dt.mon = month;
    dt.day = day;
    
    // Determine correct UTC hour based on US daylight saving
    // US Eastern Time: EST = UTC-5 (winter), EDT = UTC-4 (summer)
    // NFP always releases at 8:30 AM US Eastern Time
    bool isDst = IsUSDST(StructToTime(dt));
    dt.hour = isDst ? 12 : 13;  // 12:30 UTC (summer) or 13:30 UTC (winter)
    dt.min = 30;
    
    return StructToTime(dt);
}

9. Lógica do horário de verão

Para levar em conta as mudanças do horário de verão nos EUA (DST), esta função calcula se determinada data está dentro do período de horário de verão. Segundo a legislação dos EUA, o horário de verão começa no segundo domingo de março e termina no primeiro domingo de novembro. Ao calcular os limites de cada ano e comparar a data com esses limites, o EA adapta dinamicamente seus cálculos de timestamp ao longo de todo o ano.

//+------------------------------------------------------------------+
//| Check if US is in daylight saving time                           |
//+------------------------------------------------------------------+
bool IsUSDST(datetime time)
{
    MqlDateTime dt;
    TimeToStruct(time, dt);
    
    // US DST rules (since 2007):
    // Starts: Second Sunday in March at 2:00 AM
    // Ends: First Sunday in November at 2:00 AM
    
    // Calculate DST start
    datetime dstStart = GetNthDayOfMonth(dt.year, 3, 0, 2) + (2 * 3600);  // Second Sunday in March at 2:00 AM
    // Calculate DST end
    datetime dstEnd = GetNthDayOfMonth(dt.year, 11, 0, 1) + (2 * 3600);    // First Sunday in November at 2:00 AM
    
    return (time >= dstStart && time < dstEnd);
}

10. GetNthDayOfMonth

Esta função utilitária encontra a n-ésima ocorrência de um determinado dia da semana em um mês específico. Por exemplo, ela pode retornar o segundo domingo de março ou o primeiro domingo de novembro, usados para determinar os pontos de transição do horário de verão. Essa função torna o EA robusto e compatível com anos futuros, permitindo que ele se adapte automaticamente ao longo de vários anos sem exigir atualizações.

//+------------------------------------------------------------------+
//| Get nth day of week in a month                                   |
//+------------------------------------------------------------------+
datetime GetNthDayOfMonth(int year, int month, int dayOfWeek, int nth)
{
    MqlDateTime dtFirst = {0};
    dtFirst.year = year;
    dtFirst.mon = month;
    dtFirst.day = 1;
    datetime first = StructToTime(dtFirst);
    
    MqlDateTime dt;
    TimeToStruct(first, dt);
    int firstDayOfWeek = dt.day_of_week;
    
    // Calculate days to the first occurrence
    int daysToAdd = (dayOfWeek - firstDayOfWeek + 7) % 7;
    datetime firstOccurrence = first + daysToAdd * 86400;
    
    // Add weeks for nth occurrence
    if(nth > 1)
    {
        firstOccurrence += (nth - 1) * 7 * 86400;
    }
    
    // Verify if still in same month
    TimeToStruct(firstOccurrence, dt);
    if(dt.mon != month)
    {
        // Adjust to last occurrence in month
        firstOccurrence -= 7 * 86400;
    }
    
    return firstOccurrence;
}

11. Desenho do retângulo no gráfico

Assim que a janela temporal correta do NFP é determinada, o EA cria um retângulo que cobre esse período. O retângulo abrange todo o intervalo de preços visível e é configurado com propriedades visuais distintas, como bordas pontilhadas e fundo preenchido em azul-claro. Se o retângulo já existir desde uma execução anterior, ele é removido primeiro para evitar sobreposição ou duplicação.

//+------------------------------------------------------------------+
//| Draw the NFP event window on chart                               |
//+------------------------------------------------------------------+
void DrawEventWindow(datetime start, datetime end)
{
    ObjectDelete(0, rectName);
    
    double high = ChartGetDouble(0, CHART_PRICE_MAX);
    double low = ChartGetDouble(0, CHART_PRICE_MIN);
    
    if(ObjectCreate(0, rectName, OBJ_RECTANGLE, 0, start, high, end, low))
    {
        ObjectSetInteger(0, rectName, OBJPROP_COLOR, clrDodgerBlue);
        ObjectSetInteger(0, rectName, OBJPROP_STYLE, STYLE_DASHDOT);
        ObjectSetInteger(0, rectName, OBJPROP_WIDTH, 2);
        ObjectSetInteger(0, rectName, OBJPROP_BACK, true);
        ObjectSetInteger(0, rectName, OBJPROP_FILL, true);
        ObjectSetInteger(0, rectName, OBJPROP_BGCOLOR, C'240,248,255'); // AliceBlue
    }
}

12. OnTick (placeholder)

Embora o EA tenha sido projetado para operar com eventos temporais, e não com ticks de preço, uma função OnTick vazia ainda é incluída por questões de completude e compatibilidade. Nesta implementação, ela não tem nenhum efeito prático, mas é exigida pela estrutura do EA do MetaTrader.

Teste da reprodução NFP_Event

Depois de compilar com sucesso o EA plenamente funcional a partir das seções de código apresentadas acima, passamos a testar sua funcionalidade no modo de visualização do testador de estratégias do MetaTrader 5. Os resultados foram impressionantes: em cada dia determinado de divulgação do NFP, o EA destacava com precisão a janela do evento com um retângulo na cor clrAliceBlue. Esse marcador visual nos permitiu identificar facilmente a dinâmica do preço durante o período da divulgação do NFP. Em particular, o segmento de reprodução de junho de 2024 a dezembro de 2024 ilustra claramente o surto típico de volatilidade associado ao NFP, confirmando que o EA identifica e marca corretamente a janela do evento. Abaixo dos resultados, reuni algumas das capturas de gráficos registradas, que agora serão analisadas para desenvolver uma estratégia robusta de trading 'Pós-impacto', baseada no comportamento do preço após a divulgação do NFP.

Strategy Tester-NFP_ Event_Replay.ex5

Strategy Tester-NFP_ Event_Replay.ex5

Log do testador:

2025.07.17 19:20:59.343 USDJPY.0: symbol to be synchronized
2025.07.17 19:20:59.346 USDJPY.0: symbol synchronized, 3960 bytes of symbol info received
2025.07.17 19:20:59.347 USDJPY.0: history synchronization started
2025.07.17 19:20:59.514 USDJPY.0: load 31 bytes of history data to synchronize in 0:00:00.013
2025.07.17 19:20:59.514 USDJPY.0: history synchronized from 2024.05.26 to 2025.07.20
2025.07.17 19:20:59.547 USDJPY.0: start time changed to 2024.05.27 00:00 to provide data at beginning
2025.07.17 19:20:59.548 USDJPY.0,M1: history cache allocated for 224402 bars and contains 173 bars from 2024.05.26 21:05 to 2024.05.26 23:59
2025.07.17 19:20:59.548 USDJPY.0,M1: history begins from 2024.05.26 21:05
2025.07.17 19:20:59.563 USDJPY.0,M1 (Deriv-Demo): every tick generating
2025.07.17 19:20:59.563 USDJPY.0,M1: testing of Experts\NFP_Event_Replay.ex5 from 2024.01.01 00:00 to 2024.12.31 00:00 started with inputs:
2025.07.17 19:20:59.563   MinutesBefore=5
2025.07.17 19:20:59.563   MinutesAfter=5
2025.07.17 19:29:59.082 2024.06.07 00:00:00   Alert: NFP Day: Set tester replay speed to 70%
2025.07.17 19:30:02.995 2024.06.07 12:25:00   NFP UTC Time: 12:30:00
2025.07.17 19:30:02.995 2024.06.07 12:25:00   Broker Time: 12:25:00
2025.07.17 19:30:02.995 2024.06.07 12:25:00   NFP Broker Time: 12:30:00
2025.07.17 19:30:02.995 2024.06.07 12:25:00   Event Window: 2024.06.07 12:25 to 2024.06.07 12:35
2025.07.17 19:30:41.055 2024.07.05 00:00:00   Alert: NFP Day: Set tester replay speed to 70%
2025.07.17 19:30:41.717 2024.07.05 12:25:00   NFP UTC Time: 12:30:00
2025.07.17 19:30:41.717 2024.07.05 12:25:00   Broker Time: 12:25:00
2025.07.17 19:30:41.717 2024.07.05 12:25:00   NFP Broker Time: 12:30:00
2025.07.17 19:30:41.717 2024.07.05 12:25:00   Event Window: 2024.07.05 12:25 to 2024.07.05 12:35
2025.07.17 19:30:55.060 2024.08.02 00:00:00   Alert: NFP Day: Set tester replay speed to 70%
2025.07.17 19:30:55.551 2024.08.02 12:25:00   NFP UTC Time: 12:30:00
2025.07.17 19:30:55.551 2024.08.02 12:25:00   Broker Time: 12:25:00
2025.07.17 19:30:55.551 2024.08.02 12:25:00   NFP Broker Time: 12:30:00
2025.07.17 19:30:55.551 2024.08.02 12:25:00   Event Window: 2024.08.02 12:25 to 2024.08.02 12:35
2025.07.17 19:31:15.547 2024.09.06 00:00:00   Alert: NFP Day: Set tester replay speed to 70%
2025.07.17 19:31:16.250 2024.09.06 12:25:00   NFP UTC Time: 12:30:00
2025.07.17 19:31:16.250 2024.09.06 12:25:00   Broker Time: 12:25:00
2025.07.17 19:31:16.250 2024.09.06 12:25:00   NFP Broker Time: 12:30:00
2025.07.17 19:31:16.250 2024.09.06 12:25:00   Event Window: 2024.09.06 12:25 to 2024.09.06 12:35
2025.07.17 19:31:30.214 2024.10.04 00:00:00   Alert: NFP Day: Set tester replay speed to 70%
2025.07.17 19:31:30.699 2024.10.04 12:25:00   NFP UTC Time: 12:30:00
2025.07.17 19:31:30.699 2024.10.04 12:25:00   Broker Time: 12:25:00
2025.07.17 19:31:30.699 2024.10.04 12:25:00   NFP Broker Time: 12:30:00
2025.07.17 19:31:30.699 2024.10.04 12:25:00   Event Window: 2024.10.04 12:25 to 2024.10.04 12:35
2025.07.17 21:23:38.212 2024.11.01 00:00:00   Alert: NFP Day: Set tester replay speed to 70%
2025.07.17 21:23:38.448 2024.11.01 12:25:00   NFP UTC Time: 12:30:00
2025.07.17 21:23:38.448 2024.11.01 12:25:00   Broker Time: 12:25:00
2025.07.17 21:23:38.448 2024.11.01 12:25:00   NFP Broker Time: 12:30:00
2025.07.17 21:23:38.448 2024.11.01 12:25:00   Event Window: 2024.11.01 12:25 to 2024.11.01 12:35
2025.07.17 21:23:47.754 2024.12.06 00:00:00   Alert: NFP Day: Set tester replay speed to 70%
2025.07.17 21:23:47.940 2024.12.06 13:25:00   NFP UTC Time: 13:30:00
2025.07.17 21:23:47.940 2024.12.06 13:25:00   Broker Time: 13:25:00
2025.07.17 21:23:47.940 2024.12.06 13:25:00   NFP Broker Time: 13:30:00
2025.07.17 21:23:47.940 2024.12.06 13:25:00   Event Window: 2024.12.06 13:25 to 2024.12.06 13:35

Análise pós-impacto dos eventos NFP

O EA nos ajudou a identificar com precisão os dias de NFP com base na nossa lógica configurada. Embora a reprodução animada anterior oferecesse uma visão geral rápida, ela não era ideal para estudar cuidadosamente os detalhes finos do movimento do preço, devido à alta velocidade de reprodução. Para resolver esse problema, reuni abaixo uma série de imagens estáticas, permitindo uma análise mais focada e detalhada. Essas capturas oferecem uma visão mais clara da reação do mercado na janela em torno do evento NFP, facilitando a identificação de padrões recorrentes e o levantamento de ideias de estratégias viáveis para aproveitar os movimentos pós-impacto. Veja as imagens e leia minhas observações abaixo das imagens.

NFP junho de 2024

NFP junho de 2024

NFP julho de 2024

NFP julho de 2024

NFP agosto de 2024

NFP agosto de 2024

NFP setembro de 2024

NFP setembro de 2024

NFP outubro de 2024

NFP outubro de 2024

NFP novembro de 2024

NFP novembro de 2024

NFP dezembro de 2024

NFP dezembro de 2024

O conjunto de imagens acima oferece uma representação visual clara da dinâmica do preço antes, durante e depois da divulgação do NFP. Essas capturas mostram como os mercados reagem a eventos importantes desse tipo. Acredito que, com a integração de machine learning e uma análise mais profunda dos dados históricos de notícias importantes, podemos identificar muitos padrões ocultos e oportunidades de trading. A partir dos resultados obtidos no segundo semestre de 2024, é possível tirar uma conclusão essencial: quando duas ou mais velas japonesas acompanharam o salto inicial na mesma direção, o preço frequentemente manteve esse impulso. No entanto, nos casos em que essa confirmação não ocorreu, o mercado não conseguiu sustentar o movimento, muitas vezes revertendo ou entrando em consolidação.

Bons exemplos desse comportamento podem ser vistos nos eventos NFP de junho, outubro e dezembro. Em junho e outubro, o forte movimento direcional continuou por vários minutos após o salto inicial, confirmando o impulso e criando potenciais oportunidades de entrada. Em contraste, o evento de julho apresentou volatilidade inicial, mas não teve continuidade, resultando em um movimento irregular ou sem continuidade bem-sucedida, uma distinção importante ao desenvolver estratégias de trading 'Pós-impacto'.

Plano da estratégia

Quando ocorre um evento econômico importante, ele costuma provocar um movimento brusco de alta ou de baixa em poucos ticks. Em alguns casos, o mercado pode testar rapidamente as duas direções, para cima e para baixo, antes de se estabilizar, o que pode levar a stop-outs prematuros ou ao acionamento involuntário de ordens. Para evitar os riscos associados a essa volatilidade inicial, esta estratégia se concentra em abrir operações logo após o salto brusco, quando o mercado mostra uma direção mais clara. A entrada depende da confirmação de condições formadas após o evento, e não da antecipação do próprio movimento. Abaixo, descrevemos tanto o setup de alta quanto o setup de baixa baseados nessa abordagem "Pós-impacto".

Setup de alta

Após um salto de alta provocado por um evento de notícia importante, nossa estratégia exige que, antes de abrir uma posição longa, duas velas consecutivas de alta se formem como confirmação. Assim que essas velas de confirmação surgem, abrimos uma operação de compra. A faixa de preço coberta pelas duas velas define nossa zona de risco, que passa a servir de base para posicionar o stop-loss. O nível de take-profit deve oferecer uma recompensa superior ao risco, mantendo uma relação recompensa-risco favorável. Em alguns cenários, esse setup também pode sinalizar o início de um forte impulso, oferecendo potencial para um lucro excepcionalmente alto caso o movimento seja capturado em uma fase inicial. A ilustração abaixo, extraída da visualização do testador de estratégias durante a reprodução do evento NFP, mostra o setup em ação.

Strategy on Bullish momentum setup

Strategy on Bullish momentum setup

Setup de baixa

O setup de baixa segue a mesma lógica da abordagem descrita no setup de alta acima. Abaixo está uma imagem que ilustra como esse padrão costuma aparecer.

Strategy on a Bearish Setup

Strategy on a Bearish Setup

O que fizemos acima foi exercitar o desenvolvimento de uma estratégia baseada na análise do movimento do preço. Usando os recursos do MQL5, criamos um EA único, capaz de reproduzir e demarcar eventos NFP, algo que seria tedioso, demorado e ineficiente fazer manualmente. Essa abordagem nos permitiu obter insights valiosos e ideias práticas, que agora podem ser convertidos em lógica de trading. Na próxima etapa, vamos nos concentrar na implementação da estratégia de trading, permitindo que o EA detecte esses setups e execute trades automaticamente. Essa nova lógica complementará a estratégia de ordens pendentes que examinamos anteriormente, criando uma ferramenta mais robusta e versátil para trading baseado em notícias.


Implementação final: integração da estratégia "Pós-impacto" ao EA "Manchetes de notícias"

Para tornar nosso EA "Manchetes de notícias" mais flexível e robusto, o próximo passo lógico é integrar as duas estratégias, a abordagem de ordens pendentes e a estratégia de confirmação "Pós-impacto", em um único sistema. Enquanto a estratégia de ordens pendentes busca capturar o surto inicial de volatilidade posicionando ordens imediatamente antes da divulgação das notícias, a estratégia baseada em confirmação permite que o EA reaja de forma inteligente depois que o mercado revelar sua direção.

Ao combinar os dois métodos, o EA pode operar tanto o rompimento imediato quanto o movimento de continuação que frequentemente vem em seguida. Esse sistema de abordagem dupla aumenta a flexibilidade e a probabilidade de obter resultados lucrativos, independentemente de as notícias provocarem um rompimento forte e inequívoco ou um whipsaw seguido por uma tendência mais definida. Nesta etapa do desenvolvimento, vamos integrar as duas estratégias à lógica do EA, permitindo que ele escolha, alterne ou até combine as duas, dependendo do perfil do evento ou das configurações do usuário.

Passemos aos próximos passos: dividiremos o código abaixo em seções, explicando cada uma em detalhes e mostrando exatamente como as linhas recentemente adicionadas se integram aos módulos existentes e à estratégia geral.

Etapa 1: configuração dos parâmetros de entrada "Pós-impacto"

No topo do EA, introduzimos um bloco especial de parâmetros de entrada que permite ao usuário ativar ou desativar a estratégia "Pós-impacto" e ajustar seu comportamento. Em MQL5, os parâmetros de entrada definem valores configuráveis antes da execução que os traders podem configurar na janela de propriedades do EA. Aqui, um flag booleano ativa ou desativa a função, enquanto as entradas numéricas indicam o intervalo de tempo em torno do evento (minutos antes e depois), a magnitude mínima do salto em pips, o número exigido de barras de confirmação, o buffer além da máxima ou mínima de controle e a relação recompensa-risco desejada. Esse design torna a estratégia fácil de configurar sem alterar o próprio código.

//--- POST-IMPACT STRATEGY INPUTS -------------------------------------
input bool   InpEnablePostImpact       = false;  // Enable post-impact market orders
input int    InpPostImpactBeforeMin    = 0;      // Minutes before event to start window
input int    InpPostImpactAfterMin     = 5;      // Minutes after event to end window
input double InpSpikeThresholdPipsPI   = 20.0;   // Minimum pip spike magnitude
input int    InpConfirmBarsPI          = 2;      // Number of confirming bars
input double InpBufferPipsPI           = 5.0;    // Buffer beyond reference high/low
input double InpRR_PIP                 = 2.0;    // Desired reward:risk ratio

Etapa 2: objetos e variáveis globais de estado

Para gerenciar o ciclo de vida da funcionalidade, declaramos várias variáveis globais. Flags como postImpactPlaced e postRectDrawn garantem que destaquemos a janela no gráfico e posicionemos a ordem a mercado apenas uma vez por evento. Atribuímos ao objeto retangular um identificador string exclusivo, para que ele possa ser criado, referenciado e removido de forma confiável. Além disso, criamos um objeto CTrade separado, que fornece ao EA métodos de trading integrados (Buy(), Sell() etc.) para o envio programático de ordens.

// Trade object & post-impact state
CTrade  trade;
bool    postImpactPlaced = false;          // Ensures only one post-impact trade
string  postRectName     = "PostImpact_Window";  // Unique object name
bool    postRectDrawn    = false;          // Ensures rectangle drawn once

Etapa 3: redefinição do estado em ReloadEvents()

Sempre que o EA atualiza a lista de eventos econômicos próximos, ele chama ReloadEvents(). Ao final dessa rotina, redefinimos todos os flags de estado da estratégia "Pós-impacto" e removemos todos os objetos retangulares existentes. Essa abordagem de estado limpo garante que cada novo evento seja tratado de forma independente, evitando artefatos residuais ou duplicação de operações associadas a eventos anteriores.

// Inside ReloadEvents(), after nextEventTime is computed:
ordersPlaced      = false;
postImpactPlaced  = false;
postRectDrawn     = false;
ObjectDelete(0, postRectName);  // Remove any old rectangle

Etapa 4: desenho da janela "Pós-impacto"

No manipulador principal do timer (OnTimer()), assim que o horário atual do servidor entra na janela temporal definida pelo usuário para um evento importante, desenhamos um retângulo semitransparente no gráfico. Extraímos do gráfico as máximas e mínimas visíveis do preço e, em seguida, usamos as funções de manipulação de objetos do MQL5 para criar e configurar o OBJ_RECTANGLE. O flag booleano garante que a criação desse retângulo ocorra apenas uma vez, tornando o evento visualmente perceptível sem redesenhar a cada tick.

// In OnTimer(), when now ∈ [evt - BeforeMin, evt + AfterMin]
if(!postRectDrawn && now >= winStart && now <= winEnd)
{
   double hi = ChartGetDouble(0, CHART_PRICE_MAX);
   double lo = ChartGetDouble(0, CHART_PRICE_MIN);
   ObjectCreate(0, postRectName, OBJ_RECTANGLE, 0, winStart, hi, winEnd, lo);
   ObjectSetInteger(0, postRectName, OBJPROP_COLOR, clrOrange);
   ObjectSetInteger(0, postRectName, OBJPROP_STYLE, STYLE_DASH);
   ObjectSetInteger(0, postRectName, OBJPROP_BACK,  true);
   ObjectSetInteger(0, postRectName, OBJPROP_FILL,  true);
   postRectDrawn = true;
}

Etapa 5: detecção de saltos bruscos de preço para posicionamento de ordens a mercado

Depois que a janela do evento se fecha, o EA encontra a barra de um minuto exata correspondente ao timestamp do evento. Ele calcula o salto de preço em pips comparando o preço de fechamento e o preço de abertura da barra, e verifica se esse salto ultrapassa o limiar definido pelo usuário. Se esse salto ultrapassar o limiar, o EA verifica o número de barras subsequentes definido pelo usuário para confirmar a direção (todas de alta ou todas de baixa). Após uma confirmação bem-sucedida, ele envia uma ordem a mercado na abertura da próxima barra, calculando os níveis de stop-loss e take-profit com base nas configurações de buffer do usuário e na relação recompensa-risco. Um último flag global impede mais de uma operação por evento.

// In OnTimer(), once now > winEnd and !postImpactPlaced
int barIdx = iBarShift(_Symbol, PERIOD_M1, evt, true);
if(barIdx >= 0)
{
   double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT), pip = point*10.0;
   double o = iOpen(_Symbol,PERIOD_M1,barIdx), c = iClose(_Symbol,PERIOD_M1,barIdx);
   double spike = (c - o)/pip;
   if(MathAbs(spike) >= InpSpikeThresholdPipsPI)
   {
      bool bullish = (c > o), ok = true;
      for(int i=1; i<=InpConfirmBarsPI; i++)
      {
         double oi = iOpen(_Symbol,PERIOD_M1,barIdx-i), ci = iClose(_Symbol,PERIOD_M1,barIdx-i);
         if(bullish ? (ci <= oi) : (ci >= oi)) { ok=false; break; }
      }
      if(ok)
      {
         int entryBar = barIdx - InpConfirmBarsPI - 1;
         double entry = iOpen(_Symbol,PERIOD_M1,entryBar);
         double refP  = bullish ? iLow(_Symbol,PERIOD_M1,barIdx-1)
                                : iHigh(_Symbol,PERIOD_M1,barIdx-1);
         double sl   = bullish ? refP - InpBufferPipsPI*pip : refP + InpBufferPipsPI*pip;
         double rr   = MathAbs(entry - sl);
         double tp   = bullish ? entry + rr*InpRR_PIP : entry - rr*InpRR_PIP;
         postImpactPlaced = true;
         trade.SetExpertMagicNumber(888888);
         trade.SetDeviationInPoints(5);
         if(bullish)
            trade.Buy(InpOrderVolume, _Symbol, entry, sl, tp, "PostImpact Buy");
         else
            trade.Sell(InpOrderVolume, _Symbol, entry, sl, tp, "PostImpact Sell");
      }
   }
}

O código-fonte totalmente integrado e compacto, incluindo todas as funções, é apresentado ao final deste artigo e está pronto para compilação. Agora podemos avançar para a seção de testes.


Testes

Não foi possível testar adequadamente a versão totalmente integrada do EA "Manchetes de notícias" no testador de estratégias, pois o testador não oferece suporte ao calendário e aos feeds de notícias em tempo real. O modo de reprodução com o EA integrado não gerava sinais significativos, por isso transferi a lógica de execução "Pós-impacto" para o EA dedicado NFP_Event_Replay. Usando o framework de reprodução, no qual o evento da folha de pagamento não agrícola é simulado com base em dados históricos, consegui verificar rapidamente o comportamento da estratégia na entrada, no stop-loss e no take-profit, sem precisar esperar por anúncios importantes em tempo real. A animação abaixo, extraída do testador de estratégias, demonstra que a lógica "Pós-impacto" funciona exatamente como planejado, em condições controladas e reproduzíveis. Confira a segunda versão do NFP_Event_Replay com a lógica de trading completa, apresentada ao final do artigo.

Post-impact strategy test result

Resultados dos testes da estratégia "Pós-impacto" para a divulgação do NFP na primeira sexta-feira de julho de 2024

New Headline EA with Post Impact Order Execution

EA "Manchetes de notícias" com execução de ordens "Pós-impacto"


Conclusão

Acabamos de concluir mais um estudo didático aprofundado: desta vez, integramos a estratégia de trading "Pós-impacto" ao nosso EA "Manchetes de notícias" e depois a validamos com o framework NFP_Event_Replay. Ao operar logo após a divulgação de notícias importantes, operamos em condições de entrada mais favoráveis: o surto inicial de volatilidade já passou, o preço se "estabilizou" e as barras de confirmação oferecem maior clareza sobre direção e força. Essa abordagem integra-se naturalmente com nossas outras táticas baseadas em notícias, tornando o EA mais versátil e confiável.

Além disso, os mesmos métodos que usamos aqui, detecção sistemática de eventos, filtros de salto baseados em pips, confirmação multibarra e controle da relação recompensa-risco, podem ser aprimorados com machine learning ou IA. Imagine um modelo que adapte seu limiar de salto ou suas regras de confirmação com base nas métricas históricas de sucesso para diferentes pares de moedas ou tipos de notícia. Temos bastante espaço para refinar cada função que criamos, seja visualização no gráfico, alertas ou envio automático de ordens. E, naturalmente, embora tenhamos nos concentrado no NFP para preservar a precisão da análise histórica e a velocidade nos testes no testador de estratégias, esta ferramenta continua útil também para o trading ao vivo do NFP.

Ficarei feliz em receber seus comentários! Compartilhe sua experiência, ideias ou perguntas nos comentários abaixo. Juntos, poderemos continuar simplificando o desenvolvimento em MQL5 e criando ferramentas algorítmicas cada vez mais robustas e voltadas ao trader.


Principais aprendizados

Lição Descrição
1. Trading "Pós-impacto" Operar logo após a divulgação de notícias importantes é perfeitamente possível e pode aumentar a probabilidade de sucesso quando se espera a volatilidade inicial diminuir.
2. Detecção de eventos baseada no tempo Uso das funções de data e hora do MQL5 para identificar programaticamente eventos específicos do calendário, como a primeira sexta-feira de cada mês (dia do NFP), e alinhar a lógica a agendas reais de divulgação.
3. Visualização no testador de estratégias Criação de elementos visuais, como retângulos e linhas, para demarcar janelas históricas durante o backtest, melhorando a avaliação manual da estratégia sem usar ferramentas externas.
4. Desenho dinâmico de objetos Uso de ObjectCreate() e ObjectSetInteger() para renderizar dinamicamente objetos gráficos com base em tempo e valores calculados, permitindo acompanhar eventos e obter feedback visual.
5. Funcionamento em tempo real versus modo de teste O uso de MQLInfoInteger(MQL_TESTER) permite distinguir entre o testador de estratégias e a execução em tempo real, possibilitando ajustar fluxos lógicos para ambientes de teste e execução real.
6. Gestão de trades com CTrade Integração da classe CTrade para envio seguro e estruturado de ordens, definição de stop-loss, take-profit e cancelamento de ordens em estratégias tanto "Pré-impacto" quanto "Pós-impacto".
7. Lógica de confirmação "Pós-impacto" Criação de entradas de trading adiadas com base na confirmação por velas após saltos fortes, uma alternativa mais segura e orientada por regras à execução imediata.
8. Configuração personalizada dos parâmetros de entrada O uso de variáveis de entrada permite que os usuários controlem quais estratégias estão ativas, quantos candles de confirmação são necessários e quais níveis de impacto dos eventos devem acionar a lógica.
9. Integração da API Calendar Uso das funções nativas de calendário do MQL5 (CalendarValueHistory, CalendarEventById etc.) para trabalhar com eventos econômicos próximos sem dependências de APIs externas.
10. Renderização de interface baseada em Canvas Uso da classe CCanvas para criar interfaces personalizadas com rolagem de notícias econômicas, indicadores técnicos e insights de mercado baseados em IA, exibidos diretamente no gráfico.
11. Desenvolvimento de uma estratégia híbrida A combinação de ordens pendentes "Pré-impacto" e operações reativas "Pós-impacto" em um único sistema do EA com condições de acionamento oferece flexibilidade e adaptabilidade a diferentes condições de mercado.

Conteúdo do anexo

Nome do arquivo Versão Descrição
NFP_Event_Replay.mq5 1.0 Ferramenta visual do testador de estratégias que destaca janelas de eventos NFP com retângulos com base na lógica histórica da primeira sexta-feira e do horário de verão dos EUA. Ajuda a analisar manualmente a reação dos preços durante eventos de notícias importantes.
News_Headline_EA.mq5 1.11 EA com calendário econômico em tempo real, rolagem de eventos, manchetes de notícias da Alpha Vantage, análises baseadas em IA e lógica de execução de dupla estratégia, tanto para ordens pendentes quanto para operações com confirmação "Pós-impacto". Inclui compatibilidade com o NFP replay durante os testes.
NFP_Event_Replay.mq5 1.01 Segunda versão do EA de reprodução do NFP, agora contendo a lógica completa de execução de ordens "Pós-impacto".

Para o conteúdo

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

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.
Desenvolvimento de um sistema personalizado de detecção do regime de mercado em MQL5 (Parte 2): Expert Advisor Desenvolvimento de um sistema personalizado de detecção do regime de mercado em MQL5 (Parte 2): Expert Advisor
Este artigo descreve em detalhes a criação de um EA adaptativo (MarketRegimeEA) usando o detector de regimes da Parte 1. Ele alterna automaticamente estratégias de negociação e parâmetros de risco para mercados de tendência, mercados laterais ou mercados voláteis. O artigo também inclui otimização prática, tratamento das transições e um indicador para vários timeframes.
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.
Do básico ao intermediário: Objetos e sub janelas (III) Do básico ao intermediário: Objetos e sub janelas (III)
Este artigo descreve um fluxo seguro para lidar com a remoção de objetos gráficos: interceptar eventos, recriar o objeto e recuperar suas propriedades mínimas. Mostramos como evitar armadilhas com ponteiros, prevenir recriações indevidas durante o encerramento e salvar posição/dimensões com atualização via DRAG/CHANGE. Assim, o indicador permanece íntegro e o usuário mantém parte das personalizações.