English Русский 中文 Español 日本語 Português
preview
Wie man einen nutzerdefinierten True Strength Index-Indikator mit MQL5 erstellt

Wie man einen nutzerdefinierten True Strength Index-Indikator mit MQL5 erstellt

MetaTrader 5Handel | 20 Juni 2023, 16:27
358 0
Mohamed Abdelmaaboud
Mohamed Abdelmaaboud

Einführung

Technische Indikatoren können sehr nützlich sein, wenn man sie richtig einsetzt, da sie zusätzliche Erkenntnisse liefern können, die bei einer alleinigen Betrachtung der Kursentwicklung schwer zu erkennen sind. Es gibt viele fertige technische Indikatoren, die wir verwenden können, aber manchmal müssen wir sie anpassen, um bestimmte Erkenntnisse zu gewinnen, oder wir müssen einen neuen Indikator auf der Grundlage unserer Gewinnideen entwickeln. Es gibt eine Möglichkeit, solche nutzerdefinierten Indikatoren in MQL5 zu erstellen und sie in der MetaTrader 5 Handelsplattform zu verwenden. In diesem Artikel werde ich Ihnen zeigen, wie Sie den True Strength Index Indicator von Grund auf neu erstellen können. Wir werden die Besonderheiten dieses Indikators kennenlernen und sehen, wie wir ihn in unserem Code berechnen können. Aber nicht nur das, wir werden auch lernen, wie wir diesen angepassten Indikator in einem Handelssystem verwenden können, das auf einer Handelsstrategie basiert, indem wir einen Expert Advisor erstellen. All das werden wir in den folgenden Themen behandeln:

Nach dem Verständnis der zuvor genannten Themen werden wir in der Lage sein, die Verwendung und Interpretation des True Strength Index-Indikators zu verstehen, ihn zu berechnen und diesen Indikator als nutzerdefinierten Indikator in der Sprache MQL5 zu kodieren, um ihn im MetaTrader 5 zu verwenden. Sie können den Indikator auch in andere Handelssysteme oder EAs implementieren. Wenn Sie Ihre Programmierfähigkeiten verbessern wollen, empfehle ich Ihnen, den Inhalt selbst zu programmieren, da dies ein wichtiger Schritt in jedem Lernprozess oder Fahrplan ist. Wir werden den MetaTrader 5 verwenden, um unseren MQL5-Code in seiner IDE zu schreiben, die in das MetaTrader 5-Handelsterminal integriert ist. Wenn Sie die Plattform nicht haben oder nicht wissen, wie man sie herunterlädt und benutzt, können Sie das Thema "Schreiben von MQL5-Code in MetaEditor" in meinen früheren Artikeln lesen.

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 keinerlei Ergebnis. Wenn Sie sich dafür entscheiden, diese Materialien auf einem Ihrer Handelskonten zu verwenden, tun Sie dies auf eigenes Risiko und sind allein dafür verantwortlich.


Definition des True Strength Index (TSI)

In diesem Teil werden wir uns mit dem technischen Indikator True Strength Index (TSI) befassen, um ihn richtig zu verstehen. Er wurde von William Blau als technischer Indikator entwickelt, der das Momentum der Preisaktion misst, d.h. er misst die Stärke des Instruments, ob es stark oder schwach ist. Er oszilliert um die Nulllinie, der Indikator ist also ein Momentum-Oszillator. Eine Signallinie kann dazu verwendet werden, um zusätzliche Kauf- oder Verkaufssignale zu erhalten, die auf der Kreuzung zwischen diesen Linien basieren. Wir können jedoch auch nur auf der TSI-Linie basierende Signale erhalten, die auf dem Kreuzungspunkt mit dem Nullniveau basieren. Liegt er über der Nulllinie, bedeutet dies ein aufwärts Momentum, liegt er unter der Nulllinie, bedeutet dies ein abwärts Momentum. Er kann verwendet werden, um überkaufte und überverkaufte Bereiche sowie auf- und abwärts Divergenzen zu erkennen. Da wir wissen, dass wir seine Signale bestätigen müssen, um die Beweiskraft zu erhöhen, ist es besser, ihn zusammen mit anderen technischen Instrumenten zu verwenden, die wir im gleichen Kontext der Preisaktion einsetzen sollten, um bessere Erkenntnisse zu gewinnen.

Sehen wir uns nun an, wie man diesen Indikator berechnet. Die Berechnung erfolgt in mehreren Schritten, die da wären:

Berechnung des doppelt geglätteten Momentums:

  • Berechnung des Momentums (Preisänderung) durch Subtraktion des vorherigen Preises vom aktuellen Preis.
  • Berechnung der ersten Glättung durch Ermittlung des 25-Perioden-EMA des berechneten Momentums.
  • Berechnung der zweiten Glättung durch Ermittlung des 13-Perioden-EMA der ersten Glättung (25-Perioden-EMA des berechneten Momentums).

Berechnung des doppelt geglätteten absoluten Momentums:

  • Berechnung des absoluten Momentums durch Subtraktion des absoluten vorherigen Kurses vom absoluten aktuellen Kurs.
  • Berechnung der ersten Glättung durch Ermittlung des 25-Perioden-EMA des berechneten absoluten Momentums.
  • Berechnung der zweiten Glättung durch Ermittlung des 13-Perioden-EMA der ersten Glättung (25-Perioden-EMA des berechneten absoluten Momentum).

