English Русский 中文 Deutsch 日本語 Português
preview
Creación de un algoritmo de creación de mercado en MQL5

Creación de un algoritmo de creación de mercado en MQL5

MetaTrader 5Trading | 22 julio 2024, 09:24
273 0
Yevgeniy Koshtenko
Yevgeniy Koshtenko

¿Qué es la liquidez?

La liquidez de los mercados financieros es la "saturación" del mercado con dinero en forma de órdenes y posiciones. Esto permite a los operadores vender rápidamente acciones (o divisas) por grandes cantidades. Cuanto mayor es la liquidez del mercado, más fácil es vender o comprar un activo por grandes cantidades sin pérdidas significativas debidas al deslizamiento. 

El deslizamiento es el principal mal de los grandes operadores: los fondos más grandes observan que no es tan fácil manejar una posición grande, y a menudo la operación se cierra con pérdidas sólo por el "deslizamiento" de la orden. El deslizamiento de órdenes se produce cuando una operación se abre a un precio y se ejecuta a otro distinto del previsto. Cuando un operador sólo dispone de un par de cientos de dólares, no suele haber problemas de liquidez (salvo en el caso de mercados completamente ilíquidos de criptodivisas de tercera categoría). Pero cuando se trata de cientos de millones de dólares, es difícil abrir y cerrar una posición al mismo tiempo. Esto está directamente relacionado con la liquidez del mercado.

La liquidez del mercado se llena gracias a los creadores de mercado. Su principal tarea es mantener la liquidez. Estos participantes en el mercado hacen todo lo posible para que la negociación sea lo más fluida posible para usted, de modo que no haya diferencias bruscas en las cotizaciones y tanto un comprador como un vendedor reciban siempre precios que les convengan.

En un mercado sin creadores de mercado, muy a menudo veremos fuertes oscilaciones de los precios en una dirección, enormes fluctuaciones de los activos y brechas en las cotizaciones.


¿Cómo funciona un creador de mercado y por qué no es un "titiritero"?

Muchos operadores confían en que el creador de mercado es una especie de titiritero, un manipulador que mueve los precios donde él quiere, rompe los niveles de stop, engaña a la multitud con órdenes de stop, etc.

De hecho, el creador de mercado no necesita hacer que la "multitud" pierda en absoluto. La "multitud" del mercado pierde por sí sola debido a los diferenciales, las comisiones y los swaps. 

En cuanto a los desplazamientos del mercado en la dirección correcta, tampoco es tarea de un creador de mercado. Todo lo que un creador de mercado está obligado a hacer en virtud de su acuerdo con la bolsa es proporcionar una cotización de compra a un comprador y una cotización de venta a un vendedor, así como rellenar la "profundidad de mercado" vacía si es necesario.

Sin creadores de mercado, el mercado sería completamente diferente: veríamos constantemente huecos de precios, huecos de cotizaciones, constantes apretones en ambas direcciones, así como enormes saltos de precios en ambas direcciones. Todo esto aún se puede encontrar hoy en día en aquellos mercados donde no es rentable la presencia de un creador de mercado, por ejemplo, en muchas acciones de centavo de EE. UU.


Nuevas tecnologías AMM en el mercado de criptomonedas

Pero, ¿y si sustituimos a un participante por un contrato inteligente? En otras palabras, ¿qué pasaría si en lugar de creadores de mercado creáramos un sistema automático de ajuste de la oferta y la demanda, así como de la cotización general?

Así es como aparecieron las bolsas descentralizadas (DEX). Fueron los primeros en utilizar el mecanismo AMM (Automated Market Making / Creación automática de mercado). El algoritmo AMM funciona a través de un fondo de liquidez especial que utiliza los recursos de los participantes para las transacciones entre ellos. El precio y el volumen de los intercambios están siempre controlados por el algoritmo. Esto permite reunir a todos los vendedores con todos los compradores supuestamente sin pérdidas para los participantes. En realidad, sin embargo, todas los DEX (bolsas descentralizadas), tienen enormes desviaciones de precios. Se le garantiza que perderá un gran porcentaje en el intercambio de tokens en caso de un gran volumen de transacciones.

Además, esta innovación no ha eliminado las manipulaciones del mercado. Hay muchos en una DEX. Incluso los creadores de tokens en una DEX pueden bombear fácilmente sus tokens y hacer efectivo todo el fondo de liquidez de tokens.

¿Cómo combaten los creadores de mercado las manipulaciones de precios?

Aunque esto no es responsabilidad de los creadores de mercado, a menudo sofocan de raíz los intentos de organizar un plan de "pump and dump" cuando los precios apenas empiezan a subir por culpa de participantes fraudulentos. En estas fases iniciales, el creador de mercado lanza enormes cantidades de órdenes limitadas al jugador que intenta hacer subir los precios "de mercado". Esto extingue la demanda, por lo que los recién llegados al esquema de "pump and dump" muy a menudo se estrellan contra el creador de mercado. Pero si la bomba está bien planificada, la afluencia de muchas órdenes de mercado, que mueven poderosamente el precio, obliga al creador de mercado a abandonar temporalmente el mercado.


¿Cuándo abandonan el mercado los creadores de mercado?

La mayoría de los creadores de mercado estipulan en sus acuerdos con las bolsas que desconecten sus algoritmos y abandonen el mercado durante las vacaciones, los periodos de actividad anormal y los periodos de publicación de noticias importantes. Esto se debe al deseo de los creadores de mercado de preservar su capital. 

Podemos ver al creador de mercado abandonando el mercado inmediatamente por el diferencial ampliado. ¿Has visto cómo el diferencial se amplía incluso en el ECN en el lanzamiento de noticias globales de gran alcance? La estrechez habitual de los diferenciales se consigue gracias a los esfuerzos de los creadores de mercado. Por lo tanto, sin ellos, nos enfrentaremos a muy malas condiciones de negociación, entre otras cosas, amplios diferenciales, grandes deslizamientos de precios, caídas repentinas y picos de precios: todas las delicias salvajes del mercado.


¿Qué es el riesgo de inventario del creador de mercado?

Mucha gente piensa que un creador de mercado no asume ningún riesgo. Sin embargo, este no es el caso. El principal riesgo de un creador de mercado es el riesgo de inventario. Este riesgo radica en el hecho de que una posición puede moverse bruscamente en una dirección sin la posibilidad de deshacerse de ella y ganar dinero con el diferencial. Por ejemplo, cuando una multitud frenética vende un activo, el creador de mercado se ve obligado a comprar toda la oferta. Como resultado, el precio entra en negativo y el creador de mercado sufre pérdidas. 

Las empresas intentan evitar este riesgo utilizando ecuaciones especiales de centrado de diferenciales y determinando el precio óptimo de compra y venta. Pero esto no siempre es posible. Aunque el precio no sea óptimo, el trabajo del creador de mercado es suministrar liquidez al mercado, y debe hacerlo, aunque temporalmente opere con pérdidas. 

Análisis de los registros del mayor creador de mercado del planeta: la empresa de Kenneth Griffin

Al analizar la actividad del mayor creador de mercado del mundo, Citadel Securities, fundado por Kenneth Griffin, queda clara la importancia de su papel en los mercados financieros.

Los informes de la empresa muestran un impacto impresionante: 7 de cada 10 operaciones en el mercado bursátil estadounidense dependen de la liquidez proporcionada por este creador de mercado. Esta actividad demuestra el importante papel de Citadel Securities en el mantenimiento de la estabilidad y la disponibilidad de liquidez en este mercado.

Para evaluar la magnitud de la influencia de la empresa de Griffin, cabe mencionar que cada día pasan por sus algoritmos unos 900 millones de lotes de acciones estadounidenses. Este importante volumen de negociación refleja la gran actividad e influencia de la empresa en la bolsa estadounidense.

Por cierto, la evolución de Kenneth Griffin pasando del trading como operador a la creación de mercado es muy interesante. La empresa de Griffin se está expandiendo muy activamente en los mercados mundiales, explorando activamente las bolsas asiáticas y proporcionando liquidez en ellas.

 

Preparación de un EA de creador de mercado

Entonces, hemos entendido la teoría. ¡Es hora de empezar a crear un EA creador de mercado! Por supuesto, nuestro algoritmo será muy sencillo. No construiremos el trading de diferencial según ecuaciones especiales. 

En su lugar, implementaremos el algoritmo más simple que mantendrá dos órdenes límite constantemente abiertas - límite de venta y límite de compra.

La implementación más sencilla de la creación de mercado en MQL5

Analicemos el código de nuestro algoritmo. Encabezamiento del código. Esta sección establece los parámetros básicos de la estrategia, como el tamaño del lote, los niveles de beneficio, el número mágico del EA, los pares de divisas seleccionados para operar, etc. :

//+------------------------------------------------------------------+
//|                                                  MarketMaker.mq5 |
//|                                Copyright 2023, Evgeniy Koshtenko |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, Evgeniy Koshtenko"
#property link      "https://www.mql5.com/es/users/koshtenko"
#property version   "1.00"

#include <Trade\Trade.mqh>        // Include the CTrade trading class

//--- input parameters
input double Lots       = 0.1;    // lot
input double Profit     = 0.1;    // profit
input double BProfit    = 11;     // buy profit
input double SProfit    = 11;     // sell profit
input int StopLoss      = 0;      // stop loss
input int TakeProfit    = 0;      // take profit
input int    Count      = 5;      // number of orders
input int    Delta      = 55;     // delta
input int    Magic      = 123;    // magic number

input bool   BuyLimit   = 1;      // Buy Limit
input bool   SellLimit  = 1;      // Sell Limit

input string Symbol1    = "EURUSD";
input string Symbol2    = "GBPUSD";
input string Symbol3    = "USDCHF";
input string Symbol4    = "USDJPY";
input string Symbol5    = "USDCAD";
input string Symbol6    = "AUDUSD";
input string Symbol7    = "NZDUSD";
input string Symbol8    = "EURGBP";
input string Symbol9    = "CADCHF";
input int MaxOrders = 20; // Max number of orders
CTrade trade;

datetime t=0;
int delta=0;

Incluye ajustes básicos como delta entre órdenes, beneficio de cierre (total, beneficio de compra y beneficio de venta), número mágico de EA, importación de biblioteca de operaciones, así como selección de pares de divisas para operar y limitación del número de órdenes.

Las funciones de inicialización y desinicialización suelen ser estándar. La función OnInit() es llamada cuando el EA comienza, y OnDeinit() es llamada cuando termina. OnInit() establece el número mágico del EA y el temporizador de la función de negociación:

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   // Set a timer with a resolution of 10000 milliseconds (10 seconds) 
   EventSetMillisecondTimer(100000);
   trade.SetExpertMagicNumber(Magic);
//---
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {// Disable timer
   EventKillTimer();
   Comment("");
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+

Estas son las funciones para contar las órdenes y posiciones abiertas. CountOrders y CountTrades cuentan las órdenes y posiciones abiertas para un símbolo específico teniendo en cuenta el número mágico del EA.

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int CountOrders(string symbol, ENUM_ORDER_TYPE orderType) {
  int count = 0;
  
  for(int i = OrdersTotal()-1; i >= 0; i--) {
      
    ulong ticket = OrderGetTicket(i);
      
    if(!OrderSelect(ticket)) {
      continue;
    }
      
    if(OrderGetInteger(ORDER_TYPE) != orderType) {
      continue;
    }
    
    if(PositionGetString(POSITION_SYMBOL) != symbol ||
       PositionGetInteger(POSITION_MAGIC) != Magic) {
      continue; 
    }
      
    count++;
  }
  
  return count;
}
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int CountTrades(string symbol, ENUM_POSITION_TYPE type) {
  int count = 0;
  
  for(int i=PositionsTotal()-1; i>=0; i--) {
    
    ulong ticket=PositionGetTicket(i);
      
    if(!PositionSelectByTicket(ticket)) {
      continue;
    }
    
    if(PositionGetString(POSITION_SYMBOL)==symbol && 
       PositionGetInteger(POSITION_TYPE)==type) {
        
      count++;
    }
  }
  
  return count;
}

Estas son las funciones para borrar órdenes, calcular beneficios y cerrar órdenes. DelOrder borra todas las órdenes de un símbolo específico utilizando un número mágico. AllProfit calcula el beneficio total o el beneficio de las operaciones de compra/venta para un símbolo específico teniendo en cuenta el número mágico.

//+------------------------------------------------------------------+
//|  Position Profit                                                 |
//+------------------------------------------------------------------+
double AllProfit(string symbol, int positionType = -1) {

  double profit = 0;

  for(int i = PositionsTotal()-1; i >= 0; i--) {

    ulong ticket = PositionGetTicket(i);

    if(!PositionSelectByTicket(ticket)) {
      continue;
    }

    if(PositionGetString(POSITION_SYMBOL) != symbol ||
       PositionGetInteger(POSITION_MAGIC) != Magic) {
      continue;
    }

    if(positionType != -1 && 
       PositionGetInteger(POSITION_TYPE) != positionType) {
      continue;
    }

    profit += PositionGetDouble(POSITION_PROFIT);

  }

  return profit;

}
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CloseAll(string symbol, int positionType = -1) {

  for(int i = PositionsTotal()-1; i >= 0; i--) {

    ulong ticket = PositionGetTicket(i);

    if(!PositionSelectByTicket(ticket)) {
      continue;
    }

    if(PositionGetString(POSITION_SYMBOL) != symbol ||
       PositionGetInteger(POSITION_MAGIC) != Magic) {
      continue;
    }

    if(positionType != -1 && 
       PositionGetInteger(POSITION_TYPE) != positionType) {
      continue;  
    }

    trade.PositionClose(ticket);

  }

}

Por último, las dos funciones principales son la función de negociación y la función de tick. Trade se encarga de colocar órdenes de compra y venta limitadas teniendo en cuenta los parámetros especificados. OnTimer llama a la función Trade para negociar con el símbolo seleccionado y muestra información sobre los beneficios de ese símbolo.

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void Trade(string symb)
  {
   double sl = 0, tp = 0;
   double pr=0;
   double Bid=SymbolInfoDouble(symb,SYMBOL_BID);
  
   if(AllProfit(symb)>Profit && Profit>0)
      CloseAll(symb);
   
   if(AllProfit(symb)>Profit && Profit>0)
      CloseAll(symb);
      
   if(AllProfit(symb,0)>BProfit && BProfit>0)
      CloseAll(symb,0);
  
      for(int i=1; i<=Count; i++)
        {
         if(BuyLimit)
           {
           
            if (StopLoss > 0)
                sl = NormalizeDouble(Bid - (StopLoss) * Point(), _Digits);
            if (TakeProfit > 0)
                tp = NormalizeDouble(Bid + (TakeProfit) * Point(), _Digits);
                
            pr=NormalizeDouble(Bid-(Delta+Step)*_Point*i,_Digits);
            trade.BuyLimit(Lots,pr,symb,sl, tp,0,0,"");
           }
         if(SellLimit)
           {
            
            if (StopLoss > 0)
                sl = NormalizeDouble(Bid + (_Point * StopLoss) * Point(), _Digits);
            if (TakeProfit > 0)
                tp = NormalizeDouble(Bid - (_Point * TakeProfit) * Point(), _Digits);
                
            pr=NormalizeDouble(Bid+(Delta+Step)*_Point*i,_Digits);
            trade.SellLimit(Lots,pr,symb,sl, tp,0,0,"");
           }
         
        }
     
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTimer()
  {
   DelOrder();
   Trade(Symbol1);
   Trade(Symbol2);
   Trade(Symbol3);
   Comment("\n All Profit: ",AllProfit(Symbol1),
           "\n Buy Profit: ",AllProfit(Symbol1,0),
           "\n Sell Profit: ",AllProfit(Symbol1,1));
  }
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+--------+

Este es el código completo de este simple EA.

Resultados de las pruebas

Por lo tanto, vamos a lanzar el EA con la configuración por defecto en el probador. Aquí están los resultados del EA para EURUSD, GBPUSD, EURGBP, USDJPY y EURJPY desde el 1 de febrero de 2023 hasta el 18 de febrero de 2024:

Prueba del EA

Las potenciales pérdidas en relación con las ganancias son muy grandes. El retroceso en el patrimonio generalmente es mayor que la ganancia anual. El EA no se comporta de forma muy diferente a los EA de cuadrícula normales. Aquí están las estadísticas de la prueba:

Estadísticas de las pruebas

Aparentemente, este EA no compensa sus riesgos de ninguna manera. Como cualquier algoritmo sin nivel de parada, es una bomba de relojería. A pesar de que no muestra pérdidas, nadie puede garantizar que el mercado no experimente el desplome de las divisas en un 10-15% diario. Personalmente, los últimos cuatro años me han enseñado que absolutamente todo es posible en el mercado, e incluso los escenarios más increíbles pueden hacerse realidad, por lo que un EA versátil debe estar preparado para todo. Este EA no cumple mis criterios de evaluación, por lo que he decidido publicarlo.

Conclusión

Así pues, hemos creado un ejemplo del algoritmo de creador de mercado más sencillo. Por supuesto, este ejemplo es ilustrativo y muy sencillo. Obviamente, ni un solo creador de mercado ha trabajado así en el mercado durante mucho tiempo. Hoy en día, sus algoritmos se mantienen al día, utilizan machine learning y redes neuronales, aplican deep learning basado en datos de streaming del libro de órdenes, y tienen en cuenta muchas variables y características de los precios. Ya nadie hace pedidos por encima y por debajo del precio: esto está plagado de riesgos de inventario. En el futuro, puede ser razonable experimentar con la creación de un creador de mercado mediante aprendizaje automático, que determine por sí mismo el delta óptimo entre órdenes.


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

Archivos adjuntos |
Experts.zip (33.42 KB)
Implementación en MQL5 de la prueba de Augmented Dickey-Fuller (ADF) Implementación en MQL5 de la prueba de Augmented Dickey-Fuller (ADF)
En este artículo demostramos la implementación de la prueba Dickey-Fuller aumentada (ADF, por sus siglas en inglés), y la aplicamos para realizar pruebas de cointegración utilizando el método Engle-Granger.
Introducción a MQL5 (Parte 3): Estudiamos los elementos básicos de MQL5 Introducción a MQL5 (Parte 3): Estudiamos los elementos básicos de MQL5
En este artículo, seguiremos estudiando los fundamentos de la programación MQL5. Hoy veremos los arrays, las funciones definidas por el usuario, los preprocesadores y el procesamiento de eventos. Para una mayor claridad, todos los pasos de cada explicación irán acompañado de un código. Esta serie de artículos sienta las bases para el aprendizaje de MQL5, prestando especial atención a la explicación de cada línea de código.
Aprendizaje automático y Data Science (Parte 18): La batalla por dominar la complejidad del mercado: SVD truncado frente a NMF Aprendizaje automático y Data Science (Parte 18): La batalla por dominar la complejidad del mercado: SVD truncado frente a NMF
La descomposición del valor singular truncado (SVD, Singular Value Decomposition) y la factorización de matrices no negativas (NMF, Non-Negative Matrix Factorization) son técnicas de reducción de la dimensionalidad. Ambos desempeñan un papel importante en la elaboración de estrategias de negociación basadas en datos. Descubra el arte de reducir la dimensionalidad, desentrañar ideas y optimizar los análisis cuantitativos para obtener un enfoque informado que le permita navegar por las complejidades de los mercados financieros.
El tipo de dibujado DRAW_ARROW en indicadores de símbolo y periodo múltiple El tipo de dibujado DRAW_ARROW en indicadores de símbolo y periodo múltiple
En este artículo nos ocuparemos de dibujar los indicadores de símbolo y periodo múltiple. Asimismo, mejoraremos los métodos de la clase para representar correctamente las flechas que muestran los datos de los indicadores de flecha calculados sobre un símbolo/periodo que no se corresponde con el símbolo/periodo del gráfico actual.