Quelqu'un sait-il comment développer un indicateur multi-devises ?

 
Quelqu'un sait-il comment développer un indicateur multidevises?

Je veux choisir entre 1 et 10 devises différentes et 5 barres pour chaque devise.

Mais je ne sais pas comment faire.

 

Dans un indicateur standard, vous construisez les tableaux tampons avec les données des paramètres envoyés par la fonction événement OnCalulate( ... ). Mais, pour les devises et/ou les cadres temporels multiples, vous devrez utiliser l'une des deux solutions suivantes :

  • Utiliser l'ancienne méthode des variations de "iFunction", comme iTime(), iVolume, iOpen, iClose, etc. mais avec un symbole différent comme "EURUSD", "JPYUSD", etc. au lieu du symbole par défaut _Symbol ou Symbol().
  • En utilisant la nouvelle méthode de la première variante de la fonction ArrayCopyRates() avec des pointeurs de tableaux de MqlRates. Les tableaux "copiés" ne prendront pas réellement de place et seront juste des pointeurs vers les données existantes des différents symboles et échéances.

Cependant, pour que cela fonctionne, l'une des deux conditions suivantes doit être remplie pour que le multi-symbole et/ou le multi-trame de temps fonctionne :

  • Soit les graphiques respectifs des symboles et des périodes de temps sont déjà ouverts, de sorte qu'aucune erreur n'est générée,
  • sinon vous obtiendrez une erreur 4066 (ERR_HISTORY_WILL_UPDATED) la première fois que vous demanderez les données, et vous devrez coder une boucle sleep & retry, afin d'attendre que les données soient téléchargées et ensuite demander les données à nouveau.

La solution que je propose personnellement, et que je trouve la plus efficace et la plus simple pour gérer l'erreur 4066, est la méthode ArrayCopyRates() et MqlRates .

Vous trouverez plus d'informations à ce sujet dans la documentation et les fichiers d'aide de MQL4.

PS ! NB ! Lorsque vous accédez aux fonctions d'indicateur intégrées, telles que iMA(), iATR(), etc. pour les différents symboles et périodes, n'oubliez pas d'implémenter également les boucles sleep et retry afin de ne pas obtenir l'erreur 4066. Voici un extrait de la documentation de MQL4 :

Any indicator can be calculated on the data of not only current chart, but also on the data of any available symbol/period. If data (symbol name and/or timeframe differ from the current ones) are requested from another chart, the situation is possible that the corresponding chart was not opened in the client terminal and the necessary data must be requested from the server. In this case, error ERR_HISTORY_WILL_UPDATED (4066 - the requested history data are under updating) will be placed in the last_error variable, and one will has to re-request (see example of ArrayCopySeries())
 
N'oubliez pas que l'OP pose une question sur un indicateur. Sleep() est ignoré dans les indicateurs
 
GumRai:
N'oubliez pas que l'OP pose des questions sur un indicateur. Sleep() est ignoré dans les indicateurs

Désolé, je ne le savais pas ! J'utilise cette méthode assez largement dans les EA mais pas dans les Indicateurs, donc je ne connaissais pas le handicap du sommeil.

Dans ce cas, il devra construire une boucle de réessai autour des appels successifs à chaque tick de la fonction OnCalculate() (où l'utilisation de ArrayCopyRates() est la meilleure solution).

Alternativement, si cela fonctionne dans la fonction OnInit(), cela pourrait être la méthode préférée de préparation des données pour l'indicateur, avec un très long nombre de réessais (sans le sleep) pour ce cas.

 
FMIC:

...

  • ou vous obtiendrez une erreur 4066 (ERR_HISTORY_WILL_UPDATED) la première fois que vous demanderez les données, et vous devrez coder une boucle sleep & retry, afin d'attendre que les données soient téléchargées et ensuite demander les données à nouveau.

PS ! NB ! Lorsque vous accédez aux fonctions d'indicateurs intégrées, telles que iMA(), iATR(), etc. pour les différents symboles et périodes de temps, n'oubliez pas d'implémenter également les boucles sleep et retry afin d'éviter l'erreur 4066. Voici un extrait de la documentation de MQL4 :


À moins qu'ils n'aient changé quelque chose récemment, vous obtiendrez l'erreur 4066 à chaque fois dès le premier appel de la fonction (et seulement à partir de ce premier appel), indépendamment des conditions ou de la progression de la mise à jour de l'historique. Cela n'a aucune utilité pratique.
 
Ovo:
À moins qu'ils n'aient changé quelque chose récemment, vous obtiendrez l'erreur 4066 à chaque fois dès le premier appel de la fonction (et seulement à partir de ce premier appel), quelles que soient les conditions ou la progression de la mise à jour de l'historique. Cela n'a aucune utilité pratique.
Cela n'a pas été le cas pour moi. Lorsque les données sont déjà entièrement disponibles, je n'obtiens pas l'erreur 4066. Cependant, si elles ne sont pas directement disponibles, alors oui, j'obtiens l'erreur uniquement lors du premier appel de n'importe quelle fonction pour ce symbole et ce time.frame particuliers. Après cela, toute autre fonction qui demande ces données ne donne plus l'erreur.
 

FMIC:

Dans ce cas, il devra construire une boucle de réessai autour des appels successifs à chaque tick de la fonction OnCalculate() (où l'utilisation de ArrayCopyRates() est la meilleure solution).

Sinon, si cela fonctionne dans la fonction OnInit(), cela pourrait être la méthode préférée de préparation des données pour l'indicateur, avec un compte de réessais très long (sans le sleep) pour ce cas.

  1. Une boucle (longue ou autre) dans l'indicateur ne fonctionnera pas. Pendant que l'indicateur fonctionne, rien d'autre ne peut se produire dans le terminal. C'est pourquoi Sleep ne peut pas fonctionner dans les indicateurs. Et pourquoi ArrayCopyRates est asynchrone (pour les indicateurs).
  2. Activez le tableau des taux dans init. Testez-le dans OnTick, et gérez les tentatives à cet endroit. N'oubliez pas non plus que les différents graphiques créent de nouvelles barres à des moments différents.
    string pairs[] = {"EURUSD", "GBPUSD" ...}
    MqlRates pair0[], pair1[], ...
    bool initial;
    OnInit(){ initial=true;
       ArrayCopyRates(pair0, pairs[0], _Period);   
       ArrayCopyRates(pair1, pairs[1], _Period);
       :
    }
    OnCalculate( ... ){
       int count = IndicatorCounted();
       if(initial){
          if(pair1[0].time == 0) return;
          if(pair2[0].time == 0) return;
          :
          initial=false; count = 0; // process all bars
       }
       for(int i = Bars - 1 - MathMax(lookback, count); i >= 0; --i){
          int shift0 = iBarsShift(pairs[0], _Period, Time[i]);
          int shift1 = iBarsShift(pairs[1], _Period, Time[i]);
          buffer[i] = pair0[shift0].close - pair1[shift1].close;

  3. Si vous ne voulez pas utiliser ArrayCopyRates vous n'êtes pas obligé, mais vous devez quand même charger les autres paires en remplaçant [dans le if(initial)] la paireN[0].time par iTime().
 
   if(pair1[0].time == 0) return;

Cela ne sera jamais vrai.

S'il existe un historique chargé pour le symbole et la période, la fonction récupère la valeur la plus récente.

S'il n'y a pas d'historique chargé, vous obtiendrez une erreur de type Array out of range.

Même chose pour iTime, etc.

 
GumRai:

Cela ne sera jamais vrai.

S'il existe un historique chargé pour le symbole et la période, la fonction récupère la valeur la plus récente.

S'il n'y a pas d'historique chargé, vous obtiendrez une erreur de type Array out of range.

Même chose avec iTime, etc.

Je suis plutôt d'accord !

Personnellement, je vérifie juste la valeur de retour de "ArrayCopyRates()" et après cela je garde juste la trace de la taille du tableau avant d'accéder aux données du tableau.

En ce qui concerne "iTime()" et d'autres fonctions de ce type, je vérifie toujours d'abord "iBars()".

 
GumRai:

Cela ne sera jamais vrai.

  if(pair1[0].time == 0) return;

S'il existe un historique chargé pour le symbole et la période, la fonction récupère la valeur la plus récente.

Si aucun historique n'est chargé, vous obtiendrez une erreur de type Array out of range.

Même chose avec iTime etc.

Il existe de nombreux exemples historiques (avant la construction de 600) de consultation d'un ACR. Il n'y a pas d'autre moyen de le faire. Les appels ultérieurs à ACR ou iTime ne renverront PAS 4066, donc comment pouvez-vous savoir si les données ont été téléchargées.

iTime a toujours renvoyé zéro en cas d'erreur.

 
WHRoeder:

Il existe de nombreux exemples historiques (pré-build 600) de vérification d'un ACR. Il n'y a pas d'autre moyen de le faire. Les appels ultérieurs à ACR ou iTime ne renverront PAS 4066, donc comment pouvez-vous savoir si les données ont été téléchargées.

iTime a toujours renvoyé zéro en cas d'erreur.

Que voulez-vous dire par "il n'y a pas d'autre moyen de le faire" ?

Vérifier le nombre de retours de "ArrayCopyRates", et vérifier la taille du tableau, semble être une méthode de vérification plus robuste que de faire "pair1[0].time == 0" qui peut facilement retourner uneerreur "Array index is out of range".

EDIT : J'ai supprimé certaines de mes déclarations après avoir relu votre message de plus près.