Berechnung der TSI = 100*( Doppelt geglättetes Momentum / Doppelt geglättetes absolutes Momentum).

Diese Berechnung ergibt eine um den Nullpunkt oszillierende Linie, die das Momentum der Kursbewegung misst und überkaufte und überverkaufte Bereiche aufdeckt, wie wir bereits erwähnt haben, und andere.


Ein nutzerdefinierter einfacher TSI-Indikator

Die Programmiersprache MQL5 verfügt über viele vordefinierte technische Indikatoren, die wir in unseren Systemen verwenden können, indem wir die vordefinierte Funktion nutzen. Wir haben bereits in früheren Artikeln dieser Serie über eine Vielzahl solcher Indikatoren gesprochen und erörtert, wie wir ein Handelssystem auf der Grundlage dieser beliebten technischen Indikatoren entwickeln können. Sie können sich die früheren Artikel ansehen und vielleicht etwas Nützliches finden. Die Frage ist nun, wie wir einen Indikator erstellen können, wenn er nicht im Standardlieferumfang der Plattform enthalten ist, oder selbst wenn er vorhanden ist, wie wir einen angepassten Indikator erstellen können, um die gewünschten Signale oder Auslöser zu erhalten. Die kurze Antwort ist, einen nutzerdefinierten Indikator mit Hilfe der Hauptprogrammiersprache zu erstellen, und genau das werden wir in diesem Teil tun.

Wir werden lernen, wie wir unseren eigenen True Strength Index-Indikator mit MQL5 erstellen können. Dann werden wir seine Funktionen in anderen Systemen oder EAs verwenden. Die folgenden Schritte dienen der Erstellung dieses nutzerdefinierten Indikators.

Erstellen von zusätzlichen Parametern durch die Verwendung von #property und daneben werden wir den Wert des Identifikators angeben. Die folgenden sind diese Parameter, die wir angeben müssen:

  • (indicator_separate_window) — um den Indikator in einem separaten Fenster anzuzeigen.
  • (indicator_buffers) — um die Anzahl der Puffer des Indikators anzugeben, geben wir (8) an.
  • (indicator_plots) — um die Anzahl der grafischen Reihen im Indikator festzulegen, wird (1) angegeben.
  • (indicator_label1) — um die Bezeichnung für die Nummer der grafischen Reihe festzulegen, geben wir (TSI) an.
  • (indicator_type1) — um die Art der grafischen Darstellung durch Angabe eines Wertes aus den ENUM_DRAW_TYPE-Werten festzulegen, geben wir (DRAW_LINE) an.
  • (indicator_color1) — um die Farbe der angezeigten Linie des Indikators zu bestimmen, geben wir (clrBlue) an.
  • (indicator_style1) — um den Stil der Linie des Indikators zu bestimmen, geben wir (STYLE_SOLID) an.
  • (indicator_width1) — um die Dicke der Linie des Indikators zu bestimmen, geben wir (3) an.
#property indicator_separate_window
#property indicator_buffers 8
#property indicator_plots   1
#property indicator_label1  "TSI"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrBlue
#property indicator_style1  STYLE_SOLID
#property indicator_width1  3

Wir müssen die Datei MovingAverage.mqh einbinden, um ihre Komponente in unserer Berechnung zu verwenden, und diese Datei ist in der Include-Datei vorhanden, indem wir den Befehl #include verwenden. Achten Sie darauf, dass Sie den Namen der Datei genauso schreiben wie den Namen der Datei.

#include <MovingAverages.mqh>

Wir müssen zwei Eingaben für die Glättungsperioden festlegen, die wir bei der Berechnung des Indikators verwenden werden, indem wir die Eingabeklasse verwenden, um diese Werte durch den Nutzer einzugeben, wenn er die im Programm festgelegten Standardwerte aktualisieren muss. Danach bestimmen wir den Datentyp der Variablen (InpSmPeriod1, InpSmPeriod2), die wir mit Hilfe von uint, einer Ganzzahl ohne Vorzeichen, deklarieren müssen. Dann ordnen wir (25) der InpSmPeriod1 und (13) der InpSmPeriod2 als Standardwerte zu. 

input uint     InpSmPeriod1   =  25;    // Smoothing period 1
input uint     InpSmPeriod2   =  13;   // Smoothing period 2

Erstellung von zwei ganzzahligen Variablen für Glättungsperioden (smperiod1,smperiod2):

int            smperiod1;
int            smperiod2;

Erstellen von sieben Arrays für die Indikatorpuffer:

double         indBuff[];
double         momBuff[];
double         momSmBuff1[];
double         momSmBuff2[];
double         absMomBuff[];
double         absMomSmBuff1[];
double         absMomSmBuff2[];

In der Funktion OnInit() werden wir die folgenden Schritte durchführen:

Deklaration von Variablen (smperiod1,smperiod2) durch Rückgabe des Wertes 2, wenn die Nutzereingabe von InpSmPeriod1 und InpSmPeriod2 kleiner als 2 ist, oder Rückgabe der Werte von InpSmPeriod1 und InpSmPeriod2, wenn etwas anderes vorliegt.

   smperiod1=int(InpSmPeriod1<2 ? 2 : InpSmPeriod1);
   smperiod2=int(InpSmPeriod2<2 ? 2 : InpSmPeriod2);

Binden der Indikatorpuffer mit Arrays durch Verwendung der Funktion (SetIndexBuffer). Die Parameter sind:

index: zum Einstellen der Nummer des Indikatorpuffers und der Zahlen, die in unserem Programm mit 0 bis 7 beginnen.

buffer[]: zur Angabe des im nutzerdefinierten Indikator deklarierten Arrays.

data_type: zur Angabe der Art der im Indikator-Array gespeicherten Daten.

   SetIndexBuffer(0,indBuff,INDICATOR_DATA);
   SetIndexBuffer(2,momBuff,INDICATOR_CALCULATIONS);
   SetIndexBuffer(3,momSmBuff1,INDICATOR_CALCULATIONS);
   SetIndexBuffer(4,momSmBuff2,INDICATOR_CALCULATIONS);
   SetIndexBuffer(5,absMomBuff,INDICATOR_CALCULATIONS);
   SetIndexBuffer(6,absMomSmBuff1,INDICATOR_CALCULATIONS);
   SetIndexBuffer(7,absMomSmBuff2,INDICATOR_CALCULATIONS);

Um den Wert der entsprechenden Indikatoreigenschaft einzustellen, muss diese Indikatoreigenschaft (prop value) vom Typ string sein, indem die Funktion (IndicatorSetString) mit der Variante des Aufrufs verwendet wird, bei der nur der Eigenschaftsbezeichner angegeben wird. In diesem Schritt legen Sie einen Kurznamen für den Indikator fest und bestimmen die Zeiträume, die im linken oberen Teil des Indikatorfensters angezeigt werden sollen. Die Parameter:

  • prop_id: zur Angabe der Kennung der Indikatoreigenschaft, die eine aus der Enumeration (ENUM_CUSTOMIND_PROPERTY_STRING) ist. In unserem Programm wird dies (INDICATOR_SHORTNAME) sein.
  • prop_value: um den Wert der Eigenschaft anzugeben, der ein String-Datentyp sein wird. Es wird "True Strength Index ("+(string)smperiod1+", "+(string)smperiod2+")" sein.
IndicatorSetString(INDICATOR_SHORTNAME,"True Strength Index ("+(string)smperiod1+","+(string)smperiod2+")");

Einstellen eines anderen Wertes der Indikatoreigenschaft in einem ganzzahligen Datentyp, um den Wert des Indikators nach Ziffern zu normalisieren, indem die (IndicatorSetInteger) mit der Variante des Aufrufs mit Angabe des Eigenschaftsbezeichners verwendet wird. Ihre Parameter 

  • prop_id: zur Angabe der Kennung der Indikatoreigenschaft, die eine aus der Enumeration (ENUM_CUSTOMIND_PROPERTY_INTEGER) ist. In unserem Programm wird es (INDICATOR_DIGITS) sein.
  • prop_value: um den Wert der Eigenschaft anzugeben, der ein Integer-Datentyp sein wird. Es wird Digits() sein.
IndicatorSetInteger(INDICATOR_DIGITS,Digits());

Setzen des AS_SERIES-Flags für das Array mit der Funktion (ArraySetAsSeries).

   ArraySetAsSeries(indBuff,true);
   ArraySetAsSeries(momBuff,true);
   ArraySetAsSeries(momSmBuff1,true);
   ArraySetAsSeries(momSmBuff2,true);
   ArraySetAsSeries(absMomBuff,true);
   ArraySetAsSeries(absMomSmBuff1,true);
   ArraySetAsSeries(absMomSmBuff2,true);

In der Funktion OnCalculate:

  • Wir setzen das AS_SERIES-Flag für das Array der Schlusskurse aus dem OnCalculate-Teil und prüfen dann, ob rates_total kleiner als 2 ist, um 0 zurückzugeben.
  • Erstellung einer ganzzahligen Variablen (limit), die gleich (rates_total-prev_calculated) ist.
  • Prüfung, ob die Variable limit größer als 1 ist; in diesem Fall sind die folgenden Schritte erforderlich:
  • Aktualisierung von limit mit dem Ergebnis von (rates_total - 2).
  • Initialisierung von numerischen Arrays vom Typ Double mit einem voreingestellten Wert unter Verwendung der Funktion (ArrayInitialize). Ihre Parameter sind array[], um das numerische Array anzugeben, das initialisiert werden soll, und der andere Parameter ist value, um den neuen Wert anzugeben, der gesetzt werden soll.
   ArraySetAsSeries(close,true);
   if(rates_total<2)
      return 0;

   int limit=rates_total-prev_calculated;
   if(limit>1)
     {
      limit=rates_total-2;
      ArrayInitialize(indBuff,EMPTY_VALUE);
      ArrayInitialize(momBuff,0);
      ArrayInitialize(momSmBuff1,0);
      ArrayInitialize(momSmBuff2,0);
      ArrayInitialize(absMomBuff,0);
      ArrayInitialize(absMomSmBuff1,0);
      ArrayInitialize(absMomSmBuff2,0);
     }

Erstellen einer Schleife zur Aktualisierung von momBuff[i], absMomBuff[i]. Neue Funktionen, die in diesem Schritt verwendet wurden, sind:

  • (for)-Schleife mit ihren drei Ausdrücken und einem ausführbaren Operator.
  • IsStopped(), um zu prüfen, ob das mql5-Programm zwangsweise beendet wurde.
  • MathAbs, um den absoluten Wert (modulus) zurückzugeben, und wir können die Funktion fabs() für das gleiche Ergebnis verwenden.
   for(int i=limit; i>=0 && !IsStopped(); i--)
     {
      momBuff[i]=close[i]-close[i+1];
      absMomBuff[i]=MathAbs(momBuff[i]);
     }

Wir überprüfen das Folgende mit der Funktion ExponentialMAOnBuffer aus der eingebundenen Datei (MovingAverage).

   if(ExponentialMAOnBuffer(rates_total,prev_calculated,0,smperiod1,momBuff,momSmBuff1)==0)
      return 0;
   if(ExponentialMAOnBuffer(rates_total,prev_calculated,0,smperiod1,absMomBuff,absMomSmBuff1)==0)
      return 0;
   if(ExponentialMAOnBuffer(rates_total,prev_calculated,smperiod1,smperiod2,momSmBuff1,momSmBuff2)==0)
      return 0;
   if(ExponentialMAOnBuffer(rates_total,prev_calculated,smperiod1,smperiod2,absMomSmBuff1,absMomSmBuff2)==0)
      return 0;

Erstellen einer weiteren Schleife zur Aktualisierung der Variablen indBuff[i] mit Hilfe der Funktion for:

   for(int i=limit; i>=0 && !IsStopped(); i--)
      indBuff[i]=(absMomSmBuff2[i]!=0 ? 100.0*momSmBuff2[i]/absMomSmBuff2[i] : 0);

Am Ende des Programms befindet sich die Funktion return(rates_total):

   return(rates_total);

Damit haben wir den Code zur Erstellung unseres TSI-Indikators fertiggestellt. Aber Sie können Ihren Code auch nach Ihren Wünschen anpassen. Im Folgenden finden Sie den vollständigen Code in einem Block dieses erstellten Indikators:

//+------------------------------------------------------------------+
//|                                                   simple TSI.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 8
#property indicator_plots   1
#property indicator_label1  "TSI"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrBlue
#property indicator_style1  STYLE_SOLID
#property indicator_width1  3
#include <MovingAverages.mqh>
input uint     InpSmPeriod1   =  25;    // Smoothing period 1
input uint     InpSmPeriod2   =  13;   // Smoothing period 2
int            smperiod1;
int            smperiod2;
double         indBuff[];
double         momBuff[];
double         momSmBuff1[];
double         momSmBuff2[];
double         absMomBuff[];
double         absMomSmBuff1[];
double         absMomSmBuff2[];
int OnInit()
  {
   smperiod1=int(InpSmPeriod1<2 ? 2 : InpSmPeriod1);
   smperiod2=int(InpSmPeriod2<2 ? 2 : InpSmPeriod2);
   SetIndexBuffer(0,indBuff,INDICATOR_DATA);
   SetIndexBuffer(2,momBuff,INDICATOR_CALCULATIONS);
   SetIndexBuffer(3,momSmBuff1,INDICATOR_CALCULATIONS);
   SetIndexBuffer(4,momSmBuff2,INDICATOR_CALCULATIONS);
   SetIndexBuffer(5,absMomBuff,INDICATOR_CALCULATIONS);
   SetIndexBuffer(6,absMomSmBuff1,INDICATOR_CALCULATIONS);
   SetIndexBuffer(7,absMomSmBuff2,INDICATOR_CALCULATIONS);
   IndicatorSetString(INDICATOR_SHORTNAME,"True Strength Index ("+(string)smperiod1+","+(string)smperiod2+")");
   IndicatorSetInteger(INDICATOR_DIGITS,Digits());
   ArraySetAsSeries(indBuff,true);
   ArraySetAsSeries(momBuff,true);
   ArraySetAsSeries(momSmBuff1,true);
   ArraySetAsSeries(momSmBuff2,true);
   ArraySetAsSeries(absMomBuff,true);
   ArraySetAsSeries(absMomSmBuff1,true);
   ArraySetAsSeries(absMomSmBuff2,true);
   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[])
  {
   ArraySetAsSeries(close,true);
   if(rates_total<2)
      return 0;

   int limit=rates_total-prev_calculated;
   if(limit>1)
     {
      limit=rates_total-2;
      ArrayInitialize(indBuff,EMPTY_VALUE);
      ArrayInitialize(momBuff,0);
      ArrayInitialize(momSmBuff1,0);
      ArrayInitialize(momSmBuff2,0);
      ArrayInitialize(absMomBuff,0);
      ArrayInitialize(absMomSmBuff1,0);
      ArrayInitialize(absMomSmBuff2,0);
     }
   for(int i=limit; i>=0 && !IsStopped(); i--)
     {
      momBuff[i]=close[i]-close[i+1];
      absMomBuff[i]=MathAbs(momBuff[i]);
     }
   if(ExponentialMAOnBuffer(rates_total,prev_calculated,0,smperiod1,momBuff,momSmBuff1)==0)
      return 0;
   if(ExponentialMAOnBuffer(rates_total,prev_calculated,0,smperiod1,absMomBuff,absMomSmBuff1)==0)
      return 0;
   if(ExponentialMAOnBuffer(rates_total,prev_calculated,smperiod1,smperiod2,momSmBuff1,momSmBuff2)==0)
      return 0;
   if(ExponentialMAOnBuffer(rates_total,prev_calculated,smperiod1,smperiod2,absMomSmBuff1,absMomSmBuff2)==0)
      return 0;
   for(int i=limit; i>=0 && !IsStopped(); i--)
      indBuff[i]=(absMomSmBuff2[i]!=0 ? 100.0*momSmBuff2[i]/absMomSmBuff2[i] : 0);
   return(rates_total);
  }

Nach der fehlerfreien Kompilierung dieses Codes finden wir den Indikator unter den verfügbaren Indikatoren im Ordner Indicators in unserem Navigator, indem wir ihn auf das gewünschte Chart ziehen und dort ablegen. Das Fenster des Indikators und die Eingaben sind wie folgt:

simpleTSI-Eingänge Fenster

Wir haben also zwei Eingaben, die der Nutzer bestimmen kann, und die Standardwerte sind 25 für die Glättungsperiode 1 und 13 für die Glättungsperiode 2. Dennoch kann der Nutzer sie, wie bereits erwähnt, nach seinen Wünschen verändern.

simpleTSI-Farben Fenster

Wie in der vorherigen Abbildung zu sehen ist, kann der Nutzer auf der Registerkarte Farben die Farbe, die Breite und den Stil der TSI-Linie auswählen. Nachdem wir unsere Präferenzen für die Eingaben und den Stil des Indikators wie oben beschrieben festgelegt haben, können wir den Indikator wie folgt auf dem Chart finden:

 simpleTSI gestartet

Wie im vorherigen Chart zu sehen ist, befindet sich die Linie des TSI-Indikators in einem separaten Fenster unter den Kursen, und diese Linie oszilliert um Null. Und wir haben die Bezeichnung des Indikators, seine Glättungsperioden und den Wert des Indikators.


Ein nutzerdefinierter TSI-EA

In diesem Teil werden wir auf sehr einfache Weise lernen, wie wir unseren nutzerdefinierten Indikator in einem automatisierten System verwenden können, sodass er ein bestimmtes Signal oder eine Aktion erzeugen kann, sobald eine bestimmte Bedingung ausgelöst wird. Wir beginnen mit der Erstellung eines sehr einfachen Systems, indem wir einen Expert Advisor erstellen, der einen Kommentar auf dem Chart mit dem aktuellen TSI-Wert erzeugt, bevor wir einen EA entwickeln, der komplexere Anweisungen ausführt.

Im Folgenden finden Sie die Schritte, die zur Erstellung unseres Expert Advisors erforderlich sind:

  • Erstellen einer Integer-Variable von (TSI).
  • Die TSI wird mit Hilfe der iCustom-Funktion definiert, die den Handle des Indikators zurückgibt und dessen Parameter sind:
    • symbol: Zur Angabe des Symbolnamens wird _Symbol verwendet, das für das aktuelle Symbol gilt.
    • period: Zur Angabe des Zeitrahmens wird _period verwendet, der für den aktuellen Zeitrahmen gilt.
    • name: um den Pfad des nutzerdefinierten Indikators anzugeben.
  • Ausgabe des Textes "TSI System Removed" im OnDeinit(const int reason)-Teil, sobald die EA entfernt wurde.
  • Erstellen eines Arrays von tsiVal[]
  • Abrufen der Daten des Puffers des TSI-Indikators mit Hilfe der Funktion CopyBuffer mit der Variante des Aufrufs durch die erste Position und die Anzahl der erforderlichen Elemente. Die Parameter sind:
    • indicator_handle: Um den vom Indikator zurückgegebenen Indikator-Handle anzugeben, verwenden wir (TSI).
    • buffer_num: Zur Angabe der Nummer des Indikatorpuffers wird (0) verwendet.
    • start_pos: Um die Startposition für die Kopie anzugeben, verwenden wir (0).
    • count: Um die Anzahl der zu kopierenden Daten anzugeben, wird (1) verwendet.
    • buffer[]: Um das zu kopierende Array anzugeben, verwenden wir (tsiVal).
  • Mit der Funktion Comment wird der aktuelle TSI-Wert in eine Zeichenkette umgewandelt, indem die Funktion (DoubleToString) mit den Parametern value zur Angabe des aktuellen TSI-Werts und digits zur Angabe der Anzahl der Ziffern verwendet wird; wir verwenden (_Digits) für den aktuellen Wert.

Der vollständige Code sieht also wie folgt aus:

//+------------------------------------------------------------------+
//|                                           customSimpleTSI-EA.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 TSI;
int OnInit()
  {
   TSI=iCustom(_Symbol,_Period,"My Files\\TSI\\simpleTSI");
   return(INIT_SUCCEEDED);
  }
void OnDeinit(const int reason)
  {
   Print("TSI System Removed");
  }
void OnTick()
  {
   double tsiVal[];
   CopyBuffer(TSI,0,0,1,tsiVal);
   Comment("TSI Value ",DoubleToString(tsiVal[0],_Digits));
  }

Nachdem dieser Code ohne Fehlern kompiliert und dann ausgeführt wurde, wird er auf dem Chart gestartet. Nachfolgend ist ein Beispiel für ein Signal aus einem Test dargestellt:

 iCustom TSI-EA-Signal

Wie wir sehen können, haben wir einen Kommentar im oberen linken Chart mit dem aktuellen TSI-Wert. Wenn wir sicherstellen wollen, dass das Signal dasselbe ist, das wir auf der Grundlage des Indikators haben, können wir den EA anhängen und den Indikator gleichzeitig einfügen, um Werte zu erhalten. Das Folgende dient dazu, sich von unserer Arbeit zu überzeugen:

iCustom TSI-EA gestartet - gleiches Signal

Wie wir oben rechts sehen können, ist der EA angehängt und sein Signal erscheint in der oberen linken Ecke mit dem aktuellen TSI-Wert. Gleichzeitig haben wir den TSI-Indikator als separates Fenster unter den Preisen in den Chart eingefügt und sein Wert über der Linie in der linken Ecke ist derselbe wie das EA-Signal.


EA eines TSI Systems

In diesem Teil werden wir einen EA entwickeln, der auf dem erstellten TSI-Indikator basiert, um Signale zu erhalten, die auf einer bestimmten Strategie basieren. Bitte beachten Sie, dass die Strategie, die wir erörtern werden, nur für Bildungszwecke gedacht ist. Sie wird auf jeden Fall optimiert werden müssen, genau wie jede andere Strategie. Sie müssen ihn also testen, bevor Sie ihn für ein echtes Konto verwenden, um sicherzustellen, dass er für Sie nützlich ist.

Wir werden den nutzerdefinierten TSI-Indikator in Kombination mit den beiden gleitenden Durchschnitten verwenden, um Kauf- und Verkaufssignale auf der Grundlage einer bestimmten Strategie zu erhalten, die wie folgt aussieht:

Wir werden zwei einfache gleitende Durchschnitte verwenden, einen schnellen mit einer Periode von 10 und einen langsamen mit einer Periode von 20, zusätzlich zu unserem eigenen TSI-Indikator. Wenn der vorherige schnelle MA-Wert kleiner als der vorherige langsame MA-Wert ist und gleichzeitig der aktuelle schnelle MA-Wert größer als der aktuelle langsame MA-Wert ist, bedeutet dies, dass wir eine aufwärts Kreuzung der MA haben, dann prüfen wir, ob der aktuelle TSI-Wert größer als Null ist, um ein Kaufsignal als Kommentar auf dem Chart auszuweisen. Wenn der vorherige schnelle MA-Wert größer als der vorherige langsame MA-Wert ist und gleichzeitig der aktuelle schnelle MA-Wert kleiner als der aktuelle langsame MA-Wert ist, bedeutet dies, dass wir eine abwärts Kreuzung der MA haben, dann werden wir prüfen, ob der aktuelle TSI-Wert kleiner als Null ist und wir ein Verkaufssignal als Kommentar auf dem Chart ausweisen.

Einfach:

Wenn fastMA[1]<slowMA[1] && fastMA[0]>slowMA[0] && tsiVal[0]>0 ==> Kaufsignal
Wenn fastMA[1]>slowMA[1] && fastMA[0]<slowMA[0] && tsiVal[0]<0 ==> Verkaufssignal

Nachfolgend finden Sie den vollständigen Code, um diese Art von System zu erstellen:

//+------------------------------------------------------------------+
//|                                                TSI System EA.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 ENUM_MA_METHOD inpMAType = MODE_SMA; //Moving Average Type
input ENUM_APPLIED_PRICE inpPriceType = PRICE_CLOSE; //Price type
input int inpFastMAPeriod = 10; // Fast moving average period
input int inpSlowMAPeriod = 20; //Slow moving average period
int tsi;
double fastMAarray[], slowMAarray[];
int OnInit()
  {
   tsi=iCustom(_Symbol,_Period,"My Files\\TSI\\simpleTSI");
   return(INIT_SUCCEEDED);
  }
void OnDeinit(const int reason)
  {
   Print("TSI System Removed");
  }
void OnTick()
  {
   double tsiVal[];
   CopyBuffer(tsi,0,0,1,tsiVal);
   int fastMA =iMA(_Symbol,_Period,inpFastMAPeriod,0,inpMAType,inpPriceType);
   int slowMA =iMA(_Symbol,_Period,inpSlowMAPeriod,0,inpMAType,inpPriceType);
   ArraySetAsSeries(fastMAarray,true);
   ArraySetAsSeries(slowMAarray,true);
   CopyBuffer(fastMA,0,0,3,fastMAarray);
   CopyBuffer(slowMA,0,0,3,slowMAarray);
   if(fastMAarray[1]<slowMAarray[1]&&fastMAarray[0]>slowMAarray[0])
     {
      if(tsiVal[0]>0)
        {

         Comment("Buy Signal",
                 "\nTSI Value ",DoubleToString(tsiVal[0],_Digits),
                 "\nfastMA ",DoubleToString(fastMAarray[0],_Digits),
                 "\nslowMA ",DoubleToString(slowMAarray[0],_Digits));
        }
     }
   if(fastMAarray[1]>slowMAarray[1]&&fastMAarray[0]<slowMAarray[0]&&tsiVal[0]<0)
     {
      if(tsiVal[0]<0)
        {
         Comment("Sell Signal",
                 "\nTSI Value ",DoubleToString(tsiVal[0],_Digits),
                 "\nfastMA ",DoubleToString(fastMAarray[0],_Digits),
                 "\nslowMA ",DoubleToString(slowMAarray[0],_Digits));
        }
     }
  }

Unterschiede in diesem Code sind die gleichen wie die folgenden:

Legen Sie vier Nutzereingaben für den Typ des gleitenden Durchschnitts, für den angewandten Preistyp, die schnelle MA-Periode und die langsame MA-Periode an, und weisen Sie ihnen Standardwerte zu.

input ENUM_MA_METHOD inpMAType = MODE_SMA; //Moving Average Type
input ENUM_APPLIED_PRICE inpPriceType = PRICE_CLOSE; //Price type
input int inpFastMAPeriod = 10; // Fast moving average period
input int inpSlowMAPeriod = 20; //Slow moving average period

Erstellen von zwei Arrays für schnelle MA-Arrays und langsame MA.

double fastMAarray[], slowMAarray[];

Definition der beiden gleitenden Durchschnitte mit Hilfe der vordefinierten iMA-Funktion, die den Handle des gleitenden Durchschnitts zurückgibt und folgende Parameter enthält:

  • symbol: Wir verwenden _Symbol, das auf das aktuelle Symbol angewendet wird.
  • period: Wir verwenden _period für den aktuellen Zeitrahmen.
  • ma_period: Wir verwenden die Eingabe des Nutzers für die schnellen und die langsamen MAs.
  • ma_shift: Wir verwenden (0), da eine Verschiebung nicht erforderlich ist.
  • ma_method: Wir verwenden die Eingabe des Nutzers für den MA-Typ.
  • applied _price: Wir verwenden die Eingabe des Nutzers für den Preistyp.
   int fastMA =iMA(_Symbol,_Period,inpFastMAPeriod,0,inpMAType,inpPriceType);
   int slowMA =iMA(_Symbol,_Period,inpSlowMAPeriod,0,inpMAType,inpPriceType);

Setzen des Flags AS_SERIES mit Hilfe der Funktion ArraySetAsSeries für die langsamen und schnellen MAs:

   ArraySetAsSeries(fastMAarray,true);
   ArraySetAsSeries(slowMAarray,true);

Abrufen von Daten aus dem Puffer der beiden gleitenden Durchschnitte mit Hilfe der Funktion CopyBuffer:

   CopyBuffer(fastMA,0,0,3,fastMAarray);
   CopyBuffer(slowMA,0,0,3,slowMAarray);

Festlegung der Bedingungen für die Strategie:

Im Falle eines Kaufsignals:

Wenn der vorherige fastMA kleiner ist als der vorherige slowMA und der aktuelle fastMA größer ist als der aktuelle slowMA und gleichzeitig der aktuelle tsiVal größer als Null ist, muss der EA das Kaufsignal als Kommentar auf dem Chart zurückgeben, genauso wie die folgende Reihenfolge:

  • Buy Signal
  • TSI Wert
  • fastMA Wert
  • slowMA Wert
   if(fastMAarray[1]<slowMAarray[1]&&fastMAarray[0]>slowMAarray[0])
     {
      if(tsiVal[0]>0)
        {

         Comment("Buy Signal",
                 "\nTSI Value ",DoubleToString(tsiVal[0],_Digits),
                 "\nfastMA ",DoubleToString(fastMAarray[0],_Digits),
                 "\nslowMA ",DoubleToString(slowMAarray[0],_Digits));
        }
     }

Im Falle eines Verkaufssignals:

Wenn der vorherige fastMA größer ist als der vorherige slowMA und der aktuelle fastMA kleiner ist als der aktuelle slowMA und gleichzeitig der aktuelle tsiVal kleiner als Null ist, muss der EA das Verkaufssignal als Kommentar auf dem Chart ausgeben, in der folgenden Reihenfolge:

  • Sell Signal
  • TSI Wert
  • fastMA Wert
  • slowMA Wert
   if(fastMAarray[1]>slowMAarray[1]&&fastMAarray[0]<slowMAarray[0]&&tsiVal[0]<0)
     {
      if(tsiVal[0]<0)
        {
         Comment("Sell Signal",
                 "\nTSI Value ",DoubleToString(tsiVal[0],_Digits),
                 "\nfastMA ",DoubleToString(fastMAarray[0],_Digits),
                 "\nslowMA ",DoubleToString(slowMAarray[0],_Digits));
        }
     }

Nach dem fehlerfreien Kompilieren dieses Codes und dem Ziehen und Ablegen zur Ausführung, um seine Signale zu erhalten, finden wir sein Fenster wie das folgende auf der Registerkarte Eingaben:

EA eines TSI Systems Eingänge Fenster

Wie wir sehen können, haben wir die vier Eingaben des MA-Typs, des Preistyps, der schnellen MA-Periode und der langsamen MA-Periode. Nachdem wir unsere Einstellungen vorgenommen und auf OK geklickt haben, können wir feststellen, dass der EA auf dem Chart läuft und seine Signale wie die folgenden aussehen werden:

Im Falle eines Kaufsignals:

 EA eines TSI Systems - Kaufsignal

Wie wir in der vorherigen Grafik sehen können, haben wir ein Kaufsignal als Kommentar in der oberen linken Ecke gemäß unserer Strategiebedingungen, die den folgenden entsprechen:

  • Buy Signal
  • TSI Wert
  • fastMA Wert
  • slowMA Wert

Im Falle eines Verkaufssignals:

 EA eines TSI Systems - Verkaufssignal

Wie wir im vorherigen Chart sehen können, haben wir ein Verkaufssignal als Kommentar in der oberen linken Ecke gemäß unserer Strategiebedingungen. das gleiche wie das folgende:

  • Sell Signal
  • TSI Wert
  • fastMA Wert
  • slowMA Wert

Schlussfolgerung

In diesem Artikel haben wir gelernt, wie Sie Ihren eigenen technischen Indikator True Strength Index erstellen können, um Ihre spezifischen Einstellungen und Präferenzen umzusetzen. Wir haben gesehen, welche Informationen und Erkenntnisse dieser Indikator liefert, die beim Handel sehr hilfreich sein können. Wir haben auch gelernt, wie wir diesen angepassten Indikator in einem einfachen Handelssystem verwenden können, um den aktuellen Wert des TSI-Indikators als Kommentar auf dem Chart zu generieren. Wir haben auch gesehen, wie der Indikator in einem automatisierten Handelssystem verwendet werden kann, indem wir einen EA erstellt haben, der die TSI-Daten in Kombination mit einem anderen technischen Instrument, in unserem Fall dem gleitenden Durchschnitt, nutzt. Diese Kombination aus dem nutzerdefinierten TSI und zwei gleitenden Durchschnitten generiert Kauf- und Verkaufssignale, die auf einer speziellen Strategie beruhen, die wir im Thema EA eines TSI Systems im Detail betrachtet haben.

Ich hoffe, dass dieser Artikel für Ihren Handel und Ihre Programmierkenntnisse nützlich sein wird. Wenn Sie weitere Artikel über Indikatoren lesen und lernen möchten, wie man Handelssysteme auf der Grundlage der beliebtesten technischen Indikatoren erstellt, lesen Sie bitte meine früheren Artikel, in denen ich beliebte Indikatoren wie den gleitenden Durchschnitt, Bollinger Bands, RSI, MACD, Stochastik, parabolischen SAR, ATR und andere behandle.

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

Beigefügte Dateien |
simpleTSI.mq5 (7.46 KB)
iCustomTSI_ea.mq5 (0.81 KB)
TSI_System_EA.mq5 (2.09 KB)
Erstellen eines automatisch arbeitenden EA (Teil 13): Automatisierung (V) Erstellen eines automatisch arbeitenden EA (Teil 13): Automatisierung (V)
Wissen Sie, was ein Flussdiagramm ist? Können Sie es verwenden? Glauben Sie, dass Flussdiagramme etwas für Anfänger sind? Ich schlage vor, dass wir mit diesem neuen Artikel fortfahren und lernen, wie man mit Flussdiagrammen arbeitet.
Kategorientheorie in MQL5 (Teil 7): Mehrere, relative und indizierte Domänen Kategorientheorie in MQL5 (Teil 7): Mehrere, relative und indizierte Domänen
Die Kategorientheorie ist ein vielfältiger und expandierender Zweig der Mathematik, der erst seit kurzem in der MQL5-Gemeinschaft Beachtung findet. In dieser Artikelserie sollen einige der Konzepte und Axiome erforscht und untersucht werden, mit dem übergeordneten Ziel, eine offene Bibliothek einzurichten, die Einblicke gewährt und hoffentlich auch die Nutzung dieses bemerkenswerten Bereichs für die Strategieentwicklung von Händlern fördert.
Mehrschichtiges Perzeptron und Backpropagation-Algorithmus (Teil 3): Integration mit dem Strategy Tester - Überblick (I). Mehrschichtiges Perzeptron und Backpropagation-Algorithmus (Teil 3): Integration mit dem Strategy Tester - Überblick (I).
Das mehrschichtige Perzeptron ist eine Weiterentwicklung des einfachen Perzeptrons, das nichtlineare separierbare Probleme lösen kann. Zusammen mit dem Backpropagation-Algorithmus kann dieses neuronale Netz effektiv trainiert werden. In Teil 3 der Serie Multilayer Perceptron und Backpropagation werden wir sehen, wie man diese Technik in den Strategy Tester integriert. Diese Integration ermöglicht die Nutzung komplexer Datenanalysen, um bessere Entscheidungen zur Optimierung Ihrer Handelsstrategien zu treffen. In diesem Artikel werden wir die Vorteile und Probleme dieser Technik erörtern.
Rebuy-Algorithmus: Mathematisches Modell zur Effizienzsteigerung Rebuy-Algorithmus: Mathematisches Modell zur Effizienzsteigerung
In diesem Artikel werden wir den Rebuy-Algorithmus für ein tieferes Verständnis der Effizienz von Handelssystemen verwenden und uns mit den allgemeinen Grundsätzen der Verbesserung der Handelseffizienz unter Verwendung von Mathematik und Logik befassen sowie die nicht standardisierten Methoden zur Steigerung der Effizienz im Hinblick auf die Verwendung absolut beliebiger Handelssysteme anwenden.