Aprendendo PrintFormat() e obtendo exemplos prontos para uso
A saída de valores para o log ou para a tela do monitor é uma operação simples e conhecida, até que seja necessário gerar algo mais complexo do que "Hello, world". Mas, mais cedo ou mais tarde, surge aquela situação em que você precisa gerar uma saída formatada de um valor ou de uma propriedade que não é necessária com frequência. Certamente, você pode acessar a Documentação MQL5 e se lembrar do que esqueceu ou não sabia.
Mas, às vezes, você quer ter uma coleção de receitas prontas para produzir todos os tipos de informações fornecidas pelo terminal MetaTrader 5. Neste artigo, tentaremos entender as nuances da chamada da função PrintFormat e escrever modelos prontos que podem ser simplesmente inseridos em seu código.
Conteúdo
- Introdução
- PrintFormat(). O que é e como funciona
- Formatação de exibição das propriedades da conta
- Exibição de propriedades inteiras da conta
- Número da conta:
- Tipo de conta de negociação
- Tamanho da alavancagem
- Número máximo de ordens
- Modo garantia mínima
- Permitir negociação para a conta
- Permitir negociação para o EA
- Modo cálculo da margem
- Número de casas decimais para a moeda da conta
- Sinal de fechamento FIFO
- Permitir posições opostas por símbolo
- Exibição de propriedades reais da conta
- Saldo da conta
- Crédito concedido
- Lucro total
- Fundos próprios
- Fundos de garantia reservados
- Fundos livres disponíveis para abrir posição
- Nível de garantia da conta em porcentagem
- Nível de garantia para acionar Margin Call
- Nível de garantia para acionar Stop Out
- Quantidade reservada na conta para cobrir margem de todas as ordens pendentes
- Quantidade mínima reservada na conta para cobrir o valor mínimo de todas as posições abertas
- Ativos totais
- Quantidade de passivos
- Comissões bloqueadas
- Exibição das propriedades de string da conta
- Nome do cliente
- Nome do servidor de negociação
- Nome da moeda do depósito
- Nome de uma empresa que atende a conta
- Função para imprimir todas as informações da conta no log
- Tempo com milissegundos dos detalhes do tick
- Considerações finais
Introdução
Qualquer programa que trabalhe em um terminal deve ser capaz de informar o usuário sobre o seu estado e o estado do seu ambiente. Esses dados são sempre registrados no log do programa, que pode ser visto na guia "Experts" do terminal de negociação. Mais tarde, ao analisar os logs do programa, é importante que todos os registros estejam em um formato conveniente, pois a facilidade de leitura e busca de informações depende disso.
A linguagem MQL5 tem a função Print(), que imprime no log strings ou dados convertidos em strings, da forma como estão escritos nessas strings. Para um breve registro em log, isso é suficiente. Mas se imprimirmos grandes conjuntos de dados no log, é bom que eles sejam formatados de uma forma fácil de entender.
Quando o cabeçalho de dados (descrição) e seu valor correspondente são registrados em uma linha sem nenhuma formatação, a leitura desses dados em uma lista curta não causará dificuldades. Por outro lado, se houver muitos dados, e todos eles se sucederem e tiverem diferentes tamanhos de descrições e valores, tudo se transformará em um longo fluxo de informações. É desejável formatar esses dados e colocá-los em um único formato tabular, em que todos os cabeçalhos tenham a mesma largura (coluna de cabeçalho) e os dados correspondentes aos cabeçalhos estejam localizados à mesma distância do cabeçalho (coluna de dados). E essa possibilidade existe. É a função PrintFormat() que formata e imprime conjuntos de caracteres e valores no log do Expert Advisor de acordo com a de acordo com um formato especificado.
PrintFormat(). O que é e como funciona
A função PrintFormat() tem como entrada uma string de formato que descreve como os dados devem ser exibidos e um conjunto de dados correspondente à string de formato.Esses dados serão colocados na string resultante de acordo com a maneira de exibi-los no log. Para cada um dos valores, é possível especificar um formato de saída distinto. Eis um esquema:
("%Value1 is to be displayed like this%Value2 is to be displayed like this%Value3 is to be displayed like this ... ... %ValueN is to be displayed like this some text", Value1, Value2, Value3, ... ..., ValueN)
Como podemos ver, onde quisermos exibir dados no texto, devemos ter strings de formato que descrevam como os valores dos dados devem ser exibidos. Cada string de formato é precedida por um sinal de %, que informa que a seguir está a descrição do formato de exibição. Entre as descrições de formato pode ser escrito qualquer texto (no exemplo acima, está escrito no final como "algum texto"). Depois de terminar de inserir a string com caracteres de formato e texto, os dados são colocados na ordem em que o formato de exibição foi definido na string de formato, separados por vírgula. No exemplo acima, cada descrição de formato e seu valor correspondente são marcados com a mesma cor.
Isso significa que primeiro escrevemos o texto que deve ser exibido no log. Em seguida, dentro do texto, se houver dados nesse ponto, inserimos os caracteres de formato dos dados.
Por exemplo: ("%Este texto estará em uma coluna com largura de 50 caracteres%estes dados double estarão na próxima coluna e alinhados à esquerda", variável_de_string_da_primeira_coluna, double_variável_da_segunda_coluna);
Naturalmente, para descrever tudo isso, não é necessário usar texto, pois existem caracteres de formato especiais. Eles devem estar em uma ordem estritamente definida, mas nem todos eles precisam estar presentes na string de formato.
A string de formato é lida da esquerda para a direita. Quando a primeira especificação de formato é encontrada (se houver), o valor do primeiro parâmetro após a string de formato é convertido e exibido de acordo com a especificação fornecida. A segunda especificação de formato aciona a conversão e exibição do segundo parâmetro e assim por diante, até o final da string de formato.
A especificação de formato tem a seguinte forma:
%[flags][width][.precision][{h | l | ll | I32 | I64}]type
Vamos analisar cada um dos elementos da string de formato conforme descrito na documentação e descrever em mais detalhes.
Símbolo de porcentagem (%) - inicia uma nova string de formato. Após este símbolo, deve ser pelo menos um especificador, sendo importante entender que o especificador de tipo (type) é o único campo obrigatório para a saída formatada. Ou seja, se um '%' for inserido na string, o tipo de dados a ser exibido deve ser especificado após ele. Ou outro símbolo de porcentagem (%) pode ser inserido - para incluir um '%' no texto. Para evitar que isso inicie uma nova string de formato e, em vez disso, insira apenas o símbolo de porcentagem no texto, é necessário escrever a combinação: '%%'.
Então, os sinalizadores (flags):
- - (sinal de menos): Indica que o texto será alinhado à esquerda dentro da largura especificada. A largura é definida pelo especificador de largura (width) que segue o sinalizador. Se você escrever "%-10", isso significa que o texto será alinhado à esquerda em um campo de 10 caracteres. O texto subsequente nesta linha será colocado a partir da extremidade direita deste mesmo campo de 10 caracteres. Se o texto dentro deste campo de 10 caracteres for maior do que 10 caracteres, o próximo texto será colocado a partir do final deste texto e não do campo. Ou seja, o campo se expande para o comprimento do texto que é colocado nele. O texto não é truncado na largura do campo, pelo contrário, o campo se expande para acomodar o comprimento do texto.
void OnStart() { //--- Declare the variables to be printed string header=""; // Data header double value1=0; // First value double value2=0; // Second value //--- First line with a header of less than 10 characters and data in 20-character fields //--- The header and data are pressed to the left edge of their field header="10characters"; value1=10000000; value2=20000000; PrintFormat("%-10s%-20ld%-20lld",header,(int)value1,(long)value2); //--- Second line with a header of more than 10 characters and data in 20-character fields //--- The header and data are pressed to the left edge of their field header="Over10characters"; value1=10000000; value2=20000000; PrintFormat("%-10s%-20ld%-20lld",header,(int)value1,(long)value2); /* Sample output: 10characters10000000 20000000 Over10characters10000000 20000000 */ }
- + (sinal de mais): Para tipos numéricos, o sinal + ou - será sempre exibido, dependendo do valor dos dados a serem exibidos. Por exemplo: +222 ou -12.35. Se duas linhas de texto formatado seguirem uma após a outra e na linha superior os dados a serem exibidos forem positivos, enquanto na linha inferior forem negativos, visualmente os valores serão deslocados um caractere um do outro (devido ao sinal '-'). Abaixo, será explicada um sinalizador que elimina essa inconveniência visual.
void OnStart() { //--- Declare the variables to be printed string header=""; // Data header double value1=0; // First value double value2=0; // Second value //--- The first line with a header in a 16-character field and data in 20-character fields //--- The header and data are pressed to the left edge. //--- Data values of the second field are displayed with +/- signs header="Header1"; value1=-10000000; value2=20000000; PrintFormat("%-16s%-+20ld%-20lld",header,(int)value1,(long)value2); //--- The second line with a header in a 16-character field and data in 20-character fields //--- The header and data are pressed to the left edge. //--- Data values of the second field are displayed with +/- signs header="Header2"; value1=10000000; value2=-20000000; PrintFormat("%-16s%-+20ld%-20lld",header,(int)value1,(long)value2); /* Sample output: Header1 -10000000 20000000 Header2 +10000000 -20000000 */ }
- 0 (zero): Zeros são adicionados antes do valor a ser exibido, dentro da largura do campo especificada. Se o sinalizador 0 for usado com um formato de número inteiro (i, u, x, X, o, d) e uma especificação de precisão for definida (por exemplo, %04.d), o 0 será ignorado. Em outras palavras, para tipos inteiros que têm um formato de precisão definido (para exibir pelo menos tantos caracteres), os zeros líderes deste formato (formato 0) não têm prioridade, pois preenchem todo o campo, o que entra em conflito com o formato de precisão.
void OnStart() { //--- Declare the variables to be printed string header=""; // Data header double value1=0; // First value double value2=0; // Second value //--- The first line with a header in a 16-character field and data in 20-character fields //--- The header and data are pressed to the left edge. //--- Data values of the second field are displayed with +/- signs //--- The data values of the third field are pressed to the right edge with leading zeros added. header="Header1"; value1=-10000000; value2=20000000; PrintFormat("%-16s%-+20ld%020lld",header,(int)value1,(long)value2); //--- The second line with a header in a 16-character field and data in 20-character fields //--- The header and data of the second field are pressed to the left edge. //--- Data values of the second field are displayed with +/- signs //--- The data values of the third field are pressed to the right edge with leading zeros added. header="Header2"; value1=10000000; value2=-20000000; PrintFormat("%-16s%-+20ld%020lld",header,(int)value1,(long)value2); /* Sample output: Header1 -10000000 00000000000020000000 Header2 +10000000 -0000000000020000000 */ }
- (espaço em branco): Um espaço é colocado antes do valor a ser exibido, se o valor for numérico e positivo. Cada valor positivo deste campo com esse sinalizador é deslocado para a direita em um caractere. Isso permite alinhar visualmente os valores quando há valores positivos e negativos em uma coluna em diferentes linhas. Um espaço é inserido onde um sinal '-' apareceria para valores negativos.
void OnStart() { //--- Declare the variables to be printed string header=""; // Data header double value1=0; // First value double value2=0; // Second value //--- The first line with a header in a 16-character field and data in 20-character fields //--- The header and data of the second field are pressed to the left edge. //--- Data values of the third field are pressed to the right edge //--- For the second and third fields from the left, a space is added for positive values. header="Header1"; value1=-10000000; value2=20000000; PrintFormat("%-16s%- 20ld% 20lld",header,(int)value1,(long)value2); //--- The second line with a header in a 16-character field and data in 20-character fields //--- The header and data of the second field are pressed to the left edge. //--- Data values of the third field are pressed to the right edge //--- For the second and third fields from the left, a space is added for positive values. header="Header2"; value1=10000000; value2=-20000000; PrintFormat("%-16s%- 20ld% 20lld",header,(int)value1,(long)value2); /* Sample output: Header1 -10000000 20000000 Header2 10000000 -20000000 */ }
- sinal #
1. Se usado com os formatos o, x ou X, 0, 0x ou 0X é adicionado antes do valor exibido, respectivamente.
void OnStart() { //--- Declare the variables to be printed string header=""; // Data header double value1=0; // First value double value2=0; // Second value //--- First line with a header and data in 16-character fields //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed in decimal format //--- Data values of the third field are displayed in octal format with 0 added before the value header="Header1"; value1=10000; value2=10000; PrintFormat("%-16s(DEC) %-16ld(OCT) %-#16lo",header,(uint)value1,(uint)value2); //--- Second line with header and data in 16-character fields //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed in hexadecimal format with 0x added before the value //--- Data values of the third field are displayed in hexadecimal format with 0X added before the value header="Header2"; value1=10000; value2=10000; PrintFormat("%-16s(hex) %-#16lx(HEX) %-#16lX",header,(uint)value1,(uint)value2); /* Sample output: Header1 (DEC) 10000 (OCT) 023420 Header2 (hex) 0x2710 (HEX) 0X2710 */ }
2. Se usado com os formatos e, E, a ou A, o valor sempre é exibido com um ponto decimal.void OnStart() { //--- Declare the variables to be printed string header=""; // Data header double value1=0; // First value double value2=0; // Second value //--- The first line with a header in a 16-character field and data in 22-character fields //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed together with the 'e' format //--- Data values of the third field are displayed together with the 'E' format header="Header1"; value1=255; value2=1024; PrintFormat("%-16s(e) %-22e(E) %-#22E",header,(double)value1,(double)value2); //--- The second line with a header in a 16-character field and data in 22-character fields //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed together with the 'a' format //--- Data values of the third field are displayed together with the 'A' format header="Header2"; value1=255; value2=1024; PrintFormat("%-16s(a) %-#22a(A) %-#22A",header,(double)value1,(double)value2); /* Sample output: Header1 (e) 2.550000e+02 (E) 1.024000E+03 Header2 (a) 0x1.fe00000000000p+7 (A) 0X1.0000000000000P+10 */ }
3. Quando usado com os formatos g ou G, o sinalizador determina a presença de um ponto decimal no valor exibido e impede a remoção de zeros à esquerda. O formato g escolhe a representação mais compacta entre os formatos f ou e e exibe o valor no formato escolhido. O formato G é idêntico ao formato g, mas a escolha é feita entre os formatos f e E.void OnStart() { //--- Declare the variables to be printed string header=""; // Data header double value1=0; // First value double value2=0; // Second value //--- The first line with a header in a 16-character field and data in 22-character fields //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed together with the 'f' format with default precision //--- Data values of the third field are displayed together with the 'g' format header="Header1"; value1=Point(); value2=DBL_MAX; PrintFormat("%-16s(f) %-22f(g) %-#22g",header,(double)value1,(double)value2); //--- The second line with a header in a 16-character field and data in 22-character fields //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed together with the 'f' format with 5-character precision //--- Data values of the third field are displayed together with the 'G' format header="Header2"; value1=Point(); value2=EMPTY_VALUE; PrintFormat("%-16s(f) %-#22.5f(G) %-#22G",header,(double)value1,(double)value2); /* Sample output: Header1 (f) 0.000010 (g) 1.79769e+308 Header2 (f) 0.00001 (G) 1.79769E+308 */ }
O sinalizador # é ignorado quando usado em conjunto com os formatos c, d, i, u ou s.
Especificador de largura (width): número mínimo de caracteres exibidos no valor formatado. A interação do especificador com os sinalizadores foi discutida anteriormente. Há um detalhe interessante: se você usar um asterisco (*) como valor de largura, o valor a ser substituído no lugar do asterisco deve ser especificado na lista junto com os dados:
void OnStart() { //--- Declare the variables to be printed string header=""; // Data header double value1=0; // First value double value2=0; // Second value //--- The first line with a header in a *-character field (16) and data in *-character fields (22) //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed together with the 'f' format with default precision //--- Data values of the third field are displayed together with the 'g' format header="Header1"; value1=Point(); value2=DBL_MAX; PrintFormat("%-*s(f) %-*f(g) %-#*g",16,header,22,(double)value1,22,(double)value2); //--- The second line with a header in a *-character field (16) and data in *-character fields (22) //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed together with the 'f' format with 5-character precision //--- Data values of the third field are displayed together with the 'G' format header="Header2"; value1=Point(); value2=EMPTY_VALUE; PrintFormat("%-*s(f) %-#*.5f(G) %-#*G",16,header,22,(double)value1,22,(double)value2); /* Sample output: Header1 (f) 0.000010 (g) 1.79769e+308 Header2 (f) 0.00001 (G) 1.79769E+308 */ }
Neste exemplo, a saída não é diferente da anterior, mas aqui especificamos a largura de cada campo numericamente na lista de valores. Isso é útil quando a tabela é impressa dentro de uma função à qual podemos passar os valores de largura para cada coluna da tabela, e eles serão substituídos no lugar dos asteriscos na string de formato.
Especificador de precisão (.precision): número de dígitos após o ponto decimal. A especificação de precisão pode truncar parte do valor fracionário com ou sem arredondamento.
Para diferentes tipos de formato (type), a especificação de precisão é aplicada de maneira diferente:
- a, A: indica o número de dígitos após o ponto decimal.
void OnStart() { //--- Declare the variables to be printed string header=""; // Data header double value1=0; // First value double value2=0; // Second value //--- The first line with a header in a 16-character field and data in 22-character fields //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed together with the 'a' format with default precision //--- Data values of the third field are displayed together with the 'A' format with default precision header="Header1"; value1=Point(); value2=DBL_MAX; PrintFormat("%-16s(a) %-22a(A) %-#22A",header,(double)value1,(double)value2); //--- The second line with a header in a 16-character field and data in 22-character fields //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed together with the 'a' format with 5-character precision //--- Data values of the third field are displayed together with the 'A' format with 7-character precision header="Header2"; value1=Point(); value2=EMPTY_VALUE; PrintFormat("%-16s(a) %-#22.5a(A) %-#22.7A",header,(double)value1,(double)value2); /* Sample output: Header1 (a) 0x1.4f8b588e368f1p-17 (A ) 0X1.FFFFFFFFFFFFFP+1023 Header2 (a) 0x1.4f8b6p-17 (A) 0X2.0000000P+1023 */ }
- d, i, u, o, x, X: indica o número mínimo de dígitos a serem exibidos. Se o número de dígitos no parâmetro correspondente for menor do que a precisão especificada, o valor exibido será preenchido com zeros à esquerda. O valor exibido não é truncado se o número de dígitos a serem exibidos for maior do que a precisão especificada.
void OnStart() { //--- Declare the variables to be printed string header=""; // Data header double value1=0; // First value double value2=0; // Second value //--- The first line with a header in a 16-character field and data in 22-character fields //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed together with the 'd' format with 4-character precision //--- Data values of the third field are displayed together with the 'i' format with 11-character precision header="Header1"; value1=INT_MAX; value2=INT_MAX; PrintFormat("%-16s(d) %-22.4d(i) %-#22.11i",header,(int)value1,(int)value2); //--- The second line with a header in a 16-character field and data in 22-character fields //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed together with the 'u' format with 4-character precision //--- Data values of the third field are displayed together with the 'o' format with 11-character precision header="Header2"; value1=INT_MAX; value2=INT_MAX; PrintFormat("%-16s(u) %-#22.4u(o) %-#22.11o",header,(double)value1,(double)value2); //--- The third line with a header in a 16-character field and data in 22-character fields //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed together with the 'x' format with 4-character precision //--- Data values of the third field are displayed together with the 'X' format with 11-character precision header="Header3"; value1=INT_MAX; value2=INT_MAX; PrintFormat("%-16s(x) %-#22.4x(X) %-#22.11X",header,(double)value1,(double)value2); /* Sample output: Header1 (d) 2147483647 (i) 02147483647 Header2 (u) 4290772992 (o) 037760000000 Header3 (x) 0xffc00000 (X) 0X000FFC00000 */ }
- e, E, f: indica o número de dígitos a serem exibidos após o ponto decimal. O último dígito exibido é arredondado.
void OnStart() { //--- Declare the variables to be printed string header=""; // Data header double value1=0; // First value double value2=0; // Second value //--- The first line with a header in a 16-character field and data in 22-character fields //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed together with the 'e' format with 4-character precision //--- Data values of the third field are displayed together with the 'E' format with 11-character precision header="Header1"; value1=DBL_MAX; value2=DBL_MAX; PrintFormat("%-16s(e) %-22.4e(E) %-#22.11E",header,(double)value1,(double)value2); //--- The second line with a header in a 16-character field and data in 22-character fields //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed together with the 'f' format with 4-character precision //--- Data values of the third field are displayed together with the 'f' format with 11-character precision header="Header2"; value1=SymbolInfoDouble(Symbol(),SYMBOL_ASK); value2=SymbolInfoDouble(Symbol(),SYMBOL_ASK); PrintFormat("%-16s(f) %-#22.4f(f) %-#22.11f",header,(double)value1,(double)value2); /* Sample output: Header1 (e) 1.7977e+308 (E) 1.79769313486E+308 Header2 (f) 1.2729 (f) 1.27286000000 */ }
- g, G: indica o número máximo de dígitos significativos.
void OnStart() { //--- Declare the variables to be printed string header=""; // Data header double value1=0; // First value double value2=0; // Second value //--- The first line with a header in a 16-character field and data in 22-character fields //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed together with the 'g' format with 4-character precision //--- Data values of the third field are displayed together with the 'G' format with 11-character precision header="Header1"; value1=DBL_MAX; value2=SymbolInfoDouble(Symbol(),SYMBOL_ASK); PrintFormat("%-16s(g) %-22.4g(G) %-#22.11G",header,(double)value1,(double)value2); //--- The second line with a header in a 16-character field and data in 22-character fields //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed together with the 'g' format with 4-character precision //--- Data values of the third field are displayed together with the 'G' format with 11-character precision header="Header2"; value1=SymbolInfoDouble(Symbol(),SYMBOL_ASK); value2=DBL_MAX; PrintFormat("%-16s(g) %-#22.4g(G) %-#22.11G",header,(double)value1,(double)value2); /* Sample output: Header1 (g) 1.798e+308 (G) 1.2731600000 Header2 (g) 1.273 (G) 1.7976931349E+308 */ }
É importante notar que o número máximo de dígitos significativos não se refere ao número de dígitos após o ponto decimal. Todos os dígitos do número são levados em consideração. Por exemplo, se a largura for definida como 4 e o valor de Digits() for definido como 5, você não verá quatro dígitos após o ponto decimal no valor de preço. Neste exemplo, você verá apenas três dígitos após o ponto decimal (1.273), pois o quarto dígito do número é aquele antes do ponto decimal. - s: O número de caracteres a serem exibidos da sequência de caracteres. Se o comprimento da sequência de caracteres exceder o valor de precisão, a sequência de caracteres será truncada na saída.
void OnStart() { //--- //--- Declare the variables to be printed string header=""; // Data header double value1=0; // First value double value2=0; // Second value //--- The first line with a header in a 16-character field and data in 22-character fields //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed together with the 'g' format with 4-character precision //--- Data values of the third field are displayed together with the 's' format with 11-character precision header="Header1"; value1=DBL_MAX; value2=SymbolInfoDouble(Symbol(),SYMBOL_ASK); PrintFormat("%-16s(g) %-22.4g(s) %-#22.11s",header,(double)value1,(string)value2); //--- The second line with a header in a 16-character field and data in 22-character fields //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed together with the 'g' format with 5-character precision //--- Data values of the third field are displayed together with the 's' format with 4-character precision header="Header2"; value1=DBL_MAX; value2=SymbolInfoDouble(Symbol(),SYMBOL_ASK); PrintFormat("%-16s(g) %-#22.5g(s) %-#22.4s",header,(double)value1,(string)value2); /* Sample output: Header1 (g) 1.798e+308 (s) 1.2872 Header2 (g) 1.7977e+308 (s) 1.28 */ }
Especificador de tamanho de dados (h | l | ll | I32 | I64): indica o tamanho dos dados inteiros passados como parâmetro. Ao passar um número inteiro como parâmetro, podemos especificar o tamanho desses dados (int, uint, short, ushort, long, ulong). Abaixo está uma tabela de compatibilidade dos especificadores de tamanho com os tipos de dados:
Tamanho dos dados | Especificadores de tamanho | Especificadores de tipo |
---|---|---|
short | h | d, i, o, x, X |
ushort | h | u, o, x, X |
int | l (L pequeno), I32 | d, i, o, x, X |
uint | l (L pequeno), I32 | u, o, x, X |
long | ll (dois L's pequenos), I64 | d, i, o, x, X |
ulong | I64 | u, o, x, X |
Especificador de tipo de dados (type): único campo obrigatório para saída formatada.
Símbolo | Tipo | Formato |
---|---|---|
c | int | Caractere de tipo short (Unicode) |
C | int | Caractere de tipo char (ANSI) |
d | int | Inteiro decimal com sinal |
i | int | Inteiro decimal com sinal |
o | int | Inteiro octal sem sinal |
u | int | Inteiro decimal sem sinal |
x | int | Inteiro hexadecimal sem sinal usando "abcdef" |
X | int | Inteiro hexadecimal sem sinal usando "ABCDEF" |
e | double | Valor de ponto flutuante no formato [ – ]d.dddd e [sign]ddd, onde d é um dígito decimal, dddd são um ou mais dígitos decimais, ddd é um número de três dígitos que determina o tamanho da exponencial, sign é um sinal de mais ou menos |
E | double | Idêntico ao formato e, exceto que o sinal da exponencial é exibido em maiúsculas (E em vez de e) |
f | double | Valor de ponto flutuante no formato [ – ]dddd.dddd, onde dddd é um ou mais dígitos decimais. O número de dígitos exibidos antes do ponto decimal depende do valor do número. O número de dígitos após o ponto decimal depende da precisão necessária. |
g | double | Valor de ponto flutuante exibido no formato f ou e, dependendo de qual formato é mais compacto. |
G | double | Valor de ponto flutuante exibido no formato f ou E, dependendo de qual formato é mais compacto. |
a | double | Valor de ponto flutuante no formato [−]0xh.hhhh p±dd, onde h.hhhh é a mantissa em forma de dígitos hexadecimais usando "abcdef", dd é um ou mais dígitos da exponencial. O número de dígitos após o ponto é determinado pela especificação de precisão. |
A | double | Valor de ponto flutuante no formato [−]0xh.hhhh P±dd, onde h.hhhh é a mantissa em forma de dígitos hexadecimais usando "ABCDEF", dd é um ou mais dígitos da exponencial. O número de dígitos após o ponto é determinado pela especificação de precisão. |
s | string | Saída de uma string |
O tipo de dados permite especificar como gostaríamos de obter o registro no log do terminal. Por exemplo, ao usar os tipos 'c' ou 'C', obtemos um único caractere na saída. O valor passado como parâmetro indica o código desse caractere na tabela Unicode ou ANSI, enquanto o uso desse mesmo valor com outros especificadores de tipo exibirá o próprio valor do parâmetro no formato escolhido, mas não como um caractere:
void OnStart() { //--- Declare the variables to be printed string header=""; // Data header char value1=0; // First value char value2=0; // Second value //--- The first line with a header in a 16-character field and data in 10-character fields //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed together with the 'c' format //--- Data values of the third field are displayed together with the 'C' format header="Header1"; value1=65; value2=66; PrintFormat("%-16s(c) %-10c(C) %-10C",header,(char)value1,(char)value2); //--- The second line with a header in a 16-character field and data in 10-character fields //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed together with the 'c' format //--- Data values of the third field are displayed together with the 'C' format header="Header2"; value1=67; value2=68; PrintFormat("%-16s(c) %-10c(C) %-10C",header,(char)value1,(char)value2); //--- The third line with a header in a 16-character field and data in 10-character fields //--- The header and data of all fields are pressed to the left edge. //--- Data values of the second field are displayed together with the 'd' format //--- Data values of the third field are displayed together with the 'i' format header="Header3"; value1=65; value2=66; PrintFormat("%-16s(d) %-10d(i) %-10i",header,(int)value1,(int)value2); /* Sample output: Header1 (c) A (C) B Header2 (c) C (C) D Header3 (d) 65 (i) 66 */ }
Nós examinamos brevemente todos os especificadores de formatação para o texto exibido no log. Vamos ver como isso funciona em exemplos específicos de exibição das propriedades da conta de negociação.
Formatação de exibição das propriedades da conta
As propriedades da conta, sejam elas inteiras, de ponto flutuante ou de string, podem ser obtidas usando as funções AccountInfoInteger(), AccountInfoDouble() e AccountInfoString(), respectivamente.
Não é sempre necessário exibir a lista completa de todas as propriedades. Por isso, criaremos uma função para cada propriedade que imprimirá a descrição dessa propriedade no log. Então, a partir das funções prontas que imprimem as descrições das propriedades no log, poderemos montar qualquer função que imprima as propriedades desejadas no log, seja todas ou apenas algumas.
Na função, passaremos dois parâmetros: a largura do cabeçalho do campo e a margem do cabeçalho do campo em relação à margem esquerda. Começaremos em ordem: propriedades inteiras, seguidas de propriedades de ponto flutuante e, finalmente, propriedades de string.
Funções para impressão de propriedades inteiras da conta.
Número da conta:
//+------------------------------------------------------------------+ //| Print a description of the account number into the journal | //+------------------------------------------------------------------+ void AccountLoginPrint(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="Login:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation PrintFormat("%*s%-*s%-s",indent,"",w,header,(string)AccountInfoInteger(ACCOUNT_LOGIN)); /* Sample output: Login: 68008618 */ }
Na string de formato, começamos usando um asterisco para especificar a margem da linha à esquerda. Nos parâmetros da string, passamos o tamanho do campo de margem (no lugar do asterisco) e um valor de string - uma string vazia (no lugar do caractere s).
O formato "%*s" preencherá a string vazia passada nos parâmetros com espaços de acordo com o valor da margem, também passado nos parâmetros da string. Isso torna conveniente criar qualquer campo vazio na string com o tamanho necessário, usando espaços em branco. Em seguida, na string de formato, também especificamos o tamanho do campo de cabeçalho com um asterisco, passando no lugar dele o valor da variável w e a string de cabeçalho na variável header. O último parâmetro será o valor do número da conta de AccountInfoInteger() como uma string.
Tipo de conta:
//+------------------------------------------------------------------+ //| Print a trading account type into the journal | //+------------------------------------------------------------------+ void AccountTradeModePrint(const uint header_width=0,const uint indent=0) { //--- Get the value of the trading account type ENUM_ACCOUNT_TRADE_MODE trade_mode=(ENUM_ACCOUNT_TRADE_MODE)AccountInfoInteger(ACCOUNT_TRADE_MODE); //--- "Cut out" the name of the trading account type from the line obtained from enum string mode=StringSubstr(EnumToString(trade_mode),19); //--- Convert the characters of the resulting line to lower case and replace the first letter from small to capital if(mode.Lower()) mode.SetChar(0,ushort(mode.GetChar(0)-0x20)); //--- 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="Trade mode:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation PrintFormat("%*s%-*s%-s",indent,"",w,header,mode); /* Sample output: Trade mode: Demo */ }
Tamanho da alavancagem:
//+------------------------------------------------------------------+ //| Print a description of the provided leverage size in the journal | //+------------------------------------------------------------------+ void AccountLeveragePrint(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="Leverage:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation PrintFormat("%*s%-*s1:%-s",indent,"",w,header,(string)AccountInfoInteger(ACCOUNT_LEVERAGE)); /* Sample output: Leverage: 1:100 */ }
Número máximo de ordens:
//+------------------------------------------------------------------+ //| Print a description of the maximum allowed | //| number of active pending orders | //+------------------------------------------------------------------+ void AccountLimitOrdersPrint(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="Limit orders:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation PrintFormat("%*s%-*s%-s",indent,"",w,header,(string)AccountInfoInteger(ACCOUNT_LIMIT_ORDERS)); /* Sample output: Limit orders: 200 */ }
Modo garantia mínima:
//+------------------------------------------------------------------+ //| Print a description of the mode for setting a minimal | //| accepted level of collateral in the journal | //+------------------------------------------------------------------+ void AccountMarginSOModePrint(const uint header_width=0,const uint indent=0) { //--- Get the value of the mode for setting the minimum available collateral ENUM_ACCOUNT_STOPOUT_MODE so_mode=(ENUM_ACCOUNT_STOPOUT_MODE)AccountInfoInteger(ACCOUNT_MARGIN_SO_MODE); //--- "Cut out" the mode name from the line obtained from enum string mode=StringSubstr(EnumToString(so_mode),21); //--- Convert the characters of the resulting line to lower case and replace the first letter from small to capital if(mode.Lower()) mode.SetChar(0,ushort(mode.GetChar(0)-0x20)); //--- 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="StopOut mode:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation PrintFormat("%*s%-*s%-s",indent,"",w,header,mode); /* Sample output: StopOut mode: Percent */ }
Permitir negociação para a conta:
//+------------------------------------------------------------------+ //| Print a description | //| of allowing trading for the current account in the journal | //+------------------------------------------------------------------+ void AccountTradeAllowedPrint(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="Trade allowed:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation //--- Depending on the bool value of the property, pass the "Yes" or "No" line as a parameter PrintFormat("%*s%-*s%-s",indent,"",w,header,((bool)AccountInfoInteger(ACCOUNT_TRADE_ALLOWED) ? "Yes" : "No")); /* Sample output: Trade allowed: Yes */ }
Permitir negociação para o EA:
//+------------------------------------------------------------------+ //| Print a description | //| allowing trading for an EA | //+------------------------------------------------------------------+ void AccountTradeExpertPrint(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="Trade expert:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation //--- Depending on the bool value of the property, pass the "Yes" or "No" line as a parameter PrintFormat("%*s%-*s%-s",indent,"",w,header,((bool)AccountInfoInteger(ACCOUNT_TRADE_EXPERT) ? "Yes" : "No")); /* Sample output: Trade expert: Yes */ }
Modo de cálculo de margem:
//+------------------------------------------------------------------+ //| Print a description of the margin calculation mode in the journal| //+------------------------------------------------------------------+ void AccountMarginModePrint(const uint header_width=0,const uint indent=0) { //--- Get the value of the margin calculation mode ENUM_ACCOUNT_MARGIN_MODE margin_mode=(ENUM_ACCOUNT_MARGIN_MODE)AccountInfoInteger(ACCOUNT_MARGIN_MODE); //--- "Cut out" the mode name from the line obtained from enum string mode=StringSubstr(EnumToString(margin_mode),20); //--- Convert the characters of the resulting line to lower case and replace the first letter from small to capital if(mode.Lower()) mode.SetChar(0,ushort(mode.GetChar(0)-0x20)); //--- Replace all underscore characters with space in the resulting line StringReplace(mode,"_"," "); //--- 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="Margin mode:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation PrintFormat("%*s%-*s%-s",indent,"",w,header,mode); /* Sample output: Margin mode: Retail hedging */ }
Número de casas decimais para a moeda da conta:
//+------------------------------------------------------------------+ //| Print a description of the number of | //| decimal places for an account currency | //+------------------------------------------------------------------+ void AccountCurrencyDigitsPrint(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="Currency digits:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation PrintFormat("%*s%-*s%-s",indent,"",w,header,(string)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS)); /* Sample output: Currency digits: 2 */ }
Sinal de fechamento FIFO:
//+------------------------------------------------------------------+ //| Print a description of the flag indicating | //| that positions can only be closed using the FIFO rule | //+------------------------------------------------------------------+ void AccountFIFOClosePrint(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="FIFO close:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation //--- Depending on the bool value of the property, pass the "Yes" or "No" line as a parameter PrintFormat("%*s%-*s%-s",indent,"",w,header,((bool)AccountInfoInteger(ACCOUNT_FIFO_CLOSE) ? "Yes" : "No")); /* Sample output: FIFO close: No */ }
Permitir posições opostas por símbolo:
//+------------------------------------------------------------------+ //| Print a description of the flag indicating | //| opposite positions are allowed on a single symbol | //+------------------------------------------------------------------+ void AccountHedgeAllowedPrint(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="Hedge allowed:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation //--- Depending on the bool value of the property, pass the "Yes" or "No" line as a parameter PrintFormat("%*s%-*s%-s",indent,"",w,header,((bool)AccountInfoInteger(ACCOUNT_HEDGE_ALLOWED) ? "Yes" : "No")); /* Sample output: Hedge allowed: Yes */ }
Funções para imprimir propriedades de ponto flutuante da conta.
Saldo da conta:
//+------------------------------------------------------------------------------------+ //| Print a description of the account balance in the deposit currency in the journal | //+------------------------------------------------------------------------------------+ void AccountBalancePrint(const uint header_width=0,const uint indent=0) { //--- Get the balance, the number of decimal places for the symbol and its name double ballance=AccountInfoDouble(ACCOUNT_BALANCE); int digits=(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS); string currency=AccountInfoString(ACCOUNT_CURRENCY); //--- 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="Balance:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation //--- To display the value correctly, replace the asterisk in the format line with the digits value for the symbol PrintFormat("%*s%-*s%-.*f %-s",indent,"",w,header,digits,ballance,currency); /* Sample output: Balance: 10015.00 USD */ }
Crédito fornecido:
//+------------------------------------------------------------------+ //| Print a description of account credit size | //| in a deposit currency | //+------------------------------------------------------------------+ void AccountCreditPrint(const uint header_width=0,const uint indent=0) { //--- Get the credit, the number of decimal places for the symbol and its name double credit=AccountInfoDouble(ACCOUNT_CREDIT); int digits=(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS); string currency=AccountInfoString(ACCOUNT_CURRENCY); //--- 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="Credit:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation //--- To display the value correctly, replace the asterisk in the format line with the digits value for the symbol PrintFormat("%*s%-*s%-.*f %-s",indent,"",w,header,digits,credit,currency); /* Sample output: Credit: 0.00 USD */ }
Lucro atual na conta:
//+------------------------------------------------------------------+ //| Print a description of account credit size | //| of the current profit in the deposit currency | //+------------------------------------------------------------------+ void AccountProfitPrint(const uint header_width=0,const uint indent=0) { //--- Get the current profit, the number of decimal places for the symbol and its name double profit=AccountInfoDouble(ACCOUNT_PROFIT); int digits=(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS); string currency=AccountInfoString(ACCOUNT_CURRENCY); //--- 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="Profit:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation //--- To display the value correctly, replace the asterisk in the format line with the digits value for the symbol PrintFormat("%*s%-*s%-.*f %-s",indent,"",w,header,digits,profit,currency); /* Sample output: Profit: 0.00 USD */ }
Fundos próprios na conta:
//+------------------------------------------------------------------+ //| Print a description of the value of | //| equity on an account in a deposit currency | //+------------------------------------------------------------------+ void AccountEquityPrint(const uint header_width=0,const uint indent=0) { //--- Get the equity, the number of decimal places for the symbol and its name double equity=AccountInfoDouble(ACCOUNT_EQUITY); int digits=(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS); string currency=AccountInfoString(ACCOUNT_CURRENCY); //--- 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="Equity:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation //--- To display the value correctly, replace the asterisk in the format line with the digits value for the symbol PrintFormat("%*s%-*s%-.*f %-s",indent,"",w,header,digits,equity,currency); /* Sample output: Equity: 10015.00 USD */ }
Fundos de garantia reservados:
//+------------------------------------------------------------------+ //| Print a description of account credit size | //| reserved collateral funds on the account in a deposit currency | //+------------------------------------------------------------------+ void AccountMarginPrint(const uint header_width=0,const uint indent=0) { //--- Get the reserved collateral, the number of decimal places for the symbol and its name double margin=AccountInfoDouble(ACCOUNT_MARGIN); int digits=(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS); string currency=AccountInfoString(ACCOUNT_CURRENCY); //--- 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="Margin:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation //--- To display the value correctly, replace the asterisk in the format line with the digits value for the symbol PrintFormat("%*s%-*s%-.*f %-s",indent,"",w,header,digits,margin,currency); /* Sample output: Margin: 0.00 USD */ }
Fundos livres disponíveis para abrir posição:
//+----------------------------------------------------------------------------------------+ //| Print a description of the free funds, | //| available for opening a position on an account in a deposit currency, in the journal | //+----------------------------------------------------------------------------------------+ void AccountMarginFreePrint(const uint header_width=0,const uint indent=0) { //--- Get the reserved collateral, the number of decimal places for the symbol and its name double margin_free=AccountInfoDouble(ACCOUNT_MARGIN_FREE); int digits=(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS); string currency=AccountInfoString(ACCOUNT_CURRENCY); //--- 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="Margin free:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation //--- To display the value correctly, replace the asterisk in the format line with the digits value for the symbol PrintFormat("%*s%-*s%-.*f %-s",indent,"",w,header,digits,margin_free,currency); /* Sample output: Margin free: 10015.00 USD */ }
Nível de garantia da conta em porcentagem:
//+------------------------------------------------------------------+ //| Print a description | //| of the collateral level on an account in % | //+------------------------------------------------------------------+ void AccountMarginLevelPrint(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="Margin level:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation //--- The value is set with 'digits' equal to 2 and the fact that the property is displayed in % is specified PrintFormat("%*s%-*s%-.2f %%",indent,"",w,header,AccountInfoDouble(ACCOUNT_MARGIN_LEVEL)); /* Sample output: Margin level: 0.00 % */ }
Nível de garantia para acionar Margin Call:
//+----------------------------------------------------------------------------+ //| Print a description of the collateral level, | //| at which a deposit to an account is required (Margin Call), in the journal | //+----------------------------------------------------------------------------+ void AccountMarginSOCallPrint(const uint header_width=0,const uint indent=0) { //--- Get the MarginCall level values, the number of decimal places for the symbol and its name double margin_so_call=AccountInfoDouble(ACCOUNT_MARGIN_SO_CALL); int digits=(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS); string currency=AccountInfoString(ACCOUNT_CURRENCY); //--- If the level of collateral for MarginCall is calculated as %, //--- specify 'currency' in % rather than in account currency, while 'digits' will be equal to 2 if(AccountInfoInteger(ACCOUNT_MARGIN_SO_MODE)==ACCOUNT_STOPOUT_MODE_PERCENT) { currency="%"; digits=2; } //--- 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="Margin Call:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation //--- To display the value correctly, replace the asterisk in the format line with the digits value obtained above PrintFormat("%*s%-*s%-.*f %s",indent,"",w,header,digits,margin_so_call,currency); /* Sample output: Margin Call: 50.00 % */ }
Nível de garantia para acionar Stop Out:
//+------------------------------------------------------------------+ //| Print a description of the collateral level, | //| upon reaching which | //| the most loss-making position is forcefully closed (Stop Out) | //+------------------------------------------------------------------+ void AccountMarginStopOutPrint(const uint header_width=0,const uint indent=0) { //--- Get the StopOut level values, the number of decimal places for the symbol and its name double margin_so_so=AccountInfoDouble(ACCOUNT_MARGIN_SO_SO); int digits=(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS); string currency=AccountInfoString(ACCOUNT_CURRENCY); //--- If the level of collateral for StopOut is calculated as %, //--- specify 'currency' in % rather than in account currency, while 'digits' will be equal to 2 if(AccountInfoInteger(ACCOUNT_MARGIN_SO_MODE)==ACCOUNT_STOPOUT_MODE_PERCENT) { currency="%"; digits=2; } //--- 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="Margin Stop Out:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation //--- To display the value correctly, replace the asterisk in the format line with the digits value obtained above PrintFormat("%*s%-*s%-.*f %s",indent,"",w,header,digits,margin_so_so,currency); /* Sample output: Margin Stop Out: 30.00 % */ }
Quantidade reservada na conta para cobrir margem de todas as ordens pendentes:
//+------------------------------------------------------------------+ //| Print a description of the funds | //| reserved on the account for security | //| of a guarantee amount for all pending orders | //+------------------------------------------------------------------+ void AccountMarginInitialPrint(const uint header_width=0,const uint indent=0) { //--- Get the amount of the reserved funds, the number of decimal places for the symbol and its name double margin_initial=AccountInfoDouble(ACCOUNT_MARGIN_INITIAL); int digits=(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS); string currency=AccountInfoString(ACCOUNT_CURRENCY); //--- 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="Margin initial:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation //--- To display the value correctly, replace the asterisk in the format line with the digits value for the symbol PrintFormat("%*s%-*s%-.*f %-s",indent,"",w,header,digits,margin_initial,currency); /* Sample output: Margin initial: 0.00 USD */ }
Quantidade mínima reservada na conta para cobrir o valor mínimo de todas as posições abertas:
//+------------------------------------------------------------------+ //| Print a description of the funds | //| reserved on the account for security | //| of the min amount of all open positions | //+------------------------------------------------------------------+ void AccountMarginMaintenancePrint(const uint header_width=0,const uint indent=0) { //--- Get the amount of the reserved funds, the number of decimal places for the symbol and its name double margin_maintenance=AccountInfoDouble(ACCOUNT_MARGIN_MAINTENANCE); int digits=(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS); string currency=AccountInfoString(ACCOUNT_CURRENCY); //--- 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="Margin maintenance:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation //--- To display the value correctly, replace the asterisk in the format line with the digits value for the symbol PrintFormat("%*s%-*s%-.*f %-s",indent,"",w,header,digits,margin_maintenance,currency); /* Sample output: Margin maintenance: 0.00 USD */ }
Ativos totais:
//+----------------------------------------------------------------------------+ //| Print a description of the current asset size on the account in the journal| //+----------------------------------------------------------------------------+ void AccountAssetsPrint(const uint header_width=0,const uint indent=0) { //--- Get the current asset size on the account, the number of decimal places for the symbol and its name double assets=AccountInfoDouble(ACCOUNT_ASSETS); int digits=(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS); string currency=AccountInfoString(ACCOUNT_CURRENCY); //--- 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="Assets:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation //--- To display the value correctly, replace the asterisk in the format line with the digits value for the symbol PrintFormat("%*s%-*s%-.*f %-s",indent,"",w,header,digits,assets,currency); /* Sample output: Assets: 0.00 USD */ }
Quantidade de passivos:
//+------------------------------------------------------------------+ //| Print a description | //| of the current liabilities on the account | //+------------------------------------------------------------------+ void AccountLiabilitiesPrint(const uint header_width=0,const uint indent=0) { //--- Get the current liabilities on the account, the number of decimal places for the symbol and its name double liabilities=AccountInfoDouble(ACCOUNT_LIABILITIES); int digits=(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS); string currency=AccountInfoString(ACCOUNT_CURRENCY); //--- 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="Liabilities:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation //--- To display the value correctly, replace the asterisk in the format line with the digits value for the symbol PrintFormat("%*s%-*s%-.*f %-s",indent,"",w,header,digits,liabilities,currency); /* Sample output: Liabilities: 0.00 USD */ }
Comissões bloqueadas:
//+------------------------------------------------------------------+ //| Print a description | //| of the current sum of blocked commissions on an account | //+------------------------------------------------------------------+ void AccountComissionBlockedPrint(const uint header_width=0,const uint indent=0) { //--- Get the current blocked commissions on the account, the number of decimal places for the symbol and its name double commission_blocked=AccountInfoDouble(ACCOUNT_COMMISSION_BLOCKED); int digits=(int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS); string currency=AccountInfoString(ACCOUNT_CURRENCY); //--- 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="Comission blocked:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation //--- To display the value correctly, replace the asterisk in the format line with the digits value for the symbol PrintFormat("%*s%-*s%-.*f %-s",indent,"",w,header,digits,commission_blocked,currency); /* Sample output: Comission blocked: 0.00 USD */ }
Funções para impressão de propriedades de string da conta.
Nome do cliente:
//+------------------------------------------------------------------+ //| Print a description of the client name into the journal | //+------------------------------------------------------------------+ void AccountNamePrint(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="Name:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation PrintFormat("%*s%-*s%-s",indent,"",w,header,AccountInfoString(ACCOUNT_NAME)); /* Sample output: Name: Artem */ }
Nome do servidor de negociação:
//+------------------------------------------------------------------+ //| Print a description of the trade server name into the journal | //+------------------------------------------------------------------+ void AccountServerPrint(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="Server:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation PrintFormat("%*s%-*s%-s",indent,"",w,header,AccountInfoString(ACCOUNT_SERVER)); /* Sample output: Server: MetaQuotes-Demo */ } //+------------------------------------------------------------------+
Nome da moeda do depósito:
//+------------------------------------------------------------------+ //| Print a description of a deposit currency name | //+------------------------------------------------------------------+ void AccountCurrencyPrint(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="Currency:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation PrintFormat("%*s%-*s%-s",indent,"",w,header,AccountInfoString(ACCOUNT_CURRENCY)); /* Sample output: Currency: USD */ }
Nome de uma empresa que atende a conta:
//+------------------------------------------------------------------+ //| Print a description of the company name, | //| serving an account, into the journal | //+------------------------------------------------------------------+ void AccountCompanyPrint(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="Company:"; uint w=(header_width==0 ? header.Length()+1 : header_width); //--- Print the property value in the log with a header with the required width and indentation PrintFormat("%*s%-*s%-s",indent,"",w,header,AccountInfoString(ACCOUNT_COMPANY)); /* Sample output: Company: MetaQuotes Software Corp. */ }
Todas as funções apresentadas acima são praticamente idênticas umas às outras. Cada uma delas permite definir o recuo da linha à esquerda e a largura do campo de cabeçalho. Os valores padrão de zero passados para as funções significam que não há recuo, e a largura do campo é igual ao tamanho do cabeçalho + 1 caractere. Assim, essas funções podem ser usadas conforme estão para imprimir as propriedades necessárias da conta no log. Mas quando for necessário criar uma função para imprimir um grupo de propriedades, será necessário definir o recuo e a largura do campo de cabeçalho para obter uma saída de valores bonita e fácil de ler no log.
Vamos criar um exemplo de tal função que imprime todas as propriedades da conta no log.
Função para imprimir todas as informações da conta no log:
//+------------------------------------------------------------------+ //| Print account data into the journal | //+------------------------------------------------------------------+ void AccountInfoPrint(const uint header_width=0,const uint indent=0) { //--- Display descriptions of integer properties according to their location in ENUM_ACCOUNT_INFO_INTEGER Print("AccountInfoInteger properties:"); AccountLoginPrint(header_width,indent); AccountTradeModePrint(header_width,indent); AccountLeveragePrint(header_width,indent); AccountLimitOrdersPrint(header_width,indent); AccountMarginSOModePrint(header_width,indent); AccountTradeAllowedPrint(header_width,indent); AccountTradeExpertPrint(header_width,indent); AccountMarginModePrint(header_width,indent); AccountCurrencyDigitsPrint(header_width,indent); AccountFIFOClosePrint(header_width,indent); AccountHedgeAllowedPrint(header_width,indent); //--- Display descriptions of real properties according to their location in ENUM_ACCOUNT_INFO_DOUBLE Print("AccountInfoDouble properties:"); AccountBalancePrint(header_width,indent); AccountCreditPrint(header_width,indent); AccountProfitPrint(header_width,indent); AccountEquityPrint(header_width,indent); AccountMarginPrint(header_width,indent); AccountMarginFreePrint(header_width,indent); AccountMarginLevelPrint(header_width,indent); AccountMarginSOCallPrint(header_width,indent); AccountMarginStopOutPrint(header_width,indent); AccountMarginInitialPrint(header_width,indent); AccountMarginMaintenancePrint(header_width,indent); AccountAssetsPrint(header_width,indent); AccountLiabilitiesPrint(header_width,indent); AccountComissionBlockedPrint(header_width,indent); //--- Display descriptions of string properties according to their location in ENUM_ACCOUNT_INFO_STRING Print("AccountInfoString properties:"); AccountNamePrint(header_width,indent); AccountServerPrint(header_width,indent); AccountCurrencyPrint(header_width,indent); AccountCompanyPrint(header_width,indent); }
A função chama sequencialmente todas as funções que imprimem dados das propriedades da conta, na ordem em que essas propriedades estão listadas nas enumerações ENUM_ACCOUNT_INFO_INTEGER, ENUM_ACCOUNT_INFO_DOUBLE e ENUM_ACCOUNT_INFO_STRING.
Resultado da chamada da função a partir de um script com largura de campo de cabeçalho de 20 caracteres e recuo de 2 caracteres:
void OnStart() { //--- Print trading account properties in the journal AccountInfoPrint(20,2); /* Sample output: AccountInfoInteger properties: Login: 68008618 Trade mode: Demo Leverage: 1:100 Limit orders: 200 StopOut mode: Percent Trade allowed: Yes Trade expert: Yes Margin mode: Retail hedging Currency digits: 2 FIFO close: No Hedge allowed: Yes AccountInfoDouble properties: Balance: 10015.00 USD Credit: 0.00 USD Profit: 2.11 USD Equity: 10017.11 USD Margin: 25.61 USD Margin free: 9991.50 USD Margin level: 39114.06 % Margin Call: 50.00 % Margin Stop Out: 30.00 % Margin initial: 0.00 USD Margin maintenance: 0.00 USD Assets: 0.00 USD Liabilities: 0.00 USD Comission blocked: 0.00 USD AccountInfoString properties: Name: Artem Server: MetaQuotes-Demo Currency: USD Company: MetaQuotes Software Corp. */ }
Tempo com milissegundos dos detalhes do tick
A estrutura MqlTick é projetada para obter rapidamente as informações mais solicitadas sobre os preços atuais.
Uma variável do tipo MqlTick permite obter os valores de Ask, Bid, Last e Volume com uma única chamada à função SymbolInfoTick(). Além disso, a estrutura contém o tempo do tick em milissegundos. O valor de tempo é armazenado em uma variável do tipo long. Ou seja, ao imprimir esses dados no log, simplesmente obtemos um número - a quantidade de milissegundos desde a data de 01/01/1970. Para exibir esses dados em um formato de tempo fácil de entender, é necessário converter esse número em uma data e adicionar o valor em milissegundos a essa data.
Para obter a data com segundos, você precisa dividir a quantidade de milissegundos por 1000, e para obter os milissegundos do tempo, você precisa pegar o resto da divisão por 1000 da quantidade de milissegundos da data.
Em geral, isso será semelhante a isto:
void OnStart() { //--- MqlTick tick; if(SymbolInfoTick(Symbol(),tick)) { string time_str=string((datetime)tick.time_msc / 1000)+"."+string(tick.time_msc % 1000); Print("time_str=",time_str); } /* Sample output: time_str=2023.07.10 18:49:36.463 */ }
Vamos escrever uma função que obtenha o tempo em milissegundos e o imprima no log no formato Data Hora.Ms:
//+------------------------------------------------------------------+ //| Print the time in the Date Time.Msc format in the journal | //+------------------------------------------------------------------+ void TimeMSCPrint(const long time_msc,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); //--- Print the date and time in the journal with a header with the required width and indentation, milliseconds with 3 digit precision PrintFormat("%*s%-*s%-s.%.3lu",indent,"",w,header,string((datetime)time_msc / 1000),time_msc % 1000); /* Sample output: Time msc: 2023.07.10 19:49:05.233 */ }
Para obter a data e hora em milissegundos e imprimi-los no log diretamente, você pode usar a seguinte função:
//+------------------------------------------------------------------+ //| Print the time in the Date Time.Msc format for a symbol | //+------------------------------------------------------------------+ void TimeMSCPrint(const string symbol,const uint header_width=0,const uint indent=0) { //--- Get time from the tick MqlTick tick; if(!SymbolInfoTick(symbol,tick)) { Print(__FUNCTION__,": SymbolInfoTick error: ",(string)GetLastError()); return; } //--- Print the time in milliseconds using the first version of the function TimeMSCPrint(tick.time_msc,header_width,indent); /* Sample output: Time msc: 2023.07.10 20:07:08.202 */ }
Considerações finais
Nesta visão geral, examinamos as capacidades do PrintFormat() para impressão de uma string formatada e criamos exemplos de funções para imprimir propriedades da conta que podem ser usadas "como estão" em seus programas. No entanto, há outra maneira de criar saída formatada - a função StringFormat(), que, ao contrário do PrintFormat(), que imprime a string no formato desejado no log, retorna a string formatada no formato especificado. Acredito que seja mais conveniente para a saída de texto formatado, pois cria a string necessária a partir das strings de formato, que podem ser posteriormente usadas em diferentes partes do programa, e não apenas impressas no log. No próximo artigo, discutiremos o StringFormat() e examinaremos suas capacidades.
Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/12905
- 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