English 日本語
preview
Einführung in MQL5 (Teil 11): Eine Anleitung für Anfänger zur Arbeit mit integrierten Indikatoren in MQL5 (II)

Einführung in MQL5 (Teil 11): Eine Anleitung für Anfänger zur Arbeit mit integrierten Indikatoren in MQL5 (II)

MetaTrader 5Indikatoren |
186 4
Israel Pelumi Abioye
Israel Pelumi Abioye

Einführung

Willkommen zurück zu unserer MQL5-Serie! In diesem Kapitel werden wir ein faszinierendes Thema behandeln, das Sie sicher sehr nützlich und faszinierend finden werden. Im letzten Kapitel haben wir uns mit der Verwendung der in MQL5 integrierten Indikatoren befasst und dabei dem RSI besondere Aufmerksamkeit gewidmet. Und nicht nur das: Wir haben sogar an einem praktischen Projekt gearbeitet, das Ihnen zeigt, wie Sie den RSI mühelos in Ihren Handelsansatz einbeziehen können. Diesmal gehen wir noch einen Schritt weiter, indem wir nicht nur einen, sondern gleich drei starke Indikatoren in unser Projekt einbeziehen (RSI, Stochastik-Oszillator und gleitender Durchschnitt). Und das ist noch nicht alles: In unserem Projekt lernen Sie auch die faszinierende Idee der versteckten Divergenzerkennung kennen. Wir werden insbesondere darauf eingehen, wie man versteckte Auf- und Abwärts-Divergenzen erkennt.

Es ist wichtig, daran zu denken, dass das einzige Ziel dieses Projekts die Ausbildung ist. Das Hauptziel besteht darin, Ihr Vertrauen in die Nutzung von MQL5 zu stärken und zu lernen, wie man diese Muster programmatisch erkennt. Lassen Sie uns also mit diesem praktischen Projekt beginnen, das Ihr Verständnis von MQL5 vertiefen und Sie in die Lage versetzen wird, Ihre Handelsfähigkeiten zu verbessern.

In diesem Artikel erfahren Sie mehr über Folgendes:

  • Wie man Tiefs und Hochs des RSI in Verbindung mit der entsprechenden Kursbewegung untersucht, um versteckte Auf- und Abwärts-Divergenzen aufzudecken.
  • Entwicklung von Expert Advisors unter Verwendung mehrerer Indikatoren (RSI, MA und Stochastik-Oszillator).
  • Identifizierung und Visualisierung von versteckten Auf- und Abwärts-Divergenzen auf dem Chart.
  • Implementierung des Risikomanagements durch Berechnung von Losgrößen auf der Grundlage des Dollar-Risikos und der Stop-Loss-Abstands für inkonsistente Kerzengrößen bei Verwendung der integrierten Indikatoren.
  • Automatisierung der Handelsgeschäfte mit einem vordefinierten Risiko-Gewinn-Verhältnis (RRR) unter Verwendung von Divergenzsignalen.


1. Das Projekt einrichten

1.1. Wie der EA funktioniert

Der gleitende Durchschnitt und der RSI-Indikator werden in diesem Projekt verwendet, um versteckte Auf- und Abwärts-Divergenzen zu finden. Während der RSI Unterschiede zwischen den RSI-Niveaus und den entsprechenden Kursen feststellt, hilft der MA bei der Identifizierung des Trends. Der Stochastik-Oszillator wird nur verwendet, um die Handelssignale zu validieren und nicht, um Divergenzen zu erkennen.

1.1.1. Versteckte Aufwärts-Divergenz

Zu diesem Zeitpunkt bildet der RSI ein tieferes Tief (lower low bzw. LL), während der Kurs ein höheres Tief (higher low bzw. HL) bildet. Diese Divergenz deutet darauf hin, dass der RSI schwach ist, was auf ein mögliches Aufwärtsmomentum in der Zukunft hindeutet, auch wenn der entsprechende Kurs (C-Kurs) einen höheren Boden gebildet hat.

Abbildung 1. Versteckte Aufwärts-Divergenz

1.1.2. Versteckte Abwärts-Divergenz

Zu diesem Zeitpunkt bildet der RSI ein höheres Hoch, während der Kurs ein niedrigeres Hoch bildet. Dies deutet auf eine mögliche Abwärtsdynamik in der Zukunft hin.

Abbildung 2. Versteckte Abwärts-Divergenz

1.1.3. Logik für einen Verkauf

Trend-Filter:

  • Vergewissern Sie sich, dass der aktuelle Kurs unter dem 200 EMA liegt, um einen Abwärtstrend zu bestätigen.

Markieren Sie das letzte signifikante RSI-Hoch:

  • Identifizieren Sie das jüngste RSI-Hoch, das sich nach einer Aufwärts-Kerze gebildet hat und auf das 3 aufeinanderfolgende Abwärts-Kerzen folgten.
  • Legen Sie eine horizontale Linie auf dem RSI-Chart bei diesem Niveau an.

Markieren des entsprechenden Preises:

  • Ziehen Sie im Kurschart (wechseln Sie zu einem Linienchart) eine horizontale Linie auf dem entsprechenden Kursniveau (C-PRICE) des RSI-Hochs.

Versteckte Abwärts-Divergenz:

  • Halten Sie Ausschau nach einem neuen RSI-Hoch über der horizontalen RSI-Linie.
  • Vergewissern Sie sich, dass der entsprechende Höchstkurs unter der horizontalen Kurslinie im Chart liegt.

Bestätigung durch den Stochastik-Oszillator:

  • Wenn alle Bedingungen erfüllt sind, warten Sie, bis der Stochastik über den überkauften Bereich (z.B. 80) und dann innerhalb von 11 Balken wieder darunter gekreuzt hat.
  • Wenn die Bestätigung nicht innerhalb von 11 Balken erfolgt, wird kein Handel platziert.

SL und TP einstellen:

  • SL: Letztes Swing-Hoch.
  • TP: Definiert durch einen Eingabeparameter für das Risiko-Ertrags-Verhältnis (RRR).

1.1.4. Logik für einen Kauf

Trend-Filter:

  • Stellen Sie sicher, dass der aktuelle Kurs über dem 200 EMA liegt.

Markieren Sie das letzte signifikante RSI-Tief:

  • Identifizieren Sie das jüngste RSI-Tief, das sich nach einer Abwärts-Kerze gebildet hat, auf die 3 aufeinanderfolgende Aufwärts-Kerzen folgten.
  • Legen Sie eine horizontale Linie auf dem RSI-Chart bei diesem Niveau an.

Markieren des entsprechenden Preises:

  • Ziehen Sie im Kurschart (wechseln Sie zu einem Linienchart) eine horizontale Linie auf dem entsprechenden Kursniveau (C-PRICE) des RSI-Tiefs.

Versteckte Aufwärts-Divergenz:

  • Achten Sie auf ein neues RSI-Tief unterhalb der horizontalen RSI-Linie.
  • Vergewissern Sie sich, dass das entsprechende Preistief über der horizontalen Linie des Preises (C-PRICE) im Chart liegt.

Bestätigung durch den Stochastik-Oszillator:

  • Wenn alle Bedingungen erfüllt sind, warten Sie darauf, dass der Stochastik unter den überverkauften Wert (z.B. 20) fällt und dann innerhalb von 11 Balken wieder darüber steigt.
  • Wenn die Bestätigung nicht innerhalb von 11 Balken erfolgt, wird kein Handel platziert.

SL und TP einstellen:

  • SL: Letztes Swing-Tief.
  • TP: Definiert durch einen Eingabeparameter für das Risiko-Ertrags-Verhältnis (RRR).


2. Hinzufügen von Indikatoreigenschaften und Abrufen von Daten

2.1. Einrichten der Indikatoreigenschaften

Wir richten die Eigenschaften der Indikatoren ein, die wir in unserem Projekt verwenden werden: den Stochastik-Oszillator, den RSI und den gleitenden Durchschnitt. Diese Eigenschaften bieten Freiheiten bei der Gestaltung des EA und legen fest, wie sich die Indikatoren verhalten sollen.

Analogie

Stellen Sie sich vor, Sie stellen einen Werkzeugkasten für eine bestimmte Aufgabe zusammen. Ähnlich wie ein Maßband sorgt der gleitende Durchschnitt dafür, dass Sie die Gesamtdimensionen der Aufgabe (Trendrichtung) erfassen können. Wie ein Vergrößerungsglas hilft Ihnen der RSI dabei, kleinste Nuancen oder versteckte Divergenzen zu erkennen. Bevor wir zur nächsten Phase (endgültige Bestätigung) übergehen, dient der Stochastik-Oszillator als Nivellierungsinstrument, um sicherzustellen, dass alles in perfekter Übereinstimmung ist.

Betrachten Sie den Computer als Ihren Helfer bei diesem Unterfangen. Sie müssen ihm genau erklären, was diese Werkzeuge sind und wie sie funktionieren sollen, bevor Sie es auffordern können, sie zu nutzen. Man kann ein allgemeines Werkzeug nicht einfach übergeben und erwarten, dass er weiß, was zu tun ist. Vielmehr müssen Sie die Eigenschaften jedes Werkzeugs angeben, z. B. die Art des Maßbands, die Vergrößerungsstufe der Lupe oder die Empfindlichkeit des Nivelliergeräts. Durch die Konfiguration dieser Funktionen wird sichergestellt, dass der Computer genau weiß, welche Indikatoren er verwenden muss und wie er sie effizient nutzen kann.

Beispiele:
//DECLEAR INDICATOR HANDLES
int ma_handle;
int rsi_handle;
int stoch_handle;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {

//INDICATOR PROPERTIES
   ma_handle = iMA(_Symbol,PERIOD_CURRENT,200,0,MODE_EMA,PRICE_CLOSE);
   rsi_handle = iRSI(_Symbol,PERIOD_CURRENT,14,PRICE_CLOSE);
   stoch_handle = iStochastic(_Symbol,PERIOD_CURRENT,5,3,3,MODE_SMA,STO_LOWHIGH);

   return(INIT_SUCCEEDED);
  }

Erläuterung:

Stellen Sie sich vor, Sie befinden sich in einer Werkstatt mit drei speziellen Geräten für Ihr Projekt: einem Maßband (MA), einer Lupe (RSI) und einer Wasserwaage (Stochastik-Oszillator). Vergewissern Sie sich, dass alle Werkzeuge einsatzbereit und richtig eingestellt sind, bevor Sie beginnen. Sie würden sie nicht einfach aus dem Werkzeugkasten nehmen und sofort verwenden!

Deklaration von Indikator-Handles (Vorbereitung der Werkzeuge)

int ma_handle;
int rsi_handle;
int stoch_handle;

Das ist vergleichbar mit der Benennung der Schränke in Ihrer Werkstatt, in denen Ihre Werkzeuge aufbewahrt werden. Jedes Werkzeug muss seinen eigenen Platz haben, damit Sie es bei Bedarf finden können.

  • ma_handle ist für das Maßband (gleitender Durchschnitt).
  • rsi_handle ist für die Lupe (RSI).
  • stoch_handle ist für die Wasserwaage (Stochastik-Oszillator).

Einrichten der Werkzeuge (Initialisierung der Indikatoren)

Einrichten des iMA (gleitender Durchschnitt)

ma_handle = iMA(_Symbol,PERIOD_CURRENT,200,0,MODE_EMA,PRICE_CLOSE);

Das ist so, als würden Sie Ihrem Assistenten sagen: „Ich muss das Maßband für ein Projekt einrichten“. Sie geben genau an, wie es zu verwenden ist:

  • _Symbol: Dadurch erfährt der Assistent, was Sie messen, z. B. den Vermögenswert, die Aktie oder das Währungspaar, mit dem Sie gerade handeln. Dies beschreibt den zu untersuchenden Vermögenswert (z. B. EUR/USD), so wie Sie mit Ihrem Maßband das zu messende Objekt identifizieren würden.
  • PERIOD_CURRENT: Dies bezieht sich auf den Zeitrahmen, mit dem Sie arbeiten. Denken Sie an die Länge des Maßbands - messen Sie den vergangenen Tag, die vergangene Woche oder den vergangenen Monat? PERIOD_CURRENT bedeutet, dass Sie mit dem Zeitrahmen des aktuellen Charts arbeiten.
  • 200: Dies ist die Länge des Maßbandes (die Anzahl der Kerzen, die der gleitende Durchschnitt abdeckt). Sie bitten also Ihren Assistenten, ein Maßband zu nutzen, das die letzten 200 Kerzen verwendet, um den allgemeinen Trend zu messen.
  • 0: Das ist die Verschiebung. Sie gibt an, um wie viel Sie die Messung nach rechts oder links verschieben möchten. Hier bedeutet 0 keine Verschiebung - Sie messen den aktuellen Preis und die letzten 200 direkt.
  • MODE_EMA: Hier wird die Art des Maßbandes angegeben, das Sie verwenden: Exponentieller gleitender Durchschnitt (EMA). Der EMA ist empfindlicher und reagiert schneller auf Preisänderungen als ein einfacher gleitender Durchschnitt. Sie entscheiden sich also für ein Maßband, das sich schnell an neue Daten anpassen lässt.
  • PRICE_CLOSE: Dies ist der Bezugspunkt für Ihr Maßband. In diesem Fall messen Sie auf der Grundlage des Schlusskurses der jeweiligen Kerze. Genauso wie ein Maßband kalibriert werden kann, um bestimmte Entfernungen zu messen, weisen Sie Ihren Assistenten an, die Schlusskurse gezielt zu messen.

Abbildung 3. Eigenschaften des MA

Einrichten des iRSI (Relative Stärke Index)

rsi_handle = iRSI(_Symbol,PERIOD_CURRENT,14,PRICE_CLOSE);

Jetzt richten Sie die Lupe (RSI) ein. Sie sagen Ihrem Assistenten genau, wie er es verwenden soll:

  • _Symbol: Dies funktioniert auf dieselbe Weise wie zuvor, indem Sie das zu analysierende Handelsinstrument angeben.
  • PERIOD_CURRENT: Genau wie beim gleitenden Durchschnitt arbeiten Sie mit dem Zeitrahmen des aktuellen Charts.
  • 14: Dies ist der Zeitraum für den RSI. Stellen Sie sich das so vor, als ob Sie die Vergrößerungsstärke Ihres Vergrößerungsglases einstellen würden. Sie weisen Ihren Assistenten an, sich auf 14 Perioden (oder Kerzen) zu konzentrieren, die Ihnen helfen, die relative Stärke zu analysieren und Divergenzen zu erkennen.
  • PRICE_CLOSE: Genau wie beim gleitenden Durchschnitt konzentrieren Sie sich bei der Berechnung des RSI auf die Schlusskurse. Dadurch wird sichergestellt, dass Sie den Endpunkt jeder Periode betrachten, um einen genauen Messwert zu erhalten.

Abbildung 4. Eigenschaften des RSI

Einrichten des iStochastic (Stochastik-Oszillator)

stoch_handle = iStochastic(_Symbol,PERIOD_CURRENT,5,3,3,MODE_SMA,STO_LOWHIGH);

  • _Symbol: Auch hier wird, wie bei den vorherigen Indikatoren, angegeben, welchen Vermögenswert Sie analysieren.
  • PERIOD_CURRENT: Sie arbeiten mit dem Zeitrahmen des aktuellen Charts.
  • 5, 3 und 3: Dies sind die Parameter für den Stochastik-Oszillator:
  • 5 ist die %K-Periode: Dies entspricht der Einstellung, wie empfindlich die Wasserwaage (Stochastik-Oszillator) auf Kursbewegungen reagiert. Er prüft die letzten 5 Perioden, um zu sehen, wo der Preis im Verhältnis zu seiner Spanne steht.
  • 3 ist die %D-Periode: Dies ist die geglättete Version von %K, die oft verwendet wird, um ein deutlicheres Signal zu erhalten. 
  • 3 ist die Verzögerung (Slowing period): Auf diese Weise wird der Indikator weiter geglättet, um sicherzustellen, dass er nicht zu sehr auf kleine Veränderungen reagiert, was dazu beiträgt, falsche Signale zu vermeiden.
  • MODE_SMA: Sie fordern die Wasserwaage auf, einen einfachen gleitenden Durchschnitt (SMA) zur Glättung der %K- und %D-Werte zu verwenden, eine einfache, aber zuverlässige Methode zur Mittelwertbildung.
  • STO_LOWHIGH: Dies weist den Assistenten an, die Low/High-Methode für die Berechnung des Stochastik-Oszillators zu verwenden. Das bedeutet, dass Sie sich auf die Preisspanne (tiefstes Tief und höchstes Hoch) in jedem Zeitraum konzentrieren, anstatt die Schlusskurse zu verwenden.

Abbildung 5. Eigenschaften des Oszillators

Indem Sie dem Computer diese Parameter mitteilen, stellen Sie sicher, dass jeder Ihrer Indikatoren (Werkzeuge) richtig kalibriert ist, um seine Aufgabe im Projekt effektiv und genau zu erfüllen.


3. Abrufen der Daten der Indikatoren und der Kerzen

3.1. Abrufen von Indikatordaten

Die Datenextraktion aus den Indikatoren, die wir im vorangegangenen Abschnitt festgelegt haben, wird den Schwerpunkt dieses Kapitels bilden. Wir können die Indikatordaten für die Handelsempfehlungen unseres Expert Advisors nutzen, indem wir sie abrufen. Wir werden auch untersuchen, wie man Informationen aus dem Stochastik-Oszillator, dem RSI und dem gleitenden Durchschnitt (MA) extrahieren kann. Diese Faktoren sind entscheidend, denn sie geben unserem EA die Hinweise, die er für die Platzierung von Handelsgeschäften benötigt. Unser EA muss die relevanten Daten von diesen Indikatoren erhalten, um festzustellen, ob die Bedingungen für den Handel erfüllt sind, so wie ein Bauunternehmer genaue Messungen von seinen Geräten benötigt, um sicherzustellen, dass ein Projekt gut vorankommt. In den folgenden Phasen werden wir untersuchen, wie diese Variablen effektiv abgerufen und gespeichert werden können, sodass der EA Echtzeit-Marktdaten als Grundlage für seine Entscheidungen nutzen kann.

Beispiel:

//DECLEAR INDICATOR HANDLES
int ma_handle;
int rsi_handle;
int stoch_handle;

//DECLEAR DOUBLE VARIABLES THAT STORES INDICATORS DATA
double ma_buffer[];
double rsi_buffer[];
double stoch_buffer_k[], stoch_buffer_d[];

//DECLEAR VARIABLES TO STORE CANDLE DATA
double open[];
double close[];
double high[];
double low[];
datetime time[];

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {

//INDICATOR PROPERTIES
   ma_handle = iMA(_Symbol,PERIOD_CURRENT,200,0,MODE_EMA,PRICE_CLOSE);
   rsi_handle = iRSI(_Symbol,PERIOD_CURRENT,14,PRICE_CLOSE);
   stoch_handle = iStochastic(_Symbol,PERIOD_CURRENT,5,3,3,MODE_SMA,STO_LOWHIGH);

//START FROM THE LATEST CANDLE ON THE CHART
   ArraySetAsSeries(ma_buffer,true);
   ArraySetAsSeries(rsi_buffer,true);
   ArraySetAsSeries(stoch_buffer_k,true);
   ArraySetAsSeries(stoch_buffer_d,true);

//START FROM THE LATEST CANDLE ON THE CHART
   ArraySetAsSeries(open,true);
   ArraySetAsSeries(close,true);
   ArraySetAsSeries(high,true);
   ArraySetAsSeries(low,true);
   ArraySetAsSeries(time,true);

   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {

//COPY INDICATOR'S DATA FROM THE SECOND BAR ON THE CHART TO THE LAST 31st BAR ON THE CHART
   CopyBuffer(ma_handle,0,1,30,ma_buffer);
   CopyBuffer(stoch_handle,0,1,30,stoch_buffer_k);
   CopyBuffer(stoch_handle,1,1,30,stoch_buffer_d);
   CopyBuffer(rsi_handle,0,1,30,rsi_buffer);

//COPY CANDLE'S DATA FROM THE SECOND BAR ON THE CHART TO THE LAST 31st BAR ON THE CHART
   CopyOpen(_Symbol,PERIOD_CURRENT,1,30,open);
   CopyClose(_Symbol,PERIOD_CURRENT,1,30,close);
   CopyHigh(_Symbol,PERIOD_CURRENT,1,30,high);
   CopyLow(_Symbol,PERIOD_CURRENT,1,30,low);
   CopyTime(_Symbol,PERIOD_CURRENT,1,30,time);

  }

Erläuterung:

Deklarieren von Double-Variablen, um die Indikatordaten zu speichern.

Arrays müssen deklariert werden, bevor die Anzeigedaten gespeichert werden können. Da die numerischen Werte der Indikatoren - einschließlich des Stochastik-Oszillators, des RSI und des gleitenden Durchschnitts - in diesen Arrays gespeichert werden, sind sie vom Typ double. Der ma_buffer[] enthält die Werte des gleitenden Durchschnitts (MA), während der rsi_buffer[] die Werte des RSI speichert. In den Arrays stoch_buffer_k[] und stoch_buffer_d[] werden speziell die K- und D-Linien des Stochastik-Oszillators gespeichert. Diese Arrays sind anfangs leer und füllen sich schnell mit den Indikatordaten, die wir von der Grafik erhalten.

Ausgehend von der letzten Kerze im Chart.

In diesem Schritt verwenden wir die Funktion ArraySetAsSeries(), um die Arrays so anzuordnen, dass die neuesten Daten im ersten Index jedes Arrays stehen. Indem wir true als Argument übergeben, weisen wir das Programm an, mit dem Auffüllen der Arrays anhand der neuesten Werte zu beginnen. Dies ist wichtig, da Arrays standardmäßig zuerst mit den ältesten Daten (den ersten Elementen) gefüllt werden. In diesem Fall müssen wir jedoch sicherstellen, dass die jüngsten Indikatorwerte am Anfang zugänglich sind. Diese Regelung erleichtert es uns, bei unseren Handelsentscheidungen mit den neuesten Daten zu arbeiten.

Kopieren von Indikatordaten in Arrays

Sobald die Arrays eingerichtet sind, verwenden wir die Funktion CopyBuffer(), um die eigentlichen Indikatordaten aus dem Chart abzurufen. Die Funktion CopyBuffer() kopiert die Daten aus dem Puffer des Indikators in unsere zuvor deklarierten Arrays. Jeder Aufruf von CopyBuffer() ist spezifisch für einen Indikator:

  • Für den gleitenden Durchschnitt kopieren wir die Daten mit Hilfe von ma_handle und legen sie in ma_buffer[] ab.
  • Wir rufen sowohl die %K- als auch die %D-Werte für den Stochastik-Oszillator ab und speichern sie in stoch_buffer_k[] bzw. stoch_buffer_d[].
  • Wir kopieren die Daten des RSI in rsi_buffer[].

Mit dem vierten Parameter 30 wird die Funktion angewiesen, die Daten der letzten 30 Balken zu übertragen und mit dem dritten Parameter mit dem zweitjüngsten Balken zu beginnen, sodass wir aus den Indikatoren die historischen Daten extrahieren können, die wir für die Analyse und die Entscheidungsfindung unseres Expert Advisors benötigen.

Zusammenfassend lässt sich sagen, dass diese Schritte sicherstellen, dass wir die Daten unserer Indikatoren erfassen, speichern und abrufen können. Indem wir die Arrays deklarieren, die Reihenfolge der Daten korrekt festlegen und CopyBuffer() zum Abrufen der Daten verwenden, haben wir alles vorbereitet, um mit der Analyse der Indikatorwerte zu beginnen und auf der Grundlage dieser Werte Handelsentscheidungen zu treffen.

3.2. Kerzendaten

Nachdem wir die Daten von den Indikatoren erfolgreich abgerufen haben, müssen wir nun die passenden Kerzendaten sammeln, um sie mit den Indikatorwerten abzugleichen. Da sie uns den Kontext liefern, in dem wir unsere Indikatoren anwenden können, sind Kerzendaten für die Entscheidungsfindung beim Handel von entscheidender Bedeutung. Die Kerzen zeigen uns die tatsächliche Marktpreisaktivität, so wie die Indikatoren uns über Trends und Dynamik informieren. Durch die Integration von Indikator- und Kerzendaten können wir mögliche Handelssignale finden, einschließlich der Entwicklung von Auf- oder Abwärts-Divergenzen oder anderen Mustern, die auf eine Veränderung der Marktstimmung hindeuten könnten.

Beispiele:

double open[];
double close[];
double high[];
double low[];
datetime time[];

Wir deklarieren Arrays (open[], close[], high[], low[] und time[]), um wichtige Kerzeninformationen wie Eröffnungs- und Schlusskurse, die Hochs und Tiefs sowie die entsprechenden Zeitstempel zu speichern. Mit Hilfe dieser Variablen können wir die Kursbewegungen analysieren und sie mit den zuvor abgerufenen Indikatordaten korrelieren.

ArraySetAsSeries(open,true);
ArraySetAsSeries(close,true);
ArraySetAsSeries(high,true);
ArraySetAsSeries(low,true);
ArraySetAsSeries(time,true);
Um sicherzustellen, dass die jüngste Kerze am Anfang eines jeden Arrays steht, verwenden wir die Funktion ArraySetAsSeries. Dadurch werden die Daten neu angeordnet, sodass die jüngste Kerze bei Index 0 steht und ältere Kerzen der Reihe nach folgen. Diese Ausrichtung vereinfacht die Analyse und gewährleistet die Konsistenz mit der Struktur der Indikatordaten.
CopyOpen(_Symbol,PERIOD_CURRENT,1,30,open);
CopyClose(_Symbol,PERIOD_CURRENT,1,30,close);
CopyHigh(_Symbol,PERIOD_CURRENT,1,30,high);
CopyLow(_Symbol,PERIOD_CURRENT,1,30,low);
CopyTime(_Symbol,PERIOD_CURRENT,1,30,time);

Mit Funktionen wie CopyOpen, CopyClose, CopyHigh, CopyLow und CopyTime füllen wir die Arrays mit aktuellen Marktdaten. Wir rufen die Daten der letzten 30 Kerzen ab der zweiten Kerze auf dem Chart ab und gleichen die Kursdaten mit den entsprechenden Indikatorwerten ab, um eine genaue Entscheidungsfindung zu ermöglichen.


4. Identifizierung der letzten RSI-Höchst- und Tiefstwerte mit entsprechenden Daten

Als Kriterium für den Vergleich des Indikatorverhaltens mit der Kursentwicklung ist es entscheidend, die jüngsten Höchst- und Tiefststände des RSI zu ermitteln. Der Markt kann weiter steigen, wenn eine versteckte Aufwärts-Divergenz auftritt, d. h. wenn der Kurs ein höheres Tief und der RSI ein niedrigeres Tief erreicht. Es gibt jedoch eine versteckte Abwärts-Divergenz, die auf eine mögliche Fortsetzung des Abwärtstrends hindeutet, wenn der Kurs ein niedrigeres Hoch und der RSI ein höheres Hoch erreicht.

Um festzustellen, ob das Hoch zu diesem Zeitpunkt unter oder der Tiefststand über dem gleitenden Durchschnitt lag, erhalten wir ebenfalls die entsprechende Zahl. Diese zusätzliche Validierung garantiert, dass der Trend mit der erwarteten Bewegung übereinstimmt und hilft bei der Validierung der Divergenzsignale.

4.1. Finden von versteckten Aufwärts-Divergenzen

Die Identifizierung des letzten RSI-Tiefs ist ein wichtiger Schritt, um versteckte Aufwärts-Divergenzen zu erkennen. Der RSI-Tiefstwert stellt einen Punkt dar, an dem die Dynamik während eines Kursrückgangs nachlässt, und seine Analyse zusammen mit den entsprechenden Kurs- und gleitenden Durchschnittswerten (MA) liefert wertvolle Erkenntnisse. Eine versteckte Aufwärts-Divergenz tritt auf, wenn der RSI ein tieferes Tief bildet, während der Kurs ein höheres Tief bildet, was auf ein potenzielles Aufwärtsmomentum trotz des Rücksetzers hinweist.

Um das RSI-Tief zu erkennen, müssen wir eine bestimmte Logik definieren: Das Tief muss sich nach mindestens einer Abwärtsbewegung, gefolgt von drei aufeinanderfolgenden Aufwärtsbewegungen, bilden. Diese Bedingung stellt sicher, dass der Tiefststand eine bedeutende Verschiebung der Dynamik widerspiegelt. Sobald der RSI-Tiefpunkt identifiziert ist, werden wir seine Position abrufen, den entsprechenden Preis auf dem Chart zu diesem Zeitpunkt notieren und den Wert des gleitenden Durchschnitts extrahieren, um festzustellen, ob der Preistiefpunkt über dem MA lag. Diese Validierung trägt dazu bei, die Übereinstimmung des Divergenzsignals mit dem vorherrschenden Trend zu bestätigen, wodurch seine Zuverlässigkeit erhöht wird.

Nachdem wir das RSI-Tief identifiziert haben, werden wir auch eine Logik definieren, um nach einem tieferen Tief zu suchen, das sich nach dem RSI-Tief bilden könnte. Dieses untere Tief muss einen RSI-Wert haben, der unter dem identifizierten RSI-Tief liegt, wobei der Preis zu diesem Zeitpunkt über dem vorherigen Preistief bleibt. Dies gewährleistet, dass die Divergenz intakt bleibt und unterstützt das Kriterium der versteckten Aufwärts-Divergenz. Durch die Integration dieser Schritte schaffen wir einen umfassenden und strukturierten Ansatz zur zuverlässigen Identifizierung von versteckten Aufwärtsdivergenzmöglichkeiten.

Beispiel:
//DECLEAR INDICATOR HANDLES
int ma_handle;
int rsi_handle;
int stoch_handle;

//DECLEAR DOUBLE VARIABLES THAT STORES INDICATORS DATA
double ma_buffer[];
double rsi_buffer[];
double stoch_buffer_k[], stoch_buffer_d[];

//DECLEAR VARIABLES TO STORE CANDLE DATA
double open[];
double close[];
double high[];
double low[];
datetime time[];

//DECLEAR VARIBLE ROR RSI LOW AND CORESPONDING  CANDLE
double   rsi_low_value;          // Stores the RSI value at the identified low point.
double   corresponding_low_value; // Stores the price (closing value) corresponding to the RSI low.
double   corresponding_low_ma;    // Stores the Moving Average value at the same point.
datetime rsi_low_time;           // Stores the timestamp of the RSI low.

//DECLEAR VARIABLE FOR THE MINIMUM CORRESPONDING PRICE VALUE
int  minimum_value_low;

//DECLEAR VARIBLE ROR NEW RSI LOW AND CORESPONDING  CANDLE
double new_rsi_low_value;
datetime new_rsi_low_time;
double new_corresponding_low_value;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {

//INDICATOR PROPERTIES
   ma_handle = iMA(_Symbol,PERIOD_CURRENT,200,0,MODE_EMA,PRICE_CLOSE);
   rsi_handle = iRSI(_Symbol,PERIOD_CURRENT,14,PRICE_CLOSE);
   stoch_handle = iStochastic(_Symbol,PERIOD_CURRENT,5,3,3,MODE_SMA,STO_LOWHIGH);

//START FROM THE LATEST CANDLE ON THE CHART
   ArraySetAsSeries(ma_buffer,true);
   ArraySetAsSeries(rsi_buffer,true);
   ArraySetAsSeries(stoch_buffer_k,true);
   ArraySetAsSeries(stoch_buffer_d,true);

//START FROM THE LATEST CANDLE ON THE CHART
   ArraySetAsSeries(open,true);
   ArraySetAsSeries(close,true);
   ArraySetAsSeries(high,true);
   ArraySetAsSeries(low,true);
   ArraySetAsSeries(time,true);

   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {

//COPY INDICATOR'S DATA FROM THE SECOND BAR ON THE CHART TO THE LAST 31st BAR ON THE CHART
   CopyBuffer(ma_handle,0,1,30,ma_buffer);
   CopyBuffer(stoch_handle,0,1,30,stoch_buffer_k);
   CopyBuffer(stoch_handle,1,1,30,stoch_buffer_d);
   CopyBuffer(rsi_handle,0,1,30,rsi_buffer);

//COPY CANDLE'S DATA FROM THE SECOND BAR ON THE CHART TO THE LAST 31st BAR ON THE CHART
   CopyOpen(_Symbol,PERIOD_CURRENT,1,30,open);
   CopyClose(_Symbol,PERIOD_CURRENT,1,30,close);
   CopyHigh(_Symbol,PERIOD_CURRENT,1,30,high);
   CopyLow(_Symbol,PERIOD_CURRENT,1,30,low);
   CopyTime(_Symbol,PERIOD_CURRENT,1,30,time);

//LOOP THROUGH THE LAST 30 BARS ON THE CHART
   for(int i = 0; i < 30; i++)
     {
      //PREVENT ARRAY OUT OF RANGE ERROR
      if((i+1 < 30) && (i+2 < 30) && (i < 30) && (i+3 < 30) && (i+4 < 30))
        {
         //LOGIC TO IDENTIFY THE LATEST RSI LOW
         if(rsi_buffer[i+4] > rsi_buffer[i+3] && rsi_buffer[i+2] > rsi_buffer[i+3] && rsi_buffer[i+1] > rsi_buffer[i+2] && rsi_buffer[i] > rsi_buffer[i+1])
           {
            //GETTING LATEST RSI LOW, CORRESPONDING CANDLE LOW, CORRESPONDING MA VALUE, and RSI TIME
            rsi_low_value = rsi_buffer[i+3];
            corresponding_low_value = close[i+3];
            corresponding_low_ma = ma_buffer[i+3];
            rsi_low_time = time[i+3];

            break;
           }

        }
     }

//TOTAL NUMBERS OF BARS FROM THE LAST SIGNIFICANT RSI LOW
   int total_bars_2 = 0;
   total_bars_2 = Bars(_Symbol,PERIOD_CURRENT,rsi_low_time, time[0]);

//MINIMUM CLOSE PRICE FROM THE LAST SIGNIFICANT RSI LOW
   minimum_value_low = ArrayMinimum(close,0,total_bars_2);

   if(corresponding_low_value > corresponding_low_ma && close[0] > ma_buffer[0] && close[minimum_value_low] >= corresponding_low_value)
     {
      //CREATE LINES TO MARK RSI AND CORRESPONDING CANDLE LOW
      ObjectCreate(ChartID(),"RSI LOW VALUE",OBJ_TREND,1,rsi_low_time,rsi_low_value,TimeCurrent(),rsi_low_value);
      ObjectCreate(ChartID(),"C-CANDLE",OBJ_TREND,0,rsi_low_time,corresponding_low_value,TimeCurrent(),corresponding_low_value);
      //SETTING OBJECTS COLOUR
      ObjectSetInteger(ChartID(),"RSI LOW VALUE",OBJPROP_COLOR,clrBlack);
      ObjectSetInteger(ChartID(),"C-CANDLE",OBJPROP_COLOR,clrBlack);

      //CREATE TWO LINES TO CONNECT RSI LOW AND THE CORRESPONDING PRICE ON THE CHART
      ObjectCreate(ChartID(),"C-CANDLE LINE",OBJ_TREND,0,rsi_low_time,corresponding_low_value,rsi_low_time,0);
      ObjectCreate(ChartID(),"RSI LOW LINE",OBJ_TREND,1,rsi_low_time,rsi_low_value,rsi_low_time,100);
      //SETTING OBJECTS COLOUR
      ObjectSetInteger(ChartID(),"C-CANDLE LINE",OBJPROP_COLOR,clrBlack);
      ObjectSetInteger(ChartID(),"RSI LOW LINE",OBJPROP_COLOR,clrBlack);

      //CREATE TEXTS TO MART RSI LOW AND CORRESPONDING PRICE (C-PRICE)
      ObjectCreate(ChartID(),"C-CANDLE TEXT",OBJ_TEXT,0,TimeCurrent(),corresponding_low_value);
      ObjectSetString(ChartID(),"C-CANDLE TEXT",OBJPROP_TEXT,"C-PRICE");
      ObjectCreate(ChartID(),"RSI LOW TEXT",OBJ_TEXT,1,TimeCurrent(),rsi_low_value);
      ObjectSetString(ChartID(),"RSI LOW TEXT",OBJPROP_TEXT,"RSI LOW");
      //SETTING TEXT COLOUR
      ObjectSetInteger(ChartID(),"C-CANDLE TEXT",OBJPROP_COLOR,clrBlack);
      ObjectSetInteger(ChartID(),"RSI LOW TEXT",OBJPROP_COLOR,clrBlack);

      //19 LOGIC TO GET THE NEW RSI LOW
      if(rsi_buffer[0] > rsi_buffer[1] && rsi_buffer[1] < rsi_buffer[2] && rsi_buffer[1] < rsi_low_value && close[1] > corresponding_low_value)
        {
         new_rsi_low_value = rsi_buffer[1];
         new_rsi_low_time = time[1];
         new_corresponding_low_value = close[1];

        }

      //CONDITION FOR HIDDEN BULLISH DIVERGENCE
      if(rsi_low_value > new_rsi_low_value && corresponding_low_value < new_corresponding_low_value)
        {
         ObjectCreate(ChartID(),"RSI LOW TREND LINE",OBJ_TREND,1,rsi_low_time,rsi_low_value,new_rsi_low_time,new_rsi_low_value);
         ObjectCreate(ChartID(),"L",OBJ_TEXT,1,rsi_low_time,rsi_low_value);
         ObjectSetString(ChartID(),"L",OBJPROP_TEXT,"L");
         ObjectSetInteger(ChartID(),"L",OBJPROP_FONTSIZE,15);

         ObjectSetInteger(ChartID(),"RSI LOW TREND LINE",OBJPROP_COLOR,clrBlack);
         ObjectSetInteger(ChartID(),"L",OBJPROP_COLOR,clrBlack);

         ObjectCreate(ChartID(),"LL",OBJ_TEXT,1,new_rsi_low_time,new_rsi_low_value);
         ObjectSetString(ChartID(),"LL",OBJPROP_TEXT,"LL");
         ObjectSetInteger(ChartID(),"LL",OBJPROP_FONTSIZE,15);

         ObjectSetInteger(ChartID(),"LL",OBJPROP_COLOR,clrBlack);

         //for candle
         ObjectCreate(ChartID(),"C-CANDLE TREND LINE",OBJ_TREND,0,rsi_low_time,corresponding_low_value,new_rsi_low_time,new_corresponding_low_value);
         ObjectCreate(ChartID(),"CL",OBJ_TEXT,0,rsi_low_time,corresponding_low_value);
         ObjectSetString(ChartID(),"CL",OBJPROP_TEXT,"L");
         ObjectSetInteger(ChartID(),"CL",OBJPROP_FONTSIZE,15);
         ObjectSetInteger(ChartID(),"C-CANDLE TREND LINE",OBJPROP_COLOR,clrBlack);
         ObjectSetInteger(ChartID(),"CL",OBJPROP_COLOR,clrBlack);

         ObjectCreate(ChartID(),"CLL",OBJ_TEXT,0,new_rsi_low_time,new_corresponding_low_value);
         ObjectSetString(ChartID(),"CLL",OBJPROP_TEXT,"HL");
         ObjectSetInteger(ChartID(),"CLL",OBJPROP_FONTSIZE,15);
         ObjectSetInteger(ChartID(),"CLL",OBJPROP_COLOR,clrBlack);

        }

     }

//LOGIC TO DELETE THE OBJECTS WHEN ITS NO LONGER RELEVEANT
   else
      if((close[0] < ma_buffer[0]) || (close[minimum_value_low] < corresponding_low_value))
        {

         ObjectDelete(ChartID(),"RSI LOW VALUE");
         ObjectDelete(ChartID(),"C-CANDLE");
         ObjectDelete(ChartID(),"C-CANDLE LINE");
         ObjectDelete(ChartID(),"RSI LOW LINE");
         ObjectDelete(ChartID(),"C-CANDLE TEXT");
         ObjectDelete(ChartID(),"RSI LOW TEXT");
         ObjectDelete(ChartID(),"RSI LOW TREND LINE");
         ObjectDelete(ChartID(),"L");
         ObjectDelete(ChartID(),"LL");
         ObjectDelete(ChartID(),"C-CANDLE TREND LINE");
         ObjectDelete(ChartID(),"CL");
         ObjectDelete(ChartID(),"RSI LOW TEXT");
         ObjectDelete(ChartID(),"CLL");

        }

}

Erläuterung:

Potenzielle Divergenzen können mit Hilfe des rsi_low_value ermittelt werden, der den niedrigsten RSI-Wert innerhalb einer bestimmten Spanne aufzeichnet. Da Liniencharts auf Schlusskursen basieren, wird die Kompatibilität mit ihnen durch den corresponding_low_value gewährleistet, der der Schlusskurs der Kerze ist, bei der das RSI-Tief auftritt. Bei der Umwandlung in ein Linienchart lässt diese Ausrichtung die RSI-Tiefs und die zugehörigen Preispunkte logisch erscheinen. Um festzustellen, ob der Kurs über oder unter dem gleitenden Durchschnitt (MA) liegt, der häufig Trends bestätigt, hält der corresponding_low_ma den MA-Wert an derselben Stelle. Schließlich ermöglicht die Funktion rsi_low_time die Konstruktion von Objekten wie Trendlinien oder Kennzeichnungen, die mit bestimmten Kerzen verbunden sind, indem der genaue Zeitpunkt des RSI-Tiefs aufgezeichnet wird.

Der nächste Schritt besteht darin, das letzte signifikante RSI-Tief zu ermitteln. Dabei wird nach bestimmten Mustern in den RSI-Werten gesucht, bei denen mindestens eine Abwärtsbewegung, gefolgt von drei aufeinander folgenden Aufwärtsbewegungen, zu verzeichnen ist.

  1. Der Code durchsucht die letzten 30 Balken nach einem signifikanten RSI-Tief.
  2. Wichtigste Bedingung:
    • Der RSI-Wert bei i+3 muss zunächst sinken (Abwärtsbewegung von i+4 auf i+3).
    • Danach muss sie drei aufeinander folgende Erhöhungen aufweisen (i+3 → i+2 → i+1 → i).
  3. Sobald dieses Muster erkannt wird, werden das RSI-Tief, der entsprechende Schlusskurs, der Wert des gleitenden Durchschnitts und der Zeitstempel gespeichert.

Diese Logik stellt sicher, dass der Tiefpunkt Teil eines aussagekräftigen RSI-Verhaltens ist, bei dem auf einen Rückgang des RSI eine Erholung folgt, was ihn zu einem wichtigen Wendepunkt macht.

Warum close[i+3] verwenden?

Wenn Sie ein Linienchart verwenden, wird die Linie anhand der Schlusskurse gezeichnet. Durch die Verknüpfung der RSI-Tiefststände mit dem Schlusskurs werden die von Ihnen erstellten Markierungen (z. B. Trendlinien) korrekt auf das Linienchart ausgerichtet. Dies gewährleistet Klarheit und visuelle Konsistenz.

if(corresponding_low_value > corresponding_low_ma && close[0] > ma_buffer[0] && close[minimum_value_low] >= corresponding_low_value)

Diese Bedingung prüft mehrere Faktoren, um festzustellen, ob die aktuelle Situation den Kriterien für die Erkennung einer versteckten Aufwärtsdivergenz entspricht:

  • corresponding_low_value > corresponding_low_ma: Dabei wird geprüft, ob der Preis beim ermittelten RSI-Tief über dem gleitenden Durchschnitt (MA) liegt. Es deutet darauf hin, dass der Kurs über seinem gleitenden Durchschnitt liegt, was darauf hindeutet, dass der Trend noch relativ stark steigt.
  • close[0] > ma_buffer[0]: Dabei wird geprüft, ob der letzte Schlusskurs (aktuelle Kerze) über dem gleitenden Durchschnittswert liegt, was bestätigt, dass der Kurs immer noch über dem MA liegt und sich in einem Aufwärtstrend befindet.
  • close[minimum_value_low] >= corresponding_low_value: Dies bestätigt, dass der Kurs am jüngsten signifikanten Tiefpunkt (der früher gefunden wurde) immer noch auf oder über dem vorherigen signifikanten Tiefpunkt liegt. Dies trägt dazu bei, dass der Preis nicht unter das vorherige Tief fällt, was auf höhere Preistiefs hindeutet und die Aufwärts-Interpretation unterstützt.

Wenn alle diese Bedingungen zutreffen, deutet dies darauf hin, dass der Kurs über seinem gleitenden Durchschnitt liegt und ein höheres Tief gebildet hat, was ein Hauptmerkmal einer potenziellen versteckten Aufwärts-Divergenz ist, bei der die Kursentwicklung das vom RSI angezeigte tiefere Abwärtsmomentum nicht bestätigt.

//CREATE LINES TO MARK RSI AND CORRESPONDING PRICE
ObjectCreate(ChartID(),"RSI LOW VALUE",OBJ_TREND,1,rsi_low_time,rsi_low_value,TimeCurrent(),rsi_low_value);
ObjectCreate(ChartID(),"C-CANDLE",OBJ_TREND,0,rsi_low_time,corresponding_low_value,TimeCurrent(),corresponding_low_value);
//SETTING OBJECTS COLOUR
ObjectSetInteger(ChartID(),"RSI LOW VALUE",OBJPROP_COLOR,clrBlack);
ObjectSetInteger(ChartID(),"C-CANDLE",OBJPROP_COLOR,clrBlack);

//CREATE TWO LINES TO CONNECT RSI LOW AND THE CORRESPONDING PRICE ON THE CHART
ObjectCreate(ChartID(),"C-CANDLE LINE",OBJ_TREND,0,rsi_low_time,corresponding_low_value,rsi_low_time,0);
ObjectCreate(ChartID(),"RSI LOW LINE",OBJ_TREND,1,rsi_low_time,rsi_low_value,rsi_low_time,100);
//SETTING OBJECTS COLOUR
ObjectSetInteger(ChartID(),"C-CANDLE LINE",OBJPROP_COLOR,clrBlack);
ObjectSetInteger(ChartID(),"RSI LOW LINE",OBJPROP_COLOR,clrBlack);

//CREATE TEXTS TO MART RSI LOW AND CORRESPONDING PRICE (C-PRICE)
ObjectCreate(ChartID(),"C-CANDLE TEXT",OBJ_TEXT,0,TimeCurrent(),corresponding_low_value);
ObjectSetString(ChartID(),"C-CANDLE TEXT",OBJPROP_TEXT,"C-PRICE");
ObjectCreate(ChartID(),"RSI LOW TEXT",OBJ_TEXT,1,TimeCurrent(),rsi_low_value);
ObjectSetString(ChartID(),"RSI LOW TEXT",OBJPROP_TEXT,"RSI LOW");
//SETTING TEXT COLOUR
ObjectSetInteger(ChartID(),"C-CANDLE TEXT",OBJPROP_COLOR,clrBlack);
ObjectSetInteger(ChartID(),"RSI LOW TEXT",OBJPROP_COLOR,clrBlack);

Dieser Code erstellt visuelle Elemente auf dem Chart, um das RSI-Tief und den entsprechenden Preis hervorzuheben, die Schlüsselpunkte für die Identifizierung potenzieller Divergenzmuster sind. Zunächst werden Trendlinien eingezeichnet, um sowohl den RSI-Tiefstwert als auch den entsprechenden Preis (C-PRICE) am selben Punkt zu markieren. Diese Linien, die mit „RSI LOW VALUE“ und „C-CANDLE“ beschriftet sind, werden in Schwarz gezeichnet, um die visuelle Klarheit zu erhalten. Der Zweck dieser Trendlinien besteht darin, das RSI-Tief mit dem entsprechenden Kurs zu verbinden, was Ihnen hilft, die Beziehung zwischen der Kursbewegung und dem RSI-Verhalten leicht zu erkennen.

Anschließend werden zusätzliche Trendlinien erstellt, um das RSI-Tief mit dem entsprechenden Kurs im Chart zu verbinden. Die „C-CANDLE LINE“ verbindet den Kurs des RSI-Tiefs mit dem aktuellen Zeitpunkt, während die „RSI LOW LINE“ das RSI-Tief vertikal auf dem Chart verlängert. Diese Linien dienen als visuelle Markierung, die bei der Analyse der Bewegung des RSI und des Preises helfen, insbesondere bei der Suche nach potenziellen Auf- oder Abwärts-Divergenzen. Alle diese Trendlinien sind auf die Farbe Schwarz eingestellt, um die Konsistenz zu wahren und sicherzustellen, dass sie vor dem Hintergrund des Charts deutlich sichtbar sind.

Schließlich erstellt der Code Textbeschriftungen, um das Chart mit den Werten des RSI-Tiefs und dem entsprechenden Preis (Kerzentief) zu kommentieren. Die Beschriftungen „RSI LOW“ und „C-PRICE“ befinden sich auf den jeweiligen Niveaus des RSI und des Preises, sodass diese Schlüsselpunkte direkt auf dem Chart zu erkennen sind. Diese Textbeschriftungen sind ebenfalls in Schwarz gehalten, damit sie gut lesbar sind. Durch die Erstellung dieser Objekte hilft der Code den Händlern, wichtige Kursniveaus und RSI-Punkte schnell zu visualisieren, was die technische Analyse und die Identifizierung versteckter Divergenzen erleichtert.

AUSGABE:

Abbildung 6. RSI-Tief und entsprechender Preis

Sobald das erste signifikante RSI-Tief identifiziert ist, besteht der nächste Schritt darin, ein neues niedrigeres RSI-Tief zu finden. Die Logik ist hier einfacher als beim ersten Tiefpunkt.

Logik für das neue RSI-Tief:


Das neue RSI-Tief:

  1. Es darf nur eine Abwärtsbewegung geben, bei der der RSI für einen Balken fällt.
  2. Darauf muss eine Aufwärtsbewegung folgen, bei der der RSI unmittelbar nach dem Tiefpunkt ansteigt.
if(rsi_buffer[0] > rsi_buffer[1] && rsi_buffer[1] < rsi_buffer[2] && rsi_buffer[1] < rsi_low_value && close[1] > corresponding_low_value)
  {
  new_rsi_low_value = rsi_buffer[1];
  new_rsi_low_time = time[1];
  new_corresponding_low_value = close[1];

  }

Im ersten Teil des Codes werden Variablen deklariert, die Informationen über das neue RSI-Tief und das entsprechende Kursniveau speichern. Die Variable new_rsi_low_value enthält den Wert des neuen RSI-Tiefs, der für den Vergleich und die Analyse der Divergenz erforderlich ist. Die new_rsi_low_time speichert den Zeitpunkt, an dem der neue RSI-Tiefpunkt auftritt, und dieser Zeitstempel ist wichtig, um diesen Punkt im Chart zu markieren. Schließlich speichert new_corresponding_low_value den mit dem neuen RSI-Tief verbundenen Preis, in der Regel den Schlusskurs, was dazu beiträgt, die RSI-Bewegungen mit dem tatsächlichen Marktpreisgeschehen zu verbinden.

Die Voraussetzung für die Bestimmung des neuen RSI-Tiefststandes wird im zweiten Abschnitt des Codes definiert. Die Argumentation garantiert, dass das neue Tief zwei Voraussetzungen erfüllt: eine Abwärtsbewegung (wenn der RSI fällt) und eine Aufwärtsbewegung (wenn der RSI zu steigen beginnt). Darüber hinaus muss der entsprechende Kurs ein höheres Tief aufweisen, was auf eine mögliche versteckte Aufwärts-Divergenz hindeutet, während das neue RSI-Tief niedriger sein muss als das vorherige RSI-Tief. Um die Divergenz später im Chart hervorzuheben, weist der Algorithmus die neuen Werte für das RSI-Tief, seinen Zeitstempel und den zugehörigen Preis zu, wenn diese Kriterien erfüllt sind.

if(rsi_low_value > new_rsi_low_value && corresponding_low_value < new_corresponding_low_value)

Diese Bedingung sucht nach einer versteckten Aufwärts-Divergenz zwischen dem Preischart und dem RSI. Wenn der Kurs ein höheres Tief erreicht und der RSI ein niedrigeres Tief, spricht man von einer versteckten Aufwärts-Divergenz.

//FOR RSI
ObjectCreate(ChartID(),"RSI LOW TREND LINE",OBJ_TREND,1,rsi_low_time,rsi_low_value,new_rsi_low_time,new_rsi_low_value);
ObjectCreate(ChartID(),"L",OBJ_TEXT,1,rsi_low_time,rsi_low_value);
ObjectSetString(ChartID(),"L",OBJPROP_TEXT,"L");
ObjectSetInteger(ChartID(),"L",OBJPROP_FONTSIZE,15);
ObjectSetInteger(ChartID(),"RSI LOW TREND LINE",OBJPROP_COLOR,clrBlack);
ObjectSetInteger(ChartID(),"L",OBJPROP_COLOR,clrBlack);
ObjectCreate(ChartID(),"LL",OBJ_TEXT,1,new_rsi_low_time,new_rsi_low_value);
ObjectSetString(ChartID(),"LL",OBJPROP_TEXT,"LL");
ObjectSetInteger(ChartID(),"LL",OBJPROP_FONTSIZE,15);
ObjectSetInteger(ChartID(),"LL",OBJPROP_COLOR,clrBlack);

//FOR CORRESPONDING PRICE
ObjectCreate(ChartID(),"C-CANDLE TREND LINE",OBJ_TREND,0,rsi_low_time,corresponding_low_value,new_rsi_low_time,new_corresponding_low_value);
ObjectCreate(ChartID(),"CL",OBJ_TEXT,0,rsi_low_time,corresponding_low_value);
ObjectSetString(ChartID(),"CL",OBJPROP_TEXT,"L");
ObjectSetInteger(ChartID(),"CL",OBJPROP_FONTSIZE,15);
ObjectSetInteger(ChartID(),"C-CANDLE TREND LINE",OBJPROP_COLOR,clrBlack);
ObjectSetInteger(ChartID(),"CL",OBJPROP_COLOR,clrBlack);
ObjectCreate(ChartID(),"CLL",OBJ_TEXT,0,new_rsi_low_time,new_corresponding_low_value);
ObjectSetString(ChartID(),"CLL",OBJPROP_TEXT,"HL");
ObjectSetInteger(ChartID(),"CLL",OBJPROP_FONTSIZE,15);
ObjectSetInteger(ChartID(),"CLL",OBJPROP_COLOR,clrBlack);

Sobald eine versteckte Aufwärts-Divergenz identifiziert ist, soll dieser Codeblock wichtige Chartaspekte grafisch markieren. Bei der ersten Reihe von Maßnahmen liegt der Schwerpunkt auf dem RSI. Der erste wichtige RSI-Tiefpunkt und der darauf folgende niedrigere RSI-Tiefpunkt werden durch Trendlinien und Textbeschriftungen dargestellt. Der Code erstellt zunächst eine Trendlinie zwischen dem neuen unteren RSI-Tief (new_rsi_low_value) und dem ursprünglichen RSI-Tief (rsi_low_value). Händler können den Abwärtstrend des RSI dank der Trendlinie leichter erkennen. In diesen Fällen werden auch die Textbezeichnungen „L“ und „LL“ hinzugefügt, um sie als bemerkenswerte Tiefststände zu kennzeichnen; „L“ bezeichnet den anfänglichen Tiefstand und „LL“ den unteren Tiefstand.

Die nächste Reihe von Maßnahmen konzentriert sich auf die entsprechenden Preisniveaus. Ähnlich wie beim RSI werden Trendlinien und Textbeschriftungen erstellt, um das erste Preistief (corresponding_low_value) mit dem neuen Preistief (new_corresponding_low_value) zu verbinden. Es wird erwartet, dass der entsprechende Kurs ein höheres Tief bildet, was für die versteckte Aufwärts-Divergenz entscheidend ist. Der Code erstellt eine Trendlinie zwischen diesen beiden Kurspunkten und kennzeichnet sie mit „L“ und „HL“, wobei „L“ das erste signifikante Preistief und „HL“ das vom Kurs gebildete höhere Tief kennzeichnet. Diese visuellen Elemente helfen Ihnen zu bestätigen, dass die Kursbewegung das erwartete höhere Tief anzeigt, während der RSI ein niedrigeres Tief anzeigt, ein klassischer Indikator für eine versteckte Aufwärts-Divergenz.

Die Funktion ObjectDelete() ist für die Bereinigung der visuellen Objekte auf dem Chart verantwortlich, wenn die Bedingungen für eine versteckte Aufwärts-Divergenz nicht mehr gültig sind. Konkret wird geprüft, ob der aktuelle Schlusskurs unter dem gleitenden Durchschnitt (ma_buffer[0]) liegt oder ob der minimale Schlusskurs seit dem letzten signifikanten RSI-Tiefstand niedriger ist als der entsprechende Tiefstkurs (corresponding_low_value). Wenn eine dieser Bedingungen erfüllt ist, werden die zuvor gezeichneten Trendlinien, Textbeschriftungen und andere Objekte, die den RSI und die Preistiefs markieren, gelöscht. Dadurch wird sichergestellt, dass das Chart frei von veralteten oder irrelevanten visuellen Markierungn bleibt, sodass sich die Händler auf die aktuellsten und gültigsten Marktbedingungen konzentrieren können.

AUSGABE:

Abbildung 7. alte und neue Tiefs

4.2. Finden von versteckten Abwärts-Divergenzen

Eine versteckte Abwärts-Divergenz tritt auf, wenn der RSI ein höheres Hoch bildet, während der Kurs ein niedrigeres Hoch bildet, was trotz einer vorübergehenden Kurserholung eine potenzielle Abwärtsdynamik signalisiert. Um dieses Muster zu erkennen, wird das letzte RSI-Hoch nach einer bestimmten Logik ermittelt: Es muss nach mindestens einer Aufwärtsbewegung, gefolgt von drei aufeinanderfolgenden Abwärtsbewegungen, auftreten, was auf einen bedeutsamen Höhepunkt der Dynamik hinweist. Sobald das RSI-Hoch identifiziert ist, werden der entsprechende Preis und der Wert des gleitenden Durchschnitts (MA) abgerufen, um die Ausrichtung auf den vorherrschenden Abwärtstrend zu bestätigen. Eine gültige versteckte Abwärts-Divergenz setzt voraus, dass das Kurshoch unter dem MA bleibt, was die abwärts gerichtete Tendenz untermauert.

Im Gegensatz zur versteckten Aufwärts-Divergenz, bei der der RSI ein tieferes Tief und der Kurs ein höheres Tief bildet (was eine potenzielle Aufwärtsdynamik signalisiert), funktioniert die versteckte Abwärts-Divergenz in die entgegengesetzte Richtung. Nach der Identifizierung des RSI-Hochs umfasst die Logik auch die Prüfung auf ein neues RSI-Hoch, das das erste übersteigt, wobei der entsprechende Kurs ein niedrigeres Hoch bildet. Diese Divergenz unterstreicht ein nachlassendes Aufwärts-Momentum, im Gegensatz zu einer versteckten Aufwärts-Divergenz, die ein nachlassendes Abwärts-Momentum anzeigt. Diese Unterscheidungen gewährleisten einen strukturierten Ansatz zur wirksamen Erkennung und Unterscheidung beider Arten von Abweichungen.

Beispiel:

//DECLEAR VARIBLE ROR RSI HIGH AND CORESPONDING  PRICE
double   rsi_high_value;
double   corresponding_high_value;
double   corresponding_high_ma;
datetime rsi_high_time;

//DECLEAR VARIABLE FOR THE MAXIMUM CORRESPONDING PRICE VALUE
int maximum_value_high;

// DECLEAR VARIBLE ROR NEW RSI HIGH AND CORESPONDING PRICE
double new_rsi_high_value;
datetime new_rsi_high_time;
double new_corresponding_high_value;
//LOOP THROUGH THE LAST 30 BARS ON THE CHART
for(int i = 0; i < 30; i++)
  {
//PREVENT ARRAY OUT OF RANGE ERROR
   if((i+1 < 30) && (i+2 < 30) && (i < 30) && (i+3 < 30) && (i+4 < 30))
     {
      //LOGIC TO IDENTIFY THE LATEST RSI HIGH
      if(rsi_buffer[i+4] < rsi_buffer[i+3] && rsi_buffer[i+2] < rsi_buffer[i+3] && rsi_buffer[i+1] < rsi_buffer[i+2] && rsi_buffer[i] < rsi_buffer[i+1])
        {
         //GETTING LATEST RSI HIGH, CORRESPONDING PRICE, CORRESPONDING MA VALUE, and RSI TIME
         rsi_high_value = rsi_buffer[i+3];
         corresponding_high_value = close[i+3];
         corresponding_high_ma = ma_buffer[i+3];
         rsi_high_time = time[i+3];

         break;
        }

     }
  }

//TOTAL NUMBERS OF BARS FROM THE LAST SIGNIFICANT RSI HIGH
int total_bars_3 = 0;
total_bars_3 = Bars(_Symbol,PERIOD_CURRENT,time[0],rsi_high_time);

//MAXIMUM CLOSE PRICE FROM THE LAST SIGNIFICANT RSI LOW
maximum_value_high = ArrayMaximum(close,0,total_bars_3);

if(corresponding_high_value < corresponding_high_ma && close[0] < ma_buffer[0] && close[maximum_value_high] <= corresponding_high_value)
  {
//CREATE LINES TO MARK RSI AND CORRESPONDING PRICE
   ObjectCreate(ChartID(),"RSI HIGH VALUE",OBJ_TREND,1,rsi_high_time,rsi_high_value,TimeCurrent(),rsi_high_value);
   ObjectCreate(ChartID(),"C-CANDLE HIGH",OBJ_TREND,0,rsi_high_time,corresponding_high_value,TimeCurrent(),corresponding_high_value);
//SETTING OBJECTS COLOUR
   ObjectSetInteger(ChartID(),"RSI HIGH VALUE",OBJPROP_COLOR,clrBlack);
   ObjectSetInteger(ChartID(),"C-CANDLE HIGH",OBJPROP_COLOR,clrBlack);

//CREATE TWO LINES TO CONNECT RSI HIGH AND THE CORRESPONDING PRICE ON THE CHART
   ObjectCreate(ChartID(),"C-CANDLE LINE HIGH",OBJ_TREND,0,rsi_high_time,corresponding_high_value,rsi_high_time,0);
   ObjectCreate(ChartID(),"RSI HIGH LINE",OBJ_TREND,1,rsi_high_time,rsi_high_value,rsi_high_time,100);
//SETTING OBJECTS COLOUR
   ObjectSetInteger(ChartID(),"C-CANDLE LINE HIGH",OBJPROP_COLOR,clrBlack);
   ObjectSetInteger(ChartID(),"RSI HIGH LINE",OBJPROP_COLOR,clrBlack);

//CREATE TEXTS TO MART RSI HIGH AND CORRESPONDING PRICE (C-PRICE)
   ObjectCreate(ChartID(),"C-CANDLE TEXT HIGH",OBJ_TEXT,0,TimeCurrent(),corresponding_high_value);
   ObjectSetString(ChartID(),"C-CANDLE TEXT HIGH",OBJPROP_TEXT,"C-PRICE");
   ObjectCreate(ChartID(),"RSI HIGH TEXT",OBJ_TEXT,1,TimeCurrent(),rsi_high_value);
   ObjectSetString(ChartID(),"RSI HIGH TEXT",OBJPROP_TEXT,"RSI HIGH");

//SETTING TEXT COLOUR
   ObjectSetInteger(ChartID(),"C-CANDLE TEXT HIGH",OBJPROP_COLOR,clrBlack);
   ObjectSetInteger(ChartID(),"RSI HIGH TEXT",OBJPROP_COLOR,clrBlack);

//LOGIC TO GET THE NEW RSI HIGH
   if(rsi_buffer[0] < rsi_buffer[1] && rsi_buffer[1] > rsi_buffer[2] && rsi_buffer[1] > rsi_high_value && close[1] < corresponding_high_value)
     {

      new_rsi_high_value = rsi_buffer[1];
      new_rsi_high_time = time[1];
      new_corresponding_high_value = close[1];

     }

   if(rsi_high_value < new_rsi_high_value && corresponding_high_value > new_corresponding_high_value)
     {
      //for rsi
      ObjectCreate(ChartID(),"RSI HIGH TREND LINE",OBJ_TREND,1,rsi_high_time,rsi_high_value,new_rsi_high_time,new_rsi_high_value);
      ObjectCreate(ChartID(),"H",OBJ_TEXT,1,rsi_high_time,rsi_high_value);
      ObjectSetString(ChartID(),"H",OBJPROP_TEXT,"H");
      ObjectSetInteger(ChartID(),"H",OBJPROP_FONTSIZE,15);
      ObjectSetInteger(ChartID(),"RSI HIGH TREND LINE",OBJPROP_COLOR,clrBlack);
      ObjectSetInteger(ChartID(),"H",OBJPROP_COLOR,clrBlack);
      ObjectCreate(ChartID(),"HH",OBJ_TEXT,1,new_rsi_high_time,new_rsi_high_value);
      ObjectSetString(ChartID(),"HH",OBJPROP_TEXT,"HH");
      ObjectSetInteger(ChartID(),"HH",OBJPROP_FONTSIZE,15);
      ObjectSetInteger(ChartID(),"HH",OBJPROP_COLOR,clrBlack);

      //for candle
      ObjectCreate(ChartID(),"C-CANDLE TREND LINE HIGH",OBJ_TREND,0,rsi_high_time,corresponding_high_value,new_rsi_high_time,new_corresponding_high_value);
      ObjectCreate(ChartID(),"CH",OBJ_TEXT,0,rsi_high_time,corresponding_high_value);
      ObjectSetString(ChartID(),"CH",OBJPROP_TEXT,"H");
      ObjectSetInteger(ChartID(),"CH",OBJPROP_FONTSIZE,15);
      ObjectSetInteger(ChartID(),"C-CANDLE TREND LINE HIGH",OBJPROP_COLOR,clrBlack);
      ObjectSetInteger(ChartID(),"CH",OBJPROP_COLOR,clrBlack);
      ObjectCreate(ChartID(),"CLH",OBJ_TEXT,0,new_rsi_high_time,new_corresponding_high_value);
      ObjectSetString(ChartID(),"CLH",OBJPROP_TEXT,"LH");
      ObjectSetInteger(ChartID(),"CLH",OBJPROP_FONTSIZE,15);
      ObjectSetInteger(ChartID(),"CLH",OBJPROP_COLOR,clrBlack);
     }

  }

//LOGIC TO DELETE THE OBJECTS WHEN ITS NO LONGER RELEVEANT
else
   if((close[0] > ma_buffer[0]) || (close[maximum_value_high] > corresponding_high_value))
     {

      ObjectDelete(ChartID(),"RSI HIGH VALUE");
      ObjectDelete(ChartID(),"C-CANDLE HIGH");
      ObjectDelete(ChartID(),"C-CANDLE LINE HIGH");
      ObjectDelete(ChartID(),"RSI HIGH LINE");
      ObjectDelete(ChartID(),"C-CANDLE TEXT HIGH");
      ObjectDelete(ChartID(),"RSI HIGH TEXT");
      ObjectDelete(ChartID(),"RSI HIGH TREND LINE");
      ObjectDelete(ChartID(),"H");
      ObjectDelete(ChartID(),"HH");
      ObjectDelete(ChartID(),"C-CANDLE TREND LINE HIGH");
      ObjectDelete(ChartID(),"CH");
      ObjectDelete(ChartID(),"CLH");

     }

Erläuterung:

Dieses Codesegment dient dazu, versteckte Abwärts-Divergenzen zu erkennen, indem RSI-Hochs und die entsprechenden Kurshochs ermittelt werden, wobei eine ähnliche Logik wie in 4.1 verfolgt wird. Finden von versteckten Aufwärts-Divergenzen. An dieser Stelle soll nicht weiter darauf eingegangen werden, da der größte Teil der Logik bereits in 4.1 erläutert wurde. Finden versteckter Aufwärts-Divergenzen; der einzige Unterschied ist, dass der Fokus nun auf dem entgegengesetzten Szenario liegt. Während der zugrundeliegende Ansatz konsistent bleibt, zielt diese Implementierung auf ein Abwärts-Momentum ab, indem sie sich auf RSI-Hochs statt auf Tiefs konzentriert.

Im ersten Teil des Codes werden Variablen wie rsi_high_value, corresponding_high_value und corresponding_high_ma deklariert, um den RSI-Höchstwert, den entsprechenden Preis bzw. den Wert des gleitenden Durchschnitts (MA) zu speichern. Diese werden verwendet, um das letzte RSI-Hoch zu identifizieren, indem die letzten 30 Balken in einer Schleife durchlaufen werden und die Bedingung einer Aufwärtsbewegung gefolgt von drei aufeinanderfolgenden Abwärtsbewegungen angewendet wird. Sobald ein RSI-Hoch gefunden wird, werden der entsprechende Kurs und der MA-Wert abgerufen und der Zeitstempel (rsi_high_time) aufgezeichnet. Ein Validierungsschritt stellt sicher, dass der entsprechende Preishöchststand unter dem MA liegt, wodurch der Abwärtstrend verstärkt wird.

Abbildung 8. RSI und korrespondierendes Hoch

Als Nächstes stellen wir ein neues RSI-Hoch fest, bei dem der RSI ein höheres Hoch und der Kurs ein niedrigeres Hoch (LH) bildet. Dies erfüllt die Kriterien für eine versteckte Abwärts-Divergenz und signalisiert ein nachlassendes Aufwärts-Momentum der Kursbewegung. Wenn diese Bedingung erfüllt ist, werden Trendlinien und Beschriftungen erstellt, um die RSI-Höchststände (H und HH) und die entsprechenden Kurshöchststände (H und LH) auf dem Chart visuell zu markieren. Diese visuellen Markierung helfen Händlern, potenzielle versteckte Abwärts-Divergenzpunkte schnell zu erkennen.

Der Code enthält auch eine Logik zum Löschen von Objekten, wenn die Bedingungen für eine versteckte Baisse-Divergenz nicht mehr erfüllt sind, z. B. wenn der aktuelle Kurs über dem MA schließt oder der Höchstkurs seit dem identifizierten RSI-Hoch den entsprechenden Höchstwert überschreitet. Dadurch wird sichergestellt, dass das Chart sauber bleibt und nur gültige Divergenzsignale widerspiegelt.

Abbildung 9. Höchststände und neue Höchststände


5. Einbeziehung des Stochastik-Oszillators und Ausführung von Handelsgeschäften

Der Stochastik-Oszillator wird als letztes Bestätigungsinstrument vorgestellt, nachdem wir nun wissen, wie wir den gleitenden Durchschnitt und den RSI nutzen können, um versteckte Auf- und Abwärts-Divergenzen zu finden. Da der Oszillator sicherstellt, dass die Divergenz mit Verschiebungen der Marktdynamik übereinstimmt, erhöht er die Präzision des Handelseinstiegs. Bei strikten Timing- und Risikomanagement-Richtlinien hängt der Bestätigungsgrund für beide Divergenzarten von der Leistung des Oszillators in Bezug auf überkaufte und überverkaufte Niveaus ab.

5.1. Einbindung des Stochastik-Oszillators

Nach der Bestätigung der versteckten Aufwärts-Divergenz durch den RSI und die Kursbewegung werden wir darauf achten, dass der Stochastik-Oszillator unter den überverkauften Bereich (20) fällt und dann wieder darüber steigt. Dieses Kreuzen muss 11 Balken nach Erkennen der Divergenz erfolgen, um das Signal zu bestätigen. Wird dies bestätigt, wird ein Kaufgeschäft eingeleitet, wobei der Stop-Loss (SL) das letzte Swing-Tief ist. Der Take-Profit (TP) wird durch ein vordefiniertes Risiko-Ertrags-Verhältnis (RRR) festgelegt, um ein diszipliniertes Handelsmanagement zu gewährleisten.

Beispiel:

if(total_bars < 11)
  {
   if(stoch_buffer_k[0] < 20 && stoch_buffer_k[1] > 20 && currentBarTime != lastTradeBarTime && totalPositions < 1)
     {
      //
     }
  }

Erläuterung:

Dieser Code bestätigt ein verstecktes Aufwärts-Divergenz-Setup, indem er es mit dem Stochastik-Oszillator validiert. Zunächst wird mit Hilfe der Funktion Bars die Anzahl der Balken seit dem RSI-Tief (new_rsi_low_time) berechnet und sichergestellt, dass das Handels-Setup innerhalb eines Fensters von 11 Balken gültig bleibt „(if(total_bars < 11))“. Innerhalb dieses Zeitraums wird geprüft, ob die %K-Linie des Stochastik-Oszillators den überverkauften Bereich von 20 überschritten hat (stoch_buffer_k[1] < 20 und stoch_buffer_k[0] > 20). Dieses Kreuzen bestätigt ein potenzielles Aufwärtsmomentum und verstärkt das Aufwärts-Signal. Wenn beide Bedingungen erfüllt sind, führt der Code die Handelslogik aus und stellt sicher, dass alle Kriterien für eine versteckte Aufwärtsdivergenz erfüllt sind.

Ebenso werden wir abwarten, bis der Stochastik-Oszillator über den überkauften Bereich (80) steigt und dann wieder darunter kreuzt, um die versteckte Abwärts-Divergenz zu bestätigen. Darüber hinaus muss dieses Abwärts-Kreuzen innerhalb von 11 Bars nach Erkennen der Divergenz erfolgen. Wenn dies bestätigt wird, wird eine Verkaufstransaktion durchgeführt, wobei der TP unter Verwendung des angegebenen RRR berechnet und der SL auf das letzte Swing-Hoch gesetzt wird. Durch die Kombination dieser Verfahren mit der ursprünglichen Divergenzerkennungsmethode wird sichergestellt, dass nur dann gehandelt wird, wenn ein offensichtliches Risikomanagement und eine gute Momentumausrichtung vorliegen.

Beispiel:

int total_bars = Bars(_Symbol,PERIOD_CURRENT,new_rsi_high_time,TimeCurrent());

if(total_bars < 11)
  {
   if(stoch_buffer_k[0] < 80 && stoch_buffer_k[1] > 80)
     {
      //
     }
  }

Erläuterung:

Die Anzahl der Balken zwischen dem aktuellen Zeitpunkt (TimeCurrent()) und dem Zeitpunkt, an dem das neue RSI-Hoch (new_rsi_high_time) entdeckt wurde, wird durch die Variable total_bars bestimmt. Sie garantiert, dass die Einrichtung noch aktiv ist und nicht abgelaufen ist, wenn weniger als elf Balken vorhanden sind. Der Code ermittelt dann, ob die %K-Linie des Stochastik-Oszillators (stoch_buffer_k) im aktuellen Balken unter den Schwellenwert für überkaufte Kurse (80) gefallen ist (stoch_buffer_k[0] < 80) und im vorherigen Balken darüber lag (stoch_buffer_k[1] > 80). Der Geschäftsaufbau wird überprüft, und der Code beginnt mit der Ausführung der erforderlichen Logik zur Eingabe des Handelsgeschäfts, wenn beide Anforderungen erfüllt sind.

5.2. Ausführung des Handels

5.2.1. Swing Low und Swing High

Dieser Abschnitt befasst sich mit allen wesentlichen Komponenten, die erforderlich sind, um nach Bestätigung eines gültigen Divergenz- und Stochastik-Oszillator-Signals die Handelsgeschäfte auszuführen. Sie stellt sicher, dass die Handelsgeschäfte systematisch und mit angemessenem Risikomanagement ausgeführt werden.

Um den Stop-Loss (SL) zu definieren, muss zunächst das letzte Swing-Hoch oder -Tief ermittelt werden. Bei einer versteckten Aufwärtsdivergenz ist das letzte Swing-Tief der SL, bei einer versteckten Abwärts-Divergenz das letzte Swing-Hoch. Damit ist gewährleistet, dass die Handelsgeschäfte je nach vorherigem Kursverhalten eine genau definierte Risikoschwelle haben.

Beispiel:

double last_high;
double last_low;

//LOGIC FOR LAST HIGH
for(int i = 0; i < 30; i++)
  {
   if(i < 30 && i+1 < 30)
     {
      if(close[i] < open[i] && close[i+1] > open[i+1])
        {

         last_high = MathMax(high[i],high[i+1]);

         break;
        }
     }

  }

//LOGIC FOR LAST LOW
for(int i = 0; i < 30; i++)
  {
   if(i < 30 && i+1 < 30)
     {
      if(close[i] > open[i] && close[i+1] < open[i+1])
        {

         last_low = MathMin(low[i],low[i+1]);

         break;
        }
     }
  }
  }

Erläuterung:

Um das jüngste Swing-Hoch und -Tief zu ermitteln, untersucht dieser Code die letzten 30 Bars. Er ermittelt den höchsten Kurs (last_high), indem er eine Abwärts-Kerze, gefolgt von einer steigenden, erkennt, und den niedrigsten Kurs (last_low), indem er eine Aufwärts-Kerze, gefolgt von einer Abwärts-Kerze, erkennt. Bei der Festlegung von Stop-Loss-Niveaus sind diese Zahlen von entscheidender Bedeutung.

5.2.2. Verwaltung der Handelsausführung und Verhinderung von Over-Trading

Das System lässt jeweils nur eine offene Position zu, um übermäßigen Handel zu verhindern und unnötige Risiken zu verringern. Der Code stellt sicher, dass es keine offenen Positionen gibt, bevor eine neue Transaktion durchgeführt wird. Dies garantiert ein besser kontrolliertes Handelsverhalten, da das System nicht mehr bei jedem Signal Transaktionen abschließt. Für eine effektive Handelsausführung ist die Bibliothek #include <Trade/Trade.mqh> erforderlich, die den Zugriff auf die Klasse CTrade für die Handelsverwaltung ermöglicht.

Beispiel:

#include <Trade/Trade.mqh>
CTrade trade;
input int MagicNumber   = 9097; //MAGIC NUMBER

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {

//SET MAGIC NUMBER
   trade.SetExpertMagicNumber(MagicNumber);

   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {

// Getting total positions
   int totalPositions = 0;

   for(int i = 0; i < PositionsTotal(); i++)
     {
      ulong ticket = PositionGetTicket(i);
      if(PositionGetInteger(POSITION_MAGIC) == MagicNumber && PositionGetString(POSITION_SYMBOL) == ChartSymbol(ChartID()))
        {
         totalPositions++;
        }
     }
  }

Erläuterung:

Der Code beginnt mit der Einbindung der Trade.mqh-Bibliothek, die Zugang zu den Handelsfunktionen in MetaTrader bietet. Das CTrade-Objekt, Trade, wird dann instanziiert, um Handelsoperationen zu verwalten. Die MagicNumber wird als Eingabe definiert, die in diesem Fall auf 9097 gesetzt ist und die von diesem speziellen Expert Advisor (EA) eröffneten Trades eindeutig identifiziert, um sie von anderen auf demselben Konto zu unterscheiden. In der Funktion OnInit() wird die magische Zahl mit SetExpertMagicNumber(MagicNumber) auf das Handelsobjekt angewendet. Dadurch wird sichergestellt, dass der EA seine Handelsgeschäfte erkennt, wenn er Operationen wie das Öffnen, Ändern oder Schließen von Positionen durchführt.

In der Funktion OnTick() prüft der Code die Gesamtzahl der offenen Positionen für das Symbol im aktuellen Chart, indem er mit PositionsTotal() durch alle Positionen iteriert. Er ruft die Ticketnummer jeder Position mit PositionGetTicket(i) ab und überprüft, ob die magische Zahl der Position mit der magischen Zahl des EA übereinstimmt, indem er PositionGetInteger(POSITION_MAGIC) verwendet. Zusätzlich prüft der Code, ob die Position zum aktuellen Chart-Symbol gehört, indem er PositionGetString(POSITION_SYMBOL) verwendet. Wenn beide Bedingungen erfüllt sind, wird die Variable totalPositions inkrementiert, wobei die Anzahl der offenen Handelsgeschäfte in Bezug auf den spezifischen EA und das Symbol verfolgt wird, wodurch sichergestellt wird, dass jeweils nur eine Position offen ist.

5.2.3. Risikomanagement

Das Handelssystem garantiert einen methodischen Ansatz für das Risikomanagement und die Maximierung der Rentabilität durch die Integration dieser beiden wesentlichen Elemente. Diese Strategie unterstützt den langfristigen Markterfolg und trägt zur Sicherung des Handelskontos bei. Die Implementierung eines starken Risikomanagementsystems, das es den Händlern ermöglicht, den genauen Geldbetrag anzugeben, den sie bei jedem Handelsgeschäft riskieren wollen, ist das Hauptziel dieses Abschnitts. Um sicherzustellen, dass die möglichen Gewinne die möglichen Risiken übersteigen, wird auch beschrieben, wie das Risiko-Ertrags-Verhältnis (RRR) für jeden Handel berechnet wird.

Beispiel:

//INPUTS
input double risk_amount = 20; // $ PER TRADE
input double rrr = 4; //RRR
input int MagicNumber   = 9097; //MAGIC NUMBER

double take_profit;
double points_risk;
double lot_size;
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//BULLISH HIDDEN DIVERGENCE
   if(stoch_buffer_k[0] > 20 && stoch_buffer_k[1] < 20 && currentBarTime != lastTradeBarTime && totalPositions < 1)
     {
      take_profit  = ((ask_price - last_low) * rrr) + ask_price;
      points_risk = ask_price - low[0];
      lot_size = CalculateLotSize(_Symbol, risk_amount, points_risk);

      trade.Buy(lot_size,_Symbol,ask_price,last_low,take_profit);
      lastTradeBarTime = currentBarTime;

     }

//BEARISH HIDDEN DIVERGENCE
   if(stoch_buffer_k[0] < 80 && stoch_buffer_k[1] > 80 && currentBarTime != lastTradeBarTime && totalPositions < 1)
     {
      take_profit  = MathAbs(((last_high - ask_price) * rrr) - ask_price);
      points_risk = high[0] - ask_price;
      lot_size = CalculateLotSize(_Symbol, risk_amount, points_risk);

      trade.Sell(lot_size,_Symbol,ask_price,last_high,take_profit);
      lastTradeBarTime = currentBarTime;

     }

  }

//+-----------------------------------------------------------------------+
//| Function to calculate the lot size based on risk amount and stop loss |
//+-----------------------------------------------------------------------+
double CalculateLotSize(string symbol, double riskAmount, double stopLossPips)
  {
// Get symbol information
   double point = SymbolInfoDouble(symbol, SYMBOL_POINT);
   double tickValue = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE);

// Calculate pip value per lot
   double pipValuePerLot = tickValue / point;

// Calculate the stop loss value in currency
   double stopLossValue = stopLossPips * pipValuePerLot;

// Calculate the lot size
   double lotSize = riskAmount / stopLossValue;

// Round the lot size to the nearest acceptable lot step
   double lotStep = SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP);
   lotSize = MathFloor(lotSize / lotStep) * lotStep;

// Ensure the lot size is within the allowed range
   double minLot = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);
   double maxLot = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX);

   return lotSize;
  }

Erläuterung:

Auf der Grundlage eines bestimmten Risikobetrags (in Dollar) und der Stop-Loss-Distanz (in Pip) berechnet die Funktion CalculateLotSize die richtige Losgröße für einen Handel. Die Losgröße wird bestimmt, indem der Risikobetrag durch den Stop-Loss-Wert geteilt, die Stop-Loss-Distanz in einen Geldwert umgerechnet und der Pip-Wert pro Losgröße anhand symbolspezifischer Daten berechnet wird. Das Ergebnis wird so angepasst, dass es den Anforderungen des Maklers an die Mindest- und Höchstlosgröße sowie an die Losgrößenschritte entspricht. Damit diese Funktion im gesamten Code wiederverwendet werden kann und das Risikomanagement einheitlich und effektiv ist, sollte sie im globalen Bereich deklariert werden.

Für einen Kauf muss die %K-Linie des Stochastik-Oszillators über 20 steigen, nachdem sie darunter gefallen ist. Trades werden nur ausgeführt, wenn keine Positionen offen sind (totalPositions < 1) und der aktuelle Balken von dem zuletzt gehandelten Bar abweicht. Der Stop-Loss wird auf das letzte Swing-Low gesetzt, und der Take-Profit wird anhand des Risiko-Ertrags-Verhältnisses (rrr) und des Abstands zwischen dem Briefkurs und dem Swing-Low berechnet. Die Losgröße wird mit der Funktion CalculateLotSize auf der Grundlage des Risikobetrags und des Stop-Loss-Abstands bestimmt. Nach der Ausführung wird die lastTradeBarTime aktualisiert, um doppelte Abschlüsse auf demselben Balken zu verhindern.

Abbildung 10. KAUFEN

Die %K-Linie des Oszillators muss zunächst über der 80er-Marke (überkauft) liegen, bevor sie diese unterschreitet, um ein Verkaufsignal zu setzen. In ähnlicher Weise wird die Transaktion nur ausgeführt, wenn es keine offenen Positionen gibt und der Balken neu ist. Das Chance-Risiko-Verhältnis und die Differenz zwischen dem Briefkurs und dem letzten Swing-High (last_high) werden verwendet, um den Take-Profit (take_profit) zu bestimmen. Beim letzten Hoch des Swing wird der Stop-Loss gesetzt. Die Funktion CalculateLotSize wird noch einmal verwendet, um die Losgröße zu bestimmen. Um doppelte Abschlüsse zu vermeiden, aktualisiert die Verkaufsfunktion lastTradeBarTime und platziert den Verkaufsauftrag.

Durch die Einhaltung von Transaktionslimits, angemessenem Risikomanagement und Bestätigungssignalen garantiert dieser Code diszipliniertes Handeln und erhöht die Verlässlichkeit der Handelsstrategie.

Abbildung 11. VERKAUFEN


Schlussfolgerung

Dieser Artikel enthält eine Schritt-für-Schritt-Anleitung zur Identifizierung und zum Handel mit versteckten Auf- und Abwärts-Divergenzen unter Verwendung von MQL5, wobei Indikatoren wie der gleitende Durchschnitt, der RSI und der Stochastik-Oszillator integriert werden. Der Schwerpunkt lag dabei auf Risikomanagement, Handelsausführung und Automatisierung, um den Händlern zu helfen, diese Muster auf dem Markt effektiv zu erkennen. Dieser Lehrinhalt zielt darauf ab, die Grundlagen der Divergenzerfassung und des systematischen Handels zu vermitteln. Ein detaillierter Quellcode mit ausführlichen Kommentaren wird beigefügt und dient als praktische Referenz für die Umsetzung der besprochenen Konzepte.

Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/16956

