Русский Português
preview
Aplicación de la teoría de juegos a algoritmos comerciales

Aplicación de la teoría de juegos a algoritmos comerciales

MetaTrader 5Sistemas comerciales |
139 8
Yevgeniy Koshtenko
Yevgeniy Koshtenko

En un entorno en el que la rapidez en la toma de decisiones resulta fundamental y el mercado se caracteriza por un alto grado de incertidumbre, se requiere un enfoque diferente para el diseño de sistemas comerciales.

AdaptiveQ Enhanced es un asesor comercial desarrollado sobre la base del aprendizaje profundo por refuerzo (DQN), la teoría de juegos y el análisis causal. El asesor experto analiza el mercado simulando 531.441 estados únicos, considerando las interrelaciones entre los siete principales pares de divisas. El elemento clave del algoritmo es el equilibrio de Nash usado para seleccionar la estrategia óptima bajo la influencia mutua de los instrumentos.

La nueva versión del sistema cuenta con un conjunto ampliado de acciones: además de las operaciones estándar de compra y venta, se han añadido funciones de creación de posiciones y cierre selectivo de transacciones rentables. Esto garantiza la adaptabilidad y flexibilidad en distintos escenarios de mercado. El artículo analiza la aplicación práctica de estos enfoques en MQL5 y demuestra cómo la combinación de aprendizaje adaptativo, teoría de juegos e IA permite construir estrategias comerciales más precisas y sostenibles.


Antecedentes teóricos: del aprendizaje por refuerzo al equilibrio de Nash

Aprendizaje profundo por refuerzo (DQN)

Antes de sumergirnos en los aspectos técnicos del código, debemos sentar una base teórica. Nuestro sistema se basa en Deep Q-Network (DQN), una versión moderna del algoritmo de aprendizaje por refuerzo que ha demostrado su eficacia no solo en juegos, sino también en la resolución de problemas financieros complejos.

En el aprendizaje por refuerzo clásico, el agente (en nuestro caso, el sistema comercial) interactúa con el entorno (el mercado) realizando determinadas acciones (apertura/cierre de posiciones). Por cada acción, el agente recibe una recompensa y pasa a un nuevo estado. El objetivo del agente consiste en maximizar la recompensa agregada a lo largo del tiempo.

Matemáticamente, esto se expresa a través de una función Q que estima la utilidad esperada de la acción a en el estado s:

Q(s, a) = r + γ max Q(s', a')

donde r es la recompensa inmediata, γ es el factor de descuento (cuánto valoramos las recompensas futuras), s' es el nuevo estado y a' son las acciones posibles en el nuevo estado.


Teoría de juegos y equilibrio de Nash

Los sistemas comerciales tradicionales analizan cada instrumento de forma aislada. Nuestro enfoque es fundamentalmente distinto: nosotros aplicamos la teoría de juegos para explicar las interrelaciones entre pares de divisas.

El equilibrio de Nash es un estado en el que ningún jugador puede mejorar su resultado cambiando unilateralmente su estrategia. En el contexto de nuestro sistema, esto implica que encontramos la estrategia óptima para cada par de divisas, considerando las estrategias de todos los demás pares.

Esto se implementa en el código a través de la función DetermineActionNash(), que ahora trabaja con un espacio ampliado de seis acciones posibles. Cada acción se evalúa no solo según los datos de un par de divisas concreto, sino también considerando las correlaciones con otros instrumentos:

void DetermineActionNash(int symbolIdx) {
   double actionScores[TOTAL_ACTIONS];
   
   // Получаем базовые оценки действий из Q-матрицы
   for(int action = 0; action < TOTAL_ACTIONS; action++) {
      actionScores[action] = qMatrix[tradeStates[symbolIdx].currentStateIdx][action][symbolIdx];
   }
   
   // Корректировка на основе корреляции с другими символами (Нэш)
   for(int otherIdx = 0; otherIdx < TOTAL_SYMBOLS; otherIdx++) {
      if(otherIdx != symbolIdx) {
         double corr = correlationMatrix[symbolIdx][otherIdx];
         
         for(int action = 0; action < TOTAL_ACTIONS; action++) {
            double otherScore = qMatrix[tradeStates[otherIdx].currentStateIdx][action][otherIdx];
            // Учитываем корреляцию только если есть значимая связь
            if(MathAbs(corr) > 0.3) {
               actionScores[action] += corr * otherScore * 0.05;
            }
         }
      }
   }

Preste atención al ajuste fino: la correlación solo se tiene en cuenta si su valor absoluto es superior a 0,3. Esto le permite filtrar el "ruido" y centrarse en las relaciones realmente significativas entre pares de divisas.



Inferencia causal en un espacio de acción multidimensional

En AdaptiveQ Enhanced, nuestro sistema ha recibido un arsenal ampliado de posibles acciones:

  1. Abrir una posición de compra
  2. Apertura de posición de venta
  3. Añadir volumen a las posiciones de compra existentes
  4. Añadir volumen a las posiciones de venta existentes
  5. Cerrar solo las posiciones de compra rentables
  6. Cerrar solo las posiciones de venta rentables

Y esto enriquece considerablemente el potencial estratégico del sistema. Ahora no solo podemos abrir y cerrar posiciones, sino también aumentar los volúmenes cuando la tendencia se desarrolla en la dirección correcta, además de fijar beneficios de forma selectiva, dejando abiertas las posiciones no rentables en previsión de una inversión del mercado.

Resulta especialmente interesante la implementación del cierre solo de posiciones rentables, pues este mecanismo permite al sistema fijar beneficios sin realizar pérdidas, lo que mejora significativamente la rentabilidad global:

void ClosePositionsByTypeIfProfitable(string symbol, ENUM_POSITION_TYPE posType) {
   CTrade trade;
   CPositionInfo pos;
   
   for(int i = PositionsTotal() - 1; i >= 0; i--) {
      if(pos.SelectByIndex(i)) {
         if(pos.Symbol() == symbol && pos.PositionType() == posType) {
            double profit = pos.Profit();
            
            // Закрываем только если позиция в прибыли
            if(profit > 0) {
               trade.PositionClose(pos.Ticket());
            }
         }
      }
   }
}



Implementación técnica: la anatomía de AdaptiveQ Enhanced

Enorme espacio de estados y análisis multinivel

Una de las principales características de nuestro sistema es su enorme espacio de estados (nada menos que 531.441 estados únicos). Esto hace posible un análisis detallado de las condiciones del mercado y permite al sistema adaptarse a una amplia gama de escenarios.

En la versión actualizada, cada Estado resulta aún más informativo. Ahora el sistema analiza el mercado no solo en el marco temporal actual, sino simultáneamente en tres marcos temporales distintos: M15, H1 y H4. Este enfoque de marco temporal múltiple permite a AdaptiveQ Enhanced obtener una visión completa de la dinámica del mercado, desde las fluctuaciones a corto plazo hasta las tendencias a medio plazo.

Para cada marco temporal, el sistema monitorea toda una serie de parámetros:

  • La diferencia entre el precio y 20 medias móviles (MA10 a MA200)
  • Las banderas binarias sobre la posición del precio en relación con los niveles clave de la MA
  • Los valores de los indicadores técnicos RSI y Stochastic
  • El impulso (momentum) del movimiento de los precios

Todos estos datos se convierten en un índice de estado único, que luego se usa para referirse a la matriz Q:

int ConvertToStateIndex(MarketState &state) {
   double range = state.price_high - state.price_low;
   if(range == 0) range = 0.0001;
   
   // Базовые компоненты из цен
   int o_idx = (int)((state.price_open - state.price_low) / range * 9);
   int c_idx = (int)((state.price_close - state.price_low) / range * 9);
   int m_idx = (int)((state.momentum + 0.001) / 0.002 * 9);
   
   // Базовый индекс из основных компонентов
   int stateIdx = o_idx * 81 + c_idx * 9 + m_idx;
   
   // Добавляем компоненты из разницы с MA для текущего таймфрейма
   int ma_idx = 0;
   for(int i = 0; i < 10; i++) {
      int diff_idx = (int)((state.ma_diff[i] + 0.01) / 0.02 * 9);
      diff_idx = MathMin(MathMax(diff_idx, 0), 8);
      ma_idx += diff_idx * (int)MathPow(9, i % 3);
   }
   
   // Добавляем компоненты из индикаторов для каждого таймфрейма
   ulong tf_state = 0;
   
   for(int tfIdx = 0; tfIdx < TOTAL_TIMEFRAMES; tfIdx++) {
      // RSI: 0-100 -> 0-9
      int rsi_idx = (int)(state.tf_rsi[tfIdx] / 10);
      rsi_idx = MathMin(MathMax(rsi_idx, 0), 9);
      tf_state = tf_state * 10 + rsi_idx;
      
      // Stochastic %K: 0-100 -> 0-9
      int stoch_k_idx = (int)(state.tf_stoch_k[tfIdx] / 10);
      stoch_k_idx = MathMin(MathMax(stoch_k_idx, 0), 9);
      tf_state = tf_state * 10 + stoch_k_idx;
      
      // Бинарные флаги для MA: выбираем ключевые МА (10, 50, 100, 200)
      int ma_flags = 0;
      ma_flags |= state.tf_ma_above[tfIdx][0] << 0;  // MA10
      ma_flags |= state.tf_ma_above[tfIdx][4] << 1;  // MA50
      ma_flags |= state.tf_ma_above[tfIdx][9] << 2;  // MA100
      ma_flags |= state.tf_ma_above[tfIdx][19] << 3; // MA200
      tf_state = tf_state * 16 + ma_flags;
   }
   
   // Хэшируем вместе базовый индекс и индикаторы
   ulong hash = stateIdx + ma_idx + (ulong)tf_state;
   
   // Приводим к диапазону TOTAL_STATES через хэш
   return (int)(hash % TOTAL_STATES);
}

Eche un vistazo a esta función. Aquí se produce una transformación sorprendente: el espacio multidimensional de los parámetros del mercado se convierte en un identificador de estado único. Es como si creáramos un mapa multidimensional del mercado en el que cada punto se corresponde con una combinación concreta de precios e indicadores y, a continuación, lo convirtiéramos en un índice unidimensional usando una función hash.

Almacenamiento en la caché y optimización del rendimiento

Dada la complejidad computacional del sistema, hemos prestado especial atención a la optimización. La nueva versión añade el almacenamiento en la caché no solo de los precios y las correlaciones, sino también de los valores de todos los indicadores utilizados:

// Кэш для цен и корреляций (оптимизация быстродействия)
double bidCache[TOTAL_SYMBOLS], askCache[TOTAL_SYMBOLS];
double correlationMatrix[TOTAL_SYMBOLS][TOTAL_SYMBOLS];
double pointCache[TOTAL_SYMBOLS]; // Кэш для Point

// Кэш для индикаторов
double maCache[TOTAL_SYMBOLS][10];
double maTFCache[TOTAL_SYMBOLS][TOTAL_TIMEFRAMES][20];
int maAboveCache[TOTAL_SYMBOLS][TOTAL_TIMEFRAMES][20];
double rsiCache[TOTAL_SYMBOLS][TOTAL_TIMEFRAMES];
double stochKCache[TOTAL_SYMBOLS][TOTAL_TIMEFRAMES];
double stochDCache[TOTAL_SYMBOLS][TOTAL_TIMEFRAMES];
Además, ahora el sistema guarda los manejadores de los indicadores entre llamadas, lo cual evita crearlos varias veces:
// Хендлы для индикаторов, чтобы избежать многократного создания
int rsiHandles[TOTAL_SYMBOLS][TOTAL_TIMEFRAMES];
int stochHandles[TOTAL_SYMBOLS][TOTAL_TIMEFRAMES];
Y para ahorrar recursos informáticos, hemos añadido un mecanismo de actualización periódica de los indicadores:

// Время последнего обновления индикаторов
datetime lastMAUpdate = 0;
datetime lastIndicatorsUpdate = 0;
int indicatorUpdateInterval = 60; // Обновлять индикаторы каждую минуту

void UpdateIndicatorsCache() {
   datetime currentTime = TimeCurrent();
   if(currentTime - lastIndicatorsUpdate < indicatorUpdateInterval) return;
   
   // ... код обновления индикаторов ...
   
   lastIndicatorsUpdate = currentTime;
}

Esta técnica puede parecer trivial, pero en la práctica ofrece un aumento significativo del rendimiento, lo que resulta fundamental para un sistema que trabaja simultáneamente con siete pares de divisas en tres marcos temporales.

Aprendizaje adaptativo con un mecanismo de coste de oportunidad

El corazón de nuestro sistema es el mecanismo de aprendizaje adaptativo, que ahora es todavía más avanzado. A diferencia del Q-learning clásico, el AdaptiveQ Enhanced utiliza el concepto de coste de oportunidad (opportunity cost), que permite al sistema aprender más rápido de sus errores.

Cuando el sistema toma una decisión, no solo evalúa la recompensa real de la acción seleccionada, sino que también simula el resultado potencial de acciones alternativas. Si resulta que una acción distinta podría haber reportado mayores beneficios, el sistema ajustará su estrategia de forma más agresiva:
// Проверяем, привело ли действие к убытку и можно ли было получить прибыль с альтернативным действием
bool wasLoss = reward < 0;
bool couldProfit = tradeStates[symbolIdx].alternativeReward > 0 && tradeStates[symbolIdx].opportunityCost < 0;

// Применяем адаптивную скорость обучения для случаев упущенной выгоды
if(wasLoss && couldProfit) {
   // Увеличиваем скорость обучения для быстрой адаптации к неправильным решениям
   double adaptiveLearningRate = MathMin(learningRate * adaptiveMultiplier, 0.9);
   
   // Дополнительно уменьшаем Q-значение пропорционально упущенной выгоде
   newQ -= adaptiveLearningRate * MathAbs(tradeStates[symbolIdx].opportunityCost) * opportunityCostWeight;
}

Esto resulta similar a cómo un tráder experimentado no solo aprende de sus errores, sino que también analiza las oportunidades perdidas, ajustando su estrategia de forma más agresiva cuando ve que una solución alternativa habría sido mucho mejor. Con el parámetro adaptiveMultiplier, el usuario puede configurar la intensidad con la que el sistema aprende de las oportunidades perdidas.

Otro aspecto innovador del aprendizaje es la influencia causal entre pares de divisas:

// Обновляем Q-значения для других символов на основе корреляции (каузальное обучение)
for(int otherSymbol = 0; otherSymbol < TOTAL_SYMBOLS; otherSymbol++) {
   if(otherSymbol != symbolIdx) {
      double corr = correlationMatrix[symbolIdx][otherSymbol];
      
      // Применяем обновление только если корреляция значима
      if(MathAbs(corr) > 0.2) {
         qMatrix[tradeStates[symbolIdx].previousStateIdx][tradeStates[symbolIdx].previousAction][otherSymbol] += 
            learningRate * reward * corr * 0.1;
      }
   }
}

Cuando el sistema adquiere experiencia en un par de divisas, puede transferirla a otros instrumentos relacionados, considerando el grado de correlación entre ellos. Se crea así un efecto de "aprendizaje cruzado" que acelera sustancialmente el proceso de adaptación del sistema a las condiciones del mercado.


Aspectos prácticos del uso de AdaptiveQ Enhanced

Capacidades avanzadas de personalización y gestión de riesgos

AdaptiveQ Enhanced ofrece una impresionante gama de parámetros para configurar el sistema a las preferencias de cada tráder:

input OPERATION_MODE OperationMode = MODE_LEARN_AND_TRADE; // Режим работы системы
input CLOSE_STRATEGY CloseStrategy = STRATEGY_CLOSE_ALL;   // Стратегия закрытия
input POSITION_MODE PositionMode = MODE_MULTI;             // Режим позиций

input double TradeVolume = 0.01;        // Базовый объем сделки
input double AddVolumePercent = 50.0;   // Процент от базового объема для добавления к позиции
input int TakeProfit = 2500;            // Take Profit (пункты)
input int StopLoss = 1500;              // Stop Loss (пункты)

input double LearningRate = 0.1;         // Скорость обучения
input double DiscountFactor = 0.9;       // Фактор дисконтирования
input double AdaptiveMultiplier = 1.5;   // Множитель адаптивной скорости обучения
input double OpportunityCostWeight = 0.2; // Вес упущенной выгоды

input int MaxPositionsPerSymbol = 5;     // Максимальное количество позиций на один символ

El sistema puede funcionar en tres modos de posiciones: MODE_SINGLE permite solo una posición por símbolo, MODE_MULTI permite hasta MaxPositionsPerSymbol posiciones unidireccionales, y MODE_OPPOSITE permite tener posiciones simultáneas en direcciones opuestas.

Especial atención merece el parámetro AddVolumePercent, que define cuánto volumen se añadirá a la posición existente durante las acciones ACTION_ADD_BUY y ACTION_ADD_SELL. Esto ofrece la oportunidad de aplicar una estrategia de creación de posiciones en la que el sistema añade volumen en la dirección de una tendencia acertada.

Gestión inteligente de posiciones

La posibilidad de cerrar selectivamente solo las posiciones rentables es una de las innovaciones más interesantes de AdaptiveQ Enhanced. Esto permite al sistema fijar los beneficios y dar a las posiciones perdedoras la oportunidad de recuperarse:

case ACTION_CLOSE_PROFITABLE_BUYS:
   if(tradeStates[symbolIdx].buyPositions > 0) {
      // Закрываем только прибыльные позиции BUY
      ClosePositionsByTypeIfProfitable(symbol, POSITION_TYPE_BUY);
      tradeStates[symbolIdx].actionSuccessful = true;
   }
   break;

Combinado con la capacidad de abrir múltiples posiciones, esto crea una dinámica interesante: el sistema puede acumular posiciones gradualmente cuando se desarrolla una tendencia y, a continuación, fijar parcialmente los beneficios a los primeros signos de retroceso, manteniendo algunas posiciones para una posible continuación del movimiento.

Guardado periódico y carga del modelo entrenado

Lo más destacado de nuestro sistema sigue siendo su capacidad de almacenar y cargar una matriz Q entrenada. En la nueva versión, este mecanismo resulta aún más robusto, gracias al guardado automático periódico:

void CheckAndSaveQMatrix() {
   if(IsNewBar() && OperationMode == MODE_LEARN_AND_TRADE) {
      Print("Периодическое сохранение Q-матрицы...");
      SaveQMatrix();
   }
}

El sistema comprueba la aparición de una nueva barra y guarda periódicamente los conocimientos acumulados, lo cual protege contra la pérdida de datos de entrenamiento en caso de finalización inesperada.

Así funciona todo el sistema:



Conclusión: nuevos horizontes para el trading algorítmico

El asesor experto AdaptiveQ Enhanced no es una herramienta más para el trading algorítmico, sino un enfoque fundamentalmente nuevo del análisis y la previsión de los mercados financieros. Combinando el aprendizaje profundo por refuerzo, la teoría de juegos y la inferencia causal con un avanzado arsenal de acciones comerciales y análisis de múltiples marcos temporales, hemos creado un sistema capaz de captar las complejas relaciones entre distintos pares de divisas y tomar decisiones comerciales óptimas.

El mecanismo de la tasa de aprendizaje adaptativa ha demostrado ser especialmente eficaz a la hora de contabilizar la pérdida de beneficios. Cuando el sistema toma una decisión equivocada y una acción alternativa podría haber resultado rentable, aumenta la tasa de aprendizaje según el AdaptiveMultiplier (1,5 veces por defecto). Se trata de una especie de "lección con mayor intensidad": el sistema aprende más rápido de sus errores que de sus aciertos, lo cual también concuerda con la psicología humana.

El futuro del trading algorítmico reside precisamente en el ámbito de los sistemas adaptativos que pueden aprender y evolucionar con el mercado. Y AdaptiveQ Enhanced no es solo un experimento, sino una herramienta de trabajo que abre nuevos horizontes a la investigación y el desarrollo. El código presentado en este artículo está disponible para su experimentación y mejora por parte de los usuarios. Invito a la comunidad MQL5 a participar en el desarrollo de este concepto y en la creación de sistemas comerciales aún mejores basados en la inteligencia artificial y la teoría de juegos.

El mundo de las finanzas es cada vez más complejo e interconectado, y solo los sistemas capaces de absorber y adaptarse a esta complejidad podrán competir con éxito en los mercados del futuro. AdaptiveQ Enhanced supone un paso en esa dirección, un paso hacia un trading algorítmico más inteligente, más adaptable y, en última instancia, más rentable.

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

Archivos adjuntos |
Casual_DQN_Nash.mq5 (93.44 KB)
Maxim Dmitrievsky
Maxim Dmitrievsky | 29 mar 2025 en 03:16

Cosa original, estoy rebosante de deleite como de un objeto de arte, gracias :) Pero es deseable probarlo en garrapatas reales, porque es superficial con ofertas.

osmo1717
osmo1717 | 29 mar 2025 en 06:54
La teoría de juegos es buena en el póquer
Ваня Викторов
Ваня Викторов | 2 abr 2025 en 09:01

Saludos, estoy muy interesado en su proyecto, pero soy nuevo en este campo. No puedo entender cómo ejecutar el Asesor Experto en el probador de estrategias. Según tengo entendido es imposible configurarlo completamente y entrenarlo a través del tester? ¿O estoy haciendo algo mal? Agradecería el SO

Alexey Viktorov
Alexey Viktorov | 2 abr 2025 en 09:47
Ваня Викторов probador de estrategias. Según tengo entendido es imposible configurarlo completamente y entrenarlo a través del tester? ¿O estoy haciendo algo mal? Agradecería el SO

¿Dónde tengo parientes en los Países Bajos? 👀

Ваня Викторов
Ваня Викторов | 2 abr 2025 en 10:54
Alexey Viktorov #:

Cómo es que tengo parientes en Holanda 👀.

Ahahahahah, no en los Países Bajos)))) VPN es una cosa)))))


PS: línea de fondo en el probador de estrategia es posible ejecutar la formación o no? Según la captura de pantalla del gráfico de balance es un probador de estrategias, pero haga lo que haga ni me acerco al + en él

Utilizando redes neuronales en MetaTrader Utilizando redes neuronales en MetaTrader
En el artículo se muestra la aplicación de las redes neuronales en los programas de MQL, usando la biblioteca de libre difusión FANN. Usando como ejemplo una estrategia que utiliza el indicador MACD se ha construido un experto que usa el filtrado con red neuronal de las operaciones. Dicho filtrado ha mejorado las características del sistema comercial.
Arbitraje de swaps en Forex: Reunimos un portafolio sintético y creamos un flujo de swaps estable Arbitraje de swaps en Forex: Reunimos un portafolio sintético y creamos un flujo de swaps estable
¿Quiere saber cómo aprovechar los spreads de los tipos de interés? En este artículo, veremos cómo usar el arbitraje de swaps en Forex para generar unos ingresos constantes cada noche construyendo un portafolio resistente a las fluctuaciones del mercado.
Particularidades del trabajo con números del tipo double en MQL4 Particularidades del trabajo con números del tipo double en MQL4
En estos apuntes hemos reunido consejos para resolver los errores más frecuentes al trabajar con números del tipo double en los programas en MQL4.
Automatización de estrategias de trading en MQL5 (Parte 11): Desarrollo de un sistema de negociación de cuadrícula multinivel Automatización de estrategias de trading en MQL5 (Parte 11): Desarrollo de un sistema de negociación de cuadrícula multinivel
En este artículo, desarrollamos un sistema EA de trading de cuadrícula multinivel utilizando MQL5, centrándonos en la arquitectura y el diseño del algoritmo que hay detrás de las estrategias de trading de cuadrícula. Exploramos la implementación de una lógica de red multicapa y técnicas de gestión de riesgos para hacer frente a las condiciones variables del mercado. Por último, ofrecemos explicaciones detalladas y consejos prácticos para guiarle en la creación, prueba y perfeccionamiento del sistema de negociación automatizado.