English Русский 中文 Español Deutsch 日本語
preview
Estruturas em MQL5 e formas de imprimir seus dados

Estruturas em MQL5 e formas de imprimir seus dados

MetaTrader 5Exemplos | 5 dezembro 2023, 17:06
396 0
Artyom Trishkin
Artyom Trishkin

Conteúdo


Introdução

Uma estrutura é uma ferramenta conveniente para armazenar, gravar e recuperar dados logicamente relacionados de uma única variável pertencente a alguma definição.

Na linguagem MQL5, existem 12 estruturas predefinidas destinadas a armazenar e transmitir informações de serviço:

As estruturas MqlParam e MqlTradeRequest são usadas para transmitir informações técnicas para a criação de indicadores e o envio de solicitações de negociação para o servidor. Preenchemos os campos necessários das estruturas de acordo com o resultado desejado ao enviar os dados na estrutura preenchida. Ou seja, essas estruturas não precisam necessariamente imprimir os dados preenchidos nela pelo programador.
Por outro lado, as outras estruturas retornam resultados de solicitações, e cada campo é preenchido pelo subsistema do terminal ou pelo servidor de negociação. Obter dados dessas estruturas, analisar os campos preenchidos programaticamente ou imprimir no log para análise manual são convenientes e essenciais tanto para a tomada de decisões programáticas quanto para a compreensão e busca de erros lógicos.

Para imprimir todos os campos de uma estrutura, existe a função padrão ArrayPrint(), que exibe os dados em formato de tabela contidos em um array com o tipo da estrutura processada. No entanto, às vezes é necessário imprimir os dados de uma estrutura em um formato diferente, que pode ser mais conveniente do que uma representação de tabela. Por exemplo, imprimir todos os campos de uma estrutura em uma única linha, com cabeçalhos e dados correspondentes. Isso pode ser mais conveniente para a análise de grandes conjuntos de dados. Ao mesmo tempo, às vezes é necessário ver uma representação mais detalhada, com descrições dos campos da estrutura e uma apresentação diferente dos dados correspondentes.

Hoje, vamos examinar os meios padrão para visualizar dados de estruturas e criar funções personalizadas para diferentes representações de dados de estruturas no log.


Estrutura MqlDateTime

A estrutura de data contém oito campos do tipo int.

struct MqlDateTime
  {
   int year;           // year
   int mon;            // month
   int day;            // day
   int hour;           // hour
   int min;            // minutes
   int sec;            // seconds
   int day_of_week;    // day of the week (0-Sunday, 1-Monday, ... ,6-Saturday)
   int day_of_year;    // number of a day in the year (1st of January has number 0)
  };

Para preencher os campos da estrutura, são usadas funções padrão como TimeCurrent(), TimeGMT(), TimeLocal(), TimeTradeServer() e TimeToStruct().

As primeiras quatro funções, além de retornarem a data atual, a data GMT, a hora local do computador e a data do servidor de negociação, têm uma sobrecarga cada uma.Nos parâmetros formais da função, você pode passar uma estrutura de data por referência, e após a execução da função, os campos da estrutura passada para a função serão preenchidos com os dados da data retornada pela função.

A função TimeToStruct() é especialmente projetada para preencher uma estrutura a partir de um valor do tipo datetime (quantidade de segundos desde 01/01/1970) em uma variável do tipo MqlDateTime.

bool  TimeToStruct(
   datetime      dt,            // date and time
   MqlDateTime&  dt_struct      // structure for accepting values 
   );

Ela retorna verdadeiro em caso de sucesso, caso contrário, falso. Após seu funcionamento, a estrutura de data será preenchida com os dados de tempo passados como o primeiro parâmetro na variável do tipo datetime.

Ótimo. Nossa estrutura de data está preenchida, mas como imprimi-la? Existe a função padrão TimeToString() que converte o valor contendo o tempo em segundos desde 01/01/1970 em uma string no formato "yyyy.mm.dd hh:min:sec".

No entanto, a função não funciona com a estrutura MqlDateTime, mas sim com um datetime. Então, precisamos converter a estrutura de volta em um valor de tempo? Claro que não. Cada uma das funções tem seus próprios propósitos. A partir da estrutura de data, podemos separadamente obter qualquer componente da data e hora - ano, mês, hora, minuto, dia da semana, etc... Mas como imprimir todos os dados da estrutura?
Para isso, a função ArrayPrint() é muito útil, pois imprime um array de um tipo de dados simples ou de uma estrutura simples no log. Ela exibe os dados em forma de tabela, onde as colunas são os campos da estrutura e as linhas são as células do array. Ou seja, para imprimir a estrutura de uma única data, precisaríamos de um array com uma dimensão de 1. Para uma semana de negociação, considerando a obtenção de dados de um gráfico D1, a dimensão do array seria de 5 (normalmente) dias úteis.


MqlDateTime, métodos de impressão

Este script imprimirá no log a estrutura de data obtida a partir do tempo atual usando ArrayPrint():

void OnStart()
  {
//--- Declare a date structure variable
   MqlDateTime  time;
//--- Get the current time and at the same time fill in the date structure
   TimeCurrent(time);
//--- Declare an array with the MqlDateTime type and write the data of the filled structure into it

   MqlDateTime array[1];
   array[0]=time;
//--- Display the header and time using the standard ArrayPrint()
   Print("Time current (ArrayPrint):");
   ArrayPrint(array);
   /* Sample output:
      Time current (ArrayPrint):
          [year] [mon] [day] [hour] [min] [sec] [day_of_week] [day_of_year]
      [0]   2023     7    17     12     8    37             1           197
   */
  }

Consequentemente, uma função que aceita uma estrutura de data e a imprime no log ficaria assim:

//+------------------------------------------------------------------+
//| Take a date structure and display its data to the journal.       |
//| Use ArrayPrint() for display                                     |
//+------------------------------------------------------------------+
void MqlDateTimePrint(const MqlDateTime& time_struct)
  {
//--- Declare an array with the MqlDateTime type and write the data of the obtained structure into it
   MqlDateTime array[1];
   array[0]=time_struct;
//--- Print the array
   ArrayPrint(array);
   /* Sample output:
      Time current (ArrayPrint):
          [year] [mon] [day] [hour] [min] [sec] [day_of_week] [day_of_year]
      [0]   2023     7    17     12     8    37             1           197
   */
  }

Esta função permite imprimir no log uma única data passada para ela na variável time_struct.

Um script que imprime no log a única estrutura de data usando a função apresentada acima:

void OnStart()
  {
//--- Declare a date structure variable
   MqlDateTime  time;
//--- Get the current time and at the same time fill in the date structure
   TimeCurrent(time);
//--- Display the header and time using the standard ArrayPrint()
   Print("Time current (ArrayPrint):");
   MqlDateTimePrint(time);
   /* Sample output:
      Time current (ArrayPrint):
          [year] [mon] [day] [hour] [min] [sec] [day_of_week] [day_of_year]
      [0]   2023     7    17     12     8    37             1           197
   */
  }


Se precisarmos imprimir um array de datas - afinal, ArrayPrint() foi projetada para facilitar a impressão de conjuntos de dados - então precisamos passar um array de dados datetime para a função, preenchê-la com dados MqlDateTime e imprimi-la.

Função que recebe um array datetime e imprime um array MqlDateTime:

//+------------------------------------------------------------------+
//| Accept the datetime array, convert it into MqlDateTime and       |
//| display converted data into the journal.                         |
//| Use ArrayPrint() for display                                     |
//+------------------------------------------------------------------+
void MqlDateTimePrint(const datetime& array_time[])
  {
//--- Declare a dynamic array of the MqlDateTime type
   MqlDateTime array_struct[];
//--- Get the size of the array passed to the function
   int total=(int)array_time.Size();
//--- If an empty array is passed, report on that and leave the function
   if(total==0)
     {
      PrintFormat("%s: Error. Empty array.",__FUNCTION__);
      return;
     }
//--- Change the size of the MqlDateTime array to match the size of the datetime array
   ResetLastError();
   if(ArrayResize(array_struct,total)!=total)
     {
      PrintFormat("%s: ArrayResize() failed. Error %s",__FUNCTION__,(string)GetLastError());
      return;
     }
//--- Convert dates from the datetime array into the date structure in the MqlDateTime array
   for(int i=0;i<total;i++)
     {
      ResetLastError();
      if(!TimeToStruct(array_time[i],array_struct[i]))
         PrintFormat("%s: [%s] TimeToStruct() failed. Error %s",__FUNCTION__,(string)i,(string)GetLastError());
     }
//--- Print the filled MqlDateTime array
   ArrayPrint(array_struct);
   /* Sample output:
      Time data of the last 10 bars GBPUSD H1 (ArrayPrint):
          [year] [mon] [day] [hour] [min] [sec] [day_of_week] [day_of_year]
      [0]   2023     7    17      7     0     0             1           197
      [1]   2023     7    17      8     0     0             1           197
      [2]   2023     7    17      9     0     0             1           197
      [3]   2023     7    17     10     0     0             1           197
      [4]   2023     7    17     11     0     0             1           197
      [5]   2023     7    17     12     0     0             1           197
      [6]   2023     7    17     13     0     0             1           197
      [7]   2023     7    17     14     0     0             1           197
      [8]   2023     7    17     15     0     0             1           197
      [9]   2023     7    17     16     0     0             1           197
   */
  }


Consequentemente, o script que utiliza a função acima para imprimir um array datetime no log será o seguinte:

void OnStart()
  {
//--- Declare a time array
   datetime array[];
//--- Copy the time of the last 10 bars to the array
   ResetLastError();
   if(CopyTime(Symbol(),Period(),0,10,array)<0)
     {
      PrintFormat("CopyTime() failed. Error %s",(string)GetLastError());
      return;
     }
//--- Display the header and the time data array of the last 10 bars using the standard ArrayPrint()
   PrintFormat("Time data of the last 10 bars %s %s (ArrayPrint):",Symbol(),StringSubstr(EnumToString(Period()),7));
   MqlDateTimePrint(array);
   /* Sample output:
      Time data of the last 10 bars GBPUSD H1 (ArrayPrint):
          [year] [mon] [day] [hour] [min] [sec] [day_of_week] [day_of_year]
      [0]   2023     7    17      7     0     0             1           197
      [1]   2023     7    17      8     0     0             1           197
      [2]   2023     7    17      9     0     0             1           197
      [3]   2023     7    17     10     0     0             1           197
      [4]   2023     7    17     11     0     0             1           197
      [5]   2023     7    17     12     0     0             1           197
      [6]   2023     7    17     13     0     0             1           197
      [7]   2023     7    17     14     0     0             1           197
      [8]   2023     7    17     15     0     0             1           197
      [9]   2023     7    17     16     0     0             1           197
   */
  }


Funções para trabalhar com os dados da estrutura MqlDateTime.

Tudo o que foi testado acima é conveniente, prático e conciso. No entanto, às vezes é necessário obter informações mais detalhadas e, idealmente, em um formato igualmente conciso. Ou vice-versa: uma descrição mais detalhada às custas da redução da brevidade e da simplicidade da apresentação das informações. Por exemplo, um simples número de dia pode ser confuso. Mas se estiver escrito "qui.", imediatamente entendemos que se refere a quinta-feira. Da mesma forma, em relação ao número do mês - às vezes é melhor ver "07 (julho)" do que contar qual é o sétimo mês... Exagerando um pouco, é claro, mas essas pequenas adições realmente acrescentam conveniência. Essas pequenas conveniências se somam a uma economia de tempo considerável ao analisar grandes volumes de registros nos logs do programa.

Para adicionar essas conveniências, será necessário criar sua própria função que retorne descrições dos campos da estrutura no formato MqlDateTime.

A função será:

  1. emitir dados em formato conciso (dia da semana, mês, dia, ano, hora);
  2. emitir dados em formato tabular (cabeçalho de dados|Valor);

Antes de começarmos a criar funções para retornar descrições dos campos da estrutura, vamos criar funções auxiliares que retornem os nomes dos dias da semana e dos meses.

Funções auxiliares.

Para obter o nome do dia da semana, escreveremos uma função simples que retornará o texto do dia da semana, dependendo do valor no campo da estrutura que armazena o dia da semana em formato numérico:

//+------------------------------------------------------------------+
//| Return the name of a week day                                    |
//+------------------------------------------------------------------+
string DayWeek(MqlDateTime &date_time)
  {
//--- Define a week day name
   string dw=EnumToString((ENUM_DAY_OF_WEEK)date_time.day_of_week);
//--- Convert all obtained symbols to lower case and replace the first letter from small to capital
   if(dw.Lower())
      dw.SetChar(0,ushort(dw.GetChar(0)-0x20));
//--- Return a resulting string
   return dw;
   /* Sample output:
      Wednesday
   */
  }

Como o MQL5 possui uma enumeração com os nomes dos dias da semana, aqui usaremos a representação de string da constante dessa enumeração. Para garantir que o texto seja corretamente capitalizado, converteremos todos os caracteres da string para minúsculas, com exceção da primeira letra da palavra.

Para obter o nome do mês, escreveremos uma função simples que retornará o texto do mês, dependendo do valor no campo da estrutura que armazena o mês em formato numérico:

//+------------------------------------------------------------------+
//| Return a month name                                              |
//+------------------------------------------------------------------+
string Month(MqlDateTime &date_time)
  {
//--- Define a month name
   switch(date_time.mon)
     {
      case  1  :  return "January";
      case  2  :  return "February";
      case  3  :  return "March";
      case  4  :  return "April";
      case  5  :  return "May";
      case  6  :  return "June";
      case  7  :  return "July";
      case  8  :  return "August";
      case  9  :  return "September";
      case 10  :  return "October";
      case 11  :  return "November";
      case 12  :  return "December";
      default  :  return "Undefined";
     }
   /* Sample output:
      July
   */
  }

No MQL5, não há enumeração para escolher o mês, então aqui precisamos usar uma instrução switch para selecionar e retornar o texto do nome do mês com base no valor numérico armazenado no campo da estrutura.

Essas funções serão úteis para exibir descrições dos dias da semana e dos meses, e podem ser úteis no futuro para outros projetos.

As funções que retornam descrições dos campos da estrutura MqlDateTime terão o mesmo formato que foi adotado no artigo "Funções para trabalhar com dados da estrutura MqlDateTimeStringFormat(). Visão geral, exemplos prontos de uso". Cada linha retornada pela função terá um cabeçalho e dados. O cabeçalho pode ter um recuo da margem esquerda e uma largura pode ser definida para a exibição tabular do registro retornado. Os valores do recuo e da largura serão passados como parâmetros nas funções. Por padrão, os valores desses parâmetros são iguais a zero, o que significa ausência de recuo e uma largura igual ao comprimento do texto do cabeçalho + 1.


Ano na estrutura MqlDateTime:

//+------------------------------------------------------------------+
//| Return the year as a string from MqlDateTime                     |
//+------------------------------------------------------------------+
string MqlDateTimeYear(MqlDateTime &date_time,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Year:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-lu",indent,"",w,header,date_time.year);
   /* Sample output:
      Year: 2023
   */
  }


Mês na estrutura MqlDateTime:

//+------------------------------------------------------------------+
//| Return the month as a string from MqlDateTime                    |
//+------------------------------------------------------------------+
string MqlDateTimeMonth(MqlDateTime &date_time,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Month:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Get a month name
   string mn=Month(date_time);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%02lu (%s)",indent,"",w,header,date_time.mon,mn);
   /* Sample output:
      Month: 07 (July)
   */
  }


Dia na estrutura MqlDateTime:

//+------------------------------------------------------------------+
//| Return the day as a string from the MqlDateTime structure        |
//+------------------------------------------------------------------+
string MqlDateTimeDay(MqlDateTime &date_time,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Day:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%02lu",indent,"",w,header,date_time.day);
   /* Sample output:
      Day: 19
   */
  }



Horas na estrutura MqlDateTime:

//+------------------------------------------------------------------+
//| Return hours as a string from the MqlDateTime structure          |
//+------------------------------------------------------------------+
string MqlDateTimeHour(MqlDateTime &date_time,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Hour:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%02lu",indent,"",w,header,date_time.hour);
   /* Sample output:
      Hour: 08
   */
  }


Minutos na estrutura MqlDateTime:

//+------------------------------------------------------------------+
//| Return minutes as a string from MqlDateTime                      |
//+------------------------------------------------------------------+
string MqlDateTimeMin(MqlDateTime &date_time,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Minutes:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%02lu",indent,"",w,header,date_time.min);
   /* Sample output:
      Minutes: 41
   */
  }


Segundos na estrutura MqlDateTime:

//+------------------------------------------------------------------+
//| Return seconds as a string from MqlDateTime                      |
//+------------------------------------------------------------------+
string MqlDateTimeSec(MqlDateTime &date_time,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Seconds:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%02lu",indent,"",w,header,date_time.sec);
   /* Sample output:
      Seconds: 23
   */
  }


Dia da semana na estrutura MqlDateTime:

//+------------------------------------------------------------------+
//| Return a week day as a string from the MqlDateTime structure     |
//+------------------------------------------------------------------+
string MqlDateTimeDayWeek(MqlDateTime &date_time,const uint header_width=0,const uint indent=0,bool descr=true)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Day of week:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Get a week day name
   string dw=DayWeek(date_time);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-s (%-lu)",indent,"",w,header,dw,date_time.day_of_week);
   /* Sample output:
      Day of week: Wednesday (3)
   */
  }


Número do dia no ano na estrutura MqlDateTime:

//+------------------------------------------------------------------+
//|Return a number of a day in a year from MqlDateTime               |
//+------------------------------------------------------------------+
string MqlDateTimeDayYear(MqlDateTime &date_time,const uint header_width=0,const uint indent=0)
  {
//--- Define the header text and the width of the header field
//--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
   string header="Day of year:";
   uint w=(header_width==0 ? header.Length()+1 : header_width);
//--- Return the property value with a header having the required width and indentation
   return StringFormat("%*s%-*s%-lu",indent,"",w,header,date_time.day_of_year);
   /* Sample output:
      Day of year: 199
   */
  }


Exemplo de uso:

Para exibir um registro da data e hora da estrutura MqlDateTime em um formato "DW, Mês DD, AAAA, HH:MM:SS", escreveremos uma função que retorna a data dessa forma:

//+------------------------------------------------------------------+
//| Return the date as a string from the MqlDateTime structure       |
//| in the DW, Month DD, YYYY, HH:MM:SS format                       |
//+------------------------------------------------------------------+
string DateTime(MqlDateTime &date_time)
  {
//--- Get the month and the first three characters of a week day
   string mn=Month(date_time);
   string dw=StringSubstr(DayWeek(date_time),0,3);
//--- Return a string in the DW, Month DD, YYYY, HH:MM:SS format
   return StringFormat("%s, %s %02lu, %lu, %02lu:%02lu:%02lu",dw,mn,date_time.day,date_time.year,date_time.hour,date_time.min,date_time.sec);
   /* Sample output:
      Wed, July 19, 2023, 08:41:23
   */
  }

Este é um registro em uma única linha de todos os dados da estrutura, exceto o número do dia no ano. A função é conveniente para imprimir no log o tempo, por exemplo, de um certo número de barras:

void OnStart()
  {
   datetime array[];
   MqlDateTime adt[];
   if(CopyTime(Symbol(),PERIOD_CURRENT,0,10,array)==10)
     {
      int total=(int)array.Size();
      if(ArrayResize(adt,total)==total)
        {
         for(int i=0;i<total;i++)
           {
            ResetLastError();
            if(!TimeToStruct(array[i],adt[i]))
               Print("TimeToStruct failed. Error: ",GetLastError());
            PrintFormat("%s %s [%02u] %s",Symbol(),StringSubstr(EnumToString(Period()),7),i,DateTime(adt[i]));
           }
        }
     }
   /* Sample output:
      GBPUSD H1 [00] Wed, July 19, 2023, 02:00:00
      GBPUSD H1 [01] Wed, July 19, 2023, 03:00:00
      GBPUSD H1 [02] Wed, July 19, 2023, 04:00:00
      GBPUSD H1 [03] Wed, July 19, 2023, 05:00:00
      GBPUSD H1 [04] Wed, July 19, 2023, 06:00:00
      GBPUSD H1 [05] Wed, July 19, 2023, 07:00:00
      GBPUSD H1 [06] Wed, July 19, 2023, 08:00:00
      GBPUSD H1 [07] Wed, July 19, 2023, 09:00:00
      GBPUSD H1 [08] Wed, July 19, 2023, 10:00:00
      GBPUSD H1 [09] Wed, July 19, 2023, 11:00:00
   */
  }


Para imprimir no log todos os campos da estrutura em formatos resumidos e tabulares à escolha, escreveremos a seguinte função:

//+------------------------------------------------------------------+
//| Logs descriptions of all fields of the MqlDateTime structure     |
//+------------------------------------------------------------------+
void MqlDateTimePrint(MqlDateTime &date_time,const bool short_entry=true,const uint header_width=0,const uint indent=0)
  {
//--- If it is a short entry, log the date and time in the DW, Month DD, YYYY, HH:MM:SS format
   if(short_entry)
      Print(DateTime(date_time));
   /* Sample output:
      Wed, July 19, 2023, 08:41:23
   */
//--- Otherwise
   else
     {
      //--- create a string describing all the data of the structure with indents and a given width of the header field 
      string res=StringFormat("%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s",
                              MqlDateTimeYear(date_time,header_width,indent),
                              MqlDateTimeMonth(date_time,header_width,indent),
                              MqlDateTimeDay(date_time,header_width,indent),
                              MqlDateTimeHour(date_time,header_width,indent),
                              MqlDateTimeMin(date_time,header_width,indent),
                              MqlDateTimeSec(date_time,header_width,indent),
                              MqlDateTimeDayWeek(date_time,header_width,indent),
                              MqlDateTimeDayYear(date_time,header_width,indent)
                             );
      //--- Display the obtained string in the journal
      Print(res);
     }
   /* Sample output:
      Year: 2023
      Month: 07 (July)
      Day: 19
      Hour: 09
      Minutes: 32
      Seconds: 25
      Day of week: Wednesday (3)
      Day of year: 199
   */
  }

Script com um exemplo de uso desta função. Primeiro, exibimos um registro no log e, em seguida, em formato tabular com recuo nos cabeçalhos dos campos e largura dos campos de 2 e 14 caracteres, respectivamente:

void OnStart()
  {
   MqlDateTime dt;
   TimeCurrent(dt);
   MqlDateTimePrint(dt,true);
   MqlDateTimePrint(dt,false,14,2);
   /* Sample output:
      Wed, July 19, 2023, 09:33:56
        Year:         2023
        Month:        07 (July)
        Day:          19
        Hour:         09
        Minutes:      33
        Seconds:      56
        Day of week:  Wednesday (3)
        Day of year:  199
   */
  }

Todas as funções para trabalhar com os campos da estrutura MqlDateTime e as funções auxiliares apresentadas acima podem ser usadas "como estão" em seus programas, ou podem ser personalizadas de acordo com sua visão e necessidades.


Estrutura MqlTick

Esta estrutura é usada para armazenar as últimas cotações de um símbolo. É projetada para obter rapidamente informações essenciais sobre os preços atuais.

struct MqlTick
  {
   datetime     time;          // Last price update time
   double       bid;           // Current Bid price
   double       ask;           // Current Ask price
   double       last;          // Current price of the last trade (Last)
   ulong        volume;        // Volume for the current Last price
   long         time_msc;      // Last price update time in milliseconds
   uint         flags;         // Tick flags
   double       volume_real;   // Volume for the current Last price
  };

A variável do tipo MqlTick permite obter os valores de Ask, Bid, Last, Volume e o tempo em milissegundos com uma única chamada à função SymbolInfoTick().

Todos os parâmetros são sempre preenchidos para cada tick, independentemente de os dados terem mudado em comparação com o tick anterior. Isso permite sempre ter um estado atualizado dos preços a qualquer momento sem a necessidade de procurar valores anteriores no histórico de ticks. Por exemplo, apenas o preço de Bid pode ter mudado com um tick, mas na estrutura, além do novo preço, os outros parâmetros também serão listados: preço Ask anterior, volume, etc.

Para descobrir quais dados mudaram com o tick atual, é necessário analisar seus flags:

  • TICK_FLAG_BID – tick alterou o preço Bid
  • TICK_FLAG_ASK  – tick alterou o preço Ask
  • TICK_FLAG_LAST – tick alterou o preço da última negociação
  • TICK_FLAG_VOLUME – tick alterou o volume
  • TICK_FLAG_BUY – tick surgiu como resultado de uma operação de compra
  • TICK_FLAG_SELL – tick surgiu como resultado de uma operação de venda

    MqlTick, maneiras de impressão

    Para imprimir a estrutura no log, da mesma forma que para MqlDateTime, a função ArrayPrint() pode ser usada:

    void OnStart()
      {
    //--- Declare a variable with the MqlTick type
       MqlTick  tick;
    //--- If failed to get the last tick, display the error message and exit the method
       if(!SymbolInfoTick(Symbol(),tick))
         {
          Print("SymbolInfoTick failed, error: ",(string)GetLastError());
          return;
         }
    //--- Display the tick using standard ArrayPrint()
    //--- To do this, declare an array of dimension 1 with type MqlTick,
    //--- enter the value of the 'tick' variable into it and print it
       MqlTick array[1];
       array[0]=tick;
       Print("Last tick (ArrayPrint):");
       ArrayPrint(array);
       /* Sample output:
          Last tick (ArrayPrint):
                           [time]   [bid]   [ask] [last] [volume]    [time_msc] [flags] [volume_real]
          [0] 2023.07.19 17:02:49 1.28992 1.28996 0.0000        0 1689786169589       6       0.00000
       */
      }
    
    

    Logicamente, para imprimir um array, você pode preenchê-lo com um intervalo de ticks:

    void OnStart()
      {
    //--- Declare a dynamic array of the MqlTick type
       MqlTick  array[];
    //--- If failed to get the last 10 ticks, display the error message and exit the method
       if(CopyTicks(Symbol(),array,COPY_TICKS_ALL,0,10)!=10)
         {
          Print("CopyTicks failed, error: ",(string)GetLastError());
          return;
         }
       Print("Last 10 tick (ArrayPrint):");
       ArrayPrint(array);
       /* Sample output:
          Last 10 tick (ArrayPrint):
                           [time]   [bid]   [ask] [last] [volume]    [time_msc] [flags] [volume_real]
          [0] 2023.07.19 17:24:38 1.28804 1.28808 0.0000        0 1689787478461       6       0.00000
          [1] 2023.07.19 17:24:38 1.28806 1.28810 0.0000        0 1689787478602       6       0.00000
          [2] 2023.07.19 17:24:38 1.28804 1.28808 0.0000        0 1689787478932       6       0.00000
          [3] 2023.07.19 17:24:39 1.28806 1.28810 0.0000        0 1689787479210       6       0.00000
          [4] 2023.07.19 17:24:39 1.28807 1.28811 0.0000        0 1689787479765       6       0.00000
          [5] 2023.07.19 17:24:39 1.28808 1.28812 0.0000        0 1689787479801       6       0.00000
          [6] 2023.07.19 17:24:40 1.28809 1.28813 0.0000        0 1689787480240       6       0.00000
          [7] 2023.07.19 17:24:40 1.28807 1.28811 0.0000        0 1689787480288       6       0.00000
          [8] 2023.07.19 17:24:40 1.28809 1.28813 0.0000        0 1689787480369       6       0.00000
          [9] 2023.07.19 17:24:40 1.28810 1.28814 0.0000        0 1689787480399       6       0.00000
       */
      }
    
    

    Novamente, gostaríamos de uma saída de valores mais relevante. Por exemplo, tempo em milissegundos e flags. Provavelmente, é mais conveniente vê-los no formato usual, isto é, tempo em formato de hora e os flags como constantes de enumeração.


    Funções para trabalhar com dados da estrutura MqlTick.

    Vamos criar funções para trabalhar com os dados da estrutura MqlTick da mesma forma que todas as funções já criadas para a estrutura MqlDateTime. As funções para trabalhar com MqlTick retornarão uma string formatada da mesma forma. A string terá um recuo do texto à esquerda e uma largura do campo de cabeçalho. Por padrão, os valores desses parâmetros serão zero, o que significa ausência de recuo e uma largura igual ao comprimento do texto do cabeçalho + 1.


    Funções auxiliares.

    Para retornar o tempo em milissegundos como uma string, já criamos uma função. Aqui, ela será útil para retornar o tempo do tick em milissegundos, então a usaremos:

    //+------------------------------------------------------------------+
    //| Accept a date in ms, return time in Date Time.Msc format         |
    //+------------------------------------------------------------------+
    string TimeMSC(const long time_msc)
      {
       return StringFormat("%s.%.3hu",string((datetime)time_msc / 1000),time_msc % 1000);
       /* Sample output:
          2023.07.13 09:31:58.177
       */
      }
    
    


    Tempo na estrutura MqlTick:

    //+------------------------------------------------------------------+
    //| Return the time of the last price update as a string             |
    //+------------------------------------------------------------------+
    string MqlTickTime(const MqlTick &tick,const uint header_width=0,const uint indent=0)
      {
    //--- Define the header text and the width of the header field
    //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
       string header="Time:";
       uint w=(header_width==0 ? header.Length()+1 : header_width);
    //--- Return the property value with a header having the required width and indentation
       return StringFormat("%*s%-*s%-s",indent,"",w,header,(string)tick.time);
       /* Sample output:
          Time: 2023.07.19 20:58:00
       */
      }
    
    


    Preço Bid na estrutura MqlTick:

    //+------------------------------------------------------------------+
    //| Return the Bid price as a string                                 |
    //+------------------------------------------------------------------+
    string MqlTickBid(const string symbol,const MqlTick &tick,const uint header_width=0,const uint indent=0)
      {
    //--- Define the header text and the width of the header field
    //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
       string header="Bid:";
       uint w=(header_width==0 ? header.Length()+1 : header_width);
    //--- Get the number of decimal places
       int dg=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS);
    //--- Return the property value with a header having the required width and indentation
       return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,tick.bid);
       /* Sample output:
          Bid: 1.29237
       */
      }
    
    


    Preço Ask na estrutura MqlTick:

    //+------------------------------------------------------------------+
    //| Return the Ask price as a string                                 |
    //+------------------------------------------------------------------+
    string MqlTickAsk(const string symbol,const MqlTick &tick,const uint header_width=0,const uint indent=0)
      {
    //--- Define the header text and the width of the header field
    //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
       string header="Ask:";
       uint w=(header_width==0 ? header.Length()+1 : header_width);
    //--- Get the number of decimal places
       int dg=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS);
    //--- Return the property value with a header having the required width and indentation
       return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,tick.ask);
       /* Sample output:
          Ask: 1.29231
       */
      }
    
    


    Preço da última negociação (Last) na estrutura MqlTick:

    //+------------------------------------------------------------------+
    //| Return the Last price as a string                                |
    //+------------------------------------------------------------------+
    string MqlTickLast(const string symbol,const MqlTick &tick,const uint header_width=0,const uint indent=0)
      {
    //--- Define the header text and the width of the header field
    //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
       string header="Last:";
       uint w=(header_width==0 ? header.Length()+1 : header_width);
    //--- Get the number of decimal places
       int dg=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS);
    //--- Return the property value with a header having the required width and indentation
       return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,tick.last);
       /* Sample output:
          Last: 0.00000
       */
      }
    
    


    Volume para o preço Last na estrutura MqlTick:

    //+------------------------------------------------------------------+
    //| Return the volume for the Last price as a string                 |
    //+------------------------------------------------------------------+
    string MqlTickVolume(const MqlTick &tick,const uint header_width=0,const uint indent=0)
      {
    //--- Define the header text and the width of the header field
    //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
       string header="Volume:";
       uint w=(header_width==0 ? header.Length()+1 : header_width);
    //--- Return the property value with a header having the required width and indentation
       return StringFormat("%*s%-*s%-I64u",indent,"",w,header,tick.volume);
       /* Sample output:
          Volume: 0
       */
      }
    
    


    Tempo em milissegundos na estrutura MqlTick:

    //+------------------------------------------------------------------+
    //| Return the time in milliseconds as a string                      |
    //+------------------------------------------------------------------+
    string MqlTickTimeMSC(const MqlTick &tick,const uint header_width=0,const uint indent=0)
      {
    //--- Define the header text and the width of the header field
    //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
       string header="Time msc:";
       uint w=(header_width==0 ? header.Length()+1 : header_width);
    //--- Return the property value with a header having the required width and indentation
       return StringFormat("%*s%-*s%-s",indent,"",w,header,TimeMSC(tick.time_msc));
       /* Sample output:
          Time msc: 2023.07.19 21:21:09.732
       */
      }
    
    


    Flags de tick na estrutura MqlTick:

    //+------------------------------------------------------------------+
    //| Return tick flags as a string                                    |
    //+------------------------------------------------------------------+
    string MqlTickFlags(const MqlTick &tick,const uint header_width=0,const uint indent=0)
      {
    //--- Define the header text and the width of the header field
    //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
       string header="Flags:";
       uint w=(header_width==0 ? header.Length()+1 : header_width);
    //--- Define a variable to describe tick flags
       string flags="";
    //--- Parse tick flags into components
       if((tick.flags & TICK_FLAG_BID)==TICK_FLAG_BID)
          flags+=(flags.Length()>0 ? "|" : "")+"BID";
       if((tick.flags & TICK_FLAG_ASK)==TICK_FLAG_ASK)
          flags+=(flags.Length()>0 ? "|" : "")+"ASK";
       if((tick.flags & TICK_FLAG_LAST)==TICK_FLAG_LAST)
          flags+=(flags.Length()>0 ? "|" : "")+"LAST";
       if((tick.flags & TICK_FLAG_VOLUME)==TICK_FLAG_VOLUME)
          flags+=(flags.Length()>0 ? "|" : "")+"VOLUME";
       if((tick.flags & TICK_FLAG_BUY)==TICK_FLAG_BUY)
          flags+=(flags.Length()>0 ? "|" : "")+"BUY";
       if((tick.flags & TICK_FLAG_SELL)==TICK_FLAG_SELL)
          flags+=(flags.Length()>0 ? "|" : "")+"SELL";
    //--- Return the property value with a header having the required width and indentation
       return StringFormat("%*s%-*s%-s",indent,"",w,header,flags);
       /* Sample output:
          Flags: BID|ASK
       */
      }
    
    


    Volume para o preço Last com precisão aumentada na estrutura MqlTick:

    //+------------------------------------------------------------------+
    //| Return the volume for the Last price as a string                 |
    //+------------------------------------------------------------------+
    string MqlTickVolumeReal(const MqlTick &tick,const uint header_width=0,const uint indent=0)
      {
    //--- Define the header text and the width of the header field
    //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
       string header="Volume Real:";
       uint w=(header_width==0 ? header.Length()+1 : header_width);
    //--- Return the property value with a header having the required width and indentation
       return StringFormat("%*s%-*s%-.2f",indent,"",w,header,tick.volume_real);
       /* Sample output:
          Volume Real: 0.00
       */
      }
    
    


    Exemplos de uso.

    Para imprimir os dados do tick no log, escreveremos uma função. Para saber com que precisão imprimir os valores de preço no log, passaremos o nome do símbolo como parâmetro para a função. Como os campos Volume e Volume Real contêm volumes para o preço Last, se Last for zero (não transmitido), não faz sentido imprimir os volumes - eles também serão zero. Para poder especificar e imprimir o índice do tick retirado do array de ticks, passaremos esse índice como um parâmetro de entrada da função. Por padrão, seu valor é -1, e com esse valor, o índice não é impresso.

    //+------------------------------------------------------------------+
    //| Logs descriptions of all fields of the MqlTick structure         |
    //| If Last==0, Last, Volume and Volume Real fields are not displayed|
    //+------------------------------------------------------------------+
    void MqlTickPrint(const string symbol,const MqlTick &tick,const bool short_entry=true,const uint header_width=0,const uint indent=0,int index=WRONG_VALUE)
      {
    //--- Declare the variable for storing the result
       string res="";
    //--- Get the number of decimal places
       int dg=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS);
       string num=(index==WRONG_VALUE ? "" : StringFormat("[%ld] ",index));
    //--- If it is a short entry, log the tick data in the Symbol TimeMSC, Bid, Ask, Last, Vol/VolR, Flags format
       if(short_entry)
         {
          //--- If Last is not zero, display Last, Volume and Volume Real, otherwise they are all zero and there is no point in displaying them
          string last=(tick.last!=0 ? StringFormat(", Last: %.*f, Vol: %I64u/%.2f",dg,tick.last,tick.volume,tick.volume_real) : "");
          res=StringFormat("%sTick %s Time: %s, Bid: %.*f, Ask: %.*f%s, %s",num,symbol,TimeMSC(tick.time_msc),dg,tick.bid,dg,tick.ask,last,MqlTickFlags(tick));
          Print(res);
         }
       /* Sample output (if Last is not zero):
          Tick GBPUSD Time: 2023.07.20 13:57:31.376, Bid: 1.28947, Ask: 1.28951, Last: 1.28947, Vol: 33/33.45, Flags: BID|ASK
          Sample output (if Last is zero):
          Tick GBPUSD Time: 2023.07.20 13:59:33.274, Bid: 1.28956, Ask: 1.28960, Flags: BID|ASK
       */
    //--- Otherwise
       else
         {
          //--- create a string describing all the data of the structure with indents and a given width of the header field 
          res=StringFormat("%s\n%s\n%s%s%s\n%s\n%s%s",
                           MqlTickTime(tick,header_width,indent),
                           MqlTickBid(symbol,tick,header_width,indent),
                           MqlTickAsk(symbol,tick,header_width,indent),
                           (tick.last!=0 ? "\n"+MqlTickLast(symbol,tick,header_width,indent) : ""),
                           (tick.last!=0 ? "\n"+MqlTickVolume(tick,header_width,indent) : ""),
                           MqlTickTimeMSC(tick,header_width,indent),
                           MqlTickFlags(tick,header_width,indent),
                           (tick.last!=0 ? "\n"+MqlTickVolumeReal(tick,header_width,indent) : "")
                          );
          //--- Display the obtained string in the journal
          Print(res);
         }
       /* Sample output (if Last is not zero):
          Time:         2023.07.20 14:42:33
          Bid:          1.28958
          Ask:          1.28962
          Last:         1.28947
          Volume:       33
          Time msc:     2023.07.20 14:42:33.401
          Flags:        BID|ASK
          Volume Real:  33.45
          
          Sample output (if Last is zero):
          Time:         2023.07.20 14:42:33
          Bid:          1.28958
          Ask:          1.28962
          Time msc:     2023.07.20 14:42:33.401
          Flags:        BID|ASK
       */
      }
    
    

    Script que imprime os últimos 10 ticks em um formato resumido no log, incluindo os índices dos ticks do array:

    void OnStart()
      {
    //--- Declare a dynamic array of the MqlTick type
       MqlTick  array[];
    //--- If failed to get the last 10 ticks, display the error message and exit the method
       if(CopyTicks(Symbol(),array,COPY_TICKS_ALL,0,10)!=10)
         {
          Print("CopyTicks failed, error: ",(string)GetLastError());
          return;
         }
       Print("Last 10 tick (MqlTickPrint):");
       for(int i=0;i<(int)array.Size();i++)
          MqlTickPrint(Symbol(),array[i],true,0,0,i);
    
       /* Sample output:
          Last 10 tick (MqlTickPrint):
          [0] Tick GBPUSD Time: 2023.07.20 15:36:29.941, Bid: 1.28686, Ask: 1.28690, Flags: BID|ASK
          [1] Tick GBPUSD Time: 2023.07.20 15:36:29.970, Bid: 1.28688, Ask: 1.28692, Flags: BID|ASK
          [2] Tick GBPUSD Time: 2023.07.20 15:36:30.061, Bid: 1.28689, Ask: 1.28693, Flags: BID|ASK
          [3] Tick GBPUSD Time: 2023.07.20 15:36:30.212, Bid: 1.28688, Ask: 1.28692, Flags: BID|ASK
          [4] Tick GBPUSD Time: 2023.07.20 15:36:30.259, Bid: 1.28689, Ask: 1.28693, Flags: BID|ASK
          [5] Tick GBPUSD Time: 2023.07.20 15:36:30.467, Bid: 1.28682, Ask: 1.28686, Flags: BID|ASK
          [6] Tick GBPUSD Time: 2023.07.20 15:36:30.522, Bid: 1.28681, Ask: 1.28685, Flags: BID|ASK
          [7] Tick GBPUSD Time: 2023.07.20 15:36:30.572, Bid: 1.28673, Ask: 1.28677, Flags: BID|ASK
          [8] Tick GBPUSD Time: 2023.07.20 15:36:30.574, Bid: 1.28672, Ask: 1.28676, Flags: BID|ASK
          [9] Tick GBPUSD Time: 2023.07.20 15:36:30.669, Bid: 1.28674, Ask: 1.28678, Flags: BID|ASK
       */
      }
    
    

    Script que imprime os últimos 4 ticks do array no log, com um recuo de 2 caracteres à esquerda e uma largura de campo de cabeçalho de 14 caracteres:

    void OnStart()
      {
    //--- Declare a dynamic array of the MqlTick type
       MqlTick  array[];
    //--- If the last 4 ticks are not received in the array, display an error message and leave
       if(CopyTicks(Symbol(),array,COPY_TICKS_ALL,0,4)!=4)
         {
          Print("CopyTicks failed, error: ",(string)GetLastError());
          return;
         }
       Print("Last 4 tick (MqlTickPrint):");
       for(int i=0;i<(int)array.Size();i++)
         {
          PrintFormat("Tick[%lu] %s:",i,Symbol());
          MqlTickPrint(Symbol(),array[i],false,14,2);
         }
    
       /* Sample output:
          Last 4 tick (MqlTickPrint):
          Tick[0] GBPUSD:
            Time:         2023.07.20 17:04:51
            Bid:          1.28776
            Ask:          1.28780
            Time msc:     2023.07.20 17:04:51.203
            Flags:        BID|ASK
          Tick[1] GBPUSD:
            Time:         2023.07.20 17:04:51
            Bid:          1.28772
            Ask:          1.28776
            Time msc:     2023.07.20 17:04:51.331
            Flags:        BID|ASK
          Tick[2] GBPUSD:
            Time:         2023.07.20 17:04:51
            Bid:          1.28771
            Ask:          1.28775
            Time msc:     2023.07.20 17:04:51.378
            Flags:        BID|ASK
          Tick[3] GBPUSD:
            Time:         2023.07.20 17:04:51
            Bid:          1.28772
            Ask:          1.28776
            Time msc:     2023.07.20 17:04:51.680
            Flags:        BID|ASK
       */
      }
    
    


    Estrutura MqlRates

    Uma estrutura para armazenar informações sobre preços, volumes e spreads.

    struct MqlRates
      {
       datetime time;         // period start time
       double   open;         // open price
       double   high;         // high price for the period
       double   low;          // low price for the period
       double   close;        // close price
       long     tick_volume;  // tick volume
       int      spread;       // spread
       long     real_volume;  // exchange volume
      };
    

    MqlRates, métodos de impressão

    MqlRates é uma estrutura para armazenar dados de uma única barra de dados históricos. Você pode preencher a estrutura usando a função CopyRates(). Para obter dados da barra atual, você pode usar a primeira forma da função com um índice 0 e a quantidade de barras copiadas igual a 1. Em qualquer caso, essa função preenche um array do tipo MqlRates. Portanto, é conveniente imprimir esse array no log usando ArrayPrint():

    void OnStart()
      {
    //---
       MqlRates array[];
       if(CopyRates(Symbol(),PERIOD_CURRENT,0,1,array)!=1)
         {
          Print("CopyRates failed, error: ",(string)GetLastError());
          return;
         }
       Print("Current bar ",Symbol()," ",StringSubstr(EnumToString(Period()),7)," (ArrayPrint):");
       ArrayPrint(array);
       /* Sample output:
          Current bar GBPUSD H1 (ArrayPrint):
                           [time]  [open]  [high]   [low] [close] [tick_volume] [spread] [real_volume]
          [0] 2023.07.21 04:00:00 1.28763 1.28765 1.28663 1.28748          2083        7             0
       */
      }
    
    

    Portanto, para copiar os últimos dez bares, basta especificar a quantidade de dados copiados como 10:

    void OnStart()
      {
    //---
       MqlRates array[];
       if(CopyRates(Symbol(),PERIOD_CURRENT,0,10,array)!=10)
         {
          Print("CopyRates failed, error: ",(string)GetLastError());
          return;
         }
       Print("Data of the last 10 bars: ",Symbol()," ",StringSubstr(EnumToString(Period()),7)," (ArrayPrint):");
       ArrayPrint(array);
       /* Sample output:
          Data of the last 10 bars: GBPUSD H1 (ArrayPrint):
                           [time]  [open]  [high]   [low] [close] [tick_volume] [spread] [real_volume]
          [0] 2023.07.20 20:00:00 1.28530 1.28676 1.28512 1.28641          2699        4             0
          [1] 2023.07.20 21:00:00 1.28641 1.28652 1.28557 1.28587          1726        3             0
          [2] 2023.07.20 22:00:00 1.28587 1.28681 1.28572 1.28648          2432        3             0
          [3] 2023.07.20 23:00:00 1.28648 1.28683 1.28632 1.28665           768        4             0
          [4] 2023.07.21 00:00:00 1.28663 1.28685 1.28613 1.28682           396        1             0
          [5] 2023.07.21 01:00:00 1.28684 1.28732 1.28680 1.28714           543        8             0
          [6] 2023.07.21 02:00:00 1.28714 1.28740 1.28690 1.28721           814        2             0
          [7] 2023.07.21 03:00:00 1.28721 1.28774 1.28685 1.28761          2058        5             0
          [8] 2023.07.21 04:00:00 1.28763 1.28791 1.28663 1.28774          3480        7             0
          [9] 2023.07.21 05:00:00 1.28774 1.28776 1.28769 1.28774            18        7             0
       */
      }
    
    

    Sim, aqui é mais do mesmo - uma longa lista de dados no log. Se o cabeçalho da tabela estiver oculto na parte superior da janela do log, não fica claro a que se referem todos os números apresentados.

    Vamos escrever nossas próprias funções para retornar descrições dos campos da estrutura e imprimir esses dados no log do terminal.


    Funções para trabalhar com os dados da estrutura MqlRates.

    Nossas funções personalizadas retornarão descrições de texto para cada campo da estrutura. Cada descrição terá um cabeçalho e os próprios dados. Você pode especificar um recuo da borda esquerda e a largura do campo do cabeçalho para a string retornada.


    Time:

    Time é o horário de início do período. Em outras palavras, é o horário de abertura da barra no símbolo e período do gráfico a partir do qual os dados armazenados na estrutura são solicitados.

    //+------------------------------------------------------------------+
    //| Return the bar opening time as a string                          |
    //+------------------------------------------------------------------+
    string MqlRatesTime(const MqlRates &rates,const uint header_width=0,const uint indent=0)
      {
    //--- Define the header text and the width of the header field
    //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
       string header="Time:";
       uint w=(header_width==0 ? header.Length()+1 : header_width);
    //--- Return the property value with a header having the required width and indentation
       return StringFormat("%*s%-*s%-s",indent,"",w,header,(string)rates.time);
       /* Sample output:
          Time: 2023.07.21 06:00:00
       */
      }
    
    


    Open:

    O preço de abertura da barra no símbolo e período do gráfico a partir do qual os dados armazenados na estrutura são solicitados.

    //+------------------------------------------------------------------+
    //| Return the bar open price as a string                            |
    //+------------------------------------------------------------------+
    string MqlRatesOpen(const string symbol,const MqlRates &rates,const uint header_width=0,const uint indent=0)
      {
    //--- Define the header text and the width of the header field
    //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
       string header="Open:";
       uint w=(header_width==0 ? header.Length()+1 : header_width);
    //--- Get the number of decimal places
       int dg=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS);
    //--- Return the property value with a header having the required width and indentation
       return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,rates.open);
       /* Sample output:
          Open: 1.28812
       */
      }
    
    


    High:

    Preço High é o preço mais alto da barra no símbolo e período do gráfico a partir do qual os dados armazenados na estrutura são solicitados.

    //+------------------------------------------------------------------+
    //| Return the High bar price as a string                            |
    //+------------------------------------------------------------------+
    string MqlRatesHigh(const string symbol,const MqlRates &rates,const uint header_width=0,const uint indent=0)
      {
    //--- Define the header text and the width of the header field
    //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
       string header="High:";
       uint w=(header_width==0 ? header.Length()+1 : header_width);
    //--- Get the number of decimal places
       int dg=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS);
    //--- Return the property value with a header having the required width and indentation
       return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,rates.high);
       /* Sample output:
          High: 1.28859
       */
      }
    
    


    Low:

    Preço Low é o preço mais baixo da barra no símbolo e período do gráfico a partir do qual os dados armazenados na estrutura são solicitados.

    //+------------------------------------------------------------------+
    //| Return the bar Low price as a string                             |
    //+------------------------------------------------------------------+
    string MqlRatesLow(const string symbol,const MqlRates &rates,const uint header_width=0,const uint indent=0)
      {
    //--- Define the header text and the width of the header field
    //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
       string header="Low:";
       uint w=(header_width==0 ? header.Length()+1 : header_width);
    //--- Get the number of decimal places
       int dg=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS);
    //--- Return the property value with a header having the required width and indentation
       return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,rates.low);
       /* Sample output:
          Low: 1.28757
       */
      }
    
    


    Close:

    Preço Close é o preço de fechamento da barra no símbolo e período do gráfico a partir do qual os dados armazenados na estrutura são solicitados.
    Para a barra atual, o preço de fechamento é igual ao preço atual de Bid ou Last, dependendo de como o gráfico é construído.

    //+------------------------------------------------------------------+
    //| Return the bar close price as a string                           |
    //+------------------------------------------------------------------+
    string MqlRatesClose(const string symbol,const MqlRates &rates,const uint header_width=0,const uint indent=0)
      {
    //--- Define the header text and the width of the header field
    //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
       string header="Close:";
       uint w=(header_width==0 ? header.Length()+1 : header_width);
    //--- Get the number of decimal places
       int dg=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS);
    //--- Return the property value with a header having the required width and indentation
       return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,rates.close);
       /* Sample output:
          Close: 1.28770
       */
      }
    
    


    TickVolume:

    O volume de ticks da barra.

    //+------------------------------------------------------------------+
    //| Return the tick volume of a bar as a string                      |
    //+------------------------------------------------------------------+
    string MqlRatesTickVolume(const MqlRates &rates,const uint header_width=0,const uint indent=0)
      {
    //--- Define the header text and the width of the header field
    //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
       string header="Tick Volume:";
       uint w=(header_width==0 ? header.Length()+1 : header_width);
    //--- Return the property value with a header having the required width and indentation
       return StringFormat("%*s%-*s%-lld",indent,"",w,header,rates.tick_volume);
       /* Sample output:
          Tick Volume: 963
       */
      }
    
    


    Spread:

    O spread na barra.

    //+------------------------------------------------------------------+
    //| Return the bar spread as a string                                |
    //+------------------------------------------------------------------+
    string MqlRatesSpread(const MqlRates &rates,const uint header_width=0,const uint indent=0)
      {
    //--- Define the header text and the width of the header field
    //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
       string header="Spread:";
       uint w=(header_width==0 ? header.Length()+1 : header_width);
    //--- Return the property value with a header having the required width and indentation
       return StringFormat("%*s%-*s%-ld",indent,"",w,header,rates.spread);
       /* Sample output:
          Spread: 4
       */
      }
    
    


    RealVolume:

    O volume real da barra.

    //+------------------------------------------------------------------+
    //| Return the bar exchange volume as a string                       |
    //+------------------------------------------------------------------+
    string MqlRatesRealVolume(const MqlRates &rates,const uint header_width=0,const uint indent=0)
      {
    //--- Define the header text and the width of the header field
    //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
       string header="Real Volume:";
       uint w=(header_width==0 ? header.Length()+1 : header_width);
    //--- Return the property value with a header having the required width and indentation
       return StringFormat("%*s%-*s%-lld",indent,"",w,header,rates.real_volume);
       /* Sample output:
          Real Volume: 0
       */
      }
    
    


    Exemplos de uso.

    Para imprimir os dados das últimas 10 barras no log, escreveremos o seguinte script:

    void OnStart()
      {
    //--- Copy the last 10 data bars to the MqlRates array
       MqlRates array[];
       if(CopyRates(Symbol(),PERIOD_CURRENT,0,10,array)!=10)
         {
          Print("CopyRates failed, error: ",(string)GetLastError());
          return;
         }
    
    //--- Set the indexing of the array like a timeseries
       ArraySetAsSeries(array,true);
    //--- Print short entries in the journal in a loop through the array with the received bar data
       for(int i=0;i<(int)array.Size();i++)
          MqlRatesPrint(Symbol(),PERIOD_CURRENT,array[i],true,0,0,i);
       
       /* Sample output:
          GBPUSD H1[0]: 2023.07.21 14:00:00, O: 1.28451, H: 1.28541, L: 1.28451, C: 1.28501, S:  4, V:   821, RV: 0
          GBPUSD H1[1]: 2023.07.21 13:00:00, O: 1.28678, H: 1.28685, L: 1.28418, C: 1.28452, S:  1, V:  3602, RV: 0
          GBPUSD H1[2]: 2023.07.21 12:00:00, O: 1.28581, H: 1.28696, L: 1.28557, C: 1.28678, S:  1, V:  4807, RV: 0
          GBPUSD H1[3]: 2023.07.21 11:00:00, O: 1.28695, H: 1.28745, L: 1.28401, C: 1.28581, S:  1, V:  7440, RV: 0
          GBPUSD H1[4]: 2023.07.21 10:00:00, O: 1.28933, H: 1.28960, L: 1.28651, C: 1.28696, S:  1, V:  8883, RV: 0
          GBPUSD H1[5]: 2023.07.21 09:00:00, O: 1.28788, H: 1.29040, L: 1.28753, C: 1.28934, S:  1, V:  5474, RV: 0
          GBPUSD H1[6]: 2023.07.21 08:00:00, O: 1.28794, H: 1.28848, L: 1.28713, C: 1.28787, S:  1, V:  1885, RV: 0
          GBPUSD H1[7]: 2023.07.21 07:00:00, O: 1.28762, H: 1.28808, L: 1.28744, C: 1.28794, S:  4, V:   878, RV: 0
          GBPUSD H1[8]: 2023.07.21 06:00:00, O: 1.28812, H: 1.28859, L: 1.28743, C: 1.28760, S:  3, V:  1112, RV: 0
          GBPUSD H1[9]: 2023.07.21 05:00:00, O: 1.28774, H: 1.28820, L: 1.28747, C: 1.28812, S:  7, V:  1671, RV: 0
       */
      }
    
    

    Após copiar a quantidade necessária de dados para um array, faremos uma indexação para ele, como em uma série de tempo, para que os dados sejam exibidos da mesma forma que as barras do gráfico no terminal, onde os dados com índice zero correspondem à barra atual.

    Esse script imprimirá no log as últimas 4 barras em um formato de tabela, com um recuo de dois caracteres à esquerda e uma largura de campo de cabeçalho de 14 caracteres:

    void OnStart()
      {
    //--- Copy the last 4 data bars to the MqlRates array
       MqlRates array[];
       if(CopyRates(Symbol(),PERIOD_CURRENT,0,4,array)!=4)
         {
          Print("CopyRates failed, error: ",(string)GetLastError());
          return;
         }
    
    //--- Set the indexing of the array like a timeseries
       ArraySetAsSeries(array,true);
    //--- Print short entries in the journal in a loop through the array with the received bar data
       for(int i=0;i<(int)array.Size();i++)
          MqlRatesPrint(Symbol(),PERIOD_CURRENT,array[i],false,14,2,i);
       
       /* Sample output:
          GBPUSD H1[0]:
            Time:         2023.07.21 14:00:00
            Open:         1.28451
            High:         1.28541
            Low:          1.28451
            Close:        1.28491
            Tick Volume:  1098
            Spread:       4
            Real Volume:  0
          GBPUSD H1[1]:
            Time:         2023.07.21 13:00:00
            Open:         1.28678
            High:         1.28685
            Low:          1.28418
            Close:        1.28452
            Tick Volume:  3602
            Spread:       1
            Real Volume:  0
          GBPUSD H1[2]:
            Time:         2023.07.21 12:00:00
            Open:         1.28581
            High:         1.28696
            Low:          1.28557
            Close:        1.28678
            Tick Volume:  4807
            Spread:       1
            Real Volume:  0
          GBPUSD H1[3]:
            Time:         2023.07.21 11:00:00
            Open:         1.28695
            High:         1.28745
            Low:          1.28401
            Close:        1.28581
            Tick Volume:  7440
            Spread:       1
            Real Volume:  0
       */
      }
    
    


    Estrutura MqlBookInfo

    Uma estrutura que fornece informações sobre o livro de ofertas.

    struct MqlBookInfo
      {
       ENUM_BOOK_TYPE   type;            // order type from ENUM_BOOK_TYPE enumeration
       double           price;           // price
       long             volume;          // volume
       double           volume_real;     // volume with increased accuracy
      };
    

    Para usar a estrutura, basta declarar uma variável desse tipo. O livro de ofertas não está disponível para todos os instrumentos financeiros. Antes de obter os dados do livro de ofertas, é necessário se inscrever para recebê-los usando MarketBookAdd(). Após a conclusão do trabalho com o livro de ofertas, é necessário cancelar a inscrição: MarketBookRelease(). Para lidar com as notificações recebidas no programa do expert, a função void OnBookEvent() deve estar presente.


    MqlBookInfo, métodos de impressão

    Cada obtenção do livro de ofertas implica a obtenção de uma lista de ordens presentes no livro de ofertas. Portanto, isso é um array de dados. Sendo assim, podemos imprimir um instantâneo do livro de ofertas usando ArrayPrint():

    void OnStart()
      {
    //--- Declare an array to store a snapshot of the market depth
       MqlBookInfo array[];
    //--- If unable to open the market depth and subscribe to its events, inform of that and leave
       if(!MarketBookAdd(Symbol()))
         {
          Print("MarketBookAdd failed, error: ",(string)GetLastError());
          return;
         }
    //--- If unable to obtain the market depth entries, inform of that and leave
       if(!MarketBookGet(Symbol(),array))
         {
          Print("MarketBookGet failed, error: ",(string)GetLastError());
          return;
         }
    //--- Print the header in the journal and the market depth snapshot from the array below
       Print("MarketBookInfo by ",Symbol(),":");
       ArrayPrint(array);
    //--- If unable to unsubscribe from the market depth, send an error message to the journal
       if(!MarketBookRelease(Symbol()))
          Print("MarketBookRelease failed, error: ",(string)GetLastError());
       /* Sample output:
          MarketBookInfo by GBPUSD:
              [type] [price] [volume] [volume_real]
          [0]      1 1.28280      100     100.00000
          [1]      1 1.28276       50      50.00000
          [2]      1 1.28275       20      20.00000
          [3]      1 1.28273       10      10.00000
          [4]      2 1.28268       10      10.00000
          [5]      2 1.28266       20      20.00000
          [6]      2 1.28265       50      50.00000
          [7]      2 1.28260      100     100.00000
       */
      }
    
    

    Como podemos ver, os tipos de ordens aqui são expressos como valores numéricos, o que não é conveniente para a percepção. Vamos escrever funções para retornar descrições dos campos do livro de ofertas no estilo já aceito para outras estruturas mencionadas anteriormente.


    Funções para trabalhar com os dados da estrutura MqlBookInfo.

    Todas as funções que retornam uma representação de string dos campos da estrutura MqlBookInfo serão mantidas no mesmo estilo das funções de descrição dos campos das estruturas correspondentes. Vamos analisá-las em ordem.


    Tipo de ordem na estrutura do livro de ofertas MqlBookInfo:

    //+------------------------------------------------------------------+
    //| Return the order type in the market depth as a string            |
    //+------------------------------------------------------------------+
    string MqlBookInfoType(const MqlBookInfo &book,const uint header_width=0,const uint indent=0)
      {
    //--- Get the value of the order type
       ENUM_BOOK_TYPE book_type=book.type;
    //--- "Cut out" the type from the string obtained from enum
       string type=StringSubstr(EnumToString(book_type),10);
    //--- Convert all obtained symbols to lower case and replace the first letter from small to capital
       if(type.Lower())
          type.SetChar(0,ushort(type.GetChar(0)-0x20));
    //--- Replace all underscore characters with space in the resulting line
       StringReplace(type,"_"," ");
    //--- Define the header text and the width of the header field
    //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
       string header="Type:";
       uint w=(header_width==0 ? header.Length()+1 : header_width);
    //--- Return the property value with a header having the required width and indentation
       return StringFormat("%*s%-*s%-s",indent,"",w,header,type);
       /* Sample output:
          Type: Sell
       */
      }
    
    


    Preço da ordem na estrutura do livro de ofertas MqlBookInfo:

    //+------------------------------------------------------------------+
    //| Return the order price in the market depth as a string           |
    //+------------------------------------------------------------------+
    string MqlBookInfoPrice(const string symbol,const MqlBookInfo &book,const uint header_width=0,const uint indent=0)
      {
    //--- Define the header text and the width of the header field
    //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
       string header="Price:";
       uint w=(header_width==0 ? header.Length()+1 : header_width);
    //--- Get the number of decimal places
       int dg=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS);
    //--- Return the property value with a header having the required width and indentation
       return StringFormat("%*s%-*s%-.*f",indent,"",w,header,dg,book.price);
       /* Sample output:
          Price: 1.28498
       */
      }
    
    


    Volume da ordem na estrutura do livro de ofertas MqlBookInfo:

    //+------------------------------------------------------------------+
    //| Return the order volume in the market depth as a string          |
    //+------------------------------------------------------------------+
    string MqlBookInfoVolume(const MqlBookInfo &book,const uint header_width=0,const uint indent=0)
      {
    //--- Define the header text and the width of the header field
    //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
       string header="Volume:";
       uint w=(header_width==0 ? header.Length()+1 : header_width);
    //--- Return the property value with a header having the required width and indentation
       return StringFormat("%*s%-*s%-lld",indent,"",w,header,book.volume);
       /* Sample output:
          Volume: 100
       */
      }
    
    


    Volume com alta precisão:

    //+------------------------------------------------------------------+
    //| Return the order volume with increased accuracy as a string      |
    //+------------------------------------------------------------------+
    string MqlBookInfoVolumeReal(const MqlBookInfo &book,const uint header_width=0,const uint indent=0)
      {
    //--- Define the header text and the width of the header field
    //--- If the header width is passed to the function equal to zero, then the width will be the size of the header line + 1
       string header="Volume Real:";
       uint w=(header_width==0 ? header.Length()+1 : header_width);
    //--- Return the property value with a header having the required width and indentation
       return StringFormat("%*s%-*s%-.2f",indent,"",w,header,book.volume_real);
       /* Sample output:
          Volume Real: 100.00
       */
      }
    
    


    Exemplos de uso.

    Agora, escreveremos uma função que imprimirá todos os dados da estrutura MqlBookInfo no log. Você poderá imprimir em dois modos: em uma única linha e em formato de tabela:

    //+------------------------------------------------------------------+
    //| Logs a description of all fields of the MqlRates structure       |
    //+------------------------------------------------------------------+
    void MqlBookInfoPrint(const string symbol,const MqlBookInfo &book,
                          const bool short_entry=true,const uint header_width=0,const uint indent=0,int index=WRONG_VALUE)
      {
    //--- Declare the variable for storing the result
       string res="";
    //--- Get the number of decimal places and the string index value
       int dg=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS);
       string num=(index==WRONG_VALUE ? "" : StringFormat("[%02ld]",index));
       
    //--- "Cut out" the type from the order type name string obtained from enum
       string type=StringSubstr(EnumToString(book.type),10);
    //--- Convert all obtained symbols to lower case and replace the first letter from small to capital
       if(type.Lower())
          type.SetChar(0,ushort(type.GetChar(0)-0x20));
    //--- Replace all underscore characters with space in the resulting line
       StringReplace(type,"_"," ");
       
    //--- If it is a short entry, log the market depth data in the [index] Type Price V VR format
       if(short_entry)
         {
          res=StringFormat("%-8s%-11s%- *.*f Volume%- 5lld Real%- 8.2f",
                           num,type,dg+4,dg,book.price,book.volume,book.volume_real);
          Print(res);
         }
       /* Sample output:
          [00]    Sell        1.28598  Volume 100  Real 100.00 
       */
    //--- Otherwise
       else
         {
          //--- create a string describing all the data of the structure with indents and a given width of the header field 
          res=StringFormat("Market Book by %s %s:\n%s\n%s\n%s\n%s",symbol,num,
                           MqlBookInfoType(book,header_width,indent),
                           MqlBookInfoPrice(symbol,book,header_width,indent),
                           MqlBookInfoVolume(book,header_width,indent),
                           MqlBookInfoVolumeReal(book,header_width,indent)
                          );
          //--- Display the obtained string in the journal
          Print(res);
         }
       /* Sample output
          BoolInfo by GBPUSD [00]:
            Type:         Sell
            Price:        1.28588
            Volume:       100
            Volume Real:  100.00
       */
      }
    
    

    O modo principal aqui deve ser a impressão em uma única linha no log, pois o livro de ofertas não é apenas uma ordem, e recebemos uma lista delas em um array. Assim, você pode imprimir esse array no log usando essa função:

    //+---------------------------------------------------------------------+
    //| Display the market depth entries in the journal in the short format |
    //+---------------------------------------------------------------------+
    void MqlBookInfoPrintShort(const string symbol,const MqlBookInfo &book_array[])
      {
       PrintFormat("Market Book by %s:",symbol);
       for(int i=0;i<(int)book_array.Size();i++)
          MqlBookInfoPrint(symbol,book_array[i],true,0,0,i);
      }
    
    

    A função recebe um array de ordens do livro de ofertas e, em um loop através do array, imprime todos os dados do livro de ofertas no log usando uma saída concisa.

    Script que demonstra o funcionamento dessa função e o resultado:

    void OnStart()
      {
    //--- Declare an array to store a snapshot of the market depth
       MqlBookInfo array[];
    //--- If unable to open the market depth and subscribe to its events, inform of that and leave
       if(!MarketBookAdd(Symbol()))
         {
          Print("MarketBookAdd failed, error: ",(string)GetLastError());
          return;
         }
    //--- If unable to obtain the market depth entries, inform of that and leave
       if(!MarketBookGet(Symbol(),array))
         {
          Print("MarketBookGet failed, error: ",(string)GetLastError());
          return;
         }
    //--- Print in the journal a snapshot of the market depth from the array in the form of strings
       MqlBookInfoPrintShort(Symbol(),array);
    
    //--- If unable to unsubscribe from the market depth, send an error message to the journal
       if(!MarketBookRelease(Symbol()))
          Print("MarketBookRelease failed, error: ",(string)GetLastError());
       
       /* Sample output:
          Market Book by GBPUSD:
          [00]    Sell        1.28674  Volume 100  Real 100.00 
          [01]    Sell        1.28668  Volume 50   Real 50.00  
          [02]    Sell        1.28666  Volume 20   Real 20.00  
          [03]    Sell        1.28664  Volume 10   Real 10.00  
          [04]    Buy         1.28657  Volume 10   Real 10.00  
          [05]    Buy         1.28654  Volume 20   Real 20.00  
          [06]    Buy         1.28653  Volume 50   Real 50.00  
          [07]    Buy         1.28646  Volume 100  Real 100.00 
       */
      }
    
    

    No entanto, em alguns casos, você pode precisar exibir os mesmos dados em formato de tabela. Para fazer isso, você pode usar a seguinte função:

    //+------------------------------------------------------------------------+
    //| Display the market depth entries in the journal in the tabular format  |
    //+------------------------------------------------------------------------+
    void MqlBookInfoPrintTable(const string symbol,const MqlBookInfo &book_array[],const uint header_width=0,const uint indent=0)
      {
       for(int i=0;i<(int)book_array.Size();i++)
          MqlBookInfoPrint(symbol,book_array[i],false,header_width,indent,i);
      }
    
    

    Script que demonstra o funcionamento dessa função e o resultado:

    void OnStart()
      {
    //--- Declare an array to store a snapshot of the market depth
       MqlBookInfo array[];
    //--- If unable to open the market depth and subscribe to its events, inform of that and leave
       if(!MarketBookAdd(Symbol()))
         {
          Print("MarketBookAdd failed, error: ",(string)GetLastError());
          return;
         }
    //--- If unable to obtain the market depth entries, inform of that and leave
       if(!MarketBookGet(Symbol(),array))
         {
          Print("MarketBookGet failed, error: ",(string)GetLastError());
          return;
         }
    //--- Print in the journal a snapshot of the market depth from the array in the form of strings
       MqlBookInfoPrintTable(Symbol(),array,14,2);
    
    //--- If unable to unsubscribe from the market depth, send an error message to the journal
       if(!MarketBookRelease(Symbol()))
          Print("MarketBookRelease failed, error: ",(string)GetLastError());
       
       /* Sample output:
          Market Book by GBPUSD [00]:
            Type:         Sell
            Price:        1.28627
            Volume:       100
            Volume Real:  100.00
          Market Book by GBPUSD [01]:
            Type:         Sell
            Price:        1.28620
            Volume:       50
            Volume Real:  50.00
          Market Book by GBPUSD [02]:
            Type:         Sell
            Price:        1.28618
            Volume:       20
            Volume Real:  20.00
          Market Book by GBPUSD [03]:
            Type:         Sell
            Price:        1.28615
            Volume:       10
            Volume Real:  10.00
          Market Book by GBPUSD [04]:
            Type:         Buy
            Price:        1.28610
            Volume:       10
            Volume Real:  10.00
          Market Book by GBPUSD [05]:
            Type:         Buy
            Price:        1.28606
            Volume:       20
            Volume Real:  20.00
          Market Book by GBPUSD [06]:
            Type:         Buy
            Price:        1.28605
            Volume:       50
            Volume Real:  50.00
          Market Book by GBPUSD [07]:
            Type:         Buy
            Price:        1.28599
            Volume:       100
            Volume Real:  100.00
       */
      }
    
    


    Considerações finais

    Nós examinamos a impressão dos campos de quatro estruturas: MqlDateTime, MqlTick, MqlRates e MqlBookInfo. As funções criadas retornam descrições dos campos de cada estrutura no formato "Cabeçalho-Dados" como uma string que pode ser impressa ou usada dentro de outra função. Todas as funções são autossuficientes, prontas para uso, e podem ser usadas diretamente em seus programas. A próxima etapa é lidar com as estruturas de transações comerciais - sua descrição e impressão no log.


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

    Análise de ciclos usando o algoritmo de Goertzel Análise de ciclos usando o algoritmo de Goertzel
    Neste artigo, são apresentados utilitários que implementam o algoritmo de Goertzel em MQL5 e duas maneiras de aplicar esse método na análise de cotações de preços para o desenvolvimento de estratégias.
    Desenvolvendo um sistema de Replay (Parte 38): Pavimentando o Terreno (II) Desenvolvendo um sistema de Replay (Parte 38): Pavimentando o Terreno (II)
    Muita gente que se diz programador de MQL5, não tem as bases que estarei apresentando aqui, neste artigo. Muitos consideram o MQL5 algo limitado, mas tudo isto se deve a falta de conhecimento. Então, não fique com vergonha por não saber. Mas tenha vergonha de não perguntar. Mas o simples fato, de forçar, e obrigar o MetaTrader 5 a não permitir que um indicador seja duplicado. Não nos dá de maneira alguma meios de efetivar uma comunicação bilateral entre o indicador e o EA. Ainda estamos um pouco longe disto. Mas o simples fato de que o indicador não estará duplicado no gráfico, já nos garante uma certa tranquilidade.
    Teoria das Categorias em MQL5 (Parte 14): funtores com ordem linear Teoria das Categorias em MQL5 (Parte 14): funtores com ordem linear
    Este artigo, parte de uma série de artigos sobre a implementação da teoria das categorias no MQL5, é dedicado aos funtores. Vamos explorar como a ordem linear pode ser mapeada em um conjunto de dados através dos funtores ao analisar dois conjuntos de dados que, à primeira vista, parecem não ter nenhuma conexão entre si.
    Redes neurais de maneira fácil (Parte 50): Soft Actor-Critic (otimização do modelo) Redes neurais de maneira fácil (Parte 50): Soft Actor-Critic (otimização do modelo)
    No artigo anterior, implementamos o algoritmo Soft Actor-Critic, mas não conseguimos treinar um modelo lucrativo. Neste artigo, vamos realizar a otimização do modelo previamente criado para obter os resultados desejados a nível de seu funcionamento.