MetaTrader 5 build 3490: versión móvil del terminal web y nuevos métodos de matrices en MQL5

En la nueva versión del terminal web se ha añadido el soporte completo para dispositivos móviles. Ahora la interfaz se adapta automáticamente al tamaño de la pantalla, lo cual permite a los usuarios trabajar cómodamente en la plataforma tanto en teléfonos como tabletas con iOS y Android

4 noviembre 2022

Versión móvil del terminal web

En la nueva versión del terminal web se ha añadido el soporte completo para dispositivos móviles. Ahora la interfaz se adapta automáticamente al tamaño de la pantalla, lo cual permite a los usuarios trabajar cómodamente en la plataforma tanto en teléfonos como tabletas con iOS y Android:


Además, hemos introducido en el terminal web numerosas correcciones y mejoras.

El nuevo terminal web MetaTrader 5 ofrece todas las funciones que necesita un tráder moderno. La aplicación le permitirá:

  • Trabajar con cuentas demo y reales
  • Recibir cotizaciones de cualquier instrumento financiero
  • Comerciar en cualquier mercado
  • Realizar el análisis técnico de las cotizaciones con más de 30 indicadores y 20 objetos gráficos
  • Analizar los datos del Calendario Económico

Terminal

  1. Ampliadas las funciones del gestor de tareas. Ahora permite monitorear de forma más precisa el consumo de recursos.

    • Añadida la visualización del tamaño de la pila para los hilos
    • Añadida la visualización del número de cambios de contexto
    • Añadido el reconocimiento de los hilos del sistema y los hilos de las DLL de terceros
    • Añadida la visualización del tiempo de ejecución en el modo kernel. Un aumento de este indicador comparado con el tiempo de ejecución en el modo usuario puede indicar problemas a nivel de sistema: problemas de drivers, errores de hardware, hardware lento. Encontrará más información en la documentación de Microsoft.
    • Añadida la visualización del tiempo de funcionamiento en el modo usuario.



  2. Añadida una pestaña OpenCL a la configuración del terminal para administrar los dispositivos disponibles. El nuevo administrador de OpenCL nos permitirá indicar explícitamente los dispositivos que se utilizarán para los cálculos.




  3. Agregada la adición de niveles de Stop Loss y Take Profit en la Profundidad de Mercado para las cuentas que operan en el modo FIFO (se puede activar en el lado del bróker).

    El modo FIFO implica que las posiciones de cada instrumento deberán cerrarse en el orden en que se han abierto. Para garantizar que el cierre de posiciones según los niveles stop siempre se corresponda con la regla FIFO, en el lado del terminal del cliente se implementa siguiente lógica :

    Si hay varias posiciones para el mismo instrumento, la colocación de niveles stop para cualquiera de ellas dará lugar a la colocación de niveles stop similares para todas las demás. En consecuencia, al activarse un nivel, todas las posiciones se cerrarán según el orden de la regla FIFO.

    Al abrir la Profundidad de Mercado para un instrumento del que ya existen posiciones, los campos Stop Loss y Take Profit se rellenarán ahora automáticamente con los niveles de las posiciones existentes (si han sido establecido).

  4. Corregida la eliminación de los niveles de Stop Loss y Take Profit con los botones "X" en el apartado «Herramientas/Trading». El error se producía cuando la función de comercio rápido estaba desactivada. Al pulsar el botón, se abrirá una ventana de diálogo comercial con un valor en blanco para el nivel correspondiente.

  5. Se han realizado cambios en el informe comercial, hemos corregido los rótulos fijos en los gráficos y el cálculo de la comisión final. Salvo en algunos casos, se mostraba un beneficio incorrecto en las estadísticas del informe, además de valores incorrectos en la información sobre las herramientas al pasar el cursor del ratón sobre los gráficos de equidad y balance.

MQL5

  1. Añadidos los métodos vectoriales y matriciales CopyTicks y CopyTicksRange. Estos permiten copiar fácilmente los arrays de datos de precio en vectores y matrices.
    bool matrix::CopyTicks(string symbol,uint flags,ulong from_msc,uint count);
    bool vector::CopyTicks(string symbol,uint flags,ulong from_msc,uint count);
    
    bool matrix::CopyTicksRange(string symbol,uint flags,ulong from_msc,ulong to_msc);
    bool matrix::CopyTicksRange(string symbol,uint flags,ulong from_msc,ulong to_msc);
    El tipo de datos a copiar se indica en el parámetro rates_mask con la ayuda de la enumeración ENUM_COPY_RATES. Están disponibles los valores siguientes:
    COPY_TICKS_INFO    = 1,       // ticks llamados por los cambios de Bid y/o Ask
    COPY_TICKS_TRADE   = 2,       // ticks llamados por los cambios de Last y Volume
    COPY_TICKS_ALL     = 3,       // todos los ticks en en los que hay cambios
    COPY_TICKS_TIME_MS = 1<<8,    // tiempo en milisegundos
    COPY_TICKS_BID     = 1<<9,    // precio Bid
    COPY_TICKS_ASK     = 1<<10,   // precio Ask
    COPY_TICKS_LAST    = 1<<11,   // precio Last
    COPY_TICKS_VOLUME  = 1<<12,   // volumen
    COPY_TICKS_FLAGS   = 1<<13,   // banderas de tick
    Al seleccionar varios tipos de datos (solo disponible para matrices), el orden de las filas de la matriz se corresponderá con el orden de los valores de la enumeración.

  2. Ampliados los métodos matrix::Assign y vector::Assign.

    Ahora se puede asignar a la matriz un array o vector unidimensional:
    bool matrix::Assign(const vector &vec);
    Obtendremos como resultado una matriz de una línea.

    Ahora también se puede asignar una matriz a un vector (se realizará el suavizado de la matriz):
    bool vector::Assign(const matrix &mat);
  3. Añadidos los métodos Swap para vectores y matrices.
    bool vector::Swap(vector &vec);
    bool vector::Swap(matrix &vec);
    bool vector::Swap(double &arr[]);
    bool matrix::Swap(vector &vec);
    bool matrix::Swap(matrix &vec);
    bool matrix::Swap(double &arr[]);
    Cada array, vector o matriz se refiere a un búfer de memoria que contiene elementos de ese objeto. El método Swap realmente intercambia los punteros a estos búferes sin escribir los elementos en la memoria. Así que una matriz sigue siendo una matriz, y un vector un vector. Al intercambiar una matriz y un vector se obtiene una matriz de una línea con elementos vectoriales y un vector con elementos matriciales en representación plana (puede consultar el método Flat).
    //+------------------------------------------------------------------+
    //| Script program start function                                    |
    //+------------------------------------------------------------------+
    void OnStart()
     {
    //---
      matrix a= {{1, 2, 3}, {4, 5, 6}};
      Print("a before Swap: \n", a);
      matrix b= {{5, 10, 15, 20}, {25, 30, 35, 40}, {45, 50, 55, 60}};
      Print("b before Swap: \n", b);  
    //--- intercambiamos de sitio los punteros por las matrices
      a.Swap(b);
      Print("a after Swap: \n", a);
      Print("b after Swap: \n", b);
      /*
      a before Swap:
      [[1,2,3]
      [4,5,6]]
      b before Swap:
      [[5,10,15,20]
      [25,30,35,40]
      [45,50,55,60]]
      
      a after Swap:
      [[5,10,15,20]
      [25,30,35,40]
      [45,50,55,60]]
      b after Swap:
      [[1,2,3]
      [4,5,6]]
      */
      vector v=vector::Full(10, 7);
      Print("v before Swap: \n", v);
      Print("b before Swap: \n", b);
      v.Swap(b);
      Print("v after Swap: \n", v);
      Print("b after Swap: \n", b);
      /*
      v before Swap:
      [7,7,7,7,7,7,7,7,7,7]
      b before Swap:
      [[1,2,3]
      [4,5,6]]
      
      v after Swap:
      [1,2,3,4,5,6]
      b after Swap:
      [[7,7,7,7,7,7,7,7,7,7]]
      */
     }
    El método Swap también permite trabajar con arrays dinámicos (no se puede transmitir un array de tamaño fijo como parámetro). En este caso, el array puede ser de cualquier dimensión, pero de un tamaño consistente. Esto significa que el tamaño total de la matriz o del vector deberá ser un múltiplo de la dimensionalidad cero de un array. La dimensionalidad cero de un array es el número de elementos que contiene el primer índice del array. Por ejemplo, para un array dinámico tridimensional double array[][2][3], la dimensionalidad cero será el producto de los tamaños de la segunda y tercera dimensión, es decir, 2x3=6. Por lo tanto, un array de este tipo solo podrá utilizarse en un método Swap con matrices y vectores cuyo tamaño total sea un múltiplo de 6: 6, 12, 18, 24, etc.

    Vamos a mostrar esto con un ejemplo:
    //+------------------------------------------------------------------+
    //| Script program start function                                    |
    //+------------------------------------------------------------------+
    void OnStart()
     {
    //--- rellenamos la matriz 1x10 con el valor 7.0
      matrix m= matrix::Full(1, 10, 7.0);
      Print("matrix before Swap:\n", m);
    //--- intentamos realizar el intercambio entre la matriz y el array
      double array_small[2][5]= {{1, 2, 3, 4, 5}, {6, 7, 8, 9, 10}};
      Print("array_small before Swap:");
      ArrayPrint(array_small);
      if(m.Swap(array_small))
       {
        Print("array_small after Swap:");
        ArrayPrint(array_small);
        Print("matrix after Swap: \n", m);
       }
      else // el tamaño de la matriz no es múltiplo del tamaño de la primera dimensión del array
       {
        Print("m.Swap(array_small) failed. Error ", GetLastError());
       }
      /*
      matrix before Swap:
      [[7,7,7,7,7,7,7,7,7,7]]
      array_small before Swap:
               [,0]     [,1]     [,2]     [,3]     [,4]
      [0,]  1.00000  2.00000  3.00000  4.00000  5.00000
      [1,]  6.00000  7.00000  8.00000  9.00000 10.00000
      m.Swap(array_small) failed. Error 4006
      */
    //--- tomamos una matriz mayor e intentamos realizar el intercambio de nuevo
      double array_static[3][10]= {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
         {2, 4, 6, 8, 10, 12, 14, 16, 18, 20},
         {3, 6, 9, 12, 15, 18, 21, 24, 27, 30}
       };
      Print("array_static before Swap:");
      ArrayPrint(array_static);
      if(m.Swap(array_static))
       {
        Print("array_static after Swap:");
        ArrayPrint(array_static);
        Print("matrix after Swap: \n", m);
       }
      else // no se puede utilizar un array dinámico para el intercambio con una matriz
       {
        Print("m.Swap(array_static) failed. Error ", GetLastError());
       }
      /*
      array_static before Swap:
             [,0]     [,1]     [,2]     [,3]     [,4]     [,5]     [,6]     [,7]     [,8]     [,9]
      [0,]  1.00000  2.00000  3.00000  4.00000  5.00000  6.00000  7.00000  8.00000  9.00000 10.00000
      [1,]  2.00000  4.00000  6.00000  8.00000 10.00000 12.00000 14.00000 16.00000 18.00000 20.00000
      [2,]  3.00000  6.00000  9.00000 12.00000 15.00000 18.00000 21.00000 24.00000 27.00000 30.00000
      m.Swap(array_static) failed. Error 4006
      */
    //--- un nuevo intento de de intercambiar el array y la matriz
      double array_dynamic[][10];    // array dinámico
      ArrayResize(array_dynamic, 3); // indicamos el tamaño de la primera dimensión
      ArrayCopy(array_dynamic, array_static);
    //--- ahora utilizaremos un array dinámico para el intercambio
      if(m.Swap(array_dynamic))
       {
        Print("array_dynamic after Swap:");
        ArrayPrint(array_dynamic);
        Print("matrix after Swap: \n", m);
       }
      else //  no hay error
       {
        Print("m.Swap(array_dynamic) failed. Error ", GetLastError());
       }
      /*
      array_dynamic after Swap:
            [,0]    [,1]    [,2]    [,3]    [,4]    [,5]    [,6]    [,7]    [,8]    [,9]
      [0,] 7.00000 7.00000 7.00000 7.00000 7.00000 7.00000 7.00000 7.00000 7.00000 7.00000
      matrix after Swap:
      [[1,2,3,4,5,6,7,8,9,10,2,4,6,8,10,12,14,16,18,20,3,6,9,12,15,18,21,24,27,30]]
      */
     }
  4. Añadidos los métodos LossGradient para vectores y matrices. Este método calcula un vector o matriz de derivadas parciales de la función de pérdida con respecto a los valores predichos. En álgebra lineal, dicho vector se denomina gradiente y se usa en el aprendizaje automático.
    vector vector::LossGradient(const vector &expected,ENUM_LOSS_FUNCTION loss) const;
    matrix matrix::LossGradient(const matrix &expected,ENUM_LOSS_FUNCTION loss) const;
  5. Habilitado el uso de FOREIGN KEYS en SQLite, lo cual nos permitirá crear relaciones entre tablas en solicitudes SQL.   Ejemplo:
    CREATE TABLE artist(
      artistid    INTEGER PRIMARY KEY, 
      artistname  TEXT
    );
    
    CREATE TABLE track(
      trackid     INTEGER, 
      trackname   TEXT, 
      trackartist INTEGER,
      FOREIGN KEY(trackartist) REFERENCES artist(artistid)
    );

  6. Corregida la selección del método de clase requerido dependiendo de la consistencia del método y el objeto.

MetaEditor

  1. Aumentada la longitud de comentario admitida para las confirmaciones en el repositorio MQL5 Storage.  Los comentarios detallados al enviar cambios al repositorio se consideran de buenos modales al trabajar en grandes proyectos, pero la longitud de tales mensajes antes estaba limitada a 128 caracteres. El límite ahora se ha establecido en 260 caracteres.

MetaTester

  1. Aumentada la sensibilidad en el interruptor de velocidad de simulación en el modo visual.
Correcciones de crash logs.