English Русский 中文 Deutsch 日本語 Português
preview
Analizamos PrintFormat() y tomamos ejemplos listos para usar

Analizamos PrintFormat() y tomamos ejemplos listos para usar

MetaTrader 5Ejemplos | 6 diciembre 2023, 08:55
395 0
Artyom Trishkin
Artyom Trishkin

Enviar valores al registro o a la pantalla del monitor es una operación simple y familiar, hasta que sea necesario generar algo más complejo que "Hello, world". Pero tarde o temprano surge una situación en la que debemos generar la muestra formateada de un valor o propiedad que no suele ser necesario. Obviamente, podemos consultar la guía de ayuda de MQL5 y recordar lo que hemos olvidado o aprender lo que aún no sabemos.

Pero a veces queremos disponer de una colección de recetas preparadas para mostrar la amplia gama de información que el terminal MetaTrader 5 pone a nuestro alcance. En este artículo intentaremos analizar las complejidades de la llamada a la función PrintFormat y escribir plantillas listas para usar que simplemente se puedan insertar en nuestro código.


Contenido


Introducción

Cualquier programa que se ejecute en el terminal debe poder informar al usuario sobre su estado y el estado de su entorno. Estos datos siempre se escriben en el registro del programa, que podemos ver en la pestaña "Expertos" del terminal comercial. Posteriormente, al analizar los registros del programa, resulta importante que todas las entradas estén en un formato fácil de leer, porque de esto dependerá la facilidad de lectura y búsqueda de información.

El lenguaje MQL5 dispone de la función Print(), que imprime líneas o datos convertidos en líneas en el registro, en la forma en que estén escritos en dichas líneas. Para un log breve, esto resultará suficiente. Pero si enviamos grandes cantidades de datos al registro, entonces resultará deseable que estén en un formato que sea fácil de entender.

Cuando el encabezado de datos (descripción) y su valor correspondiente se escriben en una línea sin ningún formato, la lectura de dichos datos en una lista corta no causará dificultades. Otra cuestión es si hay muchos datos, y todos se suceden y tienen diferentes longitudes de descripciones y valores, entonces todo esto se convierte en un largo flujo de información. Resulta aconsejable formatear dichos datos y convertirlos en una única forma tabular, donde todos los encabezados tengan la misma anchura (columna de encabezados) y los datos correspondientes a los encabezados se ubiquen a la misma distancia del encabezado (columna de datos). Esta posibilidad existe. Hablamos de la función PrintFormat(), que formatea e imprime conjuntos de caracteres y valores en el diario experto según el formato especificado.


PrintFormat(). ¿Qué es y cómo funciona?

A la entrada de la función PrintFormat() se suministra una línea de formato que describe la forma en que se deben generar los datos, y un conjunto de datos correspondientes a la línea de formato, que se ubicarán en la línea resultante según el método de representación que se haya establecido para ellos en el registro. Para cada valor podemos establecer nuestro propio formato de muestra. Esquemáticamente tiene el aspecto siguiente:

("%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, en el lugar donde se deben mostrar ciertos datos en el texto, debe haber líneas de formato que describan el método para mostrar los valores de los datos mostrados. Cada línea de formato está precedida por un signo %, que indicará que lo que sigue es una descripción del formato de muestra. Podremos escribir cualquier texto entre las descripciones de formato (en el ejemplo anterior, está escrito al final como "algún texto"). Tras completar la introducción de una línea con los caracteres de formato y texto, los datos se separarán por comas en el orden en que se describa el formato de salida en la línea de formato. En el ejemplo anterior, cada descripción de formato y su valor correspondiente están marcados con el mismo color,

es decir, primero escribiremos el texto que debe enviarse al registro, y a continuación, dentro del texto, si los datos deben ubicarse en este lugar, introduciremos los símbolos del formato de muestra de datos.

Por ejemplo: ("%Este texto se encontrará en una columna con una anchura de 50 caracteres%estos datos double se encontrarán en la siguiente columna y alineados respecto al borde izquierdo", variable_string_con_el_texto_de_la_primera_columna, datos double_de_la_segunda_columna);

Naturalmente, para describir todo esto no se necesitará texto, pero existen caracteres de formato especial. Estos deberán ir en un orden estrictamente especificado, pero no todos deberán estar presentes en la línea de formato.

La línea de formato se lee de izquierda a derecha. Al encontrarse la primera especificación de formato (si la hay), el valor del primer parámetro después de la línea de formato se convertirá y se generará según la especificación indicada. La segunda especificación de formato hace que el segundo parámetro se convierta y se muestre, y así sucesivamente, hasta el final de la línea de formato.

La especificación de formato tiene la forma que sigue:

         %[flags][width][.precision][{h | l | ll | I32 | I64}]type

Veamos lo que está escrito en la guía de ayuda para cada elemento en la línea de formato y describámoslo con más detalle.

Signo de porcentaje (%) — comienza una nueva línea de formato. Debe haber al menos un especificador después de este icono y es importante comprender que el especificador de tipo (type) es el único campo obligatorio para la salida formateada. Es decir, si introducimos el signo '%' en una línea, entonces deberemos indicar después el tipo de datos que se muestran en este lugar. O bien otro signo de porcentaje, para escribir el signo '%' en el texto. Y para que este no sea el comienzo de una nueva línea de formato, sino simplemente un signo de porcentaje inscrito en el texto, deberemos escribir la combinación: '%%'.

Entonces, las banderas flags:

  • - (signo menos). Especificará que el texto de la línea se alineará a la izquierda dentro de la anchura especificada. La anchura se especifica mediante el especificador width que sigue a la bandera. Si escribimos "%-10", esto significará que el texto se alineará con el borde izquierdo del campo, que tendrá 10 caracteres de anchura. El siguiente texto de esta línea se ubicará partiendo del borde derecho del mismo campo en 10 caracteres. Si el texto que se muestra dentro de este campo de 10 caracteres tiene más de 10 caracteres, el siguiente texto se ubicará al final de este, no en el campo. Es decir, la anchura del campo se ampliará hasta el tamaño del texto colocado en él. El texto no se recortará a lo largo de la anchura del campo; por el contrario, el campo se expandirá a lo largo del 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            
       */
      }
    
    


  • + (signo más). Para los tipos con signo, siempre se generará un signo + o -, según el valor de los datos mostrados. Por ejemplo: +222 o -12,35. Si dos líneas de texto formateado son consecutivas, en la línea superior de la misma columna de datos el valor de los datos de salida será positivo, mientras que en la línea inferior será negativo, entonces visualmente los valores se desplazarán entre sí en un carácter (en el signo '-'). A continuación consideraremos una bandera que elimina este inconveniente 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 (cero). Antes del valor de salida, se añadirán ceros dentro de la anchura de campo especificada. Si el indicador 0 se especifica con un formato de número entero (i, u, x, X, o, d) y se indica una especificación de precisión (por ejemplo, %04.d), entonces 0 se ignorará. En otras palabras, para los tipos de enteros a los que se les da un formato de precisión (generan al menos tantos caracteres), los ceros iniciales de este formato (formato 0) no tendrán prioridad, ya que rellenarán todo el campo, lo cual contradice el formato de precisión.
    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
       */
      }
    
    


  • (espacio). El valor de salida va precedido de un espacio si el valor tiene signo y es positivo. Cada valor de datos positivo de un campo con esta bandera se desplazará un carácter hacia la derecha. Esto permitirá alinear visualmente los valores si existen valores positivos y negativos en diferentes filas de la misma columna. El carácter de espacio se colocará en lugar del carácter '-' de los datos 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
       */
      }
    
    


  • signo #.

    1. Cuando se usa junto con el formato o, x o X, se añadirá 0, 0x o 0X antes del valor de salida, 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. Al utilizarse junto con el formato e, E, a o A, el valor siempre se generará con un punto 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. Si se usa junto con el formato g o G, la bandera determinará la presencia de un punto decimal en el valor de salida y evitará que se corten los ceros a la izquierda. El formato g seleccionará el tipo de representación más compacto entre los formatos f o e y generará la representación en el formato seleccionado. El formato G es idéntico al formato g, pero se podrá elegir entre los formatos f y 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          
       */
      }
    
    

    La bandera # se ignorará cuando se use junto con los formatos c, d, i, u, s.


    Especificador de anchura (width). Número mínimo de caracteres del valor formateado para imprimir. Más arriba hemos discutido el funcionamiento del especificador junto con las banderas. Hay un matiz interesante: si especificamos un asterisco (signo *) como valor de anchura, entonces el asterisco debe sustituirse por el valor especificado en la lista junto con los datos:

    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          
       */
      }
    
    

    En este ejemplo, la salida no es diferente a la anterior, pero aquí especificaremos el anchura de cada campo como un parámetro numérico en la lista de valores. Esto resulta cómodo si la tabla se muestra dentro de una función a la que podemos transmitir los valores de anchura para cada columna de la tabla, y serán sustituidos por los asteriscos en la línea de formato.


    Especificador de precisión (.precision). Número de dígitos después del punto decimal. La especificación de la precisión puede recortar parte del valor fraccionario con o sin redondeo.

    Para diferentes tipos de formato (type), la especificación de precisión se aplicará de manera diferente:

    • a, A.  Indica el número de dígitos después del punto 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. Especifica el número mínimo de dígitos que se generarán. Si el número de dígitos en el parámetro correspondiente es inferior a la precisión especificada, entonces el valor mostrado se rellenará a la izquierda con ceros. El valor mostrado no se truncará si el número de dígitos de salida supera la precisión 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. Especifica el número de dígitos mostrados después del punto decimal. El último dígito mostrado estará redondeado.
      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. Especifica el 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     
      
         */
        }
      
      
      Tenga en cuenta aquí que el número máximo de dígitos significativos no significa el número de decimales. Aquí se consideran todos los caracteres del número. Si la profundidad de bits especificada es de 4 dígitos, en el caso de un valor de Digits() de cinco, no veremos cuatro dígitos después del punto decimal en el valor del precio. En este ejemplo, veremos solo tres dígitos después del punto decimal (1,273), ya que el cuarto dígito del número aquí es el número antes del punto decimal.


    • s. El número de caracteres en la línea a imprimir. Si la longitud de la línea excede el valor de precisión, entonces la línea se truncará en la muestra
      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 tamaño de datos (h | l | ll | I32 | I64). Indica el tamaño de los datos enteros transmitidos ​​como parámetro. Transmitiendo un número entero como parámetro, podemos especificar el tamaño de estos datos (int, uint, short, ushort, long, ulong). A continuación le mostramos una tabla de compatibilidad entre los especificadores de tamaño y los tipos de datos:

        Tamaño de datos
        Especificadores de tamaño
         Especificadores de tipo
          short   h
          d, i, o, x, X
          ushort   h
          u, o, x, X
          int
          l (L pequeña), I32
          d, i, o, x, X
          uint
          l (L pequeña), I32
          u, o, x, X
          long
          ll (dos L pequeñas), I64
          d, i, o, x, X
          ulong
          I64
          u, o, x, X


        Especificador de tipo de datos (type). Es el único campo obligatorio para la salida formateada. 

        Símbolo
         Tipo Formato
        c
        int
        Carácter de tipo short (Unicode)
        C
        int
        Carácter de tipo char (ANSI)
        d
        int
        Entero decimal con signo
        i
        int
        Entero decimal con signo
        o
        int
        Entero octal sin signo
        u
        int
        Entero decimal sin signo
        x
        int
        Entero hexadecimal sin signo usando "abcdef"
        X
        int
        Entero hexadecimal sin signo usando "ABCDEF"
        e
        double
        Valor real en el formato [ – ]d.dddd e [signo]ddd, donde d es un dígito decimal, dddd es uno o más dígitos decimales, ddd es un número de tres dígitos que define el tamaño del exponente, el signo es un signo más o menos
        E
        double
        Idéntico al formato e, salvo que el signo del exponente estará en mayúscula (E en lugar de e)
        f
        double
        Valor real en el formato [-]dddd.dddd, donde dddd es uno o más dígitos decimales. El número de dígitos mostrados antes del punto decimal dependerá del valor del número. El número de dígitos después del punto decimal dependerá de la precisión requerida.
        g
        double
        Valor real mostrado en formato f o e, dependiendo de qué salida sea más compacta.
        G
        double
        Valor real mostrado en formato f o E, dependiendo de qué salida sea más compacta.
        a
        double
        Valor real mostrado en el formato [−]0xh.hhhh p±dd, donde h.hhhh es la mantisa en dígitos hexadecimales usando "abcdef", dd es uno o más dígitos exponentes. El número de decimales estará determinado por la especificación de la precisión.
        A
        double
        Valor real mostrado en el formato [−]0xh.hhhh P±dd, donde h.hhhh es la mantisa en dígitos hexadecimales usando "ABCDEF", dd es uno o más dígitos exponentes. El número de decimales estará determinado por la especificación de la precisión.
        s
        string
        Muestra de la línea


        El tipo de datos nos permitirá especificar en qué forma queremos obtener la entrada en el registro del terminal. Por ejemplo, al utilizar los tipos 'c' o 'C', la salida será un carácter. El valor transmitido por los parámetros especificará el código de tabla Unicode o ANSI para ese carácter, mientras que el uso del mismo valor con otros especificadores de tipo mostrará el valor del parámetro en el formato elegido, pero no el carácter:

        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        
           */
          }
        
        

        Ya hemos analizado brevemente todos los especificadores de formato para la salida de texto en el registro. Veamos ahora cómo se ve esto usando ejemplos específicos sobre la muestra de las propiedades de una cuenta comercial.


        Muestra formateada de las propiedades de la cuenta

        Propiedades de la cuenta: entera, real y string; podemos obtenerlas usando AccountInfoInteger(), AccountInfoDouble() y AccountInfoString(), respectivamente.

        No siempre resulta necesario mostrar una lista completa con todas las propiedades. Por lo tanto, para cada propiedad crearemos una función que imprima una descripción de esta propiedad en el registro, y luego podremos (a partir de funciones listas para usar que generan las descripciones de las propiedades en el registro) ensamblar cualquier función que genere las propiedades requeridas en un registro, tanto todas, como solo algunas de forma selectiva.

        Después transmitiremos dos parámetros a la función: la anchura del campo del encabezado y la separación del campo de encabezado respecto al borde izquierdo. Comenzaremos por orden: propiedades enteras, luego propiedades reales y finalmente propiedades string.


        Funciones para imprimir propiedades enteras de la cuenta.

        Número de cuenta:

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

        En la línea de formato, primero indicaremos con un asterisco el tamaño de la separación de línea respecto al borde izquierdo. En los parámetros string, transmitiremos el tamaño del campo de la separación (en lugar del asterisco) y el valor de la línea: una línea vacía (en lugar del símbolo s).
        Y el formato "%*s" rellenará la línea vacía pasada en los parámetros con espacios según el valor de separación también transmitido a los parámetros de línea. Por lo tanto, resultará conveniente crear campos vacíos en una línea del tamaño requerido a partir de caracteres «espacio». Y luego en la línea de formato también indicaremos el tamaño del campo de encabezado con un asterisco, transmitiendo en su lugar el valor de la variable w y la línea de encabezado en la variable header. El último parámetro que tendremos será el valor del número de cuenta AccountInfoInteger() en forma de línea.


        Tipo de cuenta comercial:

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


        Tamaño del apalancamiento:

        //+------------------------------------------------------------------+
        //| 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 órdenes:

        //+------------------------------------------------------------------+
        //| 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 de garantía 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 el comercio para una cuenta:

        //+------------------------------------------------------------------+
        //| 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 el comercio para un experto:

        //+------------------------------------------------------------------+
        //| 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 del margen:

        //+------------------------------------------------------------------+
        //| 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 decimales para la divisa de la cuenta:

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


        Señal de cierre según la regla 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 posiciones opuestas en un 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
           */
          }
        
        


        Funciones para imprimir propiedades reales de una cuenta.

        Balance de la cuenta:

        //+------------------------------------------------------------------------------------+
        //| 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 concedido:

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


        Beneficio actual en la cuenta:

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


        Fondos propios en la cuenta:

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


        Fondos de garantía 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
           */
          }
        
        


        Fondos disponibles para abrir una posición:

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


        Nivel de garantía de la cuenta en porcentaje:

        //+------------------------------------------------------------------+
        //| 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 %
           */
          }
        
        


        Nivel de garantía para activar 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 %
           */
          }
        
        


        Nivel de garantía para activar 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 %
           */
          }
        
        


        Reserva de fondos para asegurar el importe de garantía de las órdenes pendientes:

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


        Reserva de fondos para garantizar el importe mínimo para todas las posiciones abiertas:

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


        Cantidad de los activos:

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


        Cantidad de los pasivos:

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


        Cantidad de comisiones 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
           */
          }
        
        


        Funciones para imprimir propiedades de línea de una cuenta.

        Nombre del 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
           */
          }
        
        


        Nombre del servidor comercial:

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


        Nombre de la divisa del 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
           */
          }
        
        


        Nombre de la empresa de servicios de la cuenta:

        //+------------------------------------------------------------------+
        //| 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 las funciones presentadas antes son casi idénticas entre sí. Cada una tiene la capacidad de establecer la separación de línea desde el borde izquierdo y la anchura del campo de encabezado. Los valores cero predeterminados transmitidos ​​a la función significan que no habrá rellenado y que la anchura del margen será igual al tamaño de la línea de encabezado + 1 carácter. Por lo tanto, estas funciones se podrán utilizar tal cual para registrar las propiedades de cuenta requeridas. Pero cuando necesitemos crear una función para mostrar un grupo de propiedades, requeriremos la separación y la anchura del campo del encabezado, para obtener así una muestra de valores hermosa y fácil de leer en el registro.

        Luego crearemos un ejemplo de una función que muestre todas las propiedades de la cuenta en un registro.

        Función que imprime todos los datos de la cuenta en el registro:

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

        La función llamará de forma sucesiva a todas las funciones que imprimen los datos de las propiedades de la cuenta, en el orden en que aparecen estas propiedades en ENUM_ACCOUNT_INFO_INTEGER, ENUM_ACCOUNT_INFO_DOUBLE y ENUM_ACCOUNT_INFO_STRING.

        Resultado de la llamada a una función desde un script con una anchura de campo de encabezado de 20 caracteres y una separación 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.
           */
          }
        
        


        Tiempo con milisegundos de las propiedades del tick

        La estructura MqlTick está diseñada para obtener rápidamente la información más demandada sobre los precios actuales.

        La variable de tipo MqlTick nos permite obtener los valores Ask, Bid, Last y Volumen en una sola llamada a la función SymbolInfoTick() . Además, la estructura contiene el tiempo del tick en milisegundos. El valor del tiempo se almacenará en una variable de tipo long. Es decir, al imprimir estos datos en el registro, simplemente obtendremos un número determinado: la cantidad de milisegundos transcurridos desde la fecha 01/01/1970. Para mostrar estos datos en un formato de hora legible por humanos, deberemos convertir este número en una fecha y añadir milisegundos a la fecha resultante.

        Para obtener una fecha con segundos, deberemos dividir la cantidad de milisegundos entre 1000, y para obtener los milisegundos en fecha y hora, deberemos dividir el resto de la cantidad de milisegundos de la fecha entre 1000.

        En general se verá así:

        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 a escribir una función que obtenga la hora en milisegundos y registre la hora en el formato Date Time.Msc:

        //+------------------------------------------------------------------+
        //| 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 obtener directamente la fecha y la hora en milisegundos y enviarlas al registro, podemos utilizar la siguiente función:

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


        Conclusión

        En esta descripción general, hemos analizado la capacidad de PrintFormat() para imprimir una línea formateada, y también hemos creado funciones de ejemplo para imprimir propiedades de la cuenta que podamos usar "tal cual" en nuestros programas. Pero hay otra forma de crear una muestra formateada: la función StringFormat(), que, a diferencia de PrintFormat(), que imprime una línea en el formato deseado en el registro, retorna una línea formateada en el formato especificado. Lo considero más conveniente para generar texto formateado, ya que crea la línea deseada a partir de líneas de formato, que luego se puede usar en diferentes lugares del programa, y ​​no solo ser mostrada en el registro. En el próximo artículo hablaremos sobre StringFormat() y veremos sus posibilidades.


        Traducción del ruso hecha por MetaQuotes Ltd.
        Artículo original: https://www.mql5.com/ru/articles/12905

        StringFormat(). Panorámica, ejemplos de uso listos para aplicar StringFormat(). Panorámica, ejemplos de uso listos para aplicar
        El artículo supone una continuación de la revisión de la función PrintFormat(). Hoy veremos brevemente cómo formatear líneas utilizando StringFormat() y su uso posterior en el programa. Asimismo, escribiremos plantillas para mostrar información sobre un símbolo en el registro del terminal. El presente artículo resultará útil tanto a principiantes como a desarrolladores experimentados.
        Teoría de categorías en MQL5 (Parte 13): Eventos del calendario con esquemas de bases de datos Teoría de categorías en MQL5 (Parte 13): Eventos del calendario con esquemas de bases de datos
        El artículo analiza cómo se pueden incluir esquemas de bases de datos para la clasificación en MQL5. Vamos a repasar brevemente cómo los conceptos de esquema de base de datos pueden combinarse con la teoría de categorías para identificar información textual (cadenas) relevante para el comercio. La atención se centrará en los eventos del calendario.
        Funciones en las aplicaciones MQL5 Funciones en las aplicaciones MQL5
        Las funciones son componentes de importancia crítica en cualquier lenguaje de programación. Entre otras cosas, ayudan a los desarrolladores a aplicar el principio DRY (don't repeat youself, no te repitas). El artículo analiza las funciones y su creación en MQL5 usando aplicaciones sencillas que enriquecen nuestros sistemas comerciales sin complicarlos.
        Recordando una antigua estrategia de tendencia: dos osciladores estocásticos, MA y Fibonacci Recordando una antigua estrategia de tendencia: dos osciladores estocásticos, MA y Fibonacci
        Estrategias comerciales antiguas. Este artículo presenta una estrategia de seguimiento de tendencias. La estrategia es puramente técnica y usa varios indicadores y herramientas para ofrecer señales y niveles objetivo. Los componentes de la estrategia incluyen: Un oscilador estocástico de 14 periodos, un oscilador estocástico de 5 periodos, una media móvil de 200 periodos y una proyección de Fibonacci (para fijar los niveles objetivo).