English Русский 中文 Español Deutsch 日本語 Português 한국어 Italiano Türkçe
preview
Développer un Expert Advisor de trading à partir de zéro (Partie 20) : Nouveau système d'ordre (III)

Développer un Expert Advisor de trading à partir de zéro (Partie 20) : Nouveau système d'ordre (III)

MetaTrader 5Systèmes de trading | 21 août 2023, 08:06
891 0
Daniel Jose
Daniel Jose

Introduction

Dans l'article précédent, Développer un Expert Advisor de trading à partir de zéro (Partie 19), nous nous sommes concentrés sur les changements de code qui ont été mis en œuvre pour permettre le fonctionnement du nouveau système d'ordres. Depuis que ces changements ont été mis en œuvre, je peux me concentrer à 100 % sur le vrai problème. Il s'agit de mettre en place le système d'ordres, qui est 100% visuel et compréhensible pour ceux qui tradent sans avoir à connaître la valeur du tick ou à savoir où placer un ordre pour gagner X, ou encore où placer le Stop Loss pour ne pas perdre Y.

La création de ce système nécessite une bonne maîtrise de MQL5, ainsi qu'une compréhension du fonctionnement de la plateforme MetaTrader 5 et des ressources qu'elle offre.


1.0. Plan

1.0.1. Conception des indicateurs

L'idée ici, enfin pas seulement l'idée mais ce que je vais faire, c'est montrer comment mettre en œuvre le système présenté dans cet article. Nous allons créer quelque chose de similaire à l'image ci-dessous :

Il est très facile à comprendre, même sans explication. Un bouton de fermeture, une valeur et un point facilitent le glissement et le placement des ordres. Mais ce n'est pas tout. Lorsque le Stop Loss se transforme en Stop Gain, le système procédera comme suit :

Ainsi, nous pouvons facilement savoir quand, combien, où et si cela vaut la peine ou non de tenir une certaine position.

Les figures ci-dessus ne montrent que les objets de l'ordre OCO ou les limites de position OCO. Mais je n'ai pas oublié la partie liée au prix d'ouverture, car elle est tout aussi importante.

Pour les ordres en cours, cela se présente comme suit :

La situation sera un peu différente pour une position :

Cependant, les proportions ne sont pas très encourageantes... Mais c'est l'idée qui sera mise en œuvre. En ce qui concerne les couleurs, j'utiliserai celles présentées ici. Mais vous pouvez choisir celles qui vous plaisent.

Au fur et à mesure, nous remarquerons que nous aurons essentiellement 5 objets dans chaque indicateur. Cela signifie que MetaTrader 5 devra traiter 5 objets en même temps pour chaque indicateur. Dans le cas d'un ordre OCO, MetaTrader 5 devra traiter 15 objets, tout comme dans le cas d'une position OCO, où MetaTrader 5 doit traiter 15 objets, ce qui correspond à un ordre ou à une position. Cela signifie que si vous avez 4 ordres OCO en attente et 1 position OCO ouverte, MetaTrader 5 devra traiter 25 objets, en plus des autres qui seront également présents sur le graphique. Et seulement si vous n'utilisez qu'un seul instrument dans la plateforme.

Je dis cela car il est important de connaître la mémoire nécessaire et le traitement requis pour chaque ordre que vous allez passer pour l'instrument de trading. Ce n'est pas un problème pour les ordinateurs modernes, mais il est nécessaire de savoir exactement ce que l'on attend du matériel. Auparavant, il n'y avait qu'un seul objet à l'écran pour chaque point de l'ordre. Il y aura maintenant 5 objets dans chacun des points, et ils devront rester connectés d'une manière ou d'une autre. Cette connexion sera mise en œuvre par la plateforme. Nous nous contenterons de donner des instructions sur la manière dont les objets doivent être connectés et sur ce qui doit se passer lorsque chacun d'entre eux se déclenche.


1.0.2. Choix des objets

La question suivante concerne le choix des objets que nous utiliserons. Cette question peut sembler simple, mais elle est très importante car elle détermine le déroulement de la mise en œuvre. Le premier choix est basé sur la façon dont les objets sont positionnés sur l'écran.

Nous avons 2 façons de le mettre en œuvre. Heureusement, MetaTrader 5 couvre les deux : le premier utilise le positionnement par coordonnées de temps et de prix et le second utilise les coordonnées cartésiennes X et Y.

Mais avant de procéder à l'examen détaillé de l'un d'entre eux, je vais immédiatement écarter le modèle qui utilise des coordonnées de temps et de prix. Bien qu'idéal à première vue, il ne sera pas utile lorsque nous aurons affaire à tant d'objets qui seront reliés les uns aux autres et qui devront rester ensemble. Nous devrons donc utiliser le système cartésien.

Dans l'un des articles précédents, nous avons déjà examiné ce système et discuté de la manière de sélectionner les objets. Pour plus de détails, voir Plusieurs indicateurs sur un même graphique (Partie 05).

Nous avons terminé la planification et nous pouvons maintenant passer au codage proprement dit. Il est temps de mettre les choses en pratique.


2.0. Implémentation

Mon but n'est pas simplement de mettre en œuvre le système, mais d'expliquer ce qui s'y passe exactement afin que vous puissiez également créer le votre. Je fournirai les détails petit à petit. Cela vous aidera à comprendre comment il est créé. N'oubliez pas que toute fonctionnalité liée aux ordres en attente fonctionnera également pour les positions, puisque le système suit les mêmes principes et dispose d'un code commun.


2.0.1. Création d'une interface

Le résultat de cette première étape est visible ci-dessous. C'est ma façon de présenter les avantages afin que vous soyez aussi enthousiastes que moi lorsque j'ai développé et décidé de partager ces codes avec vous tous. J'espère que cela servira de motivation à ceux qui veulent apprendre la programmation ou développer des connaissances plus approfondies sur le sujet.


En regardant l'image ci-dessus, vous pouvez penser que la fonctionnalité a été créée de manière habituelle, en excluant tout le code créé jusqu'à présent. Mais non, nous utiliserons exactement ce qui a été construit jusqu'à présent.

Nous allons donc utiliser le code présenté dans l'article précédent et y apporter quelques modifications. Concentrons-nous donc sur les nouveautés du code. Tout d'abord, nous allons ajouter 3 nouvelles classes.


2.0.1.1. Classe C_Object_Base

Nous commencerons par créer une nouvelle classe C_Object_Base. C'est la classe la plus basse de notre système. Les premiers codes de la classe sont présentés ci-dessous :

class C_Object_Base
{
        public  :
//+------------------------------------------------------------------+
void Create(string szObjectName, ENUM_OBJECT typeObj)
{
        ObjectCreate(Terminal.Get_ID(), szObjectName, typeObj, 0, 0, 0);
        ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_SELECTABLE, false);
        ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_SELECTED, false);
        ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_BACK, true);
        ObjectSetString(Terminal.Get_ID(), szObjectName, OBJPROP_TOOLTIP, "\n");
        ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_BACK, false);
        ObjectSetString(Terminal.Get_ID(), szObjectName, OBJPROP_TOOLTIP, "\n");
        PositionAxleY(szObjectName, 9999);
};

// ... The rest of the class code

Notez que nous disposons d'un code général qui nous facilitera grandement la vie. Dans la même classe, nous avons des codes de positionnement X et Y standard.

void PositionAxleX(string szObjectName, int X)
{
        ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_XDISTANCE, X);
};
//+------------------------------------------------------------------+
virtual void PositionAxleY(string szObjectName, int Y)
{
        ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_YDISTANCE, Y);
};


Le code de positionnement Y dépend d'un objet spécifique. Mais même si l'objet n'a pas de code spécifique, la classe en fournit un général. Nous disposons d'une méthode générale pour spécifier la couleur de l'objet illustré ci-dessous.

virtual void SetColor(string szObjectName, color cor)
{
        ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_COLOR, cor);
}


Et voici comment définir les dimensions des objets :

void Size(string szObjectName, int Width, int Height)
{
        ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_XSIZE, Width);
        ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_YSIZE, Height);
};


C'est tout pour l'instant avec la classe C_Object_Base, mais nous y reviendrons plus tard.


2.0.1.2. Classe C_Object_BackGround

Créons maintenant 2 autres classes pour supporter nos deux objets graphiques. La première est C_Object_BackGround. Elle crée une boîte d'arrière-plan destinée à recevoir d'autres éléments. Son code est assez simple. Vous pouvez le voir ci-dessous dans son intégralité :

#property copyright "Daniel Jose"
//+------------------------------------------------------------------+
#include "C_Object_Base.mqh"
//+------------------------------------------------------------------+
class C_Object_BackGround : public C_Object_Base
{
        public:
//+------------------------------------------------------------------+
		void Create(string szObjectName, color cor)
                        {
                                C_Object_Base::Create(szObjectName, OBJ_RECTANGLE_LABEL);
                                ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_BORDER_TYPE, BORDER_FLAT);
                                ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_CORNER, CORNER_LEFT_UPPER);
                                ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_COLOR, clrNONE);
                                ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_BGCOLOR, cor);
                        }
//+------------------------------------------------------------------+
virtual void PositionAxleY(string szObjectName, int Y)
                        {
                                int desl = (int)(ObjectGetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_YSIZE) / 2);
                                ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_YDISTANCE, Y - desl);
                        }
//+------------------------------------------------------------------+
};


Notez que nous utilisons l'héritage pour assembler l'objet avec un minimum de code. Nous obtenons ainsi de la classe qu'elle se modifie et se modélise si nécessaire, de sorte que nous n'ayons plus à procéder à ces ajustements par la suite. On peut le voir dans le code mis en évidence, où la classe se positionne automatiquement au bon endroit simplement en connaissant la valeur de l'axe Y : elle vérifie la taille et se positionne de manière à se trouver au milieu de l'axe que nous lui transmettons.


2.0.1.3. Classe C_Object_TradeLine

La classe C_Object_TradeLine est chargée de remplacer la ligne horizontale qui était précédemment utilisée pour indiquer où se trouvait la ligne de prix de l'ordre. Cette classe est très intéressante. Regardez son code : elle possède une variable statique privée, comme vous pouvez le voir dans le code ci-dessous :

#property copyright "Daniel Jose"
#include "C_Object_BackGround.mqh"
//+------------------------------------------------------------------+
class C_Object_TradeLine : public C_Object_BackGround
{
        private :
                static string m_MemNameObj;
        public  :
//+------------------------------------------------------------------+

// ... Internal class code

//+------------------------------------------------------------------+
};
//+------------------------------------------------------------------+
string C_Object_TradeLine::m_MemNameObj = NULL;
//+------------------------------------------------------------------+


Elle est mise en évidence pour montrer comment la déclarer et comment l'initialiser correctement. Nous pourrions créer une variable globale pour remplacer la variable statique. Mais je veux garder le contrôle sur ces variables. De cette façon, chaque objet a tout ce dont il a besoin, et ils stockent directement l'information. Et si nous voulons remplacer un objet par un autre, nous pouvons facilement le faire.

La prochaine chose à laquelle il faut prêter attention est le code de création de l'objet :

void Create(string szObjectName, color cor)
{
        C_Object_BackGround::Create(szObjectName, cor);
        ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_XSIZE, TerminalInfoInteger(TERMINAL_SCREEN_WIDTH));
        SpotLight(szObjectName);
};


Pour l'implémenter correctement, nous utilisons la classe C_Object_BackGround, dans laquelle nous créons une boîte qui servira de ligne. Encore une fois, c'est parce que si un autre type d'objet était utilisé, nous n'aurions pas le même comportement que celui que nous avons maintenant. Et le seul objet qui fait ce dont nous avons besoin est celui qui est présent dans la classe C_Object_Background. Nous allons donc le modifier pour l'adapter à nos besoins, et pouvoir ainsi créer une ligne.

Nous verrons ensuite le code responsable de la mise en évidence d'une ligne.

void SpotLight(string szObjectName = NULL)
{
        if (szObjectName != NULL) ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_YSIZE, (szObjectName != NULL ? 4 : 3));
        if (m_MemNameObj != NULL) ObjectSetInteger(Terminal.Get_ID(), m_MemNameObj, OBJPROP_YSIZE, 3);
        m_MemNameObj = szObjectName;
};


Ce code est assez intéressant, car lorsque nous surlignons une ligne, nous n'avons pas besoin de savoir laquelle a été surlignée puisque l'objet lui-même le fait pour nous. Et lorsqu'une nouvelle ligne mérite d'être mise en évidence, l’ancienne ligne qui était mise en évidence perd automatiquement ce statut et la nouvelle ligne prend sa place. Maintenant, si aucune ligne ne doit être mise en évidence, il suffit d'appeler la fonction. Elle se chargera alors de supprimer la mise en évidence de n'importe quelle ligne.

Sachant cela, le code ci-dessus et le code suivant font disparaître l'ancien code de sélection. De cette façon, MetaTrader 5 nous permettra de savoir quel indicateur nous manipulons.

string GetObjectSelected(void) const { return m_MemNameObj; }


Une autre fonction mérite notre attention. Il positionne la ligne le long de l'axe Y. Nous le verrons plus loin.

