Trading de arbitraje en Forex: Un bot market-maker simple de sintéticos para comenzar
Introducción: del trading minorista hacia el pensamiento institucional
A menudo me preguntan cómo llegué a desarrollar TrisWeb_Optimised. La historia comenzó en 2016, cuando me sumergí por primera vez en el mundo del Forex, con la ingenuidad y la fe de un principiante en el trading con indicadores. Por aquel entonces, aún creía en el "santo grial" del trading: una combinación mágica de indicadores que supuestamente convertiría 1.000 dólares en un millón en tan solo un año.
En 2017 se produjo una revolución en mi mente cuando, tras una serie de dolorosas pérdidas, comencé a estudiar cómo operan realmente los grandes jugadores. No los que pregonan sus "ganancias millonarias" en YouTube, sino los realmente institucionalizados: bancos, fondos de cobertura y empresas de trading por cuenta propia.
Y esto es lo que descubrí: no usan elaboradas estrategias de indicadores. Aplican principios matemáticos como la gestión de riesgos, el arbitraje, la creación de mercado y otros enfoques basados en una comprensión fundamental de los mecanismos del mercado. Fue entonces cuando tomé la decisión: hay que negociar como un gran jugador o no negociar en absoluto.
Pasé los tres años siguientes estudiando métodos de negociación institucionales. Me sumergí en el mundo de las correlaciones entre mercados, el arbitraje estadístico y el trading algorítmico. Experimenté con Python y MQL, creando prototipos de sistemas que imitaban los planteamientos de los grandes participantes en el mercado, pero adaptados a los tráders minoristas con sus limitaciones de capital y tecnología.
Así, en enero de 2020, en vísperas de uno de los periodos más turbulentos de la historia de los mercados financieros, nació Tris_Optimised, mi respuesta a la pregunta: "¿Cómo aplica un tráder minorista las estrategias institucionales?"
Este asesor experto no intenta predecir los movimientos del mercado, no se basa en indicadores de análisis técnico y no requiere la "intuición" del tráder. En su lugar, calcula matemáticamente los posibles desequilibrios entre tres pares de divisas relacionados y coloca una cuadrícula de órdenes listas para captar esos desequilibrios cuando se produzcan.
En cinco años de funcionamiento continuo en condiciones reales de mercado, Tris_Optimised ha mostrado su viabilidad. Ha sobrevivido a pandemias, picos inflacionistas, cambios en los tipos de interés y crisis geopolíticas, y sigue produciendo beneficios constantes (durante esos raros periodos en los que negocio, en lugar de pasarme la noche en vela buscando ideas y códigos directamente). No es un sistema milagroso que promete beneficios exorbitantes, sino una herramienta de trabajo fiable basada en los principios fundamentales del trading institucional.
Hoy, esta base de pensamiento institucional me permite negociar con éxito en diversos mercados. Aunque en los últimos años me he centrado en estrategias que usan el aprendizaje automático, los enfoques de arbitraje siempre han sido una parte importante de mi arsenal comercial. Combinar los métodos estadísticos de ML con los patrones fundamentales del mercado que utilizan los tráders institucionales me proporciona una gran ventaja. Incluso me invitaron a un pequeño y desconocido fondo de cobertura, aunque en realidad no era para tanto: el fondo solo tiene un gestor de riesgos y un manager aparte de mí, y estamos preparando el lanzamiento de una insfraestructura en MetaTrader 5 para fondos de cobertura.
Hace un par de semanas estaba revisando mi almacenamiento en la nube y me encontré con un archivo de mis antiguos robots comerciales. Entre ellos estaba Triss_Optimised, uno de mis primeros proyectos que, a pesar de su "simplicidad" en comparación con los sistemas modernos de ML, sigue funcionando y ofreciendo resultados. Lo ejecuté en una cuenta de prueba y me sorprendió: incluso sin optimizarlo para las condiciones actuales del mercado, demostró resultados positivos.
Fue entonces cuando decidí compartir este código con la comunidad, no porque sea un sistema revolucionario que te hará millonario en un mes, sino porque este código es un buen ejemplo de cómo se puede adoptar un enfoque institucional de trading sin dejar de ser un tráder minorista. Es una especie de puente entre dos mundos que puede ayudarle a hacer la misma transición que yo hice una vez.
En este artículo, desvelaré la mecánica de funcionamiento de TrisWeb_Optimised, explicaré su arquitectura y compartiré mi experiencia en cuanto a su configuración y optimización. ¿Está preparado para sumergirse en el mundo del trading algorítmico profesional? Pues empecemos.
El arbitraje de tres divisas en Forex: principio del triángulo EURUSD-GBPUSD-EURJPY
Empezaremos diciendo que el arbitraje triangular en el mundo Forex es una auténtica caza de fantasmas. Imagínese la situación: usted está siguiendo simultáneamente EURUSD, GBPUSD y EURJPY, tratando de atrapar un fugaz desequilibrio de precios: cuándo el bucle cerrado EUR→USD→GBP→EUR le dará al menos un par de pips de beneficio neto. Pero lo cierto es que las oportunidades de arbitraje puro son tan raras como ver un unicornio volando. Las instituciones, con sus algoritmos de alta frecuencia y su acceso directo a la liquidez, se comen estas oportunidades sin darnos tiempo a pestañear.
Por eso he creado TrisWeb_Optimised, un asesor experto que no espera a que se den las condiciones perfectas, sino que construye una red tridimensional de órdenes listas para obtener beneficios de las fluctuaciones naturales del mercado. No se trata de un arbitraje clásico en el sentido académico, sino de una estrategia de guerrilla de un tráder minorista que usa relaciones matemáticas entre tres pares de divisas.
Pares de divisas sintéticos en MQL5: una puerta secreta al arbitraje
¿Qué es un par de divisas sintético? Es un fantasma, una abstracción matemática que construimos partiendo de instrumentos realmente negociados. Por ejemplo, teniendo las cotizaciones EURUSD y GBPUSD, podemos calcular un EURGBP sintético, y en teoría debería coincidir exactamente con el EURGBP real. Pero siempre existen discrepancias en el mundo real, y son el pan nuestro de cada día.
TrisWeb_Optimised no crea sintéticos explícitamente, pero juega con sus hilos invisibles. Aquí tiene un fragmento de código en el que obtenemos los precios actuales de cada símbolo, el primer paso para buscar desequilibrios:
// Получаем текущие цены для каждого символа double priceSymbol1 = GetCurrentPrice(Symbol1); double priceSymbol2 = GetCurrentPrice(Symbol2); double priceSymbol3 = GetCurrentPrice(Symbol3);
Estas tres líneas suponen el punto de entrada a un espacio multidimensional de posibilidades en el que las más mínimas discrepancias se convierten en dinero real.
La arquitectura de TrisWeb_Optimized: la máquina que sobrevivió a la pandemia
Cuando escribí las primeras líneas de TrisWeb_Optimized en enero de 2020, el mundo estaba a punto de sufrir una pandemia, un terremoto en los mercados y una volatilidad demencial. Nadie podría haber predicho que este sencillo asesor tendría un bautismo de fuego en algunas de las condiciones de mercado más extremas de los últimos tiempos. ¿Y sabe qué? Sobrevivió. No solo sobrevivió, sino que prosperó.
El corazón del sistema late en la función OnTick(): se activa en cada cambio de precio, analizando el panorama completo en tres frentes de forma simultánea:
void OnTick() { // Подсчет ордеров и прибыли int ordersCount1 = 0, ordersCount2 = 0, ordersCount3 = 0; double profit1 = 0, profit2 = 0, profit3 = 0; // Подсчет отложенных ордеров CountPendingOrders(ordersCount1, ordersCount2, ordersCount3); // Подсчет открытых позиций и их профита CountOpenPositions(ordersCount1, ordersCount2, ordersCount3, profit1, profit2, profit3); // ... остальной код }
Un código aparentemente ordinario. Pero tras estas líneas se esconde una elegante arquitectura modular: cada aspecto del sistema se dedica a una función distinta, como un órgano independiente en un organismo interconectado. Sin confusión, sin desorden, solo con una clara división de responsabilidades.
Ajuste de los parámetros de la red: bailando con la volatilidad
El mercado de divisas es como el océano: el EURUSD fluye lenta y majestuosamente como las corrientes profundas, mientras que el EURJPY puede estallar súbitamente como un tsunami. El intento de negociar estos pares con los mismos parámetros es un camino seguro hacia la decepción. Por ello, TrisWeb_Optimised permite configurar parámetros de cuadrícula individuales para cada instrumento:
input group "Step Settings" input int Step01_Symbol1 = 40; // Начальный шаг для Symbol1 (в пунктах) input int Step02_Symbol1 = 60; // Шаг между ордерами для Symbol1 (в пунктах) input int Step01_Symbol2 = 40; // Начальный шаг для Symbol2 (в пунктах) input int Step02_Symbol2 = 60; // Шаг между ордерами для Symbol2 (в пунктах) input int Step01_Symbol3 = 40; // Начальный шаг для Symbol3 (в пунктах) input int Step02_Symbol3 = 60; // Шаг между ордерами для Symbol3 (в пунктах)
Durante cinco años de trabajo con este sistema he desarrollado un ritual peculiar: para pares tranquilos como el EURUSD uso pasos estándar de 40 y 60 pips, mientras que para los pares cruzados más fogosos de JPY los aumento a 50 y 80. Es como ajustar la sensibilidad de una caña de pescar para distintos tipos de peces: si se usa el mismo enfoque, o lo pescas todo o no pescas nada.
Optimización del tamaño de los lotes: un sistema de ADN adaptativo
Un tamaño de lote fijo es el camino del principiante, pero el profesional sabe que el volumen debe respirar junto con el saldo de la cuenta. Y TrisWeb_Optimised sabe cómo hacerlo gracias a la función CalculateOptimalLotSize(), que considero mi pequeña obra maestra:
double CalculateOptimalLotSize(string symbol, double baseSize) { if(!AutoLotOptimization) return baseSize; double accountBalance = AccountInfoDouble(ACCOUNT_BALANCE); double lotStep = SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP); double minLot = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN); // ... остальной код расчета }Esta función es una auténtica navaja suiza, pues tiene en cuenta el saldo actual, el porcentaje de riesgo establecido, el valor del pip para un símbolo concreto, las restricciones del bróker en cuanto a tamaño mínimo de lote y paso, y (este es mi orgullo especial) ajusta automáticamente los cálculos para divisas exóticas:
// Корректировка для пар с JPY и других экзотических валют string quoteCurrency = StringSubstr(symbol, 3, 3); if(quoteCurrency == "JPY" || quoteCurrency == "XAU" || quoteCurrency == "XAG") pointCost *= 100.0;
Para los no iniciados, diremos que el valor de un pip en los pares con el yen japonés es 100 veces menor que en los pares principales. Olvídese de este ajuste y su robot negociará volúmenes microscópicos o le arruinará en una sola sesión comercial.
Gestión del tiempo del asesor experto: un algoritmo con ritmo circadiano
El mercado Forex funciona las veinticuatro horas del día, pero eso no significa que nuestro asesor deba hacer lo mismo. Hay momentos en los que es mejor hacerse a un lado: la sesión nocturna, con sus amplios spreads y movimientos poco naturales, suele traer más problemas que oportunidades. TrisWeb_Optimised incorpora un "ritmo circadiano" gracias a IsWorkTime() :
bool IsWorkTime() { MqlDateTime currentTime; TimeToStruct(TimeLocal(), currentTime); datetime currentTimeSeconds = HoursMinutesToSeconds(currentTime.hour, currentTime.min); datetime startTimeSeconds = HoursMinutesToSeconds(StartTimeHour, StartTimeMin); datetime endTimeSeconds = HoursMinutesToSeconds(EndTimeHour, EndTimeMin); return (startTimeSeconds <= currentTimeSeconds && currentTimeSeconds <= endTimeSeconds); }Y CheckNewDayAndWorkTime() añade otro rasgo humano al asesor, a saber, la capacidad de "empezar de cero" cada día nuevo:
void CheckNewDayAndWorkTime() { if(IsNewDay && IsNewDayReset && IsWorkTime()) { DeleteAllOrders(); IsNewDay = false; } if(!IsWorkTime()) { IsNewDay = true; } }
Esto resulta especialmente valioso a largo plazo: el sistema no acumula un "bagaje" de órdenes obsoletas, sino que actualiza constantemente la cuadrícula según las condiciones actuales del mercado.
Algoritmo de salida de posiciones: el arte de salir a tiempo
En el trading, como en la vida, no solo es importante llegar a tiempo, sino también marcharse a tiempo. TrisWeb_Optimised usa un criterio sencillo pero eficaz, alcanzar un determinado nivel de beneficio total:
// Общее количество ордеров int totalOrders = ordersCount1 + ordersCount2 + ordersCount3; double totalProfit = profit1 + profit2 + profit3; // Если нет ордеров - создаем, если есть - проверяем на прибыль if(totalOrders == 0) { if(IsWorkTime()) { PlaceInitialOrders(); } } else if(totalProfit > Profit) { DeleteAllOrders(); }Pero el diablo, como siempre, está en los detalles. El sistema tiene en cuenta no solo el beneficio "puro", sino el resultado total, incluidos los swaps y las comisiones:
double swap = PositionGetDouble(POSITION_SWAP); double profit = PositionGetDouble(POSITION_PROFIT); double commission = PositionGetDouble(POSITION_COMMISSION); double totalProfitForPosition = profit + swap + commission;
Esto resulta fundamental para el rendimiento a largo plazo, especialmente si mantenemos posiciones durante la noche, cuando se acumulan los swaps. De lo contrario, el sistema puede ignorar las combinaciones rentables o, por el contrario, considerar rentables aquellas que en realidad suponen una pérdida debido a los swaps negativos.
Ajuste fino en la ejecución de órdenes: un pacto con el diablo del mercado
En el mundo del trading de alta frecuencia, la calidad de la ejecución puede ser el factor decisivo entre los beneficios y las pérdidas. TrisWeb_Optimised usa estructuras MQL5 de bajo nivel para controlar al máximo el proceso de colocación y ejecución de órdenes:
bool OpenBuyStop(string symbol, double volume, double openPrice) { MqlTradeRequest request = {}; MqlTradeResult result = {}; request.action = TRADE_ACTION_PENDING; request.symbol = symbol; request.volume = volume; request.type = ORDER_TYPE_BUY_STOP; request.price = openPrice; request.deviation = Deviation; request.magic = EXPERT_MAGIC; if(UseCommentsInOrders) request.comment = OrderComment; if(!OrderSend(request, result)) { Print("OrderSend error ", GetLastError(), " retcode: ", result.retcode); return false; } return true; }Debemos prestar especial atención al parámetro Deviation, que determina a qué distancia del precio solicitado puede ejecutarse una orden:
input int Deviation = 3; // Допустимое отклонение цены
Este será el pacto con el diablo del mercado: "Estoy dispuesto a aceptar un rendimiento 3 puntos peor de lo solicitado, pero no más". En periodos de alta volatilidad, esta puede ser la diferencia entre una orden ejecutada y una oportunidad perdida. Un valor demasiado bajo y nuestras órdenes serán rechazadas debido a las recotizaciones; un valor demasiado alto, y correremos el riesgo de obtener una ejecución a un precio inesperadamente malo.
Resultados y análisis en tiempo real: los ojos y oídos del tráder
Cuando empecé a desarrollar TrisWeb_Optimised, me di cuenta de que uno de los principales problemas de muchos asesores expertos es que funcionan como una "caja negra" sin dejar que el tráder sepa lo que está ocurriendo. Así que he añadido la visualización detallada de la información a través de DisplayInfo() :
void DisplayInfo(int totalOrders, double totalProfit, double profit1, double profit2, double profit3, int count1, int count2, int count3) { string info = ""; if(AutoLotOptimization) { double lot1 = CalculateOptimalLotSize(Symbol1, Lot_Symbol1); double lot2 = CalculateOptimalLotSize(Symbol2, Lot_Symbol2); double lot3 = CalculateOptimalLotSize(Symbol3, Lot_Symbol3); info += "Auto Lot: " + Symbol1 + "=" + DoubleToString(lot1, 2) + ", " + Symbol2 + "=" + DoubleToString(lot2, 2) + ", " + Symbol3 + "=" + DoubleToString(lot3, 2) + "\n"; } // ... остальной код формирования информации Comment(info); }Podemos elegir entre un modo de visualización básico (para los que prefieren el minimalismo) o un análisis detallado que incluya un desglose de cada par de divisas:
input bool DisplayDetailedInfo = false; // Показывать детальную информацию
Es como la diferencia entre el salpicadero básico de un coche antiguo, apenas con un velocímetro y el nivel de combustible, y una cabina moderna con docenas de indicadores y monitores: la elección depende de nuestro estilo de conducción.
Así se comportaba uno de los antiguos conjuntos:
Ampliación del sistema: de un simple bot a un imperio de negocios
TrisWeb_Optimised no es solo un asesor experto listo para usar, sino una base sobre la que construir nuestro propio imperio del arbitraje. A lo largo de cinco años de evolución, lo he modificado muchas veces, añadiendo nuevas funciones y optimizando las que ya existían. Aquí tiene algunas direcciones que puedes tomar para desarrollar el sistema:
La integración con Python abre enormes oportunidades para analizar correlaciones y aplicar técnicas de aprendizaje automático. Imagínese analizar no solo las cotizaciones actuales, sino los patrones históricos de interacción entre los tres pares de divisas, prediciendo los desequilibrios más probables.
Las notificaciones a través de Telegram API añadirán movilidad a su estrategia: siempre estará al tanto de los eventos importantes, incluso cuando esté lejos de su terminal comercial. Esto resulta especialmente valioso cuando el asesor experto se ejecuta en un VPS remoto.
La ampliación a más pares de divisas convierte a TrisWeb en una plataforma de arbitraje en toda regla. ¿Por qué limitarnos a tres herramientas cuando podemos crear una red de docenas de pares interrelacionados, rastreando cientos de oportunidades potenciales de arbitraje?
Para todas estas modificaciones bastará con introducir cambios mínimos en el código existente, conservando su estructura básica y su lógica de funcionamiento. Sería como construir habitaciones adicionales en una casa ya existente: los cimientos ya están puestos, solo quedará ampliar el espacio habitable.
En lugar de una conclusión
Hace cinco años, cuando nació la primera versión de TrisWeb_Optimised, no podía imaginarme el camino que tomaría. Ha capeado temporales de mercado, periodos de extrema volatilidad y también de relativa calma. Ha pasado de ser un simple script a convertirse en un sistema comercial maduro. Pero lo más importante es que nunca ha dejado de obtener beneficios.
En la siguiente parte del artículo nos sumergiremos en los aspectos prácticos del ajuste de TrisWeb_Optimised, analizaremos ejemplos reales del funcionamiento del sistema y compartiremos los secretos de la optimización de los parámetros para las distintas condiciones del mercado. Permanezca atento: ¡la diversión está por llegar!
Traducción del ruso hecha por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/ru/articles/17424
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.
El filtro de Kalman para estrategias de reversión a la media en Forex
Algoritmo de optimización de neuroboides — Neuroboids Optimization Algorithm (NOA)
Trading de arbitraje en Forex: Análisis de movimientos de divisas sintéticas y reversión a la media
Automatización de estrategias de trading en MQL5 (Parte 10): Desarrollo de la estrategia Trend Flat Momentum
- 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
Un enfoque interesante. Empezó tal cual, sin optimización. Mantiene el equilibrio, hay un aumento en pequeños pasos.
Si lo desea, puede mover el cierre de la parrilla al final del día, antes de la formación de swap. Actualmente, la parrilla se cierra al inicio de la negociación. O no utilizar el cierre diario en absoluto.
Definitivamente hay espacio para el desarrollo y la aplicación en soluciones complejas.
¡Adelante!