Arbitraje estadístico mediante reversión a la media en el trading de pares: Cómo superar al mercado con matemáticas
Introducción
“Puedo calcular el movimiento de los cuerpos celestes, pero no la locura de las personas.” (Sir Isaac Newton, a los noventa años, tras perder casi todos sus ahorros de jubilación invirtiéndolos en la bolsa).
El 10 de mayo del año pasado, el mundo perdió a Jim Simons, el gestor de fondos de cobertura más exitoso de todos los tiempos.
Jim Simons fue un matemático reconocido, con varios reconocimientos y logros académicos en geometría diferencial y criptografía. Sin embargo, su papel en el análisis financiero cuantitativo hizo que su nombre fuera famoso incluso entre personas no interesadas en las matemáticas o las finanzas.
Fue objeto de varias biografías, docenas de libros sobre su vida y carrera, cientos de programas de televisión y miles de artículos y publicaciones de blogs en todo el mundo. The Man Who Solved the Market: How Jim Simons Launched the Quant Revolution es su biografía más famosa.
A principios de los años ochenta, Simons fundó Renaissance Technologies (RenTech) y comenzó a reunir un equipo de «matemáticos, físicos, expertos en procesamiento de señales y estadísticos» altamente cualificados. Tras décadas de trabajo conjunto, demostraron que, con suficientes datos y potencia computacional para encontrar patrones estadísticos y anomalías en dichos patrones, el mercado podía «ser vencido por las matemáticas».
«En 1988, la empresa creó su cartera más rentable, el fondo Medallion, que utilizaba una versión mejorada y ampliada de los modelos matemáticos de Leonard Baum, perfeccionados por el algebraista James Ax, para explorar correlaciones de las que pudiera obtener beneficios». (Wikipedia)
El fondo Medallion obtuvo una rentabilidad media anual del 66 % entre 1988 y 2018, lo que supuso más de 104 000 millones de dólares en beneficios comerciales en estas tres décadas. El fondo Medallion de RenTech sigue activo hoy en día y generando grandes ganancias. Como es de esperar, a muchas personas les gustaría saber cómo funcionan, los detalles, el algoritmo secreto, el código de trucos... lo que sea. Pero, hasta donde sabe cualquier ser humano mortal, su salsa secreta se conserva como un acuerdo corporativo de alto secreto. Cuando el autor de su biografía le preguntó sobre la estrategia operativa de Medallion, Simons respondió con la misma respuesta lacónica que daría a varios entrevistadores en los años siguientes: arbitraje estadístico a nivel de cartera. También reveló que han estado utilizando “una especie de aprendizaje automático” desde el principio para encontrar las anomalías del mercado.
El arbitraje estadístico es, en sí mismo, un amplio campo de investigación. Cuando le añadimos aprendizaje automático, el comerciante minorista promedio sin una sólida formación en matemáticas y estadística queda excluido. Y ni hablar del trader novato. Pero, si bien es cierto que es realmente difícil y se requieren muchos recursos para implementar un arbitraje estadístico a nivel de cartera con todas las funciones y potenciado por el aprendizaje automático sin todo ese conocimiento, también es cierto que es perfectamente posible entender qué es el arbitraje estadístico a nivel de cartera, cómo funciona y, lo que es más importante: es posible empezar de a poco con paciencia, trabajo duro y tiempo para crecer.
Este artículo no es de ninguna manera un intento de reproducir, o peor aún, “revelar el código secreto” de RenTech/Jim Simons. Como se dijo anteriormente, eso sería imposible para cualquiera que no estuviera directamente involucrado en sus operaciones. Es un esfuerzo por compartir con ustedes mi comprensión de los principios generales que impulsan sus modelos. Estos principios pueden informar el sistema comercial incluso del comerciante minorista más humilde. La diferencia estará en la escala de los resultados, que será proporcional a la cantidad de recursos invertidos en el sistema y sus operaciones.
Así pues, lo que leeréis a continuación es el resultado de una investigación en libros, documentales en vídeo y comunidades especializadas de internet, fusionada con mi experiencia personal de algunos años en el segmento financiero (más en el lado empresarial que en el lado desarrollador). Lo que hace RenTech es enorme, pero lo que veremos aquí es una miniatura, digamos, una figura de acción de un superhéroe, una maqueta de un rascacielos.
El objetivo es contribuir con un método de análisis de bajo costo, liviano y fácil de desarrollar que pueda ser probado y mejorado por el trader minorista promedio usando solo las herramientas ya disponibles en la plataforma MetaTrader 5 que se ejecuta en un portátil de consumo de materias primas, posiblemente un portátil de gama baja. El método debería ser útil tanto para el trader algorítmico como para el trader discrecional. Comenzaremos con la configuración más sencilla, lo justo para describir el proceso.
Después de comprender los conceptos generales detrás del modelo, construiremos una cartera mínima para la forma más simple de arbitraje estadístico, lo negociaremos en modo automático con un Asesor Experto, tomaremos algunas notas sobre los resultados y, finalmente, pensaremos en los próximos pasos necesarios. Espero que esta experiencia pueda ayudarte a iniciarte en esta potente técnica de trading y poder ampliar posteriormente estos conocimientos, incorporando otros símbolos al portfolio y probando otros algoritmos más allá del aquí descrito, para ir construyendo progresivamente tu propia estrategia StatArb completa y adecuada a tus recursos y objetivos.
Conceptos generales detrás del modelo
Antes de crear RenTech, Jim Simons trabajó como descifrador de códigos para la inteligencia estadounidense durante la Guerra Fría. Cuando comenzó a operar en los mercados financieros, intentó predecir los precios de las acciones y las materias primas y fracasó. Luego cambió su enfoque. Supuso que nunca sería capaz de anticipar el futuro del mercado. Comprendió que tenía que aceptar que el mercado era un enigma. Éste es el primer concepto relevante detrás del modelo.
El otro concepto es que el mercado está en un estado continuo de cambio. Es decir, no existen mercados alcistas o bajistas, patrones de velas/barras o “acciones correlacionadas que funcionan bien juntas”. Todo está cambiando ahora y para siempre.
Si piensas por un segundo verás que ambos conceptos se pasan por alto.
El mercado es un enigmaEl mercado es un enigma, pero a diferencia de aquella máquina Enigma de la Segunda Guerra Mundial cuyo código fue descifrado por Alan Turing y su equipo, el enigma del mercado no tiene un algoritmo determinista que pueda ser diseñado a la inversa y descifrado. Entre la entrada y la salida pueden ocurrir eventos inesperados. Si bien el aumento de las tasas de interés por parte de un banco central tiene el efecto esperado de fortalecer la moneda de ese país, el estallido de un conflicto político en otro país distante puede tener el efecto contrario, contrarrestando el aumento de las tasas de interés al disminuir su impacto, anularlo o incluso debilitar esa moneda.
El mercado es un enigma porque, entre la entrada y la salida, está la irracionalidad de los agentes económicos, el carácter imprevisible de la política y el aspecto caótico de la interacción entre las fuerzas que lo impulsan. Entre el mercado del oro que se mantiene alcista durante un año y su caída en picada de un mes la semana siguiente, existe un comportamiento humano. No fue por otra razón que un psicólogo, Daniel Kahneman, recibió el Premio Nobel de Ciencias Económicas. Porque aborda precisamente esta cuestión.Aunque el mercado es un enigma gobernado por agentes económicos irracionales dentro de un entorno caótico, los bancos de inversión compran y venden acciones basándose en modelos financieros, los fondos de cobertura utilizan Black-Scholes para evaluar opciones y casi todos los grandes actores del mercado gastan millones de dólares en el desarrollo de estrategias de trading cuantitativo. ¿Por qué? Porque funciona, por supuesto. ¿Por qué funciona si el mercado es imprevisible, impredecible, irracional y caótico?
Jim Simons, junto con miles de otros exitosos traders cuantitativos, algorítmicos y discrecionales, tiene la respuesta más sincera a esta pregunta. Una lección que cualquier aspirante a trader debería recitar como mantra cada mañana antes de entrar al mercado:
Pero con o sin el uso de modelos financieros, cualquier estrategia comercial puede funcionar bastante bien durante un tiempo, un período de tiempo desconocido. Puede ser rentable para un día, para un mes, para un año…, no lo sabemos. La única garantía es que funcionó en el pasado y fue rentable en esos símbolos, período y marco temporal, con esos valores de parámetros utilizados en la prueba retrospectiva. Puede dejar de ser rentable en el siguiente minuto, en la primera ejecución, o puede funcionar para siempre. Una vez más, no lo sabemos. No podemos saberlo, porque el mercado es un enigma. No podemos resolver este enigma. No existe ningún código que descifrar. Sólo existe un estado continuo de cambio.
El mercado está en un estado continuo de cambio.
El mercado está cambiando todo el tiempo. La única constante en el mercado es el cambio. Los valores de nuestros parámetros se eligen no porque sean los más adecuados para un estado específico del mercado, sino porque fueron los más adecuados para un cambio específico del mercado. Entre el momento en el que colocamos una orden ganadora y el momento en el que la orden se cerró, el mercado cambió de la manera que esperábamos. Por el contrario, entre el momento en el que colocamos una orden perdedora y el momento en el que la orden se cerró, el mercado cambió de una manera que no esperábamos. Esto es cierto incluso si no podemos decir qué cambio contribuyó más al resultado final.
Para ser claros: nunca podremos identificar el cambio preciso que convirtió una estrategia rentable en una fuente de dinero o viceversa. Para mejorar una estrategia comercial, lo que haremos es buscar un patrón para aumentar las probabilidades de repetir las decisiones correctas cuando enfrentemos cambios similares en el estado del mercado en el futuro. Encontrar, aprender y comprender estos patrones es lo que hace un trader experimentado en meses o años de operar con el mismo activo o grupo de activos. No es por ninguna otra razón que tenemos diarios comerciales. Se trata de registrar cuáles eran nuestras suposiciones sobre los cambios esperados del mercado y poder revisarlas posteriormente para mejorar nuestras suposiciones.
Gracias al gran volumen de datos disponibles hoy en día y a los potentes ordenadores para procesarlos, podemos acortar estos años de aprendizaje de búsqueda de patrones a horas o incluso minutos. Podemos automatizar la recopilación de datos, el análisis y la ejecución comercial. Podemos automatizar las pruebas y los informes. Incluso podemos automatizar la elección del símbolo/activo a comercializar y la estrategia a utilizar entrenando un modelo integral de aprendizaje automático para aprender esos patrones. Con una cantidad adecuada de recursos en dinero, gente calificada y tiempo, sí podemos.
Pero, como se mencionó anteriormente, estas notas se centran en el trader minorista promedio. Con estos dos principios simples, aunque poco conocidos, en mente, veamos cómo podemos empezar a comprender qué es StatArb y cómo funciona.
Construyendo la cartera
Debido a que el mercado es un enigma en continuo estado de cambio, construiremos nuestra cartera sin preconcepciones, no haremos suposiciones sobre lo que suponemos que es cierto y la actualizaremos periódicamente. El intervalo de actualización estará determinado por la estrategia comercial y limitado por la potencia computacional.
Debemos tener en cuenta que la construcción de carteras, o la gestión de carteras, es un campo de investigación amplio en sí mismo. Según una revisión exhaustiva de la literatura académica, hace diez años existían al menos cuatro enfoques principales para construir una cartera de arbitraje estadístico de negociación por pares: distancia, cointegración, series de tiempo y control estocástico. Además de estos cuatro enfoques principales, el autor también identificó otros enfoques que incluyen aprendizaje automático, pronósticos combinados, cópula y análisis de componentes principales.
Para mantener nuestro enfoque en ser simples y fundamentales, comencemos con una cartera simple de operaciones de pares. Para algunos autores, el trading de pares es un subconjunto del arbitraje estadístico; para otros, “se asume ampliamente que el trading de pares es el “antepasado” del arbitraje estadístico”, siendo la diferencia el tamaño de la cartera y la complejidad de los algoritmos estadísticos. Como su nombre lo indica, el trading de pares está limitado a dos valores, mientras que el arbitraje estadístico puede involucrar docenas, incluso cientos de símbolos para ser rastreados y eventualmente comercializados.
El trading de pares, como probablemente ya sabes, no es nada más que dar dos valores con precios históricos correlacionados o cointegrados, vender simultáneamente el valor con tendencia alcista y comprar el valor con tendencia bajista cuando el diferencial histórico entre sus precios se amplía más allá de un umbral elegido. El supuesto subyacente es que los precios “volverán a la media”, convergiendo alrededor del diferencial de precios histórico.
En un arbitraje estadístico completo, no estamos limitados a la correlación o cointegración entre precios. Dado que nuestro objetivo principal en este artículo es simplificar las complejidades del arbitraje estadístico para el trader minorista promedio, comenzaremos a recopilar datos históricos para construir una cartera mínima de trading de pares para el mercado de divisas. Más adelante se podrá ampliar a otros mercados y otras relaciones estadísticas más allá de la correlación de precios.
Elija un grupo de valores para comenzarAl momento de escribir esto, mi cuenta de terminal MetaTrader 5 informa que hay más de diez mil símbolos disponibles. En nuestro análisis utilizaremos la integración de Python para Metatrader 5.
print("Total symbols =",mt5.symbols_total()) # display all symbols Total symbols = 10563Entonces, por razones prácticas, primero necesitamos elegir un subconjunto de todos los símbolos disponibles. Comencemos con los pares XAU.
# get symbols containing XAU in their names xau_symbols=mt5.symbols_get("*XAU*") print('len(*XAU*): ', len(xau_symbols)) for s in xau_symbols: print(s.name) len(*XAU*): 6 XAUUSD XAUEUR XAUAUD * XAUG XAUCHF XAUGBP
* XAUG es un ETF, por lo que podemos excluirlo por ahora y centrarnos en los otros cinco pares. Veamos cómo se correlaciona cada uno con el XAUUSD.
Ahora necesitamos calcular su correlación histórica de precios. En un escenario real, podríamos querer explorar todas las permutaciones posibles entre los símbolos elegidos, posiblemente cientos de símbolos bursátiles, porque asumimos que no tenemos conocimiento sobre ellos. Pero aquí los filtraremos para ver solo la correlación de precios entre la cotización del oro en dólares estadounidenses (XAUUSD) y la cotización del oro en euros, dólares australianos, francos suizos y libras esterlinas británicas.Queremos datos de los precios de cierre diarios de un año desde el día actual, lo que supone aproximadamente 250 días de negociación para los mercados de divisas.
# get 250 D1 bars from the current day xauusd_rates = mt5.copy_rates_from_pos("XAUUSD", mt5.TIMEFRAME_D1, 0, 250) xaueur_rates = mt5.copy_rates_from_pos("XAUEUR", mt5.TIMEFRAME_D1, 0, 250) xauaud_rates = mt5.copy_rates_from_pos("XAUAUD", mt5.TIMEFRAME_D1, 0, 250) xauchf_rates = mt5.copy_rates_from_pos("XAUCHF", mt5.TIMEFRAME_D1, 0, 250) xaugbp_rates = mt5.copy_rates_from_pos("XAUGBP", mt5.TIMEFRAME_D1, 0, 250) (...) # calculate correlation coefficients import numpy as np usd_eur_corr = np.corrcoef(xauusd_close['close'], xaueur_close['close']) usd_aud_corr = np.corrcoef(xauusd_close['close'], xauaud_close['close']) usd_chf_corr = np.corrcoef(xauusd_close['close'], xauchf_close['close']) usd_gbp_corr = np.corrcoef(xauusd_close['close'], xaugbp_close['close'])
Esto nos dará los siguientes resultados:
| Correlación XAUUSD (Pearson) | |
|---|---|
| XAUEUR | 0.9692368 |
| XAUAUD | 0.96677962 |
| XAUCHF | 0.8418827 |
| XAUGBP | 0.90490282 |
Tabla 1: correlación entre el precio de cierre diario del oro en dólares estadounidenses (XAUUSD) y el oro en euros, dólares australianos, francos suizos y libras esterlinas entre el 9 de abril de 2024 y el 26 de marzo de 2025.
Podemos comprobar visualmente cómo se ve una correlación de precios cercana a 0,97 en el gráfico siguiente.

Figura 1: Precios de cierre diarios de un año del oro cotizado en dólares estadounidenses y euros.
Tenga en cuenta que el gráfico anterior puede ser engañoso. Podemos sentirnos tentados a “negociar el spread” entre los pares, pero no es el spread real, si es que existe alguno. Convirtamos los XAUEUR a dólares estadounidenses según el tipo de cambio del día.adjusted_for_dollars = pd.concat([xauusd_close, xaueur_close['close'], eurusd_close['close']], join='inner', axis=1) adjusted_for_dollars.columns = ['time', 'xauusd', 'xaueur', 'eurusd'] adjusted_for_dollars['xaueur_dollars'] = adjusted_for_dollars['xaueur'] * adjusted_for_dollars['eurusd'] adjusted_for_dollars['diff'] = abs(adjusted_for_dollars['xauusd'] - adjusted_for_dollars['xaueur_dollars']) print(adjusted_for_dollars) time xauusd xaueur eurusd xaueur_dollars diff 0 2024-04-12 2344.22 2202.92 1.06237 2340.316120 3.903880 1 2024-04-15 2383.10 2242.90 1.06181 2381.533649 1.566351 2 2024-04-16 2382.85 2243.81 1.06720 2394.594032 11.744032 3 2024-04-17 2361.16 2212.14 1.06425 2354.269995 6.890005 4 2024-04-18 2378.86 2234.79 1.06557 2381.325180 2.465180 .. ... ... ... ... ... ... 245 2025-03-25 3019.81 2797.81 1.07918 3019.340596 0.469404 246 2025-03-26 3018.85 2807.50 1.07370 3014.412750 4.437250 247 2025-03-27 3056.42 2829.26 1.07975 3054.893485 1.526515 248 2025-03-28 3084.20 2847.12 1.08276 3082.747651 1.452349 249 2025-03-31 3118.19 2882.78 1.08152 3117.784226 0.405774 [250 rows x 6 columns]
adjusted_for_dollars.plot(title = 'One Year of XAUUSD and XAUEUR in US Dollars (D1)', x='time', y=['xauusd', 'xaueur_dollars']) plt.show()

Figura 2: Precios de cierre diarios de un año de oro cotizados en dólares estadounidenses y euros ajustados a dólares estadounidenses.
Observando la diferencia entre la cotización del oro en USD y la cotización del oro en euros…
print("median: ", adjusted_for_dollars['diff'].median()) adjusted_for_dollars['diff'].describe() median: 4.052404150000029 count 250.000000 mean 5.894673 std 6.238511 min 0.050646 25% 1.279615 50% 4.052404 75% 8.587763 max 51.483719 median: 4.052404150000029
... observaremos que la diferencia media real en este periodo de un año fue de ~5,9 dólares, con una desviación estándar de ~6,2 dólares. Si simplificamos demasiado y suponemos que la diferencia (spread) entre ambas cotizaciones después de la conversión al tipo de cambio actual debería ser cercana a cero, podemos considerar cualquier spread por encima de la media como una anomalía negociable en el mercado.
Elija la relación estadística que desea buscar
Luego decidimos comenzar a construir nuestra cartera de arbitraje estadístico en función de la alta correlación que encontramos entre XAUUSD y XAUEUR en el último año comercial (~250 días). Pero, ¿es la correlación de precios la relación estadística correcta o incluso la mejor que debemos buscar al construir una cartera de arbitraje estadístico?
Cuando hablamos de correlación en precios históricos estamos sujetos a ser engañados por algunas diferencias entre el uso popular del término y su significado estadístico apropiado. Este hecho es aún más evidente en la comunidad Forex. Una simple búsqueda de “pares de Forex correlacionados” nos llevará a muchos recursos que enumeran los pares más/menos correlacionados junto con consejos sobre cómo operar con ellos. No es nuestro objetivo aquí decir si este o aquel recurso, listado o consejo comercial es correcto o incorrecto. Lo que debemos tener en cuenta es que estamos sentando las bases para un arbitraje estadístico a nivel de cartera que no debe limitarse a los pares de divisas. En cambio, nuestro sistema debe generalizarse a cualquier clase de activo, en cualquier mercado y en cualquier período de tiempo, sujeto únicamente a los requisitos de ser neutral respecto del mercado y comprobable.
Según los estadísticos, se espera que la función de coeficiente de correlación de Pearson se utilice en series estacionarias y una serie temporal de precios no es estacionaria. Calculando la correlación en una serie temporal no estacionaria podemos obtener lo que se denomina “correlaciones espurias”.
“Los datos no estacionarios, por regla general, son impredecibles y no se pueden modelar ni pronosticar. Los resultados obtenidos al utilizar series de tiempo no estacionarias pueden ser espurios, ya que pueden indicar una relación entre dos variables cuando no existe ninguna. Para obtener resultados consistentes y confiables, los datos no estacionarios deben transformarse en datos estacionarios”. (Nason, GP (2006). Series temporales estacionarias y no estacionarias. Investopedia)
Entonces, como comerciantes que buscan construir una cartera de arbitraje estadístico, tenemos que tomar una decisión: ¿es suficiente esa “correlación espuria” o necesitamos una correlación adecuada en el sentido estadístico? Por ahora, aceptamos la primera medida, no perfecta, como suficiente para nuestro modelo simplificado. Pero no debemos olvidar que los pares correlacionados pueden seguir ampliando el spread durante largos períodos mientras suben o bajan juntos, es decir, pueden no volver a la media durante largos períodos y, aun así, la correlación estadística todavía se aplica. Esta condición es excepcional cuando se trata de divisas, pero muy común cuando se trata de materias primas, futuros o series temporales de precios de acciones. Por lo tanto, los niveles de stop loss y el timing de las posiciones son obligatorios cuando se trabaja con estrategias de “retorno esperado a la media”.
Elija la medida estadística que será el disparador comercial¿Por qué elegir la media o la mediana como medida de nuestra dispersión histórica? Según los estadísticos, deberíamos utilizar la media cuando nuestros datos tienen pocos valores atípicos y la mediana cuando el conjunto de datos tiene picos extremos porque la mediana se ve menos afectada por estos picos. Por ejemplo, si desea filtrar la gran dispersión causada por noticias de alto impacto, puede elegir la mediana. Por el contrario, si desea tener en cuenta los efectos de estas noticias de alto impacto en el spread, es posible que prefiera elegir la media.
Así que no existe ninguna “receta”. Debes decidir por ti mismo basándose en tus datos y tu buen juicio. Incluso podría optar por no utilizar ni la media ni la mediana. En lugar de ello, puede investigar y decidir que otra relación es mejor para su caso de uso.
Iré con la media y estableceré un parámetro para nuestra estrategia comercial en función de la ampliación del diferencial medio. Digamos que cuando el spread entre XAUUSD y XAUEUR se amplía en más del 50% de la media, activamos la operación, comprando el símbolo que está perdiendo la carrera y vendiendo simultáneamente el símbolo que está subiendo más rápido.
¿Cómo podemos determinar qué símbolo está subiendo y cuál está bajando? Para nuestro caso específico, dado que asumimos que ambas cotizaciones del oro deberían ser las mismas después de la conversión, podemos simplemente obtener el símbolo con el precio más grande como el par ascendente y el otro como el par descendente. Si estuviéramos tratando con el spread de precios de acciones que vuelven a la media, podríamos utilizar un promedio móvil exponencial con un período muy corto y asumir que el símbolo que se negocia por encima de la EMA está subiendo y viceversa.
bool IsRising(const int symbol) { switch(symbol) { case BASE_PAIR: //Print("Base pair is rising? ", quotes_base[0] > ema_base[0]); return quotes_base[0] > ema_base[0]; case CORR_PAIR: //Print("Corr pair is rising? ", quotes_corr[0] > ema_corr[0]); return quotes_corr[0] > ema_corr[0]; default: return false; } } bool IsFalling(const int symbol) { switch(symbol) { case BASE_PAIR: //Print("Base pair is falling? ", quotes_base[0] < ema_base[0]); return quotes_base[0] < ema_base[0]; case CORR_PAIR: //Print("Corr pair is falling? ", quotes_corr[0] < ema_corr[0]); return quotes_corr[0] < ema_corr[0]; default: return false; } }O podemos utilizar la pendiente.
void CalculateSlopes(double & slope_b[], double & slope_c[]) { slope_b[0] = MathAbs((quotes_base[0] - quotes_base[SlopePeriod]) / SlopePeriod); slope_c[0] = MathAbs((quotes_corr[0] - quotes_corr[SlopePeriod]) / SlopePeriod); }En nuestro caso, simplemente utilizamos el símbolo con el precio más alto.
if(quotes_base[0] > quotes_corr[0])
Operar con la cartera
Hemos creado un EA sencillo para probar nuestra hipótesis en una prueba retrospectiva.Hemos creado un EA simple para probar nuestra hipótesis en un backtest.
Obtenemos las cotizaciones iniciales en OnInit() y las actualizamos en OnTimer(). Esto se debe a que no podemos confiar en el controlador de eventos OnTick para actualizar las cotizaciones del par que no es el del gráfico de trabajo actual, ya que OnTick() solo se llama para el símbolo/gráfico actual. Véase «Expert Advisors multidivisa» o «Expert Advisors multisímbolo».
int OnInit() { ArrayResize(quotes_base, CountQuotes); ArrayResize(quotes_corr, CountQuotes); ArrayResize(quotes_conv, CountQuotes); //--- Get start quotes for both pairs GetQuotes(); //--- EMA indicators EMA_Handle_Base = iMA(BasePair, _Period, EMAPeriod, 0, MODE_EMA, PRICE_CLOSE); EMA_Handle_Corr = iMA(CorrPair, _Period, EMAPeriod, 0, MODE_EMA, PRICE_CLOSE); if(EMA_Handle_Base == INVALID_HANDLE || EMA_Handle_Corr == INVALID_HANDLE) { printf(__FUNCTION__ + ": EMA initialization failed"); return(INIT_FAILED); } //--- create timer EventSetTimer(5); // seconds //--- return(INIT_SUCCEEDED); } bool GetQuotes() { if(CopyClose(BasePair, _Period, 0, CountQuotes, quotes_base) != CountQuotes) { Print(__FUNCTION__ + ": CopyClose failed. No data"); //printf("Size quotes base pair %i ", ArraySize(quotes_base)); return false; } if(CopyClose(CorrPair, _Period, 0, CountQuotes, quotes_corr) != CountQuotes) { Print(__FUNCTION__ + ": CopyClose failed. No data"); //printf("Size quotes corr pair %i ", ArraySize(quotes_corr)); return false; } if(CheckMode == PRICE) { if(CopyClose(ConvPair, _Period, 0, CountQuotes, quotes_conv) != CountQuotes) { Print(__FUNCTION__ + ": CopyClose failed. No data"); //printf("Size quotes conv pair %i ", ArraySize(quotes_conv)); return false; } //--- for(int i = 0; i < CountQuotes; i++) { quotes_corr[i] *= quotes_conv[i]; } } return true; } void OnTimer() { UpdateQuotes(); CalculateMeanSpread(); if(CheckMode == EMA) { GetEMAs(); } } void UpdateQuotes() { ArrayRemove(quotes_base, ArraySize(quotes_base) - 1); double new_quote_base[1]; CopyClose(BasePair, _Period, 0, 1, new_quote_base); ArrayInsert(quotes_base, new_quote_base, 0, 0); //--- ArrayRemove(quotes_corr, ArraySize(quotes_corr) - 1); double new_quote_corr[1]; CopyClose(CorrPair, _Period, 0, 1, new_quote_corr); ArrayInsert(quotes_corr, new_quote_corr, 0, 0); //--- if(CheckMode == PRICE) { ArrayRemove(quotes_conv, ArraySize(quotes_conv) - 1); double new_quote_conv[1]; CopyClose(ConvPair, _Period, 0, 1, new_quote_conv); ArrayInsert(quotes_conv, new_quote_conv, 0, 0); quotes_corr[0] *= quotes_conv[0]; } }
Calcular la dispersión media.
bool CalculateMeanSpread() { int sz_base_p = ArraySize(quotes_base); int sz_corr_p = ArraySize(quotes_corr); int sz_conv_p = ArraySize(quotes_conv); if(sz_base_p != sz_corr_p || sz_corr_p != sz_conv_p) { Print(__FUNCTION__ + " Failed: Arrays must be of same size"); return false; } //--- ArrayResize(pairs_spread, CountQuotes); for(int i = 0; i < sz_base_p; i++) { pairs_spread[i] = MathAbs(quotes_base[i] - quotes_corr[i]); } double max_spread = pairs_spread[ArrayMaximum(pairs_spread)]; double min_spread = pairs_spread[ArrayMinimum(pairs_spread)]; mean_spread = MathMean(pairs_spread); //--- //printf("Last quote XAUUSD %f ", quotes_base[0]); //printf("Last quote XAUEUR %f ", quotes_corr[0]); //printf("Last spread %f ", pairs_spread[0]); //printf("Max spread %f ", max_spread); //printf("Min spread %f ", min_spread); //printf("Mean spread %f ", mean_spread); return true; }
Comprobamos señales comerciales en OnTick.
void OnTick() { //--- CheckForClose(); CheckForOpen(); }
Cuando el spread es mayor que la media en al menos el porcentaje que hemos establecido.
bool HasSpreadTrigger() { double trigger_spread = mean_spread + (mean_spread * (PercentTrigger / 100.0)); //printf(" trigger spread %f ", trigger_spread); double current_spread = pairs_spread[0]; //printf(" current spread %f ", current_spread); return current_spread >= trigger_spread; }
Compramos el símbolo que tiene un precio bajo y vendemos el símbolo que tiene un precio alto. En nuestro ejemplo, este cambio se realiza en la enumeración CheckMode (enum).
void CheckForOpen()
{
if(PositionsTotal() == 0 && HasSpreadTrigger())
{
switch(CheckMode)
{
case EMA:
if(IsRising(BASE_PAIR) && IsFalling(CORR_PAIR))
{
OpenShort(BasePair);
OpenLong(CorrPair);
}
if(IsFalling(BASE_PAIR) && IsRising(CORR_PAIR))
{
OpenLong(BasePair);
OpenShort(CorrPair);
}
break;
case SLOPE:
CalculateSlopes(slope_base, slope_corr);
if(slope_base[0] > slope_corr[0])
{
OpenShort(BasePair);
OpenLong(CorrPair);
}
else
{
OpenLong(BasePair);
OpenShort(CorrPair);
}
break;
case PRICE:
if(quotes_base[0] > quotes_corr[0])
{
OpenShort(BasePair);
OpenLong(CorrPair);
}
else
{
OpenLong(BasePair);
OpenShort(CorrPair);
}
}
}
}
Las posiciones se cerrarán mediante stop-loss/take-profit o reversión a la media en CheckForClose().
void CheckForClose() { int total = PositionsTotal(); ulong ticket = 0; if(total > 0) { if(PositionSelect(BasePair) || PositionSelect(CorrPair)) { for(int i = 0; i < total; i++) { ticket = PositionGetTicket(i); if(ticket == 0) continue; if(pairs_spread[0] <= mean_spread) { ExtTrade.PositionClose(ticket); } } } } }
La prueba retrospectiva confirma que la estrategia de reversión a la media es viable para el trading de pares.
Figura 3. Prueba retrospectiva del gráfico de capital.
Aunque el backtest valida nuestra hipótesis, se puede ver que este algoritmo específico requiere mejoras para suavizar la curva de capital. Tal vez un tamaño de orden dinámico (el volumen comercial aquí está fijado en el mínimo de 0,01 - micro lote) y optimizaciones para la relación stop-loss/take-profit. Pero la rentabilidad no es nuestra principal preocupación aquí en este artículo. Dicho esto, echemos un vistazo a algunos resultados interesantes que, según algunos autores, parecen ser comunes en las operaciones de arbitraje estadístico.
Figura 4. Resultados de la prueba retrospectiva.
Hay una gran cantidad de operaciones, la relación entre ganancias y pérdidas es pequeña (~55/~45) y la reducción máxima del saldo es relativamente baja.
Figura 5. Tiempos de trading en la prueba retrospectiva.
La concentración en torno a periodos específicos (horas, días de la semana, etc.). En nuestro caso, la concentración está alrededor de la apertura de la sesión de EE.UU., con un pico en abril de 2024.
Figura 6. Relación entre tiempo de mantenimiento de la posición y beneficio obtenido.
La gran cantidad de operaciones muy cortas indica que nuestro sistema ha estado explorando momentos de inestabilidad del mercado reingresando después de operaciones ganadoras.
¿Qué podría ser mejor?
Ahora, me gustaría llamar su atención sobre el punto de que el vendedor de una estrategia o configuración comercial intentará mostrarle los mejores resultados pasados posibles para fomentar su interés en su producto. Al final, seleccionarán los parámetros de mayor rendimiento después de una optimización cuidadosa para enfatizar las ganancias potenciales y disminuir el riesgo de pérdidas.
Pero, excepto la idea de que puedes entender los principios y comenzar de a poco con el arbitraje estadístico, no te estoy “vendiendo” nada aquí. Por el contrario, diría que estoy contento de que el backtest muestre que estamos ante un algoritmo que requiere mejoras. Porque ésta es la piedra angular de todo sistema de arbitraje estadístico.
Es decir, hasta ahora para esta automatización simplista, nos hemos limitado a parámetros elegidos arbitrariamente para gestionar el riesgo. En cambio, lo que necesitamos es:
- Controlar el número de posiciones a abrir según el riesgo evaluado en cada punto
- Tener un porcentaje de spread de activación flotante que tenga en cuenta la volatilidad
- Desarrollar una estrategia dinámica de stop-loss/take-profit que derive la probabilidad de ganancia del valor del diferencial de activación y posiblemente de otras variables
Estas son algunas posibles formas de mejorar en el futuro este EA.
Resumen del modelo a escala
1. Empecemos con una hipótesis
La dispersión entre pares correlacionados tiende a volver a la media. Ésta es nuestra hipótesis aquí.
Desde la perspectiva del comerciante, el concepto de reversión a la media es simple e intuitivo: cuando el precio actual está por debajo del precio promedio, se puede esperar que el precio suba y cuando el precio actual está por encima del precio promedio, se puede esperar que el precio baje. Como dice el refrán, el precio siempre “busca el punto medio”.

Figura 7. Los valores sobrecomprados o sobrevendidos tienden a volver al precio medio (Fuente: ResearchGate CC BY 4.0).
En los mercados con tendencia, la media se convierte en un soporte dinámico para las tendencias alcistas y en una resistencia dinámica para las tendencias bajistas. En los mercados en consolidación, la media tiende a moverse en el canal, el punto medio entre los máximos más altos y los mínimos más bajos.
Esta característica es más observable en plazos cortos para los tipos de cambio de divisas porque, mientras que el precio de cualquier otro activo puede, al menos en teoría, subir o bajar indefinidamente, los tipos de cambio de divisas están «limitados» por las normas comerciales entre naciones.
Por ejemplo: "Apple salió a bolsa el 12 de diciembre de 1980 a 22,00 dólares por acción. Las acciones se han dividido cinco veces desde la oferta pública inicial, por lo que, ajustadas por la división, el precio de las acciones en la oferta pública inicial fue de 0,10 dólares."
En el momento de redactar este artículo, Apple cotiza a 192,00 dólares estadounidenses (~ 875 %). Y sigue subiendo. No existe límite teórico.
Por otra parte, no se puede esperar ni siquiera una apreciación o depreciación del 50% en los tipos de cambio entre dos monedas sin pensar al mismo tiempo en factores extremos como la hiperinflación o incluso una guerra a gran escala. En condiciones normales, el tipo de cambio que define el “precio” del par en el trading de Forex debería volver a la media mucho antes.
2. Buscar patrones en los datos para probar la hipótesis
La correlación de Pearson de 0,97 entre XAUUSD y XAUEUR denota nuestro patrón: los precios de estos dos valores tienden a subir o bajar simultáneamente.
3. Monitorizar anomalías en los patrones
El diferencial medio entre XAUUSD y XAUEUR que se aleja mucho de la media es nuestra anomalía. Encontrar anomalías en los patrones del mercado es el pan de cada día del arbitraje estadístico a nivel de cartera tal como lo utilizaban las operaciones del equipo de Simons.
4. Desarrollar una automatización para negociar las anomalías
El EA simplista representa nuestra automatización, pero como se dijo anteriormente, el algoritmo requiere muchas mejoras, es solo una herramienta para ayudarnos a comprender mejor los principios. Además de eso, el propio EA requiere todas las comprobaciones de errores habituales.
Conclusión
El arbitraje estadístico a nivel de cartera, tal como lo realizan los grandes participantes, es prácticamente imposible para el trader minorista promedio. Porque necesitaríamos operar en el mercado de alta frecuencia (HFT), con un equipo altamente cualificado, big data de alta calidad y mucho dinero. Para convertir nuestro modelo a escala en algo similar o incluso cercano a una operación de fondos de cobertura de Jim Simons, diría, con sarcasmo, que todo lo que necesitamos es poder...
- Realice análisis de mercado con granularidad de subsegundos para cientos de símbolos de activos en cada cartera en tiempo real. (En algún momento, el equipo de Simmons estaba lidiando con más de ocho mil acciones diferentes, en una docena de mercados y territorios).
- Envíe pedidos de un millón de dólares y recíbalos en una millonésima de segundo.
- Actualice el modelo periódicamente
Bueno, supongo que podemos empezar a actualizar el modelo periódicamente. 🙂
Pero en serio, lo que la cita de Isaac Newton nos enseña es que las matemáticas por sí solas no son suficientes para prosperar en los mercados financieros. Muchos matemáticos fracasaron donde Simons tuvo éxito. Pero Simons no fue al campo de batalla sólo con matemáticas. Comenzó su carrera en finanzas realizando operaciones como cualquier otro trader, buscando tendencias, confiando en el análisis técnico y la intuición, y ganando y perdiendo dinero. Probó varios métodos, aprendió las reglas del juego, habló, se asoció y trabajó con traders profesionales mientras intentaba encontrar una forma sostenible de operar.
Sin embargo, su marco conceptual es accesible para cualquiera que esté dispuesto a hacer el esfuerzo necesario para seleccionar la cartera adecuada, elegir las características correctas para estudiar, buscar patrones y anomalías, crear prototipos con datos gratuitos y comprar datos de alta calidad cuando el prototipo sea lo suficientemente prometedor para alcanzar el modelo más equilibrado para una cartera específica. Probablemente muchos comerciantes minoristas de todo el mundo están pagando este esfuerzo con un trabajo serio día a día. La mayoría de ellos no se están convirtiendo en multimillonarios, pero ciertamente, muchos de ellos han convertido su actividad comercial en un negocio sostenible.
Incluso podemos seguir la ruta del aprendizaje automático para descubrir estos patrones y anomalías. Es accesible a los mortales y parece ser el futuro ya presente, aquí y ahora. Hay, literalmente, cientos de artículos de alta calidad sobre el uso del aprendizaje automático en el entorno MetaTrader 5. Hoy en día NO es necesario que conozcamos matemáticas de bajo nivel para utilizar el aprendizaje automático en nuestro sistema de trading. Podemos utilizar MQL5 o Python, ambos con baterías incluidas, es decir, con librerías de machine learning de alto nivel.
En resumen, este artículo propone a los traders minoristas con recursos limitados una forma esquemática de comprender los fundamentos detrás del arbitraje estadístico a nivel de cartera.
Como dice el refrán, los resultados pasados no son garantía de resultados futuros. Pero podemos tomar decisiones más informadas si analizamos esos resultados pasados con las herramientas adecuadas y datos objetivos.
| Archivo adjunto | Descripción |
|---|---|
| pairs-trading.mq5 | Este archivo contiene el código de muestra del Asesor Experto para reproducir el experimento. Requiere (#<include>) el archivo PairsTradingFunctions.mqh. |
| PairsTradingFunctions.mqh | Este archivo es el archivo de inclusión requerido por el archivo anterior de esta lista y, por el momento, solo contiene una enumeración (enum) del modo de verificación utilizado por el EA para identificar el símbolo ascendente/descendente en los pares. |
| pairs-trading.ipynb | Este archivo es un archivo Jupyter Notebook que contiene código Python para ejecutar el análisis estadístico. |
| stat_arb_pairs_trading_GOLD_XAUEUR.ini | Este archivo contiene la configuración del probador de estrategias de MetaTrader 5 para reproducir el experimento. |
Traducción del inglés realizada por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/en/articles/17735
Advertencia: todos los derechos de estos materiales pertenecen a MetaQuotes Ltd. Queda totalmente prohibido el copiado total o parcial.
Este artículo ha sido escrito por un usuario del sitio web y refleja su punto de vista personal. MetaQuotes Ltd. no se responsabiliza de la exactitud de la información ofrecida, ni de las posibles consecuencias del uso de las soluciones, estrategias o recomendaciones descritas.
Utilizando redes neuronales en MetaTrader
Optimización de Battle Royale — Battle Royale Optimizer (BRO)
Particularidades del trabajo con números del tipo double en MQL4
Aprendizaje automático en la negociación de tendencias unidireccionales tomando el oro como ejemplo
- Aplicaciones de trading gratuitas
- 8 000+ señales para copiar
- Noticias económicas para analizar los mercados financieros
Usted acepta la política del sitio web y las condiciones de uso
Fuera del tema del artículo, pero muy interesante....
¿Cómo es posible que el artículo se publique hoy (16 de septiembre), pero los primeros comentarios al mismo estén fechados el 11 de abril?
Fuera del tema de la pregunta del artículo, pero muy interesante....
¿Cómo es que el artículo se publica hoy (16 de septiembre), pero los primeros comentarios al mismo son del 11 de abril?
Es una traducción, como me he dado cuenta, de otro idioma del foro..... en el idioma nativo se publicó antes aparentemente..... publicado
> Sir Isaac Newton a la edad de noventa...
Newton vivió 84 años (¿traducción rusa torcida?).
gracias por el articulo. Spin enfoque tanto para 3 y 4 y 6 caracteres!!! código de su análisis. ¡Gracias de nuevo el contenido es super!
Obtención de un array fuera de rango en el pairs_spread[0];