English Русский 中文 Español Deutsch 日本語 Português
preview
Comprendre les fonctions dans MQL5 avec des applications

Comprendre les fonctions dans MQL5 avec des applications

MetaTrader 5Trading |
49 23
Mohamed Abdelmaaboud
Mohamed Abdelmaaboud

Introduction

Dans le monde de la programmation, il existe un terme très populaire que l'on utilise et que l'on entend souvent en raison de son importance dans tout logiciel : les fonctions. Dans cet article, nous allons aborder cette notion en détail pour apprendre à créer des logiciels très fonctionnels et de grande qualité. Nous allons essayer de couvrir ce sujet important pour apprendre ce que sont les fonctions, pourquoi nous avons besoin d'utiliser des fonctions et comment les utiliser dans nos applications. Nous partagerons ensuite quelques fonctions simples qui peuvent être utilisées dans n'importe quel système de trading comme exemples. Les points suivants sont les idées principales que nous allons partager dans cet article pour couvrir ce sujet intéressant :

Avertissement : Toutes les informations données dans cet article sont fournies "en l'état", uniquement à des fins d'information et ne sont aucunement données à des fins de trading ou de conseil. Ces informations ne garantissent aucun type de résultat. Si vous utilisez le contenu de cet article sur l'un de vos comptes de trading, vous le faites à vos propres risques et vous en serez le seul responsable.


Définition de la fonction

Dans cette partie, nous identifierons les fonctions en programmation, leurs types et les raisons pour lesquelles nous devons les utiliser. La fonction est un bloc de code déclaré par un nom explicite et significatif qui peut être utilisé dans n'importe quelle autre partie du logiciel en l'appelant à plusieurs reprises pour effectuer une tâche spécifique. Si nous avons une tâche spécifique que le logiciel doit effectuer dans plusieurs parties de notre logiciel ou dans plusieurs logiciels, nous créons une fonction ou un bloc de code pour effectuer cette tâche et l'appeler uniquement dans ces parties sans réécrire le code complet. Nous pouvons donc dire que la fonction est une méthode pour abstraire notre code sans avoir beaucoup de code désordonné, comme nous le verrons dans cet article. Il existe 2 types principaux de fonctions : les fonctions intégrées et les fonctions définies par l'utilisateur. La fonction intégrée est la fonction prête à l'emploi par le langage de programmation lui-même, tandis que la fonction définie par l'utilisateur est la fonction qui peut être créée par l'utilisateur en fonction de ses besoins ou des tâches qu'il souhaite que le logiciel accomplisse. Dans cet article, nous nous concentrerons sur les fonctions définies par l'utilisateur. Nous allons donc étudier ce type de fonction en détail afin de voir pourquoi nous devons l'utiliser, quelle est son importance ou quelles sont ses caractéristiques.

Disons que nous avons besoin que le logiciel exécute la tâche de fermer tous les ordres ouverts si le solde a atteint un drawdown maximum. Cette tâche doit être exécutée dans plusieurs parties du logiciel. Il sera préférable ici de créer une fonction et d'inclure tout le code ou la logique nécessaire pour exécuter cette tâche, puis d'appeler cette fonction dans d'autres parties. Il serait au contraire mauvais d'écrire et de répéter le même code dans plusieurs parties pour exécuter la tâche.

Si vous vous demandez pourquoi nous devons utiliser ce type de fonction, la réponse à cette question nous amènera à apprendre les caractéristiques de l'utilisation des fonctions définies par l'utilisateur :

  • Application du concept DRY (Do not Repeat Yourself - Ne Vous Répétez Pas) : l'utilisation de fonctions définies par l'utilisateur nous aidera à ne pas répéter le même code encore et encore. Nous créerons à la place une fonction qui peut effectuer notre tâche une fois et l'appeler ensuite dans n'importe quelle partie du logiciel.
  • Réutilisation : après avoir créé notre fonction, nous pouvons la réutiliser à tout moment.
  • Application du concept "diviser pour mieux régner" : lorsque nous créons un logiciel, le code peut être complexe pour résoudre un problème. Mais si nous divisons le gros problème en petits problèmes et que nous résolvons chacun d'entre eux par des fonctions, cela peut être très utile pour atteindre notre objectif de résolution du gros problème.
  • Le code est plus lisible et compréhensible : lorsque nous utilisons des fonctions, notre code devient plus lisible car il est mieux organisé grâce aux fonctions et chacun gère un problème spécifique et a une tâche spécifique.
  • Application du concept d'abstraction : l'utilisation de fonctions permet d'abstraire notre code, car si nous ne les utilisons pas, nous risquons de devoir écrire plus de lignes de code qu'en utilisant des fonctions.
  • Appliquer du concept d'encapsulation : lorsque nous utilisons des fonctions, cela nous permet de sécuriser et de gérer notre code et nos données davantage que si nous ne les utilisions pas.
  • Améliore le processus de débogage : l'utilisation de fonctions permet d'améliorer l'exploration des erreurs et de les résoudre plus facilement.

Suivant les caractéristiques de l'utilisation des fonctions, nous pouvons facilement déterminer les avantages de l'utilisation de ces fonctions définies par l'utilisateur dans notre logiciel.


Structure de la fonction

Dans cette partie, nous allons apprendre plus de détails sur les fonctions et leurs structures. Nous allons le faire à travers les 2 étapes suivantes :

  • Déclaration ou définition de fonction
  • Appel de fonction

Tout d'abord, nous devons définir ou déclarer une nouvelle fonction, ce qui revient à faire quelque chose de similaire à la structure suivante :

returnedDataType functionName(param1, param2)
{
        bodyOfFunction
}
  • returnedDataType : il s'agit du type de données que la fonction doit renvoyer après son exécution.
  • functionName : c'est le nom de la fonction, il faut déterminer ce nom en fonction de la tâche que la fonction exécute. 
  • param1, param2 : ce sont les variables dont nous avons besoin si nécessaire, car il se peut que nous n'en indiquions aucune.
  • bodyOfFunction : c’est tout le code qui exécutera notre tâche. 

Appliquons cela à un exemple simple : créons une fonction simple pour effectuer l’addition de 2 valeurs :

//addition function
// returned data type is an integer - the name of the function is add - parameters or arguments are two int variables val1 and val2
int add(int val1, int val2)
  {
   //body of function that we need the function to perform when calling it
   //create a result new variable to be assigned by the result of val1 and val2 addition
   int result = val1+val2;
   //Print result in the experts tab
   Print(result);
   //returning value
   return result;
  }

Après avoir défini notre fonction, nous devons passer à la deuxième étape, qui consiste à appeler la fonction. Nous pouvons le faire en appelant le nom de la fonction et en spécifiant les paramètres souhaités, conformément à notre fonction, à l'endroit voulu du code du logiciel. Pour revenir à notre exemple, si nous voulons appeler notre fonction, il faudra le faire de cette façon :

   //calling our defined function by its name and specifying arguments
   add(5,15);

Lorsque nous l'appelons, le résultat 20 sera affiché dans l'onglet "Experts" conformément à notre fonction et aux arguments spécifiés, comme dans l'image suivante :

résultat de la fonction d’addition

L'exemple précédent n'est qu'un exemple de ce que l'on peut faire en utilisant une fonction. Mais il existe de nombreuses caractéristiques disponibles que l'on peut utiliser dans les fonctions. En voici quelques-unes dans la suite de l’article.

Fonction avec arguments

Dans le dernier exemple de fonction d'addition, nous avons utilisé 2 variables entières, val1 et val2, considérées comme des arguments dans notre fonction. Ces arguments peuvent être des données de type integer, string, etc. Dans notre dernier exemple, il s'agissait de variables integer. Voici un autre exemple d'arguments de type string :

//sayHello function
// returned data type is string - name of function is sayHello - parameters or arguments are two string variables greeting and name
string sayHello(string greeting, string name)
  {
   //body of function that we need the function to perform when calling it
   //create a result new variable to be assigned by the result of greeting and name addition
   string result = greeting+name;
   //Print result in the experts tab
   Print(result);
   //returning value
   return result;
  }

Nous pouvons appeler cette fonction comme la précédente, et son résultat sera également visible de la même façon :

résultat de la fonction sayhello

Les types de données peuvent également être mélangés suivant nos besoins dans la fonction. Le nombre de ces arguments peut également être différent en fonction de nos besoins.

Fonction sans arguments

La fonction peut être déclarée ou définie sans spécifier de paramètres ou d'arguments. Il suffit de donner un nom significatif à la fonction et de laisser les arguments vides, d’écrire le corps de la fonction pour qu'elle exécute la tâche, puis d'appeler la fonction sans spécifier d'arguments, comme dans le cas suivant :

//sayHello function
// returned data type is a string - the name of the function is sayHello - no parameters
string sayHello()
  {
   //body of the function that we need the function to perform when calling it
   //create a result new variable to be assigned by the result of greeting and name addition
   string greeting= "Hello, ";
   string name= "World!";
   string result = greeting+name;
   //Print the result in the experts' tab
   Print(result);
   //returning value
   return result;
  }

Lorsque nous appelons la fonction, elle sera identique à la suivante :

sayHello();

Le résultat sera le même que celui que nous avons mentionné précédemment dans la fonction avec arguments, car le corps de la fonction est le même.

Fonction avec valeurs par défaut

Nous définissons également une fonction et donnons des valeurs initiales, ou par défaut, aux paramètres. Mais nous sommes toujours en mesure de les modifier ou de les mettre à jour avec les valeurs souhaitées.

//defining function with default values
string sayHello(string greeting= "Hello, ", string name="World!")
  {
   string result = greeting+name;
   Print(result);
   return result;
  }

Nous pouvons ensuite appeler la fonction 2 fois pour identifier la différence entre les valeurs par défaut et les valeurs données au moment de l’appel, comme dans l'exemple suivant :

   sayHello();
   sayHello("Hi, ", "Developer!");

Le résultat sera le même que le suivant :

résultat des valeurs de la fonction sayhello

Transmission des paramètres

Nous pouvons passer des valeurs à la fonction et ces valeurs peuvent être n'importe quel type de données comme nous l'avons mentionné : int, string, array,... etc. En passant les paramètres par des valeurs, les variables originales de la fonction resteront identiques ou inchangées car nous avons transmis la valeur des paramètres à la fonction. Nous pouvons également transmettre des paramètres à la fonction par référence si nous devons mettre à jour les variables d'origine.

Voici un exemple simple pour comprendre le passage par référence :

//passing by reference
void updateNums(int &val1, int &val2)
  {
   val1*=2;
   val2/=2;
  }

Nous allons ensuite créer de nouvelles variables et afficher leurs valeurs, puis appeler notre fonction avec ces nouvelles variables comme paramètres, puis afficher ses valeurs après l'appel pour voir la différence :

//new variables
   int firstNum = 10;
   int secondNum = 20;
   
//before calling function
   Print("before calling: ");
   Print(firstNum, " - " ,secondNum, "\n"); 
   
// calling   
   updateNums(firstNum, secondNum);

// after calling  
   Print("after calling: ");
   Print(firstNum, " - " ,secondNum, "\n"); 

Ainsi, le résultat du premier affichage sera les valeurs des nouvelles variables 10 et 20. Puis, après l'appel, les valeurs auront été mises à jour par 20 et 10, conformément au corps de la fonction. Le résultat est le même que le suivant :

passage par référence

Opérateur return

Si une fonction renvoie une valeur, elle doit avoir un opérateur de retour, return. Nous pouvons avoir plus d'un opérateur de retour dans la fonction en fonction de la tâche de la fonction. Mais si la fonction renvoie une valeur, elle doit avoir au moins un retour à la dernière ligne de la fonction. Cet opérateur return peut être de n'importe quel type, sauf un tableau. Si nous voulons que la fonction retourne un tableau, nous pouvons passer le tableau à la fonction par référence, comme nous l’avons mentionné précédemment.

Voici un exemple de ce que nous avons mentionné précédemment et qui comporte un opérateur de retour, return

string sayHello(string greeting= "Hello, ", string name="World!")
  {
   string result = greeting+name;
   Print(result);
   return result;
  }

Fonction de type void

Si une fonction ne renvoie pas de valeur, nous devons utiliser le type void, car ce type ne renvoie pas de valeur. Nous pouvons passer des paramètres à ce type de fonction, mais celle-ci n'a pas besoin d'un opérateur de retour. Voici un exemple de ce type de fonctions :

void add(int val1, int val2)
  {
   int result= val1+val2;
  }

Surcharge des fonctions

Dans certains cas, lorsque l'on définit des fonctions, il est nécessaire de définir plusieurs fonctions sous le même nom pour effectuer la même tâche, mais avec des paramètres différents. Par exemple, si nous avons une tâche d'addition, mais que nous devons effectuer cette addition pour deux valeurs et que nous devons effectuer la même tâche pour trois valeurs, dans ce cas, nous créons deux fonctions sous le même nom de fonction mais nous changerons les paramètres en fonction de la tâche. Cela signifie que nous avons une fonction de surcharge. La fonction de surcharge est donc une fonction qui effectue la même tâche mais avec des paramètres différents.

Ces différents paramètres peuvent être des types de données différents, des nombres du même type de données, ou les deux. Voici un exemple de fonction de surcharge ayant le même type de données, mais dont le nombre de paramètres est différent :

void overloadingFun(int val1, int val2)
{
   int result=val1+val2;
}

void overloadingFun(int val1, int val2, int val3)
{
   int result=val1+val2+val3;
}

Comme nous pouvons le voir, nous avons la même fonction, mais les paramètres sont différents. Lorsque nous appelons la fonction, nous constatons que ces deux fonctions apparaissent lorsque nous tapons le nom de la fonction ; nous pouvons alors choisir celle dont nous avons besoin en fonction des détails de notre tâche. Voici un exemple de fonction de surcharge avec différents paramètres selon le type de données :

void overloadingFun(int val1, int val2)
{
   int result=val1+val2;
}

void overloadingFun(string message, int val1, int val2)
{
   int result=message+val1+val2;
}

Nous pouvons également choisir la fonction dont nous avons besoin en fonction des paramètres lors de l'appel de la fonction.


Applications fonctionnelles

Dans cette partie, nous allons créer des applications simples pour lesquelles nous pouvons utiliser une fonction définie par l'utilisateur pour faciliter le processus de codage. Après avoir créé ces applications, nous pouvons les appeler dans différentes parties du logiciel ou même dans un autre logiciel en les incluant.

Application d'alerte sur les nouvelles

Nous savons tous qu'il est très risqué de trader pendant les nouvelles économiques et de nombreux professionnels conseillent même de ne pas le faire. Si vous ne savez pas ce qu'est le calendrier économique, il s'agit d'un calendrier prêt à l'emploi qui contient des nouvelles et des indicateurs macroéconomiques avec des descriptions, leur date, leur heure et leur degré d'importance, ainsi que les valeurs publiées de ces événements économiques. Il existe de nombreuses sources qui peuvent être utilisées pour obtenir ces valeurs importantes afin d'être mis à jour avec ce qui peut affecter le marché et de négocier en fonction de cela. Ce calendrier est également disponible dans le terminal de trading MetaTrader 5. Vous trouverez son onglet dans la fenêtre Boîte à Outils, et vous pourrez contrôler ce que vous souhaitez voir en termes d'importance, de devises et de pays. Il existe également des fonctions intégrées pour travailler avec le calendrier économique, vous pouvez les consulter dans la documentation de MQL5 en cliquant sur le lien suivant :

Fonctions du Calendrier Economique

Nous devons donc vérifier manuellement le calendrier économique des nouvelles pour éviter de trader pendant les nouvelles, ou créer une application qui nous alerte lorsque nous approchons des nouvelles pour arrêter de trader. Nous pouvons donc créer une fonction pour cela et l'appeler facilement. C'est ce que nous allons faire dans cette partie à travers les étapes suivantes :

Cette application sera un EA, nous créerons un type bool pour le nom de notre fonction isNewsComing dans la portée globale et ensuite nous n'ajouterons pas de paramètres.

bool isNewsComing()

Le corps de la fonction crée un tableau avec un nom de valeurs et de type MqlCalendarValue, qui seront les valeurs du communiqué de presse comme la valeur réelle par exemple.

MqlCalendarValue values[];

Nous devons définir la journée en cours en définissant l'heure de début de la journée en utilisant iTime pour retourner l'heure d'ouverture de la barre après avoir déclaré une nouvelle variable startTime de type datetime et l'heure de fin de la journée endTime, de type datetime, égale à l'heure de début définie plus le nombre de secondes de la journée en utilisant la fonction PeriodSeconds.

   datetime startTime=iTime(_Symbol,PERIOD_D1,0);
   datetime endTime=startTime+PeriodSeconds(PERIOD_D1);

Nous devons ensuite obtenir le tableau des valeurs de tous les événements de la journée en utilisant l'heure de début et l'heure de fin définies pour déterminer l'intervalle de temps, puis nous trions par le pays et la devise actuels en utilisant la fonction CalendarValueHistory. Les paramètres sont le tableau des valeurs, l'heure de début, l'heure de fin, le pays et la devise :

CalendarValueHistory(values,startTime,endTime,NULL,NULL);

Nous allons créer une boucle sur la variable i de type int, de 0 jusqu’à ce que la valeur de i soit inférieure à la taille du tableau des valeurs, avec i incrémenté à chaque boucle :

for(int i=0; i<ArraySize(values); i++)

Le corps de la boucle for crée une variable d'événement de type MqlCalendarEvent pour les descriptions d'événements. Elle peut être utilisée dans la fonction CalendarEventById :

MqlCalendarEvent event;

Nous obtenons ensuite la description de l'événement par son ID en utilisant la fonction CalendarEventById. Ses paramètres sont event_id et l'événement.

CalendarEventById(values[i].event_id,event);

Nous créons ensuite une variable pays, de type MqlCalendarCountry pour les descriptions de pays. Elle peut être utilisée avec CalendarCountryById :

MqlCalendarCountry country;

Nous obtenons les descriptions des pays par leur ID en utilisant la fonction MqlCalendarCountry. Ses paramètres sont country_id et le pays.

CalendarCountryById(event.country_id,country);

Définissons les conditions pour filtrer les événements en fonction du symbole actuel ou de l'actualité monétaire, de l'importance moyenne ou élevée de l'actualité, et s'il y a quelque chose d'autre qui se poursuit :

      if(StringFind(_Symbol,country.currency)<0)
         continue;

      if(event.importance==CALENDAR_IMPORTANCE_NONE)
         continue;
      if(event.importance==CALENDAR_IMPORTANCE_LOW)
         continue;

Définissons la condition sur la plage horaire de l'alerte dont nous avons besoin, à savoir 30 secondes avant l'heure de la nouvelle :

      if(TimeCurrent()>=values[i].time-30*PeriodSeconds(PERIOD_M1) &&
         TimeCurrent()<values[i].time+30*PeriodSeconds(PERIOD_M1))

Nous devons ensuite afficher un message dans l'onglet des experts avec le nom de l'événement et le texte (" is coming!"). Stop Trading...)

Print(event.name, " is coming! Stop Trading...");

La valeur retournée sera true

return true;

Si les conditions sont fausses, terminer la boucle et renvoyer false pour mettre fin à la fonction.

return false;

Ensuite, nous pouvons appeler la fonction dans la fonction OnTick. Si elle renvoie true, le message doit être affiché (« News is coming... ! »).

   if(isNewsComing())
     {
      Print("News is comming...!");
     }

Maintenant, nous avons créé la fonction et nous l'avons appelée et nous pouvons l'utiliser dans n'importe quelle partie de notre logiciel selon nos besoins. Ce qui suit est le code complet en un seul bloc pour être facile à relire. Vous trouverez les fichiers de code source de toutes les applications en pièce jointe de l'article.

//+------------------------------------------------------------------+
//| News Alert Function                                              |
//+------------------------------------------------------------------+ 
void OnTick()
  {
   if(isNewsComing())
     {
      Print("News is comming...!");
     }
  }
//+------------------------------------------------------------------+
bool isNewsComing()
  {
   MqlCalendarValue values[];
   datetime startTime=iTime(_Symbol,PERIOD_D1,0);
   datetime endTime=startTime+PeriodSeconds(PERIOD_D1);
   CalendarValueHistory(values,startTime,endTime,NULL,NULL);
   for(int i=0; i<ArraySize(values); i++)
     {
      MqlCalendarEvent event;
      CalendarEventById(values[i].event_id,event);
      MqlCalendarCountry country;
      CalendarCountryById(event.country_id,country);
      if(StringFind(_Symbol,country.currency)<0)
         continue;
      if(event.importance==CALENDAR_IMPORTANCE_NONE)
         continue;
      if(event.importance==CALENDAR_IMPORTANCE_LOW)
         continue;
      if(TimeCurrent()>=values[i].time-30*PeriodSeconds(PERIOD_M1) &&
         TimeCurrent()<values[i].time+30*PeriodSeconds(PERIOD_M1))
        {
         Print(event.name, " is coming! Stop Trading...");
         return true;
        }
     }
   return false;
  }
//+------------------------------------------------------------------+

App de calcul de la taille du lot

Nous devons créer une application capable de calculer la taille de lot optimale après avoir déterminé le pourcentage de risque et la perte maximale en pips, et nous devons créer une fonction surchargée pour calculer la taille de lot optimale après avoir déterminé le pourcentage de risque, le prix d'entrée et le prix du stop loss. Nous allons créer cette application comme un script comme dans les étapes suivantes :

Créons la fonction OptimalLotSize qui retourne un double, ses deux paramètres seront le pourcentage de risque maximum maxRiskPrc, de type double, et la perte maximale en pips maxLossInPips, de type double également. La fonction sera définie comme ceci :

double OptimalLotSize(double maxRiskPrc, double maxLossInPips)

Ensuite, spécifions ce que nous devons faire pour ces paramètres. Tout d'abord, nous définissons la valeur de l'avoir du compte grâce à la fonction AccountInfoDouble qui renvoie la valeur de la propriété correspondante du compte, qui est ici l'identifiant de l'avoir du compte ENUM_ACCOUNT_INFO_DOUBLE. Et nous créons une alerte avec la valeur suivante :

   double accEquity = AccountInfoDouble(ACCOUNT_EQUITY);
   Alert("accEquity: ", accEquity);

Définissons la taille du contrat du symbole en utilisant la fonction SymbolInfoDouble qui renvoie la propriété correspondante du symbole spécifié, avec le nom du symbole _Symbol (pour utiliser le symbole actuel) et prop_id qui sera SYMBOL_TRADE_CONTRACT_SIZE (l'une des valeurs de l’énumération ENUM_SYMBOL_INFO_DOUBLE). Après quoi, nous avons besoin d'une alerte avec cette valeur renvoyée :

   double lotSize = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_CONTRACT_SIZE);
   Alert("lotSize: ", lotSize);

Calculons la valeur du pip et obtenons une alerte avec cette valeur :

   double tickValue = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_VALUE);
   Alert("tickValue: ", tickValue);

Calculons la valeur maximale de la perte à partir des fonds propres du compte défini et émettons une alerte avec cette valeur :

   double maxLossDollar = accEquity * maxRiskPrc;
   Alert("maxLossDollar: ", maxLossDollar);

Calculons la valeur maximale dans la devise de cotation sur la base de la valeur de perte maximale calculée et renvoyons une alerte avec cette valeur :

   double maxLossInQuoteCurr = maxLossDollar / tickValue;
   Alert("maxLossInQuoteCurr: ", maxLossInQuoteCurr);

Calculons la taille optimale du lot et renvoyons une alerte avec la valeur :

   double OptimalLotSize = NormalizeDouble(maxLossInQuoteCurr / (maxLossInPips * 0.0001)/ lotSize,2);
   Alert("OptimalLotSize: ", OptimalLotSize);

L'opérateur return retourne OptimalLotSize sous la forme d'une valeur de type double :

return OptimalLotSize;

Ensuite, nous créerons la fonction de surcharge en passant 3 paramètres de type double pour le pourcentage de risque maximal, le prix d'entrée et le prix de la perte maximale :

double OptimalLotSize(double maxRiskPrc, double entryPrice, double stopLoss)

Définissons la perte maximale en pips comme une valeur absolue basée sur les paramètres d'entrée du prix d'entrée et du prix du stop loss puis divisé par 0,0001 :

double maxLossInPips = MathAbs(entryPrice - stopLoss)/0.0001;

L’opérateur retourné sera la fonction OptimalLotSize créée avec ses paramètres : le pourcentage de risque maximum et la perte maximum en pips.

return OptimalLotSize(maxRiskPrc,maxLossInPips);

Nous pouvons ensuite appeler l'une des deux fonctions dans la partie OnStart() en fonction de nos besoins, par exemple comme suit :

OptimalLotSize(0.01, 1.12303, 1.11920);

Voici le code complet pour créer ce type de fonction pour créer ce type d'application :

//+------------------------------------------------------------------+
//| lotSize Calc Function                                            |
//+------------------------------------------------------------------+
void OnStart()
  {
   OptimalLotSize(0.01, 1.12303, 1.11920);
  }
//+------------------------------------------------------------------+
double OptimalLotSize(double maxRiskPrc, double maxLossInPips)
  {
   double accEquity = AccountInfoDouble(ACCOUNT_EQUITY);
   Alert("accEquity: ", accEquity);
   double lotSize = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_CONTRACT_SIZE);
   Alert("lotSize: ", lotSize);
   double tickValue = SymbolInfoDouble(_Symbol,SYMBOL_TRADE_TICK_VALUE);
   Alert("tickValue: ", tickValue);
   double maxLossDollar = accEquity * maxRiskPrc;
   Alert("maxLossDollar: ", maxLossDollar);
   double maxLossInQuoteCurr = maxLossDollar / tickValue;
   Alert("maxLossInQuoteCurr: ", maxLossInQuoteCurr);
   double OptimalLotSize = NormalizeDouble(maxLossInQuoteCurr / (maxLossInPips * 0.0001)/ lotSize,2);
   Alert("OptimalLotSize: ", OptimalLotSize);
   return OptimalLotSize;
  }
//+------------------------------------------------------------------+
double OptimalLotSize(double maxRiskPrc, double entryPrice, double stopLoss)
  {
   double maxLossInPips = MathAbs(entryPrice - stopLoss)/0.0001;
   return OptimalLotSize(maxRiskPrc,maxLossInPips);
  }
//+------------------------------------------------------------------+

En exécutant ce script, nous obtiendrons l'alerte suivante :

 app lotSizeCalcApp

Comme dans l'application mentionnée précédemment, nous disposons de la fonction lotSizeCalc que nous pouvons utiliser et appeler facilement dans différentes parties du logiciel pour effectuer la tâche sans réécrire le code.

Fermer toutes les applications

Il s'agit ici de créer un script permettant de clôturer les ordres ouverts et les ordres en attente en créant une fonction qui peut être utilisée ou appelée dans n'importe quelle partie du logiciel pour effectuer cette tâche. Nous pouvons le faire en suivant les étapes suivantes :

Inclure la classe Trade dans le code en utilisant la directive de préprocesseur #include pour inclure toutes les fonctions de trading dans le fichier Trade.mqh :

#include <Trade/Trade.mqh>

Création d'un objet du type de la classe CTrade à utiliser dans le logiciel :

CTrade trade;

Dans le champ d'application global, nous devons également créer une fonction void closeAll sans arguments :

void closeAll()

Le corps de la fonction crée une boucle for pour vérifier les ordres en cours :

for(int i=PositionsTotal()-1; i>=0; i--)

 Le corps de la boucle, qui crée une variable posTicket de type ulong et qui lui assigne le ticket des ordres ouverts :

ulong posTicket=PositionGetTicket(i);

Fermer la transaction ouverte en utilisant trade.PositionClose(posTicket) :

trade.PositionClose(posTicket);

Nous allons supprimer les ordres en attente en créant une autre boucle for pour détecter ces ordres, en assignant leurs tickets à la variable ulong de posTicket, et en supprimant l'ordre en attente par son ticket :

   for(int i=OrdersTotal()-1; i>=0; i--)
     {
      ulong posTicket=OrderGetTicket(i);
      trade.OrderDelete(posTicket);
     }

Ensuite, nous pouvons appeler cette fonction dans la partie OnStart() :

closeAll();

L'exécution de ce script entraîne la clôture et la suppression de tous les ordres. Voici le code complet pour créer cette application closeAllApp en un seul bloc :

//+------------------------------------------------------------------+
//| closeAll Function                                                |
//+------------------------------------------------------------------+ 
#include <Trade/Trade.mqh>
CTrade trade;
//+------------------------------------------------------------------+
void OnStart()
  {
   closeAll();
  }
//+------------------------------------------------------------------+
void closeAll()
  {
//close all open positions
   for(int i=PositionsTotal()-1; i>=0; i--)
     {
      ulong posTicket=PositionGetTicket(i);
      trade.PositionClose(posTicket);
     }
//delete all pending orders
   for(int i=OrdersTotal()-1; i>=0; i--)
     {
      ulong posTicket=OrderGetTicket(i);
      trade.OrderDelete(posTicket);
     }
  }
//+------------------------------------------------------------------+

Ces applications ne sont que des exemples de ce que nous pouvons créer en tant que fonctions définies par l'utilisateur. Vous pouvez les développer ou créer d'autres applications ou fonctions suivant vos besoins, comme une application de trailing stop et de gestion des transactions, un outil de sécurité du drawdown, etc.


Conclusion

D'après ce que nous avons mentionné dans cet article, il est supposé que vous avez trouvé qu'il est crucial d'utiliser des fonctions dans votre logiciel en raison de toutes les caractéristiques et de tous les avantages que vous obtiendrez en le faisant, car il est supposé que vous avez identifié les caractéristiques de leur utilisation comme :

  • Permet d'appliquer le concept DRY (do not repeat yourself) à la programmation
  • Permet de minimiser tout problème important en le divisant en petits problèmes et en les traitant
  • Rend le code plus lisible
  • Réutilisation
  • Abstraction du code
  • Encapsulation du code
  • Amélioration du débogage

On suppose également que vous avez bien compris ce qu'est une fonction, ses types, une fonction intégrée et une fonction définie par l'utilisateur, et comment vous pouvez créer ou définir des fonctions en apprenant la structure des fonctions et toutes leurs caractéristiques, comme les fonctions avec arguments et comment nous pouvons passer ces arguments ou paramètres, sans arguments, et les fonctions avec des valeurs par défaut. Vous êtes censé pouvoir définir votre fonction en utilisant n'importe quel type de données et traiter l'opérateur de retour en fonction de celui-ci. Vous savez comment créer de nombreuses fonctions de surcharge avec le même nom mais des arguments différents pour effectuer la même tâche.

Après avoir présenté des applications pour créer des fonctions à titre d'exemple, je pense que cela vous a beaucoup aidé à approfondir votre compréhension du sujet en créant deux fonctions différentes :

  • Nouvelle application d'alerte : à utiliser ou à appeler dans n'importe quelle partie du logiciel pour recevoir des alertes lorsque des nouvelles importantes arrivent. Vous trouverez le code source de newsAlertApp ci-joint.
  • Lot size Calc App : à utiliser ou à appeler dans n'importe quelle partie du logiciel pour obtenir la taille de lot optimale pour ouvrir une transaction en fonction du pourcentage de risque défini, du prix d'entrée et du prix du stop loss. Ou, sur la base du pourcentage de risque défini et de la perte maximale en pips, ce qui signifie que nous avons créé une fonction de surcharge dans cette application. Vous trouverez le code source de lotSizeCalcApp ci-joint.
  • Close All App : à utiliser ou à appeler pour clôturer tous les ordres ouverts et en attente. Vous trouverez le code source de closeAllApp ci-joint.

Le monde des fonctions est très intéressant et il est très important d'y prêter attention pour pouvoir créer des morceaux de code utiles de manière simple, fluide et efficace. J'espère que cet article vous sera utile pour développer vos compétences en matière de codage et améliorer votre carrière de trader en créant des outils utiles qui peuvent vous aider à bien trader. Si vous voulez lire plus d'articles sur la programmation ou sur la façon de créer des systèmes de trading basés sur les indicateurs techniques les plus populaires comme la moyenne mobile, le RSI, le MACD, le Stochastique, les bandes de Bollinger, le SAR Parabolique, etc., vous pouvez consulter mes publications. J'espère qu'elles vous seront également utiles.

Traduit de l’anglais par MetaQuotes Ltd.
Article original : https://www.mql5.com/en/articles/12970

Fichiers joints |
newsAlertApp.mq5 (1.37 KB)
lotSizeCalcApp.mq5 (1.45 KB)
closeAllApp.mq5 (0.86 KB)
Derniers commentaires | Aller à la discussion (23)
MrBrooklin
MrBrooklin | 12 oct. 2023 à 19:09
fxsaber #:

Elles (les fonctions de Kim) ont été portées depuis longtemps de MQL4 à MQL5.

Excusez mon ignorance et croyez-moi, je ne suis pas sarcastique, mais qu'est-ce qui est porté ? Sont-elles réécrites pour MQL5 ? Si elles sont rassemblées quelque part, et si ce n'est pas difficile pour vous, veuillez fournir un lien vers les fonctions de Kim portées sur MQL5. J'ai essayé de rechercher sur le site les fonctions portées de Kim, mais je n'ai rien trouvé.

Cordialement, Vladimir.

fxsaber
fxsaber | 13 oct. 2023 à 15:41
MrBrooklin #:

fournir un lien vers les fonctions de Kim portées sur MQL5.

https://www.mql5.com/ru/forum/107476

Forum sur le trading, les systèmes de trading automatisés et les tests de stratégies de trading

Bibliothèques : MT4Orders

fxsaber, 2019.01.13 17:23 PM.

Les fonctions de Kim sous MT4 sont assez populaires, j'ai donc téléchargé toutes les sources de son site et écrit un simple "convertisseur" pour elles sous MT5.
#include <KimIVToMT5.mqh> // https://c.mql5.com/3/263/KimIVToMT5.mqh
MrBrooklin
MrBrooklin | 13 oct. 2023 à 15:43

Je vous remercie de votre attention.

Cordialement, Vladimir.

Hilario Miguel Ofarril Gonzalez
Hilario Miguel Ofarril Gonzalez | 9 déc. 2023 à 16:43
Ajouter à la connaissance.pour enceñar le point expesifico.où nous apprenons des autres . des stratégies.très concrètes .et continuer de façon précise.c'est comme être dans une bataille où les nombres sont infinis .de ello es como digo yo sentirce satisfait .quand nous gagnons la güera .el programa.de las defensas en el tradi.es tratar de cobertice en ganadores .sin afectar.nuestras inversiones.Je me consacre à lire chaque article de chaque maître et j'en tire des leçons, en mettant en pratique le désir de devenir un grand maître comme eux et de transmettre les enseignements pour que le monde du tradi soit plus fort, c'est ce qui nous définit tous...la volonté et le sacrifice....et je me sacrifierai pour que le monde du tradi soit plus fort.
Javid Rezaei
Javid Rezaei | 15 août 2025 à 23:56
Merci beaucoup pour cet article utile.
Comment Échanger des Données : Une DLL pour MQL5 en 10 minutes Comment Échanger des Données : Une DLL pour MQL5 en 10 minutes
Maintenant, peu de développeurs se rappellent de la façon d'écrire une DLL simple et des caractéristiques spéciales des différentes liaisons système. À l'aide de plusieurs exemples, je vais tenter de montrer l'ensemble du processus de création de la DLL simple en 10 minutes, ainsi que de discuter de certains détails techniques de notre implémentation de liaison. Je vais montrer étape par étape le processus de la création de DLL dans Visual Studio avec des exemples d'échange de différents types de variables (nombres, tableaux, chaînes, etc.). En outre, je vais vous expliquer comment protéger votre terminal client des plantages dans les DLL personnalisées.
Développer un robot de trading en Python (Partie 3) : Mise en œuvre d'un algorithme de trading basé sur un modèle Développer un robot de trading en Python (Partie 3) : Mise en œuvre d'un algorithme de trading basé sur un modèle
Nous poursuivons la série d'articles sur le développement d'un robot de trading en Python et en MQL5. Dans cet article, nous allons créer un algorithme de trading en Python.
L'Histogramme des prix (Profile du Marché) et son implémentation  en MQL5 L'Histogramme des prix (Profile du Marché) et son implémentation en MQL5
Le Profile du Marché a été élaboré par le brillant penseur Peter Steidlmayer. Il a suggéré l’utilisation de la représentation alternative de l'information sur les mouvements de marché « horizontaux » et « verticaux » qui conduit à un ensemble de modèles complètement différent. Il a assumé qu'il existe une impulsion sous-jacente du marché ou un modèle fondamental appelé cycle d'équilibre et de déséquilibre. Dans cet article, j’examinerai l'Histogramme des Prix - un modèle simplifié de profil de marché, et décrirai son implémentation dans MQL5.
Développement d'un robot en Python et MQL5 (Partie 2) : Sélection, création et formation de modèles, testeur personnalisé Python Développement d'un robot en Python et MQL5 (Partie 2) : Sélection, création et formation de modèles, testeur personnalisé Python
Nous poursuivons la série d'articles sur le développement d'un robot de trading en Python et MQL5. Aujourd'hui, nous allons résoudre le problème de la sélection et de l'entraînement d'un modèle, de son test, de la mise en œuvre de la validation croisée, de la recherche en grille, ainsi que le problème de l'ensemble de modèles.