[SERVICE DESK] Errore nell'ottenere il tempo del TF senior nel timer! - pagina 15

 
Taras Slobodyanik:

Il tuo indicatore non tiene traccia dell'aggiornamento dei dati.
Arrivano nuove barre dal broker e voi non le controllate.
Ho aggiunto un paio di righe per mostrare che quando si controlla, tutto viene visualizzato correttamente.

È una situazione di lavoro - controllare il nuovo bar.

Non mi dire! Cosa ti fa pensare che io debba tenere traccia dei nuovi bar? È scritto nella documentazione? Voglio dire che DEVO ottenere il valore della funzione, e poi devo necessariamente confrontarlo con il valore precedente? C'è una funzione, la funzione è progettata per lavorare con tempi elevati. La funzione può restituire un errore quando non ha dati, o restituire un valore errato (uguale a 0 in questo caso). Questo è tutto. I programmatori non devono fare nulla per ottenere un valore corretto al 100%.

Ma guardate cosa ho trovato nella documentazione per SeriesInfoInteger():

Per ottenere maggiori informazioni sull'errore, è necessario chiamare la funzione GetLastError().

Vedete GetLastError() nel mio codice? Ecco l'assegno. Questo controllo deve essere necessario e VERAMENTE necessario! Tutto il resto sono soluzioni da stampella.
 
Alexey Kozitsyn:

E tu guarda il mio primissimo post. Vedi l'errore 4066 lì? Poi sbaglia 0 e restituisce dati errati. Perché la funzione (in questo caso, SeriesInfoInteger()) non controlla la rilevanza prima di inviare i dati? Perché non imposta il flag di errore? Vedete, preferisco aspettare un po' più a lungo che i controlli interni passino piuttosto che cercare gli errori dopo.

Ma dopo mi sono stati dati molti consigli, con i quali non ho ancora ottenuto alcun risultato. E si è scoperto che non si trattava nemmeno del timer.

Ok, leggi l'aiuto)

SeriesInfoInteger

Restituisce informazioni sullo stato dei dati storici.

La parola "storico" cosa significa?
Se la storia viene caricata - non c'è nessun errore.


Alexey Kozitsyn:

Impossibile! E cosa le fa pensare che dovrei necessariamente tracciare nuove barre? È scritto nella documentazione? Cioè, DEVO ottenere il valore della funzione, e poi devo necessariamente confrontarlo con quello precedente? C'è una funzione, la funzione è progettata per lavorare con tempi elevati. La funzione può restituire un errore quando non ha dati, o restituire un valore errato (uguale a 0 in questo caso). Questo è tutto. I programmatori non devono fare nulla per ottenere un valore corretto al 100%.

Ma guardate cosa ho trovato nella documentazione per SeriesInfoInteger():

Nel mio codice vedi GetLastError()? Ecco un controllo. Questo controllo deve essere necessario e REALE! Tutto il resto sono soluzioni da stampella.

Non devi fare nulla).
...il broker ti manda i dati aggiornati - se vuoi, usali per il calcolo, se no - nessun problema, usa lo storico esistente).


ps. è il fine settimana, il mercato è chiuso, avete dati errati nel vostro terminale!
e non c'è nessun errore!!!)

 
Taras Slobodyanik:

ok, leggi l'aiuto)

Cosa significa la parola storia?
Se la storia viene caricata - non c'è nessun errore.


Non dovete nulla).
...il broker ti manda i dati aggiornati - se vuoi usarli per calcolare, se no - nessun problema, usa History)

Ogni zecca che entra nel terminale è già una storia. E voglio ottenere i suoi valori reali o l'errore. Se questo vi sta bene - ok.

 
Alexey Kozitsyn:

Ogni zecca che entra nel terminale è già una storia. E voglio ricevere i suoi valori reali o l'errore. Se questo ti sta bene, va bene.

