Trendlinien Indikator unter Berücksichtigung von T. Demarks Ansatz

Genkov | 9 März, 2016

Einführung

Der Kampf zwischen Käufern (Bullen) und Verkäufern (Bären) kann anhand von Trendlinien dargestellt werden. Thomas Demark entwickelte die Methoden zur objektiven Auswahl zweier Punkte der TD-Linie für die Trend-Zeichnung (Sie finden detaillierte Informationen über T. Demarks Ansatz zur technischen Analyse hier).

Weil, nach T. Demark, das Wichtigste für einen Trader der letzte Zustand des Marktes ist, ist in der vorgeschlagenen Version des Indikators die letzte Trendrichtung mit einer dicken durchgehenden Linie eingezeichnet, und es ist nicht ungewöhnlich für die Ananlyse des aktuellen Zustands die nächstgelegene vorherige Trendrichtung zu kennen, die mit einer dünnen gepunkteten Linie eingezeichnet ist.


Einige Merkmale in dem MQL4 Code des vorgeschlagenen Indikators

In dem Indikator werden vier Puffer verwendet. Zwei Puffer sind für Pfeile der Linienrichtung und zwei von ihnen sind für die Verlängerung der TD-Linie zur linken Seite.

Die ersten zehn Balken (zur linken des zweiten TD-Punkts) werden durch die Puffer des Indikators in der Farbe «Aqua» gezeichnet.

#property indicator_chart_window
#property indicator_buffers 4
#property indicator_color1 Chartreuse
#property indicator_color2 Tomato
#property indicator_color3 Aqua
#property indicator_color4 Aqua
 
// ----- indicator_buffers
double   TrendUpBuffer[];
double   TrendDownBuffer[];
double   TrendLineBufferUp[];
double   TrendLineBufferDown[];

Initialisierung der Funktionen, welche die Berechnung und die Indikator-Visualisierung steuern.

int init()
  {
//---- indicators
   SetIndexStyle(0,DRAW_ARROW);        // the type and the style of the indicator line
   SetIndexArrow(0,236);               // the icon for the indicator line
   SetIndexBuffer(0,TrendUpBuffer);    // the declaration of the unidimensional array
   SetIndexEmptyValue(0,0.0);          // the size of the empty value of the indicator
   SetIndexStyle(1,DRAW_ARROW);
   SetIndexArrow(1,238);
   SetIndexBuffer(1,TrendDownBuffer);
   SetIndexEmptyValue(1,0.0);
   SetIndexStyle(2,DRAW_LINE);         
   SetIndexBuffer(2,TrendLineBufferUp);    // for the rising line
   SetIndexEmptyValue(2,0.0);           
   SetIndexStyle(3,DRAW_LINE);
   SetIndexBuffer(3,TrendLineBufferDown);  // for the descending line
   SetIndexEmptyValue(3,0.0);
//----
   return(0);

Die De-Initialisierung kann standardmäßig leer gelassen werden.

int deinit()
  {
  //  DelObj1();  
  //  DelObj2();
  return(0);
  }

Erstellen Sie die Funktion zum Löschen des Objekts mit dem angegebenen Namen.

void DelObj1()
  {
  ObjectDelete("TrDdown"); // Deleting of the object with the specified name. 
  }
  void DelObj2()
  {
  ObjectDelete("TrDup");
  }

Wir werden nach den Kontrollpunkten (der Einfachheit halber) in separaten Zyklen für Hochs und Tiefs suchen. Wir beginnen die Suche ab dem zweiten Balken, weil wir ihn mit dem rechten (nicht-Null) Balken vergleichen müssen, um die Wahrheit der Trendlinie zu klären.

Prüfen wir Bedingung #1 (der Kurs des Max. Balken muss höher sein als die Kurse des rechten und des linken Balken).

for(int i=2;i<48;i++) // 48 hours - 2 days  // i- index of the bar to be verified
    {
     if(High[i]>High[i+1]&&High[i]>High[i-1]) 
      {

Nun prüfen wir Bedingung #2 (das unterstützende Kurs-Maximum muss höher sein als der Schlusskurs über zwei Balken vor der Registrierung).

Fällt die Erfüllung der Bedingungen #1 und #2 zusammen, platzieren wir den Zähler der Übereinstimmungen.

if(High[i]>Close[i+2])  
       { 
        U++; // the counter of matches of the 1st and the 2nd conditions
        if(U==1)
         {

Dann durchlaufen wir die Registrierung nach-Spitzen der ersten Kontrollpunkt-Parameter:

// The price of the First check point when the conditions #1 and #2 are fulfilled
         TD_up[1]=High[i];  
         index_up_1=i;                               // the index of the First check point
         Pr_up_Cl_1=Close[i-1]; // the close price of the bar that follows the check point
         time_up_1=iTime(NULL,0,index_up_1);          // the time of the first check point

Hier können wir den folgenden Verifizierungscode zur Steuerung der Programmausführung eingeben:

// this is an easy-to-follow time to control the operators processing
         Time_up_1=TimeToStr(time_up_1,TIME_DATE|TIME_MINUTES); 
         Print("  Up price of First check point = ",TD_up[1],"  ;  index = ",
               index_up_1,"  time = ",Time_up_1);

Hat der Zähler einmal ausgelöst, entdecken wir den zweiten Punkt in den weiteren Iterationen und gehen zur Registrierung nach-Spitzen der zweiten Kontrollpunkt-Parameter.

          }  
          if(U==2)
           { 
           // The price of the Second check point when the conditions #1 and #2 are fulfilled
           TD_up[2]=High[i]; 
           index_up_2=i;            // the index of the Second check point
           time_up_2=iTime(NULL,0,index_up_2);// the time of the Second check point

Hier können wir den folgenden Verifizierungscode zur Steuerung der Programmausführung eingeben:

Time_up_2=TimeToStr(time_up_2,TIME_DATE|TIME_MINUTES); 
           Print("  Up price of Second check point = ",TD_up[2],"  ;  index = ",
                 index_up_2,"  time = ",Time_up_2);

Wir haben jetzt zwei TD-Kontrollpunkte, und wir müssen die Bedingung des Abwärtstrends prüfen, das heißt, der Kurs des ersten Kontrollpunkts muss geringer sein als der des zweiten Kontrollpunkts.

// the condition of the downtrend (the right TD-point must be lower than the left one)
           if((U==2 && TD_up[1]<TD_up[2])==false) 
             {  
              Print(" Up the conditions of the downtrend are not fulfilled "); 
              U--; TD_up[2]=0.0; index_up_2=0; time_up_2=0;  continue; 
              }

Ist die Bedingung nicht erfüllt, verringern wir den Zähler um eins und nullen die Werte von Kurs, Index, Zeit und kehren zurück zum Anfang des Zyklus, um einen anderen zweiten Kontrollpunkt zu suchen. Ist die Bedingung erfüllt, berechnen wir die Geschwindigkeit der fallenden TD-Linie

else
             { 
              Print(" Up the conditions of the downtrend are fulfilled ");
              // the calculation of the speed of TD_max falling by two discovered points
              V_up=(TD_up[2]-TD_up[1])/(index_up_2-index_up_1);//speed(pips/bar)
              // the calculated value of TD-line on the first bars which is to the right of Max
              Pr_Tr_up_1=TD_up[1]-V_up;
              // if we subtract the product of speed of TD-line falling times number of bars
              // from the price of the 1-st check point, we'll obtain the price of the 
              Pr_Tr_up_0=TD_up[1]-(index_up_1*V_up);           // downtrend on the "0" bar

Jetzt prüfen wir Bedingung #3 (für das letzte unterstützende Kurs-Maximum muss der Schlusskurs für den nächsten Balken (auf der rechten Seite) niedriger sein, als der berechnete Wert der Geschwindigkeit der fallenden Trendlinie) - es ist die Bedingung der Bestätigung des Abwärtstrends.

// let's check the condition #3 (for the last supporting price maximum the close
              // price for the next (to the right) bar must be lower than the calculated
              // value of the speed of TD-line falling)
              if((Pr_up_Cl_1< Pr_Tr_up_1)==false)
               {
                Print(" Up The condition of verity of downtrend is not fulfilled!");
                i=index_up_1+2; TD_up[1]=0.0; TD_up[2]=0.0; time_up_1=0; 
                time_up_2=0; index_up_1=50; index_up_2=50; U=0; continue;
                }

Ist die Bedingung #3 zur Bestätigung des Abwärtstrends nicht erfüllt, muss die Suche nach TD-Punkten wieder beginnen. Dazu ist es notwendig die Werte aller vorher erhaltenen Variablen zu nullen und die Suche von dem Balken zu beginnen, der um 2 Balken von dem ersten ermittelten Wert des ersten Kontrollpunkts nach links liegt.

Ist die Bedingung erfüllt, behalten wir die Werte der berechneten Variablen zum Zeichnen der Trendlinie.

else
               { // if the condition #3 is fulffiled, the trend is true
               Print("  Up the conditions of Downtrend verity are fulfilled ");
               // memorize the values of variables for drawing the TD_Down line
                TDu1=TD_up[1];  // price of the 1-st point
                T_u1=time_up_1; // time of the 1-st point
                TDu2=TD_up[2];  // price of the 2-nd point
                T_u2=time_up_2; // price of the 2-nd point
                TrendDownBuffer[index_up_1]=TDu1+5*Point;// put the down arrow

Jetzt füllen wir den Puffer mit 10 Werten der Trendlinie, links von dem zweiten Kontrollpunkt:

// prices of 10 bars of the trend line to the left of TD-point
                for(int k=index_up_2;k<index_up_2+10;k++) 
                TrendLineBufferDown[k]=Pr_Tr_up_0+k*V_up;
                Print("  exit from the cycle of searching, because 2 TD-points are found");   
                break;      
                }

Fügen Sie die fehlenden geschweiften Klammern ein.

               } 
              } 
             }  
            } 
//==================================================================================+

Ist die Bedingung zur Bestätigung erfüllt, wird die Trendlinie links des zweiten Kontrollpunkts für 10 Balken gezeichnet. Nun soll diese Linie nach rechts gezogen werden, mit der Funktion ObjectCreate(). Zu diesem Zweck ist am Ende des Programms ein Block zum Ziehen von Trendlinien enthalten.

In diesem Block steuern die ersten zwei Operatoren die Dicke der TD-Linie (STYLE_SOLID), einschließlich der einzigen Trendlinie in dieser Phase. Wir ziehen die abfallende Linie und verlassen den Zyklus der Suche nach Spitzen für TD-Punkte, löschen vorläufig die zuvor existierende Linie.

Mit der oben erwähnten Argumentation schreiben wir den Code für die steigende Linie.

//==================================================================================+
   // for Min points (troughs)   
   for(int j=2;j<48;j++) // 48 hours - 2 days  // j- index of the bar to be checked
    { 
     // let's check the conditon #1 (the price of the bar must be lower than the prices of the left and the right bars) 
     if(Low[j]<Low[j+1]&&Low[j]<Low[j-1])
      {
       // let's check the condition #2 (The supporting price Minimum must be lower than
       // the close price of the bar beyond two bars before the registration <to the left of Min>)
       if(Low[j]<Close[j+2])
        { 
         D++;  // the counter of coincidences of the 1-st and the 2-nd conditions
         if(D==1)
          { 
           TD_down[1]=Low[j]; 
           index_down_1=j;
           Pr_down_Cl_1=Close[j-1]; 
           time_down_1=iTime(NULL,0,j);
           
           Time_down_1=TimeToStr(time_down_1,TIME_DATE|TIME_MINUTES);            
           Print(" D price of the First check point ",TD_down[1]," ; index ",index_down_1,
           " ; Close to the right ",Pr_down_Cl_1,"  ; ",Time_down_1);           
           } 
           if(D==2)
            { 
             TD_down[2]=Low[j]; 
             index_down_2=j; 
             time_down_2=iTime(NULL,0,j);
             
             Time_down_2=TimeToStr(time_down_2,TIME_DATE|TIME_MINUTES);
             Print(" D price of the Second check point ",TD_down[2]," index ",index_down_2,
                   "  time ",Time_down_2);             
             // the condition of the rising trend (the right Min point must be higher than the left one)
             if((D==2 && TD_down[1]>TD_down[2])==false)
              {
                 Print(" D The conditions of the Rising trend are not fulfilled! "); 
                 D--;   TD_down[2]=0.0;  continue; 
                 } 
                else 
            { 
             Print(" D the conditions of the Rising trend are fulfilled");            
             // the calculation of the speed of TD_min rising by two discovered points
             V_down=(TD_down[1]-TD_down[2])/(index_down_2-index_down_1);
             // the calculated value of the line on the 1-st bar to the right of Min
             Pr_Tr_down_1=TD_down[1]+V_down;
             } 
             // let's check the condition #3 (for the last (to the right) price minimum,
             // the close price of the next bar must be higher than the calculated value
             // of the speed of TD-line rising).
             if((Pr_down_Cl_1> Pr_Tr_down_1)==false)
              {
                i=index_down_1+1; TD_down[1]=0.0; TD_down[2]=0.0; time_down_1=0; 
                time_down_2=0; index_down_1=50; index_down_2=50; D=0; continue;
                }
             else
              { // the condition #3 is fulfilled, the trend is true
               Print("  D the conditions of Rising trend verity are fulfilled ");
               TDd1=TD_down[1]; 
               T_d1=time_down_1; 
               TDd2=TD_down[2];  
               T_d2=time_down_2;
               // the calculated price of the trend line on the "0" bar
               Pr_Tr_down_0=TD_down[1]+(index_down_1*V_down); 
               TrendUpBuffer[index_down_1]=TDd2-2*Point; // put the up arrow
               // the price of 10 bars of the trend line to the right of the Second check point
               for(int n=index_down_2;n<index_down_2+10;n++)
                TrendLineBufferUp[n]=Pr_Tr_down_0-n*V_down;
               Print("  D exit the cycle of searching, because two TD-points are found ");
               break;                   
               } 
              } 
             } 
            } 
           } 
          }
// ----------------------------------------------------------------------------+ 

Der Block zum Ziehen von Trendlinien ist entwickelt, also wird die jüngste TD-Linie mit einer fetten durchgezogenen Linie gezeichnet (STYLE_SOLID), und die Linie die vor ihr liegt, aber in der entgegengesetzten Richtung, wird als gepunktete Linie gezogen (STYLE_DOT).

Es kann die Situation auftreten, in der ein Trend über eine lange Zeit in eine Richtung läuft. Daraufhin wird der zweite TD-Punkt des gegenläufigen Trends nicht ermittelt und die Zwischenwerte des Kurses, Zeit und Index, werden in die Variablen geschrieben. Damit diese Zwischenwerte nicht das Ziehen der Trendlinie beeinflussen, müssen Sie den Filter für Bedingungen zum Ziehen von Linien einfügen: Zum Beispiel, wenn die zweite TD-Linie nicht ermittelt wird, wird der Wert des Kurses auf "0" gesetzt, gleichzeitig wird der Wert Index des ersten Punkts festgelegt, und wenn dieser Wert kleiner als der Wert des ersten TD-Punkt der Linie der Gegenrichtung erscheint, dann hat die letzte Trendlinie die wahr (true) Parameter und kann mit anderem Stil und Farbe gezeichnet werden. Aus diesem Grund wird der Zeitfilter angegeben. Werfen Sie einen Blick in die angehängte Datei.

// ----------------------------------------------------------------------------+
// the drawing of the trend lines to the right of the Second check point
// ----------------------------------------------------------------------------+
    if(TDd2==0.0)   index_down_1=50;
    if(TDu2==0.0)   index_up_1=50;
     else
    {    
    Print("  TDd2 = ",TDd2,"   index_up_1 = ",index_up_1,"  >  index_down_1 = ",index_down_1);
     Print("  Up We draw the Descending one and exit from the cycle of searching the peaks for the TD-points");
       DelObj1(); // preliminary deleting the previously existed line
        ObjectCreate("TrDdown",OBJ_TREND,0,T_u2,TDu2,T_u1,TDu1); 
     if(index_up_1>index_down_1) 
      {           // the previous direction of the trend is drawn with:
       ObjectSet("TrDdown",OBJPROP_COLOR,Yellow);
       ObjectSet("TrDdown",OBJPROP_WIDTH,1);  // thin line and 
       ObjectSet("TrDdown",OBJPROP_STYLE,STYLE_DOT);// dotted line
       }
      else
       {                // the very last direction of the trend is drawn with:
        ObjectSet("TrDdown",OBJPROP_COLOR,Yellow);
        ObjectSet("TrDdown",OBJPROP_WIDTH,2);           // thicker line
        ObjectSet("TrDdown",OBJPROP_STYLE,STYLE_SOLID); // solid line
       }
      }
// -----------------------------
 
     if(TDd2==0.0)   index_down_1=50;
      else
      {
    Print("  TDd1 = ",TDd1,"   index_up_1 = ",index_up_1,"  <  index_down_1 = ",index_down_1);
      Print("  D We draw the Rising one and exit from the cycle of searching the troughs for TD-points");
        DelObj2(); // preliminary deleting the previously existed line
         ObjectCreate("TrDup",OBJ_TREND,0,T_d2,TDd2,T_d1,TDd1); 
       if(index_up_1<index_down_1)
        {   
 
         ObjectSet("TrDup",OBJPROP_COLOR,Yellow); 
         ObjectSet("TrDup",OBJPROP_WIDTH,1); 
        ObjectSet("TrDup",OBJPROP_STYLE,STYLE_DOT);
        }
         else
          {
          ObjectSet("TrDup",OBJPROP_COLOR,Yellow); 
          ObjectSet("TrDup",OBJPROP_WIDTH,2);  
          ObjectSet("TrDup",OBJPROP_STYLE,STYLE_SOLID);
          }
         }
// ----------------------------------------------------------------------------+
   return(0);
  }

Anmerkung: Nahezu alle Operatoren "Print(...)" dienen der visuellen Steuerung der Programmausführung, also können "kommentiert" werden, die Operatoren des String (TimeToStr()) Typ sind ebenfalls für die Steuerung notwendig.


Fazit

Ich hoffe, der vorgeschlagene Indikator kann nicht nur von Trading-Lehrlingen verwendet werden, sondern auch von den Erfahrenen, für das Trading an den Märkten und für die Analyse der ausgeführten Einsätze.