English Русский 中文 Español Deutsch 日本語 Português 한국어 Italiano Türkçe
Limitations et vérifications dans Expert Advisors

Limitations et vérifications dans Expert Advisors

MetaTrader 5Exemples | 22 décembre 2021, 16:13
214 0
MetaQuotes
MetaQuotes

Introduction

Lors de la création d’un algorithme de trading automatisé, vous devez être en mesure non seulement de traiter les prix pour créer des signaux de trading, mais aussi d’obtenir de nombreuses informations auxiliaires sur les limitations imposées au fonctionnement des Expert Advisors. Cet article vous expliquera comment :

  • Obtenir des informations sur les sessions de trading ;
  • Vérifiez si vous avez suffisamment d’actifs pour ouvrir une position ;
  • Imposer une limitation du volume total de trading par voie d’un symbole ;
  • Imposer une limitation du nombre total d’ordres ;
  • Calculer la perte potentielle entre le prix d’entrée et le Stop Loss ;
  • Vérifier s’il y a une nouvelle barre.

Sessions de trading et de cotation

Pour recevoir les informations sur les sessions de trading, vous devez utiliser la fonction SymbolInfoSessionTrade(), pour les sessions de cotation, utilisez la fonction SymbolInfoSessionQuote() correspondante. Les deux fonctions opèrent de la même manière : s’il existe une session avec l’indice spécifié pour le jour de la semaine spécifié (l’indexation des sessions commence à partir de zéro), alors la fonction renvoie true. L’heure de début et de fin d’une session est écrite dans les quatrième et cinquième paramètres transmis par le lien.

//--- check if there is a quotation session with the number session_index
bool session_exist=SymbolInfoSessionQuote(symbol,day,session_index,start,finish);
Pour connaître toute la session du jour spécifié, appelez cette fonction dans une boucle jusqu’à ce qu’elle renvoie false.
//+------------------------------------------------------------------+
//|  Display information about quotation sessions                    |
//+------------------------------------------------------------------+
void PrintInfoForQuoteSessions(string symbol,ENUM_DAY_OF_WEEK day)
  {
//--- start and end of session
   datetime start,finish;
   uint session_index=0;
   bool session_exist=true;

//--- go over all sessions of this day
   while(session_exist)
     {
      //--- check if there is a quotation session with the number session_index
      session_exist=SymbolInfoSessionQuote(symbol,day,session_index,start,finish);

      //--- if there is such session
      if(session_exist)
        {
         //--- display the day of week, the session number and the time of start and end
         Print(DayToString(day),": session index=",session_index,"  start=",
               TimeToString(start,TIME_MINUTES),"    finish=",TimeToString(finish-1,TIME_MINUTES|TIME_SECONDS));
        }
      //--- increase the counter of sessions
      session_index++;
     }
  }

Le jour de la semaine est affiché au format chaîne à l’aide de la fonction personnalisée DayToString() qui reçoit la valeur de l’énumération ENUM_DAY_OF_WEEK comme paramètre.

//+------------------------------------------------------------------+
//| Receive the string representation of a day of week               |
//+------------------------------------------------------------------+
string DayToString(ENUM_DAY_OF_WEEK day)
  {
   switch(day)
     {
      case SUNDAY:    return "Sunday";
      case MONDAY:    return "Monday";
      case TUESDAY:   return "Tuesday";
      case WEDNESDAY: return "Wednesday";
      case THURSDAY:  return "Thursday";
      case FRIDAY:    return "Friday";
      case SATURDAY:  return "Saturday";
      default:        return "Unknown day of week";
     }
   return "";
  }

Le code final du script SymbolInfoSession.mq5 est joint au bas de l’article. Montrons ici sa partie principale seulement.

void OnStart()
  {
//--- the array where the days of week are stored
   ENUM_DAY_OF_WEEK days[]={SUNDAY,MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY};
   int size=ArraySize(days);

//---
   Print("Quotation sessions");
//--- go over all the days of week
   for(int d=0;d<size;d++)
     {
      PrintInfoForQuoteSessions(Symbol(),days[d]);
     }

//---
   Print("Trading sessions");
//--- go over all the days of week
   for(int d=0;d<size;d++)
     {
      PrintInfoForTradeSessions(Symbol(),days[d]);
     }
  }


Vérification de la marge

Pour connaître la marge requise pour ouvrir ou augmenter une position, vous pouvez utiliser la fonction OrderCalcMargin() ; le premier paramètre qui lui est transmis est une valeur de l’énumération ENUM_ORDER_TYPE. Pour une opération d’achat, vous devez l’appeler avec le paramètre ORDER_TYPE_BUY ; pour vendre, utilisez le paramètre ORDER_TYPE_SELL . La fonction renvoie le montant de la marge en fonction du nombre de lots et du prix d’ouverture.

void OnStart()
  {
//--- the variable to receive the value of margin
   double margin;
//--- to receive information about the last tick
   MqlTick last_tick;
//--- try to receive the value from the last tick
   if(SymbolInfoTick(Symbol(),last_tick))
     {
      //--- reset the last error code
      ResetLastError();
      //--- calculate margin value
      bool check=OrderCalcMargin(type,Symbol(),lots,last_tick.ask,margin);
      if(check)
        {
         PrintFormat("For the operation %s  %s %.2f lot at %G required margin is %.2f %s",OrderTypeToString(type),
                     Symbol(),lots,last_tick.ask,margin,AccountInfoString(ACCOUNT_CURRENCY));
        }
     }
   else
     {
      Print("Unsuccessful execution of the SymbolInfoTick() function, error ",GetLastError());
     }
  }

Il convient de noter que la fonction OrderCalcMargin() permet de calculer la valeur de la marge non seulement pour les ordres sur le marché, mais également pour les ordres en attente. Vous pouvez vérifier les valeurs renvoyées pour tous les types d’ordres à l’aide du script Check_Money.mq5.

La fonction OrderCalcMargin() est destinée au calcul de la taille de la marge pour les ordres en attente, car une caution monétaire peut également être requise dans certains systèmes de trading pour les ordres en attente. Habituellement, la taille de la marge pour les ordres en attente est calculée par un coefficient de la taille de la marge pour les positions longues et courtes.

Identifiant

Description

Type de propriété

SYMBOL_MARGIN_LONG

Taux de facturation de la marge sur les positions longues

double

SYMBOL_MARGIN_SHORT

Taux de facturation de la marge sur les positions courtes

double

SYMBOL_MARGIN_LIMIT

Taux de facturation de la marge sur les limites d’ordres

double

SYMBOL_MARGIN_STOP

Taux de facturation de la marge sur l’ordre Stop

double

SYMBOL_MARGIN_STOPLIMIT

Taux de facturation de la marge sur les ordres Stop Limit

double


Vous pouvez obtenir les valeurs de ces coefficients à l’aide du code simple :

//--- Calculate the rates of margin charging for different types of orders
   PrintFormat("Rate of margin charging on long positions is equal to %G",SymbolInfoDouble(Symbol(),SYMBOL_MARGIN_LONG));
   PrintFormat("Rate of margin charging on short positions is equal to %G",SymbolInfoDouble(Symbol(),SYMBOL_MARGIN_SHORT));
   PrintFormat("Rate of margin charging on Limit orders is equal to %G",SymbolInfoDouble(Symbol(),SYMBOL_MARGIN_LIMIT));
   PrintFormat("Rate of margin charging on Stop orders is equal to %G",SymbolInfoDouble(Symbol(),SYMBOL_MARGIN_STOP));
   PrintFormat("Rate of margin charging on Stop Limit orders is equal to %G",SymbolInfoDouble(Symbol(),SYMBOL_MARGIN_STOPLIMIT));

Pour les symboles Forex, les taux de marge pour les ordres en attente sont généralement égaux à 0, c’est-à-dire qu’il n’y a pas d’exigences de marge pour eux.

Résultats de l’exécution du script Check_Money.mq5.

Résultats de l’exécution du script Check_Money.mq5.

Selon le mode de facturation de la marge, le système de gestion d’argent peut changer, ainsi que le système de trading lui-même peut connaître certaines limitations si une marge est requise pour les ordres en attente. C’est pourquoi ces paramètres peuvent également être des limitations naturelles du fonctionnement d’un Expert Advisor.

Comptabilisation des profits et pertes possibles

Lorsque vous placez un niveau d’arrêt protecteur, vous devez être prêt à le déclencher. Le risque de perte potentielle devrait être pris en compte en termes d’argent; et le OrderCalcProfit() est destiné à cet effet. Elle est très similaire à la fonction OrderCalcMargin() déjà considérée, mais elle nécessite à la fois des prix d’ouverture et de fermeture pour les calculs.

Spécifiez l’une des deux valeurs de l’énumération ENUM_ORDER_TYPE comme premier paramètre - ORDER_TYPE_BUY ou ORDER_TYPE_SELL ; d’autres types d’ordres entraîneront une erreur. Dans le dernier paramètre, vous devez passer une variable à l’aide de la référence, à laquelle la fonction OrderCalcProfit() écrira la valeur du profit / perte en cas d’exécution réussie.

Exemple d’utilisation de la fonction CalculateProfitOneLot() qui calcule le résultat lors de la clôture d’une position longue avec des niveaux spécifiés d’entrée et de sortie :

//+------------------------------------------------------------------+
//| Calculate potential profit/loss for buying 1 lot                 |
//+------------------------------------------------------------------+
double CalculateProfitOneLot(double entry_price,double exit_price)
  {
//--- receive the value of profit to this variable
   double profit=0;
   if(!OrderCalcProfit(ORDER_TYPE_BUY,Symbol(),1.0,entry_price,exit_price,profit))
     {
      Print(__FUNCTION__,"  Failed to calculate OrderCalcProfit(). Error ",GetLastError());
     }
//---
   return(profit);
  }

Le résultat du calcul de cette fonction est illustré dans la figure.

Exemple de calcul et d’affichage de la perte potentielle sur le graphique à l’aide de la fonction OrderCalcProfit().

Le code entier se trouve dans l’Expert Advisor ci-joint CalculateProfit_EA.mq5.

Vérification de l’ouverture d’une nouvelle barre

Le développement de nombreux systèmes de trading suppose que les signaux commerciaux ne sont calculés que lorsqu’une nouvelle barre apparaît ; et toutes les actions de trade ne sont effectuées qu’une seule fois. Le mode « Prix d’ouverture seulement » du testeur de stratégie dans le terminal client MetaTrader 5 est bon pour vérifier de tels systèmes de trading automatisés.

En mode « Prix d’ouverture seulement », tous les calculs des indicateurs et l’appel de la fonction OnTick() dans Expert Advisor ne sont effectués qu’une fois par barre lors des tests. C’est le mode de trading le plus rapide ; et, en règle générale, le mode le plus tolérant aux oscillations de prix insignifiantes pour la création de systèmes de trading. Dans le même temps, bien sûr, les indicateurs utilisés dans un Expert Advisor doivent être écrits correctement et ne doivent pas fausser leurs valeurs lorsqu’une nouvelle barre arrive.

Le testeur de stratégie en mode « Prix d’ouverture seulement » permet de ne pas se soucier du fait que l'Expert Advisor ne soit lancé qu'une fois par barre. Mais tout en travaillant en mode temps réel sur une démo ou sur un compte réel, un trader doit contrôler l’activité de son Expert Advisor, pour qu’il n’effectue qu’une seule opération de trade par signal reçu. Le moyen le plus simple à cette fin est de suivre l’ouverture de la barre non formée actuelle.

Pour obtenir l’heure d’ouverture de la dernière barre, vous devez utiliser la fonction SeriesInfoInteger() avec le nom spécifié du symbole, du délai et de la propriété SERIES_LASTBAR_DATE. En comparant constamment le temps d’ouverture de la barre actuelle avec celui de la barre stockée dans une variable, vous pouvez facilement détecter le moment où une nouvelle barre apparaît. Cela permet de créer la fonction personnalisée isNewBar() qui peut ressembler à ce qui suit :

//+------------------------------------------------------------------+
//| Return true if a new bar appears for the symbol/period pair      |
//+------------------------------------------------------------------+
bool isNewBar()
  {
//--- remember the time of opening of the last bar in the static variable
   static datetime last_time=0;
//--- current time
   datetime lastbar_time=SeriesInfoInteger(Symbol(),Period(),SERIES_LASTBAR_DATE);

//--- if it is the first call of the function
   if(last_time==0)
     {
      //--- set time and exit
      last_time=lastbar_time;
      return(false);
     }

//--- if the time is different
   if(last_time!=lastbar_time)
     {
      //--- memorize time and return true
      last_time=lastbar_time;
      return(true);
     }
//--- if we pass to this line then the bar is not new, return false
   return(false);
  }

Un exemple d’utilisation de la fonction est donné dans l’Expert Advisor CheckLastBar.mq5 ci-joint.

Les messages de l’Expert Advisor  CheckLastBar concernant l’apparition de nouvelles barres sur le délai M1.

Les messages de l’Expert Advisor CheckLastBar concernant l’apparition de nouvelles barres sur le délai M1.

Limitation du nombre d’ordres en attente

Si vous devez limiter le nombre d’ordres en attente actifs qui peuvent être passés simultanément sur un compte, vous pouvez écrire votre propre fonction personnalisée. Appelons cela l’OrdreIsNewautorisé() ; il vérifiera s’il est autorisé à passer un autre ordre en attente. Écrivons-le de manière à ce qu’il soit conforme aux règles du championnat de trading automatisé.

//+------------------------------------------------------------------+
//| Checks if it is allowed to place another order                   |
//+------------------------------------------------------------------+
bool IsNewOrderAllowed()
  {
//--- get the allowed number of pending orders on an account
   int max_allowed_orders=(int)AccountInfoInteger(ACCOUNT_LIMIT_ORDERS);

//--- if there is no limitations, return true; you can send an order
   if(max_allowed_orders==0) return(true);

//--- if we pass to this line, then there are limitations; detect how many orders are already active
   int orders=OrdersTotal();

//--- return the result of comparing
   return(orders<max_allowed_orders);
  }

La fonction est simple : obtenir le nombre autorisé d’ordres à la variable max_allowed_orders ; et si sa valeur n’est pas égale à zéro, comparer avec le nombre actuel des ordres. Cependant, cette fonction ne considère aucune autre limitation possible - la limitation du volume total autorisé de positions ouvertes et d’ordres en attente par un symbole spécifique.

Limitation du nombre de lots par un symbole spécifique

Pour obtenir la taille de la position ouverte par un symbole spécifique, vous devez tout d’abord sélectionner une position à l’aide de la fonction PositionSelect(). Et seulement après cela, vous pouvez demander le volume de la position ouverte en utilisant PositionGetDouble() ; il renvoie diverses propriétés de la position sélectionnée qui ont le double type. Écrivons la fonction PostionVolume() pour obtenir le volume de position par un symbole donné.

//+------------------------------------------------------------------+
//| Returns the size of position by a specific symbol                |
//+------------------------------------------------------------------+
double PositionVolume(string symbol)
  {
//--- try to select a positions by a symbol
   bool selected=PositionSelect(symbol);
//--- the position exists
   if(selected)
      //--- return the position volume
      return(PositionGetDouble(POSITION_VOLUME));
   else
     {
      //--- report about the unsuccessful attempt to select the position
      Print(__FUNCTION__," Failed to execute PositionSelect() for the symbol ",
            symbol," Error ",GetLastError());
      return(-1);
     }
  }

Avant de faire une demande de trade pour placer un ordre en attente par un symbole, vous devez vérifier la limitation du volume total de position ouverte et d’ordres en attente par ce symbole - SYMBOL_VOLUME_LIMIT. S’il n’y a pas de limitation, le volume d’un ordre en attente ne peut pas dépasser le volume maximal autorisé qui peut être reçu à l’aide du volumeSymbolInfoDouble().

double max_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_LIMIT);
if(max_volume==0) volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX);

Toutefois, cette approche ne tient pas compte du volume des ordres en attente courants par le symbole spécifié. Écrivons une fonction qui calcule cette valeur :

//+------------------------------------------------------------------+
//| Returns the size of position by a specified symbol               |
//+------------------------------------------------------------------+
double PositionVolume(string symbol)
  {
//--- try to select a position by a symbol
   bool selected=PositionSelect(symbol);
//--- the position exist
   if(selected)
      //--- return the position volume
      return(PositionGetDouble(POSITION_VOLUME));
   else
     {
      //--- return zero if there is no position
      return(0);
     }
  }

En tenant compte du volume de position ouverte et du volume des ordres en attente, la vérification finale se présentera comme suit :

//+------------------------------------------------------------------+
//|  Returns maximum allowed volume for an order by a symbol         |
//+------------------------------------------------------------------+
double NewOrderAllowedVolume(string symbol)
  {
   double allowed_volume=0;
//--- get the limitation on the maximum volume of an order
   double symbol_max_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX);
//--- get the limitation of volume by a symbol
   double max_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_LIMIT);

//--- get the volume of open position by a symbol
   double opened_volume=PositionVolume(symbol);
   if(opened_volume>=0)
     {
      //--- if we already used available volume
      if(max_volume-opened_volume<=0)
         return(0);

      //--- volume of the open position doen't exceed max_volume
      double orders_volume_on_symbol=PendingsVolume(symbol);
      allowed_volume=max_volume-opened_volume-orders_volume_on_symbol;
      if(allowed_volume>symbol_max_volume) allowed_volume=symbol_max_volume;
     }
   return(allowed_volume);
  }

Le code entier de l’Expert Advisor Check_Order_And_Volume_Limits.mq5 qui contient les fonctions, mentionnées dans cette section, est joint à l’article.

L’exemple de vérification à l’aide de l’expert advisor Check_Order_And_Volume_Limits sur le compte d’un participant au Championnat de trading automatisé 2010.

L’exemple de vérification à l’aide de l’expert advisor Check_Order_And_Volume_Limits sur le compte d’un participant au Championnat de trading automatisé 2010.

Vérification de l’exactitude du volume

Une partie importante de tout robot de trading est la possibilité de choisir un volume correct pour effectuer une opération de trading. Ici, nous n’allons pas parler des systèmes de gestion de l’argent et de gestion des risques, mais du volume à corriger en fonction des propriétés d’un symbole qui correspondent.

Identifiant

Description

Type de propriété

SYMBOL_VOLUME_MIN

Volume minimal pour une transaction

double

SYMBOL_VOLUME_MAX

Volume maximal pour une transaction

double

SYMBOL_VOLUME_STEP

Etape de changement minimal pour l'exécution d'une transaction

double


Pour effectuer une telle vérification, nous pouvons écrire la fonction personnalisée CheckVolumeValue() :

//+------------------------------------------------------------------+
//|  Check the correctness of volume of an order                     |
//+------------------------------------------------------------------+
bool CheckVolumeValue(double volume,string &description)
  {
//--- Minimum allowed volume for trade operations
   double min_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MIN);
   if(volume<min_volume)
     {
      description=StringFormat("Volume is less than the minimum allowed SYMBOL_VOLUME_MIN=%.2f",min_volume);
      return(false);
     }

//--- Maximum allowed volume for trade opertations
   double max_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX);
   if(volume>max_volume)
     {
      description=StringFormat("Volume is greater than the maximum allowed SYMBOL_VOLUME_MAX=%.2f",max_volume);
      return(false);
     }

//--- get the minimal volume change step
   double volume_step=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_STEP);

   int ratio=(int)MathRound(volume/volume_step);
   if(MathAbs(ratio*volume_step-volume)>0.0000001)
     {
      description=StringFormat("Volume is not a multiple of minimal step SYMBOL_VOLUME_STEP=%.2f, the closest correct volume is %.2f",
                               volume_step,ratio*volume_step);
      return(false);
     }
   description="Correct value of volume ";
   return(true);
  }

Vous pouvez vérifier le fonctionnement de cette fonction à l’aide du script CheckVolumeValue.mq5 joint à l’article.

Les messages du fichier CheckVolumeValue.mq5 qui vérifie que le volume est correct.

Les messages du fichier CheckVolumeValue.mq5 qui vérifie que le volume est correct.

Conclusion

L’article décrit les vérifications de base pour les limitations possibles sur le fonctionnement d’un Expert Advisor, qui peuvent être confrontées lors de la création de votre propre système de trading automatisé. Ces exemples ne couvrent pas toutes les conditions possibles qui devraient être vérifiées lors du fonctionnement d’un Expert Advisor sur un compte de trade. Mais j’espère que ces exemples aideront les débutants à comprendre comment implémenter les vérifications les plus populaires dans le langage MQL5.

Traduit du russe par MetaQuotes Ltd.
Article original : https://www.mql5.com/ru/articles/22

L'ordre de création et de destruction d'objets dans MQL5 L'ordre de création et de destruction d'objets dans MQL5
Chaque objet, qu'il s'agisse d'un objet personnalisé, d'un tableau dynamique ou d'un tableau d'objets, est créé et supprimé dans le programme MQL5 à sa manière. Souvent, certains objets font partie d'autres objets et l'ordre de suppression des objets lors de la désinitialisation devient particulièrement important. Cet article fournit quelques exemples qui couvrent les mécanismes de travail avec des objets.
Appliquer un indicateur à un autre Appliquer un indicateur à un autre
Lors de l'écriture d'un indicateur qui utilise la forme abrégée de l'appel de fonction OnCalculate(), vous pourriez manquer le fait qu'un indicateur peut être calculé non seulement par les données de prix, mais également par les données d'un autre indicateur (qu'il s'agisse du type intégré ou personnalisé). Vous souhaitez améliorer un indicateur pour sa bonne application aux données de l'autre indicateur ? Dans cet article, nous passerons en revue toutes les étapes requises pour une telle modification.
MQL5 pour les débutants : Guide d'utilisation des indicateurs techniques dans Expert Advisors MQL5 pour les débutants : Guide d'utilisation des indicateurs techniques dans Expert Advisors
Afin d’obtenir les valeurs d’un indicateur intégré ou personnalisé dans un Expert Advisor, son descripteur doit d’abord être créé à l’aide de la fonction correspondante. Les exemples de l’article montrent comment utiliser tel ou tel indicateur technique lors de la création de vos propres programmes. L’article décrit les indicateurs générés dans le langage MQL5. Il est destiné à ceux qui n’ont pas beaucoup d’expérience dans le développement de stratégies de trading et offre des moyens simples et clairs de travailler avec des indicateurs en utilisant la bibliothèque de fonctions offerte.
MQL5 : Créez votre propre indicateur MQL5 : Créez votre propre indicateur
Qu’est-ce qu’un indicateur? C’est un ensemble de valeurs calculées que nous voulons afficher à l’écran de manière pratique. Les ensembles de valeurs sont représentés dans les programmes sous forme de tableaux. Ainsi, la création d’un indicateur signifie écrire un algorithme qui gère certains tableaux (tableaux de prix) et enregistre les résultats de la manipulation sur d’autres tableaux (valeurs d’indicateur). En décrivant la création de True Strength Index, l’auteur montre comment écrire des indicateurs dans MQL5.