[Erreur dans la récupération de l'heure du senior TF dans le chronomètre ! - page 15

 
Taras Slobodyanik:

Votre indicateur ne suit pas la mise à jour des données.
De nouvelles barres arrivent du courtier et vous ne les vérifiez pas.
J'ai ajouté quelques lignes pour montrer que lorsque vous vérifiez, tout s'affiche correctement.

C'est une situation de travail - vérifier le nouveau bar.

Tu ne le dis pas ! Qu'est-ce qui te fait croire que je dois suivre les nouveaux bars ? Est-ce que c'est écrit dans la documentation ? Je veux dire que je DOIS obtenir la valeur de la fonction, et ensuite je dois nécessairement la comparer avec la valeur précédente ? Il existe une fonction, la fonction est conçue pour fonctionner avec des délais élevés. La fonction peut renvoyer une erreur si elle n'a pas de données, ou renvoyer une valeur incorrecte (égale à 0 dans ce cas). C'est tout. Les programmeurs ne doivent rien faire pour obtenir une valeur 100% correcte.

Mais regardez ce que j'ai trouvé dans la documentation de SeriesInfoInteger() :

Pour obtenir plus d'informations sur l'erreur, vous devez appeler la fonction GetLastError().

Voyez-vous GetLastError() dans mon code ? Voici le chèque. Ce contrôle doit être nécessaire et VRAIMENT nécessaire ! Toutes les autres solutions sont des béquilles.
 
Alexey Kozitsyn:

Et vous regardez mon tout premier message. Voyez-vous l'erreur 4066 ? Ensuite, l'erreur 0 et le retour de données incorrectes. Pourquoi la fonction (dans ce cas, SeriesInfoInteger()) ne vérifie-t-elle pas la pertinence avant d'envoyer les données ? Pourquoi ne met-il pas le drapeau d'erreur ? Vous voyez, je préfère attendre un peu plus longtemps pour que les contrôles internes passent plutôt que de chercher des erreurs plus tard.

Mais après cela, on m'a donné beaucoup de conseils, avec lesquels je n'ai jamais obtenu de résultat. Et il s'est avéré que ce n'était même pas à propos de la minuterie.

Ok, lisez l'aide)

SeriesInfoInteger

Renvoie des informations sur l'état des données historiques.

Le mot historique signifie quoi ?
Si l'historique est chargé - il n'y a pas d'erreur.


Alexey Kozitsyn:

Pas question ! Et qu'est-ce qui vous fait penser que je devrais nécessairement suivre de nouvelles barres ? Est-ce que c'est écrit dans la documentation ? Je veux dire que je DOIS obtenir la valeur de la fonction, et ensuite je dois nécessairement la comparer avec la précédente ? Il existe une fonction, la fonction est conçue pour fonctionner avec des délais élevés. La fonction peut renvoyer une erreur si elle n'a pas de données, ou renvoyer une valeur incorrecte (égale à 0 dans ce cas). C'est tout. Les programmeurs ne doivent rien faire pour obtenir une valeur 100% correcte.

Mais regardez ce que j'ai trouvé dans la documentation de SeriesInfoInteger() :

Dans mon code voir GetLastError() ? Voici un contrôle. Ce contrôle doit être nécessaire et réel ! Toutes les autres solutions sont des béquilles.

Vous n'avez rien à faire).
...le courtier vous envoie des données actualisées - si vous voulez, utilisez-les pour le calcul, sinon - pas de problème, utilisez l'historique existant).


ps. c'est le week-end, le marché est fermé, vous avez des données incorrectes dans votre terminal !
et il n'y a pas d'erreur ! !!)

 
Taras Slobodyanik:

ok, lisez l'aide)

Que signifie le mot "histoire" ?
Si l'historique est chargé - il n'y a pas d'erreur.


Vous ne devez rien).
...le courtier vous envoie des données actualisées - si vous voulez les utiliser pour calculer, sinon - pas de problème, utilisez l'historique)

Chaque tique qui entre dans le terminal est déjà une histoire. Et je veux obtenir ses valeurs réelles ou son erreur. Si cela vous convient - ok.

 
Alexey Kozitsyn:

Chaque tique qui entre dans le terminal est déjà une histoire. Et je veux recevoir ses valeurs réelles ou son erreur. Si cela vous convient, c'est bien.

Oui, l'historique est ce qui a déjà été téléchargé ou ce qui est en cours de téléchargement dans le passé.
Et ce qui est mis à jour seulement maintenant (après la dernière citation) n'est pas l'histoire, ce sont les nouvelles données brutes.

 
Taras Slobodyanik:

Vérifiez le temps des bougies, pas le calcul des barres.
C'est ainsi qu'il sera mis à jour correctement (coché).

Taras, voici le résultat de votre code :

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, voici le résultat de votre code :

Oui, c'est le premier tic, celui qui produit l'histoire finie, celle qui est disponible.
Après ce tick (s'il y a de nouvelles barres), vient immédiatement le second tick, dans lequel mon code met à jour vos variables et elles montrent les données correctes.

ps. vous pouvez insérer votre propre fonction pour vérifier la nouvelle barre, ce sera la même chose.

Moi-même, je vérifie constamment le nombre de barres, si le nombre a changé de plus de 1, cela signifie que vous devez tout recalculer à nouveau, si le nombre a changé de 1, cela signifie juste une nouvelle barre. Et je ne vérifie que les erreurs les plus critiques, et je ne vois pas cette erreur de retard.

 
Taras Slobodyanik:

Oui, c'est la première coche, celle qui donne l'historique prêt.
Après ce tick (s'il y a de nouvelles barres), vient immédiatement le second tick, dans lequel mon code met à jour vos variables et elles montrent les données correctes.

Si le nombre a changé de plus de 1, il s'agit d'une nouvelle barre.

Moi-même, je vérifie constamment le nombre de barres, si le nombre a changé de plus de 1, cela signifie que vous devez tout recalculer à nouveau, si le nombre a changé de 1, cela signifie juste une nouvelle barre. Et je ne vérifie que les erreurs les plus critiques, et je ne vois pas cette erreur de retard.

Et voici, d'ailleurs, un autre argument en faveur de la survenue de l'erreur. C'est une ERREUR de calcul dans l'indicateur ! J'ai écrit un conseiller expert :

#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 );
  }
//+------------------------------------------------------------------+

S'exécute sur le même graphique que l'indicateur. Voyons les résultats :

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

Ce que nous voyons. Nous voyons que tout va bien. Tout est chargé, et notez qu'il n'y a pas d'erreurs, les données sont immédiatement mises à jour ! La question principale est de savoir pourquoi les données GMT peuvent être obtenues normalement, alors que l'indicateur doit "jouer avec des diamants" ? Les programmes ne devraient-ils pas fonctionner de la même manière ? Pourquoi le même code fonctionne différemment dans un indicateur et dans un Expert Advisor ? Cela ne devrait pas être le cas.

 
Alexey Kozitsyn:

Et voici, d'ailleurs, un autre argument en faveur de la survenue d'une erreur. C'est l'ERREUR dans le calcul de l'indicateur ! J'ai écrit un conseiller expert :

S'exécute sur le même graphique que l'indicateur. Voyons les résultats :

Ce que nous voyons. Nous voyons que tout va bien. Tout est chargé, et notez qu'il n'y a pas d'erreurs, les données sont immédiatement mises à jour ! La question principale est de savoir pourquoi les données GMT peuvent être obtenues normalement, alors que l'indicateur doit "jouer avec des diamants" ? Les programmes ne devraient-ils pas fonctionner de la même manière ? Pourquoi le même code fonctionne différemment dans un indicateur et dans un Expert Advisor ? Cela ne devrait pas être le cas.

Tous les indicateurs sont dans un seul thread, et rien de nouveau ne se produira jusqu'à la fin du flux (en fait, jusqu'au prochain appel d'OpsulCalcuter). L'Expert Advisor est dans son propre thread séparé, donc quand il démarre, il est autorisé à reporter son démarrage pour les mises à jour des données, mettre à jour les données - tout le reste dans le terminal n'est pas affecté. C'est comme ça depuis la naissance et il n'y a aucun moyen de le réparer, car l'environnement metatrader4 a été enterré.

 
Unicornis:

Parce que c'est au terminal de se connecter et de faire quelque chose avec le chargement, la vérification, etc., tous les indicateurs sont dans un thread, et rien de nouveau ne se produit jusqu'à ce que tout dans le thread se termine (en fait, jusqu'au prochain appel de OpCalculate), c'est-à-dire qu'en étant dans ce thread, vous n'obtiendrez rien plus vite que la fin du thread de toute façon. L'Expert Advisor est dans son propre thread séparé, donc quand il démarre, il est autorisé à reporter son démarrage pour les mises à jour des données, mettre à jour les données - tout le reste dans le terminal n'est pas affecté. C'est comme ça depuis la naissance et il n'y a aucun moyen de le réparer, car l'environnement metatrader4 a été enterré.

Je suis conscient du fait que tous les indicateurs d'un même symbole se trouvent dans un seul fil, alors que chaque expert a son propre fil. Mais ce n'est pas le cas. Ce sont les développeurs qui corrigent les erreurs dans leurs créations. Les programmes ne devraient pas fonctionner différemment ! Si les indicateurs ont manqué quelque chose, c'est une erreur et il n'y a pas de problème. Le conseiller expert a en quelque sorte reçu les données correctes sans erreur ! Nous pouvons donc le mettre en œuvre. @Slava, pouvez-vous donner votre avis sur le fait que le comportement manifestement erroné sera corrigé ? Ou, au moins, l'ajout de documentation (qu'avec prev_calculated = 0 aucune donnée correcte des TFs seniors ne peut être obtenue) ?

 
Alexey Kozitsyn:

Oui, je suis conscient que tous les indicateurs d'un même symbole sont dans un seul fil, et qu'un fil différent est attribué à chaque expert. Mais ce n'est pas le cas. Ce sont les développeurs qui corrigent les erreurs dans leurs créations. Les programmes ne devraient pas fonctionner différemment ! Si les indicateurs ont manqué quelque chose, c'est une erreur et il n'y a pas de problème. Le conseiller expert a en quelque sorte reçu les données correctes sans erreur ! Nous pouvons donc le mettre en œuvre. @Slava, pouvez-vous donner votre avis sur le fait que le comportement manifestement erroné sera corrigé ? Ou au moins, est-ce un ajout à la documentation (que nous ne pouvons pas obtenir des données correctes de TF élevé lorsque prev_calculated = 0) ?

La documentation indique que le conseiller expert a jusqu'à 5 secondes avant de commencer à recevoir des données et pendant ce temps, le terminal essaie de recevoir des données pour le conseiller expert. L'indicateur n'a pas cette possibilité et de la même façon il ne devrait pas demander le rafraîchissement de l'historique, ce n'est pas critique pour lui, si c'est critique, alors il doit être calculé dans un Expert Advisor. L'idée principale est que la situation souhaitée n'est pas possible dans la mise en œuvre actuelle. Fondamentalement, les TF sont des minuteries et il y a des périodes où ces multiples minuteries coïncident à un moment donné - il s'agit d'un processus synchrone coïncidant à 100 % (à l'exception de l'heure d'ouverture/de fermeture), car le premier tick de la minute du TF actuel coïncide avec la première minute des cinq minutes, de l'heure, etc. - il s'agit simplement d'écrire la même valeur dans plusieurs variables, et il est logique de définir un ensemble de TF nécessaires et d'obtenir toutes les données nécessaires en une seule fois. Je ne sais pas pourquoi les développeurs l'ont fait et pas l'inverse. Peut-être que cela ne peut pas (ne veut pas) se faire dans le modèle actuel de fonctionnement des terminaux à cause de la division client-serveur, car si nous permettons maintenant aux experts d'utiliser les indicateurs, ils accrocheront le terminal.

Vous pourrez voir en fin de journée, si cela vous intéresse, comment fonctionne l'appel d'indicateur, l'indicateur appelle un autre indicateur, l'expert(_asktfexp) appelle l'indicateur(_asktf_sample) appelle l'indicateur(_asktf). Lorsqu'on appelle un indicateur à partir d'un expert, la minuterie de l'indicateur ne démarrera pas, donc les solutions avec une minuterie dans l'indicateur ne sont que pour les cas où cet indicateur sera seulement suspendu sur le graphique et ne sera pas appelé (ce qui est logique en général).

Dossiers :