preview
Desenvolvendo uma Estratégia de Pullback: Validação

Desenvolvendo uma Estratégia de Pullback: Validação

MetaTrader 5Negociação |
34 0
Samuel De Souza Ferreira
Samuel De Souza Ferreira

“Robustez não é encontrar o melhor passe. É descobrir o que continua funcionando quando a amostra termina.”

Introdução

Uma estratégia pode apresentar ótimos resultados durante a otimização e, ainda assim, desaparecer assim que encontra dados que não participaram da escolha dos parâmetros. Portanto, a pergunta decisiva não é quanto o EA ganhou no melhor teste, mas sim: quanto da lógica permaneceu de pé quando o mercado mudou?

Este é o terceiro artigo da série sobre o desenvolvimento de uma estratégia de pullback. Após apresentar os fundamentos da ideia e transformar a lógica em um Expert Advisor no MetaTrader 5, chegamos à etapa mais exigente: investigar fragilidades, adicionar contexto somente quando necessário e medir a continuidade fora da amostra.

O objetivo não é encontrar uma combinação “perfeita” de médias, nem apresentar um conjunto pronto para operação real. A proposta é mostrar um processo de pesquisa: partir de um pullback simples, identificar onde ele falha, criar hipóteses com significado de mercado e exigir que cada nova camada prove sua utilidade por meio Walk-Forward Efficiency.


O caminho da investigação

Encontrar robustez não significa procurar a combinação mais lucrativa, mas submeter cada hipótese a um ciclo contínuo de medição, comparação e exclusão. Neste artigo, chamamos de bateria cada bloco controlado de testes que mantém a estrutura já validada e libera apenas uma família de variáveis por vez — como EMAs, slopes, limites mínimo e máximo de ATR, gatilho ou gestão. Para organizar essas baterias, utilizaremos o mt5_global_optimizer, apresentado no artigo MetaTrader 5 Global Optimizer: Uma Estrutura Profissional para Otimizar EAs por Grupos, Subgrupos e Critérios de Robustez, no qual são explicadas sua configuração, estrutura e utilização. A ferramenta permite separar os componentes, aplicar critérios de robustez e comparar os resultados antes de decidir se uma nova lógica deve ser mantida, retestada ou excluída. Um anexo também disponibilizará a estrutura adequada do EA em MQL5 para acompanhar esse processo.

Robustness Cycle

Figure 1 — The robustness cycle used to add, measure, and remove degrees of freedom.


1. Onde começa a busca pela robustez

A investigação começou exclusivamente no WIN$N. O objetivo inicial era avaliar uma ideia simples e conhecida: definir o regime em um timeframe maior, esperar uma retração em um timeframe menor e entrar quando o preço retomasse o movimento na direção do regime.

A configuração manual utilizada como ponto de partida possuía a seguinte estrutura:

Camada Papel no Experimento
Regime Timeframe superior e média de referência para limitar a direção.
Retração Timeframe inferior e média curta para identificar o retorno do preço.
Gatilho Retomada confirmada por distância normalizada pelo ATR.

Table 1 — Baseline pullback layers and their role in the experiment.

Em termos conceituais, o EA possuía três blocos:

  • Regime: Preço e EMA no M15 definiam a direção permitida.
  • Retração: O M1 indicava o retorno do preço em direção à EMA curta.
  • Retomada: Um candle fechado cruzava novamente a EMA e precisava terminar suficientemente afastado dela.

Essa estrutura era simples, compreensível e adequada como hipótese inicial. O problema é que simplicidade lógica não significa robustez estatística.


2. O primeiro WFE: quando a gestão sobrevive, mas o núcleo falha

O primeiro Walk-Forward Efficiency do WIN abrangeu o período de 1º de janeiro de 2021 até 31 de dezembro de 2024, utilizando janelas móveis com seis meses de ISS, três meses de OOS e avanço trimestral. Foram obtidas 13 janelas válidas com saldo inicial de R$ 10.000. Em cada uma delas, o melhor resultado do trecho ISS era selecionado e seus parâmetros eram aplicados, sem nova escolha, ao OOS seguinte.

