Direction d'Indexation dans les Tableaux, les Buffers et les Timeseries

L'indexation par défaut de tous les tableaux et buffers d'un indicateur se fait de gauche à droite. L'indice du premier élément est toujours égal à 0. Le tout premier élément d'un tableau ou du buffer d'un indicateur avec l'indice 0 est donc par défaut à l'extrême gauche, tandis que le tout dernier élément est à l'extrême droite.

Le buffer d'un indicateur est un tableau dynamique d'éléments de double, dont la taille est gérée par le terminal client, afin qu'il corresponde toujours au nombre de barres sur lesquelles l'indicateur est calculé. Un tableau dynamique classique d'éléments de type double est assigné comme buffer de l'indicateur avec la fonction SetIndexBuffer(). Les buffers d'un indicateur ne nécessitent pas de définir leurs tailles avec la fonction ArrayResize() - ceci sera fait par le système d'exécution du terminal.

Les timeseries sont des tableaux avec une indexation inversée, c'est à dire que le premier élément d'une timeserie est à l'extrême droite, et le dernier élément est à l'extrême gauche. Les timeseries étant utilisées pour stocker les historiques des prix et pour contenir les informatiosns sur les heures, nous pouvons dire que les données les plus récentes sont placées à l'extrême droite des timeseries, tandis que les données les plus anciennes sont à l'extrême gauche.

L'élément avec l'indice 0 d'une timeserie contient donc les informations de la dernière cotation d'un symbole. Si une timeserie contient des données d'une période D1, les données encore incomplètes du jour courant sont situées à la position 0, et la position avec l'indice 1 contient les données de la veille.

Changer la Direction d'Indexation

La fonction ArraySetAsSeries() permet de changer la méthode d'accès aux éléments d'un tableau dynamique ; l'ordre physique de stockage des données dans la mémoire de l'ordinateur n'est pas changé. La fonction change simplement la méthode d'adressage des éléments du tableau, afin que lors de la copie d'un tableau dans un autre avec la fonction ArrayCopy(), le contenu du tableau destination ne dépendra pas de la direction d'indexation du tableau source.

La direction d'indexation ne peut pas être changée pour les tableaux distribués de façon statique. Même si un tableau a été passé en paramètre d'une fonction, la tentative de changer la direction d'indexation dans cette fonction n'aura aucun effet.

Pour les buffers d'un indicateur, comme pour les tableaux classiques, la direction d'indexation peut également être définie en arrière (comme pour les timeseries), c'est à dire que la référence à la position 0 dans le buffer de l'indicateur signifiera la dernière valeur du buffer correspondant de l'indicateur et correspondra à la valeur de l'indicateur sur la dernière barre. La localisation physique des barres de l'indicateur restera tout de même inchangée.

Récupérer les Prix dans les Indicateurs

Chaque indicateur personnalisé doit obligatoirement contenir la fonction OnCalculate(), à laquelle les prix nécessaires pour le calcul des valeurs dans les buffers de l'indicateur sont passés. Il est possible de connaître la direction d'indexation de ces tableaux en utilisant la fonction ArrayGetAsSeries().

Les tableaux passés à la fonction reflètent les prix, c'est à dire que ces tableaux ont le flag des timeseries et que la fonction ArrayIsSeries() retournera true lors de la vérification de ces tableaux. Cependant, il ne faut jamais vérifier la direction d'indexation uniquement avec la fonction ArrayGetAsSeries().

Pour ne pas être dépendant des valeurs par défaut, ArraySetAsSeries() devrait être appelée inconditionnellement pour les tableaux que vous allez utiliser, et pour définir la direction désirée.

Récupérer les Prix et les Valeurs de l'Indicateur

La direction d'indexation par défaut de tous les tableaux dans les Expert Advisors, dans les indicateurs et dans les scripts est de gauche à droite. Si nécessaire, vous pouvez demander les valeurs des timeseries dans un programme mql5 sur n'importe quel symbole et n'importe quelle période, ainsi que les valeurs des indicateurs calculées sur n'importe quel symbole et n'importe quelle période.

Utilisez les fonctions Copy...() pour cela :

  • CopyBuffer — copie les valeurs du buffer de l'indicateur dans un tableau d'éléments de type double ;
  • CopyRates — copies l'historique des prix dans un tableau de structures MqlRates ;
  • CopyTime — copie les valeurs de temps dans un tableau d'éléments de type datetime ;
  • CopyOpen — copie les valeurs d'ouverture (Open) dans un tableau d'éléments de type double ;
  • CopyHigh — copie les valeurs des prix les plus hauts (High) dans un tableau d'éléments de type double ;
  • CopyLow — copie les valeurs des prix les plus bas (Low) dans un tableau d'éléments de type double ;
  • CopyClose — copie les valeurs des prix de clôture (Close) dans un tableau d'éléments de type double ;
  • CopyTickVolume — copie les volumes des ticks dans un tableau d'éléments de type long ;
  • CopyRealVolume — copie les volumes réels dans un tableau d'éléments de type long ;
  • CopySpread — copie l'historique des spreads dans un tableau d'éléments de type int ;

 

Toutes ces fonctions fonctionnent de la même façon. Considérons le mécanisme d'obtention des données dans l'exemple de CopyBuffer(). Il est implicite que la direction d'indexation des données demandées est celle des timeseries, et que la position avec l'indice 0 stocke les données de la barre non encore complétée. Pour accéder à ces données, vous devez copier le volume nécessaire de données dans le tableau destination, c'est à dire dans le buffer du tableau.

copyBuffer

Lors de la copie, nous devons spécifier la position de départ dans le tableau source, à partir de laquelle les données seront copiées dans le tableau destination. En cas de succès, le nombre spécifié d'éléments seront copiés dans le tableau destination depuis le tableau source (depuis le buffer de l'indicateur dans ce cas). Indépendamment de la valeur d'indexation définie dans le tableau destination, la copie est toujours effectuée comme montrée dans la figure ci-dessus.

S'il est attendu que les prix seront traités dans une boucle avec un grand nombre d'itérations, il est conseillé de vérifier la fin forcée du programme en utilisant la fonction IsStopped() :

int copied=CopyBuffer(ma_handle,// handle de l'indicateur
                      0,        // L'indice du buffer de l'indicateur
                      0,        // Position de départ pour la copie
                      number,   // Nombre de valeurs à copier 
                      Buffer    // Le tableau qui recevra les valeurs
                      );
if(copied<0) return;
int k=0;
while(k<copied && !IsStopped())
  {
   //--- Récupère la valeur pour l'indice k
   double value=Buffer[k];
   // ... 
   // utilise la valeur
   k++;
  }

Exemple :

input int per=10; // période de l'exposant
int ma_handle;    // handle de l'indicateur
//+------------------------------------------------------------------+
//| Fonction d'initialisation de l'expert |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   ma_handle=iMA(_Symbol,0,per,0,MODE_EMA,PRICE_CLOSE);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Fonction de tick de l'Expert                                     |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   double ema[10];
   int copied=CopyBuffer(ma_handle,// handle de l'indicateur
                         0,        // indice du buffer de l'indicateur
                         0,        // position de départ à partir de laquelle la copie sera faite
                         10,       // nombre de valeurs à copier
                         ema       // tableau destination
                         );
   if(copied<0) return;
// .... code supplémentaire
  }

Voir aussi

Organiser l'Accès aux Données