virtual void PositionAxleY(string szObjectName, int Y)
{
        int desly = (m_MemNameObj == szObjectName ? 2 : 1);
        ObjectSetInteger(Terminal.Get_ID(), szObjectName, OBJPROP_YDISTANCE, Y - desly);
};


Comme la fonction présentée dans l'objet BackGround, cette fonction s'ajuste également au point correct, selon que la ligne est surlignée ou non.

Nous avons maintenant 2 objets entièrement terminés. Mais avant de pouvoir les voir à l'écran (comme indiqué ci-dessus), nous devons effectuer certaines opérations dans la classe C_ObjectsTrade.


2.0.2. Modification de la classe C_ObjectsTrade

Les modifications à apporter ne sont pas très compliquées à première vue. Mais le nombre de fois où nous devrons répéter le même code peut parfois être un peu décourageant. C'est pourquoi j'ai essayé de trouver un moyen de contourner ce problème. La première chose que nous allons faire est de créer une énumération d'événements. Nous allons utiliser des macros. Mais si vous trouvez qu'il est déroutant de suivre un code rempli de macros, n'hésitez pas à basculer vers des fonctions ou procédures et, dans les cas extrêmes, à remplacer les macros par un code interne approprié. Je préfère utiliser des macros, car je le fais depuis de nombreuses années.

Tout d'abord, nous créons une énumération d'événements :

enum eEventType {EV_GROUND = 65, EV_LINE};


Au fur et à mesure que des objets sont créés, nous devons ajouter de nouveaux événements ici. Cependant, chaque objet n'aura qu'un seul type d'événement. Cet événement sera généré par MetaTrader 5, ou le code ne fera que s'assurer que l'événement est traité correctement :

Une fois cela fait, nous créons des variables qui permettront d'accéder à chacun des objets.

C_Object_BackGround     m_BackGround;
C_Object_TradeLine      m_TradeLine;


Ils sont dans la portée globale de la classe, mais ils restent privés. Nous pourrions les déclarer dans chaque fonction qui les utilise, mais cela n'a pas beaucoup de sens puisque la classe entière s'occupera des objets.

Nous effectuons donc la modification correspondante dans le code de l'article précédent.

inline string MountName(ulong ticket, eIndicatorTrade it, eEventType ev)
{
        return StringFormat("%s%c%c%c%d%c%c", def_NameObjectsTrade, def_SeparatorInfo, (char)it, def_SeparatorInfo, ticket, def_SeparatorInfo, (char)ev);
}


Les parties mises en évidence n'existaient pas dans la version précédente, mais elles aideront désormais MetaTrader 5 à nous tenir informés de ce qui se passe.

Nous avons également une nouvelle fonction:

void SetPositionMinimalAxleX(void)
{
        m_PositionMinimalAlxeX = (int)(ChartGetInteger(ChartID(), CHART_WIDTH_IN_PIXELS) * 0.2);
}


Elle crée un point de départ le long de l'axe X pour les objets. Chacun des objets aura un certain point. Mais nous devons fournir un point de départ. Vous pouvez le modifier en changeant simplement le point dans le code ci-dessus.

La fonction de sélection a subi de nombreuses modifications. Elle en subira encore d'autres un peu plus tard. A l'heure actuelle, elle se présente comme suit :

inline void Select(const string &sparam)
{
        ulong tick;
        double price;
        eIndicatorTrade it;
        eEventType ev;
        string sz = sparam;
                                
        if (!GetInfosOrder(sparam, tick, price, it, ev)) sz = NULL;
        m_TradeLine.SpotLight(sz);
}


Une autre fonction qui a également changé est celle qui crée l'indicateur lui-même :

inline void CreateIndicatorTrade(ulong ticket, double price, eIndicatorTrade it, bool select)
{
        if (price <= 0) RemoveIndicatorTrade(ticket, it); else
        {
                CreateIndicatorTrade(ticket, it, select);
                PositionAxlePrice(price, ticket, it, -1, -1, 0, false);
        }
}

Le code ci-dessus n'est pas très important. Le code ci-dessous montre ce qui fait vraiment tout le travail :

inline void CreateIndicatorTrade(ulong ticket, eIndicatorTrade it)
{
        color cor1, cor2;
        string sz0;
                                
        switch (it)
        {
                case IT_TAKE    :
                        cor1 = clrPaleGreen;
                        cor2 = clrDarkGreen;
                        break;
                case IT_STOP    :
                        cor1 = clrCoral;
                        cor2 = clrMaroon;
                        break;
                case IT_PENDING:
                default:
                        cor1 = clrGold;
                        cor2 = clrDarkGoldenrod;
                        break;
        }                               
        m_TradeLine.Create(MountName(ticket, it, EV_LINE), cor2);
        if (ticket == def_IndicatorTicket0) m_TradeLine.SpotLight(MountName(ticket, IT_PENDING, EV_LINE));
        m_BackGround.Create(sz0 = MountName(ticket, it, EV_GROUND), cor1);
        switch (it)
        {
                case IT_TAKE:
                case IT_STOP:
                        m_BackGround.Size(sz0, 92, 22);
                        break;
                case IT_PENDING:
                        m_BackGround.Size(sz0, 110, 22);
                        break;
        }
}

Dans cette fonction, nous déterminons les couleurs, les tailles et la séquence de création des objets. Tout objet ajouté à l'indicateur doit être placé à l'aide de cette fonction afin qu’il soit bien centré et toujours vérifié. Si vous commencez à créer une fonction pour créer des indicateurs, vous obtiendrez un type de code difficile à maintenir et dans lequel les bonnes vérifications peuvent manquer. Vous pouvez penser que tout va bien, que tout fonctionne, et vous le placez sur un compte réel. Ce n'est qu'à ce moment-là qu'il sera réellement vérifié et que vous vous rendrez soudain compte que certaines choses ne fonctionnent pas correctement. Voici un conseil : essayez toujours d'assembler des fonctions à l'intérieur de choses qui font le même travail. Même si cela semble inutile au début, cela prendra du sens avec le temps, car vous serez toujours en train de vérifier des choses qui changent.

La fonction suivante a été modifiée :

#define macroDelete(A)  {                                                               \
                ObjectDelete(Terminal.Get_ID(), MountName(ticket, A, EV_GROUND));       \
                ObjectDelete(Terminal.Get_ID(), MountName(ticket, A, EV_LINE));         \
                        }
                                        
inline void RemoveIndicatorTrade(ulong ticket, eIndicatorTrade it = IT_NULL)
                        {
                                ChartSetInteger(Terminal.Get_ID(), CHART_EVENT_OBJECT_DELETE, false);
                                if ((it != NULL) && (it != IT_PENDING) && (it != IT_RESULT)) macroDelete(it)
                                else
                                {
                                        macroDelete(IT_PENDING);
                                        macroDelete(IT_RESULT);
                                        macroDelete(IT_TAKE);
                                        macroDelete(IT_STOP);
                                }
                                ChartSetInteger(Terminal.Get_ID(), CHART_EVENT_OBJECT_DELETE, true);
                        }
#undef macroDelete


Comme la fonction d’après, cela est un peu ennuyeux. La fonction doit fonctionner de manière à ce que ce soit vous qui sélectionniez un à un les objets créés. Cela doit s'appliquer à chacun des indicateurs. Pensez-y. Si nous n'utilisions pas une macro pour nous faciliter la tâche, ce serait un cauchemar. Il serait extrêmement fastidieux de coder cette fonction, puisque chaque indicateur à la fin du code contiendra 5 objets. Sachant que chaque ensemble d'un ordre OCO comporte 3 indicateurs, cela signifie que nous devons utiliser 15 objets, auquel cas les chances de se tromper (car la différence entre eux n'est que le nom) sont énormes. Ainsi, grâce à une macro, le code est réduit à ce qui est mis en évidence dans le code : nous ne coderons que 5 objets à la fin. Mais il ne s'agit là que de la première phase pour obtenir le résultat que nous attendons.

Pour compléter la première phase, nous devons écrire une autre fonctionnalité tout aussi fastidieuse. Notez que nous pourrions utiliser des procédures à la place des macros. Mais j’ai choisi d’utiliser des macros plutôt.

#define macroSetAxleY(A)        {                                               \
                m_BackGround.PositionAxleY(MountName(ticket, A, EV_GROUND), y); \
                m_TradeLine.PositionAxleY(MountName(ticket, A, EV_LINE), y);    \
                                }
                                                                        
#define macroSetAxleX(A, B)     {                                               \
                m_BackGround.PositionAxleX(MountName(ticket, A, EV_GROUND), B); \
                m_TradeLine.PositionAxleX(MountName(ticket, A, EV_LINE), B);    \
                                }

inline void PositionAxlePrice(double price, ulong ticket, eIndicatorTrade it, int FinanceTake, int FinanceStop, int Leverange, bool isBuy)
                        {
                                double ad;
                                int x, y;
                                
                                ChartTimePriceToXY(Terminal.Get_ID(), 0, 0, price, x, y);
                                macroSetAxleY(it);
                                macroSetAxleX(it, m_PositionMinimalAlxeX);
                                if (Leverange == 0) return;
                                if (it == IT_PENDING)
                                {
                                        ad = Terminal.GetAdjustToTrade() / (Leverange * Terminal.GetVolumeMinimal());
                                        ChartTimePriceToXY(Terminal.Get_ID(), 0, 0, price + Terminal.AdjustPrice(FinanceTake * (isBuy ? ad : (-ad))), x, y);
                                        macroSetAxleY(IT_TAKE);
                                        macroSetAxleX(IT_TAKE, m_PositionMinimalAlxeX + 120);
                                        ChartTimePriceToXY(Terminal.Get_ID(), 0, 0, price + Terminal.AdjustPrice(FinanceStop * (isBuy ? (-ad) : ad)), x, y);
                                        macroSetAxleY(IT_STOP);
                                        macroSetAxleX(IT_STOP, m_PositionMinimalAlxeX + 220);
                                }
                        }
#undef macroSetAxleX
#undef macroSetAxleY


Si vous pensez que la rubrique précédente était ennuyeuse, alors jetez un coup d'œil à celle-ci. Ici, le travail devrait être doublé. Mais grâce aux codes mis en évidence, cela devient acceptable.

Lorsque nous exécutons ce code, nous obtenons exactement ce que nous attendons, à savoir l'indication qui apparaît à l'écran.


Conclusion

Il reste encore un peu de temps avant que le système ne soit achevé et ne puisse afficher l'ordre directement sur le graphique. Mais cela doit être fait en une seule fois, car il est nécessaire d'apporter des changements très importants à d'autres endroits du code.

Nous laisserons donc cela pour le prochain article, car les changements seront conséquents. Et si quelque chose ne va pas, vous devrez revenir en arrière et réessayer jusqu'à ce que vous puissiez modifier le système comme vous le souhaitez. De cette manière, vous pouvez personnaliser le système. Dans le prochain article, nous obtiendrons le système illustré ci-dessous :


Cela semble facile à mettre en œuvre, non ? Mais croyez-moi, il y a beaucoup de changements à faire. Je vous donne donc rendez-vous dans notre prochain article.

Traduit du portugais par MetaQuotes Ltd.
Article original : https://www.mql5.com/pt/articles/10497

Algorithmes d'optimisation de la population : Colonie d'Abeilles Artificielles (ABC) Algorithmes d'optimisation de la population : Colonie d'Abeilles Artificielles (ABC)
Dans cet article, nous étudierons l'algorithme d'une colonie d'abeilles artificielles. Nous compléterons nos connaissances avec de nouveaux principes d'étude des espaces fonctionnels. Dans cet article, je présenterai mon interprétation de la version classique de l'algorithme.
Algorithmes d'optimisation de la population : Optimisation des Colonies de Fourmis (Ant Colony Optimization - ACO) Algorithmes d'optimisation de la population : Optimisation des Colonies de Fourmis (Ant Colony Optimization - ACO)
Cette fois, je vais analyser l'algorithme d'Optimisation des Colonies de Fourmis. L'algorithme est très intéressant et complexe. Dans cet article, je tente de créer un nouveau type d'ACO.
Développer un Expert Advisor de trading à partir de zéro (Partie 21) : Nouveau système d'ordres (IV) Développer un Expert Advisor de trading à partir de zéro (Partie 21) : Nouveau système d'ordres (IV)
Le système visuel commence enfin à fonctionner, même s'il n'est pas encore achevé. Nous allons terminer ici les principales modifications. Il y en aura plusieurs, mais elles sont toutes nécessaires. L'ensemble du travail sera très intéressant.
Apprendre à concevoir un système de trading basé sur la Puissance des Baissiers (Bears Power) Apprendre à concevoir un système de trading basé sur la Puissance des Baissiers (Bears Power)
Bienvenue dans ce nouvel article de notre série consacrée à l'apprentissage de la conception d'un système de trading à l'aide des indicateurs techniques les plus populaires. Voici un nouvel article consacré à l'apprentissage de la conception d'un système de trading à l'aide de l'indicateur technique Bear's Power ou Puissance des Baissiers.