English Русский 中文 Español Deutsch 日本語 한국어 Français Italiano Türkçe
Princípios de Programação em MQL5: Variáveis Globais do Terminal

Princípios de Programação em MQL5: Variáveis Globais do Terminal

MetaTrader 5Exemplos | 26 dezembro 2014, 13:12
2 508 0
Denis Kirichenko
Denis Kirichenko

Introdução

No ambiente MQL4/5 existe um instrumento interessante - as variáveis ​​globais do terminal do cliente. Ela permite criar um área de armazenamento de dados compartilhados para todos os programas do terminal. Além disso, o tempo de vida desta área não pára com o encerramento do terminal. Este artigo sugere a utilização das ferramentas de Programação Orientada a Objetos para ter uma idéia clara do que se trata as variáveis ​​globais do terminal.

Outras informações sobre o artigo, as variáveis ​​globais do terminal do cliente serão chamadas de "variáveis ​​globais" ao menos que ela seja especificada de outra maneira.


1. Variáveis ​​globais, Funções

Do ponto de vista de um programador, uma variável global é uma área da memória disponível para todos os programas em funcionamento de um terminal de negociação. Programadores iniciantes devem notar que, se existem vários terminais que trabalham simultaneamente, cada um deles terá o seu próprio espaço de memória independente para as variáveis ​​globais. Elas não vão se sobrepor.

Os desenvolvedores da linguagem especificaram na Documentação que existem 11 funções usadas para trabalhar com variáveis ​​globais.

A Teoria pode ser encontrada na seção "GlobalVariables" do livro texto MQL4.

Nas próximas seções, usarei os instrumentos da Programação orientada a objetos para a implementação das tarefas definidas.


2. Classe CGlobalVar

Guiado pelas idéias da Programação orientada a objetos, vamos criar a classe CGlobalVar, Que será diretamente responsável pelo objeto de uma variável global.

//+------------------------------------------------------------------+
//| 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);
  };

O que deve ser incluído dentro de uma classe? Para obter uma lista mínima de atributos, eu escolheria as seguintes propriedades:

  • nome de uma variável;
  • valor de uma variável;
  • hora da criação;
  • hora da última chamada;
  • característica de uma variável temporária.

Quanto aos métodos, eles se parecem da seguinte forma:

  • criação;
  • eliminação;
  • verificar se há existência;
  • definir um novo valor;
  • definir um novo valor por uma condição;
  • receber um nome;
  • receber um valor;
  • receber uma etiqueta de uma variável temporária.

O método CGlobalVar::GetValue deve ser mencionado separadamente. Ele é um método modelo. Ele retorna o tipo de dados para o valor da variável que o usuário definiu como um argumento.

A questão aqui é que, em MQL uma função pode ser estabelecida apenas por parâmetros. Por isso deve-se adicionar um parâmetro falso.

Vamos criar um script de teste Globals_test1.mq5 onde iremos trabalhar com os objetos do tipo 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);
     }
  }

Uma variável global é criada como se segue:

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

O primeiro argumento é o componente básico do nome da variável futura ("Gvar1"), o segundo argumento é o valor de (3,123456789101235) e o terceiro argumento é o recurso que mostra que a variável vai ser temporária (true).

O nome da variável é criado pela adição do nome e o tipo de programa ao componente de base.

No meu caso, é:

  1. Gvar1 - o componente básico;
  2. prog_Globals_test1 - programa em que a variável foi criada (seu nome é Globals_test1);
  3. o tipo do programa é - SCR (script).

Ao pressionar F3, a seguinte entrada deve aparecer na lista de variáveis ​​globais na janela do MetaTrader 5:

Fig.1. O valor da variável Test_temp_var1_prog_Globals_test1_scr é igual a 3,18

Fig.1. O valor da variável Test_temp_var1_prog_Globals_test1_scr é igual a 3,18

Em seu lançamento e se sua implementação foi bem-sucedida, as seguintes entradas serão impressas na aba "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

Diferentes tipos de dados do valor da variável são impressas no registro.

Se o terminal MetaTrader 5 é reiniciado, então a variável Gvar1_temp_prog_Globals_test1_scr desaparece da lista de variáveis ​​globais. Isso acontece porque a variável era temporária, ela "viveu" enquanto o terminal estava aberto.

Em MQL4/5, no recebimento de dados sobre a variável global, não há nenhuma maneira de saber se a variável é temporária ou não. Talvez, a maneira mais fácil de identificar uma variável temporária é a adição de uma chave para o nome da variável. Por exemplo, pode ser o sufixo "Temp"No nome da variável. No entanto, a necessidade de controlar o nome da variável global criada é uma desvantagem desta abordagem, especialmente se tais variáveis ​​são criadas por outros programas que não utilizam a classe CGlobalVar.

Em algum momento eu queria saber quantas variáveis ​​globais poderiam ser criadas e com que rapidez.

Eu alterei ligeiramente o script anterior e o chamei de Globals_test2.mq5. Ele foi lançado com um número diferente de passes. Eu reiniciei o terminal após cada rodada para eliminar as variáveis.

#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);
  }

Aqui está o resultado (Figura 2).

Fig.2. O tempo gasto na criação das variáveis ​​globais temporárias

Fig.2. O tempo gasto na criação das variáveis ​​globais temporárias

O resultado de um teste semelhante para as variáveis ​​globais completas são apresentadas na Fig.3. A sua criação não leva muito mais tempo.

A razão por trás disso é que essas variáveis ​​são salvas no disco no arquivo gvariables.dat localizado na pasta Profiles.

Fig.3. O tempo gasto na criação das variáveis ​​globais completas

Fig.3. O tempo gasto na criação das variáveis ​​globais completas

Eu não acho que há uma necessidade de criar tantas variáveis ​​globais. Eu realizei esta avaliação simplesmente por curiosidade.

Na passagem seguinte, vamos trabalhar com um conjunto de variáveis ​​globais.


3. Classe CGlobalVarList

Para regular o trabalho com variáveis ​​globais, vamos criar uma classe lista de variáveis ​​globais do tipo CGlobalVarList. Esse tipo de lista é uma descendente da classe lista padrão CList.

A declaração de classe pode ser apresentada como:

//+------------------------------------------------------------------+
//| 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);
  };

Se os objetos relacionados com as variáveis ​​globais atuais são para serem incluídas em uma lista do tipo CGlobalVarList, então o método CGlobalVarList::LoadCurrentGlobals é usado.

//+------------------------------------------------------------------+
//| 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;
  }

Este método lê todas as variáveis ​​globais presentes e inclui elas na lista.

O atributo m_gvars_type controla o tipo da variável global incluída. Ela é uma enumeração do tipo 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
  };

Vamos supor que, antes da inicialização da lista CGlobalVarList, houve um conjunto de variáveis ​​globais, tal como apresentado na Figura 4.

Fig.4. Conjunto aproximado das variáveis ​​globais

Fig.4. Conjunto aproximado das variáveis ​​globais

Vamos verificar se este conjunto vai ser processado pela lista corretamente. Para realizar essa verificação, o script de teste Globals_test3.mq5 será criado.

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

Novas variáveis ​​globais (em amarelo) aparecem após o lançamento do script, o que não deveria acontecer (Fig.5).

Fig.5. Novo conjunto de variáveis ​​globais

Fig.5. Novo conjunto de variáveis ​​globais

Uma string foi impressa como:

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

Isso aconteceu porque, na declaração do método CGlobalVarList::LoadCurrentGlobals há uma referência para o método CGlobalVar::create.

Isso significa que uma nova variável global é criada na string:

if(ptr_gvar.Create(gvar_name,gvar_val))

Além disso, os índices das variáveis ​​globais estão a mudar à medida que novas variáveis ​​aparecem. Isso é o que causa a confusão.

Eu recomendaria substituir o método CGlobalVar::create por um menos ativo. Um construtor com parâmetros tem de ser adicionado a classe CGlobalVar de modo que a variável possa ser levada em conta na lista.

Após a modificação do método CGlobalVarList::LoadCurrentGlobals, ele é semelhante como este:

//+------------------------------------------------------------------+
//| 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;
  }

O script funciona corretamente após o método ser modificado. O registro seguinte será impresso:

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

Em seguida, vamos adicionar funcionalidades que permitem apagar e imprimir uma lista.

Agora o script Globals_test3.mq5 é semelhante a:

//---
#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);
     }
  }

Nós estamos iremos complicar a tarefa, criando 10 variáveis ​​globais diversas (fig.6).

Fig.6. Diversas variáveis ​​globais

Fig.6. Diversas variáveis ​​globais

Apenas variáveis ​​completas serão incluídas na nossa lista gvarList . Então eles vão ser removidos.

A aba "Expert" irá conter o seguinte:

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

A lista inclui apenas as variáveis ​​globais completas que foram criadas corretamente.

Em seguida, ele irá ser liberada e apenas 5 variáveis ​​temporárias serão deixadas no terminal (Fig.7).

Fig.7. Variáveis ​​globais temporárias

Fig.7. Variáveis ​​globais temporárias

A tarefa pretendida foi realizada.

Na classe CGlobalVarList , também foram implementados métodos de gravação de dados para o arquivo e download dos dados do arquivo.


4. Aplicação Prática

Como é bem conhecido, a MQL4/5 é uma linguagem de programação especializada. Ele foi criada para a programação de estratégias de negociação. É por isso que qualquer ferramenta da língua deve ser considerada como um meio de formalizar uma certa ideia de negociação.

Existem exemplos suficientes ligando Expert Advisors com variáveis ​​globais na plataforma MQL5. Hoje eu sugiro dar uma olhada de perto na situação em que o controle sobre a execução do programa é necessário.

Vamos assumir que existe um código de "Globals_test_EA" robô de negociação com base na abordagem de módulo:

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

onde o módulo principal é semelhante:

//+------------------------------------------------------------------+
//| 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();
           }
  }

Esse é o módulo principal, que inclui três componentes:

  1. módulo de abertura;
  2. módulo de fechamento;
  3. módulo de stop móvel.

Agora precisamos criar as variáveis ​​globais que controlam as fases de execução do programa.

Existem três fases, sob a forma de módulos. Dois pontos de controle são utilizados para cada fase. O primeiro ponto de controle controla o início do funcionamento do módulo e a segunda é para controlar a extremidade de trabalho do módulo.

Os pontos de controle são implementadas na forma de variáveis ​​globais.

Então, precisamos de seis variáveis ​​globais com os seguintes nomes:

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

Flags para todos os módulos são definidos no início da função Main() e apuradas em cada módulo separado. E, é claro, estamos falando sobre as "próprias" flags somente. Por exemplo, vamos no referir ao módulo 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);
     }
  }

Na execução do módulo, um comentário que o programa está a funcionar no bloco Open() aparece na janela do gráfico.

Então, se o programa não foi forçado a fechar, o controle é passado para a função de definir/limpar uma flag correspondente. No caso de houver uma falha ao limpar uma flag em qualquer um dos pontos de controle, é considerado que o módulo não terminou o trabalho.

O diagrama de estágios de rastreamento do funcionamento do módulo com variáveis ​​globais é apresentado na Fig.8.

Fig.8. Diagrama da sequência de processos da flag

Fig. 8. Diagrama da sequência de processos da flag

Por exemplo, o Expert Advisor "Globals_test_EA" é anexado ao gráfico e opera normalmente.

Quando eu removi o Expert Advisor do gráfico, a seguinte entrada apareceu no registro:

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

Portanto o encerramento do Expert Advisor pega o lugar do módulo Open()..

Abra a lista de variáveis ​​globais pressionando F3 (Fig.9).

Fig. 9. As variáveis ​​globais para o Expert Advisor "Globals_test_EA"

Fig. 9. As variáveis ​​globais para o Expert Advisor "Globals_test_EA"

Pelo parecer da lista, apenas a flag responsável pelo início do funcionamento do módulo Open() foi zerado.

Parece que falhas potenciais podem ser detectadas na falha de execução de comandos relacionados com posições de abertura, seu encerramento e manutenção.

Depois de um relançamento do robô no mesmo gráfico, a seguinte informação será exibida no registro:

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>>

Desta forma, recebemos um aviso sobre uma falha de uma das fases do programa. Isso leva a uma outra questão. O que pode ser feito se esses estágios falharem? Essa é uma história diferente.


Conclusão

Neste artigo eu demonstrei as capacidades orientada a objetos da linguagem MQL5 para criar objetos que facilitam o trabalho com variáveis ​​globais do terminal.

Um caso em que as variáveis ​​globais foram usados ​​como pontos de controle para implementação de estágios do programa, que serviu de exemplo.

Como sempre, comentários, sugestões e críticas construtivas são sempre bem vindas.


Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/1210

Arquivos anexados |
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)
Guia Prático MQL5: Processamento do Evento BookEvent Guia Prático MQL5: Processamento do Evento BookEvent
Este artigo estuda o BookEvent - o evento da Profundidade do Mercado, bem como o princípio de seu processamento. Um programa em MQL e o tratamento dos estados da Profundidade do Mercado servem de exemplo. Ele é escrito usando a abordagem orientada a objetos. Os resultados do tratamento são exibidos na tela como um painel com os níveis da Profundidade do Mercado.
Porque a Hospedagem Virtual no MetaTrader 4 e no MetaTrader 5 são Melhores que os VPS Usuais Porque a Hospedagem Virtual no MetaTrader 4 e no MetaTrader 5 são Melhores que os VPS Usuais
A rede de hospedagem virtual em nuvem foi desenvolvida especialmente para o MetaTrader 4 e o MetaTrader 5, possuindo todas as vantagens de uma solução nativa. Obtenha os benefícios de nossa oferta gratuita por 24 horas - teste um servidor virtual agora mesmo.
Assistente MQL5: Colocando Ordens, Stop Loss e Take Profits sobre os Preços Calculados. Extensão da Biblioteca Padrão Assistente MQL5: Colocando Ordens, Stop Loss e Take Profits sobre os Preços Calculados. Extensão da Biblioteca Padrão
Este artigo descreve a extensão da Biblioteca Padrão MQL5, que permite criar Expert Advisors, colocar ordens, Stop Loss e Take Profits utilizando o Assistente MQL5 pelos preços que são recebidos dos módulos incluídos. Esta abordagem não aplicar quaisquer restrições adicionais sobre o número de módulos e eles não provocam conflitos quando trabalhado em conjunto.
Guia Prático MQL5: Processamento de Eventos Personalizados do Gráfico Guia Prático MQL5: Processamento de Eventos Personalizados do Gráfico
Este artigo considera os aspectos de design e desenvolvimento de eventos personalizados do gráfico no ambiente em MQL5. Um exemplo de uma abordagem para a classificação dos eventos também podem ser encontrados aqui, bem como um código de programação para uma classe de eventos e uma classe de tratamento de eventos personalizados.