English Русский 中文 Deutsch 日本語 Português
FANN2MQL Neural Network Tutorial

FANN2MQL Neural Network Tutorial

MetaTrader 4Ejemplos | 2 marzo 2016, 14:32
1 754 1
Julien
Julien

En primer lugar:

Por favor, instale la libreria de fann2MQL. es necesaria para probar este ejemplo. Puede ser descargado aquí.

Introducción

Hasta ahora, había sólo un ejemplo de cómo utilizar la libreria de Fann2MQL, que permite a los traders utilizar la libreria de red neuronal de Open-Source "FANN" en sus códigos MQL.

Pero en el ejemplo, escrito por el creador de la libreria de Fann2MQL, no es fácil de entender. No está hecho para principiantes.

Así que he escrito otro ejemplo, mucho más fácil en su concepto y completamente comentado.

IIT no está relacionada con el trading directamente y no utiliza ningún dato financiero. Es un ejemplo estático simple de aplicación.

En este ejemplo, vamos a enseñar una simple red neuronal para reconocer un patrón simple.

El patrón nos enseñará si se compone de 3 números: a, b y c.

  • if a < b && b < c entonces espera salida = 1
  • if a < b && b > c entonces espera salida = 0
  • if a > b && b > c entonces espera salida = 0
  • if a > b && b < c entonces espera salida = 1

Puede que esos números sean como coordenadas del vector, por ejemplo (vector va hacia arriba o hacia abajo) o dirección del mercado. En cuyo caso, el patrón podría interpretarse como:

UP UP = UP

UP DOWN = DOWN

DOWN DOWN = DOWN

DOWN UP = UP

En primer lugar, vamos a crear una red neuronal.

A continuación vamos a mostrar la red algunos ejemplos de patrones, por lo que puede aprender y deducir las reglas.

Por último, vamos a mostrar la red nuevos patrones que nunca ha visto y preguntarle cuáles son sus conclusiones. Si él entiende las reglas, entonces será capaz de reconocer los patrones.

El código comentado:

// Incluimos la librería Fann2MQl
#include <Fann2MQL.mqh>

#property copyright "Copyright © 2009, Julien Loutre"
#property link      "http://www.thetradingtheory.com"

#property  indicator_separate_window
#property  indicator_buffers 0

// el número total de capas. aquí, hay una capa de entrada,
// 2 capas ocultas y una capas salida = 4 capas.
int nn_layer = 4;
int nn_input = 3; // Número de neuronas de entrada. Nuestro modelo está hecho de 3 números, 
                  // eso significa que las neuronas de entrada son 3.
int nn_hidden1 = 8; // Número de neuronas en la primera capa oculta
int nn_hidden2 = 5; //  Número de neuronas en la segunda capa oculta
int nn_output = 1; // número de salidas

// trainingData[][] contiene los ejemplos 
// vamos a utilizar para enseñar las reglas para las neuronas.
double      trainingData[][4];  // IMPORTANT! size = nn_input + nn_output


int maxTraining = 500;  // número máximo de tiempo entrenaremos 
                        // neuronas con algunos ejemplos
doble targetMSE = 0.002; // el error cuadrado medio de las neuronas deben 
                          // llegar a más  (entenderá este menor en el código)

int ann; // Esta var será el identificador de la red neuronal.

// Cuando el indicador se quita, borramos todas las redes neurnales 
// de la memoria de la computadora.
int deinit() {
   f2M_destroy_all_anns();
   return(0);
}

int init() {
   int i;
   double MSE;
   
   Print("=================================== START EXECUTION ================================");
   
   IndicatorBuffers(0);
   IndicatorDigits(6);
   
   // Cambiar el tamaño de la matriz trainingData, para que podamos usar.
   // Vamos a cambiar su tamaño un tamaño a la vez.
   ArrayResize(trainingData,1);
   
   Print("##### INIT #####");
   
   // Creamos una nueva red neuronal
   ann = f2M_create_standard(nn_layer, nn_input, nn_hidden1, nn_hidden2, nn_output);
   
   // comprobamos si se ha creado correctamente. 0 = OK, -1 = error
   debug("f2M_create_standard()",ann);
   
   // Hemos creado la función de activación. No te preocupes sobre eso. Sólo hazlo.
        f2M_set_act_function_hidden (ann, FANN_SIGMOID_SYMMETRIC_STEPWISE);
        f2M_set_act_function_output (ann, FANN_SIGMOID_SYMMETRIC_STEPWISE);
        
        // Algunos estudios han demostrado estadísticamente que los mejores resultados se alcanzan con esta gama; 
     // pero usted puede tratar de cambiar y ver que es lo que es mejor o peor
        f2M_randomize_weights (ann, -0.77, 0.77);
        
        // A imprimir en la consola el número de neuronas de entrada y salida. 
      // Para comprobar. Sólo para el propósito de depuración.
   debug("f2M_get_num_input(ann)",f2M_get_num_input(ann));
   debug("f2M_get_num_output(ann)",f2M_get_num_output(ann));
        
   
   Print("##### REGISTRO DE DATOS #####");
   
   // Ahora preparamos algunos ejemplos de datos (con salida prevista) 
   // y los agregamos a la configuración del entrenamiento.
   // Una vez que tenemos todos los ejemplos que queremos, vamos los añadimos 
   // Este es conjunto de datos de entrenamiento de las neuronas, para que puedan aprender.
   // prepareData() tiene algunos argumentos:
   // - Acción (de formación o que compute)
   // - los datos (aquí, 3 datos por configuración)
   // - el último argumento es el resultado esperado.
   // Aquí, esta función toma los datos de ejemplo y el resultado esperado, 
   // y añadir al conjunto de aprendizaje.
   // Compruebe el comentario asociado a esta función para obtener más detalles.
   //
   // Aquí está el patrón que vamos a enseñar:
   // Hay 3 números. Llamémosles a, b y c.
   // Usted puede pensar en esos números como vector de coordenadas 
  // por ejemplo (vector va arriba o abajo)
   // if a < b && b < c then output = 1
   // if a < b && b > c then output = 0
   // if a > b && b > c then output = 0
   // if a > b && b < c then output = 1
   
   
   // UP UP = UP / if a < b && b < c then output = 1
   prepareData("train",1,2,3,1);
   prepareData("train",8,12,20,1);
   prepareData("train",4,6,8,1);
   prepareData("train",0,5,11,1);

   // UP DOWN = DOWN / if a < b && b > c then output = 0
   prepareData("train",1,2,1,0);
   prepareData("train",8,10,7,0);
   prepareData("train",7,10,7,0);
   prepareData("train",2,3,1,0);

   // DOWN DOWN = DOWN / if a > b && b > c then output = 0
   prepareData("train",8,7,6,0);
   prepareData("train",20,10,1,0);
   prepareData("train",3,2,1,0);
   prepareData("train",9,4,3,0);
   prepareData("train",7,6,5,0);

   // DOWN UP = UP / if a > b && b < c then output = 1
   prepareData("train",5,4,5,1);
   prepareData("train",2,1,6,1);
   prepareData("train",20,12,18,1);
   prepareData("train",8,2,10,1);
   
   // Ahora imprimimos la configuración del entrenamiento completo en la consola, para comprobar cómo se ve.
   // Esto es sólo para propósito de la depuración.
   printDataArray();
   
   
   Print("##### FORMACIÓN #####");
   
   // Tenemos que entrenar las neuronas muchas veces en orden 
   // para que sean buenos en lo que les pedimos.
   // Aquí ENTRENAREMOS con los mismos datos (ejemplos) una y otra vez, 
   // hasta que comprendAn completamente las reglas que estamos tratando de enseñan, o hasta que 
   // la formación se repite un número de veces 'maxTraining'  
   // (en este caso maxTraining = 500)
   // Mejor entienden la regla, cuanto menor sea su Error cuadrático medio.
   // la función teach() devuelve este Error cuadrado medio (o MSE)
   // 0.1 o menor es un número suficiente de reglas simples
   // 0.02 o menos es mejor que reglas complejas como el 
   // Estamos tratando de enseñarles (es un reconocimiento de patrones. no tan fáciles.)
   for (i=0;i<maxTraining;i++) {
      Enseñar a MSE = (); ) // cada vez que ejecuta el bucle, se activa la función teach(). 
                     // Compruebe los comentarios asociados a esta función para entenderlo más.
      if (MSE < targetMSE) { // isi el MSE es inferior a lo que hemos definido (aquí targetMSE = 0.02)
         debug("training finished. Trainings ",i+1); // entonces lo mostramos en la consola 
                                                     // Cuánta formación 
                                                     // les costó entender
         i = maxTraining; // y nosotros saldremos de este bucle
      }
   }
   
   // mostrar en la consola el valor MSE una vez terminado el entrenamiento
   debug("MSE",f2M_get_MSE(ann));
   
   
   Print("##### EJECUNTANDO #####");
   // Y ahora podemos pedirle a la neurona analizar nuevos datos que nunca vieron.
   // ¿Se reconocen los patrones correctamente?
   // Se puede ver que utilicé la misma función prepareData() 
   // con el primer argumento para "calcular".
   // El último argumento que se dedicaba a la producción esperada 
   // Cuando utiliza esta función para registrar los ejemplos anteriores,
   // ahora es inútil, así que lo dejamos a cero.
   // Si lo prefiere, puede llamar directamente A la función compute().
   // En este caso, la estructura es compute(inputVector[]);
   // Así que en vez de prepareData("compute",1,3,1,0); hacer algo como:
   //    double inputVector[]; // declarar una matriz nueva
   //    ArrayResize(inputVector,f2M_get_num_input(ann)); 
   // cambiar el tamaño de la matriz al número de entrada neuronal
   //    inputVector[0] = 1; // Agregar en la matriz de los datos
   //    inputVector[1] = 3;
   //    inputVector[2] = 1;
   //    result = compute(inputVector); // llamar a la función compute(), con la matriz de entrada.
   // la función prepareData() llama a la función compute(), 
   // que muestra el resultado en la consola, 
   // así podemos comprobar si las neuronas eran buenas o no.
   debug("1,3,1 = UP DOWN = DOWN. Should output 0.","");
   prepareData("compute",1,3,1,0);
   
   debug("1,2,3 = UP UP = UP. Should output 1.","");
   prepareData("compute",1,2,3,0);
   
   debug("3,2,1 = DOWN DOWN = DOWN. Should output 0.","");
   prepareData("compute",3,2,1,0);
   
   debug("45,2,89 = DOWN UP = UP. Should output 1.","");
   prepareData("compute",45,2,89,0);
   
   debug("1,3,23 = UP UP = UP. Should output 1.","");
   prepareData("compute",1,3,23,0);
   
   debug("7,5,6 = DOWN UP = UP. Should output 1.","");
   prepareData("compute",7,5,6,0);
   
   debug("2,8,9 = UP UP = UP. Should output 1.","");
   prepareData("compute",2,8,9,0);
   
   Print("=================================== FIN DE LA EJECUCIÓN ================================");
   return(0);
}

int start() {
   return(0);
}

/*************************
** printDataArray()
** La presentación de los datos utilizados para la formación de las neuronas
** Esto es inútil. Creado para el propósito de depuración.
*************************/
void printDataArray() {
   int i,j;
   int bufferSize = ArraySize(trainingData)/(f2M_get_num_input(ann)+f2M_get_num_output(ann))-1;
   string lineBuffer = "";
   for (i=0;i<bufferSize;i++) {
      for (j=0;j<(f2M_get_num_input(ann)+f2M_get_num_output(ann));j++) {
         lineBuffer = StringConcatenate(lineBuffer, trainingData[i][j], ",");
      }
      debug("DataArray["+i+"]", lineBuffer);
      lineBuffer = "";
   }
}


/*************************
** prepareData()
** Prepare los datos para el entrenamiento o la computación.
** Se toma los datos, ponerlos en una matriz, 
** y enviarlos a la formación o funcionamiento de la función
** La actualización según el número de su código necesita de entrada/salida.
*************************/
void prepareData(string action, double a, double b, double c, double output) {
   double inputVector[];
   double outputVector[];
   // cambiar el tamaño de las matrices al tamaño correcto
   ArrayResize(inputVector,f2M_get_num_input(ann));
   ArrayResize(outputVector,f2M_get_num_output(ann));
   
   inputVector[0] = a;
   inputVector[1] = b;
   inputVector[2] = c;
   outputVector[0] = output;
   if (action == "train") {
      addTrainingData(inputVector,outputVector);
   }
   if (action == "compute") {
      compute(inputVector);
   }

   // Si tienes más entradas de 3, solo tienes que cambiar la estructura de esta función.
}


/*************************
** addTrainingData()
** Añadir un único conjunto de datos de entrenamiento 
**(ejemplo de datos + salida prevista) para el conjunto de entrenamiento global
*************************/
void addTrainingData(double inputArray[], double outputArray[]) {
   int j;
   int bufferSize = ArraySize(trainingData)/(f2M_get_num_input(ann)+f2M_get_num_output(ann))-1;
   
   //register the input data to the main array
   for (j=0;j<f2M_get_num_input(ann);j++) {
      trainingData[bufferSize][j] = inputArray[j];
   }
   for (j=0;j<f2M_get_num_output(ann);j++) {
      trainingData[bufferSize][f2M_get_num_input(ann)+j] = outputArray[j];
   }
   
   ArrayResize(trainingData,bufferSize+2);
}


/*************************
** teach()
** Obtener todos los datos de entrenamiento y usarlos para entrenar las neuronas una vez.
** Para formar correctamente las neuronas, necesitará ejecutar,
**  esta función muchas veces  hasta la media al cuadrado del Error lo suficientemente baja.
*************************/
double teach() {
   int i,j;
   double MSE;
   double inputVector[];
   double outputVector[];
   ArrayResize(inputVector,f2M_get_num_input(ann));
   ArrayResize(outputVector,f2M_get_num_output(ann));
   int call;
   int bufferSize = ArraySize(trainingData)/(f2M_get_num_input(ann)+f2M_get_num_output(ann))-1;
   for (i=0;i<bufferSize;i++) {
      for (j=0;j<f2M_get_num_input(ann);j++) {
         inputVector[j] = trainingData[i][j];
      }
      outputVector[0] = trainingData[i][3];
      //f2M_train() muestra las neuronas sólo un ejemplo a la vez.
      call = f2M_train(ann, inputVector, outputVector);
   }
   // Una vez hemos les mostramos un ejemplo, 
   // comprobamos si lo buenos que son comprobando su MSE. 
   // Si es baja, aprenden bien!
   MSE = f2M_get_MSE(ann);
   return(MSE);
}


/*************************
** compute()
** Calcular un conjunto de datos y devuelve el resultado computado
*************************/
double compute(double inputVector[]) {
   int j;
   int out;
   double output;
   ArrayResize(inputVector,f2M_get_num_input(ann));
   
   // We sent new data to the neurones.
   out = f2M_run(ann, inputVector);
   // and check what they say about it using f2M_get_output().
   output = f2M_get_output(ann, 0);
   debug("Computing()",MathRound(output));
   return(output);
}


/*************************
** debug()
** Presentar los datos en la consola
*************************/
void debug(string a, string b) {
   Print(a+" ==> "+b);
}

La salida


Salida de la red neuronal en la consola.

Conclusión

También puede leer el artículo "Using Neural Networks In MetaTrader" escrito por Mariusz Woloszyn, autor de la librería Fann2MQL.

Me tomó 4 días entender cómo utilizar Fann en MetaTrader, analizando la documentación poco disponible aquí y en google.

Espero que este ejemplo sea de utilidad para usted, y que evitará perder demasiado tiempo experimentando. Más artículos seguirán en las próximas semanas.

Si tienes duda por favor pregunte, y yo te responderé.

Traducción del inglés realizada por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/en/articles/1574

Archivos adjuntos |
ASNN_1_learner.mq4 (11.74 KB)
widipa
widipa | 20 may. 2017 en 04:15
Julien, has probado la red neuronal haciendo operaciones en forex?, cuales han sido los resultados?
Comprobar el mito: todo el día de trading depende de cómo se cotiza la sesión asiática Comprobar el mito: todo el día de trading depende de cómo se cotiza la sesión asiática
En este artículo revisaremos la declaración bien conocida que "El trading de todo el día depende de cómo se cotiza la sesión de Asia".
Una visión de Acumulación/Distribución y donde se puede conseguir Una visión de Acumulación/Distribución y donde se puede conseguir
El Indicador Acumulación/Distribución (A/D) tiene una característica interesante — sugiere una ruptura de la línea de tendencia trazada en esta gráfica del indicador, con cierta probabilidad, una próxima ruptura de la línea de tendencia en el gráfico de precios. Este artículo será útil e interesante para aquellos que son nuevos en la programación en MQL4. Teniendo esto en vista, he tratado de presentar la información de una forma de fácil agarre y utilizar las estructuras de código más simples.
Investigación de recurrencia estadística de direcciones de la vela Investigación de recurrencia estadística de direcciones de la vela
¿Es posible predecir el comportamiento del mercado de un próximo corto intervalo de tiempo, basado en las tendencias recurrentes de direcciones de la vela, en momentos específicos durante todo el día? Es decir, si tal suceso se encuentra en primer lugar. Esta pregunta probablemente surgió en la mente de cada trader. El propósito de este artículo es intentar predecir el comportamiento del mercado, basado en las repeticiones estadísticas de las direcciones de la vela durante intervalos específicos de tiempo.
Cómo añadir rápidamente un panel de control a un indicador o asesor Cómo añadir rápidamente un panel de control a un indicador o asesor
¿Quiere añadir a su indicador o asesor un panel gráfico de control rápido y cómodo, pero no sabe como hacerlo? En este artículo le enseñaré paso a paso cómo "atornillar" un panel de diálogo con parámetros de entrada a su programa MQL4/MQL5.