
Einführung in MQL5 (Teil 12): Ein Anfängerleitfaden für das Erstellen nutzerdefinierter Indikatoren
Einführung
Willkommen zurück zu unserer MQL5-Serie! Bisher haben wir viel behandelt, darunter den Umgang mit integrierten Indikatoren, die Erstellung von Expert Advisors, die Erforschung grundlegender MQL5-Konzepte und die Anwendung unseres Wissens in praktischen Projekten. Jetzt ist es an der Zeit, einen Schritt weiter zu gehen und zu lernen, wie man einen nutzerdefinierten Indikator von Grund auf erstellt. Wir erhalten ein tieferes Verständnis für die interne Funktionsweise von Indikatoren, sodass wir die vollständige Kontrolle über ihre Funktionsweise und ihr Design haben, anstatt uns auf integrierte Funktionen zu verlassen. Haben Sie sich jemals gefragt, wie der gleitende Durchschnitt oder der MACD, zwei der in MQL5 integrierten Indikatoren, erstellt werden? Wenn es keine Funktionen wie iRSI oder iMA gäbe, könnten Sie dann trotzdem Indikatoren erstellen?
Mit Hilfe eines projektbezogenen Ansatzes werden wir den Prozess in zwei Hauptteile unterteilen. Zunächst werden wir einen gleitenden Durchschnittsindikator von Grund auf neu erstellen, ohne die iMA-Funktion zu verwenden. Als Nächstes gehen wir einen Schritt weiter und wandeln den gleitenden Durchschnitt von einer herkömmlichen Linienform in eine kerzenförmige Anzeige um. Darüber hinaus eröffnet diese praktische Methode neue Wege zur Entwicklung von Handelsinstrumenten, die speziell auf Ihre Bedürfnisse zugeschnitten sind.
Gleitender Durchschnitt als Linie
Gleitender Durchschnitt als Kerzen
In diesem Artikel erfahren Sie mehr über Folgendes:
- Wie man einen nutzerdefinierten Indikator von Grund auf in MQL5 erstellt.
- Der Unterschied zwischen der Darstellung von Indikatoren im Linienformat und im Kerzenformat.
- Verwendung von Indikatorpuffern zum Speichern und Anzeigen berechneter Werte.
- Setzen Sie die Eigenschaften des Indikators richtig.
- Erstellen eines nutzerdefinierten gleitenden Durchschnittsindikators in MQL5.
- Abbildung von Indikatorpuffern mit SetIndexBuffer().
- Verarbeitung von Preisdaten mit der Funktion OnCalculate().
- Wie man die Kerzenfarben je nach der Kursbewegung bestimmt.
Selbst wenn Sie MQL5 noch nicht kennen, können Sie den Ausführungen folgen, ohne sich überfordert zu fühlen, denn dieser Artikel ist anfängerfreundlich. Jede Zeile des Codes wird gründlich erklärt, wobei komplizierte Ideen in überschaubare Schritte zerlegt werden. Am Ende dieses Tutorials sollten Sie wissen, wie nutzerdefinierte Indikatoren in MQL5 funktionieren, denn ich werde die Dinge einfach und nützlich halten.
1. Nutzerdefinierte Indikatoren
1.1. Was sind nutzerdefinierte Indikatoren?
Nutzerdefinierte Indikatoren sind solche, die in MQL5 standardmäßig nicht verfügbar sind. Im Gegensatz zu den in MetaTrader 5 integrierten Indikatoren wie dem gleitenden Durchschnitt (MA), dem Relative-Stärke-Index (RSI) oder dem MACD können Nutzer ihre eigenen Indikatoren erstellen, um bestimmte Berechnungen durchzuführen, Signale zu liefern oder Marktdaten nach eigenem Ermessen darzustellen.
Es ist einfach, integrierte Indikatoren in Handelsstrategien einzubinden, da sie über Funktionen wie iMA(), iRSI() und iMACD() direkt zugänglich sind. Aber wenn es um Anpassungen geht, sind sie begrenzt. Andererseits bieten nutzerdefinierte Indikatoren die vollständige Kontrolle über die Berechnungen, die Logik und die Chartdarstellung, sodass Sie Tools erstellen können, die auf Ihre speziellen Handelsanforderungen zugeschnitten sind. Für Händler, die Marktanalysen mit Methoden durchführen möchten, die nicht von den integrierten Indikatoren unterstützt werden, sind diese Indikatoren besonders hilfreich. Mit der MQL5-Programmierung können Sie einzigartige Indikatoren entwerfen, die ein genaueres Verständnis von Preisbewegungen, Trends und möglichen Handelsmöglichkeiten bieten.
Analogie
Überlegen Sie, ob Sie ein Bücherregal in Ihrem Wohnraum aufstellen wollen. Integrierte Indikatoren sind vergleichbar mit vormontierten Bücherregalen. Diese Bücherregale haben vorgegebene Größen, Formen und Eigenschaften und sind in Standardausführungen erhältlich. Für die meisten Menschen sind sie einfach zu nutzen, bequem und effektiv. Allerdings könnte das vormontierte Bücherregal nicht genau passen oder Ihren Ansprüchen genügen, wenn Ihr Raum eine ungerade Form hat oder wenn Sie spezielle Regale für seltene Bände benötigen.
Andererseits sind nutzerdefinierte Indikatoren wie ein Bücherregal, das Sie selbst gestalten. Die genauen Maße, die Anzahl der Fächer und die Materialien können so gewählt werden, dass das Bücherregal zu Ihrem Raum passt und Ihre Bücher so angeordnet werden, wie Sie es wünschen. Auch beim Handel bieten Ihnen nutzerdefinierte Indikatoren die Präzision und Flexibilität, die integrierte Indikatoren nicht bieten können, und ermöglichen es Ihnen, Lösungen zu entwickeln, die zu Ihrer individuellen Strategie passen.
1.2. Unterschiede zwischen Expert Advisors und Indikatoren
Obwohl Indikatoren und Expert Advisors Marktdaten in ähnlicher Weise auswerten, sind ihre Funktionen recht unterschiedlich. Da EAs den Handel automatisieren sollen, analysieren sie nicht nur den Markt, sondern führen auch Handelsgeschäfte nach vorgegebenen Regeln durch. Sie sind in der Lage, das Risiko zu steuern, den Stop-Loss zu modifizieren, Take-Profit-Levels zu bestimmen und Aufträge zu eröffnen und zu schließen. Jedes Mal, wenn es eine neue Preisaktualisierung gibt, wird OnTick(), eine der wichtigsten Funktionen in einem EA, aufgerufen. Mit Hilfe dieser Funktion kann der EA die Kursbewegungen in Echtzeit verfolgen und prüfen, ob die Handelskriterien erfüllt sind, bevor er einen Auftrag erteilt.
//+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { // }
Im Gegensatz dazu sind Indikatoren nicht in der Lage, Handelsgeschäfte zu tätigen, sondern konzentrieren sich auf die Marktanalyse. Indikatoren verwenden anstelle von OnTick() die Methode OnCalculate(), die historische und aktuelle Daten analysiert, um Handelsindikationen zu erstellen. Die Berechnung von Indikatorwerten, die Aktualisierung von Chartslementen und die Darstellung von visuellen Signalen wie Trendlinien oder farbcodierten Kerzen werden alle von OnCalculate() verarbeitet.
Indikatoren bieten lediglich aufschlussreiche Informationen; die endgültige Entscheidung bleibt dem Händler überlassen, im Gegensatz zu EAs, die zum Handeln gemacht sind. Obwohl sie beide Marktdaten untersuchen, dienen Indikatoren und EAs unterschiedlichen Zwecken. Während Indikatoren den Händlern helfen, den Markt manuell zu interpretieren und fundierte Handelsentscheidungen zu treffen, handeln EAs bei Handelsgelegenheiten.
//+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]) { // }
Analogie
Betrachte Indikatoren und Expert Advisors als zwei unterschiedliche Handelsinstrumente. Ein EA analysiert den Markt, trifft Entscheidungen und führt den Handel selbstständig aus, ähnlich wie ein selbstfahrendes Auto. Ohne menschliches Zutun wendet es Handelstechniken an, überwacht kontinuierlich Marktschwankungen und kontrolliert das Risiko.
Ein Indikator hingegen funktioniert eher wie ein GPS, da er zwar die Richtung angibt, aber nichts bewirkt. Er analysiert Marktdaten, identifiziert Muster und hilft Händlern, Preisänderungen zu verstehen. Ein gleitender Durchschnitt kann beispielsweise anzeigen, ob der Markt aufwärts oder abwärts tendiert, aber er kann keine Handelsgeschäfte einleiten oder beenden. Ein Indikator bietet nur Informationen; die endgültige Entscheidung liegt bei Ihnen, aber ein EA handelt für Sie.
2. Das Projekt einrichten
Nachdem wir nun wissen, was nutzerdefinierte Indikatoren sind und wie sie sich von Expert Advisors und eingebauten Indikatoren unterscheiden, wollen wir uns ansehen, wie wir unsere Indikatoren in MQL5 erstellen und ändern können. In diesem Abschnitt werden wir das Verfahren im Detail erläutern, um sicherzustellen, dass Sie von Anfang an eine gute Vorstellung davon haben, wie ein Indikator zu erstellen ist. In diesem Tutorial werden wir zwei einzigartige Indikatoren von Grund auf neu konstruieren, ohne bereits existierende Indikatorroutinen wie z.B. MA.
2.1. MA als Linie
Der erste Indikator ist ein einfacher gleitender Durchschnitt (Moving Average, MA), der drei verschiedene gleitende Durchschnitte berechnet und anzeigt:
- Die Periodenlänge 200 wird auf den Höchstpreis angewandt.
- Die Periodenlänge 100 wird auf den Schlusskurs angewandt.
- Die Periodenlänge 50 wird auf den Eröffnungspreis angewandt.
Um einen nutzerdefinierten Indikator zu erstellen, ist es wichtig, zunächst die Logik hinter seiner Funktionalität zu verstehen. Bevor wir einen Code schreiben, müssen wir festlegen, wie der Indikator die Marktdaten verarbeiten und die relevanten Informationen anzeigen soll. Dieser Schritt stellt sicher, dass unser Ansatz gut strukturiert und einfach zu implementieren ist. Der Entwurf eines Pseudocodes ist ein wesentlicher Schritt neben dem Verständnis seiner Logik. Die Erstellung eines Pseudocodes erleichtert die Aufteilung der Implementierung in überschaubare, kleinere Teile. Sie verringert die Möglichkeit von Fehlern und erhöht die Effizienz des Kodierungsprozesses, indem sie klar umreißt, was getan werden muss.
In diesem Abschnitt wird zunächst die Logik untersucht, die zur Ermittlung und Darstellung von drei gleitenden Durchschnitten unter Verwendung verschiedener Preisquellen erforderlich ist. Bevor wir den eigentlichen Code schreiben, werden wir zunächst einen Pseudocode entwerfen, der als Leitfaden für unsere Implementierung dient. Dieser strukturierte Ansatz wird uns dabei helfen, einen gut definierten nutzerdefinierten Indikator zu erstellen und gleichzeitig die wichtigsten Programmierkonzepte in MQL5 zu stärken.
Pseudocode:
// EINRICHTEN DES INDIKATORS
1. Lege den Indikator fest, der im Chartfenster angezeigt werden soll.
2. Definiere 3 Puffer zum Speichern der Daten für die gleitenden Durchschnitte (MA200, MA100, MA50).
3. Definiere 3 Darstellungen, um die gleitenden Durchschnitte im Chart anzuzeigen.
// EINRICHTEN DER DARSTELLUNGSEIGENSCHAFTEN
4. Für MA200:
- Kennzeichnung: „MA 200“
- Type: Linie
- Stil: Strich-Punkt-Punkt
- Breite: 1
- Farbe: Blau
5. Für MA100:
- Kennzeichnung: „MA 100“
- Type: Linie
- Stil: Gedankenstrich
- Breite: 1
- Farbe: Braun
6. Für MA50:
- Kennzeichnung: „MA 50“
- Type: Linie
- Stil: Punkt
- Breite: 1
- Farbe: Lila
// PUFFER DEFINIEREN
7. Erstelle folgende Puffer, um die berechneten Werte zu speichern:
- MA200
- MA100
- MA50
// EINGABEPARAMETER DEFINIEREN
8. Erlaube dem Nutzer, den Zeitraum für jeden gleitenden Durchschnitt festzulegen:
- MA200: Standardperiodenlänge = 200
- MA100: Standardperiodenlänge = 100
- MA50: Standardperiodenlänge = 50
// INITIALISIERUNGSFUNKTION
9. Wenn der Indikator initialisiert wird:
- Ordne jeden Puffer die entsprechende Darstellung zu.
- Lege die Anzahl der Anfangsbalken fest, die für jeden gleitenden Durchschnitt übersprungen werden sollen:
- MA200: Überspringe die ersten 200 Balken
- MA100: Überspringe die ersten 100 Balken
- MA50: Überspringe die ersten 50 Balken
// BERECHNUNGSFUNKTION
10. Für jede neue Kerze oder wenn das Chart aktualisiert wird:
Addiere von jedem Balken jeweils die vorangegangenen 200, 100 und 50 Höchst-, Schluss- und Eröffnungskurse, teile sie durch die jeweilige Anzahl und speichere die Ergebnisse in den entsprechenden Puffern, um den MA200, MA100 und MA50 zu ermitteln.
2.2. Der MA als Kerze
Als Nächstes werden wir einen anderen gleitenden Durchschnittsindikator erstellen, der Preistrends im Kerzenformat darstellt. Dieser Indikator verwendet einen gleitenden Durchschnitt mit einer Periodenlänge von 5 und stellt seine Werte mit Hilfe von Kerzen anstelle von Linien visuell dar. Durch die Darstellung von gleitenden Durchschnittsdaten auf diese Weise können wir kurzfristige Trends hervorheben und Marktstörungen besser herausfiltern. Dies bietet eine einzigartige Perspektive auf die Preisbewegung, wobei die Grundsätze der Berechnung des gleitenden Durchschnitts beibehalten werden.
Jedes Projekt wird gründlich erklärt, wobei sichergestellt wird, dass jede Zeile des Codes auch für Anfänger verständlich ist. Am Ende dieses Teils werden Sie praktische Erfahrungen mit dem Aufbau und der Modifizierung von Indikatoren von Grund auf gesammelt haben, was Ihnen nützliche Fähigkeiten für weitere Projekte verleiht.
Pseudocode:
// EINRICHTEN DES INDIKATORS
1. Stelle den Indikator so ein, dass er in einem separaten Fenster angezeigt wird.
2. Erstelle 5 Arrays (Puffer) zum Speichern:
- Eröffnungspreis (OpenBuffer)
- Hochs (HighBuffer)
- Tiefs (LowBuffer)
- Schlusskurs (CloseBuffer)
- Kerzenfarben (ColorBuffer: 0 = grün, 1 = rot)
3. Definiere 1 Darstellung zur Anzeige der Kerzen.
// EINRICHTEN DER DARSTELLUNGSEIGENSCHAFTEN
4. Für die Darstellung:
- Kennzeichnung: „Kerzen“
- Typ: Farbkerzen (DRAW_COLOR_CANDLES)
- Farben: Grün für steigend, Rot für fallend
- Stil: Solide
- Breite: 1
// EINGABEPARAMETER DEFINIEREN
5. Erlaube dem Nutzer, die Glättungsperiode einzustellen (Standard = 5).
// INITIALISIERUNGSFUNKTION
6. Wenn der Indikator initialisiert wird:
- Ordne jeden Puffer dem entsprechenden Daten- oder Farbindex zu.
- Lege die Anzahl der anfänglichen Balken fest, die übersprungen werden sollen (gleich der Glättungsperiode).
// BERECHNUNGSFUNKTION
7. Für jede neue Kerze oder wenn das Chart aktualisiert wird:
- Prüfe, ob genügend Balken für die Berechnung vorhanden sind (mindestens „period“- Balken).
- Ist dies nicht der Fall, wird eine Fehlermeldung ausgegeben und der Vorgang abgebrochen.
8. Für jeden Balken der „period-1“-Balken bis zum letzten Balken:
Berechne die geglätteten Eröffnungs-, Höchst-, Tiefst- und Schlusskurse:
- Summiere die Eröffnungs-, Höchst-, Tiefst- und Schlusskurse bis zum letzten „period“-Balken.
- Teile jede Summe durch „period“, um den Durchschnitt zu erhalten.
- Speicher die Ergebnisse in OpenBuffer, HighBuffer, LowBuffer und CloseBuffer.
Stelle die Kerzenfarbe ein:
- Wenn der geglättete Schlusskurs >= geglätteter Eröffnungskurs ist, wird die Farbe auf 0 (grün) gesetzt.
- Andernfalls setze die Farbe auf 1 (rot).
3. Nutzerdefinierte Indikatoren erstellen und anpassen
Wir können nun unsere nutzerdefinierten Indikatoren erstellen und ändern, da wir einen Pseudocode geschrieben haben. Mit einer gut definierten Strategie werden wir die Logik schrittweise in die Praxis umsetzen und sicherstellen, dass der Indikator wie vorgesehen funktioniert. Wir können die Marktbewegungen effizient visualisieren und den Indikator an unsere Bedürfnisse anpassen, indem wir unseren Code richtig organisieren.
3.1. Erstellen eines gleitenden Durchschnittsindikators im Linienformat
Der erste Schritt bei der Erstellung einer Anzeige besteht darin, sich vorzustellen, wie sie aussehen und funktionieren soll. Es ist wichtig, dass Sie sich einige entscheidende Fragen stellen, um das Design und die Implementierung zu verstehen, bevor Sie einen Code erstellen:
- Soll der Indikator im Hauptchartfenster oder in einem separaten Fenster angezeigt werden?
- Wie viele Puffer benötigt der Indikator zum Speichern und Anzeigen von Daten?
- Welche Art der Darstellung sollte verwendet werden - Linie, Histogramm, Kerzen oder etwas anderes?
- Welche Farben sollten den verschiedenen Elementen zur besseren Sichtbarkeit zugewiesen werden?
- Wird der Indikator mehrere Datenquellen verwenden, z. B. Höchst-, Tiefst-, Eröffnungs- oder Schlusskurse?
Durch die Beantwortung dieser Fragen können Sie einen klaren Plan für Ihren Indikator erstellen, wodurch der Entwicklungsprozess reibungsloser und strukturierter wird.
Beispiel:
//INDICATOR IN CHART WINDOW #property indicator_chart_window //SET INDICATOR BUFFER TO STORE DATA #property indicator_buffers 3 //SET NUMBER FOR INDICATOR PLOTS #property indicator_plots 3
Erläuterung:
Indikator im Chart-Fenster#property indicator_chart_window
Anstatt den nutzerdefinierten Indikator in einem separaten Fenster anzuzeigen, weist diese Direktive MetaTrader 5 an, ihn sofort im Hauptchart anzuzeigen, in dem die Kursbewegung dargestellt wird. Um den Indikator in einem anderen Fenster darzustellen (z. B. RSI oder MACD), verwenden Sie den Befehl:
#property indicator_separate_window
Diese Direktive stellt sicher, dass der Indikator in einem separaten Fenster unterhalb des Hauptcharts angezeigt wird und nicht direkt auf dem Preischart erscheint.
Einstellen von Indikatorpuffern zum Speichern von Daten
#property indicator_buffers 3
Die berechneten Werte, die auf dem Chart dargestellt werden, werden in Arrays gespeichert, die als Indikatorpuffer bezeichnet werden. Jeder Puffer stellt ein bestimmtes Element der Anzeige dar. In diesem Fall werden wir drei verschiedene Sätze von Werten speichern, da wir drei Anzeigepuffer erstellen. Es werden drei Puffer benötigt, um die Werte für jeden gleitenden Durchschnitt unabhängig voneinander zu speichern, da wir einen gleitenden Durchschnittsindikator mit drei verschiedenen Periodenlängen (50, 100 und 200) erstellen.
Einstellen der Anzahl von Indikatorplots
#property indicator_plots 3
Hier wird angegeben, wieviel der Indikator anzeigen soll. Eine eindeutige grafische Darstellung auf dem Chart wird als „plot“ (Darstellung) bezeichnet. Es sind drei Darstellungen erforderlich, da wir drei gleitende Durchschnitte zeichnen: je einen für die gleitenden Durchschnitte der 50-, 100- und 200-Perioden.
Farbe, Stil und Format (z. B. Linie, Histogramm oder Kerzen) können für jede Darstellung angepasst werden. Hier wird jede der drei Darstellungen als eine Linie dargestellt, die einen bestimmten gleitenden Durchschnitt repräsentiert.
Zusammenfassung
- Der Indikator wird im Hauptchart angezeigt (#property indicator_chart_window).
- Er speichert drei Sätze von Werten unter Verwendung von Indikatorpuffern (#property indicator_buffers 3).
- Es werden drei verschiedene gleitende Durchschnitte dargestellt (#property indicator_plots 3).
Diese Einstellung stellt sicher, dass der Indikator die drei gleitenden Durchschnitte korrekt berechnet und auf dem Preischart anzeigt.
Nach der Definition der grundlegenden Merkmale unseres Indikators folgt die Festlegung der Darstellungseigenschaften. Um festzulegen, wie der Indikator auf dem Chart erscheinen soll, ist es wichtig, bei der Konstruktion eines nutzerdefinierten Indikators in MQL5 Darstellungs-Attribute anzugeben. Die Art der Zeichnung, der Linienstil, die Dicke, die Farbe und die Beschriftung werden durch diese Parameter bestimmt. Das Verständnis dieser Parameter hilft Ihnen bei der Erstellung und Änderung von Indikatoren für verschiedene Anwendungsfälle, da dieser Artikel sich darauf konzentriert, die Entwicklung nutzerdefinierter Indikatoren anhand eines projektbasierten Ansatzes zu vermitteln.
Beispiele:
//INDICATOR IN CHART WINDOW #property indicator_chart_window //SET INDICATOR BUFFER TO STORE DATA #property indicator_buffers 3 //SET NUMBER FOR INDICATOR PLOTS #property indicator_plots 3 //SETTING PLOTS PROPERTIES //PROPERTIES OF THE FIRST MA (MA200) #property indicator_label1 "MA 200" //GIVE PLOT ONE A NAME #property indicator_type1 DRAW_LINE //TYPE OF PLOT THE FIRST MA #property indicator_style1 STYLE_DASHDOTDOT //STYLE OF SPOT THE FIRST MA #property indicator_width1 1 //LINE THICKNESS THE FIRST MA #property indicator_color1 clrBlue //LINE COLOR THE FIRST MA //PROPERTIES OF THE SECOND MA (MA100) #property indicator_label2 "MA 100" //GIVE PLOT TWO A NAME #property indicator_type2 DRAW_LINE //TYPE OF PLOT THE SECOND MA #property indicator_style2 STYLE_DASH //STYLE OF SPOT THE SECOND MA #property indicator_width2 1 //LINE THICKNESS THE SECOND MA #property indicator_color2 clrBrown //LINE COLOR THE SECOND MA //PROPERTIES OF THE THIRD MA (MA50) #property indicator_label3 "MA 50" //GIVE PLOT TWO A NAME #property indicator_type3 DRAW_LINE //TYPE OF PLOT THE THIRD MA #property indicator_style3 STYLE_DOT //STYLE OF SPOT THE THIRD MA #property indicator_width3 1 //LINE THICKNESS THE THIRD MA #property indicator_color3 clrPurple //LINE COLOR THE THIRD MA
Erläuterung:
Erster gleitender Durchschnitt (MA 200)
#property indicator_label1 "MA 200" //GIVE PLOT ONE A NAME #property indicator_type1 DRAW_LINE //TYPE OF PLOT THE FIRST MA #property indicator_style1 STYLE_DASHDOTDOT //STYLE OF SPOT THE FIRST MA #property indicator_width1 1 //LINE THICKNESS THE FIRST MA #property indicator_color1 clrBlue //LINE COLOR THE FIRST MA
Der erste gleitende Durchschnitt (MA200) erscheint als blau gestrichelte Punktlinie mit einer Dicke von 1.
Zweiter gleitender Durchschnitt (MA 100)
#property indicator_label2 "MA 100" //GIVE PLOT TWO A NAME #property indicator_type2 DRAW_LINE //TYPE OF PLOT THE SECOND MA #property indicator_style2 STYLE_DASH //STYLE OF SPOT THE SECOND MA #property indicator_width2 1 //LINE THICKNESS THE SECOND MA #property indicator_color2 clrBrown //LINE COLOR THE SECOND MA
Der zweite gleitende Durchschnitt (MA100) wird als braun gestrichelte Linie mit einer Dicke von 1 angezeigt.
Dritter gleitender Durchschnitt (MA 50)
#property indicator_label3 "MA 50" //GIVE PLOT TWO A NAME #property indicator_type3 DRAW_LINE //TYPE OF PLOT THE THIRD MA #property indicator_style3 STYLE_DOT //STYLE OF SPOT THE THIRD MA #property indicator_width3 1 //LINE THICKNESS THE THIRD MA #property indicator_color3 clrPurple //LINE COLOR THE THIRD MA
Der dritte gleitende Durchschnitt (MA50) wird als lila gepunktete Linie mit einer Dicke von 1 angezeigt.
Verstehen der Beziehung zwischen des Darstellungseigenschaften in MQL5
Jedes Chart (Linie, Histogramm, Pfeil usw.) benötigt eine Reihe von Merkmalen, um zu bestimmen, wie ein Indikator in einem Chart angezeigt werden soll. Nummerierte Suffixe wie indicator_label1, indicator_type1, indicator_style1 usw. werden in MQL5 zur Zuweisung der Eigenschaften verwendet.
Durch diese Nummerierung ist gewährleistet, dass alle Darstellungen einer bestimmten Nummerierung zusammengehören. Lassen Sie uns das erkunden:
- indicator_label1 weist der ersten Darstellung einen Namen zu, damit sie leichter zu identifizieren ist.
- indicator_type1 gibt an, wie diese erste Darstellung gezeichnet werden soll (z. B. als Linie).
- indicator_style1 bestimmt den Linienstil für diese erste Darstellung (durchgezogen, gestrichelt, gepunktet usw.).
- indicator_width1 legt die Dicke der ersten Darstellung fest.
- indicator_color1 legt die Farbe für diese erste Darstellung fest.
Beispiel zur Verdeutlichung der Beziehung
Betrachten Sie diese Eigenschaften als einen passenden Satz für jeden gleitenden Durchschnitt:
Eigenschaft | Was es steuert | Erster MA (200) | Zweiter MA (100) | Dritter MA (50) |
---|---|---|---|---|
indicator_labelX | Name des MA | „MA 200“ | „MA 100“ | „MA 50“ |
indicator_typeX | Typ | DRAW_LINE | DRAW_LINE | DRAW_LINE |
indicator_styleX | Linienstil | STYLE_DASHDOTDOT | STYLE_DASH | STYLE_DOT |
indicator_widthX | Dicke | 1 | 1 | 1 |
indicator_colorX | Farbe | clrBlue | clrBrown | clrPurple |
Dieser Ansatz garantiert, dass jede Eigenschaft mit dem entsprechenden gleitenden Durchschnitt übereinstimmt, und ermöglicht es uns, viele Darstellungen auf organisierte Weise zu spezifizieren. Daher wirkt sich eine Änderung von indicator_style2 nur auf den zweiten MA aus. Nur die Farbe des dritten MA wird sich ändern, wenn indicator_color3 geändert wird. Wir können das Erscheinungsbild der einzelnen gleitenden Durchschnitte im Chart verwalten, ohne Verwirrung zu stiften, indem wir die Konsistenz und Organisation dieser Merkmale beibehalten.
Zusätzlich zu den vielen Diagrammtypen, Linienstilen und Farben, die wir in unserem gleitenden Durchschnittsindikator verwendet haben, bietet MQL5 eine Reihe anderer Anpassungsmöglichkeiten für Indikatordiagramme. Entwickler können mit diesen Parametern verschiedene Anzeigetypen entwerfen, von einfachen Linien bis hin zu komplizierteren Visualisierungen wie Bändern, Pfeilen und Histogrammen. Wir verwenden einen projektbasierten Ansatz, der sich auf einen einzigen Indikator konzentriert und gleichzeitig wesentliche Ideen vorstellt, die auf andere maßgeschneiderte Indikatoren angewendet werden können, da es zu viele Variablen gibt, um sie in einem einzigen Artikel zu behandeln. Es ist jedoch hilfreich zu wissen, dass es noch weitere Wahlmöglichkeiten gibt.
Generell lassen sich die verschiedenen Handlungsweisen mit der gleichen Logik analysieren, die in diesem Artikel verwendet wird. Dies gilt jedoch nicht für alle Darstellungsarten. Während zum Beispiel DRAW_LINE nur einen Puffer pro Darstellung benötigt, benötigt DRAW_CANDLES vier Puffer, um eine einzige Kerze zu zeichnen. In der MQL5-Dokumentation finden Sie eine umfassende Beschreibung der vielen verfügbaren Darstellungsarten und ihrer besonderen Anforderungen.
Die Deklaration von Doppelvariablen zur Aufnahme der Indikatorpuffer erfolgt nach der Konfiguration der Darstellungsattribute. Da sie die berechneten Werte speichern, die im Chart angezeigt werden, sind diese Puffer von entscheidender Bedeutung. Die Funktion SetIndexBuffer() muss verwendet werden, um die Variablen mit den Anzeigepuffern zu verknüpfen, nachdem sie deklariert worden sind. Dieser Schritt gewährleistet, dass die in diesen Puffern gespeicherten Daten korrekt dargestellt und den entsprechenden Darstellungen zugeordnet werden können.
Beispiel:
//INDICATOR IN CHART WINDOW #property indicator_chart_window //SET INDICATOR BUFFER TO STORE DATA #property indicator_buffers 3 //SET NUMBER FOR INDICATOR PLOTS #property indicator_plots 3 //SETTING PLOTS PROPERTIES //PROPERTIES OF THE FIRST MA (MA200) #property indicator_label1 "MA 200" //GIVE PLOT ONE A NAME #property indicator_type1 DRAW_LINE //TYPE OF PLOT THE FIRST MA #property indicator_style1 STYLE_DASHDOTDOT //STYLE OF SPOT THE FIRST MA #property indicator_width1 1 //LINE THICKNESS THE FIRST MA #property indicator_color1 clrBlue //LINE COLOR THE FIRST MA //PROPERTIES OF THE SECOND MA (MA100) #property indicator_label2 "MA 100" //GIVE PLOT TWO A NAME #property indicator_type2 DRAW_LINE //TYPE OF PLOT THE SECOND MA #property indicator_style2 STYLE_DASH //STYLE OF SPOT THE SECOND MA #property indicator_width2 1 //LINE THICKNESS THE SECOND MA #property indicator_color2 clrBrown //LINE COLOR THE SECOND MA //PROPERTIES OF THE THIRD MA (MA50) #property indicator_label3 "MA 50" //GIVE PLOT TWO A NAME #property indicator_type3 DRAW_LINE //TYPE OF PLOT THE THIRD MA #property indicator_style3 STYLE_DOT //STYLE OF SPOT THE THIRD MA #property indicator_width3 1 //LINE THICKNESS THE THIRD MA #property indicator_color3 clrPurple //LINE COLOR THE THIRD MA //SET MA BUFFER TO STORE DATA double buffer_mA200[]; //BUFFER FOR THE FIRST MA double buffer_mA100[]; //BUFFER FOR THE SECOND MA double buffer_mA50[]; //BUFFER FOR THE THIRD MA //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //SETTING BUFFER SetIndexBuffer(0, buffer_mA200, INDICATOR_DATA); //INDEX 0 FOR MA200 SetIndexBuffer(1, buffer_mA100, INDICATOR_DATA); //INDEX 1 FOR MA100 SetIndexBuffer(2, buffer_mA50, INDICATOR_DATA); //INDEX 1 FOR MA50 //--- return(INIT_SUCCEEDED); }
Erläuterung:
//SET MA BUFFER TO STORE DATA double buffer_mA200[]; //BUFFER FOR THE FIRST MA double buffer_mA100[]; //BUFFER FOR THE SECOND MA double buffer_mA50[]; //BUFFER FOR THE THIRD MA
Diese Arrays (buffer_mA200, buffer_mA100, buffer_mA50) dienen als Speicher für die berechneten Werte der einzelnen gleitenden Durchschnitte (MA).
Jeder Puffer entspricht einer bestimmten MV:
- buffer_mA200 → Speichert Werte für MA 200
- buffer_mA100 → Speichert Werte für MA 100
- buffer_mA50 → Speichert Werte für MA 50
Wenn der Indikator angezeigt wird, werden die in diesen Puffern gespeicherten Werte auf dem Chart dargestellt. Um die berechneten Werte eines Indikators in MQL5 zu speichern, werden Indikatorpuffer benötigt. Ohne Puffer wäre es unmöglich, die Ergebnisse zu speichern und darzustellen.
//SETTING BUFFER SetIndexBuffer(0, buffer_mA200, INDICATOR_DATA); //INDEX 0 FOR MA200 SetIndexBuffer(1, buffer_mA100, INDICATOR_DATA); //INDEX 1 FOR MA100 SetIndexBuffer(2, buffer_mA50, INDICATOR_DATA); //INDEX 2 FOR MA50
SetIndexBuffer() wird verwendet, um jeden Puffer mit dem Plottsystem des Indikators zu verbinden.
Sie benötigt drei Parameter:
- Den Pufferindex → Legt die Reihenfolge fest, in der die Puffer verwendet werden (beginnend bei 0).
- Die Puffervariable → Der Puffer, in dem die Werte für diesen Index gespeichert werden.
- Den Puffertyp → INDICATOR_DATA gibt an, dass der Puffer Indikatorwerte enthält.
Aufschlüsselung der einzelnen Linien:
- SetIndexBuffer(0, buffer_mA200, INDICATOR_DATA); → Weist buffer_mA200 den Index 0 (erster MA) zu.
- SetIndexBuffer(1, buffer_mA100, INDICATOR_DATA); → Weist buffer_mA100 den Index 1 (zweiter MA) zu.
- SetIndexBuffer(2, buffer_mA50, INDICATOR_DATA); → Weist buffer_mA50 den Index 2 (dritter MA) zu.
Dies garantiert, dass das MQL5-Indikatorensystem jeden Puffer korrekt erkennt und darstellt. Ohne diesen Schritt würde der Indikator nicht richtig funktionieren.
Ein gründliches Verständnis der einem Indikator zugrundeliegenden Mathematik oder Argumentation ist für seine Erstellung entscheidend. Nur wenn ein Indikator Preisänderungen auf einer soliden mathematischen oder logischen Grundlage genau bewertet, kann er als nützlich angesehen werden. Sie müssen verstehen, wie ein Indikator funktioniert und welche Eingaben erforderlich sind, um ihn effizient zu berechnen, bevor Sie ihn in MQL5 in die Praxis umsetzen können.
Nehmen wir zum Beispiel den gleitenden Durchschnitt:
Durch die Verringerung der Kursschwankungen erleichtert der gleitende Durchschnitt das Erkennen von Marktmustern, ohne von vorübergehenden Veränderungen beeinflusst zu werden.
Um einen gleitenden Durchschnitt zu berechnen, müssen wir Folgendes berücksichtigen:
Periodenlänge
Die Anzahl der historischen Kerzen, die zur Berechnung des gleitenden Durchschnitts verwendet werden, hängt vom Zeitrahmen ab. Zum Beispiel werden die letzten 200 Kerzen durch einen 200-MA gemittelt. Während der MA bei einem kürzeren Zeitraum stärker auf die jüngsten Bewegungen reagiert, ergibt ein längerer Zeitraum eine glattere Linie, die langsamer auf Preisänderungen reagiert.
Preistyp
MA kann mit verschiedenen Preistypen berechnet werden, wie z.B.:
- Close Price → Verwendet den Schlusskurs jeder Kerzen.
- Open Price → Verwendet den Eröffnungspreis jeder Kerze.
- High Price → Verwendet das Hoch jeder Kerze.
- Low Price → Verwendet das Tief jeder Kerzen.
In diesem Projekt werden wir mit drei verschiedenen gleitenden Durchschnitten arbeiten:
- MA 200 (angewendet auf „High Price“)
- MA 100 (angewendet auf „Close Price“)
- MA 50 (angewendet auf „Open Price“)
Das Verständnis dieser Kernkonzepte stellt sicher, dass wir den Gleitenden Durchschnitt korrekt berechnen und visualisieren können, ohne uns auf eingebaute MQL5-Funktionen wie iMA() zu verlassen.
Beispiel:
//INDICATOR IN CHART WINDOW #property indicator_chart_window //SET INDICATOR BUFFER TO STORE DATA #property indicator_buffers 3 //SET NUMBER FOR INDICATOR PLOTS #property indicator_plots 3 //SETTING PLOTS PROPERTIES //PROPERTIES OF THE FIRST MA (MA200) #property indicator_label1 "MA 200" //GIVE PLOT ONE A NAME #property indicator_type1 DRAW_LINE //TYPE OF PLOT THE FIRST MA #property indicator_style1 STYLE_DASHDOTDOT //STYLE OF SPOT THE FIRST MA #property indicator_width1 1 //LINE THICKNESS THE FIRST MA #property indicator_color1 clrBlue //LINE COLOR THE FIRST MA //PROPERTIES OF THE SECOND MA (MA100) #property indicator_label2 "MA 100" //GIVE PLOT TWO A NAME #property indicator_type2 DRAW_LINE //TYPE OF PLOT THE SECOND MA #property indicator_style2 STYLE_DASH //STYLE OF SPOT THE SECOND MA #property indicator_width2 1 //LINE THICKNESS THE SECOND MA #property indicator_color2 clrBrown //LINE COLOR THE SECOND MA //PROPERTIES OF THE THIRD MA (MA50) #property indicator_label3 "MA 50" //GIVE PLOT TWO A NAME #property indicator_type3 DRAW_LINE //TYPE OF PLOT THE THIRD MA #property indicator_style3 STYLE_DOT //STYLE OF SPOT THE THIRD MA #property indicator_width3 1 //LINE THICKNESS THE THIRD MA #property indicator_color3 clrPurple //LINE COLOR THE THIRD MA //SET MA BUFFER TO STORE DATA double buffer_mA200[]; //BUFFER FOR THE FIRST MA double buffer_mA100[]; //BUFFER FOR THE SECOND MA double buffer_mA50[]; //BUFFER FOR THE THIRD MA //SET MA PERIOD input int period_ma200 = 200; //PERIOD FOR THE FIRST MA input int period_ma100 = 100; //PERIOD FOR THE SECOND MA input int period_ma50 = 50; //PERIOD FOR THE THIRD MA //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //SETTING BUFFER SetIndexBuffer(0, buffer_mA200, INDICATOR_DATA); //INDEX 0 FOR MA200 SetIndexBuffer(1, buffer_mA100, INDICATOR_DATA); //INDEX 1 FOR MA100 SetIndexBuffer(2, buffer_mA50, INDICATOR_DATA); //INDEX 1 FOR MA50 //SETTING BARS TO START PLOTTING PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, period_ma200); PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, period_ma100); PlotIndexSetInteger(2, PLOT_DRAW_BEGIN, period_ma50); //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]) { //CALCULATE THE MOVING AVERAGE FOR THE THE First MA (MA200) for(int i = period_ma200 - 1; i < rates_total; i++) { double sum = 0.0; for(int j = 0; j < period_ma200; j++) { sum += high[i - j]; } buffer_mA200[i] = sum / period_ma200; } //CALCULATE THE MOVING AVERAGE FOR THE THE SECOND MA (MA100) for(int i = period_ma100 - 1; i < rates_total; i++) { double sum = 0.0; for(int j = 0; j < period_ma100; j++) { sum += close[i - j]; } buffer_mA100[i] = sum / period_ma100; } //CALCULATE THE MOVING AVERAGE FOR THE THE THIRD MA (MA50) for(int i = period_ma50 - 1; i < rates_total; i++) { double sum = 0.0; for(int j = 0; j < period_ma50; j++) { sum += open[i - j]; } buffer_mA50[i] = sum / period_ma50; } //--- return value of prev_calculated for next call return(rates_total); }
Erläuterung:
//SET MA PERIOD input int period_ma200 = 200; //PERIOD FOR THE FIRST MA input int period_ma100 = 100; //PERIOD FOR THE SECOND MA input int period_ma50 = 50; //PERIOD FOR THE THIRD MA
- Diese Eingangsvariablen definieren die Periode jedes gleitenden Durchschnitts (MA).
- Die Periode bestimmt, wie viele vergangene Kerzen der MA für seine Berechnung verwendet.
- period_ma200 = 200 bedeutet, dass der MA200 die letzten 200 Kerzen zur Berechnung des Durchschnittspreises verwendet.
- period_ma100 = 100 bedeutet, dass der MA100 die letzten 100 Kerzen zur Berechnung des Durchschnitts verwendet.
- period_ma50 = 50 bedeutet, dass der MA50 die letzten 50 Kerzen zur Berechnung des Durchschnitts verwendet.
- Da es sich um Eingabevariablen handelt, können Händler sie in den Indikatoreinstellungen ändern, ohne den Code zu verändern.
//SETTING BARS TO START PLOTTING PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, period_ma200); PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, period_ma100); PlotIndexSetInteger(2, PLOT_DRAW_BEGIN, period_ma50);
Warum ist dies notwendig?
- Da ein gleitender Durchschnitt mit der Periode 200 zur Berechnung seines Wertes 200 vorherige Kerzen benötigt, kann er nichts vor den ersten 200 Kerzen darstellen.
- PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, period_ma200); weist MetaTrader an, mit dem Zeichnen des MA200 erst zu beginnen, wenn 200 Kerzen verfügbar sind.
- PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, period_ma100); macht das gleiche für MA100 (beginnt nach 100 Kerzen).
- PlotIndexSetInteger(2, PLOT_DRAW_BEGIN, period_ma50); stellt sicher, dass MA50 nach 50 Kerzen beginnt.
//+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[])
Die zentrale Funktion jedes nutzerdefinierten Indikators, OnCalculate(), wird automatisch aufgerufen, wenn ein neuer Tick empfangen oder historische Daten aktualisiert werden. Sie ist für die Indikatorberechnungen von entscheidender Bedeutung, da sie Preisdaten verarbeitet und die Indikatorpuffer verändert. OnCalculate() wurde speziell für Indikatoren entwickelt und bietet direkten Zugriff auf historische Kursdaten, ohne dass andere Prozeduren wie CopyOpen(), CopyClose() oder ArraySetAsSeries() erforderlich sind, im Gegensatz zu OnTick(), das in Expert Advisors verwendet wird.
Unterschied zwischen OnCalculate() und OnTick()Merkmal | OnCalculate() | OnTick() |
---|---|---|
Verwendet in | Indikatoren | Expert Advisors |
Aufgerufen, wenn | neue Ticks ankommen oder das Chart aktualisiert wird | neue Ticks ankommen |
Zugriff auf Preisdaten | Verwendet integrierte Arrays (open[], close[], etc.) | Erfordert Funktionen wie CopyClose() zum Abrufen von Daten |
Zweck | Berechnet und aktualisiert Indikatorwerte | Führt Handelslogik aus, platziert Aufträge |
Parameter | Beschreibung |
---|---|
rates_total | Die Gesamtzahl der verfügbaren Kerzen (Balken) im Chart. |
prev_calculated | Die Anzahl der zuvor berechneten Balken (zur Optimierung der Leistung). |
time[] | Der Zeitstempel jeder Kerze (z. B. 2024.02.02 12:30). |
open[] | Der Eröffnungskurs jeder Kerze. |
high[] | Der höchste Preis jeder Kerze |
low[] | Der niedrigste Preis jeder Kerze. |
close[] | Der Schlusskurs der einzelnen Kerzen. |
tick_volume[] | Die Anzahl der Ticks (Kursaktualisierungen) innerhalb einer Kerze. |
volume[] | Das Gesamtvolumen, das innerhalb einer Kerze gehandelt wird. |
spread[] | Die Spanne (Differenz zwischen Geld- und Briefkurs) für jede Kerze. |
// CALCULATE THE MOVING AVERAGE FOR THE FIRST MA (MA200) for(int i = period_ma200 - 1; i < rates_total; i++) { double sum = 0.0; for(int j = 0; j < period_ma200; j++) { sum += high[i - j]; // SUM OF HIGH PRICES OVER THE PERIOD } buffer_mA200[i] = sum / period_ma200; // CALCULATE THE AVERAGE }
Eine for-Schleife, die durch die Kursdaten iteriert, wird zur Berechnung des gleitenden Durchschnitts (MA) für den ersten MA (MA200) verwendet. Wir haben genügend frühere Datenpunkte, um den Durchschnitt zu berechnen, da die Schleife bei Periode_ma200 - 1 beginnt. Es geht weiter bis rates_total, das ist die Gesamtmenge der bereitgestellten Preisdatenpunkte. Mit dieser Methode werden Fehler vermieden, die auftreten können, wenn versucht wird, auf nicht vorhandene Datenpunkte (wie negative Indexwerte) zuzugreifen. Für jeden Balken im Chart wird der gleitende Durchschnitt systematisch von der Schleife ermittelt, die dann den Indikatorpuffer entsprechend aktualisiert.
Um die kumulierte Summe der Höchstpreise über den gegebenen Zeitraum (in diesem Fall 200) zu erhalten, initialisieren wir eine Variable sum innerhalb der Schleife. Eine verschachtelte for-Schleife iteriert über die letzten 200 Balken von 0 bis period_ma200. Summe += hoch[i - j]; wird in jeder Iteration verwendet, um den Höchstpreis eines bestimmten Balkens zur Variablen Summe hinzuzufügen. Indem wir vom aktuellen Index i rückwärts gehen, garantiert die Formel i - j, dass wir die Höchstkurse der letzten 200 Balken addieren. Dieses Verfahren addiert effizient alle hohen Preise für den angegebenen Zeitraum.
Sobald wir die Summe der Höchstpreise über die 200 Balken hinweg haben, teilen wir diesen Betrag durch die Anzahl der Balken, um den Durchschnitt zu erhalten: buffer_mA200[i] = sum / period_ma200; Der berechnete MA-Wert für jeden Balken wird anschließend durch diesen Endwert dargestellt, der dann im entsprechenden Index von buffer_mA200 gespeichert wird. Da der gleitende Durchschnitt den Durchschnitt der letzten 200 Höchstkurse bildet, gleicht er Kursschwankungen aus und ermöglicht es Händlern, langfristige Muster zu erkennen. Obwohl bei den anderen gleitenden Durchschnitten andere Preistypen (Schluss- und Eröffnungskurse) und Zeiträume (100 und 50) verwendet werden, gilt für sie die gleiche Argumentation.
3.2. Erstellen eines Indikators eines gleitenden Durchschnitts im Kerzenformat
In diesem Abschnitt werden wir einen anderen Typ von gleitendem Durchschnittsindikator entwickeln, der das Kerzenformat verwendet, um Kursbewegungen anzuzeigen. Dieser Indikator verwendet einen gleitenden Durchschnitt mit einer Periodenlänge von 5 Balken und verwendet Kerzen anstelle von Linien, um seine Werte grafisch darzustellen. Durch die Darstellung von gleitenden Durchschnittsdaten können wir Marktstörungen besser herausfiltern und kurzfristige Trends hervorheben. Dadurch werden die Grundlagen der Berechnung des gleitenden Durchschnitts beibehalten, während gleichzeitig ein anderer Blickwinkel auf die Preisentwicklung geboten wird.
Der Eröffnungskurs, der Schlusskurs, der Höchstkurs und der Tiefstkurs sind die vier wesentlichen Preiskomponenten, aus denen sich eine Kerze zusammensetzt. Das Kerzenformat erfordert unabhängige Berechnungen des gleitenden Durchschnitts für diese vier Werte, im Gegensatz zum Linienformat, das nur einen Preiswert pro Periode benötigt (z. B. den Schluss- oder Eröffnungswert). Dementsprechend benötigen wir für ein einzelne Darstellung mindestens vier Puffer, einen für jeden der gleitenden Durchschnittswerte, die den Eröffnungs-, Schluss-, Höchst- und Tiefstkurs darstellen. Die Struktur dieses Indikators gewährleistet, dass die Daten des gleitenden Durchschnitts in einer Art und Weise dargestellt werden, die den tatsächlichen Kerzenmustern sehr nahe kommt, was die Analyse der Preistrends anhand bekannter visueller Hinweise erleichtert.
Beispiel:
#property indicator_separate_window #property indicator_buffers 5 #property indicator_plots 1 //---- plot ColorCandles #property indicator_label1 "Candles" #property indicator_type1 DRAW_COLOR_CANDLES #property indicator_color1 clrGreen, clrRed #property indicator_style1 STYLE_SOLID #property indicator_width1 1 //--- indicator buffers double OpenBuffer[]; double HighBuffer[]; double LowBuffer[]; double CloseBuffer[]; double ColorBuffer[]; int period = 5; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- indicator buffers mapping SetIndexBuffer(0, OpenBuffer, INDICATOR_DATA); SetIndexBuffer(1, HighBuffer, INDICATOR_DATA); SetIndexBuffer(2, LowBuffer, INDICATOR_DATA); SetIndexBuffer(3, CloseBuffer, INDICATOR_DATA); SetIndexBuffer(4, ColorBuffer, INDICATOR_COLOR_INDEX); PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, period); return INIT_SUCCEEDED; } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]) { if(rates_total < period) { Print("Error: Not enough bars to calculate."); return 0; } for(int i = period - 1; i < rates_total; i++) { if(i - period + 1 < 0) continue; double sumClose = 0.0; double sumOpen = 0.0; double sumHigh = 0.0; double sumLow = 0.0; for(int j = 0; j < period; j++) { int index = i - j; if(index < 0) continue; // Prevent out-of-bounds access sumClose += close[index]; sumOpen += open[index]; sumHigh += high[index]; sumLow += low[index]; } if(period > 0) { OpenBuffer[i] = sumOpen / period; HighBuffer[i] = sumHigh / period; LowBuffer[i] = sumLow / period; CloseBuffer[i] = sumClose / period; } else { Print("Error: Division by zero prevented."); return 0; } ColorBuffer[i] = (CloseBuffer[i] >= OpenBuffer[i]) ? 0 : 1; } return rates_total; }
Erläuterung:
#property indicator_separate_window #property indicator_buffers 5 #property indicator_plots 1 //---- plot ColorCandles #property indicator_label1 "Candles" #property indicator_type1 DRAW_COLOR_CANDLES #property indicator_color1 clrGreen, clrRed #property indicator_style1 STYLE_SOLID #property indicator_width1 1 //--- indicator buffers double OpenBuffer[]; double HighBuffer[]; double LowBuffer[]; double CloseBuffer[]; double ColorBuffer[]; int period = 5;
Die Eigenschaften und Puffer für einen nutzerdefinierten Indikator, der einen gleitenden Durchschnitt im Kerzenformat anzeigt, werden durch diesen Code definiert. Eine Kerze benötigt in der Regel vier Puffer: einen für die Preiskomponenten Open, High, Low und Close. Da jedoch ein zusätzlicher Puffer (ColorBuffer) benötigt wird, um die Farbe jeder Kerze zu identifizieren und zu speichern, benötigt dieser Indikator fünf Puffer.
Die Eigenschaften des Indikators
- #Die Eigenschaft indicator_separate_window sorgt dafür, dass der Indikator in einem separaten Fenster angezeigt wird und nicht auf dem Hauptchart erscheint.
- #property indicator_buffers 5 definiert die Anzahl der verwendeten Puffer. Obwohl eine Kerze nur vier Puffer benötigt (Open, High, Low und Close), wird ein fünfter Puffer benötigt, um jeder Kerze eine Farbe zuzuweisen.
- #Die Eigenschaft indicator_plots 1 legt fest, dass der Indikator nur einen Plot hat, der farbige Kerzen verwendet.
Visualisierungseinstellungen
- indicator_label1 „Candles“ ist der Name
- indicator_type1 DRAW_COLOR_CANDLES setzt den Darstellungstyp auf farbige Kerzen. Im Gegensatz zu DRAW_LINE benötigt dieser Typ die Werte Open, High, Low und Close sowie einen Farbindex.
- indicator_color1 clrGreen, clrRed weist den Aufwärtskerze grün und den Abwärtskerze rot zu.
- indicator_style1 STYLE_SOLID sorgt für nicht unterbrochene Kerzenränder.
- indicator_width1 1 definiert die Dicke der Kerzen.
Warum fünf Puffer anstelle von vier?
Eine typische Kerzenstruktur erfordert vier Puffer:
- OpenBuffer[]: Speichert den gleitenden Durchschnitt der Eröffnungspreise.
- HighBuffer[]: Speichert den gleitenden Durchschnitt der Höchstpreise.
- LowBuffer[]: Speichert den gleitenden Durchschnitt Tiefstpreise.
- CloseBuffer[]: Speichert den gleitenden Durchschnitt der Schlusskurse.
Da der Indikator jedoch farbige Kerzen verwendet, benötigt er auch einen fünften Puffer:
- ColorBuffer[]: Speichert den Farbindex (0 für grün, 1 für rot). Als zusätzlicher Puffer wird der gleitende Durchschnitt grafisch durch Abwärts- (rote) und Aufwärtskerzen (grün) dargestellt, was die Identifizierung von Kursmustern erleichtert.
//--- indicator buffers mapping SetIndexBuffer(0, OpenBuffer, INDICATOR_DATA); SetIndexBuffer(1, HighBuffer, INDICATOR_DATA); SetIndexBuffer(2, LowBuffer, INDICATOR_DATA); SetIndexBuffer(3, CloseBuffer, INDICATOR_DATA); SetIndexBuffer(4, ColorBuffer, INDICATOR_COLOR_INDEX); PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, period);
Um die ermittelten gleitenden Durchschnittswerte im Kerzenformat zu speichern, bildet dieser Codeabschnitt die Indikatorpuffer ab. Diese Kerzenvariante des gleitenden Durchschnitts verwendet vier Puffer (OpenBuffer, HighBuffer, LowBuffer und CloseBuffer), um das Äquivalent des gleitenden Durchschnitts von Open-, High-, Low- und Close-Kursen zu speichern, im Gegensatz zur herkömmlichen linienbasierten Version, die nur einen Puffer benötigt, um die berechneten Werte für das Plotten zu speichern.
Ein fünfter Puffer, ColorBuffer genannt, wird ebenfalls verwendet, um die Farbe jeder Kerze zu identifizieren und zwischen Abwärts- (rote) und Aufwärtskerzen (grün) zu unterscheiden. Um zu gewährleisten, dass der Indikator die Daten richtig verarbeitet und anzeigt, ordnet die Funktion SetIndexBuffer() jeden Puffer einem bestimmten Plot-Index zu. Um unvollständige oder trügerische Grafiken zu vermeiden, sorgt PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, period); dafür, dass der Indikator erst dann mit dem Zeichnen beginnt, wenn genügend Balken vorhanden sind.
if(rates_total < period) { Print("Error: Not enough bars to calculate."); return 0; } for(int i = period - 1; i < rates_total; i++) { if(i - period + 1 < 0) continue; double sumClose = 0.0; double sumOpen = 0.0; double sumHigh = 0.0; double sumLow = 0.0; for(int j = 0; j < period; j++) { int index = i - j; if(index < 0) continue; // Prevent out-of-bounds access sumClose += close[index]; sumOpen += open[index]; sumHigh += high[index]; sumLow += low[index]; } if(period > 0) { OpenBuffer[i] = sumOpen / period; HighBuffer[i] = sumHigh / period; LowBuffer[i] = sumLow / period; CloseBuffer[i] = sumClose / period; } else { Print("Error: Division by zero prevented."); return 0; } ColorBuffer[i] = (CloseBuffer[i] >= OpenBuffer[i]) ? 0 : 1; } return rates_total;
In diesem Codesegment wird zunächst festgestellt, ob genügend Kursbalken vorhanden sind, damit die Berechnung fortgesetzt werden kann. Es gibt genügend historische Datenpunkte (oder „Balken“), um den gleitenden Durchschnitt auf der Grundlage des nutzerdefinierten Zeitraums dank der Bedingung if (rates_total < period) zu berechnen. Die Funktion gibt 0 zurück und schreibt eine Fehlermeldung, wenn nicht genügend Balken vorhanden sind. Dieser Schritt ist unerlässlich, da eine aussagekräftige Berechnung des gleitenden Durchschnitts ohne ausreichende Daten nicht möglich ist und der Versuch, dies zu tun, zu ungenauen oder irreführenden Statistiken führen kann.
Die for-Schleife durchläuft die Kursdaten, beginnend mit dem Index period - 1 bis hin zu rates_total, nachdem überprüft wurde, dass genügend Balken vorhanden sind. Jeder Balken wird von der Schleife verarbeitet, die zum angegebenen Zeitpunkt beginnt und fortgesetzt wird. In dieser Schleife wird der aktuelle Balkenindex durch die Variable i dargestellt. Anhand der Preisinformationen aus den Balken der Vorperiode ermittelt diese Schleife den gleitenden Durchschnitt für jeden Balken. Die Schleife stellt sicher, dass die Berechnung erst dann beginnt, wenn die erforderliche Anzahl von Balken verfügbar ist, indem sie mit der nächsten Iteration fortfährt, wenn der Index i - period + 1 kleiner als 0 ist.
Vier Variablen werden innerhalb der Schleife auf 0,0 initialisiert: sumClose, sumOpen, sumHigh und sumLow. In diesen Variablen werden die kumulierten Summen der entsprechenden Preisdaten für den angegebenen Zeitraum gespeichert. Die Preisinformationen von jedem Balken innerhalb der Periode werden in einer zweiten for-Schleife gesammelt, die diesmal von 0 bis Periode -1 iteriert. Indem j vom aktuellen Index i abgezogen wird, ruft die innere Schleife jeden der vorhergehenden Balken ab und berechnet die Summe der Schluss-, Eröffnungs-, Höchst- und Tiefstkurse während des angegebenen Zeitraums. Die Schleife vermeidet fehlerhafte Daten, indem sie die Bedingung if(index < 0) verwendet, um den Zugriff auf nicht zulässige Einträge in den Arrays zu verhindern.
Um Probleme bei der Division durch Null zu vermeiden, bestimmt der Code, ob der Zeitraum größer als Null ist, nachdem er die Preisdaten für den Zeitraum erfasst hat. Der Code ermittelt den Durchschnitt der Eröffnungs-, Höchst-, Tiefst- und Schlusskurse über den Zeitraum und speichert das Ergebnis in den Puffern OpenBuffer, HighBuffer, LowBuffer und CloseBuffer, sofern der Zeitraum gültig ist. Die berechneten Werte für die Kerzen werden in diesen Puffern gespeichert. Schließlich wird die Farbe der Kerze durch Aktualisieren des ColorBuffer festgelegt. Die Kerze wird grün (Wert 0), wenn der Schlusskurs größer oder gleich dem Eröffnungskurs ist, was einen Aufwärtstrend anzeigt; ist der Schlusskurs kleiner oder gleich dem Eröffnungskurs, wird die Kerze rot (Wert 1), was einen Abwärtstrend anzeigt.
Der Wert von rates_total, der dem MetaTrader anzeigt, wie viele Balken erfolgreich verarbeitet wurden, wird am Ende der Funktion OnCalculate zurückgegeben. Für spätere Aufrufe der OnCalculate-Methode ist dieser Wert von entscheidender Bedeutung, da er die Anzahl der verarbeiteten Balken festhält und gewährleistet, dass Datenaktualisierungen in Echtzeit korrekt verarbeitet werden.
Durch die Arbeit mit Kerzenformaten haben wir auch die Grundlage für fortgeschrittenere Indikatoren wie Heikin-Ashi-Charts gelegt, die wir in zukünftigen Artikeln näher betrachten werden.
Schlussfolgerung
Abschließend wurden in diesem Artikel grundlegende Konzepte wie die Erstellung nutzerdefinierter Indikatoren, die Verwendung gleitender Durchschnitte und die Visualisierung von Daten in verschiedenen Formaten wie Linien- und Kerzenstilen vorgestellt. Wir haben uns auch mit der Verwendung von Puffern und der Erstellung von Diagrammen zur Darstellung von Daten beschäftigt. In künftigen Artikeln werden wir uns mit weiteren interessanten Projekten befassen. Der beste Weg, um als Anfänger zu lernen, ist ein projektbasierter Ansatz, der das Lernen in überschaubare Schritte unterteilt, anstatt Sie in diesem Stadium mit unnötigen Details zu überfordern. Diese Methode gewährleistet einen schrittweisen Fortschritt und ein vertieftes Verständnis der wichtigsten Konzepte.
Übersetzt aus dem Englischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/en/articles/17096





- 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.
Danke für die Mühe. Isreal. Ich weiß es zu schätzen.
Ich möchte in diesem Teil der Serie für den Customize-Indikator einen Kommentar abgeben.
Sie haben das prev_calculated nicht verwendet. Das bedeutet, dass Ihr Code für jeden laufenden Tick
jeden zuvor berechneten Balken erneut berechnen würde.
Sie haben das prev_calculated nicht verwendet. Das bedeutet, dass Ihr Code für jeden laufenden Tick
jeden zuvor berechneten Balken erneut berechnen würde.