English Русский 中文 Deutsch 日本語 Português
preview
Redes neuronales: así de sencillo (Parte 40): Enfoques para utilizar Go-Explore con una gran cantidad de datos

Redes neuronales: así de sencillo (Parte 40): Enfoques para utilizar Go-Explore con una gran cantidad de datos

MetaTrader 5Asesores Expertos | 11 septiembre 2023, 10:03
233 0
Dmitriy Gizlyk
Dmitriy Gizlyk

Introducción

En el artículo anterior "Redes neuronales: así de sencillo (Parte 39): Go-Explore: un enfoque diferente sobre la exploración", nos familiarizamos con el algoritmo Go-Explore y su capacidad para explorar bien el entorno. Permítanme recordarles que este algoritmo incluye 2 etapas:

  • Fase 1 — exploración
  • Fase 2 — política de entrenamiento a partir de ejemplos

En la Fase 1, utilizamos una selección aleatoria de acciones para obtener la imagen más completa del entorno, y este enfoque nos permitió recopilar una base de datos de ejemplos suficiente para entrenar con éxito a un agente con los datos históricos en un mes natural. El modelo que construimos logró encontrar una estrategia para obtener beneficios en la muestra de entrenamiento.

Sin embargo, el periodo de un mes calendario resulta demasiado corto para resumir los datos y construir una estrategia que pueda generar beneficios en un futuro previsible. Por ello, para encontrar nuestra propia estrategia, nos veremos obligados a aumentar el periodo de entrenamiento. Aumentando el periodo de entrenamiento a tres meses, descubrimos que el uso de una selección aleatoria de acciones no posibilitaba ninguna pasada rentable.

Entrenamiento con periodo aumentado Resultados de las pasadas

Desde el punto de vista de la teoría de la probabilidad, este es un resultado bastante previsible. Después de todo, la probabilidad total del evento es igual al producto de las probabilidades de todos sus componentes. Pero, como la probabilidad de cada evento individual es inferior a 1, a medida que aumente el número de pasos, la probabilidad de obtener una pasada rentable también disminuirá.

También debemos considerar que con un aumento en el periodo de entrenamiento, es posible que se produzcan cambios en el entorno que pueden influir en los resultados del entrenamiento del agente. Por consiguiente, resulta importante monitorear periódicamente el rendimiento del agente y analizar su trabajo en etapas intermedias.

Para mejorar los resultados del aprendizaje durante un periodo más largo, podemos aplicar diversos métodos para optimizar el algoritmo Go-Explore, por ejemplo, usando un enfoque mejorado para elegir acciones. Este enfoque deberá considerar un contexto más amplio de la tarea y permitir al agente tomar decisiones más fundamentadas.

En este artículo, analizaremos más de cerca los posibles métodos de optimización del algoritmo Go-Explore para mejorar su rendimiento durante periodos de entrenamiento más largos.


1. Dificultades para usar Go-Explore con un aumento del periodo de entrenamiento.

A medida que aumenta el periodo de entrenamiento del algoritmo Go-Explore, aparecen ciertas dificultades que pueden dificultar su uso. Algunas de ellas incluyen:

  1. El problema de la maldición de la dimensionalidad: a medida que aumenta el periodo de entrenamiento, la cantidad de estados que un agente puede visitar crece exponencialmente, lo cual dificulta encontrar la estrategia óptima.

  2. El cambio del entorno: a medida que aumenta el periodo de entrenamiento, es posible que se den cambios en el entorno que pueden influir en los resultados del aprendizaje del agente. Esto puede hacer que una estrategia que antes había sido exitosa se vuelva ineficaz o incluso imposible.

  3. La complejidad de las opciones de acción: a medida que aumenta el periodo de entrenamiento, es posible que el agente necesite tener en cuenta un contexto más amplio de la tarea para poder tomar decisiones fundamentadas. Esto puede complicar la tarea de selección de la acción óptima y requerir métodos de optimización de algoritmos más complejos.

  4. El aumento del tiempo de entrenamiento: a medida que aumenta el periodo de entrenamiento, también aumenta el tiempo necesario para recopilar suficientes datos y entrenar el modelo. Esto puede reducir el rendimiento y la velocidad del aprendizaje de los agentes.

Con un aumento en el periodo de entrenamiento, puede surgir el problema del aumento la dimensionalidad del espacio de estados que debe explorarse. Esto puede provocar el problema de la "maldición de la dimensionalidad", donde el número de estados posibles crece exponencialmente a medida que aumenta la dimensionalidad, lo cual dificulta la exploración del espacio de estados y puede hacer que el algoritmo dedique demasiado tiempo a explorar estados irrelevantes.

Podemos utilizar técnicas de reducción de la dimensionalidad, tales como el ACP para resolver este problema. Estas técnicas permiten reducir la dimensionalidad del espacio de estados, manteniendo información sobre la estructura de datos. También podemos usar técnicas de selección de características principales para reducir la dimensionalidad del espacio de estados y centrarnos en los aspectos más importantes del problema.

Además, para realizar un estudio más eficiente del espacio de estados, podemos utilizar métodos adicionales, como la optimización basada en algoritmos evolutivos o genéticos, que permiten buscar soluciones óptimas en grandes espacios de estados. Estos métodos permiten explorar diversas variantes del comportamiento del agente y seleccionar las soluciones más óptimas para una tarea determinada.

También podemos utilizar varios enfoques para la elección de acciones, como los métodos de exploración basados ​​en la confianza, que permiten al agente explorar nuevas regiones del espacio de estados considerando no solo la probabilidad de obtener una recompensa, sino también la confianza en su conocimiento de la tarea. Esto puede ayudar a evitar el «atasco» en óptimos locales y permitir una exploración más eficiente del espacio de estados.

Las demostraciones de aprendizaje por refuerzo (RL) suelen usar juegos de computadora u otros entornos simulados artificialmente que son estacionarios, es decir, que no cambian con el tiempo. No obstante, en aplicaciones reales, el entorno puede cambiar con el tiempo, lo cual puede afectar los resultados de aprendizaje del agente.

Al utilizar el algoritmo Go-Explore, que incluye una etapa de exploración del entorno para obtener datos históricos, cambiar el entorno puede generar resultados inesperados cuando el agente se entrena posteriormente con datos históricos.

Por ejemplo, si un agente ha sido entrenado con datos durante varios meses y durante este tiempo se han dado cambios en el entorno, como, por ejemplo, un cambio en las reglas del juego o la aparición de nuevos objetos, entonces es posible que el agente no pueda para hacer frente al nuevo entorno, y su estrategia anteriormente exitosa podría volverse ineficaz o incluso imposible.

Para reducir el impacto de los cambios del entorno en los resultados del aprendizaje de un agente, deberemos monitorear periódicamente el entorno y analizar sus cambios durante el entrenamiento del agente. Si detectamos cambios significativos en el entorno, entonces tendremos que reiniciar el proceso de entrenamiento de los agentes utilizando los datos y algoritmos actualizados.

También podemos utilizar métodos de aprendizaje que tengan en cuenta el cambio en el entorno durante el entrenamiento, como los métodos basados ​​en el aprendizaje por refuerzo mediante modelos (RL basado en modelos), que construyen un modelo del entorno y lo utilizan para predecir los estados y recompensas futuros. Esto permite al agente adaptarse a los cambios del entorno y tomar decisiones más fundamentadas.

Podemos utilizar otras técnicas de optimización, como el cambio de hiperparámetros en el algoritmo o realizar cambios en el propio algoritmo para un aprendizaje más eficiente.

En general, utilizar el algoritmo Go-Explore para entrenar a agentes durante periodos de tiempo más largos puede resultar bastante complejo y requiere muchas soluciones y mejoras técnicas.

Como resultado, el uso del algoritmo Go-Explore puede ser bastante complicado y requerir muchas soluciones y mejoras técnicas. El algoritmo Go-Explore es una poderosa herramienta para explorar entornos complejos y entrenar agentes en tareas con una gran cantidad de estados y acciones, pero su efectividad puede disminuir si aumentamos el periodo de entrenamiento y modificamos las condiciones del problema. Por ello, deberemos utilizar varios métodos de optimización y ajuste de parámetros para lograr los mejores resultados. Esta podría ser un área de investigación muy útil y prometedora.


2. Variantes de optimización del enfoque.

De lo anterior se desprende que ampliar el periodo de entrenamiento requiere un enfoque más cuidadoso que simplemente introducir nuevas fechas en el simulador de estrategias y cargar datos históricos adicionales. Para crear una estrategia comercial real, tendremos que entrenar el modelo con la máxima cantidad posible de datos históricos. Solo este enfoque permitirá crear un modelo que pueda resultar rentable en el futuro.

En este artículo no vamos a complicar el modelo. En su lugar, usaremos algunos enfoques simples para ayudar a ampliar la profundidad de los datos históricos para el entrenamiento de modelos utilizando el algoritmo Go-Explore.

Antes de optimizar un algoritmo creado previamente, deberemos analizar sus limitaciones.

El primer paso será cambiar las constantes en la estructura Cell. Esta estructura se usa para almacenar el estado individual del sistema y el camino que se ha tomado. Por razones técnicas, nos vemos obligados a usar únicamente arrays estáticos en esta estructura. A medida que aumenta el periodo de entrenamiento del modelo, también aumentará el tamaño del camino para alcanzar el estado descrito. Para hacer esto, crearemos prudentemente una constante que indique el tamaño del array. Ahora deberemos cambiar el valor de esta constante para que haya suficiente espacio para registrar el camino completo del agente desde el principio hasta el final del periodo de entrenamiento.

Usaremos algunas matemáticas simples para determinar el valor de la constante. De media, un mes natural contiene entre 21 y 22 días laborables. Para evitar errores, usaremos el valor máximo de días laborables: 22. Durante 4 meses habrá 88 días laborables.

Al probar modelos, usaremos el marco temporal H1. En un día hay 24 horas, por lo tanto, para entrenar el modelo, necesitaremos un búfer de 2112 elementos (88 * 24). Estos cálculos tienen en cuenta los valores máximos posibles y superan ligeramente el número real de barras, lo cual le permite no temer un error crítico al ir más allá del tamaño del array. Sin embargo, cuando se entrena con cotizaciones que incluyen fines de semana (por ejemplo, las criptomonedas), se deben utilizar los días naturales para calcular el tamaño del búfer, teniendo en cuenta el periodo de entrenamiento completo y las características de las cotizaciones del instrumento.

#define                    Buffer_Size  2112

El segundo obstáculo es la clasificación de los ejemplos antes de guardarlos. La práctica ha demostrado que clasificar datos puede llevar más tiempo que el propio proceso de revisar los datos históricos y recopilar estos estados. A medida que aumenta el periodo de aprendizaje, también aumentará la cantidad de datos a clasificar. Por lo tanto, hemos decidido abandonar la clasificación de datos. Como resultado, la función OnTesterDeinit en Faza1.mq5 tendrá la siguiente forma:

//+------------------------------------------------------------------+
//| TesterDeinit function                                            |
//+------------------------------------------------------------------+
void OnTesterDeinit()
  {
//---
   int total = ArraySize(Total);
   printf("total %d", total);
   Print("Saving...");
   SaveTotalBase();
   Print("Saved");
  }

Durante las pruebas hemos descubierto que el asesor con frecuencia abre varias posiciones y las mantiene abiertas durante mucho tiempo. Queríamos abordar este problema de forma integral, así que hemos realizado algunos cambios en el funcionamiento del asesor experto de recopilación de ejemplos.

Uno de los cambios se refiere a la definición de recompensa. Anteriormente, usábamos el cambio en la equidad como recompensa. Este enfoque permitía que el modelo tuviera en cuenta el cambio en el beneficio acumulado y no en el fijo, penalizándolo por las reducciones y estimulando la acumulación de beneficios en posiciones rentables. Sin embargo, este enfoque limitaba la posibilidad de obtener beneficios. No queríamos renunciar a la ventaja que supone el uso de la equidad, pero también queríamos añadir una recompensa por la obtención de beneficios.

Hemos encontrado una solución de compromiso que consiste en usar la media aritmética de la variación de la equidad y del balance de la cuenta. Al acumular beneficios o pérdidas en una posición abierta, la equidad cambiará, pero el balance de la cuenta permanecerá sin cambios. Así, el agente recibirá una recompensa o una penalización equivalente a la mitad del cambio de la equidad. Al fijar una ganancia o pérdida, la equidad no cambia, pero el monto acumulado se refleja en el balance de la cuenta. El agente recibe la otra mitad de la recompensa o penalización diferida. Así, el agente se vuelve más interesado en cerrar posiciones con beneficio y menos propenso a mantener posiciones abiertas.

      Base[action_count - 1].value = ( Base[action_count - 1].state[241] - state[241] + 
                                       Base[action_count - 1].state[240] - state[240] ) / 2.0f;

También hemos decidido limitar el volumen máximo de posiciones abiertas para reducir su número. En el proceso de creación de los ejemplos y la prueba del modelo, hemos utilizado un volumen mínimo fijo para cada operación. Por lo tanto, la introducción de un límite en el volumen de posiciones abiertas resulta completamente idéntica a limitar el número de posiciones abiertas. No obstante, al describir el estado actual del sistema, recopilamos información sobre el volumen de posiciones abiertas y los beneficios/pérdidas acumulados. Para evitar cálculos adicionales, usaremos el volumen de la posición abierta para limitar el volumen máximo. Hemos trasladado el valor del volumen máximo posible de una posición abierta a variables externas, lo cual nos permite realizar experimentos con diferentes valores.

input double               MaxPosition = 0.1;

El objetivo final de nuestro límite de posiciones abiertas máximas es reducir el número de posiciones abiertas en la cuenta y evitar la acumulación de transacciones con bloqueo positivo o negativo. Para ello, comprobaremos el límite para las transacciones largas y cortas por separado, sin tener en cuenta su diferencia.

Es importante considerar que no establecemos explícitamente las restricciones de nuestro modelo. En lugar de ello, en la etapa de creación de los ejemplos que se utilizarán para entrenar el modelo, aplicaremos restricciones al volumen máximo de posiciones abiertas. A continuación, utilizaremos estos ejemplos para entrenar el modelo, y él mismo construirá su estrategia basándose en los ejemplos recibidos. Este enfoque permitirá que el modelo se adapte a la situación cambiante del mercado y elija las acciones más efectivas.

Sin embargo, deberemos tener en cuenta que, si generamos una acción para abrir una posición, pero debido a las restricciones introducidas no se puede realizar, el estado posterior del sistema y la recompensa no se corresponderán con la acción generada. Para resolver este problema, guardaremos la acción correspondiente a la expectativa (sin operaciones comerciales) en la base de datos de ejemplos, en caso de que la acción generada no se haya realizado. Esto permitirá hacer coincidir la acción y la recompensa, y garantizará que el modelo se entrene adecuadamente.

   switch(act)
     {
      case 0:
         if(buy_value >= MaxPosition || !Trade.Buy(Symb.LotsMin(), Symb.Name()))
            act = 3;
         break;
      case 1:
         if(sell_value >= MaxPosition || !Trade.Sell(Symb.LotsMin(), Symb.Name()))
            act = 3;
         break;
      case 2:
         for(int i = PositionsTotal() - 1; i >= 0; i--)
            if(PositionGetSymbol(i) == Symb.Name())
               if(!Trade.PositionClose(PositionGetInteger(POSITION_IDENTIFIER)))
                 {
                  act = 3;
                  break;
                 }
         break;
     }

Como estamos trabajando con operaciones de mercado arriesgadas, nuestra tarea consistirá no solo en obtener ganancias, sino también en minimizar posibles pérdidas. Para hacer esto, añadiremos a nuestro modelo un límite en el tiempo máximo que se puede mantener una posición abierta.

Este límite será una variable externa entera que especificará el número máximo de barras para mantener una posición abierta. 

input int                  MaxLifeTime = 48;

Luego determinaremos la vida útil de la posición más antigua y cuando se alcance el valor límite, forzaremos la acción de cierre de todas las posiciones.

Esto será necesario para no mantener demasiado las posiciones abiertas, lo cual puede provocar grandes pérdidas. Al recopilar información sobre el estado actual de la cuenta y las posiciones abiertas, consideraremos esta limitación para no exceder el tiempo máximo de mantenimiento.

   int total = PositionsTotal();
   datetime time_current = TimeCurrent();
   int first_order = 0;
   for(int i = 0; i < total; i++)
     {
      if(PositionGetSymbol(i) != Symb.Name())
         continue;
      switch((int)PositionGetInteger(POSITION_TYPE))
        {
         case POSITION_TYPE_BUY:
            buy_value += PositionGetDouble(POSITION_VOLUME);
            buy_profit += PositionGetDouble(POSITION_PROFIT);
            break;
         case POSITION_TYPE_SELL:
            sell_value += PositionGetDouble(POSITION_VOLUME);
            sell_profit += PositionGetDouble(POSITION_PROFIT);
            break;
        }
      first_order = MathMax((int)(PositionGetInteger(POSITION_TIME) - time_current) / PeriodSeconds(TimeFrame), first_order);
     }

No obstante, si permitimos que se supere este límite, entonces se deberán tomar las medidas oportunas. En este caso, no solo cerraremos una posición después de que expire el tiempo, sino que especificaremos la acción de cierre de todas las posiciones y las cerraremos todas. Esto nos permitirá mantener la correspondencia entre la acción realizada, el nuevo estado y la recompensa, lo cual resulta importante para el correcto funcionamiento del modelo.

   int act = (first_order < MaxLifeTime ? SampleAction(4) : 2);

Así, el uso de un límite de tiempo máximo para mantener una posición abierta supondrá otro mecanismo de nuestro modelo que nos ayudará a controlar los riesgos y lograr resultados más estables ante la incertidumbre del mercado.

Ya hemos descrito los enfoques para la optimización de algoritmos basados ​​en las deficiencias identificadas en el proceso de prueba del modelo. Ahora pasaremos a un enfoque de entrenamiento del modelo con una gran cantidad de datos históricos. Vamos a considerar la posibilidad de dividir una muestra de entrenamiento grande en partes más pequeñas y entrenar a un agente en cada una de estas secciones. Podemos suponer que si el algoritmo funciona bien en intervalos temporales cortos, también lo hará en intervalos más largos. Por lo tanto, podremos utilizar este enfoque para mejorar el entrenamiento del modelo con grandes cantidades de datos.

Este enfoque permitirá que el modelo capte de manera más efectiva las tendencias del mercado y aumente su resiliencia a los cambios en los factores externos. Esto resulta especialmente importante al utilizar el modelo para operar en mercados reales, donde es fundamental predecir los cambios en la dirección de la tendencia. Además, este enfoque hará posible que el modelo utilice de forma más efectiva todos los datos disponibles, y no solo las últimas observaciones, lo cual a su vez mejorará la calidad del pronóstico.

Debemos señalar que la división de la muestra de entrenamiento en intervalos temporales más pequeños deberá realizarse considerando el orden cronológico de los datos para evitar intersecciones de los mismos y desplazamientos en el pronóstico. También tendremos que considerar que al dividir los datos en segmentos más pequeños, la cantidad de datos disponibles para entrenar en cada segmento será menor, lo cual puede provocar una disminución en la precisión de la predicción del modelo.

Por tanto, dividir la muestra de entrenamiento en intervalos temporales más pequeños será un enfoque eficaz para optimizar el algoritmo y podría mejorar significativamente la calidad de la predicción del modelo.

Dividiendo la muestra de entrenamiento en episodios más pequeños, nos enfrentaremos a la necesidad de desarrollar una estrategia general que nos permita recorrer con éxito toda la muestra de entrenamiento. Para ello, podemos usar una combinación de muestreo de acciones aleatorias y muestreo de entrenamiento dirigido para encontrar la estrategia más exitosa y rentable.

La idea es reproducir pequeños episodios secuencialmente, utilizando un muestreo aleatorio de las acciones de cada episodio. Luego seleccionaremos las pasadas más rentables y las utilizaremos como punto de partida para el siguiente episodio. Así, repasaremos secuencialmente toda la muestra de entrenamiento, acumulando los ejemplos de una estrategia rentable.

Este enfoque combinará ideas aparentemente opuestas: el muestreo aleatorio y el entrenamiento dirigido. Con la ayuda del muestreo aleatorio, exploraremos el entorno, mientras que el paso dirigido de una muestra de entrenamiento nos ayudará a encontrar la estrategia más exitosa. Como resultado, lograremos una estrategia más generalizada y rentable para nuestro agente.

En general, combinar el muestreo aleatorio y el entrenamiento dirigido nos permitirá obtener una estrategia mejor para pasar la muestra de entrenamiento, usando tanto la aleatoriedad como la experiencia de las acciones exitosas ya acumuladas.

Para implementar este enfoque, introduciremos 3 variables externas:

  • MinStartSteps — el número mínimo de pasos antes de que comience el muestreo
  • MaxSteps — el número máximo de pasos de muestreo (tamaño del episodio)
  • MinProfit — el beneficio mínimo para guardar en la base de datos de ejemplos.

input int                  MinStartSteps = 96;
input int                  MaxSteps = 120;
input double               MinProfit = 10;

Durante las discusiones sobre la optimización del algoritmo, hemos descubierto que clasificar los ejemplos antes de guardarlos resulta ineficiente. En su lugar, hemos decidido utilizar la variable MinProfit para determinar el beneficio mínimo requerido para que los ejemplos se incluyan en la base. Esto nos permite priorizar los ejemplos usados como puntos de partida para el muestreo posterior. Además, utilizaremos la variable MinStartSteps para establecer el número mínimo de pasos en un ejemplo requeridos para usar dicho ejemplo como punto de partida. Esto nos permitirá evitar quedarnos estancados en pasos intermedios del proceso de muestreo y pasar al siguiente episodio.

También utilizaremos la variable MaxSteps, que determina la duración máxima de un episodio. Tras superar este valor, el muestreo dejará de ser efectivo y deberemos guardar el camino recorrido. De esta forma, podremos usar los recursos de forma más eficiente y acelerar el proceso de aprendizaje.

En el método OnInit de nuestro asesor experto Faza1.mq5, después de cargar la base de datos de ejemplos creada anteriormente, primero seleccionaremos los ejemplos que cumplan con el requisito de la cantidad de pasos superados,

   if(LoadTotalBase())
     {
      int total = ArraySize(Total);
      Cell temp[];
      ArrayResize(temp, total);
      int count = 0;
      for(int i = 0; i < total; i++)
         if(Total[i].total_actions >= MinStartSteps)
           {
            temp[count] = Total[i];
            count++;
           }

y luego, de entre los seleccionados, elegiremos un ejemplo usando el muestreo aleatorio. Precisamente ese ejemplo seleccionado aleatoriamente se utilizará como punto de partida para el muestreo.

      if(count > 0)
        {
         count = (int)(((double)(MathRand() * MathRand()) / MathPow(32768.0, 2.0)) * (count - 1));
         StartCell = temp[count];
        }
      else
        {
         count = (int)(((double)(MathRand() * MathRand()) / MathPow(32768.0, 2.0)) * (total - 1));
         StartCell = Total[count];
        }
     }

En el método OnTick de nuestro asesor experto, primero ejecutaremos obligatoriamente todo el camino hasta llegar al punto de inicio de nuestro episodio.

void OnTick()
  {
//---
   if(!IsNewBar())
      return;
   bar++;
   if(bar < StartCell.total_actions)
     {
      switch(StartCell.actions[bar])
        {
         case 0:
            Trade.Buy(Symb.LotsMin(), Symb.Name());
            break;
         case 1:
            Trade.Sell(Symb.LotsMin(), Symb.Name());
            break;
         case 2:
            for(int i = PositionsTotal() - 1; i >= 0; i--)
               if(PositionGetSymbol(i) == Symb.Name())
                  Trade.PositionClose(PositionGetInteger(POSITION_IDENTIFIER));
            break;
        }
      return;
     }

y solo después de llegar al comienzo de nuestro episodio, pasaremos a las operaciones de muestreo de acciones. Al hacerlo, controlaremos la cantidad de acciones aleatorias realizadas. Su número no deberá exceder la duración máxima del episodio.

Si alcanzamos el número máximo de pasos, primero generaremos la acción de cierre de todas las posiciones,

   int act = (action_count < MaxSteps || first_order < MaxLifeTime ? SampleAction(4) : 2);

y después de un movimiento, inicializaremos la finalización del asesor.

   if(action_count > MaxSteps)
      ExpertRemove();

Después de completar la pasada en el simulador de estrategias, verificaremos la cantidad de beneficio obtenido como resultado de la pasada, y cuando se cumpla la condición de alcance del valor umbral de rentabilidad mínima, transmitiremos los datos para añadirlos a la base de datos de ejemplos.

//+------------------------------------------------------------------+
//| Tester function                                                  |
//+------------------------------------------------------------------+
double OnTester()
  {
//---
   double ret = 0.0;
//---
   double profit = TesterStatistics(STAT_PROFIT);
   action_count--;
   if(profit >= MinProfit)
      FrameAdd(MQLInfoString(MQL_PROGRAM_NAME), action_count, profit, Base);
//---
   return(ret);
  }

En el texto del artículo se muestran y explican solo algunos cambios menores en el código del asesor experto que describimos con detalle en el artículo anterior. Podrá familiarizarse con el código completo del asesor en el archivo adjunto.


3. Simulación

Al igual que en el artículo anterior, recopilaremos los ejemplos para entrenar el modelo usando los datos históricos del instrumento EURUSD en el marco temporal H1, solo que esta vez usaremos los datos históricos de 4 meses de 2023.

Periodo de entrenamiento

Para explorar el entorno de forma más efectiva, utilizaremos diversos valores de parámetros externos en el proceso de recopilación de los ejemplos. Al mismo tiempo utilizaremos dichos parámetros como parámetros optimizados, lo cual nos permitirá cambiar sus valores en cada pasada.

Para iniciar el proceso de optimización, seleccionaremos dos parámetros: MaxSteps y MaxLifeTime. El primer parámetro define la duración máxima del episodio tras la cual la recopilación de ejemplos se vuelve ineficaz. El segundo parámetro indica el periodo máximo de mantenimiento de una posición en un episodio. Usando varios valores de estos parámetros en el proceso de recopilación de ejemplos, podremos explorar el entorno de la forma más completa posible.

Por ejemplo, utilizando diferentes valores de MaxSteps y MaxLifeTime, podremos recopilar ejemplos para diferentes duraciones y periodos de mantenimiento de una posición. Esto nos permitirá obtener ejemplos de una amplia gama de situaciones que pueden surgir en el entorno. De esta forma, podremos crear un modelo de entrenamiento más versátil y eficiente que tendrá en cuenta muchos escenarios diferentes.

Parámetros de la primera pasada de optimización

Indicaremos un valor umbral de beneficio próximo a 0. Después de todo, esta es la primera pasada y nos bastará para obtener un pequeño beneficio.

Como resultado de la primera pasada del proceso de optimización, vemos varias pasadas exitosas con un beneficio de 46 USD en las primeras 2 semanas de enero de 2023. El factor de beneficio de estas pasadas alcanza el 1,55

Resultados de la primera optimización

Antes de comenzar la optimización, realizaremos algunos cambios en los parámetros. Para que las muestras se recopilen en diferentes intervalos temporales, añadiremos a nuestra variable optimizada la cantidad mínima de pasadas antes del muestreo. Los valores de esta variable variarán de 1 a 3 semanas en incrementos de una semana. Además, mejoraremos los resultados obtenidos aumentando el umbral de beneficio a 40 USD.

Parámetros de la segunda pasada de optimización

Según los resultados de la segunda pasada de optimización, vemos un aumento en el beneficio de hasta 84 USD para enero de 2023, aunque existe una disminución del factor de beneficio de hasta el 1,38.

Resultados de la segunda pasada de optimización

A pesar de ello, podemos ver que nuestros esfuerzos por agilizar el proceso de recogida de ejemplos comienza a dar sus frutos. Aunque todavía no hemos logrado el éxito final, la tendencia general de desarrollo está en línea con nuestros objetivos y expectativas. 

Vamos a aumentar el valor mínimo del número de pasadas antes del inicio del muestreo para la segunda semana de enero de 2023 y a realizar un proceso de optimización más. En esta ocasión aumentaremos el valor de rentabilidad mínima a 80 USD. Después de todo, nos estamos esforzando por encontrar la estrategia más rentable.

Parámetros de la tercera etapa de optimización

Como esperábamos, gracias a la posterior optimización de la recopilación de ejemplos, hemos logrado una rentabilidad aún mayor. Los ingresos totales de la pasada más exitosa han aumentado a 125 USD. Al mismo tiempo, el factor de beneficio ha disminuido ligeramente, ascendiendo a 1,36, lo cual sigue significando que el beneficio supera los costes. Debemos señalar que este aumento de rentabilidad se debe a la mejora en la recopilación de ejemplos, y podemos estar seguros de su efectividad. Sin embargo, hay que tener en cuenta que el proceso de aprendizaje aún no está completo y debemos continuarlo.

Resultados de la tercera etapa de optimización

Hemos proseguido con las iteraciones de recopilación de ejemplos en el modo de optimización del simulador de estrategias, cambiando sucesivamente el punto de inicio del muestreo y modificando el umbral de beneficio. Este enfoque nos ha permitido obtener ejemplos de varias pasadas exitosas a través de todo el conjunto de entrenamiento. La más rentable de ellas ha generado 281 dólares de ingresos con un factor de beneficio de 1,5. Estos resultados confirman que nuestra estrategia para optimizar el proceso de recopilación de ejemplos está teniendo un efecto positivo y nos está ayudando a conseguir mayores indicadores de beneficio. No obstante, entendemos que este proceso no está completo y requiere una mayor optimización y mejora.

Resultados de la recopilación de ejemplos

Una vez finalizado el proceso de recopilación de ejemplos, procederemos a entrenar el modelo con la ayuda del algoritmo Go-Explore usando como base los datos recibidos. Después de ello, entrenaremos nuevamente el modelo con métodos de aprendizaje por refuerzo para mejorar aún más su rendimiento.

Para verificar la calidad y eficiencia del modelo entrenado, lo probaremos con conjuntos de entrenamiento y prueba. Debemos señalar que nuestro modelo ha logrado obtener beneficios con los datos históricos de la primera semana de mayo de 2023, que no hemos incluido en la muestra de entrenamiento, pero la siguen de inmediato.

Muestra de prueba (mayo de 2023) Muestra de prueba (mayo de 2023)


Conclusión

En este artículo, hemos analizado métodos simples pero efectivos para optimizar el algoritmo Go-Explore; dichos métodos permiten usarlo para entrenar modelos con grandes cantidades de datos de entrenamiento. Nuestro modelo se ha entrenado con 4 meses de datos históricos, pero gracias al uso de métodos de la optimización, el algoritmo Go-Explore se puede utilizar para entrenar modelos durante periodos de tiempo más largos. También hemos probado el modelo con conjuntos de entrenamiento y prueba, lo cual ha confirmado su alta eficiencia y calidad.

En general, el algoritmo Go-Explore abre nuevas posibilidades para entrenar modelos con big data y puede convertirse en una poderosa herramienta para diversas aplicaciones en el campo de la inteligencia artificial.

No obstante lo dicho, debemos recordar que los mercados financieros son muy dinámicos y están sujetos a cambios repentinos, por lo que ni siquiera el modelo de mayor calidad puede garantizar el 100% de éxito. Por ello, deberemos monitorear constantemente los cambios en el mercado y adaptar nuestro modelo en consecuencia.


Enlaces

  1. Go-Explore: a New Approach for Hard-Exploration Problems
  2. Redes neuronales: así de sencillo (Parte 35): Módulo de curiosidad intrínseca (Intrinsic Curiosity Module)
  3. Redes neuronales: así de sencillo (Parte 36): Modelos relacionales de aprendizaje por refuerzo (Relational Reinforcement Learning)
  4. Redes neuronales: así de sencillo (Parte 37): Atención dispersa (Sparse Attention)
  5. Redes neuronales: así de sencillo (Parte 38): Exploración auto-supervisada por desacuerdo (Self-Supervised Exploration via Disagreement)
  6. Redes neuronales: así de sencillo (Parte 39): Go-Explore: un enfoque diferente sobre la exploración

Programas usados en el artículo

# Nombre Tipo Descripción
1 Faza1.mq5 Asesor Asesor de primera fase
2 Faza2.mql5 Asesor Asesor de segunda fase
3 GE-lerning.mq5 Asesor Asesor de ajuste preciso de políticas
4 Cell.mqh Biblioteca de clases Estructura de descripción del estado del sistema.
5 FQF.mqh Biblioteca de clases Biblioteca de clases de organización de modelos completamente parametrizada
6 NeuroNet.mqh Biblioteca de clases Biblioteca de clases para crear una red neuronal
7 NeuroNet.cl Biblioteca Biblioteca de código de programa OpenCL

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

Archivos adjuntos |
MQL5.zip (91.86 KB)
Características del Wizard MQL5 que debe conocer (Parte 6): Transformada de Fourier Características del Wizard MQL5 que debe conocer (Parte 6): Transformada de Fourier
La transformada de Fourier, introducida por Joseph Fourier, es un medio para descomponer puntos de datos de ondas complejos en componentes de ondas simples. Esta característica puede resultar útil para los tráders, así que hablaremos de ella en este artículo.
Implementando el algoritmo de aprendizaje ARIMA en MQL5 Implementando el algoritmo de aprendizaje ARIMA en MQL5
En este artículo, implementaremos un algoritmo que aplica un modelo autorregresivo de media móvil integrada (modelo Box-Jenkins) utilizando el método de minimización de la función de Powell. Box y Jenkins argumentaron que la mayoría de las series temporales se pueden modelar con una o ambas estructuras.
Redes neuronales: así de sencillo (Parte 41): Modelos jerárquicos Redes neuronales: así de sencillo (Parte 41): Modelos jerárquicos
El presente artículo describe modelos de aprendizaje jerárquico que ofrecen un enfoque eficiente para resolver problemas complejos de aprendizaje automático. Los modelos jerárquicos constan de varios niveles; cada uno de ellos es responsable de diferentes aspectos del problema.
Redes neuronales: así de sencillo (Parte 39): Go-Explore: un enfoque diferente sobre la exploración Redes neuronales: así de sencillo (Parte 39): Go-Explore: un enfoque diferente sobre la exploración
Continuamos con el tema de la exploración del entorno en los modelos de aprendizaje por refuerzo. En este artículo, analizaremos otro algoritmo: Go-Explore, que permite explorar eficazmente el entorno en la etapa de entrenamiento del modelo.