Bug no Compilador (Build 4885)? Erro Falso '[' - invalid index value após sequência de CopyBuffer em M1

 

Ambiente:

  • MetaTrader 5 Build:4885
  • Sistema Operacional:Microsoft Windows Server 2025 Datacenter (10.0.26100 Build 26100)
  • (Observação: Erro também ocorre em outra máquina com a mesma build do MT5)

Descrição do Problema:

Ao desenvolver um Expert Advisor que opera baseado em dados de M1, encontrei um erro de compilação persistente e aparentemente incorreto: '[' - invalid index value .

O erro ocorre dentro de um bloco  if  que detecta uma nova barra M1. Dentro deste bloco, faço várias chamadas  CopyBuffer  para obter dados de indicadores (MAs, ATR) e do indicador  iVolumes .

O problema específico surge quando tento acessar ou calcular valores usando os dados copiados logo após a sequência de chamadas  CopyBuffer . A mensagem de erro "invalid index value" é reportada em linhas onde ou não há acesso a índice, ou o acesso deveria ser válido (pois a cópia foi checada). A linha exata reportada varia ligeiramente dependendo da estrutura do código, mas sempre ocorreapósas chamadas CopyBuffer eantes ou duranteo uso dos dados copiados.

O erro  NÃO ocorre se:

  1. Eu compilo um código mínimo que apenas faz as chamadas CopyBuffer sem usar os dados (Veja Código 1 abaixo).
  2. Eu removo as chamadas CopyBuffer relacionadas ao handle do iVolumes .

O erro OCORRE consistentemente quando:

  1. As chamadas  CopyBuffer  para MA, ATR e Volume são feitas em sequência.
  2. E, logo depois, tento acessar os arrays resultantes ou fazer cálculos com eles (Veja Código 2 abaixo).

Isso sugere fortemente um bug no parser ou no compilador da build 4885, que se confunde com essa sequência específica de operações, reportando um erro incorreto. A limpeza do código (copiar/colar via Bloco de Notas) e recompilação total ( Rebuild ) não resolveram o problema.

Código MRE - Passo 1 (Compila SEM ERROS):Este código inclui todas as chamadas CopyBuffer , mas não tenta usar os dados (exceto por um Print simples no final). Ele compila com sucesso.


//+------------------------------------------------------------------+
//| Expert Advisor: BugTestInvalidIndex_Step1_5                      |
//| Propósito:     MRE + Handles/Copy MA/ATR + Copy Vol              |
//|                (Compila OK)                                      |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>
#include <Math\Stat\Math.mqh> // Manter include

// --- Handles ---
int h_ma_fast = INVALID_HANDLE;
int h_ma_slow = INVALID_HANDLE;
int h_atr     = INVALID_HANDLE;
int h_vol     = INVALID_HANDLE;

// --- Globals ---
string g_symbol;
datetime lastBarTime_M1 = 0;
int g_digits = 0;
// <<<< Usando valor fixo para o teste MRE >>>>
int MA_Volume_Period = 100;


//+------------------------------------------------------------------+
int OnInit() {
    g_symbol = _Symbol;
    g_digits = (int)SymbolInfoInteger(g_symbol, SYMBOL_DIGITS);
    // Removido get/check de Point/TickSize para simplificar MRE
    if(g_digits < 0) { Print("Erro OnInit: Falha ao obter Digits"); return(INIT_FAILED); }

    int MA_Fast_Period = 9;
    int MA_Slow_Period = 20;
    int ATR_Period = 14;

    h_ma_fast = iMA(g_symbol, PERIOD_M1, MA_Fast_Period, 0, MODE_SMA, PRICE_CLOSE);
    h_ma_slow = iMA(g_symbol, PERIOD_M1, MA_Slow_Period, 0, MODE_SMA, PRICE_CLOSE);
    h_atr     = iATR(g_symbol, PERIOD_M1, ATR_Period);
    h_vol     = iVolumes(g_symbol, PERIOD_M1, VOLUME_TICK);

    if(h_ma_fast==INVALID_HANDLE || h_ma_slow==INVALID_HANDLE || h_atr==INVALID_HANDLE || h_vol==INVALID_HANDLE) {
       Print("MRE_Step1_5: Erro criar handles.");
       IndicatorRelease(h_ma_fast); IndicatorRelease(h_ma_slow); IndicatorRelease(h_atr); IndicatorRelease(h_vol);
       return(INIT_FAILED);
    }
    Print("MRE_Step1_5 Initialized.");
    return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
void OnDeinit(const int reason) {
   IndicatorRelease(h_ma_fast); IndicatorRelease(h_ma_slow);
   IndicatorRelease(h_atr); IndicatorRelease(h_vol);
   Print("MRE_Step1_5 Deinitialized. Reason: ", reason);
}
//+------------------------------------------------------------------+
void OnTick() {
   MqlRates bars_M1[3];
   if(CopyRates(g_symbol, PERIOD_M1, 0, 3, bars_M1) < 3) return;

   if(bars_M1[1].time != lastBarTime_M1) {
      lastBarTime_M1 = bars_M1[1].time;

      // --- 1. Coleta TODOS os dados ---
      bool data_ok = true; // Flag para checar se todas as cópias funcionaram
      double ma_fast_1[2], ma_slow_1[2], atr_1[2];
      double m1_volume_history[MA_Volume_Period]; // Array para histórico de volume MA (double)
      double vol_bar1_buffer[1];                  // Array p/ volume da barra 1 (double)

      // Copia MA/ATR (sabemos que isso funcionou no Step 1)
      if(CopyBuffer(h_ma_fast, 0, 1, 2, ma_fast_1) < 2) data_ok=false;
      if(data_ok && CopyBuffer(h_ma_slow, 0, 1, 2, ma_slow_1) < 2) data_ok=false;
      if(data_ok && CopyBuffer(h_atr, 0, 1, 2, atr_1) < 2 ) data_ok=false;

      // << ADDED BACK Volume CopyBuffer calls >>
      if(data_ok && CopyBuffer(h_vol, 0, 2, MA_Volume_Period, m1_volume_history) < MA_Volume_Period) data_ok=false; // Histórico Vol (shift 2)
      if(data_ok && CopyBuffer(h_vol, 0, 1, 1, vol_bar1_buffer) < 1) data_ok=false; // Vol da barra 1

      // Checa se TODAS as cópias foram ok
      if(!data_ok) {
         // Print("MRE_Step1_5: Erro ao copiar um ou mais buffers."); // Debug opcional
         return; // Sai se alguma cópia falhou
      }

      // Nenhuma atribuição ou cálculo aqui por enquanto, SÓ as cópias.
      Print("MRE_Step1_5: Copied all buffers successfully for bar ", TimeToString(lastBarTime_M1));


   } // Fim if(Nova Barra M1)
}
//+------------------------------------------------------------------+


Código MRE - Passo 2 (Falha na Compilação):Este código é idêntico ao Passo 1, mas com a adição das linhas de cálculo e atribuição de variáveisapóso bloco de CopyBuffer . Este código falha ao compilar.


//+------------------------------------------------------------------+
//| Expert Advisor: BugTestInvalidIndex_Step2                        |
//| Propósito:     MRE + Handles/Copy + Calcs/Assigns                |
//|                (FALHA ao Compilar)                               |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>
#include <Math\Stat\Math.mqh> // Necessário para MathMean

// --- Handles ---
int h_ma_fast = INVALID_HANDLE;
int h_ma_slow = INVALID_HANDLE;
int h_atr     = INVALID_HANDLE;
int h_vol     = INVALID_HANDLE;

// --- Globals ---
string g_symbol;
datetime lastBarTime_M1 = 0;
int g_digits = 0;
double point = 0;
// <<<< Usando valores fixos para o teste MRE >>>>
int    MA_Volume_Period = 100;
double MA_Volume_Multiplier = 2.0;
double DIV_THR = 0.6;


//+------------------------------------------------------------------+
int OnInit() {
    g_symbol = _Symbol;
    g_digits = (int)SymbolInfoInteger(g_symbol, SYMBOL_DIGITS);
    point    = SymbolInfoDouble(g_symbol, SYMBOL_POINT);
    if(g_digits < 0 || point <= 0) { Print("Erro OnInit: Falha ao obter Digits/Point"); return(INIT_FAILED); }

    int MA_Fast_Period = 9;
    int MA_Slow_Period = 20;
    int ATR_Period = 14;

    h_ma_fast = iMA(g_symbol, PERIOD_M1, MA_Fast_Period, 0, MODE_SMA, PRICE_CLOSE);
    h_ma_slow = iMA(g_symbol, PERIOD_M1, MA_Slow_Period, 0, MODE_SMA, PRICE_CLOSE);
    h_atr     = iATR(g_symbol, PERIOD_M1, ATR_Period);
    h_vol     = iVolumes(g_symbol, PERIOD_M1, VOLUME_TICK);

    if(h_ma_fast==INVALID_HANDLE || h_ma_slow==INVALID_HANDLE || h_atr==INVALID_HANDLE || h_vol==INVALID_HANDLE) {
       Print("MRE_Step2: Erro criar handles.");
       IndicatorRelease(h_ma_fast); IndicatorRelease(h_ma_slow); IndicatorRelease(h_atr); IndicatorRelease(h_vol);
       return(INIT_FAILED);
    }
    Print("MRE_Step2 Initialized.");
    return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
void OnDeinit(const int reason) {
   IndicatorRelease(h_ma_fast); IndicatorRelease(h_ma_slow);
   IndicatorRelease(h_atr); IndicatorRelease(h_vol);
   Print("MRE_Step2 Deinitialized. Reason: ", reason);
}
//+------------------------------------------------------------------+
void OnTick() {
   MqlRates bars_M1[3];
   if(CopyRates(g_symbol, PERIOD_M1, 0, 3, bars_M1) < 3) return;

   if(bars_M1[1].time != lastBarTime_M1) {
      lastBarTime_M1 = bars_M1[1].time;

      // --- 1. Coleta TODOS os dados ---
      bool data_ok = true;
      double ma_fast_1[2], ma_slow_1[2], atr_1[2];
      double m1_volume_history[MA_Volume_Period];
      double vol_bar1_buffer[1];

      if(CopyBuffer(h_ma_fast, 0, 1, 2, ma_fast_1) < 2) data_ok=false;
      if(data_ok && CopyBuffer(h_ma_slow, 0, 1, 2, ma_slow_1) < 2) data_ok=false;
      if(data_ok && CopyBuffer(h_atr, 0, 1, 2, atr_1) < 2 ) data_ok=false;
      if(data_ok && CopyBuffer(h_vol, 0, 2, MA_Volume_Period, m1_volume_history) < MA_Volume_Period) data_ok=false; // Histórico Vol (shift 2)
      if(data_ok && CopyBuffer(h_vol, 0, 1, 1, vol_bar1_buffer) < 1) data_ok=false; // Vol da barra 1

      // Linha ~67 - ONDE O ERRO É REPORTADO
      if(!data_ok) {
         // Print("MRE_Step2: Erro ao copiar um ou mais buffers.");
         return;
      }

      // =======================================================================
      // --- 2. ADICIONADO: Cálculos e atribuições (Gatilho do Erro) ---
      // =======================================================================
      double val_atr = atr_1[0];
      // Check ATR cedo
      if(val_atr <= point * 5) {
           return;
      }

      double val_ma_fast = ma_fast_1[0];
      double val_ma_slow = ma_slow_1[0];
      double val_volume_dbl = vol_bar1_buffer[0]; // << Linha suspeita original, mas erro é antes
      long   val_volume = (long)val_volume_dbl;
      double avg_m1_volume_prev = MathMean(m1_volume_history);
      double val_close = bars_M1[1].close;
      double prev_high = bars_M1[2].high;

      double div = (val_ma_fast - val_ma_slow) / val_atr;
      bool strong_candle = (val_close > prev_high);
      bool high_volume = (avg_m1_volume_prev > 0 && val_volume > (long)(avg_m1_volume_prev * MA_Volume_Multiplier));

      // Debug Print (só para ter algo usando as variáveis)
      string condition_check = StringFormat("Barra M1 %s: Div=%.2f Vol=%d AvgVol=%.1f HighVol=%s Strong=%s",
                                  TimeToString(lastBarTime_M1), div, val_volume, avg_m1_volume_prev,
                                  (high_volume ? "SIM" : "NAO"), (strong_candle ? "SIM" : "NAO") );
      Print(condition_check);
      // =======================================================================


      // --- 3. Condição Final (NÃO ADICIONADA) ---
      // if(div > DIV_THR && high_volume && strong_candle) { /*...*/ }


   } // Fim if(Nova Barra M1)
}
//+------------------------------------------------------------------+


Erro Exato Obtido ao Compilar o Código MRE - Passo 2:

'[' - invalid index value BugTestInvalidIndex_Step2.mq5 67 31

(Observação: O número da linha '67' pode variar ligeiramente dependendo da formatação exata, mas o erro ocorre consistentemente na linha if(!data_ok) ou imediatamente após ela,antesdas linhas de cálculo/atribuição que parecem ser o gatilho real para o bug do compilador).

Erro Exato Obtido ao Compilar o Código MRE - Passo 2:

A única diferença entre o Código 1 (que compila) e o Código 2 (que falha) é a adição do bloco de código que processa os dados copiados pelos CopyBuffer . Isso indica que o compilador está tendo problemas em analisar corretamente o acesso aos arrays ( ma_fast_1[0] , vol_bar1_buffer[0] , etc.) ou as chamadas de função ( MathMean )logo apósa sequência de chamadas CopyBuffer dentro do mesmo escopo de função/bloco if . A mensagem de erro "invalid index value" parece ser um sintoma incorreto do problema real de parsing do compilador.
 
Felipe Raymundo De Oliveira:
double m1_volume_history[MA_Volume_Period];
Não pode usar uma variável na declaração, deixa só "[]" e quando for pedir com CopyBuffer pode colocar quantos quiser que ele aloca dinamicamente. Aqui ambos códigos falharam no compilar nessa parte.