Essa abordagem é diferente de otimizar todo o histórico e observar apenas a curva final. Cada janela obriga o modelo a tomar uma decisão usando somente o passado local e, depois, verifica quanto dessa decisão sobrevive no trecho seguinte.

Para facilitar esse processo, foi utilizada a estrutura apresentada no artigo MetaTrader 5 Global Optimizer II — Validação por Walk-Forward Efficiency, que integra a montagem das janelas, a seleção dos candidatos e a consolidação dos resultados ao fluxo de otimização do MetaTrader 5.

Os números iniciais foram reveladores:

Grupo Janelas Positivas Lucro OOS (R$) PF OOS Mediano WFE Consolidado (%)
Breakeven 7/13  6603 1,134 60,87
Trailing 10/13  7860 1,184 63,93
Stop inicial 9/13 7508 1,193 64,93
Gatilho ATR 7/13  5699 1,126 40,90
Par de EMAs 8/13  2737 1,026 18,81

Table 2 — Initial WFE diagnosis by strategy component.

O resultado mudou o rumo da investigação. Stop, trailing e breakeven preservavam alguma continuidade, mas o núcleo formado apenas pelos períodos das EMAs e o  gatilho ATR eram fracos, porém ainda positivos; por isso não deveriam ser descartados sem uma investigação adicional.

Essa diferença também revelou um risco metodológico importante: uma gestão eficiente pode esconder uma entrada frágil. Se avaliássemos apenas o resultado completo do EA, poderíamos concluir que a estratégia estava saudável. Ao separar os componentes, tornou-se evidente que parte importante da robustez vinha da forma de saída da posição, e não da qualidade estrutural da entrada. Após o primeiro WFE, a decisão foi: manter as hipóteses de pullback, rejeitar EMAs e os gatilhos isolados como descrição suficiente do regime e investigar o contexto antes de ampliar a gestão.

First Diagnosis

Figure 2 — In the first WFE, management components preserved efficiency while the EMA and ATR Trigger pair remained weak.


3. A EMA não estava errada — estava sem contexto

Situações visualmente muito diferentes podem produzir a mesma regra binária de preço acima ou abaixo da EMA:

  1. O preço está acima da média, mas a EMA permanece praticamente horizontal.
  2. O preço está acima da média após um movimento já excessivamente estendido.
  3. A EMA está inclinada e o preço mantém um afastamento moderado, caracterizando um regime mais organizado.
  4. A retração acontece alinhada ou contrária à inclinação da média curta.

Se todas essas situações recebem a mesma classificação, a EMA deixa de descrever o regime e passa a funcionar apenas como uma fronteira geométrica. A hipótese de desenvolvimento, portanto, não era procurar uma “EMA mágica”, mas fornecer contexto para que a média pudesse distinguir cenários de mercado diferentes.

Com base nesse diagnóstico, foram adicionados graus de liberdade com significado de mercado. O slope passou a medir a direção e a inclinação das EMAs, enquanto a distância do preço em relação à EMA de regime foi normalizada pelo ATR e delimitada por valores mínimo e máximo. O limite mínimo ajuda a evitar regiões indefinidas, nas quais o preço permanece excessivamente próximo da média, e o limite máximo procura impedir sinais após movimentos já muito estendidos.

Essas novas lógicas foram implementadas como filtros opcionais, permitindo que o processo de validação decidisse entre mantê-las ligadas, desligadas ou excluí-las. O objetivo passou a ser verificar se uma EMA contextualizada por inclinação e distância apresentaria maior continuidade fora da amostra do que o par de médias utilizado isoladamente.

3.1 Slope da EMA do regime

O slope mede o deslocamento da EMA do regime ao longo de determinado número de candles. Seu objetivo é verificar se a média apresenta inclinação coerente com a direção esperada. Dessa forma, a simples posição do preço acima ou abaixo de uma EMA praticamente horizontal deixa de ser suficiente para caracterizar um regime direcional.

No código, o cálculo utiliza somente candles fechados. O índice 1 representa o último candle concluído, enquanto 1 + N indica o valor da EMA observado N candles antes:

ΔEMA = EMA[1] − EMA[1 + N]

Legenda:

  • ΔEMA: Deslocamento da EMA durante o intervalo analisado.
  • EMA[1]: Valor da EMA no último candle fechado.
  • EMA[1 + N]: Valor da EMA observado N candles antes.
  • N: Quantidade de candles definida em regimeSlopeBars.

O deslocamento da EMA ainda está expresso na escala nominal do preço. Para relacioná-lo à volatilidade recente, o EA utiliza o ATR calculado no mesmo timeframe da EMA de regime. O parâmetro regimeSlopeMinAtr é multiplicado pelo ATR do último candle fechado:

SlopeRequerido = regimeSlopeMinAtr x ATR[1]

Legenda:

  • SlopeRequerido: Deslocamento mínimo exigido da EMA.
  • RegimeSlopeMinAtr: Fração mínima do ATR definida para o filtro.
  • ATR[1]: Valor do ATR no último candle fechado do timeframe de regime.

A seguir, é apresentado o trecho do EA responsável por calcular o deslocamento da EMA, transformar o limite em ATR para a escala de preço e validar o slope conforme a direção do regime:

//--- Validates the regime EMA slope using the regime ATR.
bool RegimeSlopeFilterIsValid(const bool isBuy)
  {
//--- Ignore the filter when it is disabled.
   if(!useRegimeSlopeFilter)
      return true;

//--- Compare the last closed EMA value with N candles before.
   int slopeShift = 1 + regimeSlopeBars;

   if(ArraySize(g_regimeEMA) <= slopeShift ||
      ArraySize(g_regimeATR) <= 1)
      return false;

//--- Use the ATR from the last closed regime candle.
   double atr = g_regimeATR[1];

   if(atr <= 0.0)
      return false;

//--- Calculate the EMA displacement.
   double slope =
      g_regimeEMA[1] - g_regimeEMA[slopeShift];

//--- Convert the ATR threshold into a price displacement.
   double requiredSlope =
      regimeSlopeMinAtr * atr;

//--- Validate the slope according to the regime direction.
   if(isBuy)
      return slope >= requiredSlope;

   return slope <= -requiredSlope;
  }

Em um regime comprador, a EMA precisa apresentar deslocamento positivo igual ou superior ao valor requerido:

ΔEMA >= SlopeRequerido

Em um regime vendedor, o deslocamento precisa ser negativo e alcançar a mesma magnitude no sentido oposto:

ΔEMA <= -SlopeRequerido

Legenda das condições:

  • ΔEMA: Deslocamento calculado da EMA.
  • SlopeRequerido: Deslocamento mínimo determinado pelo ATR.

Quando useRegimeSlopeFilter está desligado, a função retorna true e não acrescenta essa condição ao regime. Quando está ligado, a posição do preço em relação à EMA continua sendo necessária, mas a média também precisa demonstrar uma inclinação proporcional à volatilidade recente. Assim, o regime passa a considerar tanto a localização do preço quanto a direção apresentada pela EMA.

3.2 Slope da EMA de retração

A EMA de retração descreve o comportamento local do pullback no timeframe mais curto. Enquanto a EMA de regime identifica a direção predominante, a média curta ajuda a observar como o preço se movimenta durante a correção. Uma inclinação moderadamente contrária ao regime pode representar apenas uma retração normal, porém, quando esse deslocamento se torna excessivo, o movimento local pode estar perdendo sua característica de pullback e se aproximando de uma possível reversão.

