English Русский 中文 Deutsch 日本語 Português
Interacción entre MetaTrader 4 y MATLAB Engine (Máquina virtual MATLAB)

Interacción entre MetaTrader 4 y MATLAB Engine (Máquina virtual MATLAB)

MetaTrader 4Ejemplos | 4 mayo 2016, 17:31
1 050 0
Andrey Emelyanov
Andrey Emelyanov

Introducción

MetaTrader 4 y el paquete matemático de MATLAB se han vuelto muy populares entre los usuarios gracias a sus características positivas, como la "flexibilidad" en la creación de sistemas complejo de cálculo. Hay tres maneras principales de conectar MATLAB con las aplicaciones externas, pero sólo se recomienda una de ellas: el uso del escritorio virtual MATLAB Engine. Este método garantiza la compatibilidad completa con todo el paquete MATLAB. Muchos programadores lo evitan por las siguientes razones:

  • Muchos usuarios creen que es lento. Eso es cierto, si se compara con la llamada directa a la función desde las librerías DLL de MATLAB: El retraso principal ocurre al principio del funcionamiento, cuando se llama a la máquina virtual por la llamada de numerosas librerías que se suben al espacio virtual del proceso de llamadas (en nuestro caso, MetaTrader 4).
  • Transferibilidad del proyecto. Es cierto, cuando se transfiere un proyecto a otro ordenador, también hay que transferir todas las librerías MATLAB DLL, aunque igual que cuando se utiliza una llamada directa, para saber las "relaciones" de las últimas, ¡empieza una cola!
  • Conocimiento obligatorio de C++ o Fortan. Bueno, si conoce MQL4, puede aprender fácilmente C++ y viceversa,

Por qué recomiendo este método:

  1. Este es la versión del método MATLAB de conexión con programas externos más fiable e independiente. Puede cambiar la versión de MATLAB y los indicadores y Asesores Expertos no se darán cuenta. Esta es la ventaja más importante.
  2. Tiene un método de desarrollo relativamente rápido. No necesita depuración, y no tendrá dificultades para escribir en el envase de DLL.
  3. "Escritorio común" para varios indicadores y/o Asesores Expertos. Creo que este método es útil cuando se necesita tomar una decisión basada en los datos de varios indicadores o en la implementación de un trade piramidal.

Este artículo describe la manera de conectar MetaTrader 4 y MATLAB ver. 7.4.0 (R2007a) a través del "envase-DDL" escrito en Borland C++ Builder 6. Los programadores que prefieren los productos de Microsoft tendrán que adaptar los ejemplos a su compilador (buena suerte en este tema).

I. Establecer una tarea:

Antes que nada, hay que definir desde dónde empezar el proyecto. Vamos a dividir el proceso de desarrollo en tres partes:

  1. Desarrollo de la función ; en MATLAB que implementa el cálculo de un indicador/AE.
  2. Desarrollo del "envase-DLL" para conectar MATLAB y MetaTrader 4.
  3. Desarrollo del programa MQL.

II. Desarrollo de la función M

Este es, probablemente, el proceso más interesante y largo, e incluye la sigues acciones:

1. Preexportación de datos de MetaTrader 4 a MATLAB.

Las figuras muestran el proceso de la exportación manual de datos a MATLAB. Cuando termine la exportación, se crearán las variables en el escritorio de MATLAB.

2. Búsqueda de las fórmulas correctas, rango de parámetros de fórmula, etc.

Este proceso es creativo y muy importante, pero el desarrollo del algoritmo matemático de un indicador y/o un Asesor Experto no es el tema de este artículo. Se puede encontrar información prácticamente en cualquier artículo sobre MATLAB.

3. Creación de la función M en MATLAB.

Un programador que conozca C++ y/o MQL4 no tendrá ninguna dificultad creando la función; es más, todas las variables tiene el mismo tipo de datos: "matrix". Es decir, no es importante definir claramente una variable como una gama o una gama multidimensional: el lenguaje lo hará por sí mismo. Y no creo que el proceso de selección de datos sea importante. Yo uso siempre mxREAL. Bueno, puede que se utilice más memoria, pero no hay ninguna confusión en ese caso. Puede encontrar más detalles en las referencias 1 y 2. En el ejemplo, se implementa el filtro de frecuencias altas.

III. Desarrollo del "envase DLL"

Vamos a hablar de este aparto con más detalles, porque es tan ESENCIAL como el respirar. Cada librería DLL de vinculación tardía tiene que tener las siguientes condiciones:

  • Tiene que tener funciones internas para recopilar "desperdicios" y limpieza de memoria después del funcionamiento.
  • Tiene que ser multihilo, es decir, que aguante el funcionamiento de más de un hilo al mismo tiempo.
  • Tiene que estar ubicada en directorios concretos, vea más adelante: ubicación de archivos de previsión.

Las principales funciones externas del "envase DLL" son la interfaz API de MATLAB Engine y una función de la librería estándar de entrada/salida de C++. La interfaz API de MATLAB Engine es simple y compacta; sólo tiene 8 funciones:

Engine *pEng = engOpen(NULL): función que llama al escritorio de MATLAB, el parámetro es siempre NULL, devuelve el puntero al descriptor del escritorio, necesita otras funciones para funcionar, la variable se hace global.

nt exitCode = engClose(Engine *pEng): función que cierra el escritorio, el puntero pEng al descriptor del escritorio, devuelve un valor que se considera poco importante, porque esta a esta función se le llama al cierre del DLL y no es importante, devuelve el número de "usuarios" del escritorio MATLAB.

mxArray *mxVector = mxCreateDoubleMatrix(int m, int n, int ComplexFlag): la función crea un matrix para el escritorio de MATLAB, devuelve el puntero a un matrix variable. Es necesaria para la creación de una variable compatible con MATLAB. Las gamas normales de datos y/o los datos de tipos simples no se pueden enviar a MATLAB.

mxArray *mxVector: puntero a matrix variable:

int m: número de filas;

int n: número de columnas;

ComplexFlag: número de tipo complejo, siempre mxREAL para el funcionamiento correcto con MetaTrader 4.

void = mxDestroyArray(mxArray *mxVector): la función borra la matrix de MATLAB, que se necesita para limpiar la memoria. Borre siempre los datos cuando ya no necesite más, sino habrá problemas con la memoria o con la "superposición" de los resultados.

mxArray *mxVector: puntero a matrix variable:

int = engPutVariable( Engine *pEng, char *Name, mxArray *mxVector): función que envía una variable al escritorio. Las variables del tipo mxArray no sólo tienen que crearse, sino también enviarse a MATLAB.

Engine *pEng: puntero al "descriptor" del escritorio.

char *Name: nombre de a variable en el escritorio de MATLAB, tipo: char;

mxArray *mxVector: puntero a matrix variable:

mxArray *mxVector = engGetVariable(Engine *pEng, char *Name): función de la variable que se recibe del escritorio, la función opuesta más la anterior. Se pueden recibir las variables de tipo mxArray.

mxArray *mxVector: puntero a matrix variable:

Engine *pEng: puntero al "descriptor" del escritorio.

char *Name: nombre de a variable en el escritorio de MATLAB, tipo: char;

double *p = mxGetPr(mxArray *mxVector): la función recibe el puntero a la gama de datos; se utiliza para copiar los datos junto a la memoria(...). Utilice esta función cuando reciba/escriba una variable del tipo mxARray, para extraer/pegar una variable de tipo simple (int, double...).

double *p: puntero a la gama de doble tipo;

mxArray *mxVector: puntero a matrix variable:

nt = engEvalString(Engine *pEng, char *Command): la función envía una orden al escritorio. La orden en la línea Command se ejecutará a través del escritorio MATLAB.

Engine *pEng: puntero al "descriptor" del escritorio.

char *Command: orden para la línea MATLAB del tipo char.

Sólo hay una función para trabajar con la memoria:

void *pIn = memcpy (void *pIn, void *pOut, int nSizeByte): la función copia (clona) una variable (gama) pOut en la variable pln del tamaño de byte nSizeByte.

ATENCIÓN: Cuidado con la dimensionalidad de la gama. Tienen que ser igual, o la gama pln tiene que ser más grande que pOut.

Requisitos para exportar las funciones del "envase DLL"

Para que MetaTrader 4 pueda utilizar MATLAB, deben escribirse transmisores de funciones. Vamos a revisar los requisitos para prever dichas funciones. Cualquier función que se llame desde MetaTrader 4 tiene que ser __sdtcall, es decir, que los parámetros se transmiten desde una pila, y la función limpia esa pila. Así es cómo se declara la función:

extern "C" __declspec(dllexport) <variable_type> __stdcall Funcion(<type> <name>);

extern "C" __declspec(dllexport): informa al compilador C++ que la función es externa, está escrita en una tabla de exportación.

<variable_type>: un tipo de retorno de una variable; puede ser: inválida, bool, int, doble, las de tipo compuesto y tipo punteros no se pueden transmitir; ver más;

__stdcall: acuerdo en los parámetros de transmisión y vuelta de los parámetros a la función.

Función: nombre de la función;

<type> <name>: tipo y nombre de la variable de entrada; el número máximo de variables: 64.

Aquí está el prototipo de definición de la función, también prestando atención a __stdcall

bool __stdcall Funcion (<type> <name>)

{

//……

}

Además de esto, debe crearse un archivo con la extensión def. Normalmente es un archivo de texto que describe el nombre de la librería y los nombres de las funciones de exportación. Si este archivo no existe, el archivo "ideará" sus propios nombres de funciones distorsionadas que complicará el uso de DLL. Aquí tiene el archivo de ejemplo:

LIBRARY NameDll

EXPORTS

NameFunctionA

NameFunctionB

LIBRARY: palabra accesorio, puntero al nombre DLL.

EXPORTS: para accesorio que dice que se enumerarán abajo los nombres de la función.

NameFunctionA, NameFunctionB: nombres de las funciones DLL.

Pero MQL impone algunas restricciones: Como este lenguaje no tiene punteros, no tiene memoria dinámica, por lo que las gamas, estructuras, etc. no se pueden pasar desde la librería DLL. Pero en MetaTrader se pueden escribir en gamas pasadas por una función por referencia. El resultado se puede escribir en una gama creada por MetaTRader, el puntero del DLL que ha recibido. Pero la gama tiene que ser de una dimensionalidad concreta y no puede haber una línea de indicador (esta restricción está conectada probablemente con la configuración concreta de la memoria en MetaTrader 4).

Ahora, sabiendo cómo escribir y a qué función llamar, vamos a ver un algoritmo típico del "envase-DLL".

1. Iniciar MATLAB Engine utilizando la función engOpen() durante la primera llamada de DLL.

2. Recoger los datos de MetaTrader y enviarlos a la función DLL;

2.1. Crear variables con la función mxCreateDoubleMatrix();

2.2. Copiar datos en la variable mxVector, funciones memory() y mxGetPr();

2.3. Pasar las variables al escritorio MATLAB, función engPutVariable();

2.4. Pasar la fórmula/código al escritorio MATLAB, función engEvalString();

2.5. Recibir respuesta del escritorio MATLAB, función engGetVariable();

2.6. Devolver valores a MetaTrader, funciones memory() y mxGetPr();

3. Cerrar MATLAB utilizando la función engClose(), borrar todas las variables mxDestroyArray() cuando mientras se carga DLL desde el área de dirección del proceso MetaTrader.

Ahora vamos a crear el esqueleto del "envase-DLL".

/*---------------------------------------------------------------------------
** Libraries + *.lib + *.def:
** libeng.lib** libmx.lib
** libmex.lib** project_name.def
*/
#include <windows.h>#include <memory.h>#include "engine.h"
//---------------------------------------------------------------------------
extern "C" __declspec(dllexport)<variable_type>__stdcall Funcion(<type><name>);
//---------------------------------------------------------------------------
int WINAPI DllEntryPoint(HINSTANCE hinst,unsigned long reason,void *lpReserved)
  {
   /*    
** reason for DLL call    
*/
   switch(reason)
     {
      case DLL_PROCESS_ATTACH:
         /*            
** DLL uploaded into the address space of the process            
*/
         break;
      case DLL_PROCESS_DETACH:
         /*            
**DLL loaded from the address space of the process            
*/
         break;
     }
   return TRUE;
  }
//---------------------------------------------------------------------------
bool __stdcall Funcion(<type><name>)
  {
   ……
  }
//---------------------------------------------------------------------------

Montaje del proyecto

La imagen de abajo muestra cómo se añaden las librerías y los archivos *.def en el proyecto:

Aquí está la lista de los archivos necesarios para el proyecto de "envase-DLL":

  1. libeng.lib: ubicado en: \Program Files\MATLAB\R2007a\extern\lib\win32\borland\
  2. libmx.lib: ubicado en: \Program Files\MATLAB\R2007a\extern\lib\win32\borland\
  3. libmex.lib: ubicado en: \Program Files\MATLAB\R2007a\extern\lib\win32\borland\
  4. имя_проекта.def: este archivo tiene que crearse en una libreta como se describe arriba.

El archivo engine.h debe copiarse desde \Program Files\MATLAB\R2007a\extern\\include en la carpeta \Program Files\Borland\CBuilder6\Include: por lo que no tiene que indicar a ruta al compilador cada vez.

Atención: ¡Estas instrucciones son para montar el proyecto sólo en Borland C++ Builder 6!

IV. Desarrollar un programa MQL4

Veremos las preguntas conectadas sólo con la declaración de las funciones del "envase-DLL" y pase de los parámetros. Por lo que, para declarar una función en el lenguaje de construcción de abajo, se necesita:

#import "HighPass.dll"

void ViewAnsFilter();

bool TestDllFilter();

bool AdaptiveHighFilter(double& nInVector[], int nSizeVector, double nSizeWind, double dAmplit);

void MakeBuffFilter(int nSize);

void DestrBuffFilter();

#import

en el que:

#import "HighPass.dll": palabra clave y nombre de la librería DLL;

void MakeBuffFilter(int nSize);: nombre de la función, tipo de valor a devolver, nombre y tipo de un valor pasado.

NB ! "[]" se utiliza cuando se pasan gamas, el carácter & es necesario, si dll escribe una respuesta en esta gama de datos! No hay otras formas de pasar gamas desde programas externos en MQL 4. La gama que hay que pasar tiene que tener una dimensionalidad concreta y no puede ser una gama de indicador.

V. Ubicación de los archivos

Después de la construcción del proyecto, todos los archivos del proyecto tienen que colocarse correctamente:

*.dll and *.m: archivos de librería y funciones m en el catálogo \Program Files\MetaTrader\experts\libraries;

*.mql se coloca en su lugar habitual. es decir, si es un indicador, en la carpeta "indicadores"; si es un AE, en la carpeta "experts"; si es un script, en la carpeta "scripts".

Atención: Cuando se inicia un indicador o un Asesor Experto, puede aparecer una advertencia de servidor ocupado:

en ese caso, espere 5-10 segundos hasta que aparezca la consola Matlab en la barra de tareas y haga clic en "Repetir".

P.D. Tengo un cuaderno con 512 RAM, Celeron M 2100; No hubo ningún retraso en el funcionamiento del filtro, número de gráficos: 5, con el búfer total 500 x 8 x 5 = 20 000 bye. ¡La elección es suya! Yo ya lo he hecho. Si hay algún retraso, se puede implementar fácilmente un sistema de cálculo distribuido; es decir, se pueden iniciar varios escritorios en diferentes ordenadores conectados a una red local.

Lista de referencias

  1. Built-in MATLAB Help.
  2. "Matlab 5.х Calculations, Visualization, Programing" N.N. Martynov.
  3. "C++ Builder 6. Reference Manual" A.Y. Arkhangelski.
  4. Built-in MQL4 Help.

Conclusión

En este artículo hemos hablado de las bases del "envase DLL" desarrollo de vinculación de MetaTrader 4 con el paquete matemático de MATLAB. No se ha hablado de la cuestión de proporcionar el funcionamiento de varios indicadores y/o Asesores Expertos: se hablará de ello en el siguiente artículo. El archivo adjunto contiene MACD mejorado por el uso del filtro de alta frecuencia.

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

Archivos adjuntos |
highpas.rar (10.19 KB)
highpasFull.zip (355.1 KB)

Otros artículos del autor

Alerta y comentario para indicadores externos. Alerta y comentario para indicadores externos.
En un trabajo práctico, un trader puede encontrarse con la siguiente situación: es necesario conseguir una "alerta" o un mensaje de texto en una pantalla (en una ventana de gráfico) que indique de la aparición de una señal de un indicador. El artículo contiene un ejemplo de muestra de información sobre los objetos gráficos creados por un indicador externo.
Canales. Modelos avanzados. Ondas Wolfe Canales. Modelos avanzados. Ondas Wolfe
El artículo describe las reglas de fabricación de patrones de las Ondas Wolfe. Aquí encontrará los detalles de construcción y reglas para una fabricación precisa, lo que ayuda a encontrar las formaciones correctas de las ondas de forma rápida y correcta.
Interfaces gráficas V: Barra de desplazamiento vertical y horizontal (Capítulo 1) Interfaces gráficas V: Barra de desplazamiento vertical y horizontal (Capítulo 1)
Seguimos analizando el proceso de desarrollo de la librería para la creación de las interfaces gráficas en el entorno de los terminales de trading MetaTrader. En el primer capítulo de la quinta parte de la serie vamos a desarrollar las clases para la creación de los controles como las barras de desplazamiento verticales y horizontales.
Promediación efectiva de algoritmos con retraso mínimo: Uso en indicadores y en Asesores Expertos Promediación efectiva de algoritmos con retraso mínimo: Uso en indicadores y en Asesores Expertos
Este artículo describe las funciones de promediación personalizadas de alta calidad desarrolladas por el autor: JJMASeries(), JurXSeries(), JLiteSeries(), ParMASeries(), LRMASeries(), T3Series(). El autor considera la sustitución en caliente de estas funciones en los indicadores utilizando la llamada de la función SmoothXSeries().