Caractéristiques du langage mql5, subtilités et techniques - page 31

 
Artyom Trishkin:

Avez-vous au moins regardé le code que je vous montre ? Tu l'as fait fonctionner ?

Je ne demandais pas comment remplir le tampon de l'indicateur, mais pourquoi des valeurs vides sont retournées si je prends des valeurs de l'AO et non de la barre actuelle.
J'ai compris - il n'y a pas d'historique, il est en train de se charger, et pendant qu'il se charge, AO d'une période non native renvoie l'erreur "pas de données".

Je veux vérifier si l'historique est entièrement chargé afin de ne pas entrer dans le cycle des indicateurs.

Si vous utilisez CopyBuffer dans l'indicateur pour recevoir des données d'un autre indicateur, vous devez :

  1. Retournez votre tampon d'indicateur de façon à ce que la barre la plus à droite du graphique corresponde à l'indice "0" dans le tampon d'indicateur.
  2. Ainsi, "la barre actuelle" dans l'indicateur "iMTF_AO.mq5" sera la BARRE LA PLUS A DROITE du graphique, et elle correspondra à l'indice "0" dans le tampon de l'indicateur "Buffer[]".
  3. Et pour obtenir la "barre courante" de l'indicateur (CopyBuffer(handle,0,shift,1,array)) le paramètre "shift" doit être égal à "0".

Si vous ne voulez pas retourner le tampon de l'indicateur, faites ceci (temporairement) : AO(0) - pour comprendre comment obtenir les valeurs d'un autre indicateur à partir d'un INDICATEUR. Vous pouvez obtenir une erreur une ou deux fois, mais c'est jusqu'à ce que la série chronologique soit construite, et alors les valeurs seront stables.

 
Artyom Trishkin:
Vous avez vu ma réponse ? L'avez-vous essayé ?
 
Vladimir Karputov:

Si vous utilisez CopyBuffer dans un indicateur pour récupérer les données d'un autre indicateur, vous devez :

  1. Inversez votre tampon d'indicateur de sorte que la barre la plus à droite du graphique corresponde à l'indice "0" dans le tampon d'indicateur.
  2. Ainsi, "la barre actuelle" dans l'indicateur "iMTF_AO.mq5" sera la BARRE LA PLUS A DROITE du graphique, et elle correspondra à l'indice "0" dans le tampon de l'indicateur "Buffer[]".
  3. Et pour obtenir la "barre courante" de l'indicateur (CopyBuffer(handle,0,shift,1,array)) le paramètre "shift" doit être égal à "0".

Si vous ne voulez pas retourner le tampon de l'indicateur, faites ceci (temporairement) : AO(0) - pour comprendre comment obtenir les valeurs d'un autre indicateur à partir d'un INDICATEUR. Il se peut que vous obteniez une erreur une ou deux fois, mais c'est jusqu'à ce qu'une série chronologique soit construite et que les valeurs soient cohérentes.

1. Mon code l'a, et il était là tout de suite :

   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. c'est le cas.

3. Le décalage est égal à l'indice de cycle i. Et la boucle va du début des données historiques (rates_total-1) à la fin (aux données actuelles)

Une autre question est de savoir si nous devons calculer ces données par rapport à un TF non natif afin de ne pas obtenir des données de barres manquantes. Et nous devons déterminer avant le cycle que l'histoire du TF souhaité est entièrement synchronisée.

 
Artyom Trishkin:

1. Mon code l'a, et l'a eu tout de suite :

2. c'est comme ça.

3. Le décalage est égal à l'indice de cycle i. Et la boucle va du début des données historiques (rates_total-1) à la fin (aux données actuelles)

Un autre problème est que nous devons calculer ces données par rapport à une période de temps non native afin de ne pas obtenir de données à partir de barres manquantes. Et nous devons déterminer avant la boucle que l'histoire de la période nécessaire est complètement synchronisée.


Retravailler la boucle pour appeler AO : put de "0" à une certaine valeur (maintenant d'une certaine valeur à zéro). Lorsque les erreurs se produisent - comparez en une seule fois : le nombre de barres calculées ("limit_p") et les taux_total de l'indicateur actuel.


Ajouté : et ici ces lignes effacent tous les efforts de calcul de la "limite" (si nous nous référons à la période non native) :

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

En gros, au début (lors de l'accès à une période non native), "limit" était égal à 156, mais en dessous de BACK ! et "limit" est devenu "1545666666".



 
Alexey Kozitsyn:
Avez-vous essayé la synchronisation ? Les développeurs conseillent également de maintenir à jour les données du TF/symbole requis par le biais du timer.

Non, je ne l'ai pas encore essayé. J'ai vu le support de la pertinence des données, je me souviens - je sais.

Mais initialement, il est nécessaire de quitter OnCalculate() si les données de la date spécifiée et de la date actuelle ne sont pas encore synchronisées.

Je comprends pour l'actuel :

if(rates_total<1) return(0);

A propos de donné - il est nécessaire de vérifier ses Bars() - leur nombre au lieu de taux_total.

Mais je ne sais pas ce qu'il en est de la limite - elle peut être vérifiée sur le cadre temporel actuel (comme un exemple d'un autre indicateur) :

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

Mais dans cet indicateur de test, nous obtenons des données à la fois de la période actuelle (il montre les calculs dans OnCalculate()) et de la période spécifiée - pour obtenir les données AO de la période spécifiée.

Je ne me souviens toujours pas comment calculer toutes les données nécessaires pour le nombre de barres - parce que la boucle devrait commencer par la barre correspondant à l'heure de la barre d'historique avec la première donnée existante de la barre actuelle ou spécifiée - si elle est inférieure - à partir de cette barre nous commençons la boucle. La limite doit également être correctement calculée pour détecter l'apparition d'une nouvelle barre, ce qui doit conduire à un recalcul complet ou à un recalcul de la barre actuelle uniquement (en fonction de ce qui s'est passé - l'ouverture d'une nouvelle barre ou le chargement de l'historique).

Peut-être que j'essaie de penser à tout en même temps, et que je pense à des choses inutiles...

 
Vladimir Karputov:


Retravailler l'appel de la boucle à AO : mettre de "0" et à une certaine valeur (maintenant d'une certaine valeur à zéro). Lorsque des erreurs se produisent - comparez en une seule fois : le nombre de barres calculées ("limit_p") et les taux_total de l'indicateur actuel.


Ajouté : et ces lignes effacent tous les efforts de la "limite" calculée (si l'on se réfère à une période non native):

en gros, au début (lorsqu'on s'adresse à un temps non natif) "limite" est devenu 156, et en dessous de BATCH ! et "limite" est déjà devenu "1545666666".

Oui, j'ai écrit tout de suite que je me suis planté ici en vitesse.

Mais je ne changerai pas la boucle - il y a un indicateur assez complexe dans lequel tout est construit sur le calcul de l'historique du début à la fin - il est plus facile de recalculer les limites et d'obtenir les données que de réécrire l'indicateur entier - toute sa logique.

 
Artyom Trishkin:

Non, je ne l'ai pas encore essayé. J'ai vu le support de la pertinence des données, je me souviens - je sais.

Mais initialement, il est nécessaire de quitter OnCalculate() si les données de la période spécifiée et de la période actuelle ne sont pas encore synchronisées.

L'actuel est clair :

Ce n'est pas tout à fait ça. Lorsque vous chargez initialement le terminal avec l'indicateur, vous risquez de ne pas obtenir ce que vous attendez. Pendant la journée et s'il y a des interruptions de connexion - il peut y avoir des erreurs aussi.

A propos de la sortie de OnCalculate() : La première requête Bars() devrait être faite au stade de l'initialisation, puis dans OnCalculate() vérifier la synchronisation des TF actuels et nécessaires. S'il n'y a pas de synchronisation, quittez.

 
Artyom Trishkin:

Oui, c'est ce que j'ai dit tout de suite, que j'ai fait une erreur en vitesse.

Je ne veux pas changer la boucle, il y a un indicateur assez compliqué, qui est basé sur le calcul de l'historique du début à la fin - il est plus facile de recalculer les limites et de recevoir les données correctement, que de réécrire l'indicateur entier - toute sa logique.

Artem, que voulez-vous dire par "du début à la fin" ?

Tu penses que retourner toutes les matrices est la meilleure solution ?

Pourquoi

ArraySetAsSeries(Buffer,true);

si vous ne copiez qu'une seule valeur ?

Lors de la copie d'un TF autre que celui en cours, il est préférable de passer le temps de la mesure nécessaire à la fonction CopyBuffer(). Sinon, il ne copiera pas la barre que vous voulez.

 
Alexey Viktorov:

1. artyom, que voulez-vous dire par "du début à la fin" ?

2. Pensez-vous que retourner toutes les matrices est la meilleure solution ?

3. Pourquoi

4. si vous ne copiez qu'une seule valeur ?

Lorsque l'on copie dans la fonction CopyBuffer() le temps de la barre requise qui n'est pas l'horizon temporel actuel, il est préférable de le passer. Sinon, il ne copiera pas la barre que vous voulez.

1. Le début des données historiques est la toute première barre de l'historique avec le temps d'ouverture le plus court, la fin des données historiques est la barre actuelle.

2. Je copie d'un 4 à un 5.

Eh bien, parce que dans Buffer[] les données sont écrites en boucle de rates_total-1 à 0. Si nous ne le faisons pas comme une série temporelle, il sera affiché en arrière et en avant sur le graphique.

4. Je veux copier une valeur à un moment donné, qui correspond aux données de la barre i d'un cadre temporel donné.

Regardez comment il est laconique et facile d'obtenir les données de pas le timeframe actuel dans mql4. Je me demande comment il est possible de recevoir des données d'indicateur dans mql5 et cela ne fonctionne pas - il y a toujours l'erreur 4806 si je passe le timeframe qui ne correspond pas au timeframe du graphique dans lequel l'indicateur travaille dans la fonction de réception des données 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]);
}
//+------------------------------------------------------------------+

En même temps, le handle de l'indicateur est créé dans OnInit() qui correspond au prix actuel à partir duquel nous voulons recevoir les données :

handle_ao=iAO(symbol,periodForWork);

C'est-à-dire qu'à tout moment, quelle que soit la façon dont nous changeons le f, la poignée est créée avec le f nécessaire (sélectionné dans les paramètres). Mais les données AO ne peuvent être obtenues que si la fonction sélectionnée dans les réglages et la fonction courante coïncident. Si elles ne coïncident pas, la fonction renvoie toujours zéro.

La question est : POURQUOI ?

 
Artyom Trishkin:

1. Le début des données historiques est la toute première barre de l'historique avec le temps d'ouverture le plus court, la fin des données historiques est la barre actuelle.

2. Je réécris de quatre à cinq.

Eh bien, parce que dans Buffer[] les données sont écrites en boucle de rates_total-1 à 0. Si nous ne le faisons pas comme une série temporelle, il sera affiché en arrière et en avant sur le graphique.

4. Je copie une valeur à la fois qui correspond aux données de la barre i du cadre temporel donné.

Regardez comme il est laconique et facile de recevoir des données qui ne sont pas du cadre temporel actuel dans mql4. Je me demande comment il est possible de recevoir des données d'indicateur dans mql5 et cela ne fonctionne pas - il y a toujours l'erreur 4806 si je passe le timeframe qui ne correspond pas au timeframe du graphique dans lequel l'indicateur travaille dans la fonction de réception des données AO.

En même temps, le handle de l'indicateur est créé dans OnInit() qui correspond au prix actuel à partir duquel nous voulons recevoir les données :

C'est-à-dire qu'à tout moment, quelle que soit la façon dont nous changeons le f, la poignée est créée avec le f nécessaire (sélectionné dans les paramètres). Mais les données AO ne peuvent être obtenues que si la fonction sélectionnée dans les réglages et la fonction courante coïncident. S'ils ne correspondent pas, la fonction renvoie toujours zéro.

La question : POURQUOI ?

1. Juste une clarification. Je comprends maintenant que nous parlons de la même chose.

Je le comprends, mais je ne suis pas d'accord pour dire qu'il est nécessaire d'inverser les tableaux. Est-il nécessaire d'avoir un indicateur pour deux terminaux ? C'est presque comme faire 2en1 une faux et une hache.

3. Si je comprends bien, Buffer[] est utilisé par le récepteur dans la fonction CopyBuffer() pour obtenir une seule valeur d'indicateur.

4. Vous n'avez pas fait attention à la chose la plus importante. Le début de la copie de la valeur de l'indicateur ne doit pas être déterminé par l'indice de la barre, mais par le moment de la i-ème barre.

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