Sì, la storia è ciò che è già stato caricato, o ciò che viene caricato in passato.
E ciò che viene aggiornato solo ora (dopo l'ultima citazione) non è la storia, sono i nuovi dati grezzi.

 
Taras Slobodyanik:

Controlla il tempo della candela, non il calcolo delle barre.
In questo modo si aggiornerà correttamente (controllato).

Taras, ecco il risultato del tuo codice:

2018.10.08 11:11:39.080 test_isNewDayInOnCalculate GBPUSD,M1: initialized
2018.10.08 11:11:39.788 test_isNewDayInOnCalculate GBPUSD,M1: test_isNewDayInOnCalculate.mq4: Время открытия недельного бара = 2018.09.30 00:00. Ошибка #0
2018.10.08 11:11:39.788 test_isNewDayInOnCalculate GBPUSD,M1: test_isNewDayInOnCalculate.mq4: Актуальное время открытия текущей недели = 2018.10.01 00:00. Ошибка #0
2018.10.08 11:11:39.788 test_isNewDayInOnCalculate GBPUSD,M1: test_isNewDayInOnCalculate.mq4: Время открытия текущего дня = 2018.10.05 00:00. Ошибка #0
2018.10.08 11:11:39.788 test_isNewDayInOnCalculate GBPUSD,M1: test_isNewDayInOnCalculate.mq4: Актуальное время открытия текущего дня = 2018.10.05 00:00. Ошибка #0
2018.10.08 11:11:39.788 test_isNewDayInOnCalculate GBPUSD,M1: test_isNewDayInOnCalculate.mq4: Время открытия текущего часа = 2018.10.05 23:00. Ошибка #0
2018.10.08 11:11:39.788 test_isNewDayInOnCalculate GBPUSD,M1: test_isNewDayInOnCalculate.mq4: Актуальное время открытия текущего часа = 2018.10.05 23:00. Ошибка #0
2018.10.08 11:11:39.788 test_isNewDayInOnCalculate GBPUSD,M1: OnCalculate: Данные старших ТФ загружены!
 
Alexey Kozitsyn:

Taras, ecco il risultato del tuo codice:

Sì, è la prima spunta, quella che produce la storia finita, quella che è disponibile.
Dopo questo tick (se ci sono nuove barre), arriva immediatamente il secondo tick, in cui il mio codice aggiorna le vostre variabili e queste mostrano i dati corretti.

ps. potete inserire la vostra funzione per controllare la nuova barra, sarà la stessa.

Io stesso controllo costantemente il numero di barre, se il numero è cambiato di più di 1, significa che bisogna ricalcolare tutto di nuovo, se il numero è cambiato di 1, significa solo una nuova barra. E controllo solo gli errori più critici, e non vedo questo errore di ritardo.

 
Taras Slobodyanik:

Sì, questa è la prima spunta, quella che dà la storia pronta.
Dopo questo tick (se ci sono nuove barre), arriva immediatamente il secondo tick, in cui il mio codice aggiorna le vostre variabili e queste mostrano i dati corretti.

Se il numero è cambiato di più di 1, allora è solo una nuova barra.

Io stesso controllo costantemente il numero di barre, se il numero è cambiato di più di 1, significa che bisogna ricalcolare tutto di nuovo, se il numero è cambiato di 1, significa solo una nuova barra. E controllo solo gli errori più critici, e non vedo questo errore di ritardo.

E qui, a proposito, c'è un altro argomento a favore del verificarsi dell'errore. È ERRORE nel calcolo nell'indicatore! Ho scritto un Expert Advisor:

#property version   "1.00"
#property strict
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//--- Время открытия текущего часа, дня и недели
datetime _weekOpenTime = 0;
datetime _hourOpenTime = 0;
datetime _dayOpenTime=0;
//--- Вести лог журнала
const bool inpFileLog=true;
//--- Количество секунд в одном дне
const int SEC_PER_DAY=86400;
//--- Флаг работоспособности индикатора
bool _isWorking=true;
//--- Флаг соединения с торговым сервером (для таймера, получаем в OnCalculate())
bool _isConnected=false;
//---
bool _firstLaunch = true;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   //--- Устанавливаем флаг первого запуска
   _firstLaunch = true;
//--- Сбрасываем время открытия текущего часа, дня и недели
   _weekOpenTime= 0;
   _dayOpenTime = 0;
   _hourOpenTime= 0;
//--- Устанавливаем флаг работоспособности
   _isWorking=true;
//--- Сбрасываем флаг установки соединения
   _isConnected=false;
////--- Запускаем таймер
//   if(!EventSetMillisecondTimer(20))
//     {
//      Print(__FUNCTION__,": ОШИБКА #",GetLastError(),": таймер с частотой 20 не установлен!");
//      //--- Устанавливаем флаг неработоспособности индикатора
//      _isWorking=false;
//     }
//--- Запрос данных
   SeriesInfoInteger(_Symbol,PERIOD_W1,SERIES_LASTBAR_DATE);
   SeriesInfoInteger(_Symbol,PERIOD_D1,SERIES_LASTBAR_DATE);
   SeriesInfoInteger(_Symbol,PERIOD_H1,SERIES_LASTBAR_DATE);
//---
   return( INIT_SUCCEEDED );
  }
