Características da linguagem mql5, subtilezas e técnicas - página 31

 
Artyom Trishkin:

Olhaste sequer para o código que te mostrei? Foste tu que a geriste?

Eu não estava perguntando como preencher o buffer indicador, mas porque os valores vazios são devolvidos se eu pegar valores de AO e não da barra atual.
Eu consegui - não há histórico, ele está carregando, e enquanto ele está carregando AO de um período de tempo não nativo retorna o erro "sem dados".

Quero verificar se o histórico está totalmente carregado para não entrar no ciclo indicador.

Se utilizar CopyBuffer no código para receber dados de outro código, o usuário deve:

  1. Gire o buffer indicador para que a barra mais à direita no gráfico corresponda ao índice "0" no buffer indicador.
  2. Assim, "a barra corrente" no indicador "iMTF_AO.mq5" será a barra mais direita do gráfico, e corresponderá ao índice "0" no indicador buffer "Buffer[]".
  3. E para obter a "barra de corrente" do indicador (CopyBuffer(handle,0,shift,1,array)) o parâmetro "shift" deve ser igual a "0".

Se não quiser inverter o buffer do indicador, faça o seguinte (temporariamente): AO(0) - para entender como obter valores de outro indicador de um INDICADOR. Você pode receber um erro uma ou duas vezes, mas isso é até que a série temporal seja construída, e então os valores serão estáveis.

 
Artyom Trishkin:
Já viste a minha resposta? Já tentou?
 
Vladimir Karputov:

Se você usar CopyBuffer em um código para recuperar dados de outro código, você deve:

  1. Estornar o buffer do indicador para que a barra mais à direita no gráfico corresponda ao índice "0" no buffer do indicador.
  2. Assim, "a barra corrente" no indicador "iMTF_AO.mq5" será a barra mais direita do gráfico, e corresponderá ao índice "0" no indicador buffer "Buffer[]".
  3. E para obter a "barra de corrente" do indicador (CopyBuffer(handle,0,shift,1,array)) o parâmetro "shift" deve ser igual a "0".

Se não quiser inverter o buffer do indicador, faça o seguinte (temporariamente): AO(0) - para entender como obter valores de outro indicador de um INDICADOR. Você pode receber um erro uma ou duas vezes - mas isso é até que uma série temporal seja construída, então os valores serão estáveis.

1. O meu código tem-no, e estava lá imediatamente:

   ArraySetAsSeries(Buffer,true);
   int bars=Bars(NULL,PeriodForWork);
   datetime time_limit=GetTime(Symbol(),PeriodForWork,bars-1);
   int limit_p=GetBarShift(Symbol(),Period(),time_limit);
   if(rates_total<1) return(0);

2. É verdade.

3. turno é igual ao índice de ciclo i. E o loop vai desde o início dos dados do histórico (taxas_total-1) até ao fim (até aos dados actuais)

Outra questão é que devemos calcular estes dados com respeito a um TF não nativo para não obter dados de barras em falta. E precisamos determinar antes do ciclo que o histórico do TF desejado está totalmente sincronizado.

 
Artyom Trishkin:

1. O meu código tem-no, e tinha-o imediatamente:

2. É assim que as coisas são.

3. turno é igual ao índice de ciclo i. E o loop vai desde o início dos dados históricos (taxas_total-1) até ao fim (até aos dados actuais)

Outra questão é que precisamos de calcular estes dados em relação a um período de tempo não nativo para não obtermos dados de barras em falta. E devemos determinar antes do loop que o histórico do tempo necessário esteja completamente sincronizado.


Retrabalhe o loop para chamar AO: coloque de "0" para algum valor (agora de algum valor para zero). Quando os erros ocorrem - compare imediatamente: o número de barras calculadas ("limit_p") e taxas_total do indicador atual.


Adicionado: e aqui estas linhas apagam todos os esforços de "limite" calculado (se nos referirmos a um período de tempo não nativo):

   if(limit>1) 
     {
      limit=rates_total-1;
     }

Grosso modo, no início (ao acessar um prazo não nativo) "limite" era igual a 156, mas abaixo de VOLTAR! e "limite" tornou-se "154566666666".



 
Alexey Kozitsyn:
Você já tentou a sincronização? Além disso, os desenvolvedores aconselham a manter atualizados os dados do TF/símbolo necessário através do temporizador.

