English Русский 日本語
preview
Erstellen eines Market-Making-Algorithmus in MQL5

Erstellen eines Market-Making-Algorithmus in MQL5

MetaTrader 5Handel | 9 Mai 2024, 09:52
128 0
Yevgeniy Koshtenko
Yevgeniy Koshtenko

Was ist Liquidität?

Die Liquidität der Finanzmärkte ist die „Sättigung“ des Marktes mit Geld in Form von Aufträgen und Positionen. Auf diese Weise können Händler schnell Aktien (oder Währungen) für große Beträge verkaufen. Je höher die Marktliquidität ist, desto leichter ist es, einen Vermögenswert für große Beträge zu verkaufen oder zu kaufen, ohne dass es zu erheblichen Verlusten aufgrund von Slippage kommt. 

Slippage ist das Hauptübel der großen Marktteilnehmer: Die größten Fonds stellen fest, dass es nicht so einfach ist, eine große Position zu handhaben, und oft wird die Transaktion nur aufgrund von „Slippage“ mit Verlust abgeschlossen. Auftrags-Slippage liegt vor, wenn ein Handelsgeschäft zu einem bestimmten Preis eröffnet und zu einem anderen als dem erwarteten Preis ausgeführt wird. Wenn ein Händler nur ein paar hundert Dollar hat, gibt es in der Regel keine Probleme mit der Liquidität (außer bei völlig illiquiden Markttiefen drittklassiger Kryptowährungen). Aber wenn es um Hunderte von Millionen Dollar geht, ist es schwierig, eine Position gleichzeitig zu eröffnen und zu schließen. Dies steht in direktem Zusammenhang mit der Marktliquidität.

Die Liquidität auf dem Markt ist dank der Market Maker gegeben. Ihre Hauptaufgabe ist es, die Liquidität zu erhalten. Diese Marktteilnehmer tun alles, um den Handel für Sie so reibungslos wie möglich zu gestalten, sodass es keine großen Kursunterschiede gibt und sowohl Käufer als auch Verkäufer immer die für sie passenden Preise erhalten.

Auf einem Markt ohne Market Maker kommt es sehr häufig zu starken Kursschwankungen in eine Richtung, zu großen Vermögensschwankungen und Kurslücken.


Wie funktioniert ein Market Maker, und warum ist er kein „Puppenspieler“?

Viele Händler sind davon überzeugt, dass der Market Maker eine Art Puppenspieler ist - ein Manipulator, der die Kurse dorthin bewegt, wo er sie haben will, der die Stop-Levels bricht, der die Menge mit Stop-Orders austrickst usw.

Tatsächlich muss der Market Maker die „Masse“ gar nicht zum Verlieren bringen. Die „Masse“ verliert im Markt aufgrund von Spreads, Provisionen und Swaps von sich aus. 

Marktverschiebungen in die richtige Richtung sind auch nicht die Aufgabe eines Market Makers. Ein Market Maker ist im Rahmen seines Vertrages mit der Börse lediglich dazu verpflichtet, einem Käufer einen Kaufkurs und einem Verkäufer einen Verkaufskurs zu stellen sowie gegebenenfalls die leere „Markttiefe“ zu füllen.

Ohne Market Maker sähe der Markt völlig anders aus: Wir würden ständig Preislücken, Kurslücken, ständige Engpässe in beide Richtungen sowie riesige Preissprünge in beide Richtungen erleben. All dies ist auch heute noch auf den Märkten zu finden, auf denen es für einen Market Maker unrentabel ist, präsent zu sein, zum Beispiel bei vielen US-Penny Stocks.


Neue AMM-Technologien auf dem Kryptomarkt

Was aber, wenn wir einen Teilnehmer durch einen intelligenten Vertrag ersetzen? Mit anderen Worten: Was wäre, wenn wir anstelle von Market Makern ein automatisches System zur Anpassung von Angebot und Nachfrage sowie der allgemeinen Notierung einrichten würden?

Dies ist in etwa die Entstehungsgeschichte der dezentralen Börsen (DEX). Sie waren die ersten, die den AMM-Mechanismus (Automated Market Making) einsetzten. Der AMM-Algorithmus funktioniert über einen speziellen Liquiditätspool, der die Ressourcen der Teilnehmer für Transaktionen zwischen ihnen nutzt. Der Preis und das Volumen der Börsen werden immer vom Algorithmus gesteuert. Dies ermöglicht es, alle Verkäufer mit allen Käufern vermeintlich ohne Verluste für die Teilnehmer zusammenzubringen. In Wirklichkeit weisen jedoch alle DEX große Kursschwankungen auf. Im Falle eines großen Transaktionsvolumens verlieren Sie an der Token-Börse garantiert einen großen Prozentsatz.

Außerdem hat diese Innovation Marktmanipulationen nicht verhindert. Davon gibt es viele auf einem DEX. Selbst Token-Ersteller auf einem DEX können ihre Token leicht pumpen und den gesamten Token-Liquiditätspool auszahlen.

Wie bekämpfen Market Maker Preismanipulationen?

Obwohl dies nicht in der Verantwortung der Market Maker liegt, lassen sie Versuche, ein Pump-and-Dump-System zu arrangieren, oft schon im Keim ersticken, wenn die Preise durch betrügerische Teilnehmer gerade erst in die Höhe getrieben werden. In dieser Anfangsphase wirft der Market Maker dem Marktteilnehmer, der versucht, die „Markt“-Preise nach oben zu treiben, riesige Mengen an Limit-Aufträgen zu. Dadurch wird die Nachfrage ausgelöscht, sodass sich Neulinge im Pumpensystem sehr oft die Zähne an den Market Makern ausbeißen. Aber wenn das „Pumpen“ gut geplant ist, zwingt der Zustrom vieler Marktaufträge, die den Preis stark bewegen, den Market Maker, den Markt vorübergehend zu verlassen.


Wann verlassen die Market Maker den Markt?

Die meisten Market Maker haben in ihren Vereinbarungen mit den Börsen festgelegt, dass sie ihre Algorithmen abschalten und den Markt während der Feiertage, in Zeiten ungewöhnlicher Aktivität und in Zeiten wichtiger Nachrichten verlassen. Dies ist auf den Wunsch der MM zurückzuführen, ihr Kapital zu erhalten. 

Wir sehen, dass der Market Maker den Markt sofort verlässt, indem er den Spread erweitert. Haben Sie gesehen, wie sich der Spread sogar auf dem ECN bei starken globalen Nachrichten ausweitet? Die übliche Spread-Eingrenzung wird durch die Bemühungen der Market Maker erreicht. Ohne sie werden wir daher unter anderem mit sehr schlechten Handelsbedingungen konfrontiert, einschließlich großer Spreads, großer Kursabweichungen, plötzlicher Einbrüche und Preisspitzen - alles wilde Marktvergnügen.


Was ist das Bestandsrisiko des Market Makers?

Viele Menschen denken, dass ein Market Maker überhaupt keine Risiken trägt. Dies ist jedoch nicht der Fall. Das Hauptrisiko eines Market Makers ist das Bestandsrisiko. Dieses Risiko besteht darin, dass sich eine Position stark in eine Richtung bewegen kann, ohne dass die Möglichkeit besteht, sie zu verkaufen und mit dem Spread Geld zu verdienen. Wenn zum Beispiel eine rasende Menge einen Vermögenswert verkauft, ist der Market Maker gezwungen, das gesamte Angebot aufzukaufen. Infolgedessen geht der Kurs ins Minus und treibt den MM in die Verlustzone. 

Die Unternehmen versuchen, dieses Risiko zu vermeiden, indem sie spezielle Gleichungen zur Zentrierung der Spreads verwenden und den optimalen Preis für den An- und Verkauf ermitteln. Dies ist jedoch nicht immer möglich. Selbst wenn der Preis nicht optimal ist, ist es die Aufgabe der MM, den Markt mit Liquidität zu versorgen, und diese Aufgabe müssen sie erfüllen, auch wenn sie vorübergehend mit Verlust arbeiten. 

Analyse der Aufzeichnungen des größten Market Makers der Welt - das Unternehmen von Kenneth Griffin

Bei der Analyse der Tätigkeit des größten Market Makers der Welt - Citadel Securities, gegründet von Kenneth Griffin - wird deutlich, wie wichtig seine Rolle auf den Finanzmärkten ist.

Die Berichte des Unternehmens zeigen eine beeindruckende Wirkung: 7 von 10 Geschäften auf dem US-Aktienmarkt hängen von der Liquidität ab, die dieser Market Maker bereitstellt. Diese Aktivität zeigt die bedeutende Rolle von Citadel Securities bei der Aufrechterhaltung der Stabilität und Verfügbarkeit von Liquidität auf diesem Markt.

Um das Ausmaß des Einflusses von Griffins Unternehmen zu bewerten, sei erwähnt, dass täglich etwa 900 Millionen Losgrößen von US-Aktien durch seine Algorithmen laufen. Dieses bedeutende Handelsvolumen spiegelt die hohe Aktivität und den Einfluss des Unternehmens an der US-Börse wider.

Übrigens ist die Entwicklung von Kenneth Griffin, der vom gezielten Handel zum Market Making überging, sehr interessant. Griffins Unternehmen expandiert sehr aktiv in die globalen Märkte, erkundet aktiv die asiatischen Börsen und bietet dort Liquidität an.

 

Vorbereitung eines Market Maker EA

Wir haben also die Theorie herausgefunden. Es ist an der Zeit, einen Market Maker EA zu erstellen! Natürlich wird unser Algorithmus sehr einfach sein. Wir werden den Spread-Handel nicht nach speziellen Gleichungen aufbauen. 

Stattdessen werden wir den einfachsten Algorithmus implementieren, der zwei Limit-Aufträge ständig offen hält - Verkaufslimit und Kauflimit.

Die einfachste Implementierung von Market Making in MQL5

Analysieren wir den Code unseres Algorithmus. Code-Überschrift. In diesem Abschnitt werden die grundlegenden Parameter der Strategie festgelegt, z. B. die Losgröße, die Gewinnstufen, die MagicNumber des EA (Magic), die ausgewählten Währungspaare für den Handel, usw. :

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

Das umfasst grundlegende Einstellungen wie Delta zwischen Aufträgen, Schlussgewinn (Gesamt-, Kauf- und Verkaufsgewinn), die MagicNumber des EA, Import der Handelsbibliothek sowie die Auswahl von Währungspaaren für den Handel und die Begrenzung der Anzahl der Aufträge.

Die Initialisierungs- und Deinitialisierungsfunktionen sind im Allgemeinen Standard. Die Funktion OnInit() wird aufgerufen, wenn der EA startet, und OnDeinit() wird aufgerufen, wenn er endet. OnInit() setzt die MagicNumberl des EA und den Timer der Handelsfunktion:

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

Hier finden Sie die Funktionen zum Zählen offener Aufträge und offener Positionen. CountOrders und CountTrades zählen offene Aufträge und Positionen für ein bestimmtes Symbol unter Berücksichtigung der magischen Zahl des 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;
}

Hier finden Sie die Funktionen zum Löschen von Aufträgen, zur Gewinnberechnung und zum Schließen von Aufträgen. DelOrder löscht alle Aufträge für ein bestimmtes Symbol unter Verwendung der MagicNumber. AllProfit berechnet den Gesamtgewinn oder den Gewinn aus Kauf-/Verkaufstransaktionen für ein bestimmtes Symbol unter Berücksichtigung der MagicNumber.

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

  }

}

Die beiden wichtigsten Funktionen sind schließlich die Handelsfunktion und die Tickfunktion. Der Handel ist für die Erteilung von Limit-Kauf- und Limit-Verkaufsaufträgen unter Berücksichtigung der angegebenen Parameter zuständig. OnTimer ruft die Funktion Trade auf, um das ausgewählte Symbol zu handeln und zeigt Gewinninformationen für dieses Symbol an.

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

Dies ist der gesamte Code dieses einfachen EA.

Testergebnisse

Starten wir also den EA mit den Standardeinstellungen im Testprogramm. Hier sind die EA-Ergebnisse für EURUSD, GBPUSD, EURGBP, USDJPY und EURJPY vom 1. Februar 2023 bis zum 18. Februar 2024:

EA-Test

Die Drawdowns im Verhältnis zu den Gewinnen sind sehr hoch. Der Drawdown des Kapitals ist im Allgemeinen größer als der jährliche Gewinn. Der EA verhält sich nicht viel anders als normale Grid EAs. Hier sind die Teststatistiken:

Teststatistiken

Offensichtlich zahlt dieser EA seine Risiken in keiner Weise aus. Wie jeder Algorithmus, der nicht gestoppt werden kann, ist auch dieser eine Zeitbombe. Obwohl es keine Verluste zeigt, kann niemand garantieren, dass der Markt nicht den Zusammenbruch der Währungen um 10-15% pro Tag erleben wird. Mich persönlich haben die letzten vier Jahre gelehrt, dass auf dem Markt absolut alles möglich ist und selbst die unglaublichsten Szenarien wahr werden können, weshalb ein vielseitiger EA auf alles vorbereitet sein muss. Dieser EA entspricht nicht meinen Bewertungskriterien, daher habe ich beschlossen, ihn zu veröffentlichen.

Schlussfolgerung

Wir haben also ein Beispiel für den einfachsten Market-Maker-Algorithmus erstellt. Natürlich ist dieses Beispiel nur illustrativ und sehr einfach. Offensichtlich hat seit langem kein einziger Market Maker mehr auf diese Weise auf dem Markt gearbeitet. Heutzutage gehen ihre Algorithmen mit der Zeit, nutzen maschinelles Lernen und neuronale Netze, wenden Deep Learning auf der Grundlage von Streaming-Daten aus dem Orderbuch an und berücksichtigen zahlreiche Variablen und Preismerkmale. Niemand erteilt mehr Aufträge über und unter dem Preis - das birgt ein Bestandsrisiko. In Zukunft könnte es sinnvoll sein, mit einem Market Maker zu experimentieren, der mit Hilfe von maschinellem Lernen das optimale Delta zwischen den Aufträgen selbständig ermittelt.


Übersetzt aus dem Russischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/ru/articles/13897

Beigefügte Dateien |
Experts.zip (33.42 KB)
Entwicklung eines Replay Systems (Teil 33): Auftragssystem (II) Entwicklung eines Replay Systems (Teil 33): Auftragssystem (II)
Heute werden wir das Auftragssystem weiterentwickeln. Wie Sie sehen werden, werden wir in großem Umfang wiederverwenden, was bereits in anderen Artikeln gezeigt wurde. Dennoch werden Sie in diesem Artikel eine kleine Belohnung erhalten. Zunächst werden wir ein System entwickeln, das mit einem echten Handelsserver verwendet werden kann, sowohl von einem Demokonto als auch von einem echten Konto. Wir werden die Plattform MetaTrader 5 ausgiebig nutzen, die uns von Anfang an alle notwendige Unterstützung bietet.
Algorithmen zur Optimierung mit Populationen: Evolutionsstrategien, (μ,λ)-ES und (μ+λ)-ES Algorithmen zur Optimierung mit Populationen: Evolutionsstrategien, (μ,λ)-ES und (μ+λ)-ES
Der Artikel behandelt eine Gruppe von Optimierungsalgorithmen, die als Evolutionsstrategien (ES) bekannt sind. Sie gehören zu den allerersten Populationsalgorithmen, die evolutionäre Prinzipien für die Suche nach optimalen Lösungen nutzen. Wir werden Änderungen an den herkömmlichen ES-Varianten vornehmen und die Testfunktion und die Prüfstandsmethodik für die Algorithmen überarbeiten.
Algorithmen zur Optimierung mit Populationen: Mikro-Künstliches Immunsystem (Mikro-AIS) Algorithmen zur Optimierung mit Populationen: Mikro-Künstliches Immunsystem (Mikro-AIS)
Der Artikel befasst sich mit einer Optimierungsmethode, die auf den Prinzipien des körpereigenen Immunsystems basiert - Mikro-Künstliches Immunsystem (Micro Artificial Immune System, Micro-AIS) - eine Modifikation von AIS. Micro-AIS verwendet ein einfacheres Modell des Immunsystems und einfache Informationsverarbeitungsprozesse des Immunsystems. In dem Artikel werden auch die Vor- und Nachteile von Mikro-AIS im Vergleich zu herkömmlichen AIS erörtert.
Arbeiten mit ONNX-Modellen in den Datenformaten float16 und float8 Arbeiten mit ONNX-Modellen in den Datenformaten float16 und float8
Die Datenformate, die zur Darstellung von Modellen des maschinellen Lernens verwendet werden, spielen eine entscheidende Rolle für deren Effektivität. In den letzten Jahren sind mehrere neue Datentypen aufgetaucht, die speziell für die Arbeit mit Deep-Learning-Modellen entwickelt wurden. In diesem Artikel werden wir uns auf zwei neue Datenformate konzentrieren, die sich in modernen Modellen durchgesetzt haben.