array out of range

 

Boa noite, queria ajuda de vocês nesse codigo, no testador ele não abre ordem.




//+------------------------------------------------------------------+
//|                                                  my_first_ea.mq5 |
//|                                  Copyright 2021, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2021, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#include <TimeTrade.mqh>


//+------------------------------------------------------------------+
//| Parâmetros de Entrada                                            |
//+------------------------------------------------------------------+
sinput group "----- Parâmetros de Negociação"
input int      EA_Magic_Number       = 12345;    // MAGIC NUMBER
input double   Lote                  = 1.0;      // TAMANHO DO LOTE
//---
sinput   group    "------ Horários de Negociação [hh:mm]"
input  string  InpStartTime          = "09:10";  // ABRIR ORDENS
sinput string  InpEndTime            = "16:00";  // PARAR ABRIR ORDENS
sinput string  InpClosingTime        = "17:00";  // ENCERRAR ORDENS ABERTAS
//---
sinput   group    "------ Parametros dos Indicadores"
input int      mdperiod              = 10;       // PERIODO DA MÉDIA
input ENUM_MA_METHOD  in_ma_1_method = MODE_SMA; // MÉTODO
//---
sinput   group    "------ Gerenciamento de Risco"
input int      maxloss               = 10;       // LIMITE DE LOSS DIARIO
input int      maxgain               = 10;       // LIMITE DE GAIN DIARIO
//--- OUTROS PARÂMETROS
int     md1handle;                               // HANDLE MEDIA 1
int     md2handle;                               // HANDLE MEDIA 2
double  md1array[];                              // ARRAY DE ARMAZENAMENTO MEDIA 1
double  md2array[];                              // ARRAY DE ARMAZENAMENTO MEDIA 2
    
CTimeTrade * timeTrade;