//+------------------------------------------------------------------+
//|                                                                   |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
////--- Выключаем таймер
//   EventKillTimer();
  }
////+------------------------------------------------------------------+
////|                                                                  |
////+------------------------------------------------------------------+
//void OnTimer()
//  {
////---
//   if(!_isWorking)
//      return;
////---
//   if(!_isConnected)
//      return;
////---
//   Print(__FUNCTION__,": Данные старших ТФ загружены!");
////--- Отключаем таймер
//   EventKillTimer();
//  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnTick()
  {
//--- Проверяем связь с сервером
   if(!IsConnected())                              // Если не удалось установить связь с сервером
     {
      //--- Сбрасываем флаг соединения с сервером
      _isConnected=false;
      //--- Выходим
      return;
     }
        //--- Проверяем первый запуск эксперта
        if( _firstLaunch )
                {
            //--- Проверяем, записано ли время открытия текущей недели
            if(!CheckCurrentWeekOpenTime())                              // Если время не записано
              return;                                                // Выходим
            //--- Проверяем, записано ли время открытия текущего дня
            if(!CheckCurrentDayOpenTime())                              // Если время не записано
              return;                                                // Выходим
            //--- Проверяем, записано ли время открытия текущего часа
            if(!CheckCurrentHourOpenTime())                              // Если время не записано
              return;                                                // Выходим
            ////--- Устанавливаем флаг соединения с сервером для запуска таймера
            //_isConnected=true;
            //---
            Print(__FUNCTION__,": Данные старших ТФ загружены!");
            //--- Сбрасываем флаг первого запуска
            _firstLaunch = false;
                }
  }
//+------------------------------------------------------------------+
//| Проверяем, записано ли время открытия текущей недели             |
//+------------------------------------------------------------------+
bool CheckCurrentWeekOpenTime()
  {
//--- Проверяем, записано ли время
   if(_weekOpenTime==0) // Если время не записано
     {
      //--- Получаем время открытия недельного бара
      ResetLastError();
      const datetime weekBarOpenTime=(datetime)SeriesInfoInteger(_Symbol,PERIOD_W1,SERIES_LASTBAR_DATE);
      const int err=GetLastError();
      //---
      if(inpFileLog)
        {
         Print(__FILE__,": Время открытия недельного бара = "+TimeToString(weekBarOpenTime)+". Ошибка #",err);
        }
      //--- Проверяем, получено ли время открытия недельного бара
      if(weekBarOpenTime==0 || err!=0) // Если время бара не получено или история обновляется
         return(false);                              // Возвращаем ложь
      //--- Запоминаем время открытия текущей недели (время открытия недельного бара - воскресенье)
      _weekOpenTime=weekBarOpenTime+SEC_PER_DAY;
      //---
      if(inpFileLog)
        {
         Print(__FILE__,": Актуальное время открытия текущей недели = "+TimeToString(_weekOpenTime)+". Ошибка #",err);
        }
      //--- Возвращаем истину
      return( true );
     }
//--- Время открытия недели ранее записано. Возвращаем истину
   return( true );
  }
//+------------------------------------------------------------------+
//| Проверяем, записано ли время открытия текущего дня                  |
//+------------------------------------------------------------------+
bool CheckCurrentDayOpenTime()
  {
//--- Проверяем, записано ли время
   if(_dayOpenTime==0) // Если время не записано
     {
      //--- Получаем время открытия дневного бара
      ResetLastError();
      const datetime tempDayOpenTime=(datetime)SeriesInfoInteger(_Symbol,PERIOD_D1,SERIES_LASTBAR_DATE);
      const int err=GetLastError();
      //---
      if(inpFileLog)
        {
         Print(__FILE__,": Время открытия текущего дня = "+TimeToString(tempDayOpenTime)+". Ошибка #",err);
        }
      //--- Проверяем, получено ли время открытия дневного бара
      if(tempDayOpenTime==0 || err!=0) // Если время бара не получено
         return(false);                                 // Возвращаем ложь
      //--- Сохраняем в глобальную переменную значение открытия текущего дня
      _dayOpenTime=tempDayOpenTime;
      //---
      if(inpFileLog)
        {
         Print(__FILE__,": Актуальное время открытия текущего дня = "+TimeToString(_dayOpenTime)+". Ошибка #",err);
        }
      //--- Возвращаем истину
      return( true );
     }
//--- Время открытия дня ранее записано. Возвращаем истину
   return( true );
  }
