English Русский Español Deutsch 日本語
preview
Criando um algoritmo de market making no MQL5

Criando um algoritmo de market making no MQL5

MetaTrader 5Negociação | 17 junho 2024, 16:43
144 0
Yevgeniy Koshtenko
Yevgeniy Koshtenko

O que é liquidez

A liquidez dos mercados financeiros é a "abundância" de dinheiro no mercado na forma de ordens e posições. Isso permite a rápida realização de ações (ou moedas) em grandes quantias. Quanto maior a liquidez do mercado, mais fácil é vender ou comprar um ativo em grandes quantias sem perdas significativas devido ao slippage. 

O slippage é o grande inimigo dos grandes jogadores: os maiores fundos observam que concretizar uma posição grande não é fácil, e muitas vezes a negociação fecha com prejuízo apenas devido às perdas no "deslizamento" das ordens. O slippage ocorre quando a negociação é aberta a um preço e realizada a outro, diferente do preço esperado. Quando o trader tem apenas algumas centenas de dólares, normalmente não há problemas de liquidez, exceto em mercados de criptomoedas de baixa liquidez. Mas quando estamos falando de centenas de milhões de dólares, abrir e fechar uma posição de uma vez é difícil. Isso está diretamente relacionado à abundância de liquidez no mercado.

E a liquidez do mercado é mantida graças aos market makers, ou formadores de mercado. A principal tarefa deles é manter a liquidez. Eles fazem de tudo para que o trading seja o mais suave possível, sem grandes gaps, e para que compradores e vendedores sempre obtenham preços convenientes.

Em um mercado sem market makers, veríamos frequentemente movimentos bruscos de preço, grandes oscilações do ativo e gaps.


Como age um market maker, e por que ele não é um "manipulador"?

Muitos traders acreditam que o market maker é um manipulador que move os preços conforme deseja, tirando stop losses da multidão e forçando-a a ordens de stop.

Na verdade, o market maker não precisa "derrotar" a multidão. A "multidão" se prejudica sozinha devido à perda gradual no spread, comissão e swaps. 

Quanto aos movimentos do mercado na direção desejada, isso também não é responsabilidade do market maker. Tudo o que ele deve fazer, conforme seu contrato com a bolsa, é fornecer cotações de compra para compradores e cotações de venda para vendedores, preenchendo o "livro de ofertas" conforme necessário.

Sem os market makers, o mercado seria completamente diferente: veríamos gaps frequentes, gaps nas cotações, contrações constantes em ambas as direções e grandes oscilações de preços. Isso é visível hoje em mercados onde não é lucrativo para os market makers estarem presentes, como em muitas ações de centavos nos EUA (penny stocks).


Novas tecnologias de AMM no mercado cripto

E se substituirmos os market makers por um smart contract? Ou seja, criar um sistema automático de ajuste de demanda e oferta?

Foi mais ou menos assim que surgiram as bolsas descentralizadas (DEX), onde o mecanismo AMM (automated market making, ou formação automática de mercado) foi usado pela primeira vez. O algoritmo AMM funciona através de um pool de liquidez, utilizando os recursos dos participantes para negociações entre si, controlando sempre o preço e o volume das trocas. Isso teoricamente permite unir vendedores e compradores sem perdas para os participantes. Na prática, todas as DEXs sofrem grande slippage, e em grandes volumes de negociação, você garantidamente perderá uma boa porcentagem na troca de tokens.

Além disso, essa inovação não eliminou as manipulações no mercado, que são abundantes nas DEXs. Até mesmo o criador de um token pode facilmente inflar artificialmente (pump and dump) seu próprio token, esvaziando todo o pool de liquidez.

Como os market makers combatem as manipulações de preços?

Embora não seja sua obrigação, os market makers frequentemente sufocam tentativas de Pump&Dump no início, quando os fraudadores começam a elevar os preços. Nesses casos, o market maker coloca grandes ordens limit para evitar o aumento de preços. Isso diminui a demanda, e iniciantes no esquema de pump and dump muitas vezes falham por causa do market maker. Mas se o pump for bem planejado e executado, a enxurrada de ordens de mercado forçando os preços obriga o market maker a se retirar temporariamente.


Quando os market makers saem do mercado?

A maioria dos market makers tem em seus contratos com as bolsas a opção de desativar seus algoritmos e sair do mercado durante feriados, períodos de atividade anormal e divulgação de notícias importantes. Isso visa proteger o capital dos market makers de perdas. 

A saída dos market makers é imediatamente visível pelo spread alargado. Já viu o spread se alargar mesmo em ECNs durante grandes notícias mundiais? A estreiteza usual do spread é graças aos market makers. Sem eles, enfrentamos condições de trading muito desfavoráveis: spreads largos, grandes slippages e movimentos bruscos de preços, isto é, todas as características de um mercado selvagem.


O que é o risco de inventário para um market maker?

Muitos pensam que o market maker não corre riscos. Mas não é assim. O principal risco do market maker é o risco de inventário, ou inventory risk. Isso ocorre quando há uma acumulação repentina de posições em uma direção sem possibilidade de concretizá-las e lucrar com o spread. Por exemplo, quando a multidão vende um ativo sem parar e o market maker tem que comprar toda a oferta, a queda do preço leva o market maker ao prejuízo. 

As empresas tentam evitar esse risco usando fórmulas especiais para centralizar o spread e determinar o preço ideal de compra e venda. Mas isso nem sempre é possível: mesmo que o preço não seja ótimo, sua função é fornecer liquidez ao mercado, mesmo que isso signifique operar com prejuízo temporário. 

Analisando o relatório do maior market maker do planeta - Citadel Securities

Após analisar a atividade do maior market maker do mundo, Citadel Securities, fundada por Ken Griffin, fica claro o quão importante é o papel deles nos mercados financeiros.

Os relatórios da empresa mostram um impacto impressionante: 7 em cada 10 negociações no mercado de ações dos EUA dependem da liquidez fornecida por esse market maker. Isso destaca a função vital da Citadel Securities em manter a estabilidade e a disponibilidade de liquidez no mercado.

Para entender a magnitude da influência da Citadel, vale mencionar que cerca de 900 milhões de lotes de ações dos EUA passam por seus algoritmos diariamente. Esse volume significativo de negociações reflete a alta atividade e influência da empresa na bolsa de valores americana.

É realmente interessante observar a evolução de Ken Griffin, que passou da negociação direcionada para o market making. A empresa de Griffin, Citadel Securities, está expandindo ativamente para os mercados globais, especialmente nas bolsas asiáticas, onde tem fornecido liquidez. Em outras circunstâncias, ela também poderia fornecer liquidez na Bolsa de Moscou.

No mercado de ações russo, a principal empresa de market making é a BrokerCreditService, ou simplesmente BKS, que cota quase todas as ações de alta liquidez do primeiro escalão. Outros market makers incluem Finam, ALOR e o relativamente desconhecido banco Derzhava. 

Essas empresas não divulgam relatórios específicos de lucros e perdas, assim como seus colegas ocidentais. No entanto, há uma tendência clara de que, no futuro, surgirão entidades jurídicas separadas dedicadas exclusivamente ao market making, como a divisão de Griffin.

Criando um Expert Advisor - market maker

Agora que entendemos a teoria, é hora de partir para a prática e criar um Expert Advisor (EA) para market making! Claro, nosso algoritmo será bem simples e elementar. Não vamos tentar implementar estratégias de trading com spread utilizando fórmulas complexas descritas por especialistas. 

Em vez disso, vamos implementar o algoritmo mais básico, que manterá duas ordens limit constantemente abertas: uma acima do preço atual para venda (sell limit) e outra abaixo do preço atual para compra (buy limit).

Implementação mais simples de market making no MQL5

Vamos analisar o código do nosso algoritmo. A parte do título do código. A seção inicial do código define os parâmetros básicos da estratégia, como tamanho do lote, níveis de lucro, número mágico do EA, pares de moedas selecionados para trading, etc.

//+------------------------------------------------------------------+
//|                                                  MarketMaker.mq5 |
//|                                Copyright 2023, Evgeniy Koshtenko |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, Evgeniy Koshtenko"
#property link      "https://www.mql5.com/pt/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;

Inclui configurações básicas, como delta entre ordens, lucro de fechamento (geral, de compra e de venda), número mágico do EA, importação da biblioteca de trading e escolha dos pares de moedas para trading, além de limitar o número de ordens.

As funções de inicialização e desinicialização são padrão. A função OnInit() é chamada ao iniciar o EA, e OnDeinit() ao encerrá-lo. OnInit() define o número mágico do EA e o temporizador para a função de trading.

//+------------------------------------------------------------------+
//| 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("");
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+

Aqui estão as funções de contagem de ordens abertas e posições. CountOrders e CountTrades contabilizam as ordens abertas e posições para um determinado símbolo, considerando o número mágico do 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;
}

Aqui estão as funções de exclusão de ordens, cálculo de lucro e fechamento de ordens. DelOrder exclui todas as ordens de um determinado símbolo, usando o número mágico. AllProfit calcula o lucro total ou o lucro de negociações de compra/venda para um símbolo específico, considerando o 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);

  }

}

E, finalmente, as duas funções principais: a função de trading e a função de tick. Trade é responsável por colocar ordens limit de compra e venda, considerando os parâmetros definidos. OnTimer chama a função Trade para negociar o símbolo selecionado e exibe informações sobre o lucro para esse 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));
  }
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+--------+

Esse é o código completo deste simples Expert Advisor.

Resultados do teste

Vamos executar o EA com as configurações padrão no testador. Aqui estão os resultados para os pares EURUSD, GBPUSD, EURGBP, USDJPY e EURJPY, para o período de 1 de fevereiro de 2023 a 18 de fevereiro de 2024:

Teste do EA

Os drawdowns, ou rebaixamentos, em relação aos lucros são muito grandes, com drawdowns maiores que o lucro anual. O EA se comporta de maneira semelhante aos EAs de grid comuns. Aqui estão as estatísticas do teste:

Estatísticas de teste

Chegamos à conclusão de que este EA não compensa os riscos. Como qualquer algoritmo sem stop loss, é uma bomba-relógio. Apesar de não haver perdas significativas, não é garantido que o mercado não repita uma queda de 10-15% em um dia. Nos últimos quatro anos, aprendi que no mercado tudo é possível, até mesmo os cenários mais improváveis, então um EA deve estar preparado para tudo. Este Expert Advisor não atende aos meus critérios de avaliação, por isso decidi publicá-lo.

Considerações finais

Criamos um exemplo de algoritmo de market making. Claro, este exemplo é ilustrativo e muito simples, portanto é óbvio que nenhum market maker opera assim hoje em dia. Atualmente, seus algoritmos estão atualizados, utilizando aprendizado de máquina e redes neurais, aprendizado profundo baseado em dados de fluxo de ordens, considerando muitas variáveis e características de preço. Ninguém mais coloca ordens apenas ao redor do preço, já que isso é arriscado devido ao inventory risk. No futuro, pode ser interessante experimentar criar um market maker com aprendizado de máquina, que determinará automaticamente a delta ideal entre as ordens.


Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/13897

Arquivos anexados |
Experts.zip (33.42 KB)
Aprendendo MQL5 do iniciante ao profissional (Parte II): Tipos de dados básicos e uso de variáveis Aprendendo MQL5 do iniciante ao profissional (Parte II): Tipos de dados básicos e uso de variáveis
Continuação da série para iniciantes. Aqui veremos como criar constantes e variáveis, registrar datas, cores e outros dados úteis. Aprenderemos a criar enumerações como dias da semana ou estilos de linha (contínua, tracejada etc.). Variáveis e expressões são a base da programação. Elas estão em 99% dos programas, portanto é fundamental entendê-las. Se você é novato em programação, este é um bom ponto de partida. Se o nível de conhecimento em programação é muito básico, conforme meu artigo anterior (link no início).
Desenvolvendo um sistema de Replay (Parte 53): Complicando as coisas (V) Desenvolvendo um sistema de Replay (Parte 53): Complicando as coisas (V)
Neste artigo irei introduzir um tema muito importante, porém que poucos de fato compreender. Eventos Customizados. Perigos. Vantagens e falhas causados por tais coisas. Este assunto é muito importante para quem deseja se tornar um programador profissional em MQL5, ou em qualquer outro tipo de linguagem. Mas aqui iremos focar no MQL5 e no MetaTrader 5.
Algoritmos de otimização populacional: sistema imune micro-artificial (Micro Artificial Immune System, Micro-AIS) Algoritmos de otimização populacional: sistema imune micro-artificial (Micro Artificial Immune System, Micro-AIS)
Este artigo fala sobre um método de otimização baseado nos princípios de funcionamento do sistema imunológico do organismo — Micro Artificial Immune System (Micro-AIS) — uma modificação do AIS. O Micro-AIS utiliza um modelo mais simples do sistema imunológico e operações mais simples de processamento de informações imunológicas. O artigo também aborda as vantagens e desvantagens do Micro-AIS em comparação com o AIS tradicional.
Redes neurais de maneira fácil (Parte 71): Previsão de estados futuros com base em objetivos (GCPC) Redes neurais de maneira fácil (Parte 71): Previsão de estados futuros com base em objetivos (GCPC)
Nos trabalhos anteriores, conhecemos o método Decision Transformer e vários algoritmos derivados dele. Experimentamos com diferentes métodos de definição de objetivos. Durante os experimentos, trabalhamos com diferentes maneiras de definir objetivos, mas o estudo da trajetória já percorrida pelo modelo sempre ficou fora de nosso foco. Neste artigo, quero apresentar um método que preenche essa lacuna.