No EA, o slope da retração é calculado com candles fechados e relacionado ao ATR do próprio timeframe de retração. O parâmetro retracementSlopeMinAtr define a inclinação mínima aceita e pode assumir valores negativos, permitindo certa tolerância ao movimento contrário. Para compras, o slope da EMA curta precisa permanecer acima do limite configurado; para vendas, abaixo do limite simétrico. Dessa forma, o filtro não obriga as duas EMAs a apontarem sempre na mesma direção, mas controlar quanto a média curta pode se inclinar contra o regime antes de invalidar o gatilho. O código no EA e a fórmula seguem o mesmo padrão do slope de regime; por isso, não será apresentado novamente.

3.3 Canal ATR de distância do preço à EMA

O slope informa se a EMA apresenta direção, mas não identifica se o preço está excessivamente próximo ou distante da média. Para acrescentar esse contexto, o EA calcula a distância entre o fechamento do último candle e a EMA de regime, utilizando o ATR do mesmo timeframe para estabelecer os limites mínimo e máximo.

A distância é calculada de acordo com a direção do regime:

Distância = Close[1] - EMA[1], Regime comprador

Distância = EMA[1] - Close[1], Regime vendedor

Legenda:

  • Distância: Afastamento do fechamento em relação à EMA.
  • Close[1]: Fechamento do último candle concluído.
  • EMA[1]: Valor da EMA de regime no mesmo candle.
  • Regime comprador: Calcula a distância do preço acima da EMA.
  • Regime vendedor: Calcula a distância do preço abaixo da EMA.

Os limites do canal são convertidos para a escala de preço por meio do ATR:

DistânciaMínima = regimePriceDistanceMinAtr x ATR[1]

DistânciaMáxima = regimePriceDistanceMaxAtr x ATR[1]

Legenda:

  • DistânciaMínima: Menor afastamento aceito.
  • DistânciaMáxima: Maior afastamento permitido.
  • RegimePriceDistanceMinAtr: Limite mínimo em unidades de ATR.
  • RegimePriceDistanceMaxAtr: Limite máximo em unidades de ATR.
  • ATR[1]: ATR do último candle fechado no timeframe de regime.

A seguir, é apresentada a função original do código responsável pela validação desse canal:

//+------------------------------------------------------------------+
//| Optional regime price distance filter normalized by regime ATR.  |
//+------------------------------------------------------------------+
bool RegimePriceDistanceFromEMAByATRIsValid(const bool isBuy)
  {
   if(!useRegimePriceDistanceFromEMAByATR)
      return true;

   if(ArraySize(g_regimeRates) <= 1 ||
      ArraySize(g_regimeEMA) <= 1 ||
      ArraySize(g_regimeATR) <= 1)
      return false;

   double atr = g_regimeATR[1];

   if(atr <= 0.0)
      return false;

   double close = g_regimeRates[1].close;
   double ema = g_regimeEMA[1];

   double distance =
      (isBuy ? close - ema : ema - close);

   double minDistance =
      regimePriceDistanceMinAtr * atr;

   double maxDistance =
      regimePriceDistanceMaxAtr * atr;

   bool valid = (distance >= minDistance);

   if(valid && regimePriceDistanceMaxAtr > 0.0)
      valid = (distance <= maxDistance);

   if(!valid)
      LogBlockedEventOncePerCandle(
         (isBuy
          ? "BUY_REGIME_PRICE_ATR_BLOCKED"
          : "SELL_REGIME_PRICE_ATR_BLOCKED"),
         StringFormat(
            "close=%.2f ema=%.2f atr=%.2f "
            "distance=%.2f min_atr=%.2f max_atr=%.2f",
            close,
            ema,
            atr,
            distance,
            regimePriceDistanceMinAtr,
            regimePriceDistanceMaxAtr
         )
      );

   return valid;

A função primeiro verifica se o filtro está habilitado e se os buffers possuem os dados necessários. Em seguida, recupera o fechamento, a EMA e o ATR do último candle concluído. A distância é calculada de forma simétrica para regimes compradores e vendedores.

A distância mínima é sempre aplicada quando o filtro está ativo:

Distância >= DistânciaMínima

O limite máximo somente é verificado quando regimePriceDistanceMaxAtr possui valor superior a zero:

Distância <= DistânciaMáxima

O limite mínimo evita que o regime seja validado quando o preço permanece praticamente encostado na EMA. O limite máximo impede a validação após um movimento excessivamente estendido. Quando regimePriceDistanceMaxAtr é igual a zero, apenas o teto do canal é desativado. A exigência de distância mínima continua ativa.

Se alguma condição não for atendida, o EA registra o bloqueio por meio de LogBlockedEventOncePerCandle. A função apenas valida o estado do filtro e não envia ordens.


4. Afrouxando o gatilho ATR: uma nova hipótese para validação

O gatilho original exigia que o candle de retomada cruzasse a EMA curta e terminasse, nesse mesmo fechamento, a uma distância mínima definida pelo ATR. A condição era objetiva, mas criava uma dependência temporal rígida: o cruzamento e o afastamento precisavam ocorrer exatamente no mesmo candle.

Em alguns movimentos, o preço cruzava a EMA e confirmava a retomada, mas somente alcançava a distância ATR necessária nos candles seguintes. Mesmo preservando a direção do regime e a estrutura do pullback, esses casos eram descartados porque as duas condições não aconteciam simultaneamente.

Para investigar essa possibilidade, o EA recebeu uma lógica opcional de afrouxamento por meio de uma janela ATR. Quando a retomada da EMA era identificada sem o afastamento mínimo, o estado podia permanecer armado durante uma quantidade configurável de candles do timeframe de retração.

O fluxo implementado no código pode ser representado da seguinte forma:

//+------------------------------------------------------------------+
//| Starts the relaxed ATR trigger window on the retracement TF.     |
//+------------------------------------------------------------------+
void ArmLooseATRTriggerWindow(const bool isBuy)
  {
//--- Store the opening time of the current retracement candle.
   datetime currentRetracementBar =
      iTime(_Symbol, g_retracementTimeframe, 0);

//--- Use the current server time if the candle time is unavailable.
   if(currentRetracementBar <= 0)
      currentRetracementBar = TimeCurrent();

//--- Store an independent window start for each direction.
   if(isBuy)
      g_buyLooseATRTriggerStartRetracementBar =
         currentRetracementBar;
   else
      g_sellLooseATRTriggerStartRetracementBar =
         currentRetracementBar;
  }

//+------------------------------------------------------------------+
//| Checks whether the relaxed ATR trigger window is active.         |
//+------------------------------------------------------------------+
bool LooseATRTriggerWindowActive(const bool isBuy)
  {
//--- Select the window start according to the setup direction.
   datetime start =
      (isBuy
       ? g_buyLooseATRTriggerStartRetracementBar
       : g_sellLooseATRTriggerStartRetracementBar);

//--- A disabled or unarmed window cannot be active.
   if(!useLooseATRTriggerWindow || start <= 0)
      return false;

//--- Count elapsed candles on the retracement timeframe.
   int shift =
      iBarShift(
         _Symbol,
         g_retracementTimeframe,
         start,
         false
      );

//--- Reject the state when the reference candle is unavailable.
   if(shift < 0)
      return false;

//--- Keep the window active while it remains inside the limit.
   return (
             shift <= looseATRTriggerWindowRetracementCandles
          );
  }

//+------------------------------------------------------------------+
//| Checks whether the relaxed ATR trigger window has expired.       |
//+------------------------------------------------------------------+
bool LooseATRTriggerWindowExpired(const bool isBuy)
  {
//--- Select the stored window start for the current direction.
   datetime start =
      (isBuy
       ? g_buyLooseATRTriggerStartRetracementBar
       : g_sellLooseATRTriggerStartRetracementBar);

//--- A disabled or unarmed window cannot expire.
   if(!useLooseATRTriggerWindow || start <= 0)
      return false;

//--- Locate the starting candle on the retracement timeframe.
   int shift =
      iBarShift(
         _Symbol,
         g_retracementTimeframe,
         start,
         false
      );

//--- Expire when the candle is unavailable or the limit is exceeded.
   return (
             shift < 0 ||
             shift > looseATRTriggerWindowRetracementCandles
          );
  }

//+------------------------------------------------------------------+
//| Expires the relaxed ATR trigger and waits for a fresh pullback.  |
//+------------------------------------------------------------------+
void ExpireLooseATRTriggerWindow(const bool isBuy)
  {
   if(isBuy)
     {
      //--- Clear the buy setup and require a new retracement cycle.
      ClearBuyRetracement();
      g_buyLooseATRExpiredWaitRetracementReset = true;
      return;
     }

//--- Clear the sell setup and require a new retracement cycle.
   ClearSellRetracement();
   g_sellLooseATRExpiredWaitRetracementReset = true;
  }

//+------------------------------------------------------------------+
//| Prevents immediate rearming after a relaxed ATR window expires.  |
//+------------------------------------------------------------------+
bool LooseATRExpiredWaitResetIsActive(const bool isBuy)
  {
   if(isBuy)
     {
      //--- No reset restriction is active for the buy setup.
      if(!g_buyLooseATRExpiredWaitRetracementReset)
         return false;

      //--- Keep waiting while the previous retracement still exists.
      if(BuyRetracementCandle())
         return true;

      //--- Allow a new window after the retracement condition resets.
      g_buyLooseATRExpiredWaitRetracementReset = false;
      return false;
     }

//--- No reset restriction is active for the sell setup.
   if(!g_sellLooseATRExpiredWaitRetracementReset)
      return false;

//--- Keep waiting while the previous retracement still exists.
   if(SellRetracementCandle())
      return true;

//--- Allow a new window after the retracement condition resets.
   g_sellLooseATRExpiredWaitRetracementReset = false;
   return false;
  }
  }

