[Erro em obter o tempo do TF sênior no temporizador! - página 5

 
Vitaly Gorbunov:
O método iBarShift permite que você encontre buracos no histórico, mas você tem que verificar o histórico em intervalos. Escrevi um procedimento para mim mesmo que faz isso, e depois disso esqueci as lacunas nos programas MtF.
Não se tratava de detectar "buracos". A pessoa queria obter a última barra da história. E esta não é necessariamente a barra atual no tempo.
 
Vitaly Gorbunov:
Os dados são carregados com o erro 4066, e então é culpa dos methaquotovs, muito provavelmente os dados recebidos são processados para esta situação, o erro não foi inventado. E até esse ponto, tudo faz sentido.

Se um erro é "não inventado", isso não significa que ele não exista.

 
Alexey Navoykov:
Não se tratava de detectar "buracos". A pessoa queria obter a última barra da história. E esta não é necessariamente a barra de tempo atual.

Não se trata de iBarShift(). Ele envia os mesmos erros que o iTime() e o SeriesInfoInteger(). A muleta aqui está em comparar o tempo obtido durante a inicialização e depois compará-lo com o tempo do timer. Foi isso que permitiu obter dados reais corretos ao carregar o terminal, não o IBarShift().

Sim, e se a hora for 15:00:45 (por exemplo), e ainda não houver nenhum sinal no bar das 15:00 e se a hora da última hora de abertura do bar for 14:00 - tudo está correto, eu acho. E se o sistema retornar às 13:00 - isso é um problema.

 
Alexey Kozitsyn:

1. Igor, você já olhou o código? Onde eu consigo algo no OnInit()?

Em seu caso, uma ou várias chamadas OnTimer são executadas logo após o OnInit(). Ainda não há nenhum evento OnCalculate().

2. Que verificações? Onde está escrito que o indicador deve usar OnCalculate() pelo menos uma vez para funcionar corretamente?

Aqui precisamos entender a lógica do terminal. OnInit() é chamado imediatamente ao conectar o indicador ao gráfico. Ao iniciar o terminal, a conexão do indicador com a carta é feita logo após a janela da carta ser criada. Neste momento, o terminal ainda nem sequer enviou o pedido ao servidor.

A primeira OnCalculate() é chamada após a leitura das citações disponíveis localmente. Em alguns casos raros, acontece que não há nada localmente. Neste caso, ao se dirigir ao Time[0], os indicadores saem da matriz. Portanto, é melhor usar a função iTime ou similar.

O segundo e o próximo OnCalculate() ocorrem no carregamento do histórico ou na chegada de carrapatos reais.

 
Ihor Herasko:

A primeira OnCalculate() é chamada após a leitura das citações disponíveis localmente. Em alguns casos raros, acontece que não há nada localmente. Neste caso, ao se referir ao Tempo[0], os indicadores saem da matriz. Portanto, é melhor usar a função iTime ou similar.

Acho que estamos falando da preparação da MQL5, OHLC é diferente lá do que na MT4

Há muito tempo venho escrevendo indicadores com base em um modelo:

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
   int i,limit;
   if(prev_calculated==0)
     {
      limit=rates_total-1;    //--- Первый вызов индикатора или смена таймфрейма или подгрузка данных из истории
     }
   else limit=rates_total-prev_calculated+1;
   for(i=limit;i>=0;i--)      //---- Основной цикл расчета
     {                        
     }
   return(rates_total);
  }

nunca tive uma "falha de indicador" em arrays OHLC no MT4, acho que o MT4 não executará OnCalculate() até que um gráfico seja preparado pela primeira vez, e se o histórico for carregado, eu não o verifiquei, mas prev_calculado==0 , no MT5 será como você escreveu - você precisa de verificações adicionais para ver se os dados OHLC já estão preparados

 
Ihor Herasko:

Em seu caso, uma ou mais chamadas OnTimer serão executadas logo após o OnInit(). Ainda não há nenhum evento OnCalculate().

Aqui você precisa entender a lógica do terminal. OnInit() é chamado imediatamente ao conectar o indicador ao gráfico. Ao iniciar o terminal, a conexão do indicador com a carta é feita imediatamente após a janela da carta ser criada. Neste momento, o terminal ainda nem sequer enviou o pedido ao servidor.

A primeira OnCalculate() é chamada após as citações disponíveis terem sido lidas localmente. Em alguns casos raros, acontece que não há nada localmente. Neste caso, ao se dirigir ao Time[0], os indicadores saem da matriz. Portanto, é melhor usar a função iTime ou similar.

O segundo e o próximo OnCalculate() ocorrem no carregamento do histórico ou na chegada de carrapatos reais.

O que você sugere para resolver o problema (existe, em sua opinião)? Espere até que OnCalculate() seja chamado 1-2 vezes?

 
Alexey Kozitsyn:

O que você sugere para resolver o problema (existe, em sua opinião)? Espere até que OnCalculate() seja chamado 1-2 vezes?

Você pode tentarcopiar o valorprev_calculado==0para uma variável no escopo global e ver em OnTimer() se o indicador tiver sido calculado.OnCalculate() - será calculado em qualquer caso, suspeito que se os dados TF não estavam prontos, então oretorno(taxas_total) retornará 0, que estará na próxima chamada deOnCalculate() indicandoprev_calculate==0, aproximadamente:

void OnTimer(){
   if(Global_prev_calculated==0)return;
}
 
Igor Makanu:

você pode tentarcopiar o valorprev_calculado==0para uma variável no escopo global e ver no OnTimer() se o indicador foi calculado; escrevi acima que nunca vi nenhum bug com cálculo incorreto no MT4OnCalculate() - será calculado em qualquer caso, suspeito que se os dados TF não estavam prontos, entãoretorno(taxas_total) retornará 0, que estará na próxima chamada deOnCalculate() um sinalprev_calculado==0

Parece que a solução mais confiável é realmente esperar pela chamada da OnCalculate() com verificação obrigatória da conexão com o servidor comercial. Se não verificarmos a conexão (IsConnected()), então a obteremos mesmo em OnCalculate() quando o terminal for carregado:

2018.09.21 23:45:27.128 test_isNewDayInOnCalculate_iBarShift() EURGBP.e,M1: test_isNewDayInOnCalculate_iBarShift().mq4: Актуальное время открытия бара М15 = 2018.09.21 21:30. Ошибка #0
2018.09.21 23:45:25.990 test_isNewDayInOnCalculate_iBarShift() EURGBP.e,M1: initialized
2018.09.21 23:45:25.975 Custom indicator test_isNewDayInOnCalculate_iBarShift() EURGBP.e,M1: loaded successfully

No entanto, ela não elimina todas as dúvidas:

1. Por que não está escrito na documentação da IsConnected() que ela deve ser necessariamente chamada antes de receber dados (pelo menos) da TF sênior na OnCalculate()?

2. Por que IsConnected() no OnTimer() realmente não funciona? O fato de estabelecer conexão com um servidor comercial não deveria nos dizer que os dados podem ser obtidos?

3. Uma vez estabelecida uma conexão com o servidor de negociação e tentando receber dados no OnTimer(), as funções iTime(), iBarShift(), SeriesInfoInteger() e funções similares a elas retornam erros se os dados deste servidor de negociação em particular, do qual retiram informações, ainda não estiverem sincronizados? Caso contrário, parece um absurdo, como se devolvêssemos o erro 4066 uma vez e depois usássemos os dados atuais da maneira que quiséssemos.

 
Alexey Kozitsyn:

No entanto, isto não elimina todas as dúvidas:

1. Por que a documentação para IsConnected() não diz que ela deve necessariamente ser chamada antes de receber os dados (pelo menos) da TF sênior em OnCalculate()?

2. Por que IsConnected() no OnTimer() realmente não funciona? O fato de estabelecer conexão com um servidor comercial não deveria nos dizer que os dados podem ser obtidos?

3. Uma vez estabelecida uma conexão com o servidor de negociação e tentando receber dados no OnTimer(), as funções iTime(), iBarShift(), SeriesInfoInteger() e funções similares a eles não deveriam retornar erros se os dados deste servidor de negociação em particular, do qual eles tiram informações, ainda não estiverem sincronizados? Caso contrário, parece um absurdo, como se devolvêssemos um erro 4066 uma vez e depois tratássemos os dados existentes da maneira que você deseja.

1. bem, ninguém cancelou o caso de chamada de indicador nos dados históricos, se você precisar trabalhar on-line, então verifique a conexão, se não, ou melhor, não importante, então minha versão do modelo funciona. O grupo de funções IsConnected() é na verdade um pouco complicado, eles cruzam IsTradeContextBusy() e IsConnected() por vezes e IsTradeAllowed()... Acho que eles trapaceiam no lado do servidor e desconectam os terminais na hora das notícias ou de algumas outras manipulações

2,3. funciona, mas você esquece que GetLastError() irá redefinir seu estado após uma chamada e talvez para atualizar o estado GetLastError() precise transferir o controle para o terminal, talvez o terminal não tenha tido tempo de redefinir o estado IsConnected() em GetLastError() antes de sua chamada a partir do timer.... Eu acho que a função OnTimer() não se destina ao recebimento de dados: "MQL4 Reference / Status Check - OnTimer() será chamado, mas as variáveis do ambiente do terminal não são atualizadas, eonCalculate() é garantido preparar todos os dados pelo terminal quando o tick chegar

 
Igor Makanu:

1. bem, ninguém cancelou o caso de chamar o indicador sobre dados históricos.

2,3. funciona, mas você esquece que GetLastError() irá redefinir seu estado após a chamada, e talvez para atualizar o estado GetLastError() precise passar o controle para o terminal, talvez o terminal não tenha tempo para redefinir o estado IsConnected() em GetLastError() antes de sua chamada do timer.... Eu acho que a função OnTimer() não se destina ao recebimento de dados: "The MQL4 Reference / Status Check - OnTimer() será chamado, mas as variáveis do ambiente do terminal não são atualizadas, e é garantido que o terminal irá preparar todos os dados quando o tick vier-OnCalculate().

1. Você acha que se a barra número 0 tiver um tempo incorreto, o resto da história terá um tempo correto?)

2,3. Se as funções de acesso aos dados não tiverem tempo suficiente para definir algum erro significativo - deixe-o informar de alguma forma, mas certamente não retornando o código de erro = 0 (sem erro). O resto do "talvez" é apenas um trabalho de adivinhação. E sem provas não há nada para se falar.

A função OnTimer() não se destina a buscar dados...

Sem comentários.

OnTimer() será chamado, mas as variáveis do ambiente terminal não são necessariamente atualizadas

Para que precisamos do erro 4066?