jeudi 16 janvier 2014

IndicatorCounted() et le remplissage de l'historique de l'indicateur 1 / 3.

Concernant les indicateurs nous allons nous pencher sur un détail important qui pose des problèmes lorsqu'on débute et qu'il faut régler tout de suite: celui du remplissage de l'historique de l'index. Je vais donc vous détailler les notions avant d'expliquer ce qu'il faut faire pour chaque indicateur qu'on créé.

Historique:


Pour nous permettre de faire des anticipations de l'évolution du cours, MetaTrader conserve en mémoire les valeurs du cours pour constituer un historique du cours. On peut alors lire ces valeurs et faire des calculs avec pour prévoir, selon nos méthodes, ce que va faire le cours. Cet historique est entièrement géré par MetaTrader qui nous met à disposition un tableau de ces valeurs. Lorsqu'on fait un indicateur, le but est de faire une série de valeurs calculées pour indiquer quelque chose sur le cours. Il faut donc remplir aussi l'historique de l'indicateur, ce que nous allons voir ici.

Indicateur:


Un indicateur est un programme tout comme les experts advisors, qui va étudier le signal, mais dont le but n'est pas de passer les ordres mais de calculer une ou des valeurs caractéristiques d'une information sur ce cours. Grâce à cette information, les experts advisors vont pouvoir déterminer s'il faut acheter, vendre ou ne rien faire en temps réel. Donc un indicateur va être utilisé par les experts advisors, ou même simplement par un trader manuel qui recevra ainsi en temps réel et de manière automatique le résultat d'un calcul pour l'aider dans ses prises de décisions.

Index:


Il faut bien comprendre le concept d'index lorsqu'on créé un indicateur dans MetaTrader. Un index est un signal, c'est à dire une suite de valeurs calculées (une par période temporelle) qui vont tracer une courbe. On peut en faire huit par indicateur, chacune possédant sa série de valeurs. Une valeur pour chaque période temporelle de l'historique entier de la paire de devises. C'est-à-dire qu'on remonte tout l'historique, il va falloir toutes les calculer. Et à chaque nouvelle période qui rentre dans l'historique il faut en calculer une.

Buffer:


Pour tracer l'évolution de l'indicateur au cours du temps, il faut stocker toutes ses valeurs pour pouvoir les lire, faire encore des calculs avec ou tout simplement les afficher sur un graphique. On va stocker ces valeurs dans un tableau, qu'en programmation on nomme un buffer, "tampon" en français. C'est-à-dire une zone suffisamment vaste en mémoire qui sert de tampon de stockage. Tampon parce que vu sa taille, elle ne débordera pas. Et si elle venait à être pleine, MetaTrader gère le problème et demande au système une zone supplémentaire. De notre côté, nous avons juste à écrire et lire des valeurs dans ce tableau et rien d'autre. MetaTrader tracera tout seul le graphique avec, sans que nous nous en occupions. Il faut juste le remplir avec des valeurs ! MetaTrader ne les invente pas pour nous, puisque ce sont celles de notre indicateur, issues de nos calculs. MetaTrader s'occupe déjà de maintenir l'historique du cours, de gérer la taille de nos tampons d'indicateurs et de tracer nos courbes.

Timeserie:


Comme on l'a vu précédemment, on accède aux valeurs d'un tableau par le nom du tableau et accolé au nom, une paire de crochets encadrant le numéro de la case du tableau voulue. Chaque case du tableau correspondant à une place en mémoire numérotée. Le processeur y accède par un numéro qui est appelée adresse mémoire. Lorsqu'on créé dans un programme un tableau, le compilateur réserve une place de 4 octets en mémoire pour contenir l'adresse où le tableau sera réellement placé. Ce sera l'adresse du début du tableau. Toutes les cases du tableau seront les unes à côté des autres dans la mémoire, à l'endroit désigné par l'adresse contenue dans la variable dans le programme (nom donné au tableau). Par exemple si je créé un tableau appelé "moyenne" de 500 cases, je tape les instructions:
double moyenne[500];
Avec cette ligne de code, nous créons deux places en mémoire: celle de la variable moyenne, de quatre octets qui contient uniquement l'adresse de la véritable place du tableau, par exemple 0xA53BC970 (notation hexadécimale pour être moins grosse, si si c'est un nombre, malgré les lettres !). Et une deuxième place de 500x8=4000 octets pour contenir 500 nombres décimaux (de type double) de 8 octets chacun, commençant à l'adresse 0xA53BC970. Un petit schéma vaut mieux qu'un grand discours:
contenu de moyenne0xA5...3B...C9...70
adresse:
n° octet en mémoire
octets n°0xA53BA000 à 0xA53BA003
Et un peu plus loin dans la mémoire:
case n°012...499
adresse:
n° octet en mémoire
0xA53BC9700xA53BC9780xA53BC980...0xA53CB58
Le premier emplacement sert uniquement à retrouver où se situe le deuxième emplacement: le tableau. Et lorsqu'on veut y accéder pour lire la valeur de la case n°2 avec par exemple l'instruction:
Print(moyenne[2]);
Le compilateur va déterminer l'adresse exacte de la valeur cherchée en prenant l'adresse de base du tableau dans le premier emplacement (la variable), et en ajoutant deux fois la taille en mémoire d'une valeur de type double, c'est-à-dire 2x8 octets, on obtient donc 0xA53BC970 + 2x8 = 0xA53BC970 + 16 = 0xA53BC970 + 0x10 (en hexadécimal) = 0xA53BC980. Ce qui est l'adresse de la deuxième case mémoire du tableau. Le compilateur ne vérifiera pas si on dépasse le tableau, et si on demande la case n°500, c'est la 501ème, le calcul fera tomber en dehors du tableau dans un emplacement qui ne nous est pas attribué et le système fera arrêter le programme d'un coup car il aura tenté d'accéder à une place qui ne lui était pas réservée.
Vous constatez que la numérotation des cases du tableau suit la progression des adresses mémoire. C'est l'ordre naturel en programmation. Mais pour des considérations temporelles, l'éditeur MetaQuotes a décidé que MetaTrader devait gérer la numérotation dans l'ordre contraire: les timeseries. Il faut imaginer qu'on remonte dans l'historique, et donc quand on veut la période temporelle n°0, c'est la période en cours. La n°1, c'est celle qui vient de se terminer, et la n°2, c'est celle d'avant, etc. Or le compilateur quand il écrit ou lit dans un tableau c'est toujours dans l'ordre naturel de la programmation: la numérotation des cases augmente avec les adresses mémoire. Et là, il faut que la dernière case qui ait été remplie soit la plus récente, donc avec le numéro 0. Je vous montre avec un schéma. Les cases colorées sont celles qui ont été remplies:
n° timeserie210inutilisée...
adresse:
n° octet en mémoire
0xA53BC9700xA53BC9780xA53BC9800xA53BC988...
Dès qu'il y a une nouvelle période (celle en cours vient de finir), la numérotation est alors décalée, et elle se décale toutes les minutes si la période est M1, ou toutes les quatre heures si la période est H4, etc. La première case inutilisée devenant la n°0. Vous devez juste retenir qu'à tout moment la période en cours, c'est la n°0, celle qui vient de finir la n°1, celle d'avant c'est la n°2, etc. Rassurez-vous, c'est MetaTrader qui gère cette différence. Vous avez juste à savoir qu'il faut remonter dans le temps en augmentant le numéro des cases. Puisque MetaTrader gère tout, y compris la taille des tableaux en mémoire, vous ne devez même pas indiquer de taille lors de la création de votre buffer pour votre courbe d'indicateur:
double moyenne[];
Par contre, il faut indiquer à MetaTrader que ce tableau créé, est un buffer de signal qu'il devra gérer, et qu'on remplira avec nos valeurs. On choisit pour ce buffer, le numéro 0, et on peut aller jusqu'au numéro 7 (huit index):
SetIndexBuffer(0, moyenne);

Ça suffira pour aujourd'hui. Il y a suffisamment d'informations à digérer et je tenais à faire ces précisions pour mieux comprendre les indicateurs avant de voir une partie technique indispensable pour tous les indicateurs: remplir l'historique, même celui déjà présent avant l'exécution de l'indicateur ! Nous verrons ça au post suivant.

Aucun commentaire:

Enregistrer un commentaire