![Développer un Expert Advisor à partir de zéro (partie 13) : Times & Trade (II)](https://c.mql5.com/2/49/Developing_a_trading_Expert_Advisor_from_scratch_004_600x314.jpg)
Développer un Expert Advisor à partir de zéro (partie 13) : Times & Trade (II)
Introduction
Dans l'article précédent "Times & Trade (I)", nous avons discuté d'un système graphique alternatif, permettant d'avoir un indicateur pour une interprétation plus rapide des transactions exécutées sur le marché. Mais nous n'avons pas terminé ce système : il manque encore la capacité de montrer comment vous pouvez accéder à certaines informations. Ce type d’accès aiderait à mieux comprendre ce qui se passe. Mais ces informations ne peuvent pas être présentées directement sur le graphique. Une telle présentation pourrait être mise en œuvre, mais l'interprétation serait très confuse. Il est donc préférable que les données soient représentées de manière classique, c'est-à-dire des valeurs au format texte. Notre Expert Advisor ne dispose pas encore d'un système capable d'effectuer cette tâche. Nous devons donc le mettre en œuvre.
Afin de ne pas compliquer l'article précédent en ajoutant des informations dont certains lecteurs n'auraient peut-être pas besoin (car le système peut être utilisé sans plonger dans de tels détails), j'ai décidé d'étendre le système ici et de le rendre plus complet. Malgré tout, ces informations peuvent parfois être nécessaires pour comprendre ce qui se passe réellement sur le marché.
Plan
Il est important de comprendre une chose : ce ne sont que des détails, mais comme on dit, le diable vit dans les détails. Veuillez donc jeter un œil à l'image suivante:
Avez-vous vu quelque chose d'étrange dans cette image ? Quelque chose qui n'a peut-être pas beaucoup de sens, mais c'est bien là, alors regardez de très près.
Si vous n'avez toujours rien remarqué d'étrange, consultez la zone entourée ci-dessous.
Voyez-vous maintenant ce qui se passe ? Il y a eu des changements dans les valeurs BID et ASK à ce niveau, mais une seule transaction a été effectuée. Même s'il y avait des changements dans la valeur BID ou ASK, cela n'a toujours aucun sens d'avoir un seul trade. Mais ce sont en fait des choses plus courantes que vous ne le pensez. Le problème est que vous ne pouvez pas le voir lorsque vous utilisez le mode de lecture indiqué ci-dessous :
Lors de l'utilisation de cette méthode d'analyse de marché, nous ne pouvons pas voir le mouvement des valeurs des prix BID et ASK. Il semble que le marché fonctionne toujours, que tout le monde essaie de conclure une affaire, mais ce n'est pas vrai. En fait, les acteurs du marché placent des positions à certains points et attendent le mouvement du marché. Lorsque la position est atteinte, ils essaient de profiter du mouvement. A cause de cela, les valeurs BID ou ASK se déplacent sans aucune transaction. C'est un fait réel qui peut être vu dans la plateforme, mais qui est cependant ignoré par la plupart des gens qui pensent que cette information n'est pas très importante.
La figure ci-dessous montre à quoi ressemblera notre système Times & Trade :
Si vous regardez attentivement, vous verrez qu'il y a 4 configurations de chandeliers sur le graphique. Il devrait toutefois y en avoir 5, mais les ordres directs sont exclus du système car ils ne font pas réellement bouger le marché. Par conséquent, nous avons bien 4 configurations. Il s'agit des formations suivantes :
Parfois, l'ombre ne touche pas le corps du chandelier. Mais pourquoi cela arrive-t-il ? L'ombre est formée par la valeur du spread, qui à son tour est la différence entre BID et ASK. Mais si une opération a lieu dans ce spread, alors à quoi ressemblera le chandelier ? Ce sera le 5ème type illustré ci-dessous :
Selon ce type de formation, il s'agit d’un DOJI. C'est la raison pour laquelle les ordres directs ne sont pas affichés dans le système. Mais cela n'explique pas pourquoi le corps ne touche pas l'ombre. Un tel comportement est lié à des situations où quelque chose se produit faisant bouger le prix trop rapidement, ce qui fait qu'il y a une distance entre le corps et l'ombre. On pourrait penser qu'il s'agit d'une défaillance du système, car cela n'a aucun sens pour le prix d’avoir ce comportement. Mais cela a du sens ici car cela se produit exactement au moment où les ordres stop sont déclenchés. Pour le voir, jetez un œil à l'image ci-dessous :
Il y a une série de cas où des ordres sont présents, mais ni BID ni Ask ne sont touchés. Tous ces points représentent des ordres stop déclenchés. Lorsque cela se produit, généralement le prix saute, ce qui peut être vu sur le graphique. Ceci peut être aussi visible sur Times & Trade si vous utilisez le mode graphique pour évaluer le mouvement. Sans cela, vous ne voyez pas le déclenchement des stops et pouvez penser que le mouvement a pris de la force alors qu'en réalité il peut revenir rapidement, et vous stop sera touché.
Maintenant que vous le savez, vous comprendrez qu'une grande série de chandeliers ne touchant pas l'ombre représente des ordres stop déclenchés. En fait, il est juste impossible de capter exactement ce mouvement au moment où il se produit, puisque tout se passe très vite. Mais vous pouvez utiliser l'interprétation des valeurs BID et ASK pour savoir pourquoi cela s'est produit. Cela dépend de votre expérience du marché et de vous-même. Je n'entrerai pas dans les détails ici, mais c'est quelque chose sur lequel vous devriez vous concentrer si vous voulez vraiment utiliser la lecture de bande comme indicateur.
Viennent maintenant les détails : si ces informations ne peuvent être vues qu'à l'aide de chandeliers et qu'eux-mêmes suffisent à apprendre certaines informations, alors pourquoi est-il si nécessaire d'avoir plus de données ?
Le détail important est qu'il y a des moments où le marché est plus lent, attendant des informations qui peuvent sortir en ce moment, mais nous ne pouvons pas le savoir en regardant simplement le Times & Trade avec des chandeliers. Nous avons besoin de quelque chose de plus. Cette information existe dans le système lui-même, mais il est difficile de l'interpréter au fur et à mesure. Les données doivent être modélisées pour faciliter leur analyse.
Cette modélisation est la raison d’être de cet article : une fois cette modélisation terminée, Times & Trade changera pour ressembler à ceci :
En d'autres termes, nous aurons une image complète de ce qui se passe. De plus, tout sera rapide. Ce qui est important pour ceux qui souhaitent utiliser la lecture sur bande comme moyen de trading.
Implémentation
Pour implémenter le système, nous devons ajouter de nouvelles variables à la classe C_TimesAndTrade. Elles sont définies conformément au code ci-dessous :
#include <NanoEA-SIMD\Auxiliar\C_FnSubWin.mqh> #include <NanoEA-SIMD\Auxiliar\C_Canvas.mqh> //+------------------------------------------------------------------+ class C_TimesAndTrade : private C_FnSubWin { //+------------------------------------------------------------------+ #define def_SizeBuff 2048 #define macro_Limits(A) (A & 0xFF) #define def_MaxInfos 257 //+------------------------------------------------------------------+ private : string m_szCustomSymbol, m_szObjName; char m_ConnectionStatus; datetime m_LastTime; ulong m_MemTickTime; int m_CountStrings; struct st0 { string szTime; int flag; }m_InfoTrades[def_MaxInfos]; struct st1 { C_Canvas Canvas; int WidthRegion, PosXRegion, MaxY; string szNameCanvas; }m_InfoCanvas;
Les parties ajoutées au code source sont mises en surbrillance. Comme vous pouvez le voir, nous devons utiliser la classe C_Canvas, mais elle ne contient pas tous les éléments nécessaires. En fait, nous devons ajouter 4 fonctions à cette classe C_Canvas. Elles sont illustrés dans le code ci-dessous :
// ... C_Canvas class code inline void FontSet(const string name, const int size, const uint flags = 0, const uint angle = 0) { if(!TextSetFont(name, size, flags, angle)) return; TextGetSize("M", m_TextInfos.width, m_TextInfos.height); } //+------------------------------------------------------------------+ inline void TextOutFast(int x, int y, string text, const uint clr, uint alignment = 0) { TextOut(text, x, y, alignment, m_Pixel, m_width, m_height, clr, COLOR_FORMAT_ARGB_NORMALIZE); } //+------------------------------------------------------------------+ inline int TextWidth(void) const { return m_TextInfos.width; } //+------------------------------------------------------------------+ inline int TextHeight(void) const { return m_TextInfos.height; } //+------------------------------------------------------------------+ // ... The rest of the code ...
Ces lignes vont créer du texte. C’est très simple, et n’a rien d'extrêmement élégant.
La prochaine fonction de cette classe qui mérite d'être mentionnée est PrintTimeTrade :
void PrintTimeTrade(void) { int ui1; m_InfoCanvas.Canvas.Erase(clrBlack, 220); for (int c0 = 0, c1 = m_CountStrings - 1, y = 2; (c0 <= 255) && (y < m_InfoCanvas.MaxY); c0++, c1--, y += m_InfoCanvas.Canvas.TextHeight()) if (m_InfoTrades[macro_Limits(c1)].szTime == NULL) break; else { ui1 = m_InfoTrades[macro_Limits(c1)].flag; m_InfoCanvas.Canvas.TextOutFast(2, y, m_InfoTrades[macro_Limits(c1)].szTime, macroColorRGBA((ui1 == 0 ? clrLightSkyBlue : (ui1 > 0 ? clrForestGreen : clrFireBrick)), 220)); } m_InfoCanvas.Canvas.Update(); }
Cette fonction affichera les valeurs dans une zone réservée à cet effet. La procédure d'initialisation a également subi des modifications mineures, visibles ci-dessous dans la partie en surbrillance :
void Init(const int iScale = 2) { if (!ExistSubWin()) { m_InfoCanvas.Canvas.FontSet("Lucida Console", 13); m_InfoCanvas.WidthRegion = (18 * m_InfoCanvas.Canvas.TextWidth()) + 4; CreateCustomSymbol(); CreateChart(); m_InfoCanvas.Canvas.Create(m_InfoCanvas.szNameCanvas, m_InfoCanvas.PosXRegion, 0, m_InfoCanvas.WidthRegion, TerminalInfoInteger(TERMINAL_SCREEN_HEIGHT), GetIdSubWinEA()); Resize(); m_ConnectionStatus = 0; } ObjectSetInteger(Terminal.Get_ID(), m_szObjName, OBJPROP_CHART_SCALE, (iScale > 5 ? 5 : (iScale < 0 ? 0 : iScale))); }
Des changements supplémentaires ont également été nécessaires dans la fonction de substitution dans le Times & Trade. Les changements sont les suivants :
void Resize(void) { static int MaxX = 0; int x = (int) ChartGetInteger(Terminal.Get_ID(), CHART_WIDTH_IN_PIXELS, GetIdSubWinEA()); m_InfoCanvas.MaxY = (int) ChartGetInteger(Terminal.Get_ID(), CHART_HEIGHT_IN_PIXELS, GetIdSubWinEA()); ObjectSetInteger(Terminal.Get_ID(), m_szObjName, OBJPROP_YSIZE, m_InfoCanvas.MaxY); if (MaxX != x) { MaxX = x; x -= m_InfoCanvas.WidthRegion; ObjectSetInteger(Terminal.Get_ID(), m_szObjName, OBJPROP_XSIZE, x); ObjectSetInteger(Terminal.Get_ID(), m_InfoCanvas.szNameCanvas, OBJPROP_XDISTANCE, x); } PrintTimeTrade(); }
Le système est presque prêt. Mais nous avons encore besoin du sous-programme qui est au cœur du système. Il a aussi été modifié :
inline void Update(void) { MqlTick Tick[]; MqlRates Rates[def_SizeBuff]; int i0, p1, p2 = 0; int iflag; long lg1; static int nSwap = 0; static long lTime = 0; if (m_ConnectionStatus < 3) return; if ((i0 = CopyTicks(Terminal.GetFullSymbol(), Tick, COPY_TICKS_ALL, m_MemTickTime, def_SizeBuff)) > 0) { for (p1 = 0, p2 = 0; (p1 < i0) && (Tick[p1].time_msc == m_MemTickTime); p1++); for (int c0 = p1, c1 = 0; c0 < i0; c0++) { lg1 = Tick[c0].time_msc - lTime; nSwap++; if (Tick[c0].volume == 0) continue; iflag = 0; iflag += ((Tick[c0].flags & TICK_FLAG_BUY) == TICK_FLAG_BUY ? 1 : 0); iflag -= ((Tick[c0].flags & TICK_FLAG_SELL) == TICK_FLAG_SELL ? 1 : 0); if (iflag == 0) continue; Rates[c1].high = Tick[c0].ask; Rates[c1].low = Tick[c0].bid; Rates[c1].open = Tick[c0].last; Rates[c1].close = Tick[c0].last + ((Tick[c0].volume > 200 ? 200 : Tick[c0].volume) * (Terminal.GetTypeSymbol() == C_Terminal::WDO ? 0.02 : 1.0) * iflag); Rates[c1].time = m_LastTime; m_InfoTrades[macro_Limits(m_CountStrings)].szTime = StringFormat("%02.d.%03d ~ %02.d <>%04.d", ((lg1 - (lg1 % 1000)) / 1000) % 60 , lg1 % 1000, nSwap, Tick[c0].volume); m_InfoTrades[macro_Limits(m_CountStrings)].flag = iflag; m_CountStrings++; nSwap = 0; lTime = Tick[c0].time_msc; p2++; c1++; m_LastTime += 60; } CustomRatesUpdate(m_szCustomSymbol, Rates, p2); m_MemTickTime = Tick[i0 - 1].time_msc; } PrintTimeTrade(); }
Les lignes en surbrillance représentent le code ajouté au programme pour modéliser les données dont nous avons besoin. Le code suivant :
lg1 = Tick[c0].time_msc - lTime; nSwap++;
vérifie combien de temps s'est écoulé entre les transactions, en millisecondes, et combien de transactions qui n'ont pas provoqué de changement de prix se sont produites. Si ces chiffres sont importants, vous pouvez comprendre que le turnover diminue. Avec cette fonctionnalité, vous le déterminerez plus tôt que les autres.
La partie suivante :
m_InfoTrades[macro_Limits(m_CountStrings)].szTime = StringFormat("%02.d.%03d ~ %02.d <>%04.d", ((lg1 - (lg1 % 1000)) / 1000) % 60 , lg1 % 1000, nSwap, Tick[c0].volume); m_InfoTrades[macro_Limits(m_CountStrings)].flag = iflag; m_CountStrings++; nSwap = 0; lTime = Tick[c0].time_msc;
modélisera les valeurs qui seront affichées. Veuillez noter que nous ne testerons pas le compteur m_CountStrings en raison de son utilisation limitée. Nous augmenterons simplement ses valeurs au fur et à mesure que de nouvelles informations seront disponibles. C'est une astuce que vous pouvez parfois utiliser. Je l'utilise moi-même lorsque c'est possible, car c’est efficace en termes de traitement, ce qui est important car le système de trading est conçu pour être utilisé en temps réel. Vous devriez toujours essayer d'optimiser le système dans la mesure du possible, même si ce n'est qu'un tout petit peu, car cela fait une grande différence.
Une fois que tout a été implémenté, vous pouvez compiler l'Expert Advisor et obtenez quelque chose comme ceci :
En regardant les mouvements décrits ci-dessus sur le graphique Times & Trade, vous pouvez voir que des microstructures commencent à apparaître. Cependant, même après avoir étudié ces microstructures, je n'ai pas encore pu en tirer d’avantages. Cependant, je ne suis pas un trader expérimenté, alors qui sait, peut-être que quelqu'un avec plus d'expérience peut le faire.
Cet indicateur est si puissant et si informatif que j'ai décidé de faire une vidéo montrant une petite comparaison entre ses valeurs et les données réelles présentées par un actif au moment de la rédaction. Je veux démontrer qu'il filtre beaucoup d'informations, vous permettant de lire les données beaucoup plus rapidement et de mieux comprendre ce qui se passe. J'espère que vous apprécierez et profiterez de cet indicateur fantastique et si puissant.
Conclusion
Traduit du portugais par MetaQuotes Ltd.
Article original : https://www.mql5.com/pt/articles/10412
![Apprenez à concevoir un système de trading basé sur le MFI](https://c.mql5.com/2/47/why-and-how__1.png)
![Développer un Expert Advisor à partir de zéro (partie 12) : Times et Trade (I)](https://c.mql5.com/2/46/development__3.png)
![Apprenez à concevoir un système de trading basé sur les Volumes](https://c.mql5.com/2/47/why-and-how__2.png)
![Opérations sur les Matrices et les Vecteurs en MQL5](https://c.mql5.com/2/48/matrix_and_vectors_2.png)
![MQL5 - Langage des stratégies de trading intégré au terminal client MetaTrader 5](https://c.mql5.com/i/registerlandings/logo-2.png)
- Applications de trading gratuites
- Plus de 8 000 signaux à copier
- Actualités économiques pour explorer les marchés financiers
Vous acceptez la politique du site Web et les conditions d'utilisation