Letzte Kommentare | Zur Diskussion im Händlerforum (4)
Oluwatosin Mary Babalola
Oluwatosin Mary Babalola | 6 Feb. 2025 in 19:12
Dankeschön
Israel Pelumi Abioye
Israel Pelumi Abioye | 6 Feb. 2025 in 19:42
Oluwatosin Mary Babalola #:
Dankeschön
Gern geschehen
Jee_Pee
Jee_Pee | 18 Feb. 2025 in 15:52
Hallo Israel, danke, dass du dir so viel Zeit für die klaren Projekte nimmst, vor allem deine Analogien gefallen mir, du hältst dein Versprechen, "alles in kleinen Schritten zu tun". Danke, ich werde das Projekt jetzt beginnen (11), und ich bin ziemlich aufgeregt, ich lasse dich von mir hören John
Israel Pelumi Abioye
Israel Pelumi Abioye | 18 Feb. 2025 in 17:23
Jee_Pee Projekte nimmst, vor allem deine Analogien gefallen mir, du hältst dein Versprechen, "alles in kleinen Schritten zu tun". Danke, ich werde das Projekt jetzt beginnen (11), und ich bin ziemlich aufgeregt, ich werde dich von mir hören lassen John

Gern geschehen, vielen Dank für Ihre freundlichen Worte.

Gating-Mechanismen beim Ensemblelernen Gating-Mechanismen beim Ensemblelernen
In diesem Artikel setzen wir unsere Untersuchung von Ensemblemodellen fort, indem wir das Konzept der Gates erörtern, insbesondere wie sie bei der Kombination von Modellergebnissen nützlich sein können, um entweder die Vorhersagegenauigkeit oder die Modellgeneralisierung zu verbessern.
Selbstoptimierende Expert Advisor in MQL5 (Teil 4): Dynamische Positionsgrößen Selbstoptimierende Expert Advisor in MQL5 (Teil 4): Dynamische Positionsgrößen
Der erfolgreiche Einsatz des algorithmischen Handels erfordert kontinuierliches, interdisziplinäres Lernen. Die unendlichen Möglichkeiten können jedoch jahrelange Bemühungen verschlingen, ohne greifbare Ergebnisse zu liefern. Um dieses Problem zu lösen, schlagen wir einen Rahmen vor, der die Komplexität schrittweise einführt und es den Händlern ermöglicht, ihre Strategien iterativ zu verfeinern, anstatt sich für unbestimmte Zeit auf ungewisse Ergebnisse festzulegen.
Automatisieren von Handelsstrategien in MQL5 (Teil 4): Aufbau eines mehrstufigen Zone Recovery Systems Automatisieren von Handelsstrategien in MQL5 (Teil 4): Aufbau eines mehrstufigen Zone Recovery Systems
In diesem Artikel entwickeln wir ein mehrstufiges Zone Recovery System in MQL5, das den RSI zur Erzeugung von Handelssignalen nutzt. Jede Signalinstanz wird dynamisch zu einer Array-Struktur hinzugefügt, sodass das System mehrere Signale gleichzeitig innerhalb der Zonenwiederherstellungslogik verwalten kann. Mit diesem Ansatz zeigen wir, wie man komplexe Handelsverwaltungsszenarien effektiv handhabt und gleichzeitig einen skalierbaren und robusten Codeentwurf beibehält.
Neudefinition der Indikatoren von MQL5 und dem MetaTrader 5 Neudefinition der Indikatoren von MQL5 und dem MetaTrader 5
Ein innovativer Ansatz zur Erfassung von Indikatorinformationen in MQL5 ermöglicht eine flexiblere und rationalisierte Datenanalyse, indem Entwickler nutzerdefinierte Eingaben an Indikatoren für sofortige Berechnungen weitergeben können. Dieser Ansatz ist besonders nützlich für den algorithmischen Handel, da er eine bessere Kontrolle über die von den Indikatoren verarbeiteten Informationen ermöglicht und über die traditionellen Beschränkungen hinausgeht.