Arbitraje estadístico mediante acciones cointegradas (Parte 2): Asesor Experto, pruebas retrospectivas y optimización
Introducción
Hemos aceptado el reto de desarrollar un marco para el arbitraje estadístico que pueda ser utilizado por el trader minorista medio. La idea principal es reunir un conjunto de funciones estadísticas y métodos de análisis que permitan a un trader minorista, con tan solo un ordenador portátil y una cuenta de corretaje convencional, comenzar a realizar arbitraje estadístico en Forex, acciones, ETF y materias primas.
Comenzamos con una estrategia sencilla de negociación de pares basada en la correlación, que mostró un gran potencial en las pruebas retrospectivas, pero fracasó estrepitosamente en la cuenta demo. No fue difícil concluir que estábamos perdiendo nuestras operaciones en la fase de ejecución de las órdenes. Es decir, nuestra estrategia dependía en gran medida de la velocidad de ejecución de las órdenes, pero nuestra infraestructura (ordenador portátil de consumo, conexión a internet lenta y código prototipo) no se acercaba ni de lejos a la calidad necesaria para este tipo de arbitraje. Nuestras reglas de entrada y salida dependían en gran medida del momento oportuno, y nuestra oportunidad de arbitraje se cerraba incluso antes de que nuestras órdenes llegaran al servidor del corredor.
Podríamos intentar resolver, minimizar o sortear el problema del tiempo de ejecución configurando una VPN (lo cual haremos en algún momento en el futuro), configurando una cuenta profesional con el máximo deslizamiento permitido o intentando mejorar nuestro código prototipo. Cada una de estas medidas obvias y relativamente económicas habría sido de alguna ayuda, y ambas en conjunto sin duda habrían encauzado nuestra estrategia nuevamente. Pero como queremos mantener nuestra restricción inicial de ser útiles para el trader minorista medio con recursos mínimos, en lugar de centrarnos en la velocidad de ejecución, nos propusimos desarrollar una estrategia que no dependiera tanto de la velocidad de ejecución. La implementación que se describe a continuación es una posible respuesta a este objetivo.
En el artículo anterior, presentamos las pruebas de cointegración de Engle-Granger y Johansen, su fundamento desde la perspectiva de un trader y su interpretación básica. Ahora los utilizaremos para construir nuestra cartera cointegrada.
Construyendo una cartera de acciones cointegradas
El borracho, el perro y el paseo aleatorio*
Al investigar la cointegración, es muy común toparse con una analogía que explica bastante bien la característica fundamental de las series temporales cointegradas, o de los precios de las acciones cointegrados, en este caso. La analogía dice que dos series temporales no cointegradas son como un hombre borracho caminando con su perro. Sus trayectorias se separan de forma aleatoria, sin lógica intrínseca, percibida o medible. El hombre y el perro pueden incluso llegar a casa por caminos diferentes, o el perro puede perderse para siempre.
Pero dos series temporales cointegradas serían como si el perro fuera llevado con un collar, es decir, el hombre sigue borracho, sus pasos siguen tambaleándose, pero siguen avanzando juntos, pase lo que pase. Las acciones cointegradas son como si sus precios estuvieran ligados por un collar "invisible". A la larga, suelen llegar a casa juntos. El hogar es la media común, es decir, la media del spread.
Pero, ¿cómo podemos encontrar estas acciones cointegradas en un universo de miles de valores? Afortunadamente, ya sabemos que algunas acciones del mismo sector o industria tienden a moverse juntas. Este conocimiento reduce la cifra inicial a un número más manejable, pero aún así es considerable.
Figura 1: Número de símbolos disponibles en el servidor de demostración de MetaQuotes.
Figura 2: Número de símbolos bursátiles disponibles por país en un servidor de demostración de un bróker comercial.
Hay varios métodos clásicos y “novedosos” ya revisados en la literatura académica para filtrar los candidatos a acciones para el comercio de pares, pero al final, ninguno de ellos obtuvo mejores resultados que la cointegración [Brunetti & De Luca, 2023].
Dado que nuestro objetivo aquí no es una revisión académica, sino realizar pruebas retrospectivas y describir una implementación de ejemplo, adopté una heurística simple para construir nuestra pequeña cartera.
«Una heurística (…) es cualquier enfoque para resolver problemas que emplea un método pragmático que no está totalmente optimizado, perfeccionado ni racionalizado, pero que, aun así, es lo bastante bueno como aproximación.» (Wikipedia)
- Selecciona cuidadosamente algunas acciones de Nasdaq con alta liquidez, todas ellas de empresas de semiconductores. Puedes empezar con unas cuantas docenas.
- Entre ellas, elige aquellas que presenten mayor correlación con Nvidia en el marco temporal diario durante los últimos seis meses o menos. Evitamos periodos de análisis retrospectivos prolongados, ya que nos interesan los movimientos recientes y estamos ante un mercado muy dinámico (inteligencia artificial y semiconductores). Además, actualizaremos nuestro modelo mensualmente o semanalmente, por lo que seis meses o menos para este filtro inicial podrían encaminarte por el buen camino.
- Analizar el grupo pequeño, el que presenta mayor correlación con Nvidia, para detectar la cointegración.
- Una vez que encuentre al menos un vector de Johansen significativo, compruebe la estacionariedad del spread cointegrado.
- Cuando se tiene un grupo pequeño con al menos un vector de Johansen significativo con un spread cointegrado estacionario, se obtiene el primer vector propio de Johansen para tener las ponderaciones relativas de la cartera.
- Conociendo las ponderaciones de la cartera, se puede realizar una prueba retrospectiva de la cesta de acciones cointegradas.
Utilizando el método de correlación de Pearson que vimos en el artículo anterior, redujimos nuestra selección a las tres acciones que se enumeran a continuación. Las tres empresas tienen exposición a la demanda de hardware de IA y forman parte de la cadena de suministro de Nvidia, ya sea directamente o a través de mercados adyacentes.
Microchip Technology, Inc. (MCHP) - MCHP no está directamente vinculada a las GPU de Nvidia, pero se beneficia del sector general de los semiconductores cuando aumenta la demanda de infraestructuras relacionadas con la inteligencia artificial, como la robótica y la IA industrial, a través de fabricantes de equipos originales (OEM) e integradores de sistemas para sistemas basados en Nvidia.
Monolithic Power System Inc (MPWR) - MPWR suministra circuitos integrados de gestión de energía (PMIC) para servidores y centros de datos. Estos PMIC también se utilizan en las GPU de Nvidia de alto rendimiento, que requieren una regulación de la alimentación muy especializada para mantener la estabilidad térmica y eléctrica ante cargas de trabajo elevadas. MPWR se beneficia de la expansión de Nvidia en el ámbito de los centros de datos y la inferencia.
Micron Technology Inc. (MU) - MU suministra productos de memoria, incluida la memoria de gran ancho de banda (HBM), que resulta fundamental para aceleradores de IA como el H100 de Nvidia. Sus productos de memoria están integrados en las GPU de Nvidia y también en soluciones para centros de datos. A medida que Nvidia vende más chips de IA, la demanda de la memoria avanzada de Micron se dispara. Micron anunció unas previsiones sólidas basadas en la inteligencia artificial para el periodo 2024-2025, vinculando directamente sus perspectivas de crecimiento al rendimiento de Nvidia.
Las acciones que hemos elegido no son la información más relevante en este caso. En cambio, concéntrese en elegir el elemento que tenga mayor correlación con el símbolo que está tomando como referencia, es decir, la base de su hipótesis. En nuestro caso, fue NVDA, pero puede ser cualquier símbolo que se ajuste a tu hipótesis.
NO queremos acciones que tengan una correlación excepcionalmente alta con NVDA y una baja correlación entre ellas. En cambio, buscamos acciones que tengan una alta correlación con NVDA y que, además, presenten una correlación razonablemente alta entre sí. En cierto modo, buscamos un grupo de acciones correlacionadas en torno a nuestra referencia, ya que esta propiedad se ajusta a nuestra hipótesis cuando empezamos a seleccionar las mejores: buscamos una cesta de valores correlacionada.
Buscamos una matriz de correlación de Pearson como la siguiente.
| NVDA | MCHP | MPWR | MU | |
|---|---|---|---|---|
| NVDA | 1.000000 | 0.916887 | 0.894362 | 0.897219 |
| MCHP | 0.916887 | 1.000000 | 0.877042 | 0.941977 |
| MPWR | 0.894362 | 0.877042 | 1.000000 | 0.852675 |
| MU | 0.897219 | 0.941977 | 0.852675 | 1.000000 |
Tabla 1. Matriz de correlación de Pearson entre NVDA, MCHP, MPWR y MU
Estos datos se pueden visualizar más fácilmente como un mapa de calor de Seaborn.
import seaborn as sns sns.heatmap(corr_matrix, annot=True, cmap="coolwarm")

Figura 3: Matriz de correlación de Pearson para NVDA, MCHP, MPWR y MU vista como un mapa de calor de Seaborn.
Cabe señalar que, aunque no existe una correlación excepcionalmente alta entre MCHP, MPWR y MU con NVDA, todas ellas presentan una correlación moderada entre sí.
Ten en cuenta que, al operar, necesitaremos los ticks de cuatro activos para realizar el cálculo del spread que define nuestros puntos de entrada y salida. Esta es la razón principal por la que, en un primer momento, empezamos a seleccionar cuidadosamente activos de alta liquidez. No queremos activos ilíquidos que puedan «desincronizarse» o desviarse de nuestro gestor de eventos OnTick durante más de un par de segundos (véase más abajo).
Una vez definida esta cesta correlacionada, aplicamos la prueba de cointegración de Engle-Granger para evaluar el nivel de cointegración de los pares, así como la prueba de cointegración de Johansen para comprobar el nivel de cointegración de la cesta, es decir, el nivel de cointegración del conjunto de activos. Puedes consultar el artículo anterior para obtener una descripción más detallada de estas dos pruebas.
A continuación, obtenemos los coeficientes de cobertura de la cartera a partir del vector propio de Johansen.
🧮 Ponderaciones de la cartera (vector propio de Johansen):
MCHP-2.505294
El vector propio de Johansen es una lista de números, uno por cada acción de tu grupo, que indica la ponderación o importancia de cada acción a la hora de mantener la relación estable identificada por la prueba de Johansen. Estas ponderaciones garantizan que, al combinar las acciones —comprándolas o vendiéndolas en proporciones específicas—, la evolución conjunta de sus cotizaciones forme un patrón más o menos predecible y más o menos estable.
Estos valores se utilizarán para equilibrar el volumen de las órdenes y minimizar nuestra exposición al mercado. Recuerda que en las estrategias de arbitraje estadístico siempre buscamos una exposición neutral al mercado. Podemos considerar una cartera ponderada como una mejora con respecto a esa sencilla técnica de negociación de pares, en la que compramos/vendemos una unidad de cada símbolo al mismo tiempo.
Encontrará estas ponderaciones de la cartera entre las variables globales de nuestro Asesor Experto de ejemplo.
// Global variables string symbols[] = {"MU", "NVDA", "MPWR", "MCHP"}; // Asset symbols double weights[] = {2.699439, 1.000000, -1.877447, -2.505294}; // Johansen eigenvector
NVDA tiene el valor 1.0 porque elegimos normalizar respecto del primer activo de la lista de símbolos en nuestro código Python (adjunto), que es NVDA. La normalización nos permite tener una interpretación relativa de los demás valores. Puedes optar por normalizar con cualquier otro símbolo de la lista de Python. Es una referencia arbitraria.
# === FIRST COINTEGRATION VECTOR === v = johansen_result.evec[:, 0] # v = v / v[-1] # Normalize on symbols list last asset v = v / v[0] # Normalize on symbols list first asset
Ahora podemos comprobar la estacionariedad del spread multivariante.

Figura 4: Gráfico del spread cointegrado multivariante para NVDA, MCHP, MPWR y MU.
La inspección visual del spread multivariante es una forma válida de evaluar su idoneidad para ser utilizada en una estrategia de reversión a la media. La inspección visual nos permite obtener una estimación rápida de la distribución del spread alrededor de la media, el retorno del spread a la media y su posible estacionariedad. La ausencia de una tendencia visual es un fuerte indicio de estacionariedad, al igual que la ausencia de estacionalidad.
Pero la inspección visual no es suficiente y no puede utilizarse en modelos automatizados ni en actualizaciones de cartera. Afortunadamente, contamos con las pruebas de Dickey-Fuller ampliada (ADF) y de Kwiatkowski-Phillips-Schmidt-Shin (KPSS) para echarnos una mano.
Utiliza las pruebas ADF y KPSS para confirmar que el spread tiende a volver a la media.
# Augmented Dickey-Fuller Test from statsmodels.tsa.stattools import adfuller adf_result = adfuller(spread, regression='c') # 'ct' for trend and constant print("ADF Test on Spread:") print(f" ADF Statistic : {adf_result[0]:.4f}") print(f" p-value : {adf_result[1]:.4f}") print(f" Critical Values:") for key, value in adf_result[4].items(): print(f" {key}: {value:.4f}") if adf_result[1] < 0.05: print("\n✅ The cointegrated spread is stationary (reject the null hypothesis).") else: print("\n❌ The cointegrated spread is NOT stationary (fail to reject the null hypothesis).")
Prueba ADF sobre el spread:
Valores críticos:
10%: -2.5761
✅ El spread cointegrado es estacionario (se rechaza la hipótesis nula).
# KPSS Test from statsmodels.tsa.stattools import kpss def run_kpss(series, regression='c'): statistic, p_value, lags, crit_values = kpss(series, regression=regression, nlags='auto') print("KPSS Test on Spread:")
Prueba KPSS sobre el spread:
Valores críticos:
1%: 0.739
✅ El spread cointegrado es estacionario (no se rechaza la hipótesis nula de estacionariedad).
Este paso es fundamental. Sin un spread estacionario, nuestra hipótesis de retorno a la media se desmorona. Sin un spread estacionario, los precios pueden seguir divergiendo y podríamos quedarnos con posiciones abiertas que nunca se cierren correctamente por reversión a la media. Afirmar que el spread es estacionario es fundamental en este tipo de estrategia.
Más adelante, a medida que evolucione nuestro marco de arbitraje estadístico, iremos rotando nuestra cartera de forma automatizada. Por lo tanto, contar con estas pruebas de estacionariedad en nuestro conjunto de herramientas es primordial, ya que no podemos basarnos únicamente en la evaluación visual de los gráficos.
La implementación de ejemplo
Nuestra implementación de ejemplo comienza definiendo umbrales para los puntos de entrada/salida en forma de desviaciones estándar con respecto a la media.
// Input parameters input double EntryThreshold = 2.0; // Entry threshold (standard deviations) input double ExitThreshold = 0.3; // Exit threshold (standard deviations) input double LotSize = 10.0; // Fixed lot size per leg input int LookbackPeriod = 252; // Lookback for moving average/standard deviation input int Slippage = 3; // Max allowed slippage
El tamaño de lote predeterminado de 10,0 unidades debería facilitar la comprobación de las ponderaciones de la cartera en las órdenes durante las pruebas retrospectivas.
El deslizamiento máximo permitido es casi decorativo en este caso, ya que estamos desarrollando para el trader minorista medio, y el deslizamiento máximo permitido suele ser una función disponible solo para cuentas de trading profesionales. Pero no está de más tenerlo previsto para futuras mejoras. El servidor del bróker simplemente ignorará este parámetro si la cuenta de trading tiene esta función desactivada.
El período de análisis retrospectivo utilizado para el cálculo de la media móvil y las desviaciones estándar puede ser el mismo que se utiliza para las pruebas de correlación y cointegración, pero esto no es un requisito. Una vez que hayamos detectado una cointegración en el marco temporal diario durante los últimos seis meses, no hay problema en operar en el marco temporal horario para un período de retrospectiva de dos semanas, por ejemplo. El sistema es lo suficientemente flexible como para permitir la experimentación, y en esa flexibilidad reside una gran cantidad de oportunidades.Algunas notas sobre funciones de código específicas.
OnInit()
// Check if all symbols are available for(int i = 0; i < ArraySize(symbols); i++) { if(!SymbolSelect(symbols[i], true)) { Print("Error: Symbol ", symbols[i], " not found!"); return(INIT_FAILED); } }
Comprobamos si todos los valores de nuestra cesta están disponibles en Observación del Mercado para la solicitud de cotizaciones.
// Set a timer for spread, mean, and stdev calculations EventSetTimer(1); // one second
Configuramos un temporizador para los cálculos del spread, la media y la desviación estándar fuera de la función OnTick(). Esto se debe a que, como probablemente ya sabes, el controlador de eventos OnTick está vinculado al gráfico/símbolo donde se ejecuta el EA. Si bien no hay actualizaciones para este símbolo, el evento OnTick no se activa. No queremos depender de estas actualizaciones. Al utilizar un temporizador, en este caso con un intervalo de un segundo, podemos estar seguros de que, cada vez que transcurra ese intervalo, comprobaremos si hay nuevas cotizaciones. Estamos pasando de una actualización pasiva de cotizaciones a una actualización activa de cotizaciones.
OnTimer()
void OnTimer(void) { // Calculate current spread value currentSpread = CalculateSpread(); // Update spread buffer (rolling window) static int barCount = 0; if(barCount < LookbackPeriod) { spreadBuffer[barCount] = currentSpread; barCount++; return; // Wait until buffer is filled } // Shift buffer (remove oldest value, add newest) for(int i = 0; i < LookbackPeriod - 1; i++) spreadBuffer[i] = spreadBuffer[i + 1]; spreadBuffer[LookbackPeriod - 1] = currentSpread; // Calculate mean and standard deviation using custom functions spreadMean = CalculateMA(spreadBuffer, LookbackPeriod); spreadStdDev = CalculateStdDev(spreadBuffer, LookbackPeriod, spreadMean); }
En el controlador de eventos OnTimer, actualizamos la ventana móvil de lookback para calcular el spread, la media y la desviación estándar.
OnTick()
void OnTick() { // Trading logic if(!tradeOpen) { // Check for entry signal (spread deviates from mean) if(currentSpread > spreadMean + EntryThreshold * spreadStdDev) { // Short spread (sell MU/NVDA, buy MPWR/MCHP) ExecuteTrade(ORDER_TYPE_SELL); tradeOpen = true; } else if(currentSpread < spreadMean - EntryThreshold * spreadStdDev) { // Buy spread (buy MU/NVDA, sell MPWR/MCHP) ExecuteTrade(ORDER_TYPE_BUY); tradeOpen = true; } } else { // Check for exit signal (spread reverts to mean) if((currentSpread <= spreadMean + ExitThreshold * spreadStdDev) && (currentSpread >= spreadMean - ExitThreshold * spreadStdDev)) { CloseAllTrades(); tradeOpen = false; } } // Display spread in chart Comment(StringFormat("Spread: %.2f | Mean: %.2f | StdDev: %.2f", currentSpread, spreadMean, spreadStdDev)); }
El controlador de eventos OnTick() contiene únicamente la lógica de negociación. Si no estamos en el mercado (!tradeOpen()), y tenemos una señal de compraventa, compramos o vendemos según las ponderaciones de la cartera que recibimos del vector propio de Johansen.
ExecuteTrade(ENUM_ORDER_TYPE orderType)
//+------------------------------------------------------------------+ //| Execute trade with normalized integer lots | //+------------------------------------------------------------------+ void ExecuteTrade(ENUM_ORDER_TYPE orderType) { double volumeArray[]; ArrayResize(volumeArray, ArraySize(symbols)); if(!NormalizeVolumeToIntegerLots(volumeArray, symbols, weights, LotSize)) { Print("Volume normalization failed!"); return; } for(int i = 0; i < ArraySize(symbols); i++) { ENUM_ORDER_TYPE legType = (weights[i] > 0) ? orderType : (orderType == ORDER_TYPE_BUY ? ORDER_TYPE_SELL : ORDER_TYPE_BUY); trade.PositionOpen(symbols[i], legType, volumeArray[i], 0, 0, 0, "NVDA Coint"); } } (...) //+------------------------------------------------------------------+ //| Normalize volumes to integer lots | //+------------------------------------------------------------------+ bool NormalizeVolumeToIntegerLots(double &volumeArray[], const string &symbols_arr[], const double &weights_arr[], double baseLotSize) { MqlTick tick; // Structure to store bid/ask prices double totalDollarExposure = 0.0; double dollarExposures[]; ArrayResize(dollarExposures, ArraySize(symbols_arr)); // Step 1: Calculate dollar exposure for each leg for(int i = 0; i < ArraySize(symbols_arr); i++) { if(!SymbolInfoTick(symbols_arr[i], tick)) // Get latest bid/ask { Print("Failed to get price for ", symbols_arr[i]); return false; } // Use bid price for short legs, ask for long legs double price = (weights_arr[i] > 0) ? tick.ask : tick.bid; dollarExposures[i] = MathAbs(weights_arr[i]) * price * baseLotSize; totalDollarExposure += dollarExposures[i]; } // Step 2: Convert dollar exposure to integer lots for(int i = 0; i < ArraySize(symbols_arr); i++) { double ratio = dollarExposures[i] / totalDollarExposure; double targetDollarExposure = ratio * totalDollarExposure; // Get min/max lot size and step for the symbol double minLot = SymbolInfoDouble(symbols_arr[i], SYMBOL_VOLUME_MIN); double maxLot = SymbolInfoDouble(symbols_arr[i], SYMBOL_VOLUME_MAX); double lotStep = SymbolInfoDouble(symbols_arr[i], SYMBOL_VOLUME_STEP); // Get current price again (for lot calculation) if(!SymbolInfoTick(symbols_arr[i], tick)) return false; double price = (weights_arr[i] > 0) ? tick.ask : tick.bid; double lots = targetDollarExposure / price; lots = MathFloor(lots / lotStep) * lotStep; // Round down to nearest step // Clamp to broker constraints using custom Clamp() volumeArray[i] = Clamp(lots, minLot, maxLot); } return true; }
La prueba retrospectiva

Figura 5: Curva de capital del análisis retrospectivo de la cesta cointegrada del Nasdaq para los primeros cinco meses de 2025 en el marco temporal diario.
La curva de capital demuestra que nuestra hipótesis es viable, aunque requiere una estrategia de gestión de fondos aún no implementada para evitar algunas caídas pronunciadas del capital.
Figura 6: Resumen de la prueba retrospectiva de la cesta cointegrada del Nasdaq para los primeros cinco meses de 2025 en el marco temporal diario.
Como pueden ver, la calidad de nuestro historial de precios es muy baja, pero es lo que tenemos de forma gratuita para estos cuatro símbolos bursátiles, así que estamos trabajando con lo que tenemos. Al implementar esta estrategia para operar con dinero real, se recomienda encarecidamente buscar datos históricos de precios de mayor calidad.
Figura 7: Entradas de backtest por períodos del backtest de la cesta cointegrada del Nasdaq para los primeros cinco meses de 2025 en el marco temporal diario.
Figura 8: Tiempos de tenencia de la cesta cointegrada del Nasdaq en la prueba retrospectiva para los primeros cinco meses de 2025 en el marco temporal diario.
El tiempo medio de mantenimiento de la posición de unos 20 minutos parece ser bueno porque evitamos esos tiempos de mantenimiento de la posición de uno o dos segundos de nuestro primer intento (fallido) descrito en la primera parte de este artículo.
Figura 9: MFE y MAE del backtest de la cesta cointegrada del Nasdaq para los primeros cinco meses de 2025 en el marco temporal diario.
Cointegración más allá de las acciones
Estos son resultados bastante satisfactorios para nuestra primera cesta de acciones cointegradas del mismo sector. Con algunas mejoras, como una adecuada gestión monetaria y datos de mejor calidad para la optimización, podemos esperar tener un candidato razonable para probar en una cuenta demo durante un par de semanas.
Pero, como probablemente ya se habrá dado cuenta, se trata de una solución muy genérica en la que utilizamos solo un subconjunto muy pequeño de acciones del Nasdaq en una combinación aún más reducida de período de análisis retrospectivo y marco temporal de la prueba de cointegración. Es decir, estamos utilizando cuatro símbolos que fueron sometidos a pruebas de cointegración en los últimos seis meses en el marco temporal diario. Si empiezas a combinar estos parámetros, es posible que encuentres docenas de oportunidades que merecen tu atención.
Además, no estás limitado a las acciones de Nasdaq ni a ningún otro tipo de acciones. Puede probar con pruebas de cointegración de múltiples activos entre acciones y ETF o índices sectoriales.
Algunos ejemplos
Aquí se muestran algunos ejemplos de cointegración probados durante los últimos seis meses (180 días) en el marco temporal diario.
ETF relacionados con el oro
symbols = ['AAAU', 'USGO', 'BGLD']
1. AAAU – ETF de oro físico de Goldman Sachs
«El AAAU es un fondo cotizado en bolsa cuyo objetivo es reflejar la evolución del precio del oro en lingotes. El fondo cuenta con lingotes de oro físicos almacenados en cámaras acorazadas seguras, y los inversores pueden canjear sus participaciones por oro real (sujeto a determinadas condiciones). El AAAU está diseñado para ofrecer una exposición directa a los precios del oro con un error de seguimiento mínimo y sin derivados.»
2. USGO – ETF de acciones de oro físico de Abrdn
«USGO es un ETF de oro con respaldo físico gestionado por Aberdeen Investments. Al igual que la AAAU, su objetivo es reflejar la evolución del precio del oro en lingotes mediante la tenencia de oro físico asignado, almacenado en cámaras acorazadas seguras. Ofrece a los inversores una forma sencilla y rentable de invertir en oro sin tener que hacerse cargo de la entrega física.»
3. BGLD – ETF de renta fija con estrategia de oro de FT Vest
«BGLD es un ETF de estrategia de oro de gestión activa que busca proporcionar ingresos y exposición al oro. A diferencia de AAAU y USGO, BGLD no posee oro físico directamente. En su lugar, utiliza una combinación de derivados relacionados con el oro (como futuros y opciones) y estrategias generadoras de ingresos para ofrecer una rentabilidad específica con un comportamiento similar al del oro y centrada en la generación de ingresos mensuales.»
Index(['AAAU', 'USGO', 'BGLD'], dtype='object')
Resultados de la prueba de cointegración de Engle-Granger:
USGO y BGLD | valor p: 0,0144
Par con mayor cointegración (Engle-Granger): USGO y BGLD | valor p: 0,0144
Recuerda que la prueba de Engle-Granger solo analiza relaciones por pares. Esta prueba no indicará las interacciones de la cesta completa que sí detecta la prueba de Johansen.
Resultados de la prueba de Johansen (estadística de traza):
Número de observaciones: 119Número de variables: 3
Rango 2: Estadística de traza = 4,25 | valor crítico al 5 % = 3,84 | Significativo
Con la prueba de Johansen, podemos ver el número de relaciones de cointegración en toda la cesta en cada rango.
En el rango 0, la estadística de traza (30,21) supera el valor crítico del 5 % (29,80), lo que indica que existe al menos un vector de cointegración. En el rango 1, la prueba no es significativa, pero en el rango 2 vuelve a serlo (4,25 > 3,84), lo que implica una segunda relación de cointegración.
En el resultado de Engle-Granger, podemos observar que tanto AAAU-BGLD (p = 0,0209) como USGO-BGLD (p = 0,0144) presentan una «mayor cointegración» significativa que AAAU-USGO (p = 0,1322), lo que indica que existen dos vectores de cointegración independientes entre los tres activos y, probablemente, una relación de equilibrio a largo plazo sólida y estable en la cesta.

Figura 10: Gráfico del spread cointegrado entre el USGO y el BGLD durante los últimos seis meses en el marco temporal diario.
Prueba ADF sobre el spread:
Valores críticos:
10%: -2.5800
✅ El spread es estacionario (se rechaza la hipótesis nula).
Prueba KPSS sobre el spread:
Valores críticos:
1%: 0.739
✅ El spread es estacionario (no se rechaza la hipótesis nula de estacionariedad).
Podemos observar que BGLD tiene una fuerte relación de cointegración tanto con AAAU como con USGO, y al confirmarse la estacionariedad del spread entre USGO y BGLD, sabemos que tenemos un fuerte indicio de que estos activos son buenos candidatos para una cesta cointegrada relacionada con el oro.

Figura 11: Gráfico del spread cointegrado multivariado entre AAAU, USGO y BGLD durante los últimos seis meses en el marco temporal diario.
Sin embargo, su diferencial cointegrado no es estacionario para este período y este horizonte temporal.
Prueba ADF sobre el spread:
Valores críticos:
10%: -2.5800
❌ El spread cointegrado NO es estacionario (no se rechaza la hipótesis nula).
Prueba KPSS sobre el spread:
Valores críticos:
1%: 0.739
❌ El spread cointegrado NO es estacionario (se rechaza la hipótesis nula de estacionariedad).
ETF relacionados con la plata
symbols = ['CEF', 'SLV', 'SIVR']
1. CEF – Fideicomiso de oro y plata física de Sprott
«Un fondo de inversión de capital fijo que posee lingotes físicos de oro y plata. Se cotiza con una prima o un descuento respecto a su valor liquidativo y no es una inversión dedicada exclusivamente a la plata, lo que lo hace estructuralmente diferente del SLV y del SIVR.»
2. SLV – iShares Silver Trust
«Un ETF de plata con respaldo físico cuyo objetivo es reflejar la evolución del precio de la plata en lingotes. Es uno de los ETF de plata más grandes y con mayor liquidez.»
3. SIVR – ETF de acciones de plata física de Aberdeen
«Al igual que el SLV, el SIVR es un ETF de plata con respaldo físico, pero suele tener un ratio de gastos más bajo, lo que lo hace atractivo para los inversores que se fijan especialmente en los costes».
Index(['CEF', 'SLV', 'SIVR'], dtype='object')
Resultados de la prueba de cointegración de Engle-Granger:
CEF y SLV | valor p: 0,6092
CEF y SIVR | valor p: 0,6109SLV y SIVR | valor p: 0,0000
Par más cointegrado (Engle-Granger): SLV y SIVR | valor p: 0,0000
Resultados de la prueba de Johansen (estadística de traza):
Número de observaciones: 121Número de variables: 3
Rango 2: Estadística de traza = 1,95 | valor crítico al 5 % = 3,84 | No significativo
En el rango 0 (62,67 > 29,80), la estadística de traza es significativa, lo que indica la presencia de al menos un vector de cointegración entre los tres ETF relacionados con la plata. Sin embargo, los rangos 1 y 2 no son significativos, lo que indica que solo existe una relación estable a largo plazo común a esta cesta.
Los resultados de Engle-Granger muestran que el par SLV y SIVR presenta una clara señal de cointegración (p = 0,0000). El CEF no parece estar cointegrado ni con el SLV ni con el SIVR (p > 0,6). Si volvemos a analizar el resultado de Johansen, podemos deducir que la cointegración probablemente se deba a la estrecha relación entre el SLV y el SIVR, ya que son sustitutos casi perfectos —ambos son ETF de plata con respaldo físico—, lo que justifica su cointegración. El CEF está expuesto a la plata, pero también ofrece exposición al oro y es un fondo de capital fijo. Por lo tanto, se comporta de forma diferente.

Figura 12: Gráfico del spread cointegrado entre el SLV y el SIVR durante los últimos seis meses en el marco temporal diario.
Prueba ADF sobre el spread:
Valores críticos:
10%: -2.5798
✅ El spread es estacionario (se rechaza la hipótesis nula).
Prueba KPSS sobre el spread:
Valores críticos:
1%: 0.739
❌ El spread NO es estacionario (se rechaza la hipótesis nula de estacionariedad).
En este caso, hemos observado que el spread cointegrado entre SLV y SIVR es estacionario según la prueba ADF, pero no estacionario según la prueba KPSS. Ya vimos un ejemplo similar en el artículo anterior, con la explicación correspondiente de la documentación de la biblioteca statsmodels sobre cómo interpretar este tipo de resultados contradictorios.
«Caso 1: Ambas pruebas concluyen que la serie no es estacionaria. La serie no es estacionaria.
Caso 2: Ambas pruebas concluyen que la serie es estacionaria. — La serie es estacionaria.
Caso 3: La prueba KPSS indica estacionariedad y la prueba ADF indica no estacionariedad; la serie es estacionaria en cuanto a la tendencia. Es necesario eliminar la tendencia para que la serie sea estrictamente estacionaria. Se comprueba la estacionariedad de la serie sin tendencia.
Caso 4: El KPSS indica no estacionariedad y el ADF indica estacionariedad - La serie es estacionaria en diferencias. La diferenciación se utiliza para hacer que las series sean estacionarias. Se comprueba la estacionariedad de la serie diferenciada.»

Figura 13: Gráfico del spread cointegrado multivariante entre CEF, SLV y SIVR durante los últimos seis meses en el marco temporal diario.
Para el spread cointegrado multivariado, es decir, la cesta completa, el gráfico muestra que el spread NO está revirtiendo a la media para este período y marco temporal. La prueba de estacionariedad lo confirmará.
Prueba ADF sobre el spread:
Valores críticos:
10%: -2.5799
❌ El spread cointegrado NO es estacionario (no se rechaza la hipótesis nula).
Prueba KPSS sobre el spread:
Retrasos utilizados: 6
Valores críticos:
1%: 0.739
❌ El spread cointegrado NO es estacionario (se rechaza la hipótesis nula de estacionariedad).
¿Qué significa esto? Ciertamente, no contamos aquí con una cesta adecuada de ETF relacionados con la plata, pero tenemos dos ETF altamente cointegrados (SLV y SIVR) que podrían merecer un análisis detallado para el trading de pares, que es el tema del primer artículo de esta serie.
Estos dos ejemplos pretenden dejar claro que, a la hora de buscar activos cointegrados para oportunidades de arbitraje estadístico, la experimentación y la investigación son las palabras clave. Además, debemos tener en cuenta que las estadísticas por sí solas no sustituyen la comprensión del sector ni el conocimiento del mercado.
Conclusión
Este artículo describe un ejemplo de Asesor Experto sometido a pruebas retrospectivas sobre un pequeño grupo de acciones cointegradas. Este es el segundo de dos artículos que describen las medidas estadísticas más comunes para la construcción de carteras de arbitraje estadístico: coeficientes de correlación y evaluación de la cointegración, junto con pruebas de estacionariedad del spread.
Cabe destacar que este tipo de estrategia, aunque resulta casi imposible de utilizar para pares de divisas (FX) debido a la rareza de que existan más de dos divisas cointegradas, también se aplica a índices, ETF y materias primas.
Ahora que contamos con las herramientas básicas para la construcción de carteras basadas en la cointegración, los siguientes pasos lógicos podrían ser la implementación de una rotación de cartera en tiempo real, que eventualmente evolucionaría hacia un enfoque de aprendizaje automático en el futuro.
Referencias
Marianna Brunetti y Roberta De Luca, 2023. "Pre-selection in cointegration-based pairs trading," Statistical Methods & Applications, Springer; Società Italiana di Statistica, vol. 32(5), páginas 1611-1640, diciembre.
Notas
* Aunque es probable que la analogía se derive de él, el «paseo aleatorio» aquí mencionado no debe confundirse con el «paseo aleatorio de Pearson», el proceso estocástico descrito y denominado así por el matemático inglés.
| Archivo adjunto | Descripción |
|---|---|
| corr_pearson.ipynb | Este archivo es un cuaderno Jupyter que contiene código Python. El script ejecuta la prueba de correlación de Pearson. |
| coint_stocks_ETFs.ipynb | Este archivo es también un cuaderno Jupyter que contiene código Python. El script ejecuta las pruebas de cointegración de Engle-Granger y Johansen, así como las pruebas de estacionariedad ADF y KPSS. |
| Nasdaq_NVDA_Coint.mql5 | Este archivo contiene el ejemplo de Asesor Experto utilizado en las pruebas retrospectivas. |
| Nasdaq_NVDA_Coint.ini | Este archivo es un archivo de configuración (.ini) que contiene el parámetro utilizado en la prueba retrospectiva. |
| Nasdaq_NVDA_Coint.NVDA.Daily.20250101_20250515.021.ini | Este archivo también es un archivo de configuración (.ini) que contiene los parámetros de optimización utilizados en la prueba retrospectiva. |
Traducción del inglés realizada por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/en/articles/19052
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
Del básico al intermedio: Subventanas (III)
Particularidades del trabajo con números del tipo double en MQL4
Red neuronal en la práctica: Nacimiento de C_Neuron
- 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
¿A qué se deben todas estas complicaciones?
Esto da como resultado:
lots -> ratio * totalDollarExposure / price -> dollarExposures[i] / totalDollarExposure * totalDollarExposure / price -> dollarExposures[i] / price -> MathAbs(weights_arr[i]) * baseLotSizeAdemás, tus cálculos no son compatibles con cotizaciones expresadas en una divisa distinta a la de la cuenta.
¿A qué se deben todas estas complicaciones?
Esto da como resultado:
Además, tus cálculos no son compatibles con cotizaciones expresadas en una divisa distinta a la de la cuenta.