Tenho um código de EA que utiliza duas faixas de tempo, uma D1 e outra definida pelo usuário.
Ao executar ele devia pegar o fechamento do dia anterior, no array D1, e com isso calcular e colocar ordens no dia seguinte.
O problema é que quando mando executar retorna o erro "array out of range" e enseguida: "OnTick critical error". Após isso, ele fecha o EA.
O que pode estar causando isso? Se precisa envio cópia do código criado.
Obrigado
Pablo
Boa noite Juan,
isso acontece quando você tenta acessar uma posição do array que não existe. Pode ser que a causa esteja na manipulação incorreta da função CopyClose ou CopyRates, que por algum motivo não está preenchendo o seu array.
Eu separei dois artigos que podem ser úteis para você:
https://www.mql5.com/pt/articles/567 - Arrays
https://www.mql5.com/pt/articles/496 - Exemplo com a função CopyClose
Fique a vontade em postar o pedaço do código onde aconteceu o erro, desse modo facilita a identificação do erro pela comunidade.
Um abraço,
Romeu.
- 2014.03.18
- Dmitry Fedoseev
- www.mql5.com
Boa noite Juan,
isso acontece quando você tenta acessar uma posição do array que não existe. Pode ser que a causa esteja na manipulação incorreta da função CopyClose ou CopyRates, que por algum motivo não está preenchendo o seu array.
Eu separei dois artigos que podem ser úteis para você:
https://www.mql5.com/pt/articles/567 - Arrays
https://www.mql5.com/pt/articles/496 - Exemplo com a função CopyClose
Fique a vontade em postar o pedaço do código onde aconteceu o erro, desse modo facilita a identificação do erro pela comunidade.
Um abraço,
Romeu.
Valeu, vou verificar os artigos!
Romeu Bertho, Olha o código ai.
//+------------------------------------------------------------------+
//| Marquito1.mq5 |
//| Pablito |
//| www.linkedin.com/in/juan-pablo-silenzi-de-stagni |
//+------------------------------------------------------------------+
#property copyright "Pablito"
#property link "www.linkedin.com/in/juan-pablo-silenzi-de-stagni"
#property version "1.00"
//#include <Trade\Trade.mqh>
//--- input parameters
string Papel=Symbol();
//input string Papel = Ativo; //Papel do Gráfico
input int PontosVenda = 10; //Pontos para Venda
input int PontosCompra = 10; //Pontos para Compra
input int DefesaVenda = 30; //Pontos para a Defesa da Venda
input int DefesaCompra = 30; //Pontos para a Defesa da Compra
input int DesvioDefesa = 2; //Desvio do Take Profit na Defesa
input double Lot = SYMBOL_VOLUME_MIN; // Volume a Negociar
int EA_Magic = 7585577; // EA Magic Number
//Variáveis de trabalho D1
double TKP1; //Valor do Take Profit do 1o Nível da Ordem 1
double TKP2; //Valor do Take Profit do 10 Nível da Ordem 2
double TKPV; //Valor do Take Profit da Venda do 2o Nível
double TKPC; //Valor do Take Profit da Compra do 2o Nível
int CloseHandle; //Handle para os precos de fechamento D1
double CloseVal[]; //Array para conter os valores dos fechamentos D1
double p_close; //Variável para gravar o valor do fechamento do candle anterior D1
long position_type; //Tipo de posição
static datetime Old_Time_D1; //Variável Estática para gravar o valor da barra de fechamento do dia anterior
datetime New_Day[1];
bool IsNewDay=false;
static datetime Old_Time_M1;
datetime New_Time[1];
bool IsNewBar=false;
bool OrdemColocadaNoDia=false;
bool PrimeiraOrdem=false;
bool SegundaOrdem=false;
ulong IDOrdem1=0;
ulong IDOrdem2=0;
ulong IDOrdem3=0;
ulong IDOrdem4=0;
bool OrdensDeletadas=false;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//---
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
//---
// Temos suficientes barras para trabalhar?
if(Bars(_Symbol,_Period)<30) // se o total for menor que 30
{
Alert("Temos menos de 30 barras, não se pode trabalhar!!");
return;
}
//--- analisa a situação
//--- verifica se existe ordem colocada
if(PositionSelect(_Symbol)==true)
{
position_type=PositionGetInteger(POSITION_TYPE); // COMPRAR=0, VENDER=1
}
else
{
position_type=-1; // sem posição para o símbolo
}
//--- Temos barras suficientes para trabalhar?
int Mybars=Bars(_Symbol,PERIOD_D1);
if(Mybars<1) // se o total de barras for menor que 1
{
Alert("Não temos barras, não se pode trabalhar!!");
return;
}
// Utilizaremos a variável estática Old_Time_D1 para servir o tempo da barra D1
// A cada OnTick iremos checar o tempo da barra comparando com o tempo salvo
// Se o tempo não for igual, indicará um novo dia.
// copiar a hora da ultima barra no elemento New_Day[0]
int dia = CopyTime(_Symbol,PERIOD_D1,0,1,New_Day);
if(dia>0)
{
if(Old_Time_D1!=New_Day[0]) // Se Old_Time_D1 diferente do dia da nova barra
{
IsNewDay=true;
OrdemColocadaNoDia=false;
PrimeiraOrdem=false;
SegundaOrdem=false;
OrdensDeletadas=false;
if(MQL5InfoInteger(MQL5_DEBUGGING)) Print("Nova barra aquí em ",New_Day[0]," antes era em ",Old_Time_D1);
Old_Time_D1=New_Day[0];
}
}
else
{
Alert("Erro ao copiar os dados históricos, error =",GetLastError());
ResetLastError();
return;
}
// Pegar o fechamento do dia anterior
ArrayResize(CloseVal,1);
ArraySetAsSeries(CloseVal,true);
CopyClose(_Symbol,PERIOD_D1,0,1,CloseVal);
double FechamentoDiaAnterior = CloseVal[1];
double VendaEm = FechamentoDiaAnterior + (PontosVenda * _Point); //Valor da Venda
double DefesaVendaEm = FechamentoDiaAnterior + (DefesaVenda * _Point); //Valor da Defesa da Venda
double CompraEm = FechamentoDiaAnterior - (PontosCompra * _Point); //Valor da Compra
double DefesaCompraEm = FechamentoDiaAnterior - (DefesaCompra * _Point); //Valor da Defesa da Compra
TKP1 = CompraEm; //Valor do Take Profit do 1o Nível da Ordem 1
TKP2 = VendaEm; //Valor do Take Profit do 1o Nível da Ordem 2
TKPV = VendaEm - (DesvioDefesa * _Point); //Valor do Take Profit da Venda do 2o Nível
TKPC = CompraEm + (DesvioDefesa * _Point); //Valor do Take Profit da Compra do 2o Nível
// Utilizaremos a variável estática Old_Time_M1 para servir o tempo da barra M1
// A cada OnTick iremos checar o tempo da barra comparando com o tempo salvo
// Se o tempo não for igual, indicará um novo tick.
// copiar a hora da ultima barra no elemento New_Time[0]
int Tempo = CopyTime(_Symbol,_Period,0,1,New_Time);
if(Tempo>0) // copia de dados OK
{
if(Old_Time_M1!=New_Time[0]) // se Old_Time_M1 diferente da hora da nova barra
{
IsNewBar=true; // se não for a primeira chamada, uma nova barra apareceu
if(MQL5InfoInteger(MQL5_DEBUGGING)) Print("Nova barra aquí em ",New_Time[0]," antes era em ",Old_Time_M1);
Old_Time_M1=New_Time[0]; // salva a hora da barra
}
}
else
{
Alert("Erro ao copiar os dados históricos, error =",GetLastError());
ResetLastError();
return;
}
//--- EA somente checa por operações se houver uma barra nova
if(IsNewBar==false)
{
return;
}
//--- Definir estruturas MQL5 que usaremos nas operações
MqlTick latest_price; // Usado para obter as ultimas cotações de preços
MqlRates mrate[]; // Usado para guardar os preços, volumes e spread de cada barra
// datetime DiaAtual;
// datetime DataAtual;
//--- Obter o último preço cotado usando a estrutura MQL5 MqlTick
if(!SymbolInfoTick(_Symbol,latest_price))
{
Alert("Erro ao obter a última cotação - preço - erro:",GetLastError(),"!!");
return;
}
//--- obter os detalhes das duas ultimas barras
if(CopyRates(_Symbol,_Period,0,2,mrate)<0)
{
Alert("Erro ao obter os dados das últimas barras - erro:",GetLastError(),"!!");
return;
}
//--- Sem erros, continuar
//--- Temos posições abertas já?
bool Buy_opened=false; // variável para guardar a posição de uma COMPRA
bool Sell_opened=false; // variável para guardar a posição de uma VENDA
if (PositionSelect(_Symbol) ==true) // posição aberta
{
if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
{
Buy_opened = true; //É uma compra
}
else if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
{
Sell_opened = true; // É uma venda
}
}
// Copiar o preço de fechamento da barra prévia à barra atual, isto é barra 1.
p_close=mrate[0].close; // fechamento da barra 0
if (IsNewDay==true)
{
IsNewDay=false;
if (OrdemColocadaNoDia==false)
{
//Definir chamada de colocação das 4 ordens pendentes
// Ordem 1
func_send_order(ORDER_TYPE_SELL,Lot,VendaEm,CompraEm,1, TKP1);
// Ordem 2
func_send_order(ORDER_TYPE_BUY,Lot,VendaEm,CompraEm,2, TKP2);
OrdemColocadaNoDia=true;
}
else
{
//Verificar preços e se houve realizado.
//Caso chegou na 1a Ordem (qqr uma), deletar as ordens pendentes de signo invertido
if (p_close >= VendaEm || p_close<=CompraEm)
{
PrimeiraOrdem=true;
if (p_close>=VendaEm && p_close<=DefesaVendaEm)
{
// Deletar ordens de compra no servidor
func_delete_order(IDOrdem2);
IDOrdem2=0;
OrdensDeletadas=true;
}
else if (p_close<=CompraEm && p_close>=DefesaCompraEm)
{
// Deletar ordens de venda no servidor
func_delete_order(IDOrdem1);
IDOrdem1=0;
OrdensDeletadas=true;
}
else if (p_close>=VendaEm && p_close>=DefesaVendaEm)
{
SegundaOrdem=true;
func_send_order(ORDER_TYPE_SELL,Lot,DefesaVendaEm,DefesaCompraEm,3, TKPV);
// Deletar ordens de compra no servidor
if(IDOrdem2!=0)
{
func_delete_order(IDOrdem2);
IDOrdem2=0;
}
OrdensDeletadas=true;
}
else if (p_close<=CompraEm && p_close<=DefesaCompraEm)
{
SegundaOrdem=true;
// Deletar ordens de venda no servidor
if(IDOrdem1!=0)
{
func_delete_order(IDOrdem1);
IDOrdem1=0;
}
OrdensDeletadas=true;
}
}
}
}
else //Não estamos num novo dia
{
//Verificar preços e se houve realizado.
//Caso chegou na 1a Ordem (qqr uma), deletar as ordens pendentes de signo invertido
if (p_close >= VendaEm || p_close<=CompraEm)
{
PrimeiraOrdem=true;
if (p_close>=VendaEm && p_close<=DefesaVendaEm)
{
// Deletar ordens de compra no servidor
func_delete_order(IDOrdem2);
IDOrdem2=0;
OrdensDeletadas=true;
}
else if (p_close<=CompraEm && p_close>=DefesaCompraEm)
{
// Deletar ordens de venda no servidor
func_delete_order(IDOrdem1);
IDOrdem1=0;
OrdensDeletadas=true;
}
else if (p_close>=VendaEm && p_close>=DefesaVendaEm)
{
SegundaOrdem=true;
func_send_order(ORDER_TYPE_SELL,Lot,DefesaVendaEm,DefesaCompraEm,3, TKPV);
// Deletar ordens de compra no servidor
if(IDOrdem2!=0)
{
func_delete_order(IDOrdem2);
IDOrdem2=0;
}
OrdensDeletadas=true;
}
else if (p_close<=CompraEm && p_close<=DefesaCompraEm)
{
SegundaOrdem=true;
// Deletar ordens de venda no servidor
if(IDOrdem1!=0)
{
func_delete_order(IDOrdem1);
IDOrdem1=0;
}
OrdensDeletadas=true;
}
}
}
return;
}
//------------------------------------------------------------------------------------------------------
//+------------------------------------------------------------------+
//| Função Enviar Ordem |
//+------------------------------------------------------------------+
void func_send_order(ENUM_ORDER_TYPE type_order, //Tipo de ordem a colocar
double volume, double price_ask, double price_bid, int OrderNumber, double OTP) // Lote do volume da operação
{
MqlTradeRequest mrequest; // To be used for sending our trade requests
MqlTradeResult mresult; // To be used to get our trade results
MqlRates mrate[]; // To be used to store the prices, volumes and spread of each bar
ZeroMemory(mrequest); // Initialization of mrequest structure
mrequest.action = TRADE_ACTION_PENDING; // pending order execution
mrequest.symbol = _Symbol; // currency pair
mrequest.volume = volume; // number of lots to trade
mrequest.magic = EA_Magic; // Order Magic Number
mrequest.type = type_order; // Type Order
mrequest.type_filling = ORDER_FILLING_FOK; // Order execution type
mrequest.deviation=100;
mrequest.expiration=ORDER_TIME_DAY; // Ordem vence no fim do dia
if (type_order==ORDER_TYPE_BUY)
{
mrequest.price = NormalizeDouble(price_ask,_Digits); // latest ask price
//mrequest.sl = NormalizeDouble(price_ask - STP*_Point,_Digits); // Stop Loss
mrequest.tp = NormalizeDouble(price_ask + OTP,_Digits); // Take Profit
}
if (type_order==ORDER_TYPE_SELL)
{
mrequest.price = NormalizeDouble(price_bid,_Digits); // latest Bid price
//mrequest.sl = NormalizeDouble(price_bid + STP*_Point,_Digits); // Stop Loss
mrequest.tp = NormalizeDouble(price_bid - OTP,_Digits); // Take Profit
} // Deviation from current price
//--- send order
OrderSend(mrequest,mresult);
//--- get the result code
if(mresult.retcode==10009 || mresult.retcode==10008) //Request is completed or order placed
{
Alert("Uma ordem foi colocada com sucesso no Ticket#:",mresult.order,"!!");
switch (OrderNumber)
{
case 1:
IDOrdem1=mresult.order;
break;
case 2:
IDOrdem2=mresult.order;
break;
case 3:
IDOrdem3=mresult.order;
break;
case 4:
IDOrdem4=mresult.order;
break;
}
}
else
{
Alert("A ordem não pode ser colocada - Erro:",GetLastError());
ResetLastError();
return;
}
}
//--------------------------------------------------------------------------------------------------------------
void func_delete_order(const ulong ticket)
{
MqlTradeRequest mrequest; // To be used for sending our trade requests
MqlTradeResult mresult; // To be used to get our trade results
MqlRates mrate[]; // To be used to store the prices, volumes and spread of each bar
ZeroMemory(mrequest); // Initialization of mrequest structure
//--- setting request
mrequest.action =TRADE_ACTION_REMOVE;
mrequest.magic =EA_Magic;
mrequest.order =ticket;
//--- action and return the result
OrderSend(mrequest,mresult);
//--- get the result code
if(mresult.retcode==10009 || mresult.retcode==10008) //Request is completed or order placed
{
Alert("Uma ordem foi cancelada com sucesso no Ticket#:",mresult.order,"!!");
}
else
{
Alert("A ordem não pode ser cancelada - Erro:",GetLastError());
ResetLastError();
return;
}
}
//--------------------------------------------------------------------------------------------------------------
//--- Verifica se já estamos num novo dia
bool NewDay ( datetime aTimeCur, datetime aTimePre, int aVariant = 1 )
{
switch (aVariant)
{
case 1 :
return (NewDay1 (aTimeCur, aTimePre));
break ;
case 2 :
return (NewDay2 (aTimeCur, aTimePre));
break ;
}
return ( false );
}
//--------------------------------------------------------------------------------------------------------------
//--- Verifica se estamos num novo dia
bool NewDay1 ( datetime aTimeCur, datetime aTimePre)
{
return ((aTimeCur/86400)!=(aTimePre/86400));
}
//--------------------------------------------------------------------------------------------------------------
//--- Verifica o dia da semana
bool NewDay2 ( datetime aTimeCur, datetime aTimePre)
{
MqlDateTime STM;
// --- Novo dia
if (NewDay1 (aTimeCur, aTimePre))
{
TimeToStruct (aTimeCur, STM);
switch (STM.day_of_week)
{
case 6 : // sábado
return ( false );
break ;
case 0 : // domingo
return ( true );
break ;
case 1 : // segunda-feira
TimeToStruct (aTimePre, STM);
if (STM.day_of_week!= 0 )
{ // Precedido por qualquer dia da semana que não seja domingo
return ( true );
}
else
{
return ( false );
}
break ;
default : // qualquer outro dia da semana
return ( true );
}
}
return ( false );
}
//--------------------------------------------------------------------------------------------------------------
//+------------------------------------------------------------------+
Valeu, vou verificar os artigos!
Boa noite Juan,
isso acontece quando você tenta acessar uma posição do array que não existe. Pode ser que a causa esteja na manipulação incorreta da função CopyClose ou CopyRates, que por algum motivo não está preenchendo o seu array.
Eu separei dois artigos que podem ser úteis para você:
https://www.mql5.com/pt/articles/567 - Arrays
https://www.mql5.com/pt/articles/496 - Exemplo com a função CopyClose
Fique a vontade em postar o pedaço do código onde aconteceu o erro, desse modo facilita a identificação do erro pela comunidade.
Um abraço,
Romeu.
Fiz algumas modificações no código, mas continua dando o erro. Ele nem fala qual array é a que dá a falha.
Olha meu código, vê se descobre o problema por favor.
Abs
Boa noite Juan,
estou com um tempo meio curto, mas dando uma olhada rápida eu descobri algumas coisinhas:
Deixe as seguintes variáveis desse modo:
bool IsNewDay=false;
static datetime Old_Time_M1;
datetime New_Time[];
As funções Copy**** cuidam automaticamente do tamanho do array.
tente rodar novamente e se acontecer novamente o problema, cole o log aqui também. É a primeira vez que eu vejo um array out of range sem a linha do código, rs. Acredito que com essas modificações esse erro não apareça mais.
Um abraço,
Romeu.
Observei que seu código na parte que pega o fechamento anterior não tem verificação de erros:
ArrayResize(CloseVal,1); // --> isto não é necessário, CopyClose já ajusta o tamanho do array
ArraySetAsSeries(CloseVal,true);
CopyClose(_Symbol,PERIOD_D1,0,1,CloseVal);
double FechamentoDiaAnterior = CloseVal[1];
Minha sugestão é fazer o seguinte (em todas as funções que retornam dados do sistema ou cotações), ou algo parecido:
if(CopyClose(_Symbol,PERIOD_D1,0,1,CloseVal) <= 0){
printf("Erro código %i: ", GetLastError());
return;
}
double FechamentoDiaAnterior = CloseVal[1];
Sugiro também utilizar break points e usar o passo a passo para depurar detalhes como esse.
Valeu pelas dicas amigos!
Abs!
Também estou com um problema de array, estou com uma situação onde eu desejo utilizar um array dinamico, pois não sei qual vai ser o tamanho do mesmo, estou tentando definir o tamanho do array utilizando uma variável conforme abaixo, quando eu compilo ele diz da erro dizendo que o valor bars é inválido (bars tem o valor de 1767), se no lugar de bars eu colocar 1767 ele funciona conforme preciso, mas como se trata de um array que não sei o tamanho eu estou tentando colocar pela variável bars que atualiza conforme a janela. Por favor poderiam me dar um auxílio??
int bars=Bars(_Symbol,_Period);
double CompraBuffer[bars]; // bars tem o valor de 1767
double VendaBuffer[bars];
for(int i=0;i<(bars-1);i++)
{
CompraBuffer[i]=maVal_9[i]-maVal_21[i];
}
fala Balsante,
eu suponho que o erro cometido foi voce nao ter considerado que logo no inicio do loop, valores 0, 1, 2, 3 e mais alguns outros valores, vc nao descontou que o calculo da media nos arrays que estao dentro do loop deve ser feito tambem, e estes calculos vao tentar buscar valores que nao existem, pois teriam que estar antes da posicao 0 no loop.
Vou tentar explicar melhor,... se a quantidade de barras for por exemplo 100 no total e vc quer usar um loop que dentro dele utilize media_movel das 10 ultimas barras, entao vc tem que comecar o loop a partir da posicao 10, para que nesse ponto vc tenha uma base de dados 10 barras antes para que a media possa ser calculada, ou seja, o loop tem que ir de 10 ate 100.
acho que o ponto eh este.
boa sorte.
Andre LC
Olá @balsante
boa tarde, use o ArrayResize para definir o tamanho do array.
double CompraBuffer[],VendaBuffer[]; int bars=Bars(_Symbol,_Period); ArrayResize(CompraBuffer,bars); ArrayResize(VendaBuffer,bars); for(int i=0;i<bars;i++) { if(maVla_9[i]!=EMPTY_VALUE && maVal_21[i]!=EMPTY_VALUE) CompraBuffer[i]=maVal_9[i]-maVal_21[i]; }
- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Você concorda com a política do site e com os termos de uso
Tenho um código de EA que utiliza duas faixas de tempo, uma D1 e outra definida pelo usuário.
Ao executar ele devia pegar o fechamento do dia anterior, no array D1, e com isso calcular e colocar ordens no dia seguinte.
O problema é que quando mando executar retorna o erro "array out of range" e enseguida: "OnTick critical error". Após isso, ele fecha o EA.
O que pode estar causando isso? Se precisa envio cópia do código criado.
Obrigado
Pablo