![Plusieurs indicateurs sur un seul graphique (Partie 04) : Passer à un Expert Advisor](https://c.mql5.com/2/49/Multiple-indicators-on-one-chart-lPart-04j-Advancing-to-an-Expert-Advisor_600x314.jpg)
Plusieurs indicateurs sur un seul graphique (Partie 04) : Passer à un Expert Advisor
Introduction
Dans mes articles précédents, j'ai expliqué comment créer un indicateur utilisant plusieurs sous-fenêtres, ce qui est intéressant lorsqu'on utilise des indicateurs personnalisés. Cela n’était pas trop difficile. Mais implémenter la même fonctionnalité dans un Expert Advisor est un peu plus compliqué car nous ne disposons pas des outils que nous avons utilisés avec l’indicateur personnalisé. À ce stade, la programmation est essentielle : il est primordial d'être capable d'écrire du code pour créer une sous-fenêtre. Même si ce n'est pas si facile, savoir comment placer une sous-fenêtre dans un EA ne nécessite pas beaucoup de code, et seulement quelques connaissances sur le fonctionnement de MQL5.
Plan
Notre indicateur personnalisé fonctionne déjà, c'est-à-dire que notre classe d'objets est fonctionnelle. Et comme il s'agit d'une classe d'objets, nous pouvons facilement la transférer à d'autres modèles. Mais juste la déclarer et essayer de l'utiliser dans notre EA ne fera pas suffisant pour la faire fonctionner de la même manière que dans notre indicateur personnalisé. Ceci est dû au fait que nous ne pouvons pas encore créer une sous-fenêtre dans notre EA. Du coup, l’idée suivante est proposée : "Que se passe-t-il si nous utilisons un indicateur personnalisé, déjà compilé et fonctionnel et que nous l'appelons depuis l'EA en utilisant la commande iCustom ? Cela pourrait fonctionner puisque la sous-fenêtre n'est pas nécessaire et le code ressemblerait à ceci :
#property copyright "Daniel Jose" //+------------------------------------------------------------------+ input string user01 = ""; //Used indicators input string user02 = ""; //Assets to follow //+------------------------------------------------------------------+ int OnInit() { int m_handleSub; //... Expert Advisor code ... if ((m_handleSub = iCustom(NULL, 0, "Chart In SubWindows\\Chart In SubWindow.ex5", user01, user02)) == INVALID_HANDLE) return INIT_FAILED; if (!ChartIndicatorAdd(ChartID(), 0, m_handleSub)) return INIT_FAILED; //... Expert Advisor code ... ChartRedraw(); return(INIT_SUCCEEDED); } //...The rest of the Expert Advisor code ...
Ce simple extrait de code permet de charger notre indicateur personnalisé, mais il ne fonctionne pas correctement car il n’a pas de sous-fenêtre. Ici, lorsque le code sera exécuté, l'EA appliquera notre indicateur directement dans la fenêtre principale. Cela signifie que notre graphique sera caché par les modèles chargés par l'indicateur, ce qui n'est absolument pas ce que nous recherchons.
Notre problème est donc de créer une sous-fenêtre qui puisse être utilisée pour que nous puissions y placer notre indicateur déjà fonctionnel. Mais pourquoi créer une sous-fenêtre pour le lancement ultérieur de notre indicateur ? Cela n'a pas de sens ; il est préférable d'ajouter des fonctionnalités directement dans notre EA et ainsi de surmonter les limitations qui peuvent arriver.
Nous devons donc effectuer plusieurs tâches :
Tâche | Objectif |
---|---|
1 => Créer un indicateur polyvalent. | Permet de créer et d'utiliser la commande iCustom sans polluer le graphique. |
2 => Inclure cet indicateur dans l'EA. | Permet de transférer l’Expert Advisor avec toutes ses fonctionnalités sans aucun problème. |
3 => Générer une classe générale d'objets pour la sous-fenêtre. | Permet d'ajouter des sous-fenêtres via l'EA |
4 => Récupérer la classe C_TemplateChart liée à la classe de la fenêtre. | Permet de gérer le contenu des sous-fenêtres sans rien changer au code en cours d'exécution. |
Cela peux paraître compliqué, mais les difficultés sont résolues simplement. Traitons ces points un par un.
Implémentation : Création d'un indicateur polyvalent
Cette partie peut être résolue en écrivant le code d’un indicateur personnalisé complètement propre mais fonctionnel. Dans ce cas, le code ressemblerait à ceci :
#property copyright "Daniel Jose" #property version "1.00" #property description "This file only enables support of indicators in SubWin." #property indicator_chart_window #property indicator_plots 0 //+------------------------------------------------------------------+ int OnInit() { return INIT_SUCCEEDED; } //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[]) { return rates_total; } //+------------------------------------------------------------------+
Pas besoin de plus. Enregistrons maintenant ce fichier sous le nom de SubSupport.mq5. Par contre, il ne sera pas situé avec les autres indicateurs - au lieu de cela, nous le déplaçons dans le répertoire RESOURCE de notre Expert Advisor. La structure du fichier ressemblera donc à l'image ci-dessous :
Implémentation : Inclure l'indicateur dans l'EA
Pour ce faire, nous devons ajouter le code suivant au début de notre EA.
//+------------------------------------------------------------------+ #define def_Resource "Resources\\SubSupport.ex5" //+------------------------------------------------------------------+ #resource def_Resource //+------------------------------------------------------------------+
Cela permettra d'inclure le code compilé de l'indicateur dans notre EA. Une fois cette opération effectuée, le fichier .ex5 de l'indicateur sera supprimé car il n'est plus nécessaire. Vous devez maintenant faire attention au fait que si le fichier SubSupport.ex5 n'est pas trouvé au moment de la compilation de l'EA, le compilateur compilera automatiquement le code de l'indicateur SubSupport.mq5 et ajoutera ce nouveau fichier exécutable à notre Expert Advisor. Donc, si vous venez à modifiez le fichier SubSupport.mq5 et que vous avez besoin de faire les mêmes changements dans l’Expert Advisor, vous devez supprimer le fichier SubSupport.ex5; sinon, les changements ne seront pas ajoutés.
C’est un détail important : vous devez savoir comment ajouter des modifications nouvellement mises en œuvre à une ressource.
L'indicateur fait maintenant partie de l’Expert Advisor, nous pouvons donc passer à la tâche suivante.
Implémentation : Création d'une classe d'objets sous-fenêtre
Cette partie est également simple. Ici, nous devons définir les caractéristiques dont nous avons réellement besoin dans cette classe. Au départ, j'ai décidé d'utiliser ceci :
Fonction | Description |
---|---|
Init | Permet d'ajouter des sous-fenêtres via l'EA |
Close | Permet d'ajouter des sous-fenêtres via l'EA |
Ces fonctions ne seront pas testées, je suppose donc qu'elles ne seront appelées qu'une seule fois pendant la durée de vie de l'EA. Mais comme notre EA se développe, il est bon de penser à la rendre encore plus pratique pour l'avenir. Par conséquent, créons une nouvelle classe d'objets appelée C_Terminal. Cette classe prendra en charge quelques éléments liés au terminal graphique. Nous en apprendrons davantage à ce sujet plus tard. Passons à la dernière tâche, car il n'y a aucun moyen de mettre en œuvre la solution de manière partielle.
Implémentation : Héritage de la classe C_TemplateChart
Lorsque j'ai décidé de créer quelque chose de nouveau en utilisant la POO (Programmation Orientée Objet), je l'ai fait parce que je savais déjà qu'il y avait de gros avantages à utiliser cette approche, notamment la sécurité et l'héritage. Il existe également le polymorphisme. Nous l'utiliserons plus tard lors de la création d'un système d'ordres croisés. Dans ce cas particulier, nous allons utiliser l'un des avantages de la POO : l'héritage. C_TemplateChart est déjà une classe entièrement fonctionnelle. En voyant cela, vous ne voudriez pas devoir tout reprogrammer, ou courir le risque d'ajouter du code à la classe qui l’empêcherait d'être utilisée à d'autres endroits. La solution consiste à utiliser l'héritage. Il permet d'ajouter un nouveau code ou une nouvelle fonction sans modifier le code d'origine.
L'utilisation de l'héritage présente un certain nombre d'avantages : le code déjà testé reste testé ; la complexité augmente sans que la taille du code n'augmente dans les mêmes proportions ; seules les nouvelles fonctionnalités doivent réellement être testées ; ce qui ne change pas est simplement hérité, ce qui assure la stabilité. En d'autres termes, les choses s'améliorent avec un effort minimal, mais avec une sécurité maximale. Pour comprendre cela, regardons le schéma ci-dessous.
La classe Grand-Parent est la classe de base dans laquelle nous avons le plus bas niveau de manipulation des données. Lorsque la classe Parent hérite de la classe Grand-Parent, tous les éléments déclarés avec public dans la classe Grand-Parent peuvent être vus et utilisés par la classe Parent. Et nous pouvons également ajouter de nouvelles choses à la classe mère. Cela n'affectera pas ce qui est hérité et pris en charge par l'héritage. Si la classe Parent est déjà terminée et fonctionne, et que nous voulons l'étendre sans rien changer dans les classes inférieures, alors nous créons une classe Enfant. Elle aura toutes les caractéristiques des classes précédentes. Nous pouvons également changer la façon dont les choses fonctionnent. C'est un élément intéressant de l'héritage, car ces changements n'affecteront pas les autres classes. Cependant, il y a une limitation, contrairement au C++ qui permet l'héritage multiple. Si un Enfant peut hériter des fonctions du côté du père et de la mère, cela n'est pas possible dans MQL5. Mais vous bénéficiez toujours de l'héritage. Un exemple d'héritage multiple est présenté ci-dessous :
Maintenant, comment le faire dans MQL5 ? Comment déclarer un héritage et pouvoir profiter de ses avantages ? La manière la plus précise de comprendre cela est d’étudier la Programmation Orientée Objet (POO), mais ici nous irons droit au but. L'héritage sera fait en utilisant les lignes suivantes :
#include "C_TemplateChart.mqh" //+------------------------------------------------------------------+ class C_SubWindow : public C_TemplateChart { // ... Class code };
Vous voyez que la classe C_SubWindow hérite publiquement de la classe C_TemplateChart. Donc nous pouvons maintenant utiliser la classe C_SubWindow pour accéder aux fonctionnalités de la classe C_TemplateChart.
Dans l'extrait de code ci-dessus, j'ai mis en évidence une chose. Notez que l’include est entre guillemets ( " ) et non entre crochets ( < > ) comme d'habitude. Alors pourquoi ai-je fait ça ? À l'instar du langage C++, MQL5 comporte également des éléments très intéressants. Mais certaines choses déroutent ceux qui commencent tout juste à apprendre la programmation. Lorsque nous plaçons un fichier d'en-tête entre des crochets ( < > ), nous voulons préciser d’utiliser un chemin absolu - dans ce cas, le compilateur suivra exactement le chemin que nous avons spécifié. Mais lorsque nous utilisons des guillemets (comme nous l'avons fait cette fois-ci), le compilateur utilisera un chemin relatif, ou, pour être plus clair, il commencera à chercher le fichier d'abord dans le répertoire courant où se trouve le fichier de travail. Cela peut sembler étrange. Mais il arrive d’avoir un même nom de fichier dont le contenu est différent et qui se trouvent dans des répertoires différents. Nous pouvons donc toujours faire référence au répertoire courant, et nous utilisons donc des guillemets pour cela.
Les deux fonctions que nous avions prévu d'utiliser plus tôt, INIT et CLOSE, sont présentées ci-dessous :
//+------------------------------------------------------------------+ bool Init(void) { if (m_handleSub != INVALID_HANDLE) return true; if ((m_handleSub = iCustom(NULL, 0, "::" + def_Resource)) == INVALID_HANDLE) return false; m_IdSub = (int) ChartGetInteger(Terminal.Get_ID(), CHART_WINDOWS_TOTAL); if (!ChartIndicatorAdd(Terminal.Get_ID(), m_IdSub, m_handleSub)) return false; return true; } //+------------------------------------------------------------------+ void Close(void) { ClearTemplateChart(); if (m_handleSub == INVALID_HANDLE) return; IndicatorRelease(m_IdSub); ChartIndicatorDelete(Terminal.Get_ID(), m_IdSub, ChartIndicatorName(Terminal.Get_ID(), m_IdSub, 0)); ChartRedraw(); m_handleSub = INVALID_HANDLE; } //+------------------------------------------------------------------+
Le code est très simple et court. Il y a cependant une chose à laquelle nous devons faire attention. Prêtez attention à la partie surlignée. Vous devez faire attention à ne pas faire d'erreur en ajoutant cette partie. Si vous ne la laissez pas telle quelle, le fichier exécutable SubSupport.ex5 que nous avons demandé d'ajouter à l'EA ne sera pas visible à l'intérieur de l'EA - au contraire, il sera visible à l'extérieur de l'EA. Pour plus de détails, vous pouvez consulter la rubrique Ressources. Mais fondamentalement, si vous utilisez ( : : ), cela indique que l'EA doit utiliser sa ressource interne disponible. Mais si nous indiquons seulement le nom de la ressource, l'EA le cherchera dans le répertoire MQL5. Si le fichier n'existe pas à l'emplacement spécifié, la fonction échouera même si le fichier a été ajouté comme ressource de l’EA.
Une fois la ressource chargée, nous vérifions ensuite le nombre de sous-fenêtres présentes et ajoutons un indicateur à cette sous-fenêtre.
Vous pouvez voir ci-dessous ce que le code fait réellement :
input string user01 = ""; //Used indicators input string user02 = ""; //Assets to follows //+------------------------------------------------------------------+ int OnInit() { int m_handleSub; //... if ((m_handleSub = iCustom(NULL, 0, "Chart In SubWindows\\Chart In SubWindow.ex5", user01, user02)) == INVALID_HANDLE) return INIT_FAILED; if (!ChartIndicatorAdd(ChartID(), (int) ChartGetInteger(ChartID(), CHART_WINDOWS_TOTAL), m_handleSub)) return INIT_FAILED; //... ChartRedraw(); return(INIT_SUCCEEDED); } //...The rest of the Expert Advisor code ...
Les deux codes fonctionneront de la même manière. Mais la version avec la classe d'objets nous permettra d'ajouter plus de choses au fil du temps, puisque la version présentée ci-dessus est la version consolidée et ne changera pas. Les deux versions font la même chose : elles créent une sous-fenêtre à partir de l'EA et placent tous les indicateurs personnalisés créés auparavant dans cette sous-fenêtre. Faites attention aux changements apportés au code par rapport au code du début de l'article - les changements sont mis en évidence en couleur.
Conclusion
Il est très intéressant de voir le chemin que nous avons parcouru vers la réalisation de nos objectifs. Parfois, nous pouvons rencontrer des difficultés et penser qu'il est difficile d'atteindre nos objectifs. Mais avec un peu de patience et de dévouement, nous pouvons surmonter des obstacles qui semblaient au départ insurmontables. Dans cet article, je montre comment vous pouvez étendre les fonctionnalités d'une classe sans avoir à la modifier - grâce à l'héritage. En même temps, je vous montre comment ajouter des indicateurs aux graphiques pour qu'ils fonctionnent. Nous ajoutons le programme ex5 à l'intérieur de notre EA et l'utilisons sans devoir porter l'ex5 original, en chargeant simplement l'EA.
Le fichier joint contient toutes les améliorations développées jusqu'à présent, mais il y aura bientôt des choses encore plus intéressantes dans ce code. 😁👍
Traduit du portugais par MetaQuotes Ltd.
Article original : https://www.mql5.com/pt/articles/10241
![Plusieurs indicateurs sur un seul graphique (Partie 05) : Transformer MetaTrader 5 en un système RAD (I)](https://c.mql5.com/2/45/variety_of_indicators__3.png)
![Apprenez à concevoir un système de trading utilisant le Momentum](https://c.mql5.com/2/45/why-and-how__5.png)
![Apprenez à concevoir un système de trading utilisant le RSI](https://c.mql5.com/2/45/why-and-how__4.png)
![Plusieurs indicateurs sur un seul graphique (Partie 03) : Développer des définitions pour les utilisateurs](https://c.mql5.com/2/45/variety_of_indicators__1.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