Não, eu ainda não tentei. Eu já vi sobre o suporte de relevância de dados, eu me lembro - eu sei.

Mas inicialmente é necessário sair da OnCalculate() se os dados na data especificada e na data atual ainda não estiverem sincronizados.

Eu entendo sobre o actual:

if(rates_total<1) return(0);

Sobre dado - é necessário verificar suas Barras() - seu número ao invés de taxas_total.

Mas eu não sei quanto ao limite - pode ser verificado no período atual (como um exemplo de outro indicador):

   int limit=rates_total-prev_calculated;
   if(limit>1) {
      limit=rates_total-4;
      ArrayInitialize(BufferAoDN,EMPTY_VALUE);
      ArrayInitialize(BufferAoUP,EMPTY_VALUE);
      ArrayInitialize(BufferMacdDN,EMPTY_VALUE);
      ArrayInitialize(BufferMacdUP,EMPTY_VALUE);
      ArrayInitialize(BufferRsiDN,EMPTY_VALUE);
      ArrayInitialize(BufferRsiUP,EMPTY_VALUE);
      ArrayInitialize(BufferStochDN,EMPTY_VALUE);
      ArrayInitialize(BufferStochUP,EMPTY_VALUE);
      }

Mas neste indicador de teste obtemos dados tanto do período de tempo atual (ele mostra os cálculos em OnCalculate()) como do especificado - para obter dados AO do período de tempo especificado.

Ainda não me lembro como calcular todos os dados necessários para o número de barras - porque o laço deve começar com a barra correspondente ao tempo da barra do histórico com os primeiros dados existentes do atual ou do especificado - onde é menor - a partir dessa barra iniciamos o laço. O limite também deve ser correctamente calculado para detectar o aparecimento de uma nova barra, o que deve levar a um recálculo completo ou apenas ao recálculo da barra actual (dependendo do que aconteceu - a abertura de uma nova barra ou o carregamento do histórico).

Talvez esteja a tentar pensar em tudo ao mesmo tempo, e penso em muitas coisas desnecessárias...

 
Vladimir Karputov:


Retrabalho de chamada em loop para AO: colocar de "0" e para algum valor (agora de algum valor para zero). Quando ocorrem erros - compare imediatamente: o número de barras calculadas ("limit_p") e taxas_total do indicador atual.


Adicionado: e estas linhas apagam todos os esforços do "limite" calculado (se se referir a um período de tempo não nativo):

grosso modo, no início (ao abordar um período de tempo não nativo) "limite" tornou-se 156, e abaixo de BATCH! e "limite" já se tornou "154566666666".

Sim, escrevi logo sobre isso que fiz asneira aqui, com pressa.

Mas não vou mudar o laço - há um indicador bastante complicado no qual tudo é construído sobre o cálculo da história do início ao fim - é mais fácil recalcular os limites e obter os dados do que reescrever o indicador inteiro - toda a sua lógica.

 
Artyom Trishkin:

Não, eu ainda não tentei. Eu já vi sobre o suporte de relevância de dados, eu me lembro - eu sei.

Mas inicialmente é necessário sair da OnCalculate() se os dados na data especificada e na data atual ainda não estiverem sincronizados.

A actual é clara:

Não é bem assim. Ao carregar inicialmente o terminal com o indicador, você pode não obter o que você espera. Durante o dia e se houver interrupções na conexão - pode haver erros também.

Sobre a saída de OnCalculate(): As primeiras barras de requisição() devem ser feitas na fase de inicialização, depois em OnCalculate() verificar a sincronização das TFs atuais e necessárias. Se não houver sincronização, saia.

 
Artyom Trishkin:

Sim, foi o que eu disse imediatamente, que estraguei tudo à pressa.

Não quero mudar o laço, existe um indicador bastante complicado, que se baseia no cálculo do histórico do início ao fim - é mais fácil recalcular os limites e receber os dados corretamente, do que reescrever todo o indicador - toda a sua lógica.

Artem, o que queres dizer com "desde o início até ao fim"?

Achas que virar todas as matrizes é a melhor saída?

Porquê

ArraySetAsSeries(Buffer,true);

se só estás a copiar um valor?

Ao copiar a TF diferente da atual, é melhor passar o tempo da barra necessária para a função CopyBuffer(). Caso contrário, não copiará o bar que você quer.

 
Alexey Viktorov:

1. artyom, o que queres dizer com "do princípio ao fim"?

2. Você acha que virar todas as matrizes é a melhor saída?

3. Porquê

4. se você só copiar 1 valor?

Ao copiar o tempo da barra necessária para a função CopyBuffer() que não é o tempo atual, é melhor passá-lo. Caso contrário, não copiará o bar que você quer.

1. O início dos dados históricos é a primeira barra da história com o menor tempo de abertura, o fim dos dados históricos é a barra atual.

2. Estou a copiar de um 4 para um 5.

Bem, porque em Buffer[] os dados são escritos em loop de taxas_total-1 a 0. Se não o fizermos como uma série de tempos, será mostrado para trás e para a frente no gráfico.

4. Quero copiar um valor de cada vez, que corresponde aos dados da barra i de um determinado período de tempo.

Veja como é lacónico e fácil obter os dados de não o tempo actual em mql4. Pergunto-me como é possível receber dados do indicador em mql5 e não vai funcionar - há sempre erro 4806 se eu passar o tempo que não corresponde ao tempo do gráfico em que o indicador funciona na função de receber dados AO.

//+------------------------------------------------------------------+
double GetDataAO(string sy, int timeframe, int shift) {
   double array[1];
   ZeroMemory(array);
#ifdef __MQL4__
   array[0]=iAO(sy,timeframe,shift);
#else 
   ResetLastError();
   if(CopyBuffer(handle_ao,0,shift,1,array)==WRONG_VALUE) {
      Print(__FUNCTION__," > Error: ",GetLastError());
      return(0);
      }
#endif 
   return(array[0]);
}
//+------------------------------------------------------------------+

Ao mesmo tempo, o cabo indicador é criado em OnInit() que corresponde ao preço atual do qual queremos receber os dados:

handle_ao=iAO(symbol,periodForWork);

Isto é, a qualquer momento, não importa como trocamos o f, o cabo é criado com o necessário (selecionado em configurações)f. Mas os dados AO só podem ser obtidos se a função seleccionada nas definições e a função corrente coincidirem. Se não coincidirem, então o zero é sempre retornado da função.

A questão é: PORQUÊ?

 
Artyom Trishkin:

1. O início dos dados históricos é a primeira barra na história com o menor tempo de abertura, o fim dos dados históricos é a barra atual.

2. Estou a reescrever de quatro para cinco.

Bem, porque em Buffer[] os dados são escritos em loop de taxas_total-1 a 0. Se não o fizermos como uma série de tempos, será mostrado para trás e para a frente no gráfico.

4. Eu copio um valor de cada vez que corresponde aos dados na barra i do período de tempo dado.

Veja como é conciso e fácil obter os dados não do fator de corrente em mql4; ele é bem sucedido e tudo funciona como planejado. Pergunto-me como é possível receber dados do indicador em mql5 e não vai funcionar - há sempre erro 4806 se eu passar o tempo que não corresponde ao tempo do gráfico em que o indicador funciona na função de receber dados AO.

Ao mesmo tempo, o cabo indicador é criado em OnInit() que corresponde ao preço atual do qual queremos receber os dados:

Isto é, a qualquer momento, não importa como trocamos o f, o cabo é criado com o necessário (selecionado em configurações)f. Mas os dados AO só podem ser obtidos se a função selecionada nas configurações e a função atual coincidirem. Se não corresponderem, o zero é sempre devolvido da função.

A pergunta: Porquê?

1. Só um esclarecimento. Agora entendo que estamos a falar da mesma coisa.

Eu entendo, mas não concordo que seja necessário reverter matrizes. É necessário ter um indicador para dois terminais? Quase como fazer 2 em 1 uma foice e um machado.

3. como eu entendo Buffer[] é usado pelo receptor na função CopyBuffer() para obter apenas 1 valor indicador.

4. Você não prestou atenção ao mais importante. O início da cópia do valor do indicador não deve ser determinado pelo índice de barras, mas pela hora da i-ésima barra.

int  CopyBuffer( 
   int       indicator_handle,     // handle индикатора 
   int       buffer_num,           // номер буфера индикатора 
   datetime  start_time,           // с какой даты 
   int       count,                // сколько копируем 
   double    buffer[]              // массив, куда будут скопированы данные 
   );
Razão: