English Русский 中文 Español 日本語 Português
preview
Wie man einen nutzerdefinierten Indikator (Heiken Ashi) mit MQL5 erstellt

Wie man einen nutzerdefinierten Indikator (Heiken Ashi) mit MQL5 erstellt

MetaTrader 5Handel | 14 Juni 2023, 15:57
363 3
Mohamed Abdelmaaboud
Mohamed Abdelmaaboud

Einführung

Wir alle müssen Charts lesen, und jedes Hilfsmittel, das bei dieser Aufgabe hilfreich sein kann, ist sehr willkommen. Zu den Instrumenten, die beim Lesen von Charts hilfreich sein können, gehören Indikatoren, die auf der Grundlage von Preisen, Volumen, einem anderen technischen Indikator oder einer Kombination davon berechnet werden, wobei es in der Handelswelt viele Ideen gibt. Wir haben viele vorgefertigte Indikatoren in das Handelsterminal integriert, und wenn wir einige Funktionen hinzufügen müssen, um für unseren Handelsstil geeignet zu sein, können wir auf einige Herausforderungen stoßen, weil sie möglicherweise nicht veränderbar sind, und außerdem finden wir diesen Indikator möglicherweise nicht als integrierten Indikator im Handelsterminal.

In diesem Artikel werde ich Ihnen eine Methode vorstellen, wie Sie diese Herausforderung meistern können, indem Sie die iCustom-Funktion nutzen und Ihren eigenen Indikator nach Ihren Vorgaben und Präferenzen erstellen. Wir werden auch ein Beispiel sehen, wie wir einen nutzerdefinierten Heiken Ashi technischen Indikator erstellen und diesen nutzerdefinierten Indikator in Handelssystemen verwenden werden. Wir werden dies anhand der folgenden Themen behandeln:

Nachdem Sie verstanden haben, was ich in den vorangegangenen Kapiteln erklärt habe, sollten Sie in der Lage sein, Ihren eigenen Indikator zu erstellen, der Ihnen beim Lesen von Charts hilft und den Sie in Ihrem Handelssystem verwenden können. Wir werden die MQL5 (MetaQuotes Language) verwenden, die in die Handelsplattform MetaTrader 5 integriert ist, um Codes für die zu erstellenden Indikatoren und EAs zu schreiben. Wenn Sie nicht wissen, wie man sie herunterlädt und verwendet, können Sie das Thema Schreiben von MQL5-Code in MetaEditor aus einem früheren Artikel lesen, es kann dabei hilfreich sein.

Haftungsausschluss: Alle Informationen werden in der vorliegenden Form nur zu Informationszwecken bereitgestellt und sind nicht für Handelszwecke oder als Ratschläge gedacht. Die Informationen garantieren keinen Erfolg. Wenn Sie sich dafür entscheiden, diese Materialien auf einem Ihrer Handelskonten zu verwenden, tun Sie dies auf eigenes Risiko und sind die einzige Person, die dafür verantwortlich ist.

Nutzerdefinierter Indikator und Heiken Ashi-Definition

In diesem Teil werden wir den nutzerdefinierten Indikator und den Heiken Ashi-Indikator genauer kennenlernen. Wie ich in der Einleitung des vorigen Abschnitts erwähnt habe, ist der nutzerdefinierte Indikator ein Werkzeug der technischen Analyse, das vom Nutzer mit der Programmiersprache MQL5 erstellt werden kann. Es kann in MetaTrader 5 verwendet werden, um die Marktbewegungen zu analysieren und zu verstehen und kann dabei helfen, fundierte Investitionsentscheidungen zu treffen. Es gibt viele nützliche, integrierte, technische Indikatoren, aber manchmal müssen wir analysieren und verstehen, wie sich der Markt auf der Grundlage einiger zusätzlicher und spezifischer mathematischer, statistischer oder technischer Konzepte verhält, und diese Konzepte existieren nicht in den eingebauten Indikatoren oder es gibt keinen Indikator, der diese Aufgabe erfüllen kann. In solchen Fällen müssen wir den Indikator also selbst erstellen — und das ist eines der Merkmale der MetaTrader 5-Plattform, da sie uns hilft, unsere eigenen Analyse- oder Handelsinstrumente zu erstellen, die unseren spezifischen Vorlieben und Zielen entsprechen.

Betrachten wir die erforderlichen Schritte, um mit der Erstellung Ihres nutzerdefinierten Indikators zu beginnen:

Öffnen Sie die MetaEditor IDE und wählen Sie den Ordner ‚Indicators‘ im Navigator

Ordner Indicators

Klicken Sie auf die Schaltfläche „New“, um ein neues Programm zu erstellen, wie in der folgenden Abbildung gezeigt:

Schaltfläche New

Danach wird das folgende Fenster geöffnet, in dem Sie den Typ des zu erstellenden Programms auswählen müssen. Hier wählen wir ‚Benutzerdefinierter Indikator‘:

Auswahl des Programms

Nachdem Sie auf „Weiter“ geklickt haben, wird das folgende Fenster mit den Details des Indikators geöffnet. Geben Sie hier den Namen für den nutzerdefinierten Indikator an und klicken Sie dann auf „Weiter“:

Details zum Indikator

In den nächsten Fenstern werden wir weitere Details zu den Indikatoren festlegen:

Details zum Indikator2

Details zum Indikator3

Sobald wir die Einstellungen vorgenommen und auf „Weiter“ und dann auf „Fertig stellen“ (Finish) geklickt haben, öffnet sich das Editor-Fenster, in dem wir den Code des Indikators schreiben.

Wir werden uns ansehen, wie man einen nutzerdefinierten Indikator am Beispiel des Heiken Ashi entwickelt. Wir müssen also mehr über den technischen Indikator Heiken Ashi erfahren. Es handelt sich um eine Chart-Methode vom Typ Kerze, die zur Darstellung und Analyse von Marktbewegungen verwendet werden kann. Sie kann in Verbindung mit anderen Instrumenten eingesetzt werden, um effektive und bessere Erkenntnisse zu gewinnen, auf deren Grundlage wir fundierte Handelsentscheidungen treffen können, nachdem wir gute potenzielle Handelsideen und -gelegenheiten gefunden haben.

Die Heiken Ashi-Charts ähneln den normalen technischen Kerzencharts, aber die Berechnung zur Darstellung dieser Kerzen ist anders. Es gibt nämlich zwei unterschiedliche Methoden. Wie wir wissen, berechnet der normale Kerzenchart die Preise auf der Grundlage der tatsächlichen Eröffnungs-, Höchst-, Tiefst- und Schlusskurse in einem bestimmten Zeitraum, aber der Heiken Ashi berücksichtigt bei der Berechnung seiner Kerzen die Preise der vorherigen ähnlichen Preise (Eröffnungs-, Höchst-, Tiefst- und Schlusskurse).

So werden die relevanten Werte für Heiken Ashi berechnet:

  • Open = (Open der vorherigen Kerze + Close der vorherigen Kerze) / 2
  • Close = (Open + Close + High + Low der aktuellen Kerze) / 4
  • Hoch = der höchste Wert des Hochs, des Eröffnungswerts oder des Schlusswerts des aktuellen Zeitraums
  • Tiefstwert = der niedrigste Wert des Tiefstwerts, des Eröffnungswerts oder des Schlusswerts des aktuellen Zeitraums

Auf der Grundlage der Berechnung konstruiert der Indikator Auf- und Abwärtskerzen, deren Farben die jeweilige Marktrichtung anzeigen: ob es sich um einen Auf- oder Abwärtstrend handelt. Das folgende Beispiel zeigt die traditionellen japanischen Kerzen und den Heiken Ashi, damit Sie den Unterschied aus visueller Sicht erkennen können.

 ha-Indikator

In der vorherigen Abbildung zeigt der obere Teil des Charts die traditionellen Kerzen, während im unteren Teil der Heiken Ashi-Indikator als blaue und rote Kerze erscheint, die die Marktrichtung bestimmen. Das Ziel dieses Indikators ist es, einen Teil des Rauschens in der Marktbewegung zu filtern und zu eliminieren, indem die Daten geglättet werden, um falsche Signale zu vermeiden.


Einfacher Heiken Ashi Indikator

In diesem Teil werden wir einen einfachen Heiken Ashi-Indikator erstellen, der im MetaTrader 5 verwendet werden kann. Der Indikator sollte fortlaufend die Preise (Eröffnungs-, Höchst-, Tiefst- und Schlusskurs) überprüfen und die mathematischen Berechnungen durchführen, um die Werte haOpen, haHigh, haLow und haClose zu erzeugen. Auf der Grundlage der Berechnungen sollte der Indikator die Werte auf dem Chart als Kerzen in verschiedenen Farben darstellen: blau, wenn die Kerzenrichtung steigt, und rot, wenn sie fällt. Die Kerzen sollten in einem separaten Fenster unterhalb des traditionellen Charts als Unterfenster angezeigt werden.

Sehen wir uns alle Schritte an, die wir zur Erstellung dieses nutzerdefinierten Indikators ausführen müssen.

Festlegung der Indikatoreinstellungen durch Angabe zusätzlicher Parameter über #property und Bezeichnerwerte, wie folgt:

  • (indicator_separate_window), um den Indikator in einem separaten Fenster anzuzeigen.
  • (indicator_buffers), um die Anzahl der Puffer für die Indikatorberechnung zu bestimmen.
  • (indicator_plots), um die Anzahl der grafischen Zeitreihen im Indikator zu bestimmen. Grafischen Zeitreihen sind Zeichenstile, die bei der Erstellung eines nutzerdefinierten Indikators verwendet werden können.
  • (indicator_typeN), um die Art der grafischen Darstellung aus den Werten von (ENUM_DRAW_TYPE) zu bestimmen, N ist die Anzahl der grafischen Reihen, die wir im letzten Parameter festgelegt haben, und beginnt bei 1.
  • (indicator_colorN), um die Farbe von N zu bestimmen. N ist auch die Anzahl der Grafikserien, die wir zuvor bestimmt haben, und sie beginnt bei 1.
  • (indicator_widthN), um auch die Dicke von N- oder Grafikreihen zu bestimmen.
  • (indicator_labelN), um eine Beschriftung für N der ermittelten Grafikreihen zu setzen.
#property indicator_separate_window
#property indicator_buffers 5
#property indicator_plots   1
#property indicator_type1   DRAW_COLOR_CANDLES
#property indicator_color1  clrBlue, clrRed
#property indicator_width1  2
#property indicator_label1  "Heiken Ashi Open;Heiken Ashi High;Heiken Ashi Low;Heiken Ashi Close"

Wir erstellen fünf Arrays für fünf Puffer des Indikators (haOpen, haHigh, haLow, haClose, haColor) mit dem Typ double.

double haOpen[];
double haHigh[];
double haLow[];
double haClose[];
double haColor[];

Innerhalb der Funktion OnInit() wird diese Funktion verwendet, um einen laufenden Indikator zu initialisieren.

int OnInit()

Sortieren von Indikatorpuffern mit einem eindimensionalen dynamischen Array vom Typ Double unter Verwendung der Funktion (SetIndexBuffer). Die Parameter sind:

  • index: die Nummer des Indikatorpuffers, beginnend bei 0, und diese Nummer muss kleiner sein als der Wert, der im Parameter determined von (indicator_buffers) angegeben ist.
  • buffer[]: das Array, das in unserem nutzerdefinierten Indikator deklariert ist.
  • data_type: der Datentyp, der im Indikator-Array gespeichert werden soll.
   SetIndexBuffer(0,haOpen,INDICATOR_DATA);
   SetIndexBuffer(1,haHigh,INDICATOR_DATA);
   SetIndexBuffer(2,haLow,INDICATOR_DATA);
   SetIndexBuffer(3,haClose,INDICATOR_DATA);
   SetIndexBuffer(4,haColor,INDICATOR_COLOR_INDEX);

Einstellung des Wertes der entsprechenden Indikatoreigenschaft durch Verwendung der Funktion (IndicatorSetInteger) mit der Aufrufvariante, in der wir den Eigenschaftsbezeichner angeben. Die Parameter sind:

  • prop_id: der Bezeichner der Eigenschaft, der einer der (ENUM_CUSTOMIND_PROPERTY_INTEGER) sein kann, wir werden (INDICATOR_DIGITS) angeben.
  • prop_value: der Wert der Eigenschaft, den wir angeben werden (_Digits).
IndicatorSetInteger(INDICATOR_DIGITS,_Digits);

Einstellen des Wertes der entsprechenden Eigenschaft vom Typ String mit der Variante des Aufrufs, bei der wir auch den Bezeichner der Eigenschaft angeben. Die Parameter sind:

  • prop_id: der Bezeichner der Eigenschaft, der einer der (ENUM_CUSTOMIND_PROPERTY_STRING) sein kann, wir geben (INDICATOR_SHORTNAME) an, um einen Kurznamen für den Indikator zu verwenden.
  • prop_value: der Wert der Eigenschaft, die wir angeben werden („Simple Heiken Ashi“).
   IndicatorSetString(INDICATOR_SHORTNAME,"Simple Heiken Ashi");

Einstellung des Wertes der entsprechenden Eigenschaft vom Typ Double des entsprechenden Indikators mit Hilfe der Funktion (PlotIndexSetDouble). Die Parameter sind:

  • plot_index: der Index der grafischen Darstellung, wir geben 0 an.
  • prop_id: einer der Werte (ENUM_PLOT_PROPERTY_DOUBLE), bei keiner Zeichnung ist es (PLOT_EMPTY_VALUE).
  • prop_value: der Wert der Eigenschaft.
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);

Geben Sie dann (INIT_SUCCEEDED) als Teil der Funktion OnInit() zurück, um sie durch Rückgabe der erfolgreichen Initialisierung zu beenden.

   return(INIT_SUCCEEDED);

Innerhalb der Funktion OnCalculate(), die im Indikator zur Verarbeitung von Preisdaten aufgerufen wird, ändert sich die Art der Berechnungen auf der Grundlage der aktuellen Zeitreihe.

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[])

Erstellen einer Integer-Variablen „start“, deren Wert wir später zuweisen werden:

int start;

Mit der if-Anweisung werden die Indexwerte (low, high, open und close) und der Startwert=1 zurückgegeben, wenn prev_calculated gleich 0 ist, oder der Startwert wird (prev_calculated-1) zugewiesen:

   if(prev_calculated==0)
     {
      haLow[0]=low[0];
      haHigh[0]=high[0];
      haOpen[0]=open[0];
      haClose[0]=close[0];
      start=1;
     }
   else
      start=prev_calculated-1;

Bei der Verwendung der Funktion „for“ für die Hauptschleife der Berechnung besteht der „for“-Operator aus drei Ausdrücken und ausführbaren Operatoren.

Die drei Ausdrücke sind:

  • i=start: für die Startposition.
  • i<rates_total && !IsStopped(): für die Bedingungen zum Beenden der Schleife. IsStopped() prüft das zwangsweise Abschalten des Indikators.
  • i++: erhöht i um 1.

Die Operationen, die wir jedes Mal während der Schleife ausführen müssen:

Berechnung für die vier Variablen vom Typ double.

  • haOpenVal: für den Eröffnungskurs des Heiken Ashi.
  • haCloseVal: für den Schlusskurs des Heiken Ashi.
  • haHighVal: für das Hoch des Heiken Ashi.
  • haLowVal: für das Tief des Heiken Ashi.

Die Zuweisung der im vorherigen Schritt berechneten Werte entspricht der folgenden Vorgehensweise

  • haLow[i]=haLowVal
  • haHigh[i]=haHighVal
  • haOpen[i]=haOpenVal
  • haClose[i]=haCloseVal

Wenn der Eröffnungswert des Heiken Ashi niedriger ist als der Schlusswert, muss der Indikator eine blaue Kerze zeichnen, andernfalls eine rote Kerze.

   for(int i=start; i<rates_total && !IsStopped(); i++)
     {
      double haOpenVal =(haOpen[i-1]+haClose[i-1])/2;
      double haCloseVal=(open[i]+high[i]+low[i]+close[i])/4;
      double haHighVal =MathMax(high[i],MathMax(haOpenVal,haCloseVal));
      double haLowVal  =MathMin(low[i],MathMin(haOpenVal,haCloseVal));

      haLow[i]=haLowVal;
      haHigh[i]=haHighVal;
      haOpen[i]=haOpenVal;
      haClose[i]=haCloseVal;

      //--- set candle color
      if(haOpenVal<haCloseVal)
         haColor[i]=0.0;
      else
         haColor[i]=1.0;
     }

Beenden der Funktion mit der Rückgabe von (rates_total), dem prev_calculated des nächsten Aufrufs.

return(rates_total);

Dann kompilieren wir den Code, um sicherzustellen, dass er keine Fehler enthält. Im Folgenden finden Sie den vollständigen Code in einem Block:

//+------------------------------------------------------------------+
//|                                             simpleHeikenAshi.mq5 |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_separate_window
#property indicator_buffers 5
#property indicator_plots   1
#property indicator_type1   DRAW_COLOR_CANDLES
#property indicator_color1  clrBlue, clrRed
#property indicator_width1  2
#property indicator_label1  "Heiken Ashi Open;Heiken Ashi High;Heiken Ashi Low;Heiken Ashi Close"
double haOpen[];
double haHigh[];
double haLow[];
double haClose[];
double haColor[];
int OnInit()
  {
   SetIndexBuffer(0,haOpen,INDICATOR_DATA);
   SetIndexBuffer(1,haHigh,INDICATOR_DATA);
   SetIndexBuffer(2,haLow,INDICATOR_DATA);
   SetIndexBuffer(3,haClose,INDICATOR_DATA);
   SetIndexBuffer(4,haColor,INDICATOR_COLOR_INDEX);
   IndicatorSetInteger(INDICATOR_DIGITS,_Digits);
   IndicatorSetString(INDICATOR_SHORTNAME,"Simple Heiken Ashi");
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
   return(INIT_SUCCEEDED);
  }
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[])
  {
   int start;
   if(prev_calculated==0)
     {
      haLow[0]=low[0];
      haHigh[0]=high[0];
      haOpen[0]=open[0];
      haClose[0]=close[0];
      start=1;
     }
   else
      start=prev_calculated-1;
   for(int i=start; i<rates_total && !IsStopped(); i++)
     {
      double haOpenVal =(haOpen[i-1]+haClose[i-1])/2;
      double haCloseVal=(open[i]+high[i]+low[i]+close[i])/4;
      double haHighVal =MathMax(high[i],MathMax(haOpenVal,haCloseVal));
      double haLowVal  =MathMin(low[i],MathMin(haOpenVal,haCloseVal));

      haLow[i]=haLowVal;
      haHigh[i]=haHighVal;
      haOpen[i]=haOpenVal;
      haClose[i]=haCloseVal;
      if(haOpenVal<haCloseVal)
         haColor[i]=0.0;
      else
         haColor[i]=1.0;
     }
   return(rates_total);
  }

Nach dem fehlerfreien Kompilieren sollte der Indikator im Ordner „Indicators“ im Navigator-Fenster verfügbar sein, wie in der folgenden Abbildung dargestellt.

simpleHA nav

Dann machen Sie einen Doppelklick darauf, um ihn auf dem gewünschten Chart zu starten, woraufhin das allgemeine Fenster mit den Indikatorinformationen erscheint:

 einfachHA gewinnen

Die Registerkarte Farben zeigt die Standardeinstellungen: blaue Farbe für die Aufwärtsbewegung und rote Farbe für die Abwärtsbewegung. Bei Bedarf können Sie diese Werte bearbeiten, um Ihre bevorzugten Farben einzustellen. Diese Registerkarte sieht wie folgt aus:

 einfachHA win2

Nachdem wir auf OK gedrückt haben, wird der Indikator auf dem Chart gestartet und es erscheint die folgende Abbildung:

simpleHA beigefügt

Wie Sie im vorherigen Chart sehen können, läuft der Simple Heiken Ashi Indikator in einem separaten Unterfenster des Charts. Er hat blaue und rote Kerzen, entsprechend der Richtung dieser Kerzen (auf- oder abwärts). Jetzt haben wir einen nutzerdefinierten Indikator, den wir in unserem MetaTrader 5 erstellt haben, und wir können diesen nutzerdefinierten Indikator in jedem Handelssystem verwenden. Wir werden in den nächsten Themen sehen, wie wir das einfach machen können.


EA basierend auf dem nutzerdefinierten Heiken Ashi Indikator

In diesem Teil werden wir lernen, wie wir einen beliebigen nutzerdefinierten Indikator in unserem Handelssystem EA verwenden können. Wir werden ein einfaches Heiken Ashi System erstellen, das uns die Preise des Indikators (Open, High, Low und Close) liefern kann, da wir bereits wissen, dass sie von den tatsächlichen Preisen gemäß der Berechnung des Indikators abweichen.

Dazu müssen Sie einen neuen Expert Advisor erstellen. Im Folgenden finden Sie den vollständigen Code:

//+------------------------------------------------------------------+
//|                                             heikenAshiSystem.mq5 |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
int heikenAshi;
int OnInit()
  {
   heikenAshi=iCustom(_Symbol,_Period,"My Files\\Heiken Ashi\\simpleHeikenAshi");
   return(INIT_SUCCEEDED);
  }
void OnDeinit(const int reason)
  {
   Print("Heiken Ashi System Removed");
  }
void OnTick()
  {
   double heikenAshiOpen[], heikenAshiHigh[], heikenAshiLow[], heikenAshiClose[];
   CopyBuffer(heikenAshi,0,0,1,heikenAshiOpen);
   CopyBuffer(heikenAshi,1,0,1,heikenAshiHigh);
   CopyBuffer(heikenAshi,2,0,1,heikenAshiLow);
   CopyBuffer(heikenAshi,3,0,1,heikenAshiClose);
   Comment("heikenAshiOpen ",DoubleToString(heikenAshiOpen[0],_Digits),
           "\n heikenAshiHigh ",DoubleToString(heikenAshiHigh[0],_Digits),
           "\n heikenAshiLow ",DoubleToString(heikenAshiLow[0],_Digits),
           "\n heikenAshiClose ",DoubleToString(heikenAshiClose[0],_Digits));
  }

Unterschiede in diesem Code:

Der Typ des Programms ist ein Expert Advisor. Der Aufbau dieses Programms wird also anders sein, da er aus drei Teilen besteht, und zwar:

  • int OnInit(): wird verwendet, um einen laufenden EA mit seinem empfohlenen Typ zu initialisieren, der einen Integer-Wert zurückgibt.
  • void OnDeinit: wird verwendet, um eine Ausführung des EA zu deinitialisieren, es wird kein Wert zurückgegeben.
  • void OnTick(): wird verwendet, um die Kurse bei jedem neuen Tick zu verarbeiten, es wird kein Wert zurückgegeben.

Außerhalb des Anwendungsbereichs der vorherigen Funktionen und vor ihnen haben wir eine Integer-Variable (heikenAshi) erstellt:

int heikenAshi;

Innerhalb des Bereichs von OnInit() haben wir den Wert der Funktion iCustom der Variablen „heikenAshi“ zugewiesen. Die Funktion iCustom gibt das Handle des nutzerdefinierten Indikators zurück, der hier der Simple Heiken Ashi sein wird, aber Sie können jeden beliebigen nutzerdefinierten Indikator aus Ihrem Indikatorenordner verwenden. Die Parameter sind:

  • symbol: der Name des Symbols, wir verwenden (_Symbol) für das aktuelle Symbol.
  • period: der Zeitrahmen, wir haben die (_Periode) für den aktuellen Zeitrahmen verwendet.
  • name: der Name des nutzerdefinierten Indikators mit seinem Pfad im Ordner „Indicators“ Ihres MetaTrader 5. Hier haben wir „My Files\\Heiken Ashi\\simpleHeikenAshi“ verwendet.

Dann beendeten wir die Funktion, indem wir (INIT_SUCCEEDED) für eine erfolgreiche Initialisierung zurückgeben.

int OnInit()
  {
   heikenAshi=iCustom(_Symbol,_Period,"My Files\\Heiken Ashi\\simpleHeikenAshi");
   return(INIT_SUCCEEDED);
  }

Innerhalb des Bereichs der Funktion OnDeinit() haben wir die Funktion print verwendet, um mitzuteilen, dass der EA im Experten entfernt wurde:

void OnDeinit(const int reason)
  {
   Print("Heiken Ashi System Removed");
  }

Innerhalb des Bereichs der Funktion OnTick() haben wir unseren Code wie folgt vervollständigt:

Erstellen von vier Variablen vom Typ double für die Heiken Ashi-Kurse (Open, High, Low und Close).

   double heikenAshiOpen[], heikenAshiHigh[], heikenAshiLow[], heikenAshiClose[];

Abrufen von Daten aus Puffern des nutzerdefinierten Indikators mit der Funktion CopyBuffer. Die Parameter sind:

  • indicator_handle: der von uns verwendete Indikator-Handle (heikenAshi).
  • buffer_num: die Nummer des Indikatorpuffers, die wir verwendet haben (0 für open, 1 für high, 2 für low und 3 für close).
  • start_pos: die erste zu kopierende Elementposition, wir haben 0 für das aktuelle Element verwendet.
  • count: die Anzahl der zu kopierenden Daten, wir haben 1 verwendet und brauchen hier nicht mehr als das.
  • buffer[]: das Array für die benötigten Daten, wir haben (heikenAshiOpen für Open, heikenAshiHigh für High, heikenAshiLow für Low und heikenAshiClose für Close) verwendet.

Wir sehen einen Kommentar auf dem Chart mit den aktuellen Heiken Ashi Kursen (Open, High, Low und Close), indem wir die Kommentarfunktion verwenden:

   Comment("heikenAshiOpen ",DoubleToString(heikenAshiOpen[0],_Digits),
           "\n heikenAshiHigh ",DoubleToString(heikenAshiHigh[0],_Digits),
           "\n heikenAshiLow ",DoubleToString(heikenAshiLow[0],_Digits),
           "\n heikenAshiClose ",DoubleToString(heikenAshiClose[0],_Digits));

Nach dem fehlerfreien Kompilieren dieses Codes und dem Ausführen finden wir den EA an das Chart angehängt. Im folgenden Testbeispiel können wir das Signal auf die gleiche Weise empfangen:

 haSystem

Wie im vorherigen Chart zu sehen ist, erscheinen die Indikatorpreise als Kommentar in der oberen linken Ecke des Charts.


Heiken Ashi - EMA-System

In diesem Thema werden wir ein anderes technisches Werkzeug kombinieren, um zu sehen, ob das Ergebnis besser ist oder nicht. Die Idee, die wir anwenden müssen, ist, die Signale des nutzerdefinierten Indikators zu filtern, indem wir den exponentiellen gleitenden Durchschnitt mit den Preisen verwenden. Es gibt viele Methoden, um das zu tun, können wir eine andere nutzerdefinierte Indikator für die EMA erstellen, wenn wir mehr Funktionen, um die EMA hinzufügen möchten, dann können wir es in der EA als iCustom die gleiche wie wir taten, um Ihre gewünschten Signale zu nehmen. Wir können auch einen geglätteten Indikator erstellen, indem wir die Werte des Indikators glätten und dann unsere Signale nehmen. Wir können die eingebaute iMA-Funktion in unserem EA verwenden, um unsere Signale von ihm zu erhalten, und wir werden diese Methode hier der Einfachheit halber verwenden.

Was wir tun müssen, ist, dass der EA kontinuierlich die Werte der aktuellen 2 EMA (Fast und Slow) und der vorherigen schnellen EMA und Heiken Ash close überprüft, um die Positionen jedes Wertes zu bestimmen. Wenn der vorherige heikenAshiClose größer ist als das vorherige fastEMAarray und das aktuelle fastEMA größer ist als der aktuelle slowEMA-Wert, sollte der EA ein Kaufsignal und diese Werte als Kommentar auf dem Chart zurückgeben. Wenn der vorherige heikenAshiClose niedriger ist als das vorherige fastEMAarray und das aktuelle fastEMA niedriger ist als der aktuelle slowEMA-Wert, sollte der EA ein Verkaufssignal und diese Werte als Kommentar auf dem Chart zurückgeben.

Im Folgenden der vollständige Code zur Erstellung dieses EA:

//+------------------------------------------------------------------+
//|                                          heikenAsh-EMASystem.mq5 |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
input int fastEMASmoothing=9; // Fast EMA Period
input int slowEMASmoothing=18; // Slow EMA Period
int heikenAshi;
double fastEMAarray[], slowEMAarray[];
int OnInit()
  {
   heikenAshi=iCustom(_Symbol,_Period,"My Files\\Heiken Ashi\\simpleHeikenAshi");
   return(INIT_SUCCEEDED);
  }
void OnDeinit(const int reason)
  {
   Print("Heiken Ashi-EMA System Removed");
  }
void OnTick()
  {
   double heikenAshiOpen[], heikenAshiHigh[], heikenAshiLow[], heikenAshiClose[];
   CopyBuffer(heikenAshi,0,0,3,heikenAshiOpen);
   CopyBuffer(heikenAshi,1,0,3,heikenAshiHigh);
   CopyBuffer(heikenAshi,2,0,3,heikenAshiLow);
   CopyBuffer(heikenAshi,3,0,3,heikenAshiClose);
   int fastEMA = iMA(_Symbol,_Period,fastEMASmoothing,0,MODE_SMA,PRICE_CLOSE);
   int slowEMA = iMA(_Symbol,_Period,slowEMASmoothing,0,MODE_SMA,PRICE_CLOSE);
   ArraySetAsSeries(fastEMAarray,true);
   ArraySetAsSeries(slowEMAarray,true);
   CopyBuffer(fastEMA,0,0,3,fastEMAarray);
   CopyBuffer(slowEMA,0,0,3,slowEMAarray);
   if(heikenAshiClose[1]>fastEMAarray[1])
     {
      if(fastEMAarray[0]>slowEMAarray[0])
        {
         Comment("Buy Signal",
                 "\nfastEMA ",DoubleToString(fastEMAarray[0],_Digits),
                 "\nslowEMA ",DoubleToString(slowEMAarray[0],_Digits),
                 "\nprevFastEMA ",DoubleToString(fastEMAarray[1],_Digits),
                 "\nprevHeikenAshiClose ",DoubleToString(heikenAshiClose[0],_Digits));
        }
     }
   if(heikenAshiClose[1]<fastEMAarray[1])
     {
      if(fastEMAarray[0]<slowEMAarray[0])
        {
         Comment("Sell Signal",
                 "\nfastEMA ",DoubleToString(fastEMAarray[0],_Digits),
                 "\nslowEMA ",DoubleToString(slowEMAarray[0],_Digits),
                 "\nprevFastEMA ",DoubleToString(fastEMAarray[1],_Digits),
                 "\nheikenAshiClose ",DoubleToString(heikenAshiClose[0],_Digits));
        }
     }
  }

Die Unterschiede in diesem Code sind:

Erstellung von Nutzereingaben, um die schnelle EMA-Periodenlänge und die langsame EMA-Periodenlänge gemäß den Nutzerpräferenzen einzustellen.

input int fastEMASmoothing=9; // Fast EMA Period
input int slowEMASmoothing=18; // Slow EMA Period

Erstellen von zwei Arrays für fastEMA und slowEMA.

double fastEMAarray[], slowEMAarray[];

Einstellung der zu kopierenden Datenmenge auf 3 im CopyBuffer, um die vorherigen Schlusswerte des Heiken Ashi Indikators zu erhalten

   CopyBuffer(heikenAshi,0,0,3,heikenAshiOpen);
   CopyBuffer(heikenAshi,1,0,3,heikenAshiHigh);
   CopyBuffer(heikenAshi,2,0,3,heikenAshiLow);
   CopyBuffer(heikenAshi,3,0,3,heikenAshiClose);

Definition des schnellen und langsamen EMA mit Hilfe der integrierten Funktion von iMA, die den Handle des Indikators für den gleitenden Durchschnitt zurückgibt. Die Parameter sind:

  • symbol: der Name des Symbols, wir haben (_Symbol) für das aktuelle Symbol verwendet.
  • period: der Zeitrahmen, wir haben (_Period) für den aktuellen Zeitrahmen verwendet.
  • ma_period: die Periodenlänge, der für die Glättung des Durchschnitts benötigt wird; wir haben die Eingaben fastEMASmoothing und slowEMASmoothing verwendet.
  • ma_shift: die Verschiebung des Indikators, wir haben 0 verwendet.
  • ma_method: der Typ des gleitenden Durchschnitts, wir haben MODE_SMA für den einfachen gleitenden Durchschnitt verwendet.
  • applied_price: der benötigte Preistyp, der in der Berechnung verwendet werden soll; wir haben den PRICE_CLOSE verwendet.
   int fastEMA = iMA(_Symbol,_Period,fastEMASmoothing,0,MODE_SMA,PRICE_CLOSE);
   int slowEMA = iMA(_Symbol,_Period,slowEMASmoothing,0,MODE_SMA,PRICE_CLOSE);

Verwendung der Funktion ArraySetAsSeries, um das AS_SERIES-Flag zu setzen. Die Parameter sind:

  • array[]: das Array, das wir verwendet haben (fastEMAarray und slowEMA).
  • flag: die Richtung der Array-Indizierung, wir haben true verwendet.
   ArraySetAsSeries(fastEMAarray,true);
   ArraySetAsSeries(slowEMAarray,true);

Abrufen der Daten des Puffers des EMA-Indikators mit Hilfe der Funktion CopyBuffer.

   CopyBuffer(fastEMA,0,0,3,fastEMAarray);
   CopyBuffer(slowEMA,0,0,3,slowEMAarray);

Bedingungen für die Rückgabe von Signalen mit Hilfe der if-Anweisung:

Im Falle eines Kaufsignals:

Wenn der vorherige heikenAshiClose > das vorherige fastEMAarray und das aktuelle fastEMAarray > das aktuelle slowEMAarray ist, muss der EA ein Kaufsignal und die folgenden Werte zurückgeben:

  • fastEMA
  • slowEMA
  • prevFastEMA
  • prevHeikenAshiClose
   if(heikenAshiClose[1]>fastEMAarray[1])
     {
      if(fastEMAarray[0]>slowEMAarray[0])
        {
         Comment("Buy Signal",
                 "\nfastEMA ",DoubleToString(fastEMAarray[0],_Digits),
                 "\nslowEMA ",DoubleToString(slowEMAarray[0],_Digits),
                 "\nprevFastEMA ",DoubleToString(fastEMAarray[1],_Digits),
                 "\nprevHeikenAshiClose ",DoubleToString(heikenAshiClose[0],_Digits));
        }

Im Falle eines Verkaufssignals

Wenn der vorherige HeikenAshiClose < dem vorherigen fastEMAarray und der aktuelle fastEMAarray < dem aktuellen slowEMAarray ist, muss der EA ein Verkaufssignal und Preiswerte von zurückgeben:

  • fastEMA
  • slowEMA
  • prevFastEMA
  • prevHeikenAshiClose
   if(heikenAshiClose[1]<fastEMAarray[1])
     {
      if(fastEMAarray[0]<slowEMAarray[0])
        {
         Comment("Sell Signal",
                 "\nfastEMA ",DoubleToString(fastEMAarray[0],_Digits),
                 "\nslowEMA ",DoubleToString(slowEMAarray[0],_Digits),
                 "\nprevFastEMA ",DoubleToString(fastEMAarray[1],_Digits),
                 "\nheikenAshiClose ",DoubleToString(heikenAshiClose[0],_Digits));
        }
     }

Nachdem wir diesen Code ohne Fehlern kompiliert und ausgeführt haben, erhalten wir unsere Signale wie in den folgenden Testbeispielen gezeigt.

Im Falle eines Kaufsignals:

HA mit 2EMA - Kaufsignal

Wie wir in der vorherigen Grafik sehen können, haben wir das folgende Signal als Kommentar in der oberen linken Ecke:

  • Kaufsignal (Buy Signal)
  • fastEMA
  • prevFastEMA
  • prevHeikenAshiClose

Im Falle eines Verkaufssignals:

HA mit 2EMA - Signal verkaufen

Wir haben die folgenden Werte als Signal auf dem Chart:

  • Verkaufssignal (Sell Signal)
  • fastEMA
  • prevFastEMA
  • prevHeikenAshiClose

Schlussfolgerung

Wenn Sie alles verstanden haben, was wir in diesem Artikel besprochen haben, sind Sie vermutlich in der Lage, Ihren eigenen Custom Heiken Ashi Indikator zu erstellen oder sogar weitere Funktionen nach Ihren Wünschen hinzuzufügen. Dies ist sehr nützlich, um Charts zu lesen und effektive Entscheidungen auf der Grundlage Ihres Verständnisses zu treffen. Darüber hinaus können Sie den erstellten Indikator in Ihren Handelssystemen als Expert Advisor verwenden, da wir ihn in zwei Handelssystemen als Beispiel erwähnt und verwendet haben.

  • Heiken Ashi System
  • Heiken Ashi-EMA-System

Ich hoffe, dass dieser Artikel für Sie nützlich war und Sie einen guten Einblick in das Thema oder ein verwandtes Thema bekommen haben. Ich hoffe auch, dass Sie versucht haben, das, was Sie in diesem Artikel gelernt haben, anzuwenden, da es sehr nützlich für Ihre Lernreise in der Programmierung sein wird, da das Üben ein sehr wichtiger Faktor in effektiven Bildungsprozessen ist. Bitte beachten Sie, dass Sie alles, was Sie in diesem Artikel oder in anderen Ressourcen gelernt haben, testen müssen, bevor Sie es in Ihrem echten Konto verwenden, da es schädlich sein kann, wenn es für Sie nicht geeignet ist. Das Hauptziel dieses Artikels ist rein pädagogisch, deshalb müssen Sie vorsichtig sein.

Wenn Sie diesen Artikel nützlich fanden und weitere Artikel lesen möchten, darf ich Sie auf meine anderen Artikel verweisen. Ich hoffe, auch sie können Ihnen nützlich sein.

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

Letzte Kommentare | Zur Diskussion im Händlerforum (3)
Johann Kern
Johann Kern | 11 Nov. 2023 in 05:29

Deklaration- Definition

Hi, 
wie ich sehe, verwendest Du zur objektorientierten Programmierung die Member OnInit(),- OnDenit(),- OnTick().
Aber gehört die Deklaration- bzw. das Initialisieren der Variablen, wie z.B. double heikenAshiOpen[]… nicht einmalig in die OnInit()- und Folge dessen das Bewerten der Variablen (Definition), wie auch die Objektvariablen, fastEMA- und slowEMA in den Ticker?

Carl Schreiber
Carl Schreiber | 11 Nov. 2023 in 08:53

Im Prinzip ja, aber hier nicht, da die Variablen bei Verlassen der Funktion(en) ihre Werte wieder verlieren würden. Google mal nach: site:mql5.com scope variable

und lies: https://www.mql5.com/en/docs/basis/variables/variable_scope

Igor Widiger
Igor Widiger | 11 Nov. 2023 in 16:42

Deklaration- Definition

Hi, 
wie ich sehe, verwendest Du zur objektorientierten Programmierung die Member OnInit(),- OnDenit(),- OnTick().
Aber gehört die Deklaration- bzw. das Initialisieren der Variablen, wie z.B. double heikenAshiOpen[]… nicht einmalig in die OnInit()- und Folge dessen das Bewerten der Variablen (Definition), wie auch die Objektvariablen, fastEMA- und slowEMA in den Ticker?

Ich denke genauso wie Carlo. Arrays in

OnInit()

werden nur beim Hochladen des EA's geladen und bei Timeframe - Wechsel.

Weil sich der Wert beim jeden Tick ändert.

Und bei Indikator halt, tut das 

OnCalculate

berechnen.

Wie man mit MQL5 Trends und Chartmuster erkennt Wie man mit MQL5 Trends und Chartmuster erkennt
In diesem Artikel stellen wir eine Methode vor, mit der MQL5 automatisch Preisaktionsmuster wie Trends (Aufwärtstrend, Abwärtstrend, Seitwärtsbewegung) und Chartmuster (Doppelspitzen, Doppelböden) erkennt.
Einige Lektionen der Prop-Firmen (Teil 1) — Eine Einführung Einige Lektionen der Prop-Firmen (Teil 1) — Eine Einführung
In diesem einführenden Artikel spreche ich einige der Lehren an, die man aus den Risikoregeln ziehen kann, die Unternehmen für den Eigenhandel, engl. proprietary trading firms oder Prop-Firms, anwenden. Dies ist besonders wichtig für Anfänger und diejenigen, die Schwierigkeiten haben, in dieser Welt des Handels Fuß zu fassen. Der folgende Artikel wird sich mit der Implementierung des Codes befassen.
Implementierung eines ARIMA-Trainingsalgorithmus in MQL5 Implementierung eines ARIMA-Trainingsalgorithmus in MQL5
In diesem Artikel wird ein Algorithmus implementiert, der das autoregressive integrierte gleitende Durchschnittsmodell von Box und Jenkins unter Verwendung der Powells-Methode der Funktionsminimierung anwendet. Box und Jenkins stellten fest, dass die meisten Zeitreihen mit einem oder beiden Rahmen modelliert werden können.
Geldmanagement im Handel Geldmanagement im Handel
Wir werden uns verschiedene neue Arten von Geldmanagementsystemen ansehen und ihre wichtigsten Merkmale definieren. Heute gibt es eine ganze Reihe von Geldmanagementstrategien für jeden Geschmack. Wir werden versuchen, verschiedene Möglichkeiten der Geldverwaltung auf der Grundlage unterschiedlicher mathematischer Wachstumsmodelle zu prüfen.