//+------------------------------------------------------------------+
//| Проверяем, записано ли время открытия текущего часа              |
//+------------------------------------------------------------------+
bool CheckCurrentHourOpenTime()
  {
//--- Проверяем, записано ли время
   if(_hourOpenTime==0) // Если время не записано
     {
      //--- Получаем время открытия часового бара
      ResetLastError();
      const datetime tempHourOpenTime=(datetime)SeriesInfoInteger(_Symbol,PERIOD_H1,SERIES_LASTBAR_DATE);
      const int err=GetLastError();
      //---
      if(inpFileLog)
        {
         Print(__FILE__,": Время открытия текущего часа = "+TimeToString(tempHourOpenTime)+". Ошибка #",err);
        }
      //--- Проверяем, получено ли время открытия часового бара
      if(tempHourOpenTime==0 || err!=0) // Если время бара не получено
         return(false);                                 // Возвращаем ложь
      //---
      _hourOpenTime=tempHourOpenTime;
      //---
      if(inpFileLog)
        {
         Print(__FILE__,": Актуальное время открытия текущего часа = "+TimeToString(_hourOpenTime)+". Ошибка #",err);
        }
      //--- Возвращаем истину
      return( true );
     }
//--- Время открытия часа ранее записано. Возвращаем истину
   return( true );
  }
//+------------------------------------------------------------------+

Viene eseguito dallo stesso grafico dell'indicatore. Vediamo i risultati:

2018.10.09 08:45:42.627 test_isNewDayInOnTick GBPUSD,M1: OnTick: Данные старших ТФ загружены!
2018.10.09 08:45:42.627 test_isNewDayInOnTick GBPUSD,M1: test_isNewDayInOnTick.mq4: Актуальное время открытия текущего часа = 2018.10.09 06:00. Ошибка #0
2018.10.09 08:45:42.627 test_isNewDayInOnTick GBPUSD,M1: test_isNewDayInOnTick.mq4: Время открытия текущего часа = 2018.10.09 06:00. Ошибка #0
2018.10.09 08:45:42.627 test_isNewDayInOnTick GBPUSD,M1: test_isNewDayInOnTick.mq4: Актуальное время открытия текущего дня = 2018.10.09 00:00. Ошибка #0
2018.10.09 08:45:42.627 test_isNewDayInOnTick GBPUSD,M1: test_isNewDayInOnTick.mq4: Время открытия текущего дня = 2018.10.09 00:00. Ошибка #0
2018.10.09 08:45:42.627 test_isNewDayInOnTick GBPUSD,M1: test_isNewDayInOnTick.mq4: Актуальное время открытия текущей недели = 2018.10.08 00:00. Ошибка #0
2018.10.09 08:45:42.627 test_isNewDayInOnTick GBPUSD,M1: test_isNewDayInOnTick.mq4: Время открытия недельного бара = 2018.10.07 00:00. Ошибка #0
2018.10.09 08:45:41.479 test_isNewDayInOnTick GBPUSD,M1: initialized

2018.10.09 08:45:40.822	GBPUSD,M1: CheckCurrentHourOpenTime: Время открытия текущего часа = 2018.10.08 11:00
2018.10.09 08:45:40.822	GBPUSD,M1: CheckCurrentDayOpenTime: Время открытия текущего дня = 2018.10.08 00:00
2018.10.09 08:45:40.822	GBPUSD,M1: CheckCurrentWeekOpenTime: Время открытия текущей недели = 2018.10.08 00:00
2018.10.09 08:45:40.064	GBPUSD,M1: initialized

2018.10.09 08:45:40.022 Expert Other\test_isNewDayInOnTick GBPUSD,M1: loaded successfully

Cosa vediamo. Vediamo che tutto va bene. Tutto caricato, e notate che non ci sono errori, i dati sono immediatamente aggiornati! La domanda principale è perché i dati GMT possono essere ottenuti normalmente, mentre l'indicatore dovrebbe "giocare con i diamanti"? I programmi non dovrebbero funzionare allo stesso modo? Perché lo stesso codice funziona diversamente in un indicatore e in un Expert Advisor? Questo non dovrebbe essere il caso.

 
Alexey Kozitsyn:

E qui, a proposito, c'è un altro argomento a favore del verificarsi di un errore. È l'ERRORE nel calcolo dell'indicatore! Ho scritto un Expert Advisor:

Viene eseguito dallo stesso grafico dell'indicatore. Vediamo i risultati:

Cosa vediamo. Vediamo che tutto va bene. Tutto caricato, e notate che non ci sono errori, i dati sono immediatamente aggiornati! La domanda principale è perché i dati GMT possono essere ottenuti normalmente, mentre l'indicatore dovrebbe "giocare con i diamanti"? I programmi non dovrebbero funzionare allo stesso modo? Perché lo stesso codice funziona diversamente in un indicatore e in un Expert Advisor? Questo non dovrebbe essere il caso.

Tutti gli indicatori sono in un unico thread, e nulla di nuovo accadrà fino alla fine del flusso (in effetti, fino alla prossima chiamata di OpsulCalcuter). Expert Advisor è in un proprio thread separato, quindi quando si avvia, gli è permesso di posticipare il suo avvio per gli aggiornamenti dei dati, aggiornare i dati - tutto il resto nel terminale non è influenzato. È così dalla nascita e non c'è modo di sistemarlo, dato che l'ambiente metatrader4 è stato sepolto.

 
Unicornis:

Poiché spetta al terminale connettersi e fare qualcosa con il caricamento, il controllo, ecc., tutti gli indicatori sono in un thread, e nulla di nuovo accade fino a quando tutto nel thread finisce (in effetti, fino alla prossima chiamata a OpCalculate), cioè essendo in questo thread, non otterrete comunque nulla di più veloce della fine del thread. Expert Advisor è in un proprio thread separato, quindi quando si avvia, gli è permesso di posticipare il suo avvio per gli aggiornamenti dei dati, aggiornare i dati - tutto il resto nel terminale non è influenzato. È così dalla nascita e non c'è modo di sistemarlo, perché l'ambiente metatrader4 è stato sepolto.

Sono consapevole del fatto che tutti gli indicatori di un simbolo sono in un unico thread mentre ogni esperto ha il proprio thread. Ma non è questo il caso. Gli sviluppatori sono gli stessi che correggono gli errori nelle loro creazioni. I programmi non dovrebbero funzionare diversamente! Se gli indicatori hanno mancato qualcosa, è un errore e non c'è problema. L'Expert Advisor ha in qualche modo ricevuto i dati corretti senza errori! Quindi possiamo implementarlo. @Slava, puoi dare la tua opinione sul fatto che il comportamento palesemente errato sarà corretto? O, almeno, l'aggiunta di documentazione (che con prev_calculated = 0 non si possono ottenere dati corretti di TFs senior)?

 
Alexey Kozitsyn:

Sì, sono consapevole che tutti gli indicatori di un simbolo sono in un thread, e un thread diverso è assegnato ad ogni esperto. Ma non è questo il caso. Gli sviluppatori sono quelli che correggono gli errori nelle loro creazioni. I programmi non dovrebbero funzionare diversamente! Se gli indicatori hanno mancato qualcosa, è un errore e non c'è nessun problema. L'Expert Advisor ha in qualche modo ricevuto i dati corretti senza errori! Quindi possiamo implementarlo. @Slava, puoi dare la tua opinione sul fatto che il comportamento palesemente errato sarà corretto? O almeno, è un'aggiunta alla documentazione (che non possiamo ottenere dati corretti di alto TF quando prev_calculated = 0)?

La documentazione dice che Expert Advisor ha fino a 5 secondi prima di iniziare a ricevere dati e durante questo tempo il terminale cerca di ricevere dati per l'Expert Advisor. L'indicatore non ha questa possibilità e allo stesso modo non dovrebbe richiedere l'aggiornamento della cronologia, non è fondamentale per esso, se è fondamentale, allora deve essere calcolato in un Expert Advisor. L'idea principale è che la situazione desiderata non è possibile nell'implementazione attuale. Fondamentalmente, i TF sono timer e ci sono periodi in cui questi timer multipli coincidono in un momento - questo è un processo sincrono al 100% coincidente (eccetto il tempo di apertura/chiusura), perché il primo tick del minuto del TF corrente coincide con il primo minuto di cinque minuti, ora, ecc. - è solo scrivere lo stesso valore in diverse variabili, ed è logico impostare un insieme di TF necessari e ottenere tutti i dati necessari in una sola volta. Perché gli sviluppatori hanno fatto così e non viceversa, non lo so. Forse, non può (non vuole) essere fatto nel modello di funzionamento del terminale esistente a causa della divisione client-server, poiché se ora permettiamo agli esperti di usare gli indicatori, questi impicceranno il terminale.

Potete vedere alla fine, se vi interessa, come funziona l'indicatore call, l'indicatore chiama un altro indicatore, expert(_asktfexp) chiama indicator(_asktf_sample) che chiama indicator(_asktf). Quando si chiama un indicatore da un esperto, il timer nell'indicatore non partirà, quindi le soluzioni con un timer nell'indicatore sono solo per i casi in cui questo indicatore rimarrà sospeso sul grafico e non sarà chiamato (il che è logico in generale).

File: