Zeichnen von Widerstands- und Unterstützungsebenen mithilfe von MQL5

Aleksandr Teleguz | 27 Juni, 2016

Inhaltsverzeichnis

  1. Einleitung
  2. Ziel dieses Beitrags
  3. Kurze Beschreibung von früher vorgestellten Methoden zum Zeichnen von Unterstützungs- und Widerstandsebenen
  4. Prinzip des Findens von Extrema
  5. Funktion zum Finden des extremen Balkens mit dem geringsten Index (erster Balken) Ext_1
  6. Allgemeine Funktion zum Finden aller nachfolgenden Extrema Ext_2
  7. Verarbeitung der Ergebnisse
  8. Beispiel eines Indikators, der Unterstützungs- und Widerstandsebenen anzeigt
  9. Fazit

Einleitung

Zuerst möchte ich Ihnen kurz erklären, was Unterstützungs- und Widerstandslinien sind, wie sie aufgebaut werden und wie ich sie für den Handel nutze.

Alle Trendfiguren, -linien und -modelle sind Kombinationen aus Unterstützungs- und Widerstandslinien, die der klassischen Trendanalyse zugrunde liegen. Die Widerstandslinie basiert auf maximalen Preisen, die auftreten, wenn Händler ("Bullen") aufhören, eine Währung zu einem höheren Preis zu kaufen, und anfangen, offene Positionen zum Kauf zu schließen. Der Preis eines Finanzinstruments reagiert darauf mit einen Zurückfallen, bis eine ähnliche Situation unter "Bären" eintritt, d. h. die Unterstützungslinie auf Mindestpreisen aufgebaut wird.

Somit kann angenommen werden, dass Maxima entstehen, wenn eine Währung überkauft wird, und Minima, wenn sie überverkauft wird. Aus diesem Grund nutze ich zum Zeichnen von Unterstützungs- und Widerstandslinien einen Standardindikator aus dem Satz von MetaTrader: Relative Strength Index (RSI), der 1978 von John Wilder entwickelt und publiziert wurde. Dieser Indikator bestimmt überkaufte und überverkaufte Zonen einer Währung.

Ich nutze den Indikator RSI mit der Periode 8. Dieser Wert ist nicht das Ergebnis meiner Beobachtungen, sondern wurde von Eric L. Nyman in seinem Buch "The Small Trader's Encyclopedia" für alle Diagrammzeiträume außer Tages- und größeren Diagrammen empfohlen. Ich bin mit den Ergebnissen der Arbeit meines Indikators mit RSI (8) absolut zufrieden.

Es gibt zwei unterschiedliche Meinungen darüber, ob Kerzendochte bei der Suche nach maximalen und minimalen Preisen (High und Low) berücksichtigt werden sollten. Ich persönlich berücksichtige sie und vergleiche High-Preise mit Low-Preisen, wenn ich nach Extrema suche. Wenn Sie sie nicht berücksichtigen möchten, können sie einfach einige kleine Veränderungen am weiter unten vorgestellten Indikatorcode vornehmen.

Der Handel mit Unterstützungs- und Widerstandslinien kann genauso außerhalb dieser Linien stattfinden wie bei Preisschwankungen innerhalb des durch diese Linien gebildeten Bereichs.

Signal mit einem Durchbruch von Unterstützungs- und Widerstandsebenen

Abb. 1. Kaufsignal

Ich betrachte die zweite Methode als weniger wirksam, insbesondere, wenn das Zurückfallen des Preises von einer der Linien eine wichtige Rolle für das Treffen von Handelsentscheidungen spielt. In Abbildung 1 sieht man die Situation, dass der Preis nach einem Zurückfallen von der Widerstandslinie die Unterstützungslinie nicht erreicht, umkehrt und durch die Widerstandslinie bricht. Dadurch wird ein Kaufsignal stärker. Mit der Analyse der Winkel, die durch Linien gebildet werden, die die Zeitachse überkreuzen, definieren wir eine allgemeine Trendrichtung. Wenn der Preis des Finanzinstruments eine der Linien überkreuzt, ermöglicht dies einen Rückschluss bezüglich einer Stärkung oder Umkehrung des vorhandenen Trends. Häufig erreicht der Preis, bevor er beispielsweise die Unterstützungslinie überkreuzt, nur die Mitte der Unterstützungslinie (dieser Faktor verstärkt ein Handelssignal).

Ex existiert eine Plattform namens "Autochartist", die für die Erkennung von Trendfiguren und -modellen vorgesehen ist. Als Experiment habe ich zwei Monate lang auf einem Demokonto mit Signalen des Zurückfallens des Preises vom Widerstands- oder Unterstützungsniveau gehandelt. Die meisten Transaktionen wurden dabei im Gegensatz zu Handelssignalen aus Durchbruchsniveaus mit einem Verlust abgeschlossen.

Unterstützungs- und Widerstandsebenen werden ebenfalls zum Bestimmen der Beschleunigung oder Verlangsamung von Trends verwendet. Erhöht sich der Winkel einer Trendlinie in einem haussierenden Trend, bedeutet das eine Beschleunigung, deren Auftreten zu einer Fortführung des Trends führt. Andererseits bedeutet die Erhöhung des Winkels in einem baissierenden Trend, dass sich der Trend verlangsamt. Eine Unterstützungslinie (auf Basis von Low-Preisen) dient als Trendlinie bei einem haussierenden Trend und eine Widerstandslinie (auf Basis von High-Preisen) als Trendlinie bei einem baissierenden Trend.

Verlangsamung eines haussierenden Trends

Abb. 2. Verlangsamung eines haussierenden Trends

Verlangsamung eines baissierenden Trends

Abb. 3. Verlangsamung eines baissierenden Trends

Die Verlangsamung eines Trends kann auf seine zeitnahe Umkehrung hindeuten.


Ziel dieses Beitrags

Die Analyse von grafischen Figuren, die durch Unterstützungs- und Widerstandslinien geformt werden, ist eine der ältesten Methoden der technischen Analyse. Aus eigener Erfahrung auf dem Devisenmarkt kann ich festhalten, dass diese Methode nicht nur alt ist, sondern auch wirksam. Ich glaube, dass sie von vielen Händlern genutzt wird. Der manuelle Aufbau von Unterstützungs- und Widerstandslinien mit dem MetaTrader 5 Terminal ist eine einfache Aufgabe für jeden Händler, der über etwas theoretisches Wissen verfügt. Doch das gilt nicht für die Erstellung eines Programms, das diese Linien automatisch zeichnet.

In diesem Beitrag möchte ich meine eigene Methode zum Zeichnen von Unterstützungs- und Widerstandslinien vorstellen, die sowohl in MQL5 als auch in MQL4 umgesetzt werden kann. Ich hoffe, dass Sie diese Informationen nützlich finden werden.


Kurze Beschreibung von früher vorgestellten Methoden zum Zeichnen von Unterstützungs- und Widerstandsebenen

Gebote für Währungspaare befinden sich die meiste Zeit über innerhalb der Unterstützungs- und Widerstandslinien. Diese Tatsache liegt dem Beitrag von Gleb Slobodow zum Zeichnen dieser Linien zugrunde. Somit haben wir zwei horizontale Ebenen, die einen Bereich von Preisschwankungen definieren. Der Durchbruch einer dieser Linien gibt uns vermutlich ein Signal zum Kaufen oder Verkaufen. Allerdings hat das vorgestellte Prinzip einige Nachteile:

  • Die Anzahl der zu analysierenden Balken wird manuell festgelegt. Dieser Parameter definiert einen Preisbereich und somit den Wert von Unterstützungs- und Widerstandsebenen.
  • Der Prozess zum Zeichnen der Ebenen ist nicht vollautomatisiert und bietet somit nicht die Möglichkeit, ein automatisiertes Handelssystem zu erstellen.
  • Mithilfe dieser Methode erhalten wir horizontale Ebenen, die uns nicht die Analyse der Richtung und Stärke des Trends ermöglichen.

Der in Igor Geraskos Handelsstrategie verwendete Indikator von Unterstützungs- und Widerstandsebenen definiert ebenfalls horizontale Ebenen.

In diesem Beitrag möchte ich Ihnen ein Prinzip des Zeichnens von Unterstützungs- und Widerstandslinien vorstellen, das die Bestimmung der Trendrichtung und die Entstehung von Trendmodellen und -figuren ermöglicht. Die Linien werden basierend auf absoluten Minima und Maxima gezeichnet.


Prinzip des Findens von Extrema

Die Bestimmung von Maximal- und Minimalpreisen in einem bestimmten Zeitraum ist kein Problem. Es ist wichtig, die Länge des zu analysierenden Diagrammabschnitts (Zeitintervall) richtig zu wählen, die sich ständig ändert und somit nicht manuell festgelegt werden kann. Um diesen Abschnitt des Währungsdiagramms zu finden, nutze ich den Indikator Relative Strength Index (RSI), der im Standard-Indikatorensatz des MetaTrader 5 Terminals enthalten ist.

Überkaufte und überverkaufte Ebenen werden gemäß den Ebenen des RSI-Indikators bestimmt. Zu diesen Zeitpunkten weicht das Diagramm unserer Währungspaare von seiner Richtung (seinem Trend) ab und erzeugt ein Zurückfallen des Preises. Extrema werden insbesondere hier geformt. In diesen Lücken suchen wir nach den Minimal- und Maximalpreisen.

Als überverkaufte Ebene nehme ich den Wert 35 des RSI-Indikators, als überkaufte Ebene 65 (die obere und untere Ebene sind von der Mitte des RSI = 50 gleich weit entfernt). Der Zeitraum des RSI-Indikators entspricht 8.

Beachten Sie, dass während eines starken Trends, beispielsweise eines steigenden Trends, der RSI häufig mehrfach die obere Ebene überkreuzt, die untere allerdings nicht erreicht. Dies macht eine Anpassung der Ebene erforderlich, die nicht der Trendrichtung entspricht.

Suche der Extrema

Abb. 4. Suchbereiche für Extrema

In der obigen Abbildung habe ich einen Suchbereich für Balken mit Extrema bestimmt – jeweils des ersten, zweiten, dritten und vierten mit den Zahlen 1, 2, 3, und 4. Vor der Überkreuzung einer Untergrenze (RSI = 35) wird der RSI-Indikator ab dem aktuellen Balken dreimal im überkauften Bereich (RSI >= 65) eingefügt. Somit entstehen drei Zeitintervalle für die Suche nach dem ersten Extremum. Im weiteren Verlauf werden nacheinander Suchzonen für drei aufeinanderfolgende Balken bestimmt.

In den Zonen 1 und 3 suche ich nach Balken mit den höchsten Preisen und in den Zonen 2 und 4 Balken mit den niedrigsten Preisen. Somit erhalten wir 4 Extrema. Indem wir sie mit Strahlen kombinieren, erhalten wir den aufsteigenden Preiskanal.

Abb. 5. Aufsteigender Kanal

Abb. 5 Aufsteigender Kanal

Vermutlich ist ihnen aufgefallen, dass an der Suche nach den Mindestpreisen nur 4 Balken (2 je Zone) beteiligt waren. Aufgrund des vorherrschenden Aufwärtstrends hat der RSI-Indikator das Minimum kaum berührt, während der Indikator sich fast genauso lange außerhalb von RSI = 65 befand wie innerhalb des Kanals 35 < RSI < 65. Deshalb wird der Indikatorcode, den ich in diesem Beitrag zum Finden der Punkte 2 und 4 vorgestellt habe, die zur Mitte (in Richtung 50) verschobene RSI-Ebene nutzen. Je nachdem, was das erste Extremum war (Minimum oder Maximum), wird eine hohe oder niedrige RSI-Ebene festgelegt.

Alle Währungspaare und alle Zeiträume des Diagramms der RSI-Werte und des Werts der nachfolgenden Abweichung werden experimentell ausgewählt. Ich betrachte dies als Nachteil meines Systems zum Bestimmen von Extrema.


Funktion zum Finden des extremen Balkens mit dem geringsten Index (erster Balken) Ext_1

Die Funktion zum Finden von extremen Balken, die ich "Ext_1" genannt habe, hat die folgenden Eingabeparameter:

int Ext_1(double low,      //low RSI level, oversold level
          double high,     //high RSI level, overbought level
          int bars,        //number of analyzed bars, to avoid copying unnecessary data
                           //possible to set bars = 300
          int h_rsi,       //handle of RSI indicator
          string symbol,   //symbol of chart
          float distans,   //distance for deviation of one of indicator levels
                           //allows to define search boundaries of first extremum bar
          ENUM_TIMEFRAMES period_trade) //period of chart

Die ersten beiden Eingabeparameter der Funktion sind die Parameter des RSI-Indikators. Sie spielen bei der Berechnung der Indikatorlinie keine Rolle und werden nur für eine praktische optische Bewertung der Werte verwendet (Lage der Indikatorlinie in Bezug auf die angegebenen Ebenen). Ich nutze diese Ebenen zum Bestimmen von Preisbereichen, unter denen ich nach den Minimal- und Maximalwerten suchen werde. Die Parameter "low" und "high" erhalten Werte von entsprechenden externen Variablen, die im Indikatorcode auf globaler Ebene eingegeben wurden:

input double Low_RSI = 35.0; // Low RSI level for finding extremum
input double High_RSI= 65.0; // High RSI level for finding extremum

Der Eingabeparameter "bars" legt die Anzahl der Elemente fest, die in die Arrays kopiert werden, die die Preise "Low" und "High" der Balken sowie die Werte des RSI-Indikators beinhalten:

double m_rsi[],m_high[],m_low[];                              //initialization of arrays
int h_high = CopyHigh(symbol, period_trade, 0, bars, m_high); //fill array of high candle prices
int h_low = CopyLow(symbol, period_trade, 0, bars, m_low);    //fill array of low candle prices
if(CopyBuffer(h_rsi, 0, 0, bars, m_rsi)<bars)                 //fill array with indicator RSI data
{
   Print("Failed to copy indicator buffer!");
}

Die Arrays m_rsi[], m_high[] und m_low[] haben eine umgekehrte Indexierungsreihenfolge:

ArraySetAsSeries(m_rsi,true); 
ArraySetAsSeries(m_high,true); 
ArraySetAsSeries(m_low,true);

Wie ich bereits erwähnt habe, nimmt die Linie des RSI-Indikators, die einen Wertebereich von 0 bis 100 hat, bei einem vorherrschenden haussierenden Trend meistens einen Wert > 50 an. Wenn Minima geformt werden, liegt der RSI-Wert weiter vom Mittelpunkt (50) entfernt als bei der Entstehung des Maximums. Deshalb muss bei der Überkreuzung eines der Indikatorwerte (low oder high) ein anderer Wert näher an den Mittelpunkt verschoben werden. Die Höhe der Abweichung wird durch den Eingabeparameter "distans" bestimmt, der den Wert einer externen Variable erhält:

input float Distans=13.0;    // Deviation of RSI level

Der Eingabeparameter "h_rsi" der Funktion "Ext_1" erhält den Wert des RSI-Handles, der aus der Initialisierung des Indikators mithilfe der Funktion iRSI() entsteht:

h_RSI=iRSI(Trade_Symbol,Period_Trade,Period_RSI,PRICE_CLOSE);  //return handle of RSI indicator

Die Variablen Trade_Symbol und Period_Trade werden auf globaler Ebene initialisiert und enthalten Informationen über das Währungspaar bzw. den Zeitraum des Diagramms. Die Variable Period_RSI enthält den Wert des Zeitraums des Indikators RSI, der in den externen Parametern meines Indikators festgelegt ist:

input uchar Period_RSI =8;   // RSI period

Sobald wir die Arrays mit den Preisen der High- und Low-Balken sowie den Wert des Indikators RSI gemäß diesen Balken erzeugt und befüllt haben, können wir mit der tatsächlichen Suche nach dem ersten Extremum fortfahren. Um zu bestimmen, wo sich die ersten Extrema befinden (Unterstützungs- oder Widerstandslinie), und um die Analyse der Balken zum richtigen Zeitpunkt anzuhalten, werden zwei Variablen des Typen bool benötigt:

bool ext_max = true;    //bool type variables are used to stop
bool ext_min = true;    //bar analysis at the right time

Der Wert ext_max = true ermöglicht die Suche nach dem maximalen Extremum, der Wert ext_min = true dementsprechend die Suche nach dem minimalen Extremum. Bei der ersten Überkreuzung des RSI-Indikators durch eine der Ebenen (low oder high) ändert sich der Wert einer der bool-Variablen zu false. Die Überkreuzung der RSI-Ebene, für die die Analyse der Balken deaktiviert ist, bedeutet, dass die erforderliche Anzahl von Balken analysiert und das erste Extremum gefunden wurde. 

Wenn der Wert des RSI-Indikators bei der Analyse des ersten Balkens außerhalb einer seiner Ebenen liegt, ist es wahrscheinlich, dass die Formierung des Preisbereichs, in dem das Extremum gesucht werden soll, noch nicht abgeschlossen ist. In diesem Fall ist es nicht zielführend, ihn zu analysieren. Die Analyse solcher Balken sollte ausgeschlossen werden. In der nachfolgenden Abbildung habe ich den Preisbereich gekennzeichnet, in dem keine Analyse durchgeführt wird (beachten Sie die Position der Linie des RSI-Indikators in Relation zur oberen Ebene):

Deaktivieren der Analyse im unvollständigen Preisbereich

Abb. 6. Deaktivieren der Analyse im unvollständigen Preisbereich

Zur Umsetzung dieser Vorgehensweise muss eine weitere Variable des Typen bool erstellt werden:

bool flag=false;

Um Höchst- und Mindestpreise unter den zu analysierenden Balken zu bestimmen, müssen die folgenden zusätzlichen Variablen des Typen double erstellt werden:

double min = 100000.0;  //variables to identify maximum and minimum prices
double max = 0.0;       //...

Die gesamte Schleife für die Suche nach dem Balken mit dem ersten Extremum sieht so aus:

for(int i=0;i<bars;i++) //bar loop
{
   double rsi = m_rsi[i];                                   //get RSI indicator value
   double price_max = NormalizeDouble(m_high[i], digits);   //High prices
   double price_min = NormalizeDouble(m_low[i], digits);    //Low prices of selected bar
   if(flag==false) //condition to avoid searching for extremum on incomplete trend
   {
      if(rsi<=low||rsi>=high) //if first bars in overbought zones or oversold zones,
         continue;            //then move to next bar
      else flag = true;       //if not, proceed with analysis  
   }
   if(rsi<low) //if found crossing of RSI with low level
   {
      if(ext_min==true) //if RSI hasn't crossed high level
      {
        if(ext_max==true) //if searching for maximum extremum hasn't been disabled
        {
           ext_max=false;     //then disable searching for maximum extremum
           if(distans>=0) high=high-distans; //change high level, on which then
        }                                    //second bar search will be executed
        if(price_min<min) //search and memorise first bar index
        {                 //comparing Low candle prices
           min=price_min;
           index_bar=i;
        }
      }
      else break; /*Exit loop since searching for minimum extremum is already disabled,
                    it means the maximum is found*/
   }
   if(rsi>high) //further, algorithm is the same, only in search for maximum extremum
   {
      if(ext_max==true)
      {
        if(ext_min==true)
        {
           ext_min=false;
           if(distans>=0) low=low+distans;
        }
        if(price_max>max)
        {
           max=price_max;
           index_bar=i;
        }
      }
      else break; /*Exit loop since searching for maximum extremum is disabled,
                    it means the minimum is found*/
   }
}

Allgemeine Funktion zum Finden aller nachfolgenden Extrema Ext_2

Diese Funktion erhält die gleichen Eingabeparameter wie die Funktion Ext_1 sowie drei weitere wichtige Parameter:

  1. Den Parameter, der einen Verweis zur Struktur enthält, in der die Indizes der extremen Balken gespeichert werden. Es muss bestimmt werden, ab welchem Balkenindex die Suche nach dem Extremum beginnt.
  2. Die Seriennummer des zu findenden extremen Balkens (nimmt einen Wert zwischen 2 und 4 an). Sie wird benötigt, um den Index des gewünschten Balkens aus der Struktur zu bestimmen und um festzulegen, auf welcher Linie (Unterstützung oder Widerstand) sich das gewünschte Extremum befinden soll.
  3. Den Parameter des Typen bool, der bestimmt, auf welcher Linie (Unterstützung oder Widerstand) sich der erste extreme Balken befinden soll. Ohne diese Information ist es unmöglich, anhand der Seriennummer zu bestimmen, auf welcher Linie sich der gewünschte Balken befinden soll.
int Ext_2(double low,    //low RSI level, oversold level
          double high,   //high RSI level, overbought level
          int bars,      //number of analyzed bars, to avoid copying unnecessary data into arrays
          int h_rsi,     //handle of RSI indicator
          string symbol, //symbol of chart
          st_Bars &bars_ext,//structure containing codes of found bars
          char n_bar,    //ordinal number of bar required to find (2,3 or 4)
          float distans, //distance for deviation of one of indicator levels
          bool first_ext,//type of first bar
          ENUM_TIMEFRAMES period_trade)//period of chart

Auf globaler Ebene erstellen wir einen Strukturtyp, der die Indizes aller 4 extremen Balken beinhalten wird:

struct st_Bars //structure initialization
  {
   int               Bar_1;
   int               Bar_2;
   int               Bar_3;
   int               Bar_4;
  };

st_Bars Bars_Ext; //declaration of structure type variable

Um die Indikatorlinie zu bestimmen, auf der sich das gewünschte Extremum befinden soll, müssen zuerst zwei Variablen des Typen bool erstellt werden:

bool high_level= false; //variables to determine type of desired bar
bool low_level = false; //...

Wenn die Ordnungszahl des gewünschten extremen Balkens 2 oder 4 ist und der erste extreme Balken auf der Unterstützungslinie liegt, muss der gewünschte Balken auf der Widerstandslinie liegen. Deshalb müssen Balken analysiert werden, deren RSI-Wert größer oder gleich der oberen Ebene (Parameter high) ist. Wenn die Ordnungszahl des gewünschten extremen Balkens 3 ist und der erste extreme Balken sich auf der Unterstützungslinie befindet, wird sich der gewünschte Balken ebenfalls auf dieser Linie befinden. Wenn der erste extreme Balken auf der Widerstandslinie liegt, wird die Position des gewünschten Balkens entsprechend gewählt.

if(n_bar!=3)
{
   if(first_ext==true)//if first point was maximum
   {
      low_level=true;//then this should be minimum
      if(distans>=0) low=low+distans; //if necessary, displace low level of RSI
   }
   else //if minimum
   {
      high_level = true;
      if(distans>=0) high=high-distans; //if necessary, displace high level of RSI
   }
}
else
{
   if(first_ext==false)//if first point was minimum
   {
      low_level=true;//then this point has to be minimum
      if(distans>=0) high=high-distans; //if necessary, displace high level of RSI
   }
   else //if maximum
   {
      high_level = true;
      if(distans>=0) low=low+distans; //if necessary, displace low level of RSI
   }
}

Eine weitere Variable des Typen bool wird benötigt, um den Zeitpunkt zu bestimmen, wenn das gewünschte Extremum gefunden wurde und die Analyse der Balken angehalten werden kann.

bool _start = false;    

Der Wert dieser Variable ändert sich zu true, wenn wir in der Historie den zu analysierenden Balkenbereich finden. Die Analyse der Balken wird beendet, wenn _start = true. Wenn low_level = true, überkreuzt die RSI-Indikatorlinie die Ebene high. Wenn high_level = true, überkreuzt die RSI-Indikatorlinie die Ebene low.

if(_start==true && ((low_level==true && rsi>=high) || (high_level==true && rsi<=low)))
  break; //exit loop if second extremum is found, and RSI crossed opposite level

Die Schleife für die Suche nach extremen Balken sieht so aus:

for(int i=bar_1;i<bars;i++) //analyze remaining bars
{
   rsi=m_rsi[i];
   price_max = NormalizeDouble(m_high[i], digits);
   price_min = NormalizeDouble(m_low[i], digits);
   if(_start==true && ((low_level==true && rsi>=high) || (high_level==true && rsi<=low)))
   {
      break; //exit loop if second extremum is found, and RSI crossed opposite level
   }
   if(low_level==true) //if looking for minimum extremum
   {
      if(rsi<=low)
      {
         if(_start==false) _start=true;
         if(price_min<min)
         {
            min=price_min;
            index_bar=i;
         }
      }
   }
   else //if looking for maximum extremum
   {
      if(rsi>=high)
      {
         if(_start==false) _start=true;
         if(price_max>=max)
         {
            max=price_max;
            index_bar=i;
         }
      }
   }
}

Die Variable Bar_1 enthält den Index des vorherigen extremen Balkens, der mithilfe des Operators switch berechnet wird:

switch(n_bar) //find index of previous bar
{
   case 2: bar_1 = bars_ext.Bar_1; break;
   case 3: bar_1 = bars_ext.Bar_2; break;
   case 4: bar_1 = bars_ext.Bar_3; break;
}

Um herauszufinden, auf welcher Indikatorlinie (Unterstützung oder Widerstand) sich der erste extreme Balken befindet, genügt es, seinen Index und den Wert des RSI-Indikators auf dem Balken mit dem erhaltenen Index abzurufen:

bool One_ext (st_Bars & bars_ext, // variable of structure type to obtain first bar index
             string symbol,     //symbol of chart
             int h_rsi,         //handle of indicator
             double low,        //set oversold level of RSI (high level can be used)
             ENUM_TIMEFRAMES period_trade) //period of chart
  {
   double m_rsi[];               //array initialization of indicator data
   ArraySetAsSeries(m_rsi,true); //indexing
   CopyBuffer(h_rsi,0,0,bars_ext.Bar_1+1,m_rsi); //fill array with RSI data
   double rsi=m_rsi[bars_ext.Bar_1]; //define RSI value on bar with first extremum
   if(rsi<=low)                      //if value is below low level,
      return(false);                 //then first extremum is minimum
   else                              //if not,
   return(true);                     //then maximum
  }

Verarbeitung der Ergebnisse

Wir kennen nun die Indizes aller vier Balken und ihre entsprechenden Preise (low oder high). Um die Arrays zu befüllen, die dem Wert der Indikatorlinien auf jedem Balken entsprechen, werden die Gleichungen von zwei Linien benötigt, die den Unterstützungs- und Widerstandslinien entsprechen. Die wohlbekannte Liniengleichung, die zu diesem Zweck genutzt wird, lautet: y = kx + b. In unserem Fall ist "x" der Index eines Balkens und "y" ein Preis (Preis der low-Kerze für die Unterstützungslinie, Preis der high-Kerze für die Widerstandslinie).

Um die Werte der Koeffizienten "k" und "b" zu finden, genügt es, die entsprechenden Werte von zwei bekannten extremen Balken in der Liniengleichung zu ersetzen und die erhaltenen Ausdrücke im Gleichungssystem zu kombinieren. Als Ergebnis erhalten wie die folgenden Ausdrücke im System:

K=(price_2-price_1)/(_bar2-_bar1);  //find coefficient K
B=price_1-K*_bar1;                  //find coefficient B

mit

double K,B;

"K" und "B" sind globale Variablen, die den Werten der Koeffizienten "k" und "b" in der Liniengleichung entsprechen;

int _bar1,_bar2;

Dies sind Indizes von Balken, die sich auf der gleichen Linie befinden;

double price_1,price_2;

Dies sind die low-Preise der entsprechenden Balken, wenn es erforderlich ist, "K" und "B" für die Unterstützungslinie zu definieren, oder die high-Preise der entsprechenden Balken, wenn es erforderlich ist, "K" und "B" für die Widerstandslinie zu bestimmen.

Die unten dargelegte Funktion legt die Werte der globalen Variablen "K" und "B" für die Unterstützungslinie fest, wenn der Parameter "_line" false ist, und für die Widerstandslinie, wenn der Parameter "_line" true ist:

void Level(bool _line,              //parameter that defines resistance/support line, which coefficients have to be found
           bool _first_ext,         //type of first extremum (already familiar to you)
           st_Bars &bars_ext,       //structure that contains bar indexes
           string _symbol,          //symbol
           ENUM_TIMEFRAMES _period) //period of chart
  {
   int bars=Bars_H;           //number of analyzed bars
   double m_high[],m_low[];         //initialization of arrays
   ArraySetAsSeries(m_high,true);   //arrays are indexed from first element
   ArraySetAsSeries(m_low,true);    //...
   int h_high = CopyHigh(_symbol, _period, 0, bars, m_high); //fill array of High candle price
   int h_low = CopyLow(_symbol, _period, 0, bars, m_low);    //fill array of Low candle price
   double price_1,price_2;
   int _bar1,_bar2;
   int digits=(int)SymbolInfoInteger(_symbol,SYMBOL_DIGITS);//number of decimal places in current symbol
   if(_line==true)                                          //if resistance line is required
     {
      if(_first_ext==true) //if first extremum is maximum
        {
         price_1 = NormalizeDouble(m_high[bars_ext.Bar_1], digits);
         price_2 = NormalizeDouble(m_high[bars_ext.Bar_3], digits);
         _bar1 = bars_ext.Bar_1;
         _bar2 = bars_ext.Bar_3;
        }
      else                                                  //if minimum
        {
         price_1 = NormalizeDouble(m_high[bars_ext.Bar_2], digits);
         price_2 = NormalizeDouble(m_high[bars_ext.Bar_4], digits);
         _bar1 = bars_ext.Bar_2;
         _bar2 = bars_ext.Bar_4;
        }
     }
   else                                                     //if support line is required
     {
      if(_first_ext==true) //if first extremum is maximum
        {
         price_1 = NormalizeDouble(m_low[bars_ext.Bar_2], digits);
         price_2 = NormalizeDouble(m_low[bars_ext.Bar_4], digits);
         _bar1 = bars_ext.Bar_2;
         _bar2 = bars_ext.Bar_4;
        }
      else                                                  //if minimum
        {
         price_1 = NormalizeDouble(m_low[bars_ext.Bar_1], digits);
         price_2 = NormalizeDouble(m_low[bars_ext.Bar_3], digits);
         _bar1 = bars_ext.Bar_1;
         _bar2 = bars_ext.Bar_3;
        }
     }
   K=(price_2-price_1)/(_bar2-_bar1);  //find coefficient K
   B=price_1-K*_bar1;                  //find coefficient B
  }

Die Liniengleichung lautet: y = kx + b. Dabei wird der Preis des Finanzinstruments für die Achse "y" und der Index des Balkens für die Achse "x" verwendet. Wenn wir für die Achse "x" die Anzahl der Sekunden seit dem 1. Januar 1970 nutzen, sehen die Ergebnisse des Liniendiagramms im Wochenendbereich chaotisch aus. Aus diesem Grund habe ich die Indizes der Balken verwendet.

Aus der Funktion "OnCalculate" wird die Funktion "Level" zweimal aufgerufen: einmal vor dem Befüllen des Arrays für die Widerstandslinie und einmal zum Befüllen des Arrays für die Unterstützungslinie mit Preiswerten:

for(int i=0;i<Bars_H;i++)
{
   resistanceBuffer[i]=NormalizeDouble(K*i+B,Dig);
}
Level(false,First_Ext,Bars_Ext,Trade_Symbol,Period_Trade); //get coefficients K и B for resistance line 
for(int i=0;i<Bars_H;i++)
{
   supportBuffer[i]=NormalizeDouble(K*i+B,Dig);
}

Beispiel eines Indikators, der Unterstützungs- und Widerstandsebenen anzeigt

Das Resultat der Ausführung des Indikators, der alle oben aufgeführten Funktionen nutzt und die Unterstützungs- und Widerstandslinien zeichnet, sieht so aus:

Resultat der Ausführung des Indikators

Abb. 7. Resultat der Ausführung des Indikators

Der Indikator ist so konstruiert, dass die Werte von Arrays der Unterstützungs- und Widerstandslinien nach dem Entstehen eines neuen extremen Balkens geändert werden können und die Ebenen automatisch neu gezeichnet werden. Wenn wir allerdings den Winkel berechnen und speichern, den eine dieser Linien mit der Zeitachse des Diagramms bildet, und diesen dann mit dem neuen Winkel der gleichen Linie vergleichen, ist es möglich, einen Rückschluss über eine Beschleunigung oder Verlangsamung des Trends zu ziehen, wie es in diesem Beitrag bereits erwähnt wurde.

Der vollständige Code des Indikators befindet sich in der an diesen Beitrag angehängten Datei.


Fazit

Natürlich ist es viel einfacher, diese Linien manuell zu konstruieren, da man so nicht die Parameter des Indikators für jedes Symbol und jeden Zeitraum auswählen muss. Allerdings dient dieser Indikator als Basis oder Bestandteil der Strategie, die dem automatischen Handelssystem zugrunde liegt. Nach dem Erhalt eines Daten-Arrays von Indikatorlinien können Sie den Neigungswinkel und die Richtung des Trends analysieren und die durch diese Linien geformte grafische Form identifizieren. All das macht es letztendlich möglich, die Stärke eines Kauf- oder Verkaufssignals zu analysieren und sowohl innerhalb des Preiskanals als auch beim Durchbruch von Unterstützungs- und Widerstandslinien zu handeln.