A janela utiliza candles do timeframe de retração. Seu início é associado ao candle em que a retomada ocorreu sem a distância necessária, enquanto o número de candles transcorridos determina se o estado permanece ativo ou deve expirar.

A estrutura também impede o rearme contínuo. Quando a janela expira, o estado da retração é limpo e o EA espera que a condição anterior deixe de existir. Somente após uma nova retração válida, o processo pode ser iniciado novamente.

A inclusão dessa lógica não representa sua aprovação antecipada. Ela transforma a rigidez temporal do gatilho em uma hipótese mensurável, que será avaliada nas baterias posteriores para verificar se o tempo adicional preserva confirmações válidas ou apenas amplia a quantidade de sinais.


5. Duas etapas da validação do WIN: exploração e consolidação

As duas baterias cumpriram funções complementares. A primeira foi exploratória: manteve janelas de seis meses de ISS para medir o efeito dos novos graus de liberdade. A segunda foi confirmatória: ampliou o ISS para 12 meses, devolveu os timeframes ao espaço de teste e procurou regiões paramétricas estáveis. Por fazerem parte do mesmo caminho de validação, elas são apresentadas juntas neste capítulo.

5.1 Bateria exploratória: adicionar contexto às EMAs

Com os novos graus de liberdade, o WIN foi novamente submetido a 13 janelas de seis meses de ISS e três meses de OOS. A seleção foi refeita com critério de saldo máximo.

Grupo Janelas Positivas PF OOS Mediano DD Máximo (%) WFE Consolidado (%) Lucro OOS (R$)
Breakeven 7/13 1,066 11,35 53,08 4805 
Canal/ Distância ATR do Regime 10/13 1,372 14,55 46,70 5342 
Trailing 9/13 1,173 9,58 60,15 6024 
Stop 9/13 1,271 8,70 66,50
6378 
Slope da Retração 7/13 1,002 10,55 41,95 4172 
Slope do Regime 10/13 1,213 10,46 67,20 7036 
Par de EMAs 8/13 1,073 12,32 42,86 5483
Gatilho ATR 7/13 1,126 13,01 40,90 5699 
Janela ATR Flexível 10/13 1,070 15,18 69,50 8380

Table 3 — Exploratory WIN battery after adding contextual degrees of freedom.

A segunda bateria mostra que os novos graus de liberdade acrescentaram contexto ao núcleo da estratégia. O avanço mais importante ocorreu no par de EMAs: o WFE passou de 18,81% para 42,86%, aumento de 24,05 pontos percentuais. O lucro OOS praticamente dobrou, de R$ 2.737 para R$ 5.483, enquanto o PF mediano subiu de 1,026 para 1,073. As janelas positivas permaneceram em 8/13, indicando melhora na qualidade e eficiência, mas não na distribuição temporal dos resultados.

Entre os novos filtros, o slope do regime apresentou a evidência mais equilibrada: WFE de 67,20%, 10/13 janelas positivas, PF de 1,213 e lucro OOS de R$ 7.036. O canal de distância ATR alcançou o maior PF mediano, 1,372, embora com WFE mais moderado e drawdown de 14,55%. Já o slope da retração apresentou benefício isolado limitado, com PF próximo da neutralidade.

EMA Context WFE

Figure 3 — WFE improved as contextual filters were added to the EMA structure.

A janela ATR flexível foi promissora em lucro e eficiência, alcançando WFE de 69,50% e R$ 8.380 no OOS. Entretanto, também apresentou o maior drawdown, 15,18%, e PF de apenas 1,070. Portanto, não deve ser escolhida somente pelo lucro ou WFE: sua permanência depende da estabilidade paramétrica e da validação nos períodos externos.

A gestão continuou relevante, mas não melhorou de maneira uniforme. O stop elevou seu WFE de 64,93% para 66,50% e o PF de 1,193 para 1,271. Breakeven e trailing perderam eficiência. O resultado central é que a segunda bateria reduziu a dependência exclusiva da gestão: slopes e limites ATR deram mais significado ao regime e fortaleceram o próprio núcleo das EMAs.

5.2 Bateria de consolidação: ampliar o ISS e procurar regiões

Na etapa final, cada janela passou a utilizar 12 meses de ISS, mantendo três meses de OOS e avanço trimestral. Foram analisadas 12 janelas. Os timeframes também voltaram ao espaço de teste e confirmaram a arquitetura M15/M1.

Grupo WFE (%) Janelas Positivas PF Mediano DD Máximo (%)  Lucro OOS (R$)
Timeframes 85,94 8/12 1,229 9,78 6729 
EMAs 74,37 9/12 1,103 9,54 7173
Gatilho ATR 54,84 9/12 1,211 17,08 6027 
Slope do Regime 72,49 9/12 1,120 9,44 6237 
Slope de Retração 66,27 7/12 1,270 10,45 5464 
Canal ATR do Regime 64,58 9/12 1,188 9,09 6007 
Janela ATR Flexível 58,45 8/12 1,046 17,22 5525 
Stop 51,82 7/12 1,148 13,90 4017 
Breakeven 58,89 6/12 1,049 11,35 4531
Trailing 53,86 7/12 1,095 9,78 4540 

Table 4 — Consolidation WIN battery using 12-month ISS windows.

As 12 rodadas da bateria final foram classificadas como fortes. Mais importante que o melhor passe, surgiu uma região de continuidade aproximadamente formada por:

  • Estabilidade da separação entre regime e retração.
  • Vizinhanças consistentes nos períodos das médias.
  • Faixa de ATR não dependente de um único valor.
  • Região coerente para stop, slopes e canal ATR.
  • Limites mínimo e máximo de distância avaliados em conjunto.

Essas faixas não devem ser tratadas como receita operacional. Seu valor está em mostrar que o comportamento não dependia de um único ponto. Quando configurações vizinhas permanecem aceitáveis, existe um platô paramétrico. Quando somente uma combinação se destaca e todas ao redor falham, existe um pico com maior risco de sobreajuste.


Conclusão: de uma ideia simples à validação

Esta série acompanhou a evolução completa de uma estratégia de pullback: dos fundamentos, passando pela construção do EA no MetaTrader 5, até a investigação de sua robustez fora da amostra.

O primeiro WFE mostrou que a gestão sobrevivia melhor que o núcleo das EMAs. A introdução de slope, canal ATR e afrouxamento controlado do gatilho permitiu testar novas hipóteses, mas também confirmou que adicionar complexidade nem sempre melhora a continuidade.

A principal contribuição não é um set definitivo, mas um método: adicionar graus de liberdade com significado, permitir que cada lógica seja desativada, procurar platôs paramétricos e exigir consistência em WFE.

Uma estratégia não se torna robusta por apresentar o maior lucro, mas por continuar reconhecível quando suas fragilidades são deliberadamente testadas.

É aí que termina a otimização, e começa a validação de verdade.

Próximos passos

A investigação avançará para uma WFA aninhada, com os seguintes objetivos:

  • analisar os clusters formados nos resultados ISS para selecionar os representantes destinados aos respectivos OOS;
  • identificar, ao final das janelas, quais regiões paramétricas e medoides apareceram com maior frequência;
  • montar e congelar poucos sets representativos para submetê-los a um teste final e intocado de robustez.
Nome Tipo Descrição
1 SimplePullback_WIN_GlobalOpt.mq5 Expert Advisor EA utilizado na validação inicial da estratégia.
2 OneEMA_LooseCore_GlobalOpt.mq5 Expert Advisor EA ampliado utilizado nas etapas de exploração e consolidação.
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.
Redes neurais em trading: Treinamento de modelos spiking profundos (SEW-ResNet) Redes neurais em trading: Treinamento de modelos spiking profundos (SEW-ResNet)
Convidamos você a conhecer o framework SEW-ResNet, que permite construir modelos spiking profundos sem problemas de degradação e com controle eficiente dos gradientes. Neste artigo, demonstramos como implementar um neurônio spiking básico e seus algoritmos com MQL5.
Está chegando o novo MetaTrader 5 e MQL5 Está chegando o novo MetaTrader 5 e MQL5
Esta é apenas uma breve resenha do MetaTrader 5. Eu não posso descrever todos os novos recursos do sistema por um período tão curto de tempo - os testes começaram em 09.09.2009. Esta é uma data simbólica, e tenho certeza que será um número de sorte. Alguns dias passaram-se desde que eu obtive a versão beta do terminal MetaTrader 5 e MQL5. Eu ainda não consegui testar todos os seus recursos, mas já estou impressionado.
Criação de um robô market-neutral probabilístico com base na distribuição dos retornos Criação de um robô market-neutral probabilístico com base na distribuição dos retornos
Uma estratégia de trading market-neutral baseada na distribuição empírica dos retornos oferece uma alternativa aos métodos clássicos de análise técnica, substituindo a previsão da direção do preço pelo posicionamento estatístico de ordens em níveis com determinada probabilidade de serem atingidos. O artigo analisa em detalhes o formalismo matemático usado no cálculo de percentis, os algoritmos de ponderação do volume das posições de acordo com a probabilidade de execução e os mecanismos de adaptação às mudanças nas condições de mercado por meio da expiração da grade. Também é apresentada uma implementação completa em MQL5.