Este script ha sido desarrollado como parte del artículo "Aprendizaje Automático: Cómo las Máquinas de Vectores de Soporte pueden ser utilizadas en Trading" publicado en el sitio web de MQL5.
Imagina un escenario hipotético: eres un investigador que está estudiando un animal raro que solo se encuentra en las profundidades del Ártico, llamado Schnick. Dada la lejanía de estos animales, solo un puñado ha sido encontrado (digamos alrededor de 5000). Como investigador, te enfrentas a la pregunta... ¿cómo puedo identificar un Schnick?
Todo lo que tienes a tu disposición son artículos de investigación previamente publicados por los pocos investigadores que han visto uno. En estos artículos, los autores describen ciertas características sobre los Schnicks que encontraron, tales como altura, peso, número de patas, etc., pero todas estas características varían entre los artículos sin un patrón discernible…
¿Cómo podemos utilizar estos datos para identificar a un nuevo animal como un Schnick?
Una posible solución a nuestro problema es utilizar una máquina de vectores de soporte para identificar los patrones en los datos y crear un marco que pueda ser utilizado para clasificar a los animales como Schnick o no. El primer paso es crear un conjunto de datos que pueda ser utilizado para entrenar tu máquina de vectores de soporte para identificar Schnicks. Los datos de entrenamiento son un conjunto de entradas y salidas coincidentes para que la máquina de vectores de soporte analice y extraiga un patrón.
Este script intenta demostrar el poder de usar máquinas de vectores de soporte para resolver problemas de clasificación utilizando la herramienta de Aprendizaje Automático de Máquinas de Vectores de Soporte disponible en el MQL5 Market. Una descripción completa de este problema hipotético y el script se puede encontrar en el artículo "Aprendizaje Automático: Cómo las Máquinas de Vectores de Soporte pueden ser utilizadas en Trading". El artículo incluye una guía sobre cómo usar el script y cómo este problema puede ofrecer información sobre el uso del aprendizaje automático para evaluar tendencias de mercado.
Código:
//+------------------------------------------------------------------+ //| Schnick_Demo.mq5 | //| Copyright 2011, MetaQuotes Software Corp. | //| http://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2011, MetaQuotes Software Corp." #property link "http://www.mql5.com" #property version "1.00" //+------------------------------------------------------------------+ //| Este script demuestra las capacidades de la herramienta de Aprendizaje Automático //| de Máquinas de Vectores de Soporte //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| La siguiente declaración importa todas las funciones incluidas en //| la herramienta de Máquinas de Vectores de Soporte 'svMachineTool.ex5' //+------------------------------------------------------------------+ #import "svMachineTool_demo.ex5" enum ENUM_TRADE {BUY,SELL}; enum ENUM_OPTION {OP_MEMORY,OP_MAXCYCLES,OP_TOLERANCE}; int initSVMachine(void); void setIndicatorHandles(int handle,int &indicatorHandles[],int offset,int N); void setParameter(int handle,ENUM_OPTION option,double value); bool genOutputs(int handle,ENUM_TRADE trade,int StopLoss,int TakeProfit,double duration); bool genInputs(int handle); bool setInputs(int handle,double &Inputs[],int nInputs); bool setOutputs(int handle,bool &Outputs[]); bool training(int handle); bool classify(int handle); bool classify(int handle,int offset); bool classify(int handle,double &iput[]); void deinitSVMachine(void); #import //--- El número de entradas que vamos a usar para el svm int N_Inputs=7; //+------------------------------------------------------------------+ //| Función de inicialización del experto | //+------------------------------------------------------------------+ int OnInit() { double inputs[]; //array doble vacío para ser usado para crear las entradas de entrenamiento bool outputs[]; //array booleano vacío para ser usado para crear las salidas de entrenamiento int N_TrainingPoints=5000; //define el número de muestras de entrenamiento que se generarán int N_TestPoints=5000; //define el número de muestras que se usarán en la prueba genTrainingData(inputs,outputs,N_TrainingPoints); //Genera las entradas y salidas que se usarán para entrenar el svm int handle1=initSVMachine(); //inicializa una nueva máquina de vectores de soporte y retorna un identificador setInputs(handle1,inputs,7); //pasa las entradas (sin errores) a la máquina de vectores de soporte setOutputs(handle1,outputs); //pasa las salidas (sin errores) a la máquina de vectores de soporte setParameter(handle1,OP_TOLERANCE,0.01); //establece el parámetro de tolerancia de error a <5% training(handle1); //entrena la máquina de vectores de soporte usando las entradas/salidas pasadas insertRandomErrors(inputs,outputs,500); //toma las entradas/salidas originales generadas y agrega errores aleatorios a los datos int handle2=initSVMachine(); //inicializa una nueva máquina de vectores de soporte y retorna un identificador setInputs(handle2,inputs,7); //pasa las entradas (con errores) a la máquina de vectores de soporte setOutputs(handle2,outputs); //pasa las salidas (con errores) a la máquina de vectores de soporte setParameter(handle2,OP_TOLERANCE,0.01); //establece el parámetro de tolerancia de error a <5% training(handle2); //entrena la máquina de vectores de soporte usando las entradas/salidas pasadas double t1=testSVM(handle1,N_TestPoints); //prueba la precisión de la máquina de vectores de soporte entrenada y la guarda en t1 double t2=testSVM(handle2,N_TestPoints); //prueba la precisión de la máquina de vectores de soporte entrenada y la guarda en t2 Print("La precisión del SVM es ",NormalizeDouble(t1,2),"% (usando entradas/salidas de entrenamiento sin errores)"); Print("La precisión del SVM es ",NormalizeDouble(t2,2),"% (usando entradas/salidas de entrenamiento con errores)"); deinitSVMachine(); //Libera toda la memoria utilizada en la generación del SVM para evitar fugas de memoria return(0); } //+------------------------------------------------------------------+ //| Función de desinicialización del experto | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- No se ejecutan funciones en OnDeinit() } //+------------------------------------------------------------------+ //| Función tick del experto | //+------------------------------------------------------------------+ void OnTick() { //--- No se ejecutan funciones en OnTick() } //+------------------------------------------------------------------+ //| Esta función toma las propiedades de observación del animal observado y //| basándose en los criterios que hemos elegido, devuelve //| verdadero/falso si es un schnick //+------------------------------------------------------------------+ bool isItASchnick(double height,double weight,double N_legs,double N_eyes,double L_arm,double av_speed,double f_call) { if(height < 1000 || height > 1100) return(false); //Si la altura está fuera de los parámetros > retornar(false) if(weight < 40 || weight > 50) return(false); //Si el peso está fuera de los parámetros > retornar(false) if(N_legs < 8 || N_legs > 10) return(false); //Si el N_Patas está fuera de los parámetros > retornar(false) if(N_eyes < 3 || N_eyes > 4) return(false); //Si el N_Ojos está fuera de los parámetros > retornar(false) if(L_arm < 400 || L_arm > 450) return(false); //Si el L_brazo está fuera de los parámetros > retornar(false) if(av_speed < 2 || av_speed > 2.5) return(false); //Si la velocidad promedio está fuera de los parámetros > retornar(false) if(f_call < 11000 || f_call > 15000) return(false); //Si el f_llamada está fuera de los parámetros > retornar(false) return(true); //De lo contrario > retornar(true) } //+------------------------------------------------------------------+ //| Esta función toma un array doble vacío y un array booleano vacío //| y genera las entradas/salidas que se utilizarán para entrenar el SVM //+------------------------------------------------------------------+ void genTrainingData(double &inputs[],bool &outputs[],int N) { double in[]; //crea un array doble vacío para ser utilizado //para almacenar temporalmente las entradas generadas ArrayResize(in,N_Inputs); //redimensiona el array in[] a N_Inputs ArrayResize(inputs,N*N_Inputs); //redimensiona el array inputs[] para tener un tamaño de N*N_Inputs ArrayResize(outputs,N); //redimensiona el array outputs[] para tener un tamaño de N for(int i=0;i<N;i++) { in[0]= randBetween(980,1120); //Entrada aleatoria generada para altura in[1]= randBetween(38,52); //Entrada aleatoria generada para peso in[2]= randBetween(7,11); //Entrada aleatoria generada para N_patas in[3]= randBetween(3,4.2); //Entrada aleatoria generada para N_ojos in[4]= randBetween(380,450); //Entrada aleatoria generada para L_brazos in[5]= randBetween(2,2.6); //Entrada aleatoria generada para velocidad promedio in[6]= randBetween(10500,15500); //Entrada aleatoria generada para f_llamada //--- copia las nuevas entradas aleatorias generadas en el array de entrada de entrenamiento ArrayCopy(inputs,in,i*N_Inputs,0,N_Inputs); //--- evalúa las entradas aleatorias y determina si es un schnick outputs[i]=isItASchnick(in[0],in[1],in[2],in[3],in[4],in[5],in[6]); } } //+------------------------------------------------------------------+ //| Esta función toma el identificador del SVM entrenado y prueba cuán //| exitosa es al clasificar nuevas entradas aleatorias //+------------------------------------------------------------------+ double testSVM(int handle,int N) { double in[]; int atrue=0; int afalse=0; int N_correct=0; bool Predicted_Output; bool Actual_Output; ArrayResize(in,N_Inputs); for(int i=0;i<N;i++) { in[0]= randBetween(980,1120); //Entrada aleatoria generada para altura in[1]= randBetween(38,52); //Entrada aleatoria generada para peso in[2]= randBetween(7,11); //Entrada aleatoria generada para N_patas in[3]= randBetween(3,4.2); //Entrada aleatoria generada para N_ojos in[4]= randBetween(380,450); //Entrada aleatoria generada para L_brazos in[5]= randBetween(2,2.6); //Entrada aleatoria generada para velocidad promedio in[6]= randBetween(10500,15500); //Entrada aleatoria generada para f_llamada //--- usa la función isItASchnick para determinar la salida deseada real Actual_Output=isItASchnick(in[0],in[1],in[2],in[3],in[4],in[5],in[6]); //--- usa el SVM entrenado para retornar la salida predicha. Predicted_Output=classify(handle,in); if(Actual_Output==Predicted_Output) { N_correct++; //Esta declaración mantiene el conteo de cuántas veces la salida predicha es correcta. } } //--- retorna la precisión del SVM entrenado como un porcentaje return(100*((double)N_correct/(double)N)); } //+------------------------------------------------------------------+ //| Esta función toma las entradas y salidas de entrenamiento correctas //| generadas e inserta N errores aleatorios en los datos //+------------------------------------------------------------------+ void insertRandomErrors(double &inputs[],bool &outputs[],int N) { int nTrainingPoints=ArraySize(outputs); //calcula el número de puntos de entrenamiento int index; //crea nuevo entero 'index' bool randomOutput; //crea nuevo booleano 'randomOutput' double in[]; //crea un array doble vacío para ser utilizado //para almacenar temporalmente las entradas generadas ArrayResize(in,N_Inputs); //redimensiona el array in[] a N_Inputs for(int i=0;i<N;i++) { in[0]= randBetween(980,1120); //Entrada aleatoria generada para altura in[1]= randBetween(38,52); //Entrada aleatoria generada para peso in[2]= randBetween(7,11); //Entrada aleatoria generada para N_patas in[3]= randBetween(3,4.2); //Entrada aleatoria generada para N_ojos in[4]= randBetween(380,450); //Entrada aleatoria generada para L_brazos in[5]= randBetween(2,2.6); //Entrada aleatoria generada para velocidad promedio in[6]= randBetween(10500,15500); //Entrada aleatoria generada para f_llamada //--- elige aleatoriamente una de las entradas de entrenamiento para insertar un error index=(int)MathRound(randBetween(0,nTrainingPoints-1)); //--- genera una salida booleana aleatoria para ser utilizada para crear el error if(randBetween(0,1)>0.5) randomOutput=true; else randomOutput=false; //--- copia las nuevas entradas aleatorias generadas en el array de entrada de entrenamiento ArrayCopy(inputs,in,index*N_Inputs,0,N_Inputs); //--- copia la nueva salida aleatoria generada en el array de salida de entrenamiento outputs[index]=randomOutput; } } //+------------------------------------------------------------------+ //| Esta función se utiliza para crear un valor aleatorio entre t1 y t2 //+------------------------------------------------------------------+ double randBetween(double t1,double t2) { return((t2-t1)*((double)MathRand()/(double)32767)+t1); } //+------------------------------------------------------------------+
Publicaciones relacionadas
- Señales de Trading con MQL5: Patrones de Estrellas y MFI
- MQL5 Wizard: Crea un Asesor Experto con Señales de Bullish Harami y Bearish Harami + CCI
- Crea tu Asesor Experto con MQL5: Señales de Trading Basadas en Dark Cloud Cover y Piercing Line
- MQL5 Wizard: Crea EAs con Señales de Trading basadas en Dark Cloud Cover y Piercing Line
- Crea tu Asesor Experto con MQL5: Señales de Trading Basadas en Estrellas de la Mañana/Atardecer y CCI