
Formulierung eines dynamischen Multi-Pair EA (Teil 1): Währungskorrelation und inverse Korrelation
Einführung
Wenn Sie über eine solide Handelsstrategie oder ein System mit einer günstigen Gewinnrate oder einem günstigen Gewinnfaktor verfügen, kann die Diversifizierung von Handelsgeschäften über korrelierte und umgekehrt korrelierte Währungspaare die Gesamtperformance verbessern. Ich werde zeigen, wie man ein System entwickelt, das Korrelationen und umgekehrte Korrelationen zwischen mehreren Währungspaaren identifiziert und es Händlern ermöglicht, diese Beziehungen für bessere Handelsmöglichkeiten zu nutzen.
Bei wichtigen Handelsereignissen, wie z. B. der Bekanntgabe der Non-Farm Payroll (NFP), bewegt sich der Markt oft schnell in eine vorher festgelegte Richtung. In solchen Szenarien kann die Ausführung über mehrere Währungspaare hinweg durch die Festlegung eines Hauptwährungspaares rationalisiert werden. Die auf diesem primären Paar initiierten Geschäfte würden die entsprechenden Geschäfte auf anderen Paaren bestimmen, wobei die Korrelations- und Umkehrkorrelationsbeziehungen zwischen ihnen genutzt würden. Dieser Ansatz kann die Effizienz und Kohärenz bei einschneidenden Marktereignissen erheblich verbessern.
Was wird behandelt:
- Die Möglichkeit, Währungspaare zu ändern und zu modifizieren.
- Die Indizierung des Währungspaares, das als Signalgeber für andere Währungspaare dienen soll.
- Bestimmung der Basis- und Kurswährungen für den Handel.
Beim Handel bezieht sich die Korrelation auf die Beziehung zwischen den Kursbewegungen verschiedener Währungspaare. Wenn zwei Währungspaare positiv korreliert sind, tendieren sie dazu, sich in dieselbe Richtung zu bewegen. So sind beispielsweise GBPUSD und EURUSD häufig positiv korreliert, d. h. wenn GBPUSD steigt, steigt auch EURUSD tendenziell. Der Grund dafür ist, dass beide Paare den USD als Leitwährung haben und eine allgemeine Schwäche oder Stärke des USD sich wahrscheinlich auf beide Paare in gleicher Weise auswirken wird.
Eine umgekehrte Korrelation liegt hingegen vor, wenn sich zwei Währungspaare in entgegengesetzte Richtungen bewegen. Ein klassisches Beispiel ist die Beziehung zwischen GBPUSD und USDCAD. Wenn GBPUSD steigt (bullish), fällt oft der USDCAD (bearish). Dies liegt daran, dass beim ersten Paar (GBPUSD) der USD die Kurswährung ist, während beim zweiten Paar (USDCAD) der USD die Basiswährung ist. Wenn der USD schwächer wird, steigt der GBPUSD, während der USDCAD tendenziell fällt.
Wir werden einen dynamischen Multi-Pair-EA formulieren, der mehrere Währungspaare gleichzeitig handhaben kann. Das System bietet Flexibilität, indem es Ihnen ermöglicht, Währungspaare entsprechend Ihrer Handelsstrategie einzugeben, zu ändern und zu modifizieren. Ein wesentliches Merkmal dieses Systems ist die Möglichkeit, ein primäres oder „Haupt“-Währungspaar zu definieren, das als Signalgeber für andere Währungspaare dient.
Das Herzstück des Systems ist die Möglichkeit, die Liste der gehandelten Währungspaare dynamisch anzupassen. Händler können leicht anpassen, welche Paare in die Handelsstrategie einbezogen werden, sodass sie an verschiedene Marktbedingungen oder Handelspläne angepasst werden kann. Der EA akzeptiert Eingaben für verschiedene Währungspaare, sodass die Nutzer je nach Bedarf Paare hinzufügen, entfernen oder zwischen ihnen wechseln können.
Einer der innovativsten Aspekte ist die Festlegung eines Primär- oder Hauptwährungspaares. Dieses Paar wird nicht nur aktiv gehandelt, sondern dient auch als Referenzpunkt für die Erzeugung von Signalen für andere Paare. Durch die Überwachung dieses Hauptpaares identifiziert der EA Handelssignale — ob Kauf oder Verkauf — und wendet sie auf die ausgewählten korrelierten oder umgekehrt korrelierten Paare an.
Das System unterstützt auch dynamische Anpassungen auf der Grundlage der Stärke der Korrelationen zwischen Währungspaaren. Wenn beispielsweise ein starkes Aufwärtssignal im Hauptwährungspaar erkannt wird, kann der EA automatisch entsprechende Geschäfte in Paaren eröffnen, die sich historisch gesehen in dieselbe Richtung bewegen. Umgekehrt kann der EA bei Paaren, die sich in der Regel invers zum Hauptpaar bewegen, gegenläufige Positionen eröffnen und sich so effektiv gegen potenzielle Marktschwankungen absichern.
Formulierung
#include <Trade\Trade.mqh>
CTrade trade;
Dies importiert die MetaTrader 5 Handelsbibliothek und erstellt eine Instanz der Klasse „Trade“, die es Ihnen ermöglicht, Handelsoperationen wie das Öffnen, Schließen und Ändern von Aufträgen zu verwalten.
int handles[];
Dieses Array wird verwendet, um die Handles für verschiedene Indikatoren oder Objekte zu speichern, die zum Verfolgen von Indikatoren für die technische Analyse über mehrere Währungspaare hinweg erforderlich sind. Dieses Array wird verwendet, um die Handles für verschiedene Indikatoren oder Objekte zu speichern, die zum Verfolgen von Indikatoren für die technische Analyse über mehrere Währungspaare hinweg erforderlich sind.
MqlTick previousTick, currentTick;
Diese Variablen speichern die Tickdaten der Symbolpreise. Der „previousTick“ enthält die Daten des vorherigen Ticks, während der „currentTick“ die Daten des aktuellen Ticks speichert.
inputstring Symbols = "XAUUSD, GBPUSD, USDCAD, USDJPY"; inputstring Base_Quote = "USD"; inputint Currecy_Main = 0;
Diese Eingaben ermöglichen es dem Nutzer, den EA individuell zu gestalten:
- „Symbols“: Eine durch Kommata getrennte Liste von Währungspaaren, die der EA überwachen und handeln wird.
- „Base-Quote“: Die Währung zur Bestimmung von Korrelationen.
- „Currency-Main“: Ein Index, der das Hauptwährungspaar angibt, das für die Erzeugung von Signalen verwendet werden soll.
string symb_List[]; string Formatted_Symbs[]; int Num_symbs = 0;
- „symb-List“: Ein Array, das die Rohliste der zu verarbeitenden Symbole enthält.
- „Formatted-Symbs“: Ein Array, in dem die verarbeiteten Symbole gespeichert werden.
- „Num-symb“: Enthält die Gesamtzahl der Symbole, die nach dem Parsen der Eingabe „Symbols“ verwendet werden sollen.
intOnInit(){ string sprtr = ","; ushort usprtr; usprtr = StringGetCharacter(sprtr, 0); StringSplit(Symbols, usprtr, symb_List); Num_symbs = ArraySize(symb_List); ArrayResize(Formatted_Symbs, Num_symbs);
Die Funktion „OnInit“ wird einmal beim Laden des EA aufgerufen, um die Anfangswerte und Konfigurationen festzulegen. Dann definieren wir als Trennzeichen („sprtr“) das Komma, das verwendet wird, um die Eingabezeichenfolge zu trennen. Die Funktion „StringGetCharacter()“ wandelt das Trennzeichen in ein „ushort“ (unsigned short) um, das für die Funktion „StringSplit()“ benötigt wird. Die Funktion „StringSplit()“ zerlegt die Eingabe „Symbols“ (eine durch Komma getrennte Zeichenkette) in ein Array von einzelnen Symbolen. Das Array „Symb-List[]“ enthält die geparsten Symbole. Das Array „Formatted-Symbs[]“ wird in der Größe an die Anzahl der geparsten Symbole angepasst. Wir verwenden dieses Array für die weitere Verarbeitung, z. B. zum Hinzufügen von Formatierungen oder Anpassungen, die für die Handelslogik erforderlich sind.
for(int i = 0; i < Num_symbs; i++){ Formatted_Symbs[i] = symb_List[i]; }
Wir gehen in einer Schleife durch die Anzahl der Symbole und übertragen Symbole aus dem Array „symb-List[]“ in das Array „Formatted-Symbs[]“. In diesem Stadium wird keine zusätzliche Formatierung vorgenommen.
ArrayResize(handles, ArraySize(Formatted_Symbs));
Hier wird die Größe des Arrays „handles[]“ an die Größe des Arrays „Formatted-Symbs[]“ angepasst. Jedes Element in „handles[]“ enthält den RSI-Handle für das entsprechende Symbol.
for(int i = 0; i < ArraySize(Formatted_Symbs); i++){ handles[i] = iRSI(Formatted_Symbs[i], PERIOD_CURRENT, 14, PRICE_CLOSE); }
Diese Schleife initialisiert den RSI-Indikator-Handle für jedes Symbol.
void OnTick(){ if(isNewBar()){ for(int i = 0; i < ArraySize(Formatted_Symbs); i++){ Sig_trade(Formatted_Symbs[Currecy_Main], handles[Currecy_Main]); } } }
Hier wird zunächst geprüft, ob ein neuer Balken vorhanden ist, und dann wird eine for-Schleife ausgeführt, um den Index der Hauptwährung zu ermitteln, der Signale erzeugt. Wir rufen dann einfach die Funktion „Sig-Trade()“ auf, die die Handelslogik ausführt. Die Funktion nimmt String-Parameter für das Symbol und Integer-Parameter für den RSI-Handle.
void Sig_trade(string symb, int handler){ double rsi[]; CopyBuffer(handler, MAIN_LINE, 1, 1, rsi); bool RSIBuy = rsi[0] < 30; bool RSISell = rsi[0] > 70; // Check if the current symbol is a base USD pair bool isBaseUSD = StringSubstr(symb, 0, 3) == Base_Quote; bool isQuoteUSD = StringSubstr(symb, 3, 3) == Base_Quote; string Bcurr = SymbolInfoString(symb, SYMBOL_CURRENCY_BASE); string Qcurr = SymbolInfoString(symb, SYMBOL_CURRENCY_PROFIT);
Wir werden eine recht einfache Strategie anwenden, nämlich die RSI-Strategie, um zu kaufen, wenn der RSI unter die 30er-Marke fällt, und zu verkaufen, wenn er die 70er-Marke überschreitet.
- `StringSubstr(symb, 0, 3) == Base-Quote`: Diese Funktion extrahiert die ersten drei Zeichen des Währungspaarsymbols ( symb ) und prüft, ob sie „USD“ entsprechen. Damit wird festgestellt, ob es sich bei dem Symbol um ein USD-Basenpaar handelt.
- `StringSubstr(symb, 3, 3) == Base-Quote`: Extrahiert die drei Zeichen ab der vierten Position des Währungspaarsymbols ( symb ) und überprüft, ob sie „USD“ entsprechen. Dies bestimmt, ob das Symbol ein Kurs-USD-Paar ist.
- `Bcurr = SymbolInfoString(symb, SYMBOL-CURRENCY-BASE)`: Ruft die Basiswährung des Symbols ab (die erste Währung des Paares) und speichert sie in der Variablen „Bcurr“.
- `Qcurr = SymbolInfoString(symb, SYMBOL-CURRENCY-PROFIT)`: Ruft die Kurswährung des Symbols ab (die zweite Währung des Paares) und speichert sie in der Variablen „Qcurr“.
for(int i = PositionsTotal() - 1; i >= 0; i--){ ulong posTicket = PositionGetTicket(i); if(PositionGetString(POSITION_SYMBOL) == symb){ if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY){ if(RSISell){ trade.PositionClose(posTicket); } RSIBuy = false; }elseif(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL){ if(RSIBuy){ trade.PositionClose(posTicket); } RSISell = false; } } }
Um alle Positionen zu verwalten, durchlaufen wir eine Schleife durch alle offenen Positionen. Die Funktion „PositionsTotal()“ gibt die Gesamtzahl der derzeit offenen Positionen zurück. Die Schleife beginnt an der letzten Position („PositionsTotal() - 1“) und iteriert rückwärts. Wir verwenden die Rückwärtsiteration, um Probleme zu vermeiden, wenn die Liste der offenen Positionen während der Schleife geändert wird. Wir verwenden die Funktion „PositionGetTicket()“, um die Ticketnummer der Position bei Index „i“ abzurufen. Das Ticket ist eine eindeutige Kennung für das Schließen oder Ändern einer bestimmten Position.
Anschließend verwenden wir die Funktion „PositionGetString()“, um das Symbol der aktuellen Position abzurufen. Von dort aus vergleichen wir dieses Symbol mit „symb“ (dem zu analysierenden Symbol). Wenn sie übereinstimmen, ist die Stelle relevant. Dann prüfen wir mit der Funktion „PositionGetInteger()“, ob die aktuelle Position ein Kaufauftrag ist. Wenn die Position ein Kauf ist und der RSI einen Verkauf nahelegt („RSISell“ ist wahr), wird die Position mit „trade.PositionClose(posTicket)“ geschlossen. Danach weisen wir „RSIBuy = false“ zu, um sicherzustellen, dass keine weiteren Kaufgeschäfte eröffnet werden, da das aktuelle Signal einen Verkauf anzeigt.
Dasselbe gilt für die Verkaufspositionen, wir prüfen, ob die aktuelle Position ein Verkaufsauftrag ist. Wenn die Position ein Verkauf ist und der RSI ein Kaufsignal anzeigt („RSIBuy“ ist wahr), wird die Position mit „trade.PositionClose(posTicket)“ geschlossen. Wir weisen auch „RSISell = false“ zu, um zu verhindern, dass neue Verkaufsgeschäfte eröffnet werden, da das Signal für eine Kaufposition ist. Wir verwenden den obigen Code, um alle offenen Positionen zu verwalten, da wir keinen Stop Loss und Take Profit verwenden. Der Code öffnet und schließt also Positionen ausschließlich in Abhängigkeit vom RSI.
for(int i = 0; i < ArraySize(Formatted_Symbs); i++){ string currSymb = Formatted_Symbs[i]; // Get base and quote currencies for the looped symbol string currBaseCurr = SymbolInfoString(currSymb, SYMBOL_CURRENCY_BASE); string currQuoteCurr = SymbolInfoString(currSymb, SYMBOL_CURRENCY_PROFIT);
Um tatsächlich Handelsgeschäfte für alle Währungspaare zu eröffnen, durchlaufen wir die alle (Anzahl) Elemente im Array „Formatted-Symbole[]“. Die Schleife durchläuft jedes Element (Währungspaar) im Array „Formatted-Symbs“. Wir speichern das aktuelle Symbol im Chart in der Variablen „currSymb“ aus dem Array „Formatted-Symbs“. Dieses Symbol wird verwendet, um relevante Informationen über das Währungspaar abzurufen.
if(RSIBuy){ if(currQuoteCurr == Base_Quote){ trade.PositionOpen(currSymb, ORDER_TYPE_BUY, volume, currentTick.ask, NULL, NULL, "Correlation"); } if(currBaseCurr == Base_Quote){ trade.PositionOpen(currSymb, ORDER_TYPE_SELL, volume, currentTick.bid, NULL, NULL, "Correlation"); } }
Hier wird nur geprüft und ausgeführt, wenn der RSI-Indikator ein Kaufsignal generiert (in der Regel, wenn der RSI-Wert unter einem bestimmten Schwellenwert liegt, was auf eine überverkaufte Situation hinweist). Anschließend wird geprüft, ob die Kurswährung des aktuellen Symbols mit der angegebenen „Basis-Kurswährung“ übereinstimmt. Wenn sie übereinstimmen, wird ein Kaufauftrag für dieses Währungspaar eröffnet. Die Logik dahinter ist, dass Sie, wenn Sie ein Währungspaar kaufen, die Basiswährung kaufen und die Kurswährung verkaufen. Wenn Ihre Handelsstrategie also auf Paare ausgerichtet ist, bei denen der Kurs Ihr „Basis-Kurs“ ist, kaufen Sie dieses Paar.
Es wird geprüft, ob die Basiswährung des aktuellen Symbols mit der angegebenen Währung „Basis-Qoute“ übereinstimmt. Wenn sie übereinstimmen, wird ein Verkaufsauftrag für dieses Währungspaar eröffnet. Wenn Ihre Strategie auf Paare ausgerichtet ist, deren Basiswährung die angegebene „Basis-Quote“ ist, würden Sie dieses Paar verkaufen. Der Verkauf des Paares würde bedeuten, dass Sie die Basiswährung verkaufen und die Kurswährung kaufen.
if(RSISell){ if(currBaseCurr == Base_Quote){ trade.PositionOpen(currSymb, ORDER_TYPE_SELL, volume, currentTick.bid, NULL, NULL, "Correlation"); } if(currQuoteCurr == Base_Quote){ trade.PositionOpen(currSymb, ORDER_TYPE_BUY, volume, currentTick.ask, NULL, NULL, "Correlation"); } }
Hier behandeln wir die Logik, wenn ein RSI-Verkaufssignal erkannt wird. Dieser Block wird ausgeführt, wenn der RSI-Indikator ein Verkaufssignal erzeugt (typischerweise, wenn der RSI über einem bestimmten Schwellenwert liegt, was auf einen überkauften Zustand hinweist). Wir prüfen, ob die Basiswährung des aktuellen Symbols mit dem angegebenen „Base-Quote“ übereinstimmt mit „currBaseCurr == Base-Quote“. Wenn sie übereinstimmen, wird ein Verkaufsauftrag für dieses Währungspaar ausgeführt. Die Logik bei fallenden Paaren, bei denen die Basiswährung der angegebene „Base-Quote“ ist, bleibt gleich. Dann wollen wir dieses Paar verkaufen. Der Verkauf dieses Paares bedeutet, dass wir die Basiswährung verkaufen und die Kurswährung kaufen.
Anschließend wird die Kurswährung des aktuellen Symbols überprüft, wenn sie mit der angegebenen Währung „Base-Quote“ übereinstimmt. Wenn sie übereinstimmen, wird ein Kaufauftrag für dieses Währungspaar eröffnet. Der Grund dafür ist, dass Sie, wenn Ihre Strategie auf Paare ausgerichtet ist, bei denen die Kurswährung der angegebene „Basis-Kurs“ ist, einen Kauf für dieses Paar eröffnen würden. Der Grund dafür ist, dass beim Kauf dieses Paares die Basiswährung gekauft und die Kurswährung verkauft wird.
bool isNewBar() { //--- memorize the time of opening of the last bar in the static variable staticdatetime last_time=0; //--- current time datetime lastbar_time= (datetime) SeriesInfoInteger(Symbol(),Period(),SERIES_LASTBAR_DATE); //--- if it is the first call of the function if(last_time==0) { //--- set the time and exit last_time=lastbar_time; return(false); } //--- if the time differs if(last_time!=lastbar_time) { //--- memorize the time and return true last_time=lastbar_time; return(true); } //--- if we passed to this line, then the bar is not new; return false return(false); }
Oben ist die Funktion „isNewBar“, damit der EA nicht mehrere Aufträge ausführt.
Ergebnisse des Strategietesters
Anhand der obigen Testergebnisse können wir bestätigen, dass das System erfolgreich Handelsgeschäfte gemäß den angegebenen Währungskorrelationen und inversen Korrelationen eröffnet. Wenn ein Kaufsignal generiert wird und die Hauptwährung ein Kurs-USD-Paar ist, führen alle Kurs-USD-Paare im Array „Formatted-Symbs“ Kaufaufträge aus, während Basis-USD-Paare Verkaufsaufträge ausführen, wie bereits erwähnt. Dieses Verhalten stimmt mit der erwarteten Funktionalität überein und zeigt, dass das System die von uns angestrebte Korrelationslogik effektiv umsetzt.
Um das System effektiv und korrekt zu nutzen, ist es wichtig, die Gruppierung nach gleichen Paaren zu berücksichtigen. Wenn Sie zum Beispiel mit EUR-basierten Paaren wie EURUSD, EURGBP und EURJPY handeln, können Sie „EUR“ als Basis-Kurs eingeben, damit die Basiswährung die Handelslogik leitet, wenn ein Signal erkannt wird. Dieser Ansatz kann auf andere Währungsgruppen wie USDEUR oder andere nutzerdefinierte Paare, die Ihr Broker zulässt, angewendet werden, um sicherzustellen, dass die Logik des Systems korrekt auf Ihre Handelsstrategie abgestimmt ist.
Das System ist dynamisch, sodass wir einfach das Hauptwährungspaar auswählen können, das Signale liefert oder generiert, indem wir einfach das gewünschte Paar indizieren. Diese Flexibilität ist besonders nützlich, da der RSI-Indikator zur Generierung von Signalen verwendet wird und der RSI-Puffer und -Handle auf alle Währungspaare angewendet werden. Dadurch wird sichergestellt, dass das ausgewählte Hauptpaar die Handelsentscheidungen für die anderen korrelierten Paare im System effektiv beeinflusst.
Schlussfolgerung
Zusammenfassend lässt sich sagen, dass wir einen dynamischen Multi-Pair-EA erforscht und entwickelt haben, der Handelssignale auf der Grundlage des RSI-Indikators verarbeitet und auf verschiedene korrelierte und umgekehrt korrelierte Währungspaare anwendet. Der EA ermöglicht die Eingabe von anpassbaren Währungspaaren und legt ein Hauptwährungspaar fest, das die Handelsentscheidungen für die anderen Währungspaare bestimmt. Durch die Analyse von Basis- und Kurswährungen eröffnet der EA Trades, die mit dem allgemeinen Markttrend übereinstimmen, indem er die Korrelationslogik nutzt.
Zusammenfassend lässt sich sagen, dass ein dynamischer Multi-Pair Expert Advisor durch die systematische Anwendung von Korrelations- und inversen Korrelationsstrategien konsistentere Handelsergebnisse erzielen kann. Dieser Ansatz optimiert nicht nur die Effizienz des Handels durch die Automatisierung der Signalausbreitung. Durch die Integration von Korrelation und inverser Korrelation in das Handelssystem können Händler die Beziehung zwischen korrelierten Währungspaaren nutzen.
Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/15378





- Freie Handelsapplikationen
- Über 8.000 Signale zum Kopieren
- Wirtschaftsnachrichten für die Lage an den Finanzmärkte
Sie stimmen der Website-Richtlinie und den Nutzungsbedingungen zu.