Creación de Asesores Expertos de red neuronal mediante MQL5 Wizard y el generador Hlaiman de Asesores Expertos

Ivan Negreshniy | 7 mayo, 2014

Introducción

Casi todos los traders saben que existen las redes neuronales. Pero para la mayoría de ellos sigue siendo una caja negra, siendo lo único que se sabe acerca de las redes neuronales su capacidad de reconocer patrones, producir búsqueda asociativa de soluciones y aprender, así como el hecho de que pueden ser efectivas para predecir el comportamiento del mercado y del trading automatizado. Muchas fuentes de información que se centran en la aplicación de redes neuronales, comentan a menudo su dificultad, resaltando el hecho de que hay que dedicar mucho tiempo y esfuerzo a aprender bien este tema y poder utilizar las redes neuronales en el futuro.

ُEl objetivo de este artículo es desmentir todos estos argumentos y demostrar que los métodos avanzados de automatización permiten a los traders tener un comienzo fácil con las redes neuronales y evitar el largo proceso de aprendizaje. No hay nada difícil en conseguir su propia experiencia con las redes neuronales. Es ciertamente más fácil que el análisis técnico.

Teniendo esto en cuenta, vamos a describir un método de generación automática de Asesores Expertos de redes neuronales para MetaTrader 5 usando MQL5 Wizard y el generador Hlaiman de Asesores Expertos.

La elección de las herramientas para resolver la tarea en cuestión está lejos de ser aleatoria:

  1. MQL5 Wizard es un mecanismo eficiente y el más rápido de generación automática de código MQL5 hasta la fecha y que le permite modificar la escala del código generado usando módulos adicionales.
  2. El generador Hlaiman de Asesores Expertos es un motor neuronal de la red con un mecanismo flexible de integración objetiva, programable directamente en el código MQL5 de un Asesor Experto.

Se ha añadido la abreviatura "EA" intencionalmente al nombre del Asesor como las propiedades similares a las humanas asociadas con el reconocimiento y el aprendizaje que son predominantes en un Asesor Experto de red neuronal, a diferencia de otros casos donde el uso de "EA" en un nombre es a menudo engañoso y no refleja la verdadera naturaleza de las cosas.


Descripción General

Debido al motivo resumido en el objetivo del artículo, no encontrará aquí ninguna información teórica, clasificaciones y estructuras de datos neuronales de redes o investigación relacionada con mercados financieros. Esta información está disponible en otros recursos. En este artículo, nos limitaremos deliberadamente al concepto de una red neuronal como una caja negra capaz realizar un pensamiento asociativo y predecir entradas de mercado basadas en el reconocimiento de patrones de gráficos de precio. Por la misma razón, utilizaremos la noción más sencilla del patrón que es una sucesión continua de barras en un gráfico de trading que precede a un movimiento provechoso del precio.

Unas pocas palabras acerca de las herramientas de resolución de problemas. A diferencia de Hlaiman, MQL5 Wizard ha sido a menudo el tema de varios artículos y documentación y no necesita traducción al igual que MetaTrader 5. El proyecto socialmente orientado de Hlaiman está pensado para el desarrollo y la promoción del software multiuso en forma de plugins, con el Generador de Asesores Expertos que es uno de ellos. Como ya se ha mencionado, el generador de Asesores Expertos representa un motor neuronal de la red con el mecanismo de integración.

El generador Hlaiman de Asesores Expertos incluye <hlaim.exe> - una capa que representa una aplicación de Windows GUI con interfaz multi-documento y programas adicionales en forma de bibliotecas de componentes que se pueden cargar dinámicamente. El sistema proporciona una gran variedad de ajustes manuales y algorítmicos y métodos de control de componentes que pueden ser ambos estándar y se pueden cargar como parte de los plugins. En la trayectoria del funcionamiento del sistema, puede crear jerarquías complejas de objetos y tener un control flexible sobre sus métodos y propiedades, utilizando Object Inspector y las herramientas de software de automatización, por ejemplo scripts.

La integración del generador Hlaiman de Asesores Expertos con MQL5 implica el intérprete de script de Object Pascal, mientras el código fuente pasa por canales con nombre. Se usa un perceptron multicapa (MLP) como principal componente neuronal de la red.

El generador Hlaiman del Asesor Experto está integrado con MQL5 Wizard usando un módulo de la señal de la biblioteca - SignalHNN.mqh. Una vez generado automáticamente, el Asesor Experto puede entonces aprender a operar con cualquier cantidad de instrumentos y periodos de tiempo. En el terminal МetaТrader 5, se pueden dibujar las flechas que indican señales en el gráfico del precio utilizando manualmente los objetos gráficos para las flechas o utilizando automáticamente el script TeachHNN.mq5 que inicia al mismo tiempo el proceso de aprendizaje del Asesor Experto.

Con esto se da por finalizada la descripción teórica. Ahora continuamos con la parte práctica que está dividida en dos secciones - Principios de Funcionamiento y Ejecución.

La segunda sección está enfocada a programadores de software y se proporciona aquí principalmente en consideración a este sitio web. Es por lo tanto opcional, especialmente para traders con un pequeño o ningún interés en tener habilidades de programación pero están interesados en crear Asesores Expertos de red neuronal y valorar su eficiencia o la inutilidad en términos de trading.


Principios de Funcionamiento

En MQL5.community, probablemente sería innecesario mencionar que necesita el terminal MetaТrader 5 para continuar. Si no lo tiene, descárguelo e instálelo. También debe descargar e instalar la versión demo del generador Hlaiman de Asesores Expertos.

Inicie el terminal МetaТrader 5 y abra MetaEditor. Abra MQL5 Wizard. Puede hacerlo usando la opción "Nuevo" en la barra de herramientas o en el menú Archivo, así como utilizando la combinación de teclas "Ctrl + N" .

En la ventana de MQL5 Wizard, seleccione "Expert Advisor (generate)" y haga clic en "Siguiente".

Fig. 1. Creación de un Asesor Experto en MQL5 Wizard

Fig. 1. Creación de un Asesor Experto en MQL5 Wizard

Especifique la ubicación y el nombre del Asesor Experto, por ejemplo' "Experts\SampleHNN" y haga el clic en "Siguiente".

Fig. 2. Propiedades Generales del Asesor Experto

Fig. 2. Propiedades Generales del Asesor Experto

Haga clic en el botón "Añadir". Verá la ventana de "Parámetros del módulo de la señal" donde debe seleccionar "Signals of patterns Hlaiman Neural Network EA generator" de la lista del menú desplegable y hacer clic en "OK".

Fig. 3. Selección del módulo de señal de trading de la red neuronal del generador Hlaiman de Asesores Expertos

Fig. 3. Selección del módulo de señal de trading de la red neuronal del generador Hlaiman de Asesores Expertos

En caso de una implementación muy básica, puede hacer clic en "Siguiente" en todos los pasos restantes de MQL5 Wizard. Si fuera necesario, se puede mejorar el Asesor Experto seleccionando opciones adicionales.

Al terminar la creación del código, haga clic en "Compile" y cierre la ventana MetaEditor. El Asesor Experto aparecerá en el panel de navegación del terminal MetaTrader 5 en la sección "Asesores Expertos".

Fig. 4. El Asesor Experto SampleHNN

Fig. 4. El Asesor Experto SampleHNN

Antes de continuar entrenando al Asesor Experto creado, debemos abrir un gráfico con el símbolo y marco necesarios en el terminal. La aplicación del generador Hlaiman de Asesores Expertos debe estar activa y en funcionamiento.

Fig. 5. Preparación del aprendizaje de la red neuronal

Fig. 5. Preparación del aprendizaje de la red neuronal

Para entrenar al Asesor Experto, seleccione "TeachHNN" de la sección "Scripts" del panel de navegación del terminal y actívelo para el gráfico indicado.

Antes de hacer funcionar el script "TeachHNN", debe asegurarse de que tiene todos los ajustes adecuados. Tiene los parámetros siguientes:

Fig. 6. Los parámetros del script TeachHNN

Fig. 6. Los parámetros del script TeachHNN

Si todo está listo, haga clic en "Aceptar" (OK) para empezar el proceso de aprendizaje del Asesor Experto. Esto iniciará la generación automática de patrones gráficas para cada una de las señales disponibles en el gráfico.

La información relevante se muestra en la pestaña "Expertos" en el panel "Caja de Herramientas" del terminal, mientras los correspondientes objetos aparecen en la ventana del generador Hlaiman de Asesores Expertos .

Una vez terminada la generación de patrones, comienza el proceso de aprendizaje. Se muestra en la barra de aprendizaje que parece en la pantalla.

El aprendizaje del generador Hlaiman de Asesores Expertos

Fig. 7. Panel de progreso del aprendizaje

Espere hasta que el proceso se haya completado. El proceso de aprendizaje se puede finalizar antes de que haya terminado haciendo clic con el botón derecho en la barra de progreso del aprendizaje y seleccionando la opción apropiada en el menú del contexto.

Una vez terminado el proceso de aprendizaje y el funcionamiento del script, aparecerá el siguiente mensaje en la pestaña "Expertos", por ejemplo "Neural net create success!" (¡Red Neuronal creada con éxito!) "On 431 patterns" indica que el aprendizaje del Asesor Experto se completó con éxito utilizando 431 señales.

Estos mensajes indican cuantos patrones han participado en el proceso de aprendizaje y averiguan los números de esos patrones. La COMPRA y la VENTA, en particular, se determina utilizando los mensajes del tipo siguiente: "Sell signal detected at pattern #211" (detectada una señal de venta en el patrón #211).

Fig. 8. Los mensajes del script TeachHNN en el transcurso del aprendizaje

Fig. 8. Los mensajes del script TeachHNN en el transcurso del aprendizaje

Las razones por las que el proceso de aprendizaje del Asesor Experto puede comenzar con un error son estas:

  1. La aplicación Hlaiman no estaba en marcha antes del comienzo, tal y como se requiere. En este caso el mensaje de error será el siguiente "CSignalHNN::InitHNN: Error! initializing pipe server (possible reason: HLAIMAN APPLICATION IS NOT RUNNING!)".
  2. La ausencia de flechas que indican señales en el gráfico con la generación automática de señales desactivada (la variable SignalsCreate = false). En este caso el mensaje de error será el siguiente: "OnStart: error, orders arrow not found!" Si la generación automática de señales está habilitada (la variable SignalsCreate = true), se puede producir un error por la presencia de otros objetos gráficos en el gráfico, ya que las marcas personalizadas se supone que no deberían interferir con en el programa. Por lo tanto se recomienda abrir todos los gráficos por separado para el objetivo de la generación automática de señales.

Cuando el aprendizaje del Asesor Experto se ha completado, puede ver los resultados pertinentes cambiando a GUI Hlaiman y seleccionando los objetos apropiados y los paneles de visualización.

Fig. 9. Pestaña "Text" del programa Hlaiman

Fig. 9. Pestaña "Text" del programa Hlaiman


Fig. 10. Pestaña "Graph" del programa Hlaiman

Fig. 10. Pestaña "Graph" del programa Hlaiman

Después del aprendizaje con éxito del Asesor Experto en por lo menos un instrumento de trading, podemos continuar con las pruebas y/o la optimización.

Para hacer esto, seleccione el nombre del Asesor Experto entrenado, el símbolo, el periodo de tiempo, el intervalo y otros parámetros de prueba en el Probador de Estrategias. Ponga las variables externas, si fuera necesario, y haga funcionar la prueba.

Fig. 11. Ajustes del Asesor Experto SampleHNN para el backtesting

Fig. 11. Ajustes del Asesor Experto SampleHNN para el backtesting


Fig. 12. Las variables externas del Asesor Experto SampleHNN Expert se pueden modificar

Fig. 12. Las variables externas del Asesor Experto SampleHNN se pueden modificar

Abajo hay un ejemplo del informe de funcionamiento del Asesor Experto en el Probador de Estrategias. El Asesor Experto ha sido entrenado utilizando señales generadas automáticamente, con todos los parámetros externos del script de aprendizaje ajustados por defecto. El período de aprendizaje: 01.01.2010-01.07.2013, el instrumento: EURUSD H4.


Informe del Probador de Estrategias

Asesor Experto:SampleHNN
Símbolo: EURUSD
Período: H4 (2010.01.01-2013.07.12)
Divisa: USD
Depósito inicial: 10.000,00
Apalancamiento: 0,111111111
Backtesting
Calidad del historial: 100%
Barras: 5497
Beneficio neto: 9.159,58
Beneficio bruto: 29.735,97
Pérdida bruta: -20.576,39
Factor de beneficio: 1,45
Factor de recuperación: 12,81
AHPR: 1,0005 (0.05%)
GHPR: 1,0005 (0.05%)
Total de operaciones: 1417
Ofertas transacciones: 2246
Ticks: 60211228
Disminución absoluta de balance: 0,00
Disminución máxima de balance: 679,98 (3.81%)
Disminución relativa de balance: 4.00% (715,08)
Rentabilidad esperada: 6,46
Ratio de Sharpe: 0,16
Correlación de LR: 0,98
Error LR Estándar: 595,06
Operaciones a corto (% ganadas): 703 (56.61%)
Operaciones con beneficio (% del total): 793 (55.96%)
Operación con mayor beneficio: 53,00
Promedio de operaciones con beneficio: 37,50
Máximo de operaciones consecutivas rentables: 9 (450,38)
Máximo beneficio consecutivo: 450.38 (9)
Promedio de operaciones consecutivas rentables: 2
Símbolos: 1
Disminución absoluta de patrimonio: 6,60
Disminución máxima de patrimonio: 715,08 (4.00%)
Disminución relativa de patrimonio: 4,00% (715,08)
Nivel de Margen: 6929.24%
Cuenta-Z: -1,24 (78.50%)
Resultado OnTester: 0
Operaciones a largo (% ganadas): 714 (55.32%)
Operaciones con pérdidas (% del total): 624 (44.04%)
Operación con mayor pérdida: -53,30
Promedio de pérdidas por operación: -32,97
Pérdidas máximas consecutivas: 9 (-234,00)
Pérdida máxima consecutiva: -276.67 (7)
Promedio de pérdidas consecutivas: 2

Fig. 13. Los resultados del backtesting del asesor Experto SampleHNN

Fig. 13. Los resultados del backtesting del asesor Experto SampleHNN


Fig. 14. Las estadísticas de entrada al mercado del Asesor Experto SampleHNN

Fig. 14. Las estadísticas de entrada al mercado del Asesor Experto SampleHNN


Fig. 15. La correlación entre ganancia y MFE/MAE del Asesor Experto SampleHNN

Fig. 15. La correlación entre ganancia y MFE/MAE del Asesor Experto SampleHNN


Fig. 16. Las estadísticas de posición del tiempo de holding del Asesor Experto SampleHNN

Fig. 16. Las estadísticas de posición del tiempo de holding del Asesor Experto SampleHNN

La implementación

El principal componente de la implementación MQL5 es la clase CSignalHNN descrita en el módulo de la señal SignalHNN.mqh. La clase es heredada de la clase base CExpertSignal e incluye todos los campos necesarios de datos y métodos para la operación y la integración de Hlaiman, así como para trabajar con Asesores Expertos generados utilizando MQL5 Wizard.

La plantilla de la clase es así:

//+------------------------------------------------------------------+
//| Class CSignalHNN.                                                |
//| Purpose: Class of generator of trade signals based on            |
//|          the 'Hlaiman EA Generator Neural Net' indicator.        |
//| Is derived from the CExpertSignal class.                         |
//+------------------------------------------------------------------+
class CSignalHNN :public CExpertSignal
  {
protected:
   //--- variables
   int               m_hnn;                   // handle of HNN connect
   string            hnn_path;                // MT5 Terminal data path
   string            hnn_fil;                 // HNN file w neural net 
   string            hnn_nam;                 // Expert name
   string            hnn_sym;                 // Symbol name
   string            hnn_per;                 // Period name
   ENUM_TIMEFRAMES   hnn_period;              // Period timeframe
   int               hnn_index;               // Index ext multinet
   int               hnn_bar;                 // index of last bar
   int               hnn_in;                  // input layer 
   int               hnn_out;                 // output layer
   int               hnn_layers;              // layers count
   int               hnn_neurons;             // neurons count
   int               hnn_epoch;               // learn epoch
   double            hnn_signal;              // value of last signal
   double            pattern[];               // values of the pattern
   bool              hnn_norm;                // normalize pattern

public:
                     CSignalHNN(void);        // class constructor
                    ~CSignalHNN(void);        // class destructor
   //--- methods of setting adjustable parameters
   void              PatternBarsCount(int value) { hnn_in = value; ArrayResize(pattern, value + 1);  }
   void              LayersCount(int value)      { hnn_layers = value;  }
   void              NeuronsCount(int value)     { hnn_neurons = value;  }
   void              EpochCount(int value)       { hnn_epoch = value;  }
   void              Normalize(bool value)       { hnn_norm = value;  }
   //--- method of verification of settings
   virtual bool      ValidationSettings(void);
   //--- method of creating the indicator and timeseries
   virtual bool      InitIndicators(CIndicators *indicators);
   //--- methods of checking conditions of entering the market
   virtual double    Direction(void);

   bool              FillPattern(datetime tim = 0);      // prepare pattern
   bool              AddPattern(string name, int ptype);  // add new pattern
   bool              TeachHNN(void);                     // learn neural net
   bool              SaveFileHNN(void);                  // neural net file
   double            CalculateHNN(void);                 // calc neural signal

                                                        //protected:
   //--- method of initialization of the Hlaiman Application
   bool              InitHNN(bool openn);                // Hlaiman App Init
   void              FreeHNN(void)
     {                     // Hlaiman App Deinit
      if(m_hnn!=0 && m_hnn!=INVALID_HANDLE)
        {
         FileClose(m_hnn);
         m_hnn=0;
        }
     };
  };

Tras la creación de la instancia de la clase usando el constructor, este objeto puede trabajar en dos modos principales:

  1. Modo aprendizaje: este modo está asociado con la colección de patrones de mercado y el aprendizaje de la red neuronal.
  2. Modo Indicador: en este modo, se calcula la señal neuronal de la red utilizando el patrón actual.

Se identifica al llamar al modo de inicio InitHNN que utiliza el parámetro Booleano openn. El verdadero valor de este parámetro inicia la búsqueda y la apertura, así como la carga y el funcionamiento del archivo de datos de la red neuronal en el modo indicador (2). Este último se considera el modo de funcionamiento y se utiliza en el Asesor Experto para el trading.

A diferencia del modo de aprendizaje (1) que se inicia al llamar al método InitHNN con openn = false, el modo indicador es preparatorio para el Asesor Experto y se usa para el funcionamiento del script de aprendizaje.

El método de inicialización se lleva a cabo de la siguiente forma:

//+------------------------------------------------------------------+
//| Initialize HNN                                                   |
//+------------------------------------------------------------------+
bool CSignalHNN::InitHNN(bool openn)
  {
//--- initialize Hlaiman Application
   int num=0;
   ulong res=0;
   if(m_symbol!=NULL)
     {
      hnn_sym=m_symbol.Name();
      hnn_period=m_period;
        } else {
      hnn_sym=_Symbol;
      hnn_period=_Period;
     }
   hnn_per = string(PeriodSeconds(hnn_period) / 60);
   hnn_fil = hnn_nam + NAME_DELIM + hnn_sym + hnn_per + NAME_DELIM + string(hnn_index) + TYPE_NEURO;
   if(m_hnn== 0|| m_hnn == INVALID_HANDLE)
      m_hnn=FileOpen(HLAIMAN_PIPE,FILE_READ|FILE_WRITE|FILE_BIN);
   if(m_hnn!=0 && m_hnn!=INVALID_HANDLE)
     {
      string source,result="";
      if(openn==true)
        {
         result=CON_OPENN+CON_TRUE;
         if(!FileIsExist(hnn_fil,FILE_READ))
           {
            if(FileIsExist(hnn_fil,FILE_READ|FILE_COMMON))
               hnn_fil=TerminalInfoString(TERMINAL_COMMONDATA_PATH)+PATH_FILES+hnn_fil;
            else
              {
               //              hnn_fil = hnn_path + PATH_MQL5 + PATH_FILES + hnn_fil;
               hnn_fil=TerminalInfoString(TERMINAL_DATA_PATH)+PATH_MQL5+PATH_FILES+hnn_fil;
              }
           }
         else hnn_fil=TerminalInfoString(TERMINAL_DATA_PATH)+PATH_MQL5+PATH_FILES+hnn_fil;
           } else {
         result=CON_OPENN+CON_FALSE;
         hnn_fil=TerminalInfoString(TERMINAL_DATA_PATH)+PATH_MQL5+PATH_FILES+hnn_fil;
        }
      source="unit InitHNN; Interface "+result+" var libr, term, exp, sym: TObject;"
             " Implementation function main: integer;\n\r" // Line #1
             " begin"
             " Result := 0;"
             " libr := Open('mt45.dll');\n\r" // Line #2
             " if (libr <> nil) then"
             " begin"
             " term := Open('"+hnn_path+"');\n\r" // Line #3
             " if (term <> nil) then"
             " begin"
             " exp := term.ObjectOfName('"+hnn_nam+"');"
             " if (exp = nil) then exp := term.AddObject('TMT45Expert');\n\r" // Line #5
             " if (exp <> nil) then"
             " begin"
             " if (exp.Name <> '"+hnn_nam+"') then exp.Name := '"+hnn_nam+"';\n\r" // Line #6
             " sym := exp.ObjectOfName('"+hnn_sym+hnn_per+"');"
             " if (sym = nil) then sym := exp.AddObject('TMT45Symbol');"
             " if (sym <> nil) then"
             " begin"
             " sym.Log.Add('"+hnn_sym+hnn_per+"');\n\r"
             " if (sym.Name <> '"+hnn_sym+hnn_per+"') then sym.Name := '"+hnn_sym+hnn_per+"';"
             " if (sym.Period <> "+hnn_per+") then sym.Period := "+hnn_per+";"
             " if (openn = true) then"
             " begin"
             //                   " sym.Log.Add('" + hnn_fil + "');"
             " if (sym.Open('"+hnn_fil+"')) then Result := sym.TeachInput;\n\r" // ret input Line #8
             " end else"
             " begin"
             " sym.TeachInput := "+IntegerToString(hnn_in)+";"
             " sym.TeachOutput := "+IntegerToString(hnn_out)+";"
             " sym.TeachLayer := "+IntegerToString(hnn_layers)+";"
             " sym.TeachNeurons := "+IntegerToString(hnn_neurons)+";"
             " sym.TeachEpoch := "+IntegerToString(hnn_epoch)+";"
             " sym.FileName := '"+hnn_fil+"';"
             " Result := sym.TeachInput;\n\r" // ret input Line #9
             " end;"
             " end;"
             " end;"
             " end;"
             " end;"
             " end; end.";
      FileWriteString(m_hnn,source,StringLen(source));
      FileFlush(m_hnn);
      while(res<=0 && (MQL5InfoInteger(MQL5_TESTER) || num<WAIT_TIMES))
        {
         Sleep(SLEEP_TIM);
         res=FileSize(m_hnn);
         num++;
        }
      if(res>0)
        {
         result=FileReadString(m_hnn,int(res/2));
         res=StringToInteger(result);
         if(res<=RES_OK)
            printf(__FUNCTION__+": Error! Initialization data(possible reason: FILE NOT EXIST OR CORRUPTED "+hnn_fil);
         else
           {
            printf(__FUNCTION__+": Initialization successful! NEURAL PATTERN "+string(res));
            ArrayResize(pattern,int(res+1));
            return(true);
           }
        }
      else
         printf(__FUNCTION__+": Error! pipe server not responding(possible elimination: RESTART HLAIMAN APPLICATION)");
     }
   else
      printf(__FUNCTION__+": Error! initializing pipe server (possible reason: HLAIMAN APPLICATION IS NOT RUNNING!)");
//--- ok
   return(false);
  }

Como puede verse a partir del código, el primer paso de inicialización cubre un intento de abrir un canal para la conectividad con la aplicación Hlaiman. Si este intento falla (por ejemplo, cuando <hlaim.exe> no funciona), se lleva a cabo la salida con un estado negativo. En el segundo paso (después de terminar con éxito el primer paso y el modo indicador en funcionamiento), las carpetas locales y comunes del terminal se buscan para el nombre necesario del archivo con los datos de la red neuronal. El tercer paso se encarga de la preparación del código en ObjectPascal (Delfos) para la inicialización directamente en la aplicación Hlaiman.

El texto del código entonces se mueve a la cadena de origen. De beneficio para el formateo, se divide en subcadenas que utilizan "\n\r" y contienen invocaciones de las propiedades y métodos del objeto Hlaiman (ver comentarios). Como se define en el texto, el medio ambiente basado en objetos del plugin MetaTrader 5 Hlaiman representa la arquitectura del árbol, con el objeto del plugin bajo la raíz.

El objeto del terminal МetaТrader 5 está en el siguiente nivel seguido por Asesor Experto y objetos del símbolo. En el caso de la traducción y la ejecución con éxito del código fuente pasado a través de la canalización nombrada, el valor devuelto del Resultado contendrá el número de elementos del vector de entrada de la red neuronal. Como el código sugiere, este valor se usa para iniciar la matriz del patrón y la ejecución del método se completa con un estado positivo.

Los otros métodos clave de la clase CSignalHNN son CalculateHNN, AddPattern y TeachHNN. El primero devuelve el resultado del cálculo neuronal de la red en el modo de indicador. Los otros dos métodos se usan en el modo aprendizaje al reunir patrones e iniciar el proceso de aprendizaje de la red neuronal, respectivamente.

La implementación de estos métodos en <SignalHNN.mqh> es como sigue:

//+------------------------------------------------------------------+
//| Calculate HNN signal                                             |
//+------------------------------------------------------------------+
double CSignalHNN::CalculateHNN(void)
  {
   if(m_hnn==0 || m_hnn==INVALID_HANDLE) return(0.0);
   int num = 0;
   ulong siz = 0;
   double res=0.0;
   string source,result="";
   if(FillPattern(0)==true)
     {
      result=CON_START;
      for(int i=1; i<(ArraySize(pattern)-1); i++)
         result= result+DoubleToString(pattern[i])+CON_ADD;
      result = result + DoubleToString(pattern[ArraySize(pattern) - 1]) + CON_END;
      source = "unit CalcHNN; Interface " + result + " var i: integer; libr, term, exp, sym, lst: TObject;"
              " Implementation function main: double;\n\r" // Line #1
              " begin"
              " Result := 0.0;"
              " libr := Open('mt45.dll');\n\r" // Line #2
              " if (libr <> nil) then"
              " begin"
              " term := Open('"+hnn_path+"');\n\r" // Line #3
              " if (term <> nil) then"
              " begin"
              " exp := term.ObjectOfName('"+hnn_nam+"');\n\r" // Line #4
              " if (exp <> nil) then"
              " begin"
              " sym := exp.ObjectOfName('"+hnn_sym+hnn_per+"');\n\r" // Line #5
              " if (sym <> nil) then"
              " begin"
              " lst := TStringList.Create;"
              " if (lst <> nil) then"
              " begin"
              " lst.Text := cons;"
              " if (lst.Count >= sym.NetInputs.Count) then"
              " begin"
              " for i := 0 to sym.NetInputs.Count - 1 do"
              " begin"
              " sym.NetInputs.Objects[i].NetValue := StrToFloat(lst[i]);\n\r" // Line #6
              //                    " sym.Log.Add('Input ' + IntToStr(i) + ' = ' + lst[i]);"              
              " end;"
              " sym.Computed := true;"
              " Result := sym.NetOutputs.Objects[0].NetValue;\n\r" // ret input Line #7
              " end;"
              " lst.Free;"
              " end;"
              " end;"
              " end;"
              " end;"
              " end;"
              " end; end.";
      FileWriteString(m_hnn,source,StringLen(source));
      FileFlush(m_hnn);
      while(siz<=0 && (MQL5InfoInteger(MQL5_TESTER) || num<WAIT_TIMES))
        {
         Sleep(SLEEP_TIM);
         siz=FileSize(m_hnn);
         num++;
        }
      if(siz>0)
        {
         result=FileReadString(m_hnn,int(siz/2));
         res=StringToDouble(result);
        }
     } //else Print("fill pattern error!");
   return(res);
  }
//+------------------------------------------------------------------+
//| AddPattern                                                       |
//+------------------------------------------------------------------+
bool CSignalHNN::AddPattern(string name,int ptype)
  {
   int num=0;
   long res=0;
   ulong siz=0;
   string result,source,nam=name;
   if(m_hnn!=0 || m_hnn!=INVALID_HANDLE)
     {
      pattern[0]=ptype;
      result=CON_START;
      for(int i=0; i<(ArraySize(pattern)-1); i++)
         result= result+DoubleToString(pattern[i])+CON_ADD;
      result = result + DoubleToString(pattern[ArraySize(pattern) - 1]) + CON_END;
      source = "unit AddPatternHNN; Interface " + result + " Implementation function main: integer;"
              " var i: integer; out: double; onam: string;"
              " libr, term, exp, sym, ord, tck, lst: TObject;\n\r" // Line #1
              " begin"
              " Result := 0;"
              " libr := Open('mt45.dll');\n\r" // Line #2
              " if (libr <> nil) then"
              " begin"
              " term := Open('"+hnn_path+"');\n\r" // Line #3
              " if (term <> nil) then"
              " begin"
              " exp := term.ObjectOfName('"+hnn_nam+"');\n\r" // Line #4
              " if (exp <> nil) then"
              " begin"
              " sym := exp.ObjectOfName('"+hnn_sym+hnn_per+"');\n\r" // Line #5
              " if (sym <> nil) then"
              " begin"
              " lst := TStringList.Create;"
              " if (lst <> nil) then"
              " begin"
              " lst.Text := cons;"
              " if (lst.Count >= (sym.TeachInput + sym.TeachOutput)) then"
              " begin"
              " out := StrToFloat(lst[0]);"
              " if(out >= 0) then onam := 'BUY-"+nam+"'"
              " else onam := 'SELL-"+nam+"';"
              " ord := sym.ObjectOfName(onam);"
              " if (ord = nil) then ord := sym.AddObject('TMT45Order');\n\r" // Line #6                    
              " if (ord <> nil) then"
              " begin"
              " if (ord.Name <> onam) then ord.Name := onam;\n\r" // Line #7
              " if (out >= 0) then ord.OrderType := 0 else ord.OrderType := 1;"
              " if (ord.NetOutput <> out) then ord.NetOutput := out;\n\r" // Line #8
              " for i := 1 to sym.TeachInput do"
              " begin"
              " if(i <= ord.Count) then tck := ord.Items[i - 1] else"
              " tck := ord.AddObject('TMT45Tick');\n\r" // Line #10                    
              " if (tck <> nil) then"
              " begin"
              " tck.x := i;"
              " tck.y := StrToFloat(lst[i]);\n\r" // Line #11
              " end;"
              " end;"
              " end;"
              " Result := sym.Count;\n\r" // ret input Line #12
              " end;"
              " lst.Free;"
              " end;"
              " end;"
              " end;"
              " end;"
              " end;"
              " end; end.";
      FileWriteString(m_hnn,source,StringLen(source));
      FileFlush(m_hnn);
      while(siz<=0 && (MQL5InfoInteger(MQL5_TESTER) || num<WAIT_TIMES))
        {
         Sleep(SLEEP_TIM);
         siz=FileSize(m_hnn);
         num++;
        }
      if(siz>0)
        {
         result=FileReadString(m_hnn,int(siz/2));
         res=StringToInteger(result);
        }
     }
   return(res>0);
  }
//+------------------------------------------------------------------+
//| TeachHNN                                                         |
//+------------------------------------------------------------------+
bool CSignalHNN::TeachHNN(void)
  {
   int num=0;
   long res=0;
   ulong siz=0;
   string result,source;
   if(m_hnn!=0 || m_hnn!=INVALID_HANDLE)
     {
      source="unit TeachHNN; Interface const WAIT_TIM = 100; WAIT_CNT = 100;"
             "  var i: integer; libr, term, exp, sym: TObject;"
             " Implementation function main: integer;\n\r" // Line #1
             " begin"
             " Result := 0;"
             " libr := Open('mt45.dll');\n\r" // Line #2
             " if (libr <> nil) then"
             " begin"
             " term := Open('"+hnn_path+"');\n\r" // Line #3
             " if (term <> nil) then"
             " begin"
             " exp := term.ObjectOfName('"+hnn_nam+"');\n\r" // Line #4
             " if (exp <> nil) then"
             " begin"
             " sym := exp.ObjectOfName('"+hnn_sym+hnn_per+"');\n\r" // Line #5
             " if (sym <> nil) then"
             " begin"
             " if (sym.Teached) then sym.Teached := false;\n\r" // Line #6
             " sym.Teached := true;\n\r" // Line #7
             " Result := sym.Count;\n\r" // ret input Line #8
             " end;"
             " end;"
             " end;"
             " end;"
             " end; end.";
      FileWriteString(m_hnn,source,StringLen(source));
      FileFlush(m_hnn);
      while(siz<=0)
        {// && (MQL5InfoInteger(MQL5_TESTER) || num < WAIT_TIMES)) {
         Sleep(SLEEP_TIM);
         siz=FileSize(m_hnn);
         num++;
        }
      if(siz>0)
        {
         result=FileReadString(m_hnn,int(siz/2));
         res=StringToInteger(result);
        }
     }
   return(res>0);
  }

Como se puede ver en el código, el cuerpo del método consiste principalmente en las líneas de código fuente, cuyo texto está dispuesto de forma similar a los textos vistos anteriormente en la descripción del método InitHNN. La única diferencia es que la jerarquía del objeto base del plugin tiene dos niveles más para la representación del patrón; orden y punto. Además, el código contiene propiedades y métodos de objetos adicionales. Por ejemplo el comienzo del cálculo de redes neuronales se marca por la bandera "Computed" (calculada) del objeto del "símbolo", mientras la bandera "Teached" (enseñada) se utiliza cuando se inicia el proceso de aprendizaje.

El método CalculateHNN es también diferente de otros métodos en que el tipo del valor devuelto "principal" por la función en este caso es "doble". Este valor es la salida neuronal de la red; la señal, por lo que el nivel COMPRAR recae en el rango 0..1 y el nivel VENDER está en la gama 0..-1. Se usa esta señal por el Asesor Consejero para tomar decisiones con respecto a apertura o cierre de posiciones de trading y está controlado por el método "Direction". Este método realiza un nuevo cálculo en el caso de la nueva barra y devuelve su valor expresado en porcentaje.

//+------------------------------------------------------------------+
//| Check conditions for trading signals.                            |
//+------------------------------------------------------------------+
double CSignalHNN::Direction(void)
  {
   if( m_hnn == 0 || m_hnn == INVALID_HANDLE) return(EMPTY_VALUE);
//--- check new bar condition
   int cur_bar = Bars(hnn_sym, hnn_period);
   if (hnn_bar != cur_bar) {
//--- condition OK
      hnn_signal = CalculateHNN() * 100;
      hnn_bar = cur_bar;
   }
   return(hnn_signal);
  }

Para establecer el umbral de respuesta de la señal del Asesor Experto con respecto a las señales para la apertura y cierre de las posiciones de trading, puede utilizar las siguientes variables:

En la práctica, los niveles de señal dependen de la calidad del aprendizaje de las redes neuronales y la intensidad que, generalmente, se puede valorar visualmente mediante el control de la dinámica de disminución del error de cálculo que se muestra en el indicador en el transcurso del aprendizaje.


Conclusiones:

El generador Hlaiman de Asesores Expertos proporciona componentes y un entorno basado en objetos controlado y transparente para la integración con MQL5, por lo cual:

  1. La interfaz de MQL5 Wizard consigue una clase adicional basada en la señal y el reconocimiento del patrón, así como en la posibilidad de generar Asesores Expertos de red neuronal.
  2. Además de la capacidad de generar rápidamente Asesores Expertos de red neuronal, puede también adaptarlos rápidamente al comportamiento cambiante del mercado y entrenarles con diferentes instrumentos de trading y períodos de tiempo.
  3. Debido al hecho de que MQL5 Wizard puede permitir múltiples módulos de señal, puede crear Asesores Expertos complejos multidivisa de red neuronal y/o los indicadores compuestos basados en Asesores Expertos de red neuronal. También se pueden combinar con varios filtros adicionales, por ejemplo filtros de tiempo.
  4. Y por último, se puede usar el propio módulo neuronal de la red como filtro adicional para aumentar la eficiencia de un Asesor Experto ya hecho. Esto es posible debido a la capacidad de que una red neuronal se pueda entrenar utilizando los gráficos de los resultados de la prueba del Asesor Experto original.

El uso del intérprete del script que hace que el sistema de computación integrado no tenga un rendimiento muy alto puede ser considerado como uno de las inconvenientes de la implementación proporcionada anteriormente. En primer lugar, aunque hay que señalar que la interpretación del código del script, así como la operación del plugin Hlaiman sean asíncronos con EX5, tratamos con la tarea de paralelización. En segundo lugar, para aumentar la velocidad de los cálculos del tiempo consumido, por ejemplo al tratar con grandes redes neuronales, MetaTrader 5 y Hlaiman pueden funcionar en diferentes ordenadores a través de canales de comunicación en red. Lanzando un terminal de trading en un ordenador separado, no sólo ganará en el rendimiento también puede aumentar su seguridad.

Cuando se ponen en perspectiva, podemos ver en el desarrollo de los Asesores Expertos que pueden aprender de forma automática durante el trading. En este punto la manera más fácil de hacer esto es combinar el código del Asesor Experto con el código del script de aprendizaje ya que ambos utilizan la misma clase CSignalHNN que proporciona la funcionalidad necesaria. Este material puede llegar a ser el tema de un artículo complementario o ser la base de un artículo completamente nuevo, si parece ser de interés.

Se puede descargar la versión demo del Generador Hlaiman de Asesores Expertos aquí.

Adjuntos: