English Русский 中文 Español Deutsch 日本語 Português 한국어 Italiano Türkçe
preview
Développer un Expert Advisor à partir de zéro (partie 10) : Accéder aux indicateurs personnalisés

Développer un Expert Advisor à partir de zéro (partie 10) : Accéder aux indicateurs personnalisés

MetaTrader 5Systèmes de trading | 21 novembre 2022, 09:25
798 0
Daniel Jose
Daniel Jose

Introduction

Un EA commercial ne peut être vraiment utile que s'il peut utiliser des indicateurs personnalisés. Sinon, ce n'est qu'un ensemble de lignes de codes et d'instructions, qui peuvent être bien conçus, aider à gérer des positions ou à exécuter des transactions sur le marché. Mais c'est probablement tout.

Et pourtant, l'ajout d'indicateurs sur un graphique MetaTrader 5 n'est pas la partie la plus difficile. Mais accéder aux données calculées par ces indicateurs directement depuis l'Expert Advisor, sans une bonne planification, devient une tâche presque impossible. Et si quelqu’un ne sait pas comment faire, il n’est alors limité qu'aux indicateurs standards. Alors que nous avons besoin de bien plus pour le trading. Par exemple, l'indicateur VWAP (Volume Weighted Average Price). C'est une moyenne mobile très importante pour quiconque trade des contrats à terme sur la bourse brésilienne. Cette Moyenne n'est pas présentée parmi les indicateurs standard dans MetaTrader. Mais nous pouvons créer un indicateur personnalisé qui calculera le VWAP et l'affichera à l'écran. Mais les choses se compliquent beaucoup lorsque nous voulons utiliser ce même indicateur dans un système qui sera analysé dans l'EA. Sans les bonnes connaissances, nous ne pourrons pas utiliser cet indicateur personnalisé dans un EA. Dans cet article, nous allons voir comment contourner cette limitation et résoudre le problème.


Plan

En premier lieu, créons les calculs à utiliser dans notre indicateur personnalisé. Heureusement, la formule de calcul du VWAP, que nous allons utiliser comme exemple dans cet article, est assez simple :


Une fois traduit en langage MQL5, nous obtenons ce qui suit :

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{
        double          Price = 0;
        ulong           Volume = 0;
        static int      siPos = 0;

        if (macroGetDate(time[rates_total - 1]) != macroGetDate(time[siPos]))
        {
                for (int c0 = rates_total - 1; macroGetDate(time[siPos]) != macroGetDate(time[c0]); siPos++);
                ArrayInitialize(VWAP_Buff, EMPTY_VALUE);
        }
        for (int c0 = siPos; c0 < rates_total; c0++)
        {
                Price += ((high[c0] + low[c0] + close[c0]) / 3) * volume[c0];
                Volume += volume[c0];
                VWAP_Buff[c0] = Price / Volume;
        }

    return rates_total;
}

La ligne des calculs est mise en surbrillance. Le reste de la fonction est utilisé pour une initialisation correcte de DAILY VWAP. Cependant, notre indicateur ne peut toujours pas être exécuté sur le graphique et nous devons ajouter quelques éléments supplémentaires dans le code. Le reste du code est visible ci-dessous :

#property copyright "Daniel Jose - Indicador VWAP ( IntraDay )"
#property version "1.01"
#property indicator_chart_window
#property indicator_buffers     1
#property indicator_plots       1
#property indicator_width1      2
#property indicator_type1 	DRAW_LINE
#property indicator_color1 	clrBlack
//+------------------------------------------------------------------+
#define macroGetDate(A) (A - (A % 86400))
//+------------------------------------------------------------------+
double VWAP_Buff[];
//+------------------------------------------------------------------+
int OnInit()
{
        SetIndexBuffer(0, VWAP_Buff, INDICATOR_DATA);   
        
        return INIT_SUCCEEDED;
}

Cela permet la possibilité d'avoir le VWAP sur un graphique comme indiqué précédemment :


Cette partie n'était pas trop compliquée. Nous devons maintenant trouver un moyen de faire en sorte que l'EA voit le VWAP, afin qu'il analyse l'indicateur d'une manière spécifique. Cela permettra d’utiliser l'indicateur en trading.

Pour un travail plus facile avec l'indicateur, enregistrons le VWAP afin qu'il soit facilement accessible.


Nous pouvons ensuite sauter dans un nouveau problème. Bien que l'indicateur VWAP soit correct, il est mal programmé pour être utilisé dans un EA. Mais pourquoi ? Le problème est que l'EA ne peut pas savoir si l'indicateur est visible sur le graphique ou non. Il ne peut pas lire l'indicateur sans le savoir.

Le nom de fichier importe peu au système. Vous pouvez écrire n'importe quel nom dans le fichier. Mais le nom de l'indicateur doit refléter ce qu'il calcule. Et notre indicateur n'a pas encore de nom qui le reflète correctement. Même s'il s'appelait "VWAP", cela ne signifierait rien pour le système. Pour cette raison, l'EA ne peut pas savoir si l'indicateur est présent ou non sur le graphique.

Pour que l'indicateur reflète ce qu'il calcule, nous devons l'indiquer dans le code. Nous créerons donc un nom unique qui ne sera pas nécessairement lié au nom du fichier. Dans notre cas, le code d'initialisation de l'indicateur devrait ressembler à ceci. Dans notre cas, le code d'initialisation de l'indicateur devrait ressembler à ceci :

int OnInit()
{
        SetIndexBuffer(0, VWAP_Buff, INDICATOR_DATA);   
        IndicatorSetString(INDICATOR_SHORTNAME, "VWAP");
        
        return INIT_SUCCEEDED;
}

En ajoutant simplement la ligne en surbrillance, nous résolvons le problème. Dans certains cas toutefois, cela peut être plus difficile - nous y reviendrons plus tard. Utilisons tout d’abord le code de l'indicateur CUSTOM MOVING AVERAGE de la bibliothèque MetaTrader 5 comme exemple. Voici son code :

void OnInit()
{
	SetIndexBuffer(0,ExtLineBuffer,INDICATOR_DATA);
	IndicatorSetInteger(INDICATOR_DIGITS,_Digits+1);
	PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,InpMAPeriod);
	PlotIndexSetInteger(0,PLOT_SHIFT,InpMAShift);

	string short_name;
	switch(InpMAMethod)
	{
      		case MODE_EMA :
			short_name="EMA";
         		break;
      		case MODE_LWMA :
	         	short_name="LWMA";
	         	break;
      		case MODE_SMA :
         		short_name="SMA";
         		break;
      		case MODE_SMMA :
         		short_name="SMMA";
         		break;
      		default :
         		short_name="unknown ma";
     	}
   	IndicatorSetString(INDICATOR_SHORTNAME, short_name + "(" + string(InpMAPeriod) + ")");
   	PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
}

La partie en surbrillance indique le nom que nous voulons et dont nous avons besoin. Et cela n'a rien à voir avec le nom du fichier. Mais il faut que ce soit fait à dans le code de l'indicateur personnalisé.

Maintenant que cela est fait et que nous nous sommes assurés que l'EA sera en mesure de vérifier si l'indicateur personnalisé s'exécute ou non sur le graphique, nous pouvons passer à l'étape suivante.


Accéder à l'indicateur depuis l'EA

Nous pouvons continuer à faire comme nous l'avons fait auparavant. Mais idéalement, pour vraiment comprendre ce qui se passe, il est préférable de créer un code complètement nouveau. Puisque l'idée est d'apprendre à développer un Expert Advisor à partir de zéro, passons à cette étape. Dans la suite de notre parcours, nous créerons donc un Expert Advisor isolé. Et nous pouvons ensuite l'inclure ou non dans le code final. Passons à l'écriture du code. L'EA commence par un code propre, comme vous pouvez le voir ci-dessous :

//+------------------------------------------------------------------+
int OnInit()
{
        EventSetTimer(1);
        return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
        EventKillTimer();
}
//+------------------------------------------------------------------+
void OnTick(){}
//+------------------------------------------------------------------+
void OnTimer(){}
//+------------------------------------------------------------------+

Ensuite, nous supposerons que l'indicateur VWAP est sur le graphique et nous chargerons la dernière valeur calculée par l'indicateur dans l'Expert Advisor. Et nous répéterons cela chaque seconde. Mais comment faire ? C'est simple. Voyez à quoi ressemble le code de l’EA après le changement :

#property copyright "Daniel Jose"
#property version   "1.00"
//+------------------------------------------------------------------+
int     handle;
double  Buff[];
//+------------------------------------------------------------------+
int OnInit()
{
        handle = ChartIndicatorGet(ChartID(), 0, "VWAP");
        SetIndexBuffer(0, Buff, INDICATOR_DATA);
        
        EventSetTimer(1);
        return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
        EventKillTimer();
}
//+------------------------------------------------------------------+
void OnTick()
{
}
//+------------------------------------------------------------------+
void OnTimer()
{
        int i;
        
        if (handle != INVALID_HANDLE)
        {
                i = CopyBuffer(handle, 0, 0, 1, Buff);
                Print(Buff[0]);
        }
}
//+------------------------------------------------------------------+

Les parties surlignées sont celles que nous avons ajoutées. Voici le résultat sur le graphique :


Pourquoi cela fonctionne t-il ? MQL5 fournit des moyens de lire et d'écrire des données entre les systèmes. L'une des façons de lire consiste à utiliser la fonction CopyBuffer. Cela fonctionne comme illustré ci-dessous :


Nous pouvons ainsi lire les données de n'importe quel indicateur personnalisé. C'est-à-dire que nous ne sommes pas limités aux indicateurs standard de MetaTrader 5. Cela signifie que nous pouvons créer n'importe quel indicateur et que cela fonctionnera.

Nous pouvons maintenant considérer un autre scénario. Cette fois, le VWAP n'est pas sur le graphique. Mais l'EA en a besoin. Nous devons donc le charger sur le graphique. Comment faire ça ? C'est assez simple également. Nous l'avons en fait déjà utilisé à d'autres fins, lors de la création d'une sous-fenêtre pour l'Expert Advisor. Nous allons maintenant utiliser la fonction iCustom. Mais nous allons cette fois charger un indicateur personnalisé. Le code de l’EA ressemblera à ceci :

#property copyright "Daniel Jose"
#property version   "1.00"
//+------------------------------------------------------------------+
int     handle;
double  Buff[];
//+------------------------------------------------------------------+
int OnInit()
{
        handle = ChartIndicatorGet(ChartID(), 0, "VWAP");
        SetIndexBuffer(0, Buff, INDICATOR_DATA);
        
        EventSetTimer(1);
        return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
        EventKillTimer();
}
//+------------------------------------------------------------------+
void OnTick()
{
}
//+------------------------------------------------------------------+
void OnTimer()
{
        int i;
        
        if (handle == INVALID_HANDLE) handle = iCustom(NULL, PERIOD_CURRENT, "VWAP.EX5");else
        {
                i = CopyBuffer(handle, 0, 0, 1, Buff);
                Print(Buff[0]);
        }
}
//+------------------------------------------------------------------+

Le code en surbrillance est le seul ajout que nous ayons fait au système d'origine. L'exécution de l'EA produit maintenant le résultat suivant :


La figure ci-dessous illustre ce que nous avons implémenté :

C'est tout ce dont vous avez besoin au niveau le plus élémentaire. Mais si vous regardez attentivement, vous remarquerez que l’indicateur VWAP n'est pas visible sur le graphique. Même si l'EA l'utilise, l'utilisateur ne sait pas ce qui se passe. Cela peut également être facilement corrigé. Le code final ressemble à celui ci-dessous. N'oubliez pas ceci : il est toujours bon de pouvoir analyser et observer ce que fait l'EA, car ce n’est pas très sûr de le laisser en totale autonomie. Je ne recommanderais donc pas de le faire :

#property copyright "Daniel Jose"
#property version   "1.00"
//+------------------------------------------------------------------+
int     handle;
long    id;
double  Buff[];
string  szCmd;
//+------------------------------------------------------------------+
int OnInit()
{
        szCmd = "VWAP";
        handle = ChartIndicatorGet(id = ChartID(), 0, szCmd);
        SetIndexBuffer(0, Buff, INDICATOR_DATA);
        
        EventSetTimer(1);
        return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
        ChartIndicatorDelete(id, 0, szCmd);
        IndicatorRelease(handle);
        EventKillTimer();
}
//+------------------------------------------------------------------+
void OnTick()
{
}
//+------------------------------------------------------------------+
void OnTimer()
{
        int i;
        
        if (handle == INVALID_HANDLE)
        {
                if ((handle = iCustom(NULL, PERIOD_CURRENT, "VWAP.EX5")) != INVALID_HANDLE)
                        ChartIndicatorAdd(id, 0, handle);
        }else
        {
                i = CopyBuffer(handle, 0, 0, 1, Buff);
                Print(Buff[0]);
        }
}
//+------------------------------------------------------------------+

Le code ci-dessus lira la dernière valeur calculée par le VWAP et l'affichera à l'écran. Si l'indicateur n'est pas sur le graphique, il sera chargé puis affiché. Si nous supprimons l'EA du graphique, le VWAP sera également supprimé de l'écran. Ainsi, l'EA aura toujours les éléments dont il a besoin pour effectuer ses calculs. Les résultats sont présentés ci-dessous :


On pourrait penser que ce n'est pas faisable, puisque nous n'avons évidemment apporté aucun changement à l'indicateur. Mais même avec les étapes ci-dessus, nous pouvons implémenter tout ce qui concerne les indicateurs personnalisés. Considérons un autre exemple pour une dernière explication. Appliquons une moyenne mobile et utilisons l'Expert Advisor de la même manière qu’avec le VWAP. Mais spécifions maintenant les paramètres de la moyenne.


Deuxième cas : utiliser des moyennes mobiles

Le calcul de la moyenne mobile n'est pas important ici. Nous nous concentrerons sur la façon de passer des paramètres dans un indicateur personnalisé. Voici le nouvel indicateur personnalisé :

#property copyright "Daniel Jose 16.05.2021"
#property description "Basic Moving Averages (Optimizes Calculation)"
#property indicator_chart_window
//+------------------------------------------------------------------+
enum eTypeMedia
{
        MME,    //Exponential moving average
        MMA     //Arithmetic moving average
};
//+------------------------------------------------------------------+
#property indicator_buffers             1
#property indicator_plots               1
#property indicator_type1               DRAW_LINE
#property indicator_width1              2
#property indicator_applied_price       PRICE_CLOSE
//+------------------------------------------------------------------+
input color      user00 = clrRoyalBlue; //Cor
input int        user01 = 9;            //Periods
input eTypeMedia user02 = MME;          //MA type
input int user03 = 0;            //Displacement
//+------------------------------------------------------------------+
double Buff[], f_Expo;
//+------------------------------------------------------------------+
int OnInit()
{
        string sz0 = "MM" + (user02 == MME ? "E": (user02 == MMA ? "A" : "_")) + (string)user01;
        
        f_Expo = (double) (2.0 / (1.0 + user01));
        ArrayInitialize(Buff, EMPTY_VALUE);
        SetIndexBuffer(0, Buff, INDICATOR_DATA);
        PlotIndexSetInteger(0, PLOT_LINE_COLOR, user00);
        PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, user01);
        PlotIndexSetInteger(0, PLOT_SHIFT, user03);
        IndicatorSetString(INDICATOR_SHORTNAME, sz0);
        
        return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
{
        double Value;
        int c0;

        switch (user02)
        {
                case MME:
                        if (user01 < rates_total)
                        {       
                                for (c0 = (prev_calculated > 0 ? prev_calculated - 1 : 0); c0 < rates_total - user03; c0++)
                                        Buff[c0] = (c0 > 0? ((price[c0] - Buff[c0 - 1]) * f_Expo) + Buff[c0 - 1] : price[c0] * f_Expo);
                                for (; c0 < rates_total; c0++)
                                        Buff[c0] = EMPTY_VALUE;
                        }
                        break;
                case MMA:
                        if (user01 < rates_total)
                        {
                                if (prev_calculated == 0) 
                                {       
                                        Value = 0;
                                        for (int c1 = 0; c1 < user01; c1++) Value += price[user01 - c1];
                                        Buff[user01] = Value / user01;
                                }
                                for (c0 = (prev_calculated > 0 ? prev_calculated - 1 : user01 + 1); c0 < rates_total - user03; c0++)
                                        Buff[c0] = ((Buff[c0 - 1] * user01) - price[c0 - user01] + price[c0]) / user01;
                                for (; c0 < rates_total; c0++)
                                        Buff[c0] = EMPTY_VALUE;
                        }
                        break;
        }
        
        return rates_total;
}
//+------------------------------------------------------------------+

Le nom de l'indicateur dépendra maintenant de plusieurs facteurs. Nous pourrons ensuite faire en sorte que l’EA vérifie et s’adapte à chaque situation. Par exemple, disons que notre EA utilise 2 moyennes mobiles et les affiche sur le graphique. Faites attention aux parties surlignées dans le code ci-dessus : l'activation de l'EA, et la fonction iCustom dans ce cas, pour modifier et configurer les paramètres de l'indicateur. Ceci est important à comprendre afin de pouvoir le mettre en œuvre si besoin. L'une des moyennes est une moyenne mobile exponentielle à 17 périodes et l'autre est une moyenne mobile simple à 52 périodes. La MA de 17 périodes sera verte et celle de 52 périodes sera rouge. Et l'EA verra l'indicateur comme une fonction sous la forme suivante :

Moyenne (couleur, période, type, décalage) donc maintenant l'indicateur n'est pas un fichier séparé mais une fonction de l’EA. Ceci est très courant en programmation car nous appelons un programme avec les bons paramètres pour exécuter une certaine tâche et à la fin nous obtenons le résultat plus facilement. Mais la question est la suivante : Comment faire en sorte que notre EA crée et gère ce scénario de la même manière que nous l'avons fait avec le VWAP ?

Pour cela, nous devons changer le code de l’EA. Le code complet du nouvel EA est présenté ci-dessous :

#property copyright "Daniel Jose"
#property version   "1.00"
//+------------------------------------------------------------------+
long    id;
int     handle1, handle2;
double  Buff1[], Buff2[];
string  szCmd1, szCmd2;
//+------------------------------------------------------------------+
int OnInit()
{
        szCmd1 = "MME17";
        szCmd2 = "MMA52";
        id = ChartID();
        handle1 = ChartIndicatorGet(id, 0, szCmd1);
        handle2 = ChartIndicatorGet(id, 0, szCmd2);
        SetIndexBuffer(0, Buff1, INDICATOR_DATA);
        SetIndexBuffer(0, Buff2, INDICATOR_DATA);
        
        EventSetTimer(1);
        return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
        ChartIndicatorDelete(id, 0, szCmd1);
        ChartIndicatorDelete(id, 0, szCmd2);
        IndicatorRelease(handle1);
        IndicatorRelease(handle2);
        EventKillTimer();
}
//+------------------------------------------------------------------+
void OnTick()
{
}
//+------------------------------------------------------------------+
void OnTimer()
{
        int i1, i2;
        
        if (handle1 == INVALID_HANDLE)
        {
                if ((handle1 = iCustom(NULL, PERIOD_CURRENT, "Media Movel.EX5", clrGreen, 17, 0)) != INVALID_HANDLE)
                        ChartIndicatorAdd(id, 0, handle1);
        };
        if (handle2 == INVALID_HANDLE)
        {
                if ((handle2 = iCustom(NULL, PERIOD_CURRENT, "Media Movel.EX5", clrRed, 52, 1)) != INVALID_HANDLE)
                        ChartIndicatorAdd(id, 0, handle2);
        };
        if ((handle1 != INVALID_HANDLE) && (handle2 != INVALID_HANDLE))
        {
                i1 = CopyBuffer(handle1, 0, 0, 1, Buff1);
                i2 = CopyBuffer(handle2, 0, 0, 1, Buff2);
                Print(Buff1[0], "<< --- >>", Buff2[0]);
        }
}
//+------------------------------------------------------------------+

Et voici son résultat:


Faites bien attention aux parties surlignées du code de l’EA. C'est exactement ce dont nous avons besoin : nous passons des paramètres à l'indicateur en utilisant le même mécanisme que celui que nous avons utilisé dans le VWAP. Cependant, dans le cas du VWAP, il n'y avait pas besoin de passer de paramètres, contrairement aux moyennes mobiles pour lesquelles la période doit être passée. Tout cela offre une très grande liberté.


Conclusion

Cet article ne contient pas un code universel. Mais nous sommes entrés dans les détails de 2 Expert Advisors différents et de 2 indicateurs personnalisés différents, pour comprendre comment utiliser ce type de système dans un Expert Advisor plus complexe et réfléchi. Je crois qu'avec ces connaissances, nous pouvons utiliser nos propres indicateurs personnalisés. Et même notre propre EA peut fournir une analyse très intéressante. Tout cela prouve que MetaTrader 5 est la plateforme la plus polyvalente qu'un trader puisse désirer. Si quelqu'un ne l’a pas compris, c'est qu'il ne l'a tout simplement pas étudié jusqu'au bout.

Utilisez les connaissances présentées dans cet article, car MetaTrader 5 vous permet d'aller beaucoup plus loin que beaucoup n'ont pu le faire jusqu'à présent.

Rendez-vous dans le prochain article.


Liens

Comment appeler des indicateurs en MQL5

Indicateurs personnalisés MQL5 pour les débutants

MQL5 pour les nuls : Guide d'utilisation des indicateurs techniques dans les Expert Advisors



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

Développer un Expert Advisor à partir de zéro (partie 11) : Système d’ordre croisés Développer un Expert Advisor à partir de zéro (partie 11) : Système d’ordre croisés
Dans cet article, nous allons créer un système d’ordres croisés. Il existe un type d'actifs qui rend la vie des traders très difficile : les contrats à terme. Mais pourquoi ?
Comment créer des graphiques 3D avec DirectX dans MetaTrader 5 Comment créer des graphiques 3D avec DirectX dans MetaTrader 5
Les graphiques 3D constituent un excellent moyen d'analyser de grosses quantités de données, car ils permettent de visualiser des choses cachées. Ces tâches peuvent être faites directement dans MQL5, et les fonctions DireсtX permettent de créer des objets tridimensionnels. Il est ainsi possible de créer des programmes de n’importe quelle complexité, même des jeux en 3D pour MetaTrader 5. Vous pouvez commencer à apprendre les graphiques 3D en dessinant des formes tridimensionnelles simples.
Apprenez à concevoir un système de trading basé sur l’OBV Apprenez à concevoir un système de trading basé sur l’OBV
Ceci est un nouvel article de notre série pour les débutants sur la façon de concevoir un système de trading basé sur certains des indicateurs les plus populaires. Nous apprendrons un nouvel indicateur qui est l’On Balance Volume (OBV), et nous apprendrons comment nous pouvons l'utiliser et concevoir un système de trading basé dessus.
SQLite Gestion native des bases de données SQL dans MQL5 SQLite Gestion native des bases de données SQL dans MQL5
Le développement de stratégies de trading est associé à la manipulation de grandes quantités de données. Vous êtes désormais en mesure de travailler avec des bases de données en utilisant des requêtes SQL basées sur SQLite directement dans MQL5. Une caractéristique importante de ce moteur de base de données est que la totalité de la base de données est placée dans un seul fichier situé sur le PC de l'utilisateur.