English Русский 中文 Español Deutsch 日本語 Português 한국어 Italiano Türkçe
Les bases de la programmation MQL5 : Variables globales du terminal

Les bases de la programmation MQL5 : Variables globales du terminal

MetaTrader 5Exemples | 13 janvier 2022, 15:55
361 0
Denis Kirichenko
Denis Kirichenko

Introduction

Dans l'environnement MQL4/5, il existe un instrument intéressant - les variables globales du terminal client. Il permet de créer des zones de stockage de données partagées pour tous les programmes du terminal. De plus, la durée de vie de cette zone ne s'arrête pas à la fermeture du terminal. Cet article suggère d'utiliser les outils de Programmation orientée objet pour avoir une idée claire de ce que sont les variables globales du terminal.

Plus loin dans l'article, les variables globales du terminal client seront appelées «variables globales» sauf indication contraire.


1. Variables globales, fonctions

Du point de vue d'un programmeur, une variable globale est une zone de mémoire nommée disponible pour tous les programmes de travail d'un terminal de trading. Les programmeurs novices doivent noter que s'il y a plusieurs terminaux fonctionnant simultanément, chacun d'eux aura son propre espace mémoire indépendant pour les variables globales. Ils ne vont pas se chevaucher.

Les développeurs de langage précisent dans la documentation qu'il y a 11 fonctions utilisées pour travailler avec des variables globales.

La théorie peut être trouvée dans la «GlobalVariables» du manuel MQL4.

Dans les sections suivantes, j'utiliserai les instruments de programmation orientés objets pour la mise en œuvre de tâches définies.


2. Classe CGlobalVar

Guidés par les idées de la programmation orientée objet, créons la classe CGlobalVar, qui sera directement responsable de l'objet d'une variable globale.

//+------------------------------------------------------------------+
//| Class CGlobalVar                                                 |
//+------------------------------------------------------------------+
class CGlobalVar : public CObject
  {
   //--- === Data members === --- 
private:
   string            m_name;
   double            m_value;
   //---
   datetime          m_create_time;
   datetime          m_last_time;
   //--- flag for temporary var
   bool              m_is_temp;

   //--- === Methods === --- 
public:
   //--- constructor/destructor
   void              CGlobalVar(void);
   void              CGlobalVar(const string _var_name,const double _var_val,
                                const datetime _create_time);
   void             ~CGlobalVar(void){};
   //--- create/delete
   bool              Create(const string _var_name,const double _var_val=0.0,
                            const bool _is_temp=false);
   bool              Delete(void);
   //--- exist
   bool              IsGlobalVar(const string _var_name,bool _to_print=false);

   //--- set methods
   bool              Value(const double _var_val);
   bool              ValueOnCondition(const double _var_new_val,const double _var_check_val);

   //--- get methods
   string            Name(void) const;
   datetime          CreateTime(void) const;
   datetime          LastTime(void);
   template<typename T>
   T                 GetValue(T _type) const;
   bool              IsTemporary(void) const;
   //---
private:
   string            FormName(const string _base_name,const bool _is_temp=false);
  };

Que doit contenir une classe ? Pour une liste d'attributs minimum, je choisirais les propriétés suivantes :

  • nom d'une variable ;
  • valeur d'une variable;
  • temps de création;
  • heure du dernier appel ;
  • caractéristique d'une variable temporaire.

Quant aux méthodes, elles se présentent comme suit :

  • création ;
  • Suppression ;
  • vérifier l'existence ;
  • définir une nouvelle valeur ;
  • définir une nouvelle valeur par condition ;
  • recevoir un nom ;
  • recevoir une valeur ;
  • recevoir un indicateur de variable temporaire.

La méthode CGlobalVar::GetValue doit être mentionnée séparément. C'est une méthode modèle. Il renvoie le type de données pour la valeur de la variable qu'un utilisateur définit comme argument.

Le problème ici est que dans MQL, une fonction ne peut être saisie que par des paramètres. Par conséquent, un faux paramètre doit être ajouté.

Créons le script de test Globals_test1.mq5 où nous travaillerons avec des objets de type CGlobalVar.

#include "CGlobalVar.mqh"
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
   CGlobalVar gVar1;
//--- create a temporary global var
   if(gVar1.Create("Gvar1",3.123456789101235,true))
     {
      Print("\n---=== A new global var ===---");
      PrintFormat("Name: \"%s\"",gVar1.Name());
      PrintFormat("Is temporary: %d",gVar1.IsTemporary());

      //--- Get the value 
      //--- double type
      double d=0.0;
      double dRes=gVar1.GetValue(d);
      PrintFormat("Double value: %0.15f",dRes);
      //--- float type
      float f=0.0;
      float fRes=gVar1.GetValue(f);
      PrintFormat("Float value: %0.7f",fRes);
      //--- string type
      string s=NULL;
      string sRes=gVar1.GetValue(s);
      PrintFormat("String value: %s",sRes);

      //--- Set a new value 
      double new_val=3.191;
      if(gVar1.Value(new_val))
         PrintFormat("New value is set: %f",new_val);

      //--- Set a new value on condition
      new_val=3.18;
      if(gVar1.ValueOnCondition(3.18,3.191))
         PrintFormat("New value on conditionis set: %f",new_val);
     }
  }

Une variable globale est créée comme suit :

gVar1.Create("Gvar1",3.123456789101235,true)

Le premier argument est le composant de base du futur nom de variable («Gvar1»), le deuxième argument est la valeur de (3.123456789101235) et le troisième argument est la caractéristique indiquant que la variable va être temporaire (vrai).

Le nom de la variable est créé en ajoutant le nom et le type du programme au composant de base.

Dans mon cas c'est :

  1. Gvar1 - le composant de base ;
  2. prog_Globals_test1 - programme où la variable a été créée (son nom est Globals_test1) ;
  3. le type de programme est - scr (script).

En appuyant sur F3, l'entrée suivante devrait apparaître dans la liste des variables globales dans la fenêtre MetaTrader 5 :

Fig. 1. La valeur de la variable Test_temp_var1_prog_Globals_test1_scr est égale à 3.18

Fig.1. La valeur de la variable Test_temp_var1_prog_Globals_test1_scr est égale à 3.18

Lors de son lancement et de sa mise en œuvre réussie, les entrées suivantes sont imprimées dans le journal « Experts » :

KP      0       10:20:20.736    Globals_test1 (AUDUSD.e,H1)     ---=== A new global var ===---
EH      0       10:20:21.095    Globals_test1 (AUDUSD.e,H1)     Name: "Gvar1_temp_prog_Globals_test1_scr"
LF      0       10:20:21.876    Globals_test1 (AUDUSD.e,H1)     Is temporary: 1
MO      0       10:20:31.470    Globals_test1 (AUDUSD.e,H1)     Double value: 3.123456789101235
KG      0       10:20:31.470    Globals_test1 (AUDUSD.e,H1)     Float value: 3.1234567
OP      0       10:20:31.470    Globals_test1 (AUDUSD.e,H1)     String value: 3.123456789101235
RH      0       10:20:31.470    Globals_test1 (AUDUSD.e,H1)     New value is set: 3.191000
DJ      0       10:20:31.470    Globals_test1 (AUDUSD.e,H1)     New value on conditionis set: 3.180000

Différents types de données de la valeur de la variable sont imprimés dans le journal.

Si le terminal MetaTrader 5 est redémarré, la variable Gvar1_temp_prog_Globals_test1_scr disparaît de la liste des variables globales. Cela se produit parce que la variable était temporaire et qu'elle vivait pendant que le terminal était ouvert.

En MQL4/5, lors de la réception des données sur la variable globale, il n'y a aucun moyen de savoir si la variable est temporaire ou non. Le moyen le plus simple d'identifier une variable temporaire est peut-être d'ajouter une clé au nom de la variable. Par exemple, il peut s'agir du suffixe «temp» dans le nom de la variable. Cependant, la nécessité de contrôler la création du nom de la variable globale est un inconvénient distinct de cette approche, surtout si de telles variables sont créées par d'autres programmes n'utilisant pas la classe CGlobalVar.

À un moment donné, j'ai voulu savoir combien de variables globales pouvaient être créées et à quelle vitesse.

J'ai légèrement modifié le script précédent et je l'ai nommé Globals_test2.mq5. Il a été lancé avec un nombre différent de pistes. J'ai redémarré le terminal après chaque exécution pour supprimer les variables.

#property script_show_inputs
//---
#include "CGlobalVar.mqh"

input uint InpCnt=10000; // Number of variables
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//--- start value
   uint start=GetTickCount();
//---
   for(uint idx=0;idx<InpCnt;idx++)
     {
      CGlobalVar gVar;
      //--- Create a temporary global var
      if(!gVar.Create("Test_var"+IntegerToString(idx+1),idx+0.15,true))
         Alert("Error creating a global variable!");
     }
//--- finish value
   uint time=GetTickCount()-start;
//--- to print
   PrintFormat("Creation of %d global variables took %d ms",InpCnt,time);
  }

Voici le résultat (Fig.2).

Fig.2. Temps passé à créer des variables globales temporaires

Fig.2. Temps passé à créer des variables globales temporaires

Le résultat d'un test similaire pour les variables globales complètes est présenté sur la Fig.3. Leur création ne prend pas beaucoup plus de temps.

La raison en est que ces variables sont enregistrées sur le disque dans le fichier gvariables.dat situé dans le dossier Profiles.

Fig.3. Temps passé à créer des variables globales complètes

Fig.3. Temps passé à créer des variables globales complètes

Je ne pense pas qu'il soit nécessaire de créer autant de variables globales. J'ai fait cette évaluation par simple curiosité.

Dans le prochain passage, nous allons travailler avec un ensemble de variables globales.


3. Classe CGlobalVarList

Pour réguler le travail avec les variables globales, nous allons créer une classe liste de variables globales de type CGlobalVarList. Ce type de liste est un descendant de la classe de liste standard CList..

La déclaration de classe peut être présentée comme :

//+------------------------------------------------------------------+
//| Class CGlobalVarList                                             |
//+------------------------------------------------------------------+
class CGlobalVarList : public CList
  {
   //--- === Data members === --- 
private:
   ENUM_GVARS_TYPE   m_gvars_type;

   //--- === Methods === --- 
public:
   //--- constructor/destructor
   void              CGlobalVarList(void);
   void             ~CGlobalVarList(void){};
   //--- load/unload
   bool              LoadCurrentGlobals(void);
   bool              KillCurrentGlobals(void);
   //--- working with files
   virtual bool      Save(const int _file_ha);
   virtual bool      Load(const int _file_ha);
   //--- service
   void              Print(const int _digs);
   void              SetGvarType(const ENUM_GVARS_TYPE _gvar_type);
   //---
private:
   bool              CheckGlobalVar(const string _var_name);
  };

Si des objets connectés avec des variables globales courantes doivent être inclus dans une liste de type CGlobalVarList, alors la méthode CGlobalVarList::LoadCurrentGlobals est utilisée.

//+------------------------------------------------------------------+
//| Load current global vars                                         |
//+------------------------------------------------------------------+
bool CGlobalVarList::LoadCurrentGlobals(void)
  {
   ENUM_GVARS_TYPE curr_gvar_type=this.m_gvars_type;
   int gvars_cnt=GlobalVariablesTotal();
//---
   for(int idx=0;idx<gvars_cnt;idx++)
     {
      string gvar_name=GlobalVariableName(idx);
      if(this.CheckGlobalVar(gvar_name))
         continue;

      //--- gvar properties
      double gvar_val=GlobalVariableGet(gvar_name);
      datetime gvar_time=GlobalVariableTime(gvar_name);
      CGlobalVar *ptr_gvar=new CGlobalVar(gvar_name,gvar_val,gvar_time);
      //--- control gvar type 
      if(CheckPointer(ptr_gvar)==POINTER_DYNAMIC)
        {
         if(curr_gvar_type>GVARS_TYPE_ALL)
           {
            bool is_temp=ptr_gvar.IsTemporary();
            //--- only full-fledged
            if(curr_gvar_type==GVARS_TYPE_FULL)
              {if(is_temp)continue;}
            //--- only temporary
            else if(curr_gvar_type==GVARS_TYPE_TEMP)
              {if(!is_temp)continue;}
           }
         //--- try to add
         if(this.Add(ptr_gvar)>-1)
            continue;
        }
      //---
      return false;
     }
//---
   return true;
  }

Cette méthode lit toutes les variables globales présentes et les inclut dans la liste.

L'attribut m_gvars_type contrôle le type de la variable globale incluse. Est-ce une énumération de type ENUM_GVARS_TYPE :

//+------------------------------------------------------------------+
//| Enumeration for gvars type                                       |
//+------------------------------------------------------------------+
enum ENUM_GVARS_TYPE
  {
   GVARS_TYPE_ALL=-1,  // all global
   GVARS_TYPE_FULL=0,  // only full
   GVARS_TYPE_TEMP=1,  // only temporary
  };

Supposons qu'avant l'initialisation de la liste CGlobalVarList, il y avait un ensemble de variables globales comme présenté sur la Fig.4.

Fig.4. Ensemble approximatif de variables globales

Fig.4. Ensemble approximatif de variables globales

Nous allons vérifier si cet ensemble va être correctement traité par la liste. Pour effectuer une telle vérification, le script de test Globals_test3.mq5 sera créé.

#include "CGlobalVarList.mqh"
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
   CGlobalVarList gvarList;
   gvarList.LoadCurrentGlobals();   
   PrintFormat("Number of variables in the set: %d",gvarList.Total());
  }

De nouvelles variables globales (surlignées en jaune) sont apparues après le lancement du script, ce qui n'était pas censé se produire (Fig.5).

Fig.5. Nouvel ensemble de variables globales

Fig.5. Nouvel ensemble de variables globales

Une chaîne a été imprimée sous la forme :

2014.10.21 11:35:00.839       Globals_test3 (AUDUSD.e,H1)              Number of variables in the list: 10

C'est arrivé parce que dans la déclaration de la méthode CGlobalVarList::LoadCurrentGlobals, il y a une référence à la méthode CGlobalVar::Create.

Cela signifie qu'une nouvelle variable globale est créée dans la chaîne :

if(ptr_gvar.Create(gvar_name,gvar_val))

De plus, les index des variables globales changent à mesure que de nouvelles variables apparaissent. C'est ce qui crée la confusion.

Je recommanderais de remplacer la méthode CGlobalVar::Create par une méthode moins active. Un constructeur avec des paramètres doit être ajouté à la classe CGlobalVar pour que la variable puisse être prise en compte dans la liste.

Après la modification, la méthode CGlobalVarList::LoadCurrentGlobals ressemble à :

//+------------------------------------------------------------------+
//| Load current global vars                                         |
//+------------------------------------------------------------------+
bool CGlobalVarList::LoadCurrentGlobals(void)
  {
   int gvars_cnt=GlobalVariablesTotal();
//---
   for(int idx=0;idx<gvars_cnt;idx++)
     {
      string gvar_name=GlobalVariableName(idx);
      double gvar_val=GlobalVariableGet(gvar_name);
      datetime gvar_time=GlobalVariableTime(gvar_name);
      CGlobalVar *ptr_gvar=new CGlobalVar(gvar_name,gvar_val,gvar_time);
      if(CheckPointer(ptr_gvar)==POINTER_DYNAMIC)
         if(this.Add(ptr_gvar)>-1)
            continue;
      //---
      return false;
     }
//---
   return true;
  }

Le script fonctionne correctement une fois la méthode modifiée. L'enregistrement suivant est imprimé :

2014.10.21 11:38:04.424      Globals_test3 (AUDUSD.e,H1)              Number of variables in the list: 6

Ensuite, nous allons ajouter des fonctionnalités permettant de supprimer et d'imprimer une liste.

Le script Globals_test3.mq5 ressemble maintenant à :

//---
#include "CGlobalVarList.mqh"
//---
input ENUM_GVARS_TYPE InpGvarType=GVARS_TYPE_FULL; // Set gvar type
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
   CGlobalVarList gvarList;
//--- delete gvars
   gvarList.SetGvarType(InpGvarType);
//--- load current gvars  
   gvarList.LoadCurrentGlobals();
   Print("Print the list before deletion.");
   gvarList.Print(10);
//--- delete gvars
   if(gvarList.KillCurrentGlobals())
     {
      Print("Print the screen after deletion.");
      gvarList.Print(10);
     }
  }

Nous allons compliquer la tâche en créant 10 variables globales différentes (Fig.6).

Fig.6. Diverses variables globales

Fig.6. Diverses variables globales

Seules les variables complètes seront incluses dans notre liste gvarList . Ensuite, ils seront supprimés.

Le journal « Expert » contiendra les éléments suivants :

MG      0       11:05:01.113    Globals_test3 (AUDUSD.e,H1)     Print the list before deletion.
KL      0       11:05:01.613    Globals_test3 (AUDUSD.e,H1)     
OI      0       11:05:01.613    Globals_test3 (AUDUSD.e,H1)     ---===Local list===---
QS      0       11:05:01.613    Globals_test3 (AUDUSD.e,H1)     Global variable type: GVARS_TYPE_FULL
RI      0       11:05:01.613    Globals_test3 (AUDUSD.e,H1)     Total number of global variables: 10
EG      0       11:05:01.613    Globals_test3 (AUDUSD.e,H1)     Number of global variables in current list: 5
RN      0       11:05:01.613    Globals_test3 (AUDUSD.e,H1)     Gvar #1, name - gVar10_prog_test1_scr, value - 16.6400000000
KP      0       11:05:01.613    Globals_test3 (AUDUSD.e,H1)     Gvar #2, name - gVar2_prog_test1_scr, value - 4.6400000000
GR      0       11:05:01.613    Globals_test3 (AUDUSD.e,H1)     Gvar #3, name - gVar4_prog_test1_scr, value - 7.6400000000
RD      0       11:05:01.613    Globals_test3 (AUDUSD.e,H1)     Gvar #4, name - gVar6_prog_test1_scr, value - 10.6400000000
LJ      0       11:05:01.613    Globals_test3 (AUDUSD.e,H1)     Gvar #5, name - gVar8_prog_test1_scr, value - 13.6400000000
EH      0       11:06:18.675    Globals_test3 (AUDUSD.e,H1)     Print the list after deletion.
FS      0       11:06:19.003    Globals_test3 (AUDUSD.e,H1)     
JJ      0       11:06:19.003    Globals_test3 (AUDUSD.e,H1)     ---===Local list===---
HN      0       11:06:19.003    Globals_test3 (AUDUSD.e,H1)     Global variable type: GVARS_TYPE_FULL
KH      0       11:06:19.003    Globals_test3 (AUDUSD.e,H1)     Total number of global variables: 5
QP      0       11:06:19.003    Globals_test3 (AUDUSD.e,H1)     Number of global variables in the current list: 0

La liste comprenant uniquement des variables globales complètes a été créée correctement.

Ensuite, il a été effacé et il ne restait plus que 5 variables temporaires dans le terminal (Fig.7).

Fig.7. Variables globales temporaires

Fig.7. Variables globales temporaires

La tâche prévue a été accomplie.

Dans la classeCGlobalVarList , des méthodes d'enregistrement de données dans le fichier et de téléchargement de données à partir du fichier ont également été implémentées.


4. Application pratique

Comme on le sait, MQL4/5 est un langage de programmation spécialisé. Il a été créé pour programmer des stratégies de trading. C'est pourquoi tout outil du langage est à considérer comme un moyen de formaliser une certaine idée de trading.

Il existe suffisamment d'exemples de liaison d'Expert Advisors avec des variables globales sur la plate-forme MQL5. Aujourd'hui, je suggère d'examiner de près la situation lorsqu'un contrôle sur la mise en œuvre du programme est requis.

Supposons qu'il existe un code du robot de trading «Globals_test_EA» basé sur une approche par module :

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   return INIT_SUCCEEDED;
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   Comment("");
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   Main();
  }

où le module principal ressemble à :

//+------------------------------------------------------------------+
//| Main module                                                      |
//+------------------------------------------------------------------+
void Main(void)
  {
//--- set flags for all modules
   for(int idx=0;idx<GVARS_LIST_SIZE;idx++)
      SetFlag(idx,false);

//--- Check the trade possibility and connectivity
//--- permission to trade
   if(TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
      //--- connection to the trading server
      if(TerminalInfoInteger(TERMINAL_CONNECTED))
         //--- permission to trade for the launched EA
         if(MQLInfoInteger(MQL_TRADE_ALLOWED))
           {
            //--- 1) opening module
            Open();
            //--- 2) closing module
            Close();
            //--- 3) Trailing Stop module
            Trail();
           }
  }

C'est-à-dire que le module principal comprend 3 constituants :

  1. module d'ouverture;
  2. module de fermeture;
  3. Module d'arrêt suiveur.

Nous devons maintenant créer des variables globales contrôlant les étapes d'exécution du programme.

Il y a trois étapes sous forme de modules. Deux points de contrôle sont utilisés pour chaque étape. Le premier point contrôle le début du travail du module et le second contrôle la fin du travail du module.

Les points de contrôle sont implémentés sous forme de variables globales.

Nous avons donc besoin de six variables globales portant les noms suivants :

//--- global variables: names
string gVar_names[6]=
  {
   "gvarOpen_start","gvarOpen_finish",
   "gvarClose_start","gvarClose_finish",
   "gvarTrail_start","gvarTrail_finish"
  };

Les drapeaux de tous les modules sont définis au début de la fonction Main() et effacés dans chaque module séparé. Il va sans dire que nous ne parlons que de «propres» drapeaux. Par exemple, référons-nous au module Open() :

//+------------------------------------------------------------------+
//| Open module                                                      |
//+------------------------------------------------------------------+
void Open(void)
  {
   Comment(curr_module+__FUNCTION__);
//---
   if(!IsStopped())
     {
      //--- clear the module start flag
      SetFlag(0,true);

      //--- assume that the module operates for approximately 1.25 s
        {
         Sleep(1250);
        }
      //--- clear the module finish flag
      SetFlag(1,true);
     }
  }

A l'exécution du module, un commentaire indiquant que le programme travaille dans le bloc Open() apparaît dans la fenêtre graphe.

Ensuite, si la fermeture du programme n'a pas été forcée, le contrôle est passé à la fonction de mise/effacement d'un drapeau correspondant. Au cas où un drapeau ne s'effacerait pas dans l'un des points de contrôle, le module est alors considéré comme n'ayant pas terminé le travail.

Un schéma des étapes de suivi du travail de module avec des variables globales est présenté sur la figure 8.

Fig.8. Modèle de la séquence d'indicateurs de traitement

Fig. 8. Modèle de la séquence d'indicateurs de traitement

Par exemple, l'Expert Advisor «Globals_test_EA» est attaché au graphique et fonctionne normalement.

Lorsque j'ai supprimé l'Expert Advisor du graphique, l'entrée suivante est apparue dans le journal :

2014.10.22 20:14:29.575 Globals_test_EA (EURUSD.e,H1)   Program forced to terminate before execution: <<Open_finish>>

Par conséquent, la fin de l'Expert Advisor a eu lieu dans Open(). module.

Ouvrez la liste des variables globales en appuyant sur F3 (Fig.9).

Fig. 9. Variables globales pour l'Expert Advisor «Globals_test_EA»

Fig. 9. Variables globales pour l'Expert Advisor «Globals_test_EA»

D'après l'apparence de la liste, seul le drapeau responsable du début du travail du module Open() a été mis à zéro.

Il semble que des défauts puissent potentiellement être détectés lors d'échecs d'exécution de commandes liés aux positions d'ouverture, à leur fermeture et à leur maintenance.

Après une relance du robot sur la même carte, les informations suivantes seront affichées dans le journal :

RQ      0       20:28:25.135    Globals_test_EA (EURUSD.e,H1)   Non-zero value for: <<Open_finish>>
CL      0       20:28:25.135    Globals_test_EA (EURUSD.e,H1)   Non-zero value for: <<Close_start>>
DH      0       20:28:25.135    Globals_test_EA (EURUSD.e,H1)   Non-zero value for: <<Close_finish>>
ES      0       20:28:25.135    Globals_test_EA (EURUSD.e,H1)   Non-zero value for: <<Trail_start>>
RS      0       20:28:25.135    Globals_test_EA (EURUSD.e,H1)   Non-zero value for: <<Trail_finish>>

De cette façon, nous recevons un avertissement en cas d'échec des étapes du programme. Cela conduit à une autre question. Que faire si ces étapes échouent ? C'est une autre histoire.


Conclusion

Dans cet article, j'ai démontré les capacités orientées objet du langage MQL5 pour créer des objets facilitant le travail avec les variables globales du terminal.

Un cas où des variables globales ont été utilisées comme points de contrôle pour la mise en œuvre des étapes du programme a servi d'exemple.

Comme toujours, les commentaires, suggestions et critiques constructives sont les bienvenues.


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

Fichiers joints |
globals_test1.mq5 (3.67 KB)
globals_test2.mq5 (2.92 KB)
globals_test3.mq5 (2.59 KB)
cglobalvar.mqh (20.52 KB)
cglobalvarlist.mqh (18.74 KB)
globals_test_ea.mq5 (13.01 KB)
Le livre de recettes statistique du trader : Hypothèses Le livre de recettes statistique du trader : Hypothèses
Cet article considère l'hypothèse - l'une des idées de base de la statistique mathématique. Diverses hypothèses sont examinées et vérifiées à l'aide d'exemples utilisant des méthodes de statistiques mathématiques. Les données réelles sont généralisées à l'aide de méthodes non paramétriques. Le progiciel Statistica et la bibliothèque d'analyse numérique portée ALGLIB MQL5 sont utilisés pour le traitement des données.
Graphique Liquide Graphique Liquide
Souhaitez-vous voir un graphique horaire avec des barres s'ouvrant à partir de la deuxième et de la cinquième minute de l'heure ? À quoi ressemble un graphique redessiné lorsque l'heure d'ouverture des bars change toutes les minutes ? Quels sont les avantages du trading sur de tels graphiques ? Vous trouverez des réponses à ces questions dans cet article.
Programmation des modes d'EA à l'aide d'une approche orientée objet Programmation des modes d'EA à l'aide d'une approche orientée objet
Cet article explique l'idée de la programmation d'un robot de trading multimode dans MQL5. Chaque mode est implémenté avec l'approche orientée objet. Des instances de la hiérarchie des classes de mode et des classes à tester sont fournies. La programmation multimode des robots de trading est censée prendre en compte toutes les particularités de chaque mode opérationnel d'un EA écrit en MQL5. Des fonctions et des énumérations sont créées pour identifier le mode.
Tracer des lignes de tendance basées sur des fractales à l’aide de MQL4 et MQL5 Tracer des lignes de tendance basées sur des fractales à l’aide de MQL4 et MQL5
L’article décrit l’automatisation du traçage des lignes de tendance en fonction de l’indicateur Fractals à l’aide de MQL4 et MQL5. La structure de l’article fournit une vue comparative de la solution pour deux langues. Les courbes de tendance sont tracées à l’aide de deux dernières fractales connues.