Metatrader nous met à disposition une variable prédéfinie, bien pratique: Bars. Cette variable disponible n'importe où dans le code contient le nombre de périodes actuellement dans l'historique. Si on a besoin de parcourir l'historique, il faut l'utiliser pour connaître le nombre de périodes dans cet historique. Elle pose cependant un problème. J'ai vu des codes utilisant la variable prédéfinie Bars comme indicateur de changement de période. Et je l'ai même, au début, utilisée pour établir un numéro temporel à chaque période comme si c'était un numéro de référence temporelle absolu. J'ai vite déchanté.
Le problème de la variable prédéfinie Bars est qu'elle ne représente que le nombre de périodes (bar) dans l'historique. Et ce nombre varie avec la taille de l'historique, qui elle dépend de la gestion interne de Metatrader. C'est-à-dire que ce nombre ne va pas forcément augmenter. Par expérience personnelle, je peux dire qu'il faut faire attention, et notamment quand on utilise ce nombre pour déterminer un numéro de période où pour déterminer s'il y a une nouvelle période ( Bars n'augmente pas forcément ). Pour déterminer un numéro de période, il faut se baser sur les horodatages, ceux-ci proviennent du serveur et sont associés aux données du cours et indissociables de ces cotations. A chaque tick qu'on reçoit, il s'agit surtout de lire la cotation, mais cette information, le serveur la fournie liée à un horodatage indissociable. La cotation a une position temporelle bien définie, sinon elle ne veux rien dire du tout.
Le principe du calcul:
Prenons par exemple une période qui durerait 5 secondes, cela signifierait que toutes les 5 secondes il y aurait une nouvelle période. C'est-à-dire que les secondes dont l'horodatage serait 0, 1, 2, 3 et 4 appartiennent à la période n°0, que les secondes n° 5, 6, 7, 8 et 9 appartiennent à la période n° 1, et que les secondes n° 10, 11, 12, 13 et 14 appartiennent à la période n° 2, etc. Vous constatez que dans les numéros des secondes de la période n°0, il y a 0 fois le nombre 5. On ne peut pas retirer le nombre 5 de ces numéros. Pour ceux de la période n°1, on peut par contre retirer 1 fois le nombre 5: 5-5=0, 6-5=1, 7-5=2, 8-5=3 et 9-5=4. Et 2 fois le nombre 5 pour ceux de la période n°2: 10-2x5=0, 11-2x5=1, 12-2x5=2, 13-2x5=3 et 14-2x5=4. Arithmétiquement c'est faire une division euclidienne (entière) c'est-à-dire une division dont on ne prend que la partie entière du résultat, soit le nombre de fois qu'on peut retirer le diviseur entier (les résultats des soustractions précédentes sont les restes de ces divisions, c'est ce qu'il reste qui n'est plus assez grand pour y retirer encore le diviseur). Faisons les divisions décimales et voyons:
- dont la partie entière est 0.
- dont la partie entière est 0.
- dont la partie entière est 0.
- dont la partie entière est 1.
- dont la partie entière est 1.
- dont la partie entière est 1.
- dont la partie entière est 2.
- dont la partie entière est 2.
- dont la partie entière est 5.
- dont la partie entière est 75.
La fonction MathFloor():
Certains langages de programmation proposent d'obtenir directement la partie entière de la division euclidienne et d'autres non. Ici ont peut utiliser deux méthodes:
- Approche triviale: division de nombres décimaux avec pour résultat un nombre décimal dont on pourra extraire la partie entière avec la fonction MathFloor().
- Utilisation du casting implicite par une division entre nombres entiers donnant un résultat entier.
MathFloor()
. On passe en paramètre à cette fonction un nombre avec des décimales et elle nous retourne le même nombre sans les décimales. Donc pour notre problème, il suffit de faire la division de l'horodatage du tick, qui est le nombre de secondes depuis le 1er janvier 1970, par le nombre de secondes dans la période. On obtient alors un nombre fractionnaire qu'on passe à la fonction pour avoir en retour ce même nombre débarrassé de ses décimales, et qui se trouve donc être le numéro de la période depuis le 1er janvier 1970. Du coup ce numéro est vraiment une référence qui ne risque pas de varier pour ce tick-là, à la différence de Bars. Les lignes de code pour ceci:
double noPeriodeFractionnaire = horodatage / nbSecondesDansPeriode;
int noPeriode = MathFloor(noPeriodeFractionnaire);
divisions entre entiers:
Quand on a fait le code précédent, on a fait deux erreurs car on a oublié deux choses que le langage MQL4 fait et qui, ici se compensent:
- La fonction
MathFloor()
prend un nombre décimal en paramètre du genre 12.3 ou 4.157 mais retourne aussi un nombre décimal, c'est-à-dire que le résultat qu'elle retourne est du genre 12.0 ou 4.0 (type double). Or nous voulons 12 ou 4, des nombres entiers (type int). - Le langage MQL4 réalise un cast implicite. Le cast est un changement de type de données opéré par le compilateur qui rajoute des instructions pour le processeur que nous n'avons pas mises et cela pour convertir le type de donnée. Dans notre cas, quand nous déclarons une variable de type int et que nous lui demandons d'y mettre la valeur 4.0 du type double, le compilateur va se débrouiller pour convertir le type et le 4.0 devient un 4. Mais ! En y réfléchissant bien, la fonction
MathFloor()
ne sert à rien ! On aurait tout aussi bien pu faire la division et demander en même temps de stocker le résultat dans une variable entière ce qui aurait provoqué la suppression des décimales ! Au final le cast implicite nous sauve la mise car nous avons comme résultat un nombre décimal et qu'on ne voulait pas ça, et que le cast convertit dans le bon type. On va continuer dans la réflexion et ceux qui l'ont testé le savent: les opérations aussi dépendent des types. Lors d'une opération arithmétique avec MQL4, s'il n'y a que des nombres entiers le résultat est entier et dès qu'un nombre décimal est en jeu, le résultat est décimal. Il y a un cast implicite aussi pour les opérations arithmétiques. Quand nous divisons deux nombres entiers, le résultat sera entier: à la différence de la même division avec au moins un nombre décimal: qui donne un résultat décimal. Or la division qu'on souhaite faire se fait entre deux nombres entiers ! Conclusion la fonction d'extraction de partie entière ne sert à rien ! La ligne de code que nous devons mettre est simplementint noPeriode = horodatage / nbSecondesDansPeriode;
Aucun commentaire:
Enregistrer un commentaire