//+------------------------------------------------------------------+
//| Função de inicialização do EA                                    |
//+------------------------------------------------------------------+
int OnInit()
  {
   
  if(timeTrade == NULL)
      timeTrade = new CTimeTrade();

   timeTrade.SetTime(InpStartTime, InpEndTime, InpClosingTime);
   timeTrade.TimeAdjustment();
   
//---

  
  md1handle = iMA(_Symbol,PERIOD_CURRENT,mdperiod,0,in_ma_1_method,PRICE_HIGH);
  md2handle = iMA(_Symbol,PERIOD_CURRENT,mdperiod,0,in_ma_1_method,PRICE_LOW);
  
  if (md1handle < 0 || md2handle < 0)
      {
      Alert("Erro ao criar handles para indicadores - erro: ",GetLastError(),"!!");
      return(-1);
      }
      
  ChartIndicatorAdd(0,0,md1handle);
  ChartIndicatorAdd(0,0,md2handle);
  
    return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Função de finalização do EA                                      |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {  
   IndicatorRelease(md1handle);             // FINALIZAR MÉDIA 1
   IndicatorRelease(md2handle);             // FINALIZAR MÉDIA 2
   
    if(timeTrade != NULL)
     {
      delete timeTrade;
      timeTrade = NULL;
     }
  }
//+------------------------------------------------------------------+
//| Função ontick                                                    |
//+------------------------------------------------------------------+
void OnTick()
  {
  
  if(timeTrade.CheckTimeEndTrade())
     {
      Print("Horário de encerramento de ordens");
      return;
     }

   if(!timeTrade.CheckTimeTrade())
     {
      Print("Horário de parar de abir ordens");
      return;
     }

   if(Bars(_Symbol,_Period)<60)                                    // verificar se temos 60 candles
     {
      Alert("Temos menos de 60 barras!!");
      return;
     } 
   
   static datetime Old_Time;                                       // Usaremos a variável estática Old_Time para servir o horário do bar.
   datetime New_Time[1];                                           // A cada execução do OnTick verificaremos o tempo de compasso atual com o salvo. 
   bool IsNewBar=false;                                            // Se o tempo da barra não for igual ao tempo economizado, indica que temos um novo tique.
   
   
   int copied = CopyTime(_Symbol,PERIOD_CURRENT,0,1,New_Time);     // Copiando a última barra de tempo para o elemento New_Time [0]
    if (copied > 0)                                                // Ok, os dados foram copiados com sucesso
     {
      if (Old_Time != New_Time[0])                                 // Se Old_time for diferente de New_time da barra atual
       {
        IsNewBar=true;                                             
        if(MQL5InfoInteger(MQL5_DEBUGGING)) Print("Temos um newbar aqui",New_Time[0]," oldtime era ",Old_Time);
        Old_Time=New_Time[0];                                      // saving bar time 
        }
  }
else
 {
      Alert("Erro ao copiar dados de tempos históricos, erro =",GetLastError());
      ResetLastError();
      return;
     }

   if(IsNewBar==false)
     {
      return;
     }
 
   int Mybars=Bars(_Symbol,_Period);
   if(Mybars<60) // se o total de barras for inferior a 60 barras
     {
      Alert("Temos menos de 60 barras!!");
      return;
     }

// Definir algumas estruturas MQL5

   MqlDateTime min;
   MqlTick latest_price;                                          // Para ser usado para obter cotações de preços recentes / mais recentes
   MqlTradeRequest mrequest;                                      // Para ser usado para enviar nossos pedidos de trading
   MqlTradeResult mresult;                                        // Para ser usado para obter nossos resultados dos trades
   MqlRates mrate[];                                              // Para ser usado para armazenar os preços, volumes e spread de cada barra
   ZeroMemory(mrequest);

// the rates arrays
   ArraySetAsSeries(mrate,true);
// Array dos valores de média 1
   ArraySetAsSeries(md1array,true);
// Array dos valores de média 2
   ArraySetAsSeries(md2array,true);
    
// --- Obtenha a última cotação de preço usando a estrutura MQL5 MqlTick

  if(!SymbolInfoTick(_Symbol,latest_price))
     {
      Alert("Erro ao obter a última cotação de preço - erro:",GetLastError(),"!!");
      return;
     }
     
// Obtenha dados das últimas 3 barras
  if(CopyRates(_Symbol,_Period,0,3,mrate)<0)
     {
      Alert("Erro ao copiar taxas / dados de histórico - erro:",GetLastError(),"!!");
      ResetLastError();
      return;
     }
     
// Copie os novos valores de nossos indicadores para buffers 

   if(CopyBuffer(md1handle,0,0,1,md1array)<0)
     {
      Alert("Erro ao copiar buffers do indicador média 1 - error:",GetLastError(),"!!");
      ResetLastError();
      return;
     }
   if(CopyBuffer(md2handle,0,0,1,md2array)<0)
     {
      Alert("Erro ao copiar o buffer do indicador média 2 - erro:",GetLastError());
      ResetLastError();
      return;
     }
     
// Já temos posições abertas?
   bool Buy_opened=false;                                                                                                     // variável para manter o resultado da posição de compra aberta
   bool Sell_opened=false;                                                                                                    // variáveis ​​para manter o resultado da posição de venda aberta
   
      if(PositionSelect(_Symbol)==true)                                                                                       //temos posiçoes abertas
     {
      if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)
        {
         Buy_opened=true;                                                                                                     // Posição de compra
        }
      else if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL)
        {
         Sell_opened=true;                                                                                                    // Posição de venda
        }
     }

 double p_open  = mrate[1].open;                                                                                                   // barra 1 preço de abertura
 double p_close = mrate[1].close;                                                                                                  // barra 1 preço de fechamento
 double p_high  = mrate[1].high;                                                                                                   // barra 1 preço maximo
 double p_low   = mrate[1].low;                                                                                                    // barra 1 preço minimo

double TickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
double smm = md1array[1] - md2array[1]; 

                                                                 
   bool Buy_Condition_1 = (p_close>p_open);                                                                                                                                     
   bool Buy_Condition_2 = (Profit() < maxgain) && (Profit() > (maxloss*-1));


   if(Buy_Condition_1 && Buy_Condition_2)
        {

         if((Buy_opened) || (Sell_opened))                                                                      
           {
            Alert("Já temos uma posição!!!");
            return;                                                                                                          
           }
         ZeroMemory(mrequest);
         mrequest.action = TRADE_ACTION_PENDING;                                                                
         mrequest.price = NormalizeDouble(p_high + TickSize,_Digits);                                                         
         mrequest.sl = NormalizeDouble(p_high - smm * _Point,_Digits);                                          
         mrequest.tp = NormalizeDouble(p_high + smm * _Point,_Digits);                                                   
         mrequest.symbol = _Symbol;                                                                             
         mrequest.volume = Lote;                                                                                     
         mrequest.magic = EA_Magic_Number;                                                                            
         mrequest.type = ORDER_TYPE_BUY_LIMIT;                                                                               
         mrequest.type_filling = ORDER_FILLING_RETURN;                                                                    
         mrequest.deviation=5;                                                                                               
          
         if(OrderSend(mrequest,mresult))                                                                           
           {
            Alert("Ordem de compra executada com sucesso, ticket: #:",mresult.order,"!!");
           }
         else
           {
            Alert("Falha na ordem de compra, ERRO:",GetLastError());
            ResetLastError();           
            return;
           }
        }
       
                                                               
   bool Sell_Condition_1 = p_open > p_close;                                                                                                                                     
   bool Sell_Condition_2 = ((Profit() < maxgain) && (Profit() > (maxloss * -1)));
   
   if(Sell_Condition_1 && Sell_Condition_2)
        {
         if((Buy_opened) || (Sell_opened))                                                                       
           {
            Alert("Já temos uma posição!!!");
            return;                                                                                                        
           }
         ZeroMemory(mrequest);
         mrequest.action=TRADE_ACTION_PENDING;                                                                      
         mrequest.price = NormalizeDouble(p_low - TickSize ,_Digits);                                               
         mrequest.sl = NormalizeDouble(p_low + smm*_Point,_Digits);                                                 
         mrequest.tp = NormalizeDouble(p_low - smm*_Point,_Digits);                                                       
         mrequest.symbol = _Symbol;                                                                                    
         mrequest.volume = Lote;                                                                                     
         mrequest.magic = EA_Magic_Number;                                                                          
         mrequest.type= ORDER_TYPE_SELL_LIMIT;                                                                           
         mrequest.type_filling = ORDER_FILLING_RETURN;                                                                       
         mrequest.deviation=5;                                                                                             

         if(OrderSend(mrequest,mresult))                                                                                    
           {
            Alert("Venda foi feita sucesso, Ticket#:",mresult.order,"!!");
           }
         else
           {
            Alert("A solicitação do pedido de venda não pôde ser concluída - erro:",GetLastError());
            ResetLastError();
            return;
           }
        
        return;
 }       
}

//+------------------------------------------------------------------+
//| Gerenciamento de Risco                                           |
//+------------------------------------------------------------------+
//--- A versão original da função retorna o resultado do dia (lucro ou prejuízo):
double Profit()
  {
   double Res = 0.0;
   datetime time_start = iTime(_Symbol, PERIOD_D1, 0);

   if(HistorySelect(time_start,TimeCurrent()))
      for(int i = HistoryDealsTotal() - 1; i >= 0; i--)
        {
         const ulong Ticket = HistoryDealGetTicket(i);

         if(HistoryDealGetInteger(Ticket, DEAL_MAGIC) == EA_Magic_Number && HistoryDealGetString(Ticket, DEAL_SYMBOL) == _Symbol)
            Res += HistoryDealGetDouble(Ticket, DEAL_PROFIT);
        }

   return(Res);
  }
 
Romeu Masselai:

Boa noite, queria ajuda de vocês nesse codigo, no testador ele não abre ordem.


Romeu,

qual linha? Você cortou a msg justamente onde diz a linha, no código, que o erro aconteceu.

 
Rogerio Giannetti Torres:

Romeu,

qual linha? Você cortou a msg justamente onde diz a linha, no código, que o erro aconteceu.

(210,22)
 

Olá, geralmente esse erro se dá quando vc utiliza o dado do array antes dele carregar compltamente o buffer. Num projeto que eu tive esse problema, eu criei uma função que calcula todos os buffers, se algum deles desem erro retorna false, e se estiver tudo ok retorna true. 

Utilizava a condição true da função pra seguir com a utilização do array. 

exemplo.






bool carregaBuffers () // coloca no fim do programa

{ if(!SymbolInfoTick(_Symbol,latest_price))

     {       Alert("Erro ao obter a última cotação de preço - erro:",GetLastError(),"!!");       return false;      }      // Obtenha dados das últimas 3 barras   if(CopyRates(_Symbol,_Period,0,3,mrate)<0)      {       Alert("Erro ao copiar taxas / dados de histórico - erro:",GetLastError(),"!!");       ResetLastError();       return false;      }      // Copie os novos valores de nossos indicadores para buffers    if(CopyBuffer(md1handle,0,0,1,md1array)<0)      {       Alert("Erro ao copiar buffers do indicador média 1 - error:",GetLastError(),"!!");       ResetLastError();       return false;      }    if(CopyBuffer(md2handle,0,0,1,md2array)<0)      {       Alert("Erro ao copiar o buffer do indicador média 2 - erro:",GetLastError());       ResetLastError();       return false;      } return true: }
if(carregaBuffers()) //adicionar no codigo 

{ 

double p_open  = mrate[1].open;                                                                                                   // barra 1 preço de abertura
 double p_close = mrate[1].close;                                                                                                  // barra 1 preço de fechamento
 double p_high  = mrate[1].high;                                                                                                   // barra 1 preço maximo
 double p_low   = mrate[1].low;                                                                                                    // barra 1 preço minimo

double TickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
double smm = md1array[1] - md2array[1]; 


}else{
Print("Buffers não carregado corretamente");
}


Deve funcionar.

 

Outro motivo é que vc pode estar tentando recuperar um dado de uma posição inexistente de um array.

Ex:


Vc criou um array[3] e esta chamando a posição 4:

exdeerro = array[4];


No caso do seu código o problema deve estar na linha  210 como é apontado na log do erro:

double smm = md1array[1] - md2array[1];


Veja se esta correta essa lógica usando o valor 1 para eles.

 
Rogerio Giannetti Torres:

Romeu,

qual linha? Você cortou a msg justamente onde diz a linha, no código, que o erro aconteceu.

.

 

Bom dia!


@Romeu Masselai, corrija para:

double smm = md1array[0] - md2array[0];
 
Romeu Masselai:

.

Olá,

falta essas duas linhas.


   mrequest.type_time   =ORDER_TIME_GTC;
   mrequest.expiration  =0;
 
Romeu Masselai:

Olá @Rogerio Giannetti Torres, adicionei e fiz outras alterações, o EA compila e roda sem erros, porem não abre nenhuma ordem, para ficar de mais fácil entendimento, a estratégia consiste em quando um candle for "X" vezes maior que a media de tamanho dos últimos "Y" candles, e o corpo ocupar "Z%" do candle, o EA abre uma venda no rompimento da mínima desse candle se ele for negativo, ou uma compra no rompimento da máxima se o candle for positivo, os stops são a media de tamanho dos últimos "Y" candles projetados pra cima e para baixo da entrada, o EA só deve abrir ordem se o rompimento ocorrer no candle seguinte ao padrão. 

Olá Romeu,

erro de lógica mano é com você, quebra a cabeça, bota uns prints, depura no metaeditor... Agora com relação ao type_time, na B3 para FUTUROS só são aceitos ORDER_TIME_DAY ou ORDER_TIME_GTC... Para ações na B3 é permitido especificar uma data expiração e você tá deixando 0(zero), desconheço o resultado disso.

Uma dúvida você quer fazer uma ordem SELL_STOP_LIMIT ?



         mrequest.action=TRADE_ACTION_PENDING;                                                                                
         mrequest.magic = EA_Magic_Number;                                           
         mrequest.price = NormalizeDouble(p_low - TickSize ,_Digits); 
         mrequest.stoplimit = p_close;
         mrequest.symbol = _Symbol;
         mrequest.volume = Lote;                                                      
         mrequest.sl = NormalizeDouble(p_low + smm*_Point,_Digits);                                                         
         mrequest.tp = NormalizeDouble(p_low - smm*_Point,_Digits);                                                                                                                                           
         mrequest.type= ORDER_TYPE_SELL_LIMIT;                                                                                   
         mrequest.type_filling = ORDER_FILLING_RETURN;
         mrequest.type_time = ORDER_TIME_SPECIFIED;                                                                        
         mrequest.deviation=5;
 
Rogerio Giannetti Torres:

Olá Romeu,

erro de lógica mano é com você, quebra a cabeça, bota uns prints, depura no metaeditor... Agora com relação ao type_time, na B3 para FUTUROS só são aceitos ORDER_TIME_DAY ou ORDER_TIME_GTC... Para ações na B3 é permitido especificar uma data expiração e você tá deixando 0(zero), desconheço o resultado disso.

Uma dúvida você quer fazer uma ordem SELL_STOP_LIMIT ?



Não, uma sell limit. A logica acredito estar correta, penso que o erro esta na requisições de abertura de posições.

 
Romeu Masselai:

Não, uma sell limit. A logica acredito estar correta, penso que o erro esta na requisições de abertura de posições.

Sé é uma sell limit  então deve colocar mrequest.stoplimit = 0;

Razão: