Vom Neuling zum Experten: Animierte Nachrichtenüberschrift mit MQL5 (XI) – Korrelation im Nachrichtenhandel
Inhalt:
- Einführung
- Verständnis der finanziellen Korrelation
- Strategie zur Umsetzung
- Tests und Ergebnisse
- Schlussfolgerung
- Wichtige Lektionen
- Anlagen
Einführung
Die Möglichkeit, mehrere Paare gleichzeitig zu handeln, mag aufregend klingen, birgt aber auch erhebliche Risiken – insbesondere beim Handel mit Paaren, die stark korreliert sind. Wenn sich Paare in die gleiche Richtung bewegen, erhöht die Eröffnung von Positionen für alle Paare das Risiko. Eine einzige falsche Entscheidung kann zu mehreren Verlustgeschäften auf einmal führen.
Eine weitere häufige Herausforderung ergibt sich in den Momenten vor wichtigen wirtschaftlichen Ankündigungen, wenn die Händler oft mit Unsicherheit und Unentschlossenheit über die zu ergreifenden Maßnahmen konfrontiert sind. In unseren jüngsten Veröffentlichungen haben wir die Möglichkeit eingeführt, mehrere Paare mit einem einzigen Klick über Handelsschaltflächen auszuwählen und zu handeln. Diese Funktion ermöglichte zwar eine schnellere Ausführung, wies aber auch auf ein neues Problem hin: ein erhöhtes Risiko.
An dieser Stelle wird das Konzept der Korrelation entscheidend. Durch die Messung der Beziehungen zwischen den Paaren können Händler ihre Strategien verfeinern, überflüssige Engagements vermeiden und sogar Techniken wie die Vorreiter-Nachfolger-Strategie (Catch-up) anwenden, bei der die Entwicklung eines Instruments hilft, die eines anderen vorherzusagen.
Nachdem mit dem Multi-Symbol-Management eine solide Grundlage geschaffen wurde, besteht der nächste Schritt darin, die Korrelationsanalyse in den News Headline EA zu integrieren. Auf diese Weise können wir Paare herausfiltern, die nicht mit der beabsichtigten Handelsrichtung übereinstimmen, führende Instrumente identifizieren und die Gesamteffizienz beim Handel mit wichtigen Nachrichten verbessern, ohne dass ein manueller Eingriff erforderlich ist.
Verständnis der finanziellen Korrelation
Korrelation ist auf den Finanzmärkten ein statistisches Maß, das den Grad der Bewegung zweier Wertpapiere zueinander quantifiziert. Sie ist der Eckpfeiler des modernen Risikomanagements und ein leistungsstarkes Instrument für den strategischen Handel, insbesondere in einem Multi-Symbol-Umfeld.
Für den News Headline EA bedeutet das Verständnis der Korrelation, dass er sich von einem einfachen Ausführer von Trades in einen hochentwickelten Strategiemanager verwandelt.
Der Korrelationskoeffizient: Die Schlüsselmetrik
Die Beziehung wird durch den Korrelationskoeffizienten ausgedrückt, der von -1 bis +1 reicht.
- +1 (perfekte positive Korrelation): Die beiden Paare bewegen sich im perfekten Gleichschritt. Wenn Paar A um 1 % steigt, steigt Paar B um 1 %. Wenn Paar A fällt, fällt auch Paar B. (z. B. zwei nahezu identische ETFs, die denselben Index abbilden).
- 0 (keine Korrelation): Es ist kein Zusammenhang zwischen den Bewegungen der beiden Paare erkennbar. Sie sind völlig unabhängig.
- -1 (perfekte negative Korrelation): Die beiden Paare bewegen sich in perfekter Opposition. Wenn Paar A um 1 % steigt, fällt Paar B um 1 %. (z. B. eine klassische Absicherung wie eine Aktie und eine Verkaufsoption auf diese Aktie).
In Wirklichkeit liegen die meisten Korrelationen irgendwo zwischen diesen Extremen (z. B. +0,85, -0,30).
Warum Korrelation nicht statisch und kontextabhängig ist
Dies ist das wichtigste Konzept für den Nachrichtenhandel: Die Korrelation ist kein festes Gesetz. Es handelt sich um eine dynamische Beziehung, die sich im Laufe der Zeit verändert und unter bestimmten Bedingungen völlig zusammenbrechen kann.
Zeitrahmen-Abhängigkeit: Die Korrelation zwischen EUR/USD und GBP/USD auf einem 1-Minuten-Chart während der Nachrichtenlage kann sich stark von ihrer Korrelation auf einem Tages-Chart unterscheiden. Ihr EA muss die Korrelation über einen kurzen, relevanten Rückblickzeitraum (z. B. 15-30 Minuten) für den Nachrichtenhandel berechnen.
- Regime Change: Größere wirtschaftliche Umwälzungen (z. B. eine Änderung der Zentralbankpolitik) können lang bestehende Korrelationen verändern.
- Stress im Markt: Während einer „Flucht in die Sicherheit“ oder einer Marktpanik (z. B. in der Krise von 2008) können die Korrelationen unerwartet auf +1 oder -1 konvergieren. Die Diversifizierung scheitert, weil sich alles zusammen bewegt – entweder alles nach oben oder alles nach unten. Dies ist der ultimative Test für das Risikomanagement Ihres EAs.
Berechnung der Korrelation für den Nachrichtenschlagzeilen-EA
Die gebräuchlichste Methode ist der Korrelationskoeffizient nach Pearson. Unser EA würde dies automatisch zwischen den prozentualen Renditen oder den Preisänderungen von zwei Vermögenswerten (A und B) über eine bestimmte Anzahl von Zeiträumen (N) berechnen.
Die Formel lautet:

wobei:
- 𝑟_A = Werte des Vermögenswerts A
- 𝑟_B = Werte des Vermögenswerts B
- Cov(𝑟_A.r_B) = Kovarianz zwischen den beiden Renditereihen
- 𝜎_A = Standardabweichung der Werte des Vermögenswerts A
- 𝜎_B = Standardabweichung der Werte des Vermögenswerts B
Praktische Umsetzung:
- Daten: Unser EA verfügt bereits über Kursdaten für alle ausgewählten Paare.
- Funktion: Wir werden eine Funktion codieren, die den Koeffizienten zurückgibt.
- Rückblick: Für den Nachrichtenhandel sind die Zeiträume klein (z. B. 50-100 Balken auf einem 1-Minuten- oder 5-Minuten-Chart).
Strategie zur Umsetzung
Um die Korrelation herzustellen, bin ich in zwei strukturierten Schritten vorgegangen. Der erste Schritt bestand darin, die Klasse CTradingButtons so zu erweitern, dass sie sowohl die Logik der Korrelationsberechnung als auch die visuelle Schnittstelle für die Anzeige der Ergebnisse im Chart enthält. Dadurch wird sichergestellt, dass alle korrelationsbezogenen Funktionen modular und wiederverwendbar bleiben und vollständig in der Header-Datei enthalten sind, aber dennoch flexibel genug sind, um von jedem EA aufgerufen zu werden.
Der zweite Schritt konzentrierte sich auf die Integration, d. h. die Einbindung dieser neuen Korrelationsfunktion in den Haupt-EA, sodass sie nahtlos neben bestehenden Komponenten wie Handelsschaltflächen, Nachrichtenspuren und Mini-Chart-Kacheln funktioniert. Durch die Trennung der beiden Schritte wurden die Entwicklung und das Debugging effizienter: Wir konnten die Berechnungen und Nutzeroberflächenelemente isoliert validieren, bevor wir sie in das größere System einfügten.
In den folgenden Abschnitten wird die Einbindung der Korrelation in die Kopfzeile erläutert. Dabei werden die Berechnungsformeln, die Platzierung der Marker im Diagramm, die Ausrichtung mit vorhandenen Symbolkennzeichnungen und die Bereinigungsroutinen behandelt, um sicherzustellen, dass nach der Deinitialisierung keine Objekte zurückbleiben.
Schritt 1: Erweitern der CTradingButtons für die Korrelation
1.1. Die Designkonstanten und der Zweck
Wir beginnen mit einer kleinen Reihe von Standardeinstellungen, die die Korrelationsberechnungen steuern: die Fensterlänge (wie viele Rücklaufstichproben wir verwenden), die maximale Verzögerung (wie viele Balken wir eine Reihe gegen die andere verschieben, um Lead/Lag-Beziehungen zu finden) und ein Schwellenwert, der entscheidet, ob eine Korrelation als stark genug angesehen wird, um als „korreliert“ markiert zu werden. Mit diesen einfachen Konstanten lässt sich der Code leicht auf Reaktionsfähigkeit und Rauschempfindlichkeit abstimmen (kurze Fenster reagieren schneller, sind aber lauter; längere Fenster sind weicher).
// ---------------- Correlation defaults & utilities (merged) ------- #define CORR_WINDOW 40 // samples used for correlation window (returns) #define CORR_MAX_LAG 3 // maximum lag (in bars) to test for cross-correlation #define CORR_THRESHOLD 0.60 // threshold for "correlated" marker
1.2. Abruf von Zeitreihen (wie wir Preise in vergleichbare Daten umwandeln)
Die Korrelation wird auf der Grundlage von Werten (relativen Preisänderungen) und nicht von Rohpreisen berechnet, um Niveaueffekte zu vermeiden und die Pearson-Formel für Instrumente mit unterschiedlichen Preisskalen aussagekräftig zu machen. Die Funktion FetchReturns kopiert die letzten Schlusskurse für das gewünschte Symbol und den gewünschten Zeitrahmen und wandelt sie in einfache prozentuale Renditen um.

wobei:
- R_t ist der Wert zum Zeitpunkt t
- 𝑃_t ist der aktuelle Schlusskurs
- 𝑃_t-1 ist der vorherige Schlusskurs
- Δ𝑃_𝑡 = 𝑃_𝑡 – 𝑃_𝑡-1 , und gibt das Array der jüngsten Werte zurück (jüngsten zuerst). Außerdem werden zusätzliche Balken reserviert, um Verzögerungstests zu ermöglichen. Wenn nicht genügend Daten vorhanden sind, wird der Vorgang ordnungsgemäß abgebrochen.
// Fetch recent returns for `symbol` on timeframe `tf`. // Returns number of return samples placed into `ret[]` (most recent first). int FetchReturns(const string symbol, const ENUM_TIMEFRAMES tf, const int samples, const int maxLag, double &ret[]) { if(StringLen(symbol) == 0 || samples <= 0) return 0; int need = samples + MathMax(0, maxLag) + 5; if(need <= 1) return 0; double closes[]; ArrayResize(closes, need); int copied = CopyClose(symbol, tf, 0, need, closes); if(copied <= 1) return 0; int available = copied - 1; // returns available int use = MathMin(samples, available - MathMax(0, maxLag)); if(use <= 0) return 0; ArrayResize(ret, use); for(int i = 0; i < use; i++) { double older = closes[i+1]; double newer = closes[i]; if(older == 0.0) ret[i] = 0.0; else ret[i] = (newer - older) / older; } return use; }
1.3. Berechnung der Pearson-Korrelation aus zwei Werte-Arrays (mathematisch erklärt)
Sobald wir zwei ausgerichtete Werte-Arrays der Länge n haben, berechnen wir Pearsons Korrelationskoeffizienten r. Die bekannte Formel lautet

wobei:
- r ist der Korrelationskoeffizient nach Pearson (eine einzelne Zahl zwischen -1 und +1, die den linearen Zusammenhang misst)
- x_i ist die i-te Beobachtung der Reihe x (in unserer EA ist dies der i-te Wert für das Symbol X, z. B. a[i])
- y_i ist die i-te Beobachtung der Reihe y (der i-te Wert für das Symbol Y, z. B. b[i])
- x̄ (x bar) ist der Mittelwert (Durchschnitt) der x-Reihe: x̄ = (1/n) Σ x_i
- ȳ (y bar) ist der Mittelwert der y-Reihe: ȳ = (1/n) Σ y_i
// Compute Pearson correlation from two return arrays of length n double ComputePearsonFromReturns(const double &a[], const double &b[], const int n) { if(n <= 1) return 0.0; double meanA = 0.0, meanB = 0.0; for(int i = 0; i < n; i++) { meanA += a[i]; meanB += b[i]; } meanA /= n; meanB /= n; double cov = 0.0, varA = 0.0, varB = 0.0; for(int i = 0; i < n; i++) { double da = a[i] - meanA; double db = b[i] - meanB; cov += da * db; varA += da * da; varB += db * db; } if(varA <= 0.0 || varB <= 0.0) return 0.0; double r = cov / MathSqrt(varA * varB); if(r > 1.0) r = 1.0; if(r < -1.0) r = -1.0; return r; }
1.4. Suche nach dem Spitzenwert der Kreuzkorrelation über die Verzögerungen hinweg (Erkennung von Vorreitern/Nachfolgern)
Eine wesentliche Verbesserung ist die Suche nach der stärksten Korrelation zwischen dem aktuellen Chartsymbol und jedem Kandidatensymbol unter Berücksichtigung kleiner Verzögerungen. Für jeden Kandidaten wird eine Zeitreihe der Werte relativ zur anderen über Verzögerungen von -maxLag bis +maxLag verschoben und das Pearson r für jede Verschiebung berechnet. Wir behalten das r mit dem größten absoluten Wert (peakCorr) und die entsprechende Verzögerung. Eine positive Verzögerung bedeutet, dass der Kandidat hinter dem aktuellen Symbol zurückbleibt; eine negative Verzögerung bedeutet, dass der Kandidat vor dem aktuellen Symbol liegt. Auf diese Weise kann der EA einen Vorreiter empfehlen. Die Funktion gibt peakCorr und lagAtPeak zurück, oder false, wenn nicht genügend Daten vorhanden sind.// Compute cross-correlation peak and lag between currSym and otherSym. // Outputs peakCorr and lagAtPeak (int). bool ComputeCrossCorrPeak(const string currSym, const string otherSym, const ENUM_TIMEFRAMES tf, const int window, const int maxLag, double &peakCorr, int &lagAtPeak) { if(StringLen(currSym) == 0 || StringLen(otherSym) == 0 || window <= 1) return(false); double rCurr[], rOther[]; int nCurr = FetchReturns(currSym, tf, window, maxLag, rCurr); int nOther = FetchReturns(otherSym, tf, window, maxLag, rOther); if(nCurr == 0 || nOther == 0) return(false); int available = MathMin(nCurr, nOther); if(available < window) return(false); bool found = false; peakCorr = 0.0; lagAtPeak = 0; for(int lag = -maxLag; lag <= maxLag; lag++) { int startCurr = 0; int startOther = lag; if(startOther < 0) { startCurr = -startOther; startOther = 0; } int maxSamples = available - MathMax(startCurr, startOther); if(maxSamples < window) continue; double a[], b[]; ArrayResize(a, window); ArrayResize(b, window); for(int i = 0; i < window; i++) { a[i] = rCurr[startCurr + i]; b[i] = rOther[startOther + i]; } double r = ComputePearsonFromReturns(a, b, window); if(!found || MathAbs(r) > MathAbs(peakCorr)) { peakCorr = r; lagAtPeak = lag; found = true; } } return(found); }
1.5. Rendering-Marker – die Zeichenfunktionen (visuelles Feedback)
Um Korrelationsergebnisse anzuzeigen, ohne die vorhandenen Symbolkennzeichnungen zu überladen, haben wir minimale Markierungen hinzugefügt: eine kompakte Kennzeichnung, die einen farbigen Punkt und den numerischen Korrelationswert zeigt. DrawCorrelationMarker erstellt ein Chart OBJ_LABEL an den angegebenen Koordinaten, setzt die Farbe auf grün (korreliert) oder rot (nicht korreliert) und schreibt einen kurzen Text wie „● 0.72“. Dadurch bleibt die Nutzeroberfläche kompakt und gut lesbar. Eine ähnliche kleine Funktion, DrawRecommendation, schreibt den Vorschlag „Recommended leader“ (Empfohlener Vorreiter); DrawCorrelationTitle setzt eine statische Überschrift „Korrelation“ über den Markierungsbereich. Bei diesen drei Funktionen handelt es sich um einfache Objektverwaltungs-Wrapper, die das Zeichnen konsistent halten und die Auswahl von Z-Reihenfolge und Schriftart zentralisieren.// Draw a small correlation marker near (x,y) — dot + numeric value only (no symbol text). void DrawCorrelationMarker(const string objName, const int x, const int y, const double corr, const bool correlated) { if(StringLen(objName) == 0) return; long chart = ChartID(); if(ObjectFind(chart, objName) == -1) ObjectCreate(chart, objName, OBJ_LABEL, 0, 0, 0); ObjectSetInteger(chart, objName, OBJPROP_CORNER, CORNER_LEFT_UPPER); ObjectSetInteger(chart, objName, OBJPROP_XDISTANCE, x); ObjectSetInteger(chart, objName, OBJPROP_YDISTANCE, y); ObjectSetInteger(chart, objName, OBJPROP_FONTSIZE, 10); int col = correlated ? clrLime : clrRed; ObjectSetInteger(chart, objName, OBJPROP_COLOR, col); ObjectSetInteger(chart, objName, OBJPROP_SELECTABLE, 0); ObjectSetInteger(chart, objName, OBJPROP_ZORDER, 20); // Show a small dot and the numeric correlation (2 decimals). Example: "● 0.72" string text = StringFormat("● %.2f", corr); ObjectSetString(chart, objName, OBJPROP_TEXT, text); } // Draw recommendation label (top-left of panel area) void DrawRecommendation(const string objName, const int x, const int y, const string text) { if(StringLen(objName) == 0) return; long chart = ChartID(); if(ObjectFind(chart, objName) == -1) ObjectCreate(chart, objName, OBJ_LABEL, 0, 0, 0); ObjectSetInteger(chart, objName, OBJPROP_CORNER, CORNER_LEFT_UPPER); ObjectSetInteger(chart, objName, OBJPROP_XDISTANCE, x); ObjectSetInteger(chart, objName, OBJPROP_YDISTANCE, y); ObjectSetInteger(chart, objName, OBJPROP_FONTSIZE, 10); ObjectSetInteger(chart, objName, OBJPROP_COLOR, clrWhite); ObjectSetInteger(chart, objName, OBJPROP_SELECTABLE, 0); ObjectSetInteger(chart, objName, OBJPROP_ZORDER, 21); ObjectSetString(chart, objName, OBJPROP_TEXT, text); } // Draw static "Correlation" title above correlation area void DrawCorrelationTitle(const string objName, const int x, const int y) { if(StringLen(objName) == 0) return; long chart = ChartID(); if(ObjectFind(chart, objName) == -1) ObjectCreate(chart, objName, OBJ_LABEL, 0, 0, 0); ObjectSetInteger(chart, objName, OBJPROP_CORNER, CORNER_LEFT_UPPER); ObjectSetInteger(chart, objName, OBJPROP_XDISTANCE, x); ObjectSetInteger(chart, objName, OBJPROP_YDISTANCE, y); ObjectSetInteger(chart, objName, OBJPROP_FONTSIZE, 11); ObjectSetInteger(chart, objName, OBJPROP_COLOR, clrWhite); ObjectSetInteger(chart, objName, OBJPROP_SELECTABLE, 0); ObjectSetInteger(chart, objName, OBJPROP_ZORDER, 22); ObjectSetString(chart, objName, OBJPROP_TEXT, "Correlation"); }
1.6. Wo die Korrelationseinstellungen und der UI-Status innerhalb der Klasse der Handelstasten liegen
Für eine saubere Integration werden die Korrelationsparameter und die Koordinaten der einzelnen Kontrollkästchen als Mitglieder der Klasse CTradingButtons gespeichert. Der Konstruktor setzt vernünftige Vorgaben, sodass der EA einfach das Handelspanel erstellen und die Korrelation bereithalten kann. Die wichtigsten Elemente sind m_corr_window, m_corr_maxlag, m_corr_threshold, die vertikalen/horizontalen Offsets (damit Sie die Punkte verschieben können) und die Arrays m_check_x/m_check_y, die sich die Positionen der Kontrollkästchen-Pixel merken. Dieser lokalisierte Zustand macht UpdateCorrelationMarkersInternal einfach und vermeidet die Streuung des Korrelationszustands über den EA.// initialize correlation defaults here (cannot initialize at declaration) m_corr_marker_prefix = "CorrMarker_"; m_corr_rec_name = "Corr_Recommendation"; m_corr_title_name = "Corr_Title"; m_corr_tf = PERIOD_M1; m_corr_window = CORR_WINDOW; m_corr_maxlag = CORR_MAX_LAG; m_corr_threshold = CORR_THRESHOLD; // vertical offsets (push correlation UI down a bit) m_corr_rec_y_offset = 24; // recommendation label y-distance in pixels (tweak) m_corr_marker_v_offset = 8; // marker offset relative to checkbox top (tweak) // horizontal offset default (shift markers slightly right) m_corr_marker_h_offset = 6; // default shift to the right by 6 pixels (tweak as needed) ArrayResize(m_check_x, 0); ArrayResize(m_check_y, 0);
1.7. Öffentliche Steuerelemente: Darstellung der Laufzeiteinstellung für den EA
Zwei kleine Methoden ermöglichen es dem EA, die Korrelation während der Laufzeit zu optimieren: SetCorrelationParams zum Ändern von Zeitrahmen/Fenster/Maxlag/Schwellenwert und SetCorrelationMarkerHorizontalOffset, damit der EA-Nutzer die Markerpositionen für unterschiedliche Bildschirmgrößen oder Checkbox-Breiten anpassen kann. Beide rufen die interne Aktualisierungsroutine auf (oder werden sie aufrufen), um die Markierungen sofort neu zu zeichnen. Durch diese Trennung bleiben die Änderungen an der Nutzeroberfläche einfach.// Configure correlation evaluation (optional runtime tuning) void SetCorrelationParams(const int timeframe, const int window, const int maxlag, const double threshold) { m_corr_tf = timeframe; m_corr_window = MathMax(1, window); m_corr_maxlag = MathMax(0, maxlag); m_corr_threshold = MathMax(0.0, MathMin(1.0, threshold)); PrintFormat("SetCorrelationParams: tf=%d window=%d maxlag=%d thresh=%.2f", m_corr_tf, m_corr_window, m_corr_maxlag, m_corr_threshold); } // Exposed update so EA can refresh markers (public wrapper) void UpdateCorrelationMarkers() { UpdateCorrelationMarkersInternal(); } // Public setter for horizontal offset of correlation markers void SetCorrelationMarkerHorizontalOffset(const int px) { m_corr_marker_h_offset = px; UpdateCorrelationMarkersInternal(); }
1.8. Zeichnen je Kontrollkästchen: DrawCorrelationForIndex (wobei jeder Marker berechnet und gezeichnet wird)
Für jedes aufgelöste Paar berechnen wir den Korrelationspeak im Vergleich zum aktuellen Chartsymbol und entscheiden, ob er den Schwellenwert erfüllt. Die Koordinaten werden aus den gespeicherten m_check_x/m_check_y-Werten gelesen (die bei der Erstellung von Kontrollkästchen oder durch Abfrage des Kontrollkästchen-Objekts erfasst werden), dann werden der Punkt und der numerische Text an dieser Pixelposition platziert (mit konfigurierbaren horizontalen und vertikalen Abständen). Die Funktion ruft ComputeCrossCorrPeak und DrawCorrelationMarker auf, um die Verantwortlichkeiten zu trennen.void DrawCorrelationForIndex(const int idx) { if(idx < 0 || idx >= ArraySize(availablePairs)) return; string sym = availablePairs[idx]; if(StringLen(sym) == 0) return; if(idx >= ArraySize(m_check_x) || idx >= ArraySize(m_check_y)) return; int x = m_check_x[idx]; int y = m_check_y[idx]; if(x < 0 || y < 0) return; // move marker slightly to the right with configurable horizontal offset int markerX = MathMax(2, x - 18 + m_corr_marker_h_offset); int markerY = y + m_corr_marker_v_offset; // configurable vertical offset double peakCorr = 0.0; int lag = 0; bool ok = ComputeCrossCorrPeak(Symbol(), sym, (ENUM_TIMEFRAMES)m_corr_tf, m_corr_window, m_corr_maxlag, peakCorr, lag); if(!ok) peakCorr = 0.0; bool correlated = (MathAbs(peakCorr) >= m_corr_threshold); string objName = m_corr_marker_prefix + sym; DrawCorrelationMarker(objName, markerX, markerY, peakCorr, correlated); }
1.9. Die Orchestrierung von allem: UpdateCorrelationMarkersInternal (Auswahl des Vorreiters + Neuzeichnen)
Dies ist die zentrale Funktion, die über berechnete Paare iteriert, sicherstellt, dass wir Pixelkoordinaten für die Kontrollkästchen haben, jede Markierung zeichnet und dann den besten Führungskandidaten berechnet, indem sie das Symbol mit der größten absoluten Spitzenkorrelation auswählt, das auch die Führung durch negative Verzögerung anzeigt (Sie können Ihre Vorreiter-Regel anpassen). Die Funktion schreibt über DrawRecommendation einen kurzen sprechenden Text „Recommended leader: ... r=... lag=...“ und zeichnet einen „Correlation“-Titel über den Bereich. Diese Funktion rufen Sie auf, wenn sich Ankreuzfelder oder das Bildschirmlayout ändern.
void UpdateCorrelationMarkersInternal() { int n = ArraySize(availablePairs); if(n == 0) return; for(int i = 0; i < n; i++) { if(StringLen(availablePairs[i]) == 0) continue; if(i >= ArraySize(m_check_x) || i >= ArraySize(m_check_y) || m_check_x[i] < 0 || m_check_y[i] < 0) { string chkName = "Chk_" + availablePairs[i]; if(ObjectFind(ChartID(), chkName) >= 0) { int y = (int)ObjectGetInteger(ChartID(), chkName, OBJPROP_YDISTANCE); int x = (int)ObjectGetInteger(ChartID(), chkName, OBJPROP_XDISTANCE); if(ArraySize(m_check_x) < n) ArrayResize(m_check_x, n); if(ArraySize(m_check_y) < n) ArrayResize(m_check_y, n); m_check_x[i] = x; m_check_y[i] = y; } else continue; } DrawCorrelationForIndex(i); } double bestCorr = 0.0; string bestSym = ""; int bestLag = 0; for(int j = 0; j < n; j++) { if(StringLen(availablePairs[j]) == 0) continue; double p = 0.0; int l = 0; bool ok = ComputeCrossCorrPeak(Symbol(), availablePairs[j], (ENUM_TIMEFRAMES)m_corr_tf, m_corr_window, m_corr_maxlag, p, l); if(!ok) continue; if(l < 0 && MathAbs(p) > MathAbs(bestCorr)) { bestCorr = p; bestSym = availablePairs[j]; bestLag = l; } } int recX = checkStartX; int recY = m_corr_rec_y_offset; // configurable vertical offset for recommendation string recText; if(bestSym != "") recText = StringFormat("Recommended leader: %s r=%.2f lag=%d", bestSym, bestCorr, bestLag); else recText = "No clear leader detected"; // Draw title above the recommendation/markers area DrawCorrelationTitle(m_corr_title_name, recX, MathMax(2, recY - 18)); DrawRecommendation(m_corr_rec_name, recX, recY, recText); }
1.10. Aufräumen: DeleteCorrelationMarkers (Aufräumen von Objekten)
Wenn die Kopfzeile/UI abgerissen wird (Deinit), entfernen wir alle Kennzeichnungsobjekte der Korrelation zusammen mit dem Titel und der Empfehlung, sodass das Chart in seinen Zustand vor dem EA zurückkehrt. Dadurch werden verwaiste Kennzeichnungen verhindert, wenn der EA oder die Tasten des Panels entfernt wird.void DeleteCorrelationMarkers() { for(int i = 0; i < ArraySize(availablePairs); i++) { if(StringLen(availablePairs[i]) == 0) continue; string obj = m_corr_marker_prefix + availablePairs[i]; if(ObjectFind(ChartID(), obj) >= 0) ObjectDelete(ChartID(), obj); } if(ObjectFind(ChartID(), m_corr_rec_name) >= 0) ObjectDelete(ChartID(), m_corr_rec_name); if(ObjectFind(ChartID(), m_corr_title_name) >= 0) ObjectDelete(ChartID(), m_corr_title_name); }
Wo und wann die Korrelations-UI ausgelöst wird (Integrationspunkte)
Um mit dem Layout der Kontrollkästchen und den Nutzerinteraktionen synchron zu bleiben, rufen wir UpdateCorrelationMarkersInternal nach der Erstellung der Kontrollkästchen auf (damit die ersten Markierungen platziert werden) und erneut, wenn ein Kontrollkästchen über HandleChartEvent umgeschaltet wird. Hier sind die beiden Aufrufstellen (CreatePairCheckboxes endet mit dem Aufruf von UpdateCorrelationMarkersInternal; HandleChartEvent ruft UpdateCorrelationMarkersInternal auf, wenn sich ein Kontrollkästchen ändert).// end of CreatePairCheckboxes() // inside HandleChartEvent() when checkbox clicked: UpdateCorrelationMarkersInternal();
Schritt 2: Integration der Korrelation in den EA
2.1. Einbinden des Headers – macht die API der Korrelationen verfügbar.
Wir fügen den Header für die Handelstasten ein (der jetzt Korrelations-Utilities enthält), damit der EA seine öffentlichen APIs aufrufen kann (Checkboxen erstellen, Korrelationsparameter setzen, Markierungen aktualisieren, de-initialisieren). Dies muss am Anfang des EA vor jeder Verwendung von buttonsEA stehen.
#include <TradingButtons.mqh> #include <Trade\Trade.mqh> #include <Canvas\Canvas.mqh> #include <ChartMiniTiles.mqh> // <-- CTM class include (make sure this file is in MQL5/Include/)
2.2. Nutzereingaben für Korrelationen – Feinabstimmung dem Händler zugänglich machen.
Zeigen Sie Zeitrahmen, Fenster, maximale Verzögerung und Schwellenwert an, damit die Nutzer einstellen können, wie empfindlich/stabil die Korrelationserkennung sein soll. Diese werden in OnInit() gelesen und an den Header übergeben.
// Correlation tuning exposed to EA input group "Correlation (TradingButtons)" input int CorrTimeframe = PERIOD_M1; input int CorrWindow = 40; input int CorrMaxLag = 3; input double CorrThreshold = 0.60;
2.3. Erstellen von Paar-UI (Kontrollkästchen) – Ankerpunkten für Korrelationsmarker
Erstellen Sie die beiden Kontrollkästchen (dadurch erhält die Kopfzeile auch die UI-Koordinaten, die sie benötigt, um Punkte und Werte neben den einzelnen Symbolen zu platzieren). Tun Sie dies frühzeitig während der Initialisierung, damit der Header die Positionen der Ankreuzfelder abfragen kann.
// Create pair checkboxes aligned below the canvas lanes: int checkboxY = InpTopOffset + (InpSeparateLanes ? 8 : 28) * lineH + 6; // same as before buttonsEA.CreatePairCheckboxes(majorPairs, pairSelected, checkboxY);
2.4. Übergabe von Korrelationsparametern und Erzwingen der ersten Anzeige
Nachdem Sie die Kontrollkästchen erstellt haben, übergeben Sie die EA-Eingaben an den Header und erzwingen einen anfänglichen Marker-Refresh, damit die Korrelations-UI sofort beim Start erscheint.
// Set correlation params in TradingButtons buttonsEA.SetCorrelationParams(CorrTimeframe, CorrWindow, CorrMaxLag, CorrThreshold); // Force initial correlation markers buttonsEA.UpdateCorrelationMarkers();
2.5. Ereignisweiterleitung und Layout-Änderungsbearbeitung
Leiten Sie Chartereignisse an die Header weiter, damit Klicks auf Kontrollkästchen und UI-Interaktionen dort verarbeitet werden. Reagieren Sie auch auf Änderungen des Chart-Layouts (CHARTEVENT_CHART_CHANGE), indem Sie sowohl die Mini-Kacheln als auch die Korrelationsmarker neu fließen lassen, damit die Positionen korrekt bleiben.
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { // Let the tiles class handle object clicks (toggle button). If handled, stop processing. if(tiles.HandleEvent(id, sparam)) return; // Forward to the TradingButtons header afterward buttonsEA.HandleChartEvent(id, sparam, majorPairs, pairSelected); // Also respond to chart change events for CTM layout if(id == CHARTEVENT_CHART_CHANGE) { tiles.UpdateLayout(); buttonsEA.UpdateCorrelationMarkers(); } }
2.6. Timergesteuerte Aktualisierung – hält Korrelationsmarker aktuell
Bei jedem Tick des Timers führt der EA viele periodische Aufgaben aus und bittet dann den Header, die Korrelationsmarker neu zu berechnen und zu zeichnen, damit die Punkte/Werte die jüngsten Kursänderungen widerspiegeln.
// Keep CTM updated every tick (timer-driven) tiles.UpdateLayout(); // Keep correlation markers fresh — call the header's public updater buttonsEA.UpdateCorrelationMarkers();
2.7. Cleanup – Die Deinitialisierung des Headers entfernt Korrelationsobjekte
Wenn der EA beendet wird, rufen Sie den Header Deinit/cleanup auf, damit der Header alle Korrelationsmarkerobjekte, Empfehlungslabel und Titel entfernen kann. Auf der EA-Ebene rufen Sie buttonsEA.Deinit() auf. Intern sollte der Header jede Marker-Beispiel-Kopfbereinigungsfunktion löschen:
void OnDeinit(const int reason) { EventKillTimer(); buttonsEA.Deinit(); // ... other UI destruction ... // delete CTM tiles and toggle button tiles.Delete(); }
Tests und Ergebnisse
Der Einsatz des aktualisierten News Headline EA auf einem Live-Chart des MetaTrader 5 ist der effektivste Weg, um seine Funktionalität zu testen, da viele seiner Funktionen auf Echtzeitdaten beruhen und im Strategy Tester nicht vollständig validiert werden können.
Die Testergebnisse sind in den folgenden Bildern dargestellt. Jedes wichtige Symbol zeigt nun einen Korrelationswert zusammen mit einem farbigen Punkt an: rot für negative Korrelation und lindgrün für positive Korrelation. Die Zahlenwerte, die von -1 bis +1 reichen, geben die Stärke und Richtung der Korrelation in Bezug auf das aktuelle Chartpaar an, das als Vorreiter fungiert. Eine positive Korrelation zeigt an, dass das Paar dazu neigt, sich in dieselbe Richtung wie der Vorreiter zu bewegen, während eine negative Korrelation auf eine Bewegung in die entgegengesetzte Richtung hindeutet.

Abbildung 1: Testen der Korrelation bei GPBAUD unter Verwendung des aktualisierten News Headline EA
Wie in den Abbildungen dargestellt, schwanken die Korrelationswerte langsam, da sie nicht nur von der Marktvolatilität, sondern auch von der Größe des Korrelationsfensters beeinflusst werden. Dieses Verhalten spiegelt die natürliche Verzögerung in statistischen Beziehungen wider und macht die Korrelationsanalyse zu einer stabilen Ergänzung für Echtzeit-Handelsentscheidungen.
Schlussfolgerung
Die Finanzkorrelation kann ein leistungsfähiges Instrument sein, um Paare herauszufiltern und das Risiko beim Handel mit mehreren Instrumenten während einschneidenden Ereignissen zu verringern. Wir haben dieses Konzept erfolgreich in den News Headline EA implementiert, um die Effizienz im Multi-Symbol-Handel unter volatilen Bedingungen zu verbessern.
Das Ziel besteht nicht einfach darin, den Handel mit allen Paaren gleichzeitig zu ermöglichen, sondern die Korrelation als statistischen Leitfaden zu nutzen, um entschiedenere und fundiertere Entscheidungen zu treffen. Durch die Analyse, wie sich die Paare im Verhältnis zueinander bewegen, ermöglicht der EA den Händlern, sich auf die Gelegenheiten zu konzentrieren, die ihrer Strategie entsprechen, während sie überflüssige oder übermäßig riskante Positionen vermeiden können.
Obwohl sich aus diesem Konzept noch viel mehr ableiten lässt, stellt unsere derzeitige Umsetzung bereits einen bedeutenden Schritt nach vorn dar. Wie in der Abbildung unten zu sehen ist, kann ich nun anhand der angezeigten Korrelationswerte auswählen, welche Paare gleichzeitig gehandelt werden sollen.

Abbildung 2: Verwendung der Korrelation, um zu entscheiden, welche Paare gleichzeitig gehandelt werden sollen.
Dieses Konzept öffnet die Tür zu vielen weiteren Strategien, und ihre Umsetzung in MQL5 ist durchaus möglich. Der gesamte Quellcode und die wichtigsten Komponenten sind beigefügt und teilweise in der nachstehenden Tabelle der Anhänge dokumentiert. Sie sind herzlich eingeladen, sich an der Diskussion zu beteiligen – teilen Sie Ihre Gedanken, Ideen und Vorschläge mit uns, während wir unsere MQL5-Tools zu praktischen, erfolgreichen Strategien ausbauen.
Wichtige Lektionen
| Lektion | Beschreibung: |
|---|---|
| Gezielte Integration | Die Korrelation sollte als ein Merkmal betrachtet werden, das die Handelsentscheidungen beeinflusst, nicht als eigenständiges Signal. Die Integration von Korrelationen in die Nutzeroberfläche und den Arbeitsablauf (Kontrollkästchen, Markierungen, Empfehlungen) macht statistische Informationen während des nachrichtengesteuerten Multi-Symbol-Handels umsetzbar. |
| Arbeiten Sie mit Werten, nicht mit Rohpreisen | Berechnen Sie die Korrelation der Werte von Periode zu Periode (relative Preisänderungen), damit die Vergleiche zwischen den Symbolen skalenfrei sind. Die Verwendung von Werten vermeidet Niveaueffekte und macht die Pearson-Korrelation für Instrumente mit unterschiedlichen Preisspannen sinnvoll. |
| Implementierung der Pearson-Korrelation | Setzen Sie den Pearson-Koeffizienten sorgfältig ein: Berechnen Sie Mittelwerte, Kovarianz (Summe der gepaarten Abweichungen) und normalisieren Sie durch das Produkt der Standardabweichungen. Schutz vor Nullvarianz, um Fehler bei der Division durch Null zu vermeiden. |
| Abwägung der Fensterlänge | Wählen Sie die Länge des Korrelationsfensters mit Bedacht: Kurze Fenster reagieren schnell, sind aber verrauscht; lange Fenster sind glatter, aber langsamer. Stellen Sie das Fenster als Laufzeitparameter zur Verfügung, damit die Nutzer die Reaktionsfähigkeit gegenüber der Stabilität abstimmen können. |
| Verzögerung und Erkennung von Vorreiter und Nachfolger | Testen Sie kleine positive und negative Verzögerungen bei der Berechnung der Kreuzkorrelation, um führende Instrumente zu identifizieren. Die Verzögerung mit der höchsten absoluten Korrelation zeigt an, ob ein anderes Paar dem aktuellen Chart voraus- oder hinterherläuft und ermöglicht so Vorreiter-Empfehlungen. |
| Schwellenwerte für Entscheidungen | Wenden Sie einen einstellbaren Schwellenwert an, um zu entscheiden, wann ein Paar als „korreliert“ markiert werden soll. Dies verhindert eine Übermarkierung und ermöglicht es den Händlern, die Empfindlichkeit zu kontrollieren (typische Schwellenwerte liegen zwischen 0,5 und 0,8, je nach Toleranz gegenüber falsch positiven Ergebnissen). |
| Kompakte, nicht-intrusive Visualisierung | Zeigen Sie die Korrelation als kleinen farbigen Punkt und einen numerischen Wert in der Nähe der vorhandenen Symbolkennzeichnungen an, und fügen Sie einen prägnanten Titel wie „Correlation“ hinzu. Kompakte Marker vermitteln Informationen, ohne das Chart zu überladen oder die Handelskontrollen zu behindern. |
| Verankerung von Markierungen an UI-Elementen | Positionieren Sie Korrelationsmarker relativ zu vorhandenen UI-Ankern (z. B. den Symbol-Kontrollkästchen), damit die Marker auch bei Größenänderungen des Charts und bei Änderungen des Panels ausgerichtet bleiben. Aktualisieren Sie die Positionen bei jeder Layoutänderung. |
| Verwenden Sie die Korrelation, um die Exposition zu verringern | Nutzen Sie die Korrelation, um bei der Eröffnung von Positionen mehrerer Paare redundante Paare herauszufiltern. Vermeiden Sie es, ähnliche direktionale Handelsgeschäfte mit stark korrelierten Paaren zu tätigen, um das Gesamtrisiko bei einschneidenden Ereignissen zu verringern. |
| Abstimmung der Laufzeiten ermöglichen | Machen Sie Zeitrahmen, Fenster, maximale Verzögerung und Schwellenwert als Eingaben verfügbar. Die Möglichkeit, diese Einstellungen während der Laufzeit vorzunehmen, erhöht die Flexibilität und hilft, den Algorithmus an unterschiedliche Marktbedingungen und Nutzerpräferenzen anzupassen. |
| Zeitgesteuertes Aktualisieren und Leistung | Neuberechnung und Neuzeichnen von Korrelationsmarkierungen nach einem kontrollierten Zeitplan, um die Werte aktuell zu halten und gleichzeitig die CPU- und API-Nutzung zu begrenzen. Abwägen der Aktualisierungshäufigkeit gegen die Berechnungskosten, sodass die Nutzeroberfläche zeitgemäß, aber nicht ressourcenintensiv ist. |
| Ordentlicher Umgang mit fehlenden oder degenerierten Daten | Erkennen Sie eine unzureichende Historie oder Zeitreihen mit einer Null-Varianz und lassen Sie solche Paare aus oder markieren Sie sie konservativ. Durch die Rückgabe von sicheren Standardwerten anstelle von abgestürzten bleibt der EA bei allen Brokern und Symbollisten stabil. |
| Aufräumen von Objekten bei Deinitialisierung | Entfernen Sie beim Deinitieren alle Korrelationsmarkierungen, Titel und Empfehlungsbeschriftungen, um zu vermeiden, dass verwaiste Objekte im Chart zurückbleiben. Eine ordnungsgemäße Bereinigung gewährleistet ein ordentliches Diagramm, nachdem der EA entfernt oder neu geladen wurde. |
| Modulares, header-basiertes Design | Kapseln Sie die Korrelationslogik und das Zeichnen in einer wiederverwendbaren Kopfzeile/Klasse (z. B. Erweiterung des Dienstprogramms „Trading-Button“). Dadurch wird der EA-Code fokussiert, das Testen vereinfacht und eine projektübergreifende Wiederverwendung ermöglicht. |
| Live-Chart-Tests für Echtzeit-Funktionen bevorzugen | Testen Sie die Korrelation und UI-Interaktionen an einem Live-Chart und nicht mit dem Strategy Tester, da die Korrelation auf Echtzeit-Tick-Dynamik und interaktive UI-Platzierung angewiesen ist, die der Tester nicht vollständig nachbilden kann. |
Anlagen
In der folgenden Tabelle sind die Quelldateien aufgeführt, die aktualisiert wurden, um die Korrelationsfähigkeit hinzuzufügen. Jede Zeile zeigt den Dateinamen, die aktuelle Dateiversion (falls zutreffend) und eine kurze Beschreibung der Änderungen – mit Schwerpunkt auf Korrelationsberechnungen, Marker/UI-Aktualisierungen, öffentlichen API-Hooks und Integrationspunkten mit dem Haupt-EA. | Dateiname | Version | Beschreibung |
|---|---|---|
| TradingButtons.mqh | 1.01 | Der UI-Header für den Handel wurde um Korrelations-Utilities erweitert. Fügt Pearson und verzögerte Kreuzkorrelationsberechnungen, konfigurierbare Parameter (Zeitrahmen, Fenster, maximale Verzögerung, Schwellenwert) und effiziente zeitgesteuerte Aktualisierungen hinzu. Zu den visuellen Änderungen gehören kompakte Korrelationsmarkierungen (farbiger Punkt + numerischer Wert), ein Titel „Correlation“ oberhalb des Blocks, Anpassungen der Platzierung (etwas nach unten und nach rechts verschoben) und die Entfernung von doppeltem Symboltext, sodass nur noch Punkte und Werte neben den vorhandenen Kennzeichnungen erscheinen. Stellt öffentliche API-Funktionen für den EA zur Verfügung: SetCorrelationParams, UpdateCorrelationMarkers, CreatePairCheckboxes, HandleChartEvent und Deinit (Aufräumen). Behandelt degenerierte Daten und bereinigt alle erstellten Objekte bei der Deinitialisierung. |
| NewsHeadlineEA.mq5 | 1.15 | Haupt-EA mit integriertem Kalender, Nachrichten, KI-Einsichten, der TradingButtons-Nutzeroberfläche und Mini-Chart-Kacheln. Aktualisiert, um Korrelationseingaben in den TradingButtons-Header zu übergeben, UpdateCorrelationMarkers bei Init-, Timer- und Chart-Änderungsereignissen aufzurufen und die Korrelations-UI so zu positionieren, dass Überschneidungen mit Handelssteuerungen und CTM vermieden werden. Es integriert auch ChartMiniTiles für Multi-Symbol-Mini-Charts und reserviert den oberen Bereich für die Handelsoberfläche. Sorgt dafür, dass Korrelationsmarker und CTM-Kacheln beim Deinitieren ordnungsgemäß bereinigt werden. |
| ChartMiniTiles.mqh | 1.0 | Wiederverwendbare Klasse für Mini-Chartkacheln zum Einbetten mehrerer Symbolcharts in das Hauptchart. |
Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/19343
Warnung: Alle Rechte sind von MetaQuotes Ltd. vorbehalten. Kopieren oder Vervielfältigen untersagt.
Dieser Artikel wurde von einem Nutzer der Website verfasst und gibt dessen persönliche Meinung wieder. MetaQuotes Ltd übernimmt keine Verantwortung für die Richtigkeit der dargestellten Informationen oder für Folgen, die sich aus der Anwendung der beschriebenen Lösungen, Strategien oder Empfehlungen ergeben.
Aufbau von KI-gesteuerten Handelssystemen in MQL5 (Teil 2): Entwicklung eines ChatGPT-integrierten Programms mit Nutzeroberfläche
Aufbau eines professionellen Handelssystems mit Heikin Ashi (Teil 2): Entwicklung eines EA
Entwicklung des Price Action Analysis Toolkit (Teil 40): Markt-DNA-Pass
Entwicklung eines nutzerdefinierten Indikators für die Kontoperformance-Matrix
- 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.