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

 
Vitaly Gorbunov:
La méthode iBarShift vous permet de trouver des trous dans l'historique, mais vous devez vérifier l'historique à intervalles réguliers. J'ai écrit une procédure pour moi-même qui fait cela, et après cela, j'ai oublié les lacunes des programmes MtF.
Il ne s'agissait pas de détecter des "trous". La personne voulait obtenir la dernière mesure de l'historique. Et ce n'est pas nécessairement la mesure actuelle dans le temps.
 
Vitaly Gorbunov:
Les données sont chargées avec l'erreur 4066, et alors c'est la faute des methaquotovs, très probablement les données reçues sont traitées pour cette situation, et l'erreur n'a pas été inventée. Et jusqu'à ce point, tout a un sens.

Si une erreur est "non inventée", cela ne signifie pas qu'elle n'existe pas.

 
Alexey Navoykov:
Il ne s'agit pas de détecter des "trous". La personne voulait obtenir la dernière barre de l'historique. Et ce n'est pas nécessairement la barre de temps actuelle.

Il ne s'agit pas de iBarShift(). Il envoie les mêmes erreurs que iTime() et SeriesInfoInteger(). La béquille ici est de comparer le temps obtenu lors de l'initialisation et de le comparer ensuite avec le temps de la minuterie. C'est ce qui permet d'obtenir les données réelles correctes lors du chargement du terminal, et non IBarShift().

Oui, et si l'heure est 15:00:45 (par exemple), et qu'il n'y a pas encore de tick sur la barre de 15:00 et si l'heure d'ouverture de la barre de la dernière heure est 14:00 - tout est correct, je pense. Et si le système renvoie 13:00 - c'est un problème.

 
Alexey Kozitsyn:

1. Igor, as-tu regardé le code ? Où puis-je obtenir quelque chose dans OnInit() ?

Dans votre cas, un ou plusieurs appels OnTimer sont exécutés juste après OnInit(). Il n'y a pas encore d'événement OnCalculate().

2. Quels contrôles ? Où est-il écrit que l'indicateur doit utiliser OnCalculate() au moins une fois pour fonctionner correctement ?

Ici, nous devons comprendre la logique du terminal. OnInit() est appelé immédiatement lors de la connexion de l'indicateur au graphique. Lors du démarrage du terminal, la connexion de l'indicateur au graphique est effectuée juste après la création de la fenêtre graphique. A ce moment, le terminal n'a même pas encore envoyé la requête au serveur.

Le premier OnCalculate() est appelé après que les cotations disponibles ont été lues localement. Dans certains cas rares, il arrive qu'il n'y ait rien localement. Dans ce cas, en adressant à Time[0], les indicateurs sortent du tableau. Il est donc préférable d'utiliser la fonction iTime ou une fonction similaire.

Le deuxième et le suivant OnCalculate() se produisent au chargement de l'historique ou à l'arrivée des ticks réels.

 
Ihor Herasko:

Le premier OnCalculate() est appelé après la lecture des devis disponibles localement. Dans certains cas rares, il arrive qu'il n'y ait rien localement. Dans ce cas, en se référant à Time[0], les indicateurs sortent du tableau. Par conséquent, il est préférable d'utiliser la fonction iTime ou une fonction similaire.

Je suppose que nous parlons de MQL5, la préparation de l'OHLC y est différente de celle de MT4.

J'écris des indicateurs basés sur un modèle depuis longtemps :

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);
  }

Je n'ai jamais eu de "plantage d'indicateur" sur des tableaux OHLC dans MT4, je pense que MT4 ne lance pas OnCalculate() tant qu'un graphique n'est pas préparé pour la première fois, et si l'historique est chargé, je ne l'ai pas vérifié, mais prev_calculated==0, dans MT5 ce sera comme vous l'avez écrit - vous avez besoin de vérifications supplémentaires pour voir si les données OHLC sont déjà préparées.

 
Ihor Herasko:

Dans votre cas, un ou plusieurs appels OnTimer seront exécutés juste après OnInit(). Il n'y a pas encore d'événement OnCalculate().

Ici, vous devez comprendre la logique du terminal. OnInit() est appelé immédiatement lors de la connexion de l'indicateur au graphique. Lors du démarrage du terminal, la connexion de l'indicateur au graphique est effectuée juste après la création de la fenêtre graphique. A ce moment, le terminal n'a même pas encore envoyé la requête au serveur.

Le premier OnCalculate() est appelé après que les cotations disponibles ont été lues localement. Dans certains cas rares, il arrive qu'il n'y ait rien localement. Dans ce cas, en adressant à Time[0], les indicateurs sortent du tableau. Il est donc préférable d'utiliser la fonction iTime et d'autres fonctions similaires.

Le deuxième et le suivant OnCalculate() se produisent au chargement de l'historique ou à l'arrivée des ticks réels.

Que suggérez-vous pour résoudre le problème (existe-t-il, à votre avis) ? Attendre que OnCalculate() soit appelé 1-2 fois ?

 
Alexey Kozitsyn:

Que suggérez-vous pour résoudre le problème (existe-t-il, à votre avis) ? Attendre que OnCalculate() soit appelé 1-2 fois ?

Vous pouvez essayer decopier la valeurprev_calculated==0dans une variable de la portée globale et voir dans OnTimer() si l'indicateur a été calculé.OnCalculate() - il sera calculé dans tous les cas, je soupçonne que si les données TF n'étaient pas prêtes, alorsreturn(rates_total) renverra 0, qui sera dans le prochain appel deOnCalculate() signeprev_calculated==0, approximativement:

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

vous pouvez essayer decopier la valeurprev_calculated==0dans une variable sur la portée globale et voir dans OnTimer() si l'indicateur a été calculé ; j'ai écrit plus haut que je n'ai jamais vu de bugs avec des calculs incorrects dans MT4.OnCalculate() - il sera calculé de toute façon, je soupçonne que si les données TF n'étaient pas prêtes, alorsreturn(rates_total) retournera 0, ce qui sera dans l'appel suivant deOnCalculate() un signeprev_calculated==0

Il semble que la solution la plus fiable soit vraiment d'attendre l'appel de OnCalculate() avec vérification obligatoire de la connexion au serveur de commerce. Si nous ne vérifions pas la connexion (IsConnected()), nous l'obtiendrons même dans OnCalculate() lorsque le terminal est chargé :

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

Toutefois, il ne supprime pas toutes les questions :

1. Pourquoi n'est-il pas écrit dans la documentation de IsConnected() qu'il doit nécessairement être appelé avant de recevoir des données (au moins) du senior TF dans OnCalculate() ?

2. Pourquoi IsConnected() dans OnTimer() ne fonctionne-t-il pas ? Le fait d'établir une connexion avec un serveur commercial n'est-il pas censé nous indiquer que des données peuvent être obtenues ?

3. Une fois que nous avons établi une connexion avec le serveur commercial et que nous essayons de recevoir des données dans OnTimer(), les fonctions iTime(), iBarShift(), SeriesInfoInteger() et les fonctions similaires ne devraient-elles pas renvoyer des erreurs si les données de ce serveur commercial particulier, dont elles tirent des informations, ne sont pas encore synchronisées ? Sinon, cela ressemble à un non-sens, comme si nous retournions une fois l'erreur 4066 et que nous utilisions ensuite les données présentes comme bon nous semble.

 
Alexey Kozitsyn:

Toutefois, cela ne supprime pas toutes les questions :

1. Pourquoi la documentation de IsConnected() ne dit-elle pas qu'il faut nécessairement l'appeler avant de recevoir des données (au moins) du senior TF dans OnCalculate() ?

2. Pourquoi IsConnected() dans OnTimer() ne fonctionne-t-il pas ? Le fait d'établir une connexion avec un serveur commercial n'est-il pas censé nous indiquer que des données peuvent être obtenues ?

3. Une fois que nous avons établi une connexion avec le serveur de commerce et que nous essayons de recevoir des données dans OnTimer(), les fonctions iTime(), iBarShift(), SeriesInfoInteger() et les fonctions similaires ne devraient-elles pas renvoyer des erreurs si les données de ce serveur de commerce particulier, dont elles tirent des informations, ne sont pas encore synchronisées ? Sinon, cela semble absurde, comme si nous renvoyions une erreur 4066 une fois et que nous traitions ensuite les données existantes comme vous le souhaitez.

1. bon, personne n'a annulé le cas de l'appel de l'indicateur sur les données historiques, si vous avez besoin de travailler en ligne, alors vérifiez la connexion, si non, ou plutôt pas important, alors ma version du modèle fonctionne. Le groupe de fonctions IsConnected() est en fait un peu délicat, elles croisent IsTradeContextBusy() et IsConnected() lui-même parfois et IsTradeAllowed()... Je pense qu'ils se trompent du côté du serveur et déconnectent les terminaux au moment des nouvelles ou de toute autre manipulation.

2,3. fonctionne, mais vous oubliez que GetLastError() va réinitialiser son état après un appel et peut-être que pour mettre à jour l'état GetLastError() doit transférer le contrôle au terminal, peut-être que le terminal n'a pas eu le temps de réinitialiser l'état IsConnected() dans GetLastError() avant votre appel depuis le timer..... Je pense que la fonction OnTimer() n'est pas destinée à recevoir des données : "MQL4 Reference / Status Check - OnTimer() sera appelé, mais les variables de l'environnement du terminal ne sont pas mises à jour, etonCalculate() il est garanti de préparer toutes les données par le terminal quand le tick arrive

 
Igor Makanu:

1. bien, personne n'a annulé le cas de l'appel de l'indicateur sur les données historiques...

2,3. ça marche, mais vous oubliez que GetLastError() va réinitialiser son état après l'appel, et peut-être que pour mettre à jour l'état GetLastError() doit passer le contrôle au terminal, peut-être que le terminal n'a pas le temps de réinitialiser l'état IsConnected() dans GetLastError() avant votre appel depuis timer..... Je pense que la fonction OnTimer() n'est pas destinée à recevoir des données : " La Référence MQL4 / Contrôle d'état - OnTimer() sera appelée, mais les variables de l'environnement du terminal ne sont pas mises à jour, et il est garanti que le terminal préparera toutes les données au moment du tick-OnCalculate().

1. Pensez-vous que si la mesure numéro 0 a une heure incorrecte, le reste de l'histoire aura une heure correcte ?)

2,3. Si les fonctions d'accès aux données n'ont pas le temps de définir une erreur significative, elles doivent la signaler d'une manière ou d'une autre, mais certainement pas en renvoyant le code d'erreur = 0 (aucune erreur). Le reste du "peut-être" est juste une supposition. Et sans preuve, il n'y a rien à dire.

La fonction OnTimer() n'est pas destinée à récupérer des données...

Aucun commentaire.

OnTimer() sera appelé mais les variables d'environnement du terminal ne seront pas nécessairement mises à jour.

A quoi sert l'erreur 4066 ?