Estruturas em MQL5 e formas de imprimir seus dados
Conteúdo
- Introdução
- Estrutura MqlDateTime
- MqlDateTime, métodos de impressão
- Funções para trabalhar com os dados da estrutura MqlDateTime.
- Funções auxiliares
- Ano na estrutura MqlDateTime:
- Mês na estrutura MqlDateTime:
- Dia na estrutura MqlDateTime:
- Horas na estrutura MqlDateTime:
- Minutos na estrutura MqlDateTime:
- Segundos na estrutura MqlDateTime:
- Dia da semana na estrutura MqlDateTime:
- Número do dia no ano na estrutura MqlDateTime:
- Exemplos de utilização
- Estrutura MqlTick
- MqlTick, maneiras de impressão
- Funções para trabalhar com dados da estrutura MqlTick.
- Funções auxiliares
- Tempo na estrutura MqlTick:
- Preço Bid na estrutura MqlTick:
- Preço Ask na estrutura MqlTick:
- Preço da última negociação (Last) na estrutura MqlTick:
- Volume para o preço Last na estrutura MqlTick:
- Tempo em milissegundos na estrutura MqlTick:
- Flags de tick na estrutura MqlTick:
- Volume para o preço Last com precisão aumentada na estrutura MqlTick:
- Exemplo de uso:
- Estrutura MqlRates
- MqlRates, métodos de impressão
- Funções para trabalhar com os dados da estrutura MqlRates
- Time
- Open
- High
- Low
- Close
- TickVolume
- Spread
- RealVolume
- Exemplos de utilização
- Estrutura MqlBookInfo
- MqlBookInfo, métodos de impressão
- Funções para trabalhar com os dados da estrutura MqlBookInfo
- Tipo de ordem na estrutura do livro de ofertas MqlBookInfo
- Preço da ordem na estrutura do livro de ofertas MqlBookInfo
- Volume da ordem na estrutura do livro de ofertas MqlBookInfo
- Volume com alta precisão
- Exemplos de utilização
- Considerações finais
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:
- MqlDateTime é destinada a representar data e hora;
- MqlParam permite a transmissão de parâmetros de entrada ao criar um identificador de indicador usando a função IndicatorCreate();
- MqlRates fornece informações sobre dados históricos, incluindo preço, volume e spread;
- MqlBookInfo para obter informações exibidas no livro de ofertas (janela de cotações);
- MqlTradeRequest para criar uma solicitação de negociação ao realizar operações de negociação;
- MqlTradeCheckResult permite verificar a solicitação de negociação preparada antes de enviá-la;
- MqlTradeResult contém a resposta do servidor de negociação a uma solicitação de negociação enviada pela função OrderSend();
- MqlTradeTransaction contém a descrição de uma operação de negociação;
- MqlTick é destinada a obter rapidamente as informações mais solicitadas sobre os preços atuais.
- Estruturas do Calendário Econômico são destinadas a obter informações sobre eventos do Calendário Econômico que chegam à plataforma MetaTrader 5 em tempo real. As funções do Calendário Econômico permitem a análise imediata dos indicadores macroeconômicos assim que os novos relatórios são publicados, pois os valores atuais são transmitidos diretamente da fonte, sem atrasos.
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á:
- emitir dados em formato conciso (dia da semana, mês, dia, ano, hora);
- 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
- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Você concorda com a política do site e com os termos de uso