MetaTrader 5 herunterladen

Der letzte Kreuzzug

29 April 2016, 15:41
Roman Zamozhnyy
0
232

Einleitung

Im MetaTrader 5 Terminal (sowie in MetaTrader 4) gibt es drei Standardmittel zur Darstellung von Instrumentpreisen: Balken, Kerzen und Linien. Im Wesentlichen stellen alle drei das Gleiche dar – Zeitdiagramme. Zusätzlich zur herkömmlichen Methode der zeitlichen Darstellung des Preises gibt es auch andere, nicht mit der Zeit verbundene Mittel, die bei Investoren und Spekulanten ziemlich beliebt sind: Renko- und Kagi-Diagramme, Three-Line-Break- und Punkt- und Zeichendiagramme.

Ich werde ihre Vorteile gegenüber den Klassikern nicht erörtern, doch die Entfernung der Zeitvariable aus der Gesamtrechnung hilft einigen Händlern dabei, sich auf die Preisvariable zu konzentrieren. Ich schlage vor, dass wir Punkt- und Zeichendiagramme zusammen mit einem entsprechenden Algorithmus zum Zeichnen von Diagrammen betrachten, auf dem Markt weit verbreitete Produkte ansehen, die zur Erzeugung solcher Diagramme vorgesehen sind, und ein einfaches Script schreiben, in dem der Algorithmus umgesetzt wird. Das Buch "Point and Figure Charting: The Essential Application for Forecasting and Tracking Market Prices" von Thomas J. Dorsey dient uns als ABC.

Bull's-Eye Broker ist das beliebteste Softwarepaket für das Zeichnen von Offline-Diagrammen. Die Software steht für einen 21-tägigen Test zur Verfügung (es sind zahlreiche Tests möglich) und während der Beta-Periode ist die neue Beta-Version verfügbar. Dieses Softwarepaket wird verwendet, um die Ausführungsergebnisse unseres Scripts zu bewerten. Eine der besten Online-Ressourcen in puncto Punkt- und Zeichendiagramme ist StockCharts. Die Webseite ist börsenorientiert, deshalb gibt sie leider keine Preise von Forex-Instrumenten an.

Zum Vergleich der Ausführungsergebnisse des von uns geschriebenen Scripts werden Futures für Gold, und leichtes Rohöl und Diagramme für S&P-500-Differenzkontrakte mithilfe der Software und der Webseite erzeugt. Ein EURUSD-Preisdiagramm wird nur mithilfe von Bull's-Eye Broker gezeichnet (denken Sie an die Beschränkungen von StockChart).


Algorithmus für das Zeichnen von Punkt- und Zeichendiagrammen

Hier ist also der Algorithmus.

Für das Zeichnen von Punkt- und Zeichendiagrammen gibt es zwei zentrale Parameter:

  1. Box-Größe, die Mindeständerung des Instrumentpreises; Änderungen, die unter der Mindestpreisänderung liegen, wirken sich nicht auf das Diagramm aus;
  2. Umkehr, die Anzahl der Boxen, die die Preisbewegung in entgegengesetzter Richtung zur aktuellen Richtung des Diagramms darstellen, woraufhin diese Bewegung in der neuen Spalte angezeigt wird.

Da die Zeichnung von Diagrammen die Historie der in Form von Open-High-Low-Close-Preisen gespeicherten Gebote benötigt, nehmen wir Folgendes an:

  1. Das Diagramm wird basierend auf High-Low-Preisen gezeichnet;
  2. Der High-Preis wird auf die Box-Größe abgerundet (MathFloor), der Low-Preis wird auf die Box-Größe aufgerundet (MathCeil).

Lassen Sie es mich anhand eines Beispiels erklären. Nehmen wir an, wir wollen ein Diagramm für leichtes Rohöl mit einer Box-Größe gleich 1 (ein) $ und einer Box-Umkehr von 3 (drei) zeichnen. Das bedeutet, dass alle High-Preise auf den nächstniedrigeren 1 $ abgerundet und alle Low-Preise auf die gleiche Weise aufgerundet werden:

Datum High Low XO High XO Low
13.02.2012 100,86 99,08 100 100
14.02.2012 101,83 100,28 101 101
15.02.2012 102,53 100,62 102 101
16.02.2012 102,68 100,84 102 101
17.02.2012 103,95 102,24 103 102


X (Kreuze) werden zum Illustrieren einer Aufwärtsbewegung des Preises im Diagramm verwendet, O (Kreise) stellen eine Abwärtsbewegung des Preises dar.

Bestimmung der ursprünglichen Richtung des Preises (ob die erste Spalte X oder O ist):

Merken Sie sich die Werte XO High und XO Low von [Bars-1] und warten Sie bis:

  • der Wert XO Low um die Umkehrmenge der Boxen im Vergleich zum ursprünglichen XO High sinkt (die erste Spalte ist O); oder
  • der Wert XO High um die Umkehrmenge der Boxen im Vergleich zum ursprünglichen XO Low steigt (die erste Spalte ist X).

In unserem Beispiel mit leichtem Rohöl müssen wir uns merken: XO High[Bars-1]=100 und XO Low [Bars-1]=100.

Warten Sie weiter, um zu sehen, was vorher geschieht:

  • Der Wert XO Low[i] des nächsten Balkens wird kleiner oder gleich 97 $, was darauf hindeutet, dass die erste Spalte O ist; oder
  • Der Wert XO High[i] des nächsten Balkens wird größer oder gleich 103 $, was darauf hindeutet, dass die erste Spalte X ist.

Wir können die erste Spalte am 17. Februar bestimmen: Der Preis XO High hat 103 $ erreicht und die erste Spalte ist X. Stellen Sie sie durch vier X von 100$ bis 103 $ dar.

Bestimmung der weiteren Bewegungen des Diagramms:

Falls die aktuelle Spalte X ist, prüfen Sie, ob XO High des aktuellen Balkens im Vergleich zum aktuellen Preis XO um die Box-Größe gestiegen ist (d. h. wir prüfen am 20. Februar zuerst, ob XO High größer oder gleich 104 $ ist). Falls XO High[2012.02.20] 104 $ oder 105 $ oder größer ist, fügen wir die entsprechende Menge von X zur bestehenden Spalte aus X hinzu.

Falls XO High des aktuellen Balkens im Vergleich zum aktuellen Preis XO nicht um die Box-Größe gestiegen ist, prüfen Sie, ob XO Low des aktuellen Balkens um die Umkehrmenge der Boxen kleiner als XO High ist (in unserem Beispiel: Falls XO Low[2012.02.20] kleiner oder gleich 103 $ -3*1 $=100 $ ist oder 99 $ oder weniger). Falls er kleiner ist, zeichnen wir eine Spalte von O rechts neben der Spalte von X von 102 $ bis 100 $.

Falls die aktuelle Spalte O ist, gelten alle oben aufgeführten Überlegungen in umgekehrter Reihenfolge.

WICHTIG: Jede neue Spalte von O wird immer rechts und eine Box unterhalb vom High-Wert der vorhergehenden Spalte von X gezeichnet und jede neue Spalte von X wird immer rechts und eine Box oberhalb vom Low-Wert der vorhergehenden Spalte von O gezeichnet.

Die Prinzipien der Diagrammzeichnung sind nun klar. Fahren wir mit den Unterstützungs- und Widerstandslinien fort.

Unterstützungs- und Widerstandslinien in konventionellen Punkt- und Zeichendiagrammen haben immer einen Winkel von 45 Grad.

Die erste Linie hängt von der ersten Spalte ab. Falls die erste Spalte X ist, so ist die erste Linie eine Widerstandslinie, die eine Box über dem Maximalwert der ersten Spalte beginnt und um 45 Grad nach UNTEN und rechts geneigt ist. Falls die erste Spalte O ist, so ist die erste Linie eine Unterstützungslinie, die eine Box unter dem Minimalwert der ersten Spalte beginnt und um 45 Grad nach OBEN und rechts geneigt ist. Unterstützungs- und Widerstandslinien werden gezeichnet, bis sie das Preisdiagramm erreichen.

Sobald die Unterstützungs-/Widerstandslinie das Preisdiagramm erreicht, beginnen wir mit der Zeichnung einer entsprechenden Widerstands-/Unterstützungslinie. Das Schlüsselprinzip beim Zeichnen ist es, sicherzustellen, dass die gezeichnete Linie sich weiter rechts von der vorhergehenden Trendlinie im Diagramm befindet. Um also eine Unterstützungslinie zu zeichnen, identifizieren wir zuerst den Mindestwert des Diagramms unter der soeben gezeichneten Widerstandslinie und zeichnen die Unterstützungslinie ab einem Ausgangspunkt eine Box unterhalb des identifizierten Minimums nach OBEN und rechts, bis sie das Diagramm oder die letzte Spalte des Diagramms erreicht.

Falls die Unterstützungslinie, die ab dem Minimum unter der vorhergehenden Widerstandslinie beginnt, nach oben geht und unter derselben Widerstandslinie auf das Diagramm stößt, bewegen Sie sich nach rechts und finden Sie ein neues Preisminimum innerhalb des Bereichs zwischen dem niedrigsten Minimum unter der Widerstandslinie und dem Ende der Widerstandslinie. Fahren Sie fort, bis die so gezeichnete Trendlinie nach rechts hinter die vorhergehende Trendlinie verläuft.

Alle oben aufgeführten Überlegungen werden klarer sein, wenn sie anhand von realen Diagrammbeispielen erklärt werden, die weiter unten dargelegt sind.

Jetzt haben wir den Algorithmus für die Diagrammzeichnung geklärt. Erweitern wir unser Script um einige praktische Funktionen:

  • Modusauswahl: Diagrammzeichnung nur für ein aktuelles Symbol oder für alle Symbole in MarketWatch;
  • Timeframe-Auswahl (es erscheint logischer, Diagramme von 100 Pips auf Daily-Timeframes und Diagramme von 1-3 Pips auf M1 zu zeichnen);
  • Festlegen der Box-Größe in Pips;
  • Festlegen der Menge der Boxen für die Umkehrung;
  • Festlegen der Menge der Zeichen für die Darstellung von Volumina (Tick-Volumina im Script, da ich noch auf keine Broker gestoßen bin, die reale Volumina anbieten) in Spalten und Zeilen (wie der Indikator MarketDepth);
  • Festlegen der Tiefe der Historie, auf deren Basis das Diagramm gezeichnet wird;
  • Auswahl des Ausgabeformats – die Ergebnisse lassen sich als Text- oder Grafikdateien speichern;
  • Und zu guter Letzt eine Funktion für Neueinsteiger: automatische Diagrammzeichnung (Autocharting, legt die Box-Größe automatisch auf Basis der erforderlichen Höhe des Diagramms fest).

Da der Algorithmus nun beschrieben wurde und die Anforderungen klar sind, ist es höchste Zeit, das Script vorzustellen.

//+------------------------------------------------------------------+
//|                                         Point&Figure text charts |
//|                                        BSD Lic. 2012, Roman Rich |
//|                                           http://www.FXRays.info |
//+------------------------------------------------------------------+
#property               copyright "Roman Rich"
#property               link      "http://www.FXRays.info"
#property               version   "1.00"
#property               script_show_inputs
#include                "cIntBMP.mqh"                                       // Include the file containing cIntBMP class

input bool              mw=true;                                    // All MarketWatch?
input ENUM_TIMEFRAMES   tf=PERIOD_M1;                                 // Time frame
input long              box=2;                                      // Box size in pips (0 - auto)
enum                    cChoice{c10=10,c25=25,c50=50,c100=100};
input cChoice           count=c50;                                 // Chart height in boxes for autocharting
enum                    rChoice{Two=2,Three,Four,Five,Six,Seven};
input rChoice           reverse=Five;                              // Number of boxes for reversal
enum                    vChoice{v10=10,v25=25,v50=50};
input vChoice           vd=v10;                                    // Characters for displaying volumes
enum                    dChoice{Little=15000,Middle=50000,Many=100000,Extremely=1000000};
input dChoice           depth=Little;                              // History depth
input bool              pic=true;                                   // Image file?
input int               cellsize=10;                                // Cell size in pixels
//+------------------------------------------------------------------+
//| cIntBMP class descendant                                          |
//+------------------------------------------------------------------+
class cIntBMPEx : public cIntBMP
  {
public:
   void              Rectangle(int aX1,int aY1,int aSizeX,int aSizeY,int aColor);
   void              Bar(int aX1,int aY1,int aSizeX,int aSizeY,int aColor);
   void              LineH(int aX1,int aY1,int aSizeX,int aColor);
   void              LineV(int aX1,int aY1,int aSizeY,int aColor);
   void              DrawBar(int aX1,int aY1,int aX2,int aY2,int aColor);
   void              TypeTextV(int aX,int aY,string aText,int aColor);
  };
cIntBMPEx bmp;    // cIntBMPEx class instance
uchar Mask_O[192]= // The naughts
  {
   217,210,241,111,87,201,124,102,206,165,150,221,237,234,248,255,255,255,255,255,255,255,255,255,
   73,42,187,137,117,211,201,192,235,140,120,212,60,27,182,178,165,226,255,255,255,255,255,255,
   40,3,174,250,249,253,255,255,255,255,255,255,229,225,245,83,54,190,152,135,216,255,255,255,
   68,36,185,229,225,245,255,255,255,255,255,255,255,255,255,247,246,252,78,48,188,201,192,235,
   140,120,212,145,126,214,255,255,255,255,255,255,255,255,255,255,255,255,188,177,230,124,102,206,
   237,234,248,58,24,181,209,201,238,255,255,255,255,255,255,255,255,255,168,153,222,124,102,206,
   255,255,255,199,189,234,63,30,183,186,174,229,247,246,252,204,195,236,60,27,182,204,195,236,
   255,255,255,255,255,255,232,228,246,117,93,203,52,18,179,83,54,190,196,186,233,255,255,255
  };
uchar Mask_X[192]= // The crosses
  {
   254,252,252,189,51,51,236,195,195,255,255,255,255,255,255,235,192,192,248,234,234,255,255,255,
   255,255,255,202,90,90,184,33,33,251,243,243,212,120,120,173,0,0,173,0,0,255,255,255,
   255,255,255,254,252,252,195,69,69,192,60,60,178,15,15,233,186,186,253,249,249,255,255,255,
   255,255,255,255,255,255,241,210,210,173,0,0,209,111,111,255,255,255,255,255,255,255,255,255,
   255,255,255,255,255,255,205,99,99,192,60,60,181,24,24,241,210,210,255,255,255,255,255,255,
   255,255,255,249,237,237,176,9,9,241,213,213,226,165,165,189,51,51,254,252,252,255,255,255,
   255,255,255,230,177,177,185,36,36,255,255,255,255,255,255,189,51,51,222,153,153,255,255,255,
   255,255,255,240,207,207,200,84,84,255,255,255,255,255,255,227,168,168,211,117,117,255,255,255
  };
//+------------------------------------------------------------------+
//| Instrument selection                                                |
//+------------------------------------------------------------------+
void OnStart()
  {
   int    mwSymb;
   string symb;
   int    height=0,width=0;
   string pnfArray[];
   if(mw==true)
     {
      mwSymb=0;
      while(mwSymb<SymbolsTotal(true))
        {
         symb=SymbolName(mwSymb,true);
         ArrayFree(pnfArray);
         ArrayResize(pnfArray,0,0);
         PNF(symb,pnfArray,height,width,pic,cellsize);
         pnf2file(symb,pnfArray,0,height);
         mwSymb++;
        };
     }
   else
     {
      symb=Symbol();
      ArrayFree(pnfArray);
      ArrayResize(pnfArray,0,0);
      PNF(symb,pnfArray,height,width,pic,cellsize);
      pnf2file(symb,pnfArray,0,height);
     };
   Alert("Ok.");
  }
//+------------------------------------------------------------------+
//| Chart calculation and drawing                      |
//+------------------------------------------------------------------+
void PNF(string sName,      // instrument
         string& array[],  // array for the output
         int& y,           // array height
         int& z,           // array width
         bool toPic,       // if true-output and draw
         int cs)           // set the cell size for drawing
  {
   string      s,ps;
   datetime    d[];
   double      o[],h[],l[],c[];
   long        v[];
   uchar       matrix[];
   long        VolByPrice[],VolByCol[],HVolumeMax,VVolumeMax;
   int         tMin[],tMax[];
   datetime    DateByCol[];
   MqlDateTime bMDT,eMDT;
   string      strDBC[];
   uchar       pnf='.';
   int         sd;
   int         b,i,j,k=0,m=0;
   int         GlobalMin,GlobalMax,StartMin,StartMax,CurMin,CurMax,RevMin,RevMax,ContMin,ContMax;
   int         height,width,beg=0,end=0;
   double      dBox,price;
   int         thBeg=1,thEnd=2,tv=0;
   uchar       trend='.';
// --------------------------------- BMP -----------------------------------------
   int RowVolWidth=10*cs;
//--- shift for prices
   int startX=5*cs;
   int yshift=cs*7;
// --------------------------------- BMP -----------------------------------------
   if(SymbolInfoInteger(sName,SYMBOL_DIGITS)<=3) sd=2; else sd=4;
   b=MathMin(Bars(sName,tf),depth);
   ArrayFree(d);
   ArrayFree(o);
   ArrayFree(h);
   ArrayFree(l);
   ArrayFree(c);
   ArrayFree(v);
   ArrayFree(matrix);
   ArrayFree(VolByPrice);
   ArrayFree(VolByCol);
   ArrayFree(DateByCol);
   ArrayFree(tMin);
   ArrayFree(tMax);
   ArrayResize(d,b,0);
   ArrayResize(o,b,0);
   ArrayResize(h,b,0);
   ArrayResize(l,b,0);
   ArrayResize(c,b,0);
   ArrayResize(v,b,0);
   ArrayInitialize(d,NULL);
   ArrayInitialize(o,NULL);
   ArrayInitialize(h,NULL);
   ArrayInitialize(l,NULL);
   ArrayInitialize(c,NULL);
   ArrayInitialize(v,NULL);
   CopyTime(sName,tf,0,b,d);
   CopyOpen(sName,tf,0,b,o);
   CopyHigh(sName,tf,0,b,h);
   CopyLow(sName,tf,0,b,l);
   CopyClose(sName,tf,0,b,c);
   CopyTickVolume(sName,tf,0,b,v);
   if(box!=0)
     {
      dBox=box/MathPow(10.0,(double)sd);
     }
   else
     {
      dBox=MathNorm((h[ArrayMaximum(h,0,WHOLE_ARRAY)]-l[ArrayMinimum(l,0,WHOLE_ARRAY)])/count,
                      1/MathPow(10.0,(double)sd),true)/MathPow(10.0,(double)sd);
     };
   GlobalMin=MathNorm(l[ArrayMinimum(l,0,WHOLE_ARRAY)],dBox,true)-(int)(reverse);
   GlobalMax=MathNorm(h[ArrayMaximum(h,0,WHOLE_ARRAY)],dBox,false)+(int)(reverse);
   StartMin=MathNorm(l[0],dBox,true);
   StartMax=MathNorm(h[0],dBox,false);
   ContMin=(int)(StartMin-1);
   ContMax=(int)(StartMax+1);
   RevMin=(int)(StartMax-reverse);
   RevMax=(int)(StartMin+reverse);
   height=(int)(GlobalMax-GlobalMin);
   width=1;
   ArrayResize(matrix,height*width,0);
   ArrayInitialize(matrix,'.');
   ArrayResize(VolByPrice,height,0);
   ArrayInitialize(VolByPrice,0);
   ArrayResize(VolByCol,width,0);
   ArrayInitialize(VolByCol,0);
   ArrayResize(DateByCol,width,0);
   ArrayInitialize(DateByCol,D'01.01.1971');
   ArrayResize(tMin,width,0);
   ArrayInitialize(tMin,0);
   ArrayResize(tMax,width,0);
   ArrayInitialize(tMax,0);
   for(i=1;i<b;i++)
     {
      CurMin=MathNorm(l[i],dBox,true);
      CurMax=MathNorm(h[i],dBox,false);
      switch(pnf)
        {
         case '.':
           {
            if(CurMax>=RevMax)
              {
               pnf='X';
               ContMax=(int)(CurMax+1);
               RevMin=(int)(CurMax-reverse);
               beg=(int)(StartMin-GlobalMin-1);
               end=(int)(CurMax-GlobalMin-1);
               SetMatrix(matrix,beg,end,height,(int)(width-1),pnf);
               SetVector(VolByPrice,beg,end,v[i]);
               VolByCol[width-1]=VolByCol[width-1]+v[i];
               DateByCol[width-1]=d[i];
               trend='D';
               break;
              };
            if(CurMin<=RevMin)
              {
               pnf='O';
               ContMin=(int)(CurMin-1);
               RevMax=(int)(CurMin+reverse);
               beg=(int)(CurMin-GlobalMin-1);
               end=(int)(StartMax-GlobalMin-1);
               SetMatrix(matrix,beg,end,height,(int)(width-1),pnf);
               SetVector(VolByPrice,beg,end,v[i]);
               VolByCol[width-1]=VolByCol[width-1]+v[i];
               DateByCol[width-1]=d[i];
               trend='U';
               break;
              };
            break;
           };
         case 'X':
           {
            if(CurMax>=ContMax)
              {
               pnf='X';
               ContMax=(int)(CurMax+1);
               RevMin=(int)(CurMax-reverse);
               end=(int)(CurMax-GlobalMin-1);
               SetMatrix(matrix,beg,end,height,(int)(width-1),pnf);
               SetVector(VolByPrice,beg,end,v[i]);
               VolByCol[width-1]=VolByCol[width-1]+v[i];
               DateByCol[width-1]=d[i];
               break;
              };
            if(CurMin<=RevMin)
              {
               pnf='O';
               ContMin=(int)(CurMin-1);
               RevMax=(int)(CurMin+reverse);
               tMin[width-1]=beg-1;
               tMax[width-1]=end+1;
               beg=(int)(CurMin-GlobalMin-1);
               end--;
               width++;
               ArrayResize(matrix,height*width,0);
               ArrayResize(VolByCol,width,0);
               ArrayResize(DateByCol,width,0);
               ArrayResize(tMin,width,0);
               ArrayResize(tMax,width,0);
               SetMatrix(matrix,0,(int)(height-1),height,(int)(width-1),'.');
               SetMatrix(matrix,beg,end,height,(int)(width-1),pnf);
               SetVector(VolByPrice,beg,end,v[i]);
               VolByCol[width-1]=0;
               VolByCol[width-1]=VolByCol[width-1]+v[i];
               DateByCol[width-1]=d[i];
               tMin[width-1]=beg-1;
               tMax[width-1]=end+1;
               break;
              };
            break;
           };
         case 'O':
           {
            if(CurMin<=ContMin)
              {
               pnf='O';
               ContMin=(int)(CurMin-1);
               RevMax=(int)(CurMin+reverse);
               beg=(int)(CurMin-GlobalMin-1);
               SetMatrix(matrix,beg,end,height,(int)(width-1),pnf);
               SetVector(VolByPrice,beg,end,v[i]);
               VolByCol[width-1]=VolByCol[width-1]+v[i];
               DateByCol[width-1]=d[i];
               break;
              };
            if(CurMax>=RevMax)
              {
               pnf='X';
               ContMax=(int)(CurMax+1);
               RevMin=(int)(CurMax-reverse);
               tMin[width-1]=beg-1;
               tMax[width-1]=end+1;
               beg++;
               end=(int)(CurMax-GlobalMin-1);
               width++;
               ArrayResize(matrix,height*width,0);
               ArrayResize(VolByCol,width,0);
               ArrayResize(DateByCol,width,0);
               ArrayResize(tMin,width,0);
               ArrayResize(tMax,width,0);
               SetMatrix(matrix,0,(int)(height-1),height,(int)(width-1),'.');
               SetMatrix(matrix,beg,end,height,(int)(width-1),pnf);
               SetVector(VolByPrice,beg,end,v[i]);
               VolByCol[width-1]=0;
               VolByCol[width-1]=VolByCol[width-1]+v[i];
               DateByCol[width-1]=d[i];
               tMin[width-1]=beg-1;
               tMax[width-1]=end+1;
               break;
              };
            break;
           };
        };
     };
//--- credits
   s="BSD License, 2012, FXRays.info by Roman Rich";
   k++;
   ArrayResize(array,k,0);
   array[k-1]=s;
   s=SymbolInfoString(sName,SYMBOL_DESCRIPTION)+",
                      Box-"+DoubleToString(box,0)+",Reverse-"+DoubleToString(reverse,0);
   k++;
   ArrayResize(array,k,0);
   array[k-1]=s;
// --------------------------------- BMP -----------------------------------------
   if(toPic==true)
     {
      //-- BMP image size on the chart display
      int XSize=cs*width+2*startX+RowVolWidth;
      int YSize=cs*height+yshift+70;
      //-- creating a bmp image sized XSize x YSize with the background color clrWhite
      bmp.Create(XSize,YSize,clrWhite);
      //-- displaying cells of the main field
      for(i=height-1;i>=0;i--)
         for(j=0;j<=width-1;j++)
           {
            bmp.Bar(RowVolWidth+startX+cs*j,yshift+cs*i,cs,cs,clrWhite);
            bmp.Rectangle(RowVolWidth+startX+cs*j,yshift+cs*i,cs,cs,clrLightGray);
           }
      bmp.TypeText(10,yshift+cs*(height)+50,array[k-2],clrDarkGray);
      bmp.TypeText(10,yshift+cs*(height)+35,array[k-1],clrGray);
     }
// --------------------------------- BMP -----------------------------------------
//--- calculating trend lines
   i=0;
   while(thEnd<width-1)
     {
      while(thBeg+i<thEnd)
        {
         if(trend=='U')
           {
            i=ArrayMinimum(tMin,thBeg,thEnd-thBeg);
            j=tMin[i];
           }
         else
           {
            i=ArrayMaximum(tMax,thBeg,thEnd-thBeg);
            j=tMax[i];
           }
         thBeg=i;
         tv=j;
         i=0;
         while(GetMatrix(matrix,j,height,(long)(thBeg+i))=='.')
           {
            i++;
            if(trend=='U') j++; else j--;
            if(thBeg+i==width-1)
              {
               thEnd=width-1;
               break;
              };
           };
         if(thBeg+i<thEnd)
           {
            thBeg=thBeg+2;
            i=0;
           };
        };
      thEnd=thBeg+i;
      if(thEnd==thBeg) thEnd++;
      for(i=thBeg;i<thEnd;i++)
        {
         SetMatrix(matrix,tv,tv,height,(long)(i),'+');
         // --------------------------------- BMP -----------------------------------------
         if(toPic==true)
           {
            //--- support and resistance lines
            if(trend=='U') { bmp.DrawLine(RowVolWidth+startX+i*cs,yshift+tv*cs,
                                         RowVolWidth+startX+(i+1)*cs,yshift+(tv+1)*cs,clrGreen); }
            if(trend=='D') { bmp.DrawLine(RowVolWidth+startX+i*cs,yshift+(tv+1)*cs,
                                         RowVolWidth+startX+(i+1)*cs,yshift+(tv)*cs,clrRed); }
            //--- broadening of support/resistance lines
            if(trend=='U') { bmp.DrawLine(RowVolWidth+1+startX+i*cs,yshift+tv*cs,
                                         RowVolWidth+1+startX+(i+1)*cs,yshift+(tv+1)*cs,clrGreen); }
            if(trend=='D') { bmp.DrawLine(RowVolWidth+1+startX+i*cs,yshift+(tv+1)*cs,
                                         RowVolWidth+1+startX+(i+1)*cs,yshift+(tv)*cs,clrRed); }
           }
         // --------------------------------- BMP -----------------------------------------
         if(trend=='U') tv++; else tv--;
        };
      if(trend=='U') trend='D'; else trend='U';
      i=0;
     };
//--- displaying data in columns
   ArrayResize(strDBC,width,0);
   TimeToStruct(DateByCol[0],bMDT);
   TimeToStruct(DateByCol[width-1],eMDT);
   if((DateByCol[width-1]-DateByCol[0])>=50000000)
     {
      for(i=0;i<=width-1;i++) StringInit(strDBC[i],4,' ');
      for(i=1;i<=width-1;i++)
        {
         TimeToStruct(DateByCol[i-1],bMDT);
         TimeToStruct(DateByCol[i],eMDT);
         if(bMDT.year!=eMDT.year) strDBC[i]=DoubleToString(eMDT.year,0);
        };
      for(i=0;i<=3;i++)
        {
         StringInit(s,vd,' ');
         s=s+"            : ";
         for(j=0;j<=width-1;j++) s=s+StringSubstr(strDBC[j],i,1);
         s=s+" : ";
         k++;
         ArrayResize(array,k,0);
         array[k-1]=s;
        };
     }
   else
     {
      if((DateByCol[width-1]-DateByCol[0])>=5000000)
        {
         for(i=0;i<=width-1;i++) StringInit(strDBC[i],7,' ');
         for(i=1;i<=width-1;i++)
           {
            TimeToStruct(DateByCol[i-1],bMDT);
            TimeToStruct(DateByCol[i],eMDT);
            if(bMDT.mon!=eMDT.mon)
              {
               if(eMDT.mon<10) strDBC[i]=DoubleToString(eMDT.year,0)+".0"+DoubleToString(eMDT.mon,0);
               if(eMDT.mon>=10) strDBC[i]=DoubleToString(eMDT.year,0)+"."+DoubleToString(eMDT.mon,0);
              }
           };
         for(i=0;i<=6;i++)
           {
            StringInit(s,vd,' ');
            s=s+"            : ";
            for(j=0;j<=width-1;j++) s=s+StringSubstr(strDBC[j],i,1);
            s=s+" : ";
            k++;
            ArrayResize(array,k,0);
            array[k-1]=s;
           };
        }
      else
        {
         for(i=0;i<=width-1;i++) StringInit(strDBC[i],10,' ');
         for(i=1;i<=width-1;i++)
           {
            TimeToStruct(DateByCol[i-1],bMDT);
            TimeToStruct(DateByCol[i],eMDT);
            if(bMDT.day!=eMDT.day)
              {
               if(eMDT.mon<10 && eMDT.day<10) strDBC[i]=DoubleToString(eMDT.year,0)+".0"
                                                       +DoubleToString(eMDT.mon,0)+".0"+DoubleToString(eMDT.day,0);
               if(eMDT.mon<10 && eMDT.day>=10) strDBC[i]=DoubleToString(eMDT.year,0)+".0"
                                                       +DoubleToString(eMDT.mon,0)+"."+DoubleToString(eMDT.day,0);
               if(eMDT.mon>=10&&eMDT.day< 10) strDBC[i]=DoubleToString(eMDT.year,0)+"." 
                                                      +DoubleToString(eMDT.mon,0)+".0"+DoubleToString(eMDT.day,0);
               if(eMDT.mon>=10&&eMDT.day>=10) strDBC[i]=DoubleToString(eMDT.year,0)+"." 
                                                      +DoubleToString(eMDT.mon,0)+"." +DoubleToString(eMDT.day,0);
              }
           };
         for(i=0;i<=9;i++)
           {
            StringInit(s,vd,' ');
            s=s+"            : ";
            for(j=0;j<=width-1;j++) s=s+StringSubstr(strDBC[j],i,1);
            s=s+" : ";
            k++;
            ArrayResize(array,k,0);
            array[k-1]=s;
           };
        };
     };
   StringInit(s,25+vd+width,'-');
   k++;
   ArrayResize(array,k,0);
   array[k-1]=s;
//--- displaying price chart
   price=GlobalMax*dBox;
   HVolumeMax=VolByPrice[ArrayMaximum(VolByPrice,0,WHOLE_ARRAY)];
   s="";
   for(i=height-1;i>=0;i--)
     {
      StringInit(ps,8-StringLen(DoubleToString(price,sd)),' ');
      s=s+ps+DoubleToString(price,sd)+" : ";
      for(j=0;j<vd;j++) if(VolByPrice[i]>HVolumeMax*j/vd) s=s+"*"; else s=s+" ";
      s=s+" : ";
      for(j=0;j<=width-1;j++) s=s+CharToString(matrix[j*height+i]);
      s=s+" : "+ps+DoubleToString(price,sd);
      k++;
      ArrayResize(array,k,0);
      array[k-1]=s;
      s="";
      price=price-dBox;
     };
   StringInit(s,25+vd+width,'-');
   k++;
   ArrayResize(array,k,0);
   array[k-1]=s;
//--- simple markup through 10
   StringInit(s,vd,' ');
   s=s+"            : ";
   for(j=0;j<=width-1;j++) if(StringGetCharacter(DoubleToString(j,0),
                                                    StringLen(DoubleToString(j,0))-1)==57) s=s+"|"; else s=s+" ";
   s=s+" : ";
   k++;
   ArrayResize(array,k,0);
   array[k-1]=s;
//--- displaying volume chart in columns
   VVolumeMax=VolByCol[ArrayMaximum(VolByCol,0,WHOLE_ARRAY)];
   for(i=vd-1;i>=0;i--)
     {
      StringInit(s,vd,' ');
      s=s+"            : ";
      for(j=0;j<=width-1;j++) if(VolByCol[j]>VVolumeMax*i/vd) s=s+"*"; else s=s+" ";
      s=s+" : ";
      k++;
      ArrayResize(array,k,0);
      array[k-1]=s;
     };
   StringInit(s,25+vd+width,'-');
   k++;
   ArrayResize(array,k,0);
   array[k-1]=s;
//--- column history
   s="     | Start Date/Time     | End Date/Time       | ";
   k++;
   ArrayResize(array,k,0);
   array[k-1]=s;
   TimeToStruct(DateByCol[0],bMDT);
   s="   1 | 0000/00/00 00:00:00 | ";
   s=s+DoubleToString(bMDT.year,0)+"/";
   if(bMDT.mon >=10) s=s+DoubleToString(bMDT.mon ,0)+"/"; else s=s+"0"+DoubleToString(bMDT.mon ,0)+"/";
   if(bMDT.day >=10) s=s+DoubleToString(bMDT.day ,0)+" "; else s=s+"0"+DoubleToString(bMDT.day ,0)+" ";
   if(bMDT.hour>=10) s=s+DoubleToString(bMDT.hour,0)+":"; else s=s+"0"+DoubleToString(bMDT.hour,0)+":";
   if(bMDT.min >=10) s=s+DoubleToString(bMDT.min ,0)+":"; else s=s+"0"+DoubleToString(bMDT.min ,0)+":";
   if(bMDT.sec >=10) s=s+DoubleToString(bMDT.sec ,0)+" | "; else s=s+"0"+DoubleToString(bMDT.sec ,0)+" | ";
   k++;
   ArrayResize(array,k,0);
   array[k-1]=s;
   for(i=1;i<=width-1;i++)
     {
      TimeToStruct(DateByCol[i-1],bMDT);
      TimeToStruct(DateByCol[i],eMDT);
      s="";
      StringInit(ps,4-StringLen(DoubleToString(i+1,0)),' ');
      s=s+ps+DoubleToString(i+1,0)+" | ";
      s=s+DoubleToString(bMDT.year,0)+"/";
      if(bMDT.mon >=10) s=s+DoubleToString(bMDT.mon ,0)+"/"; else s=s+"0"+DoubleToString(bMDT.mon ,0)+"/";
      if(bMDT.day >=10) s=s+DoubleToString(bMDT.day ,0)+" "; else s=s+"0"+DoubleToString(bMDT.day ,0)+" ";
      if(bMDT.hour>=10) s=s+DoubleToString(bMDT.hour,0)+":"; else s=s+"0"+DoubleToString(bMDT.hour,0)+":";
      if(bMDT.min >=10) s=s+DoubleToString(bMDT.min ,0)+":"; else s=s+"0"+DoubleToString(bMDT.min ,0)+":";
      if(bMDT.sec >=10) s=s+DoubleToString(bMDT.sec ,0)+" | "; else s=s+"0"+DoubleToString(bMDT.sec ,0)+" | ";
      s=s+DoubleToString(eMDT.year,0)+"/";
      if(eMDT.mon >=10) s=s+DoubleToString(eMDT.mon ,0)+"/"; else s=s+"0"+DoubleToString(eMDT.mon ,0)+"/";
      if(eMDT.day >=10) s=s+DoubleToString(eMDT.day ,0)+" "; else s=s+"0"+DoubleToString(eMDT.day ,0)+" ";
      if(eMDT.hour>=10) s=s+DoubleToString(eMDT.hour,0)+":"; else s=s+"0"+DoubleToString(eMDT.hour,0)+":";
      if(eMDT.min >=10) s=s+DoubleToString(eMDT.min ,0)+":"; else s=s+"0"+DoubleToString(eMDT.min ,0)+":";
      if(eMDT.sec >=10) s=s+DoubleToString(eMDT.sec ,0)+" | "; else s=s+"0"+DoubleToString(eMDT.sec ,0)+" | ";
      k++;
      ArrayResize(array,k,0);
      array[k-1]=s;
     };
   y=k;
   z=25+vd+width;
// --------------------------------- BMP -----------------------------------------
   if(toPic==true)
     {
      //--- displaying dates in YYYY/MM/DD format
      for(j=0;j<=width-1;j++)
        {
         string s0=strDBC[j];
         StringReplace(s0,".","/");
         bmp.TypeTextV(RowVolWidth+startX+cs*j,yshift+cs*(height-1)+5,s0,clrDimGray);
        }
      //--- volume cell support
      for(i=height-1;i>=0;i--)
         for(j=0;j<vd;j++)
           {
            bmp.Bar(cs+startX+cs*(j-1),yshift+cs*i,cs,cs,0xF6F6F6);
            bmp.Rectangle(cs+startX+cs*(j-1),yshift+cs*i,cs,cs,clrLightGray);
           }
      for(i=0; i>-7;i--)
         for(j=0;j<=vd;j++)
           {
            bmp.Bar(cs+startX+cs*(j-1),yshift+cs*i,cs,cs,clrWhite);
            bmp.Rectangle(cs+startX+cs*(j-1),yshift+cs*i,cs,cs,clrLightGray);
           }
      //--- exact volumes
      for(i=height-1;i>=0;i--)
         bmp.Bar(startX,yshift+cs*i,int(10*cs*VolByPrice[i]/HVolumeMax),cs,0xB5ABAB);
      //--- displaying naughts and crosses
      for(i=height-1;i>=0;i--)
         for(j=0;j<=width-1;j++)
           {
            int xpos=RowVolWidth+startX+cs*j+1;
            int ypos=yshift+cs*i+1;
            if(CharToString(matrix[j*height+i])=="X") ShowCell(xpos,ypos,'X');
            else
               if(CharToString(matrix[j*height+i])=="O") ShowCell(xpos,ypos,'O');
           }
      //--- volume underside support
      for(i=0;i<=60/cs;i++)
         for(j=0;j<=width-1;j++)
           {
            bmp.Bar(RowVolWidth+startX+cs*j,12+cs*i,cs,cs,0xF6F6F6);
            bmp.Rectangle(RowVolWidth+startX+cs*j,12+cs*i,cs,cs,clrLightGray);
           }
      //--- displaying volumes
      for(j=0;j<=width-1;j++) bmp.Bar(RowVolWidth+startX+cs*j,yshift-60,
                                     cs,int(60*VolByCol[j]/VVolumeMax),0xB5ABAB);
      //--- displaying the main field border
      bmp.Rectangle(RowVolWidth+startX+cs*0,yshift+cs*0,cs*(width),cs*(height),clrSilver);
      //--- displaying prices and scale
      bmp.LineV(startX,yshift,cs*height,clrBlack);
      bmp.LineV(RowVolWidth+startX+cs*width,yshift,cs*height,clrBlack);
      price=GlobalMax*dBox;
      for(i=height-1;i>=0;i--)
        {
         //-- prices on the left
         bmp.TypeText(cs,yshift+cs*i,DoubleToString(price,sd),clrBlack);
         bmp.LineH(0,yshift+cs*i,startX,clrLightGray);
         bmp.LineH(0+startX-3,yshift+cs*i,6,clrBlack);
         //-- prices on the right     
         int dx=RowVolWidth+cs*width;
         bmp.TypeText(10+startX+dx,yshift+cs*i,DoubleToString(price,sd),clrBlack);
         bmp.LineH(startX+dx,yshift+cs*i,40,clrLightGray);
         bmp.LineH(startX+dx-3,yshift+cs*i,6,clrBlack);
         price=price-dBox;
        }
      //-- saving the resulting image in a file  
      bmp.Save(sName,true);
     }
// --------------------------------- BMP -----------------------------------------
  }
//+------------------------------------------------------------------+
//|Outputting as a text file                                          |
//+------------------------------------------------------------------+
void pnf2file(string sName,        // instrument for the file name
              string& array[],    // array of lines saved in the file
              int beg,            // the line of the array first saved in the file
              int end)            // the line of the array last saved in the file
  {
   string fn;
   int    handle;
   fn=sName+"_b"+DoubleToString(box,0)+"_r"+DoubleToString(reverse,0)+".txt";
   handle=FileOpen(fn,FILE_WRITE|FILE_TXT|FILE_ANSI,';');
   for(int i=beg;i<end;i++) FileWrite(handle,array[i]);
   FileClose(handle);
  }
//+------------------------------------------------------------------+
//| Adjusting the price to the box size                                    |
//+------------------------------------------------------------------+
int MathNorm(double value,     // transforming any double-type figure into long-type figure
             double prec,      // ensuring the necessary accuracy
             bool vect)        // and if true, rounding up; if false, rounding down
  {
   if(vect==true)
      return((int)(MathCeil(value/prec)));
   else
      return((int)(MathFloor(value/prec)));
  }
//+------------------------------------------------------------------+
//| Filling the array                                                 |
//| Character one-dimensional array represented as a matrix         |
//+------------------------------------------------------------------+
void SetMatrix(uchar& array[],      // passing the array in a link to effect a replacement
               long pbeg,          // from here
               long pend,          // up to here
               long pheight,       // in the column of this height
               long pwidth,        // bearing this number among all the columns in the array
               uchar ppnf)         // with this character
  {
   long offset=0;
   for(offset=pheight*pwidth+pbeg;offset<=pheight*pwidth+pend;offset++) array[(int)offset]=ppnf;
  }
//+------------------------------------------------------------------+
//| Getting an isolated value from the array                           |
//| Character one-dimensional array represented as a matrix         |
//+------------------------------------------------------------------+
uchar GetMatrix(uchar& array[],      // passing it in a link to obtain a character...
                long pbeg,          // here
                long pheight,       // in the column of this height
                long pwidth)        // bearing this number among all the columns in the array
  {
   return(array[(int)pheight*(int)pwidth+(int)pbeg]);
  }
//+------------------------------------------------------------------+
//|Filling the vector                                                  |
//+------------------------------------------------------------------+
void SetVector(long &array[],      // passing the long-type array in a link to effect a replacement
               long pbeg,         // from here
               long pend,         // up to here
               long pv)           // with this value
  {
   long offset=0;
   for(offset=pbeg;offset<=pend;offset++) array[(int)offset]=array[(int)offset]+pv;
  }
//+------------------------------------------------------------------+
//| Displaying a horizontal line                                 |
//+------------------------------------------------------------------+
void cIntBMPEx::LineH(int aX1,int aY1,int aSizeX,int aColor)
  {
   DrawLine(aX1,aY1,aX1+aSizeX,aY1,aColor);
  }
//+------------------------------------------------------------------+
//| Displaying a vertical line                                   |
//+------------------------------------------------------------------+  
void cIntBMPEx::LineV(int aX1,int aY1,int aSizeY,int aColor)
  {
   DrawLine(aX1,aY1,aX1,aY1+aSizeY,aColor);
  }
//+------------------------------------------------------------------+
//| Drawing a rectangle (of a given size)                         |
//+------------------------------------------------------------------+
void cIntBMPEx::Rectangle(int aX1,int aY1,int aSizeX,int aSizeY,int aColor)
  {
   DrawRectangle(aX1,aY1,aX1+aSizeX,aY1+aSizeY,aColor);
  }
//+------------------------------------------------------------------+
//| Drawing a filled rectangle (of a given size)             |
//+------------------------------------------------------------------+
void cIntBMPEx::Bar(int aX1,int aY1,int aSizeX,int aSizeY,int aColor)
  {
   DrawBar(aX1,aY1,aX1+aSizeX,aY1+aSizeY,aColor);
  }
//+------------------------------------------------------------------+
//| Drawing a filled rectangle                                 |
//+------------------------------------------------------------------+
void cIntBMPEx::DrawBar(int aX1,int aY1,int aX2,int aY2,int aColor)
  {
   for(int i=aX1; i<=aX2; i++)
      for(int j=aY1; j<=aY2; j++)
        {
         DrawDot(i,j,aColor);
        }
  }
//+------------------------------------------------------------------+
//| Displaying the text vertically                                  |
//+------------------------------------------------------------------+
void cIntBMPEx::TypeTextV(int aX,int aY,string aText,int aColor)
  {
   SetDrawWidth(1);
   for(int j=0;j<StringLen(aText);j++)
     {
      string TypeChar=StringSubstr(aText,j,1);
      if(TypeChar==" ")
        {
         aY+=5;
        }
      else
        {
         int Pointer=0;
         for(int i=0;i<ArraySize(CA);i++)
           {
            if(CA[i]==TypeChar)
              {
               Pointer=i;
              }
           }
         for(int i=PA[Pointer];i<PA[Pointer+1];i++)
           {
            DrawDot(aX+YA[i],aY+MaxHeight+XA[i],aColor);
           }
         aY+=WA[Pointer]+1;
        }
     }
  }
//+------------------------------------------------------------------+
//| Transforming components into color                                    |
//+------------------------------------------------------------------+
int RGB256(int aR,int aG,int aB)
  {
   return(aR+256*aG+65536*aB);
  }
//+------------------------------------------------------------------+
//| Drawing X's or O's as an image                               |
//+------------------------------------------------------------------+
void ShowCell(int x,int y,uchar img)
  {
   uchar r,g,b;
   for(int i=0; i<8; i++)
     {
      for(int j=0; j<8; j++)
        {
         switch(img)
           {
            case 'X':
               r=Mask_X[3*(j*8+i)];
               g=Mask_X[3*(j*8+i)+1];
               b=Mask_X[3*(j*8+i)+2];
               break;
            case 'O':
               r=Mask_O[3*(j*8+i)];
               g=Mask_O[3*(j*8+i)+1];
               b=Mask_O[3*(j*8+i)+2];
               break;
           };
         int col=RGB256(r,g,b);
         bmp.DrawDot(x+i,y+j,col);
        }
     }
  }
//+------------------------------------------------------------------+

Abhängig vom Wert des Eingabeparameters pic werden die Ergebnisse des Scripts entweder in Form von Textdateien mit Grafikdateien (Datenverzeichnis_des_Terminals\MQL5\Images) oder nur in Form von Textdateien (Datenverzeichnis_des_Terminals\MQL5\Files) generiert.


Vergleich der Ergebnisse

Um die Ergebnisse zu vergleichen, zeichnen wir ein Diagramm für leichtes Rohöl mit den folgenden Parametern: Box-Größe ist 1 $, Umkehr beträgt 3 Boxen.

StockCharts.com:

Abb. 1. Von StockCharts.com generiertes Punkt- und Zeichendiagramm für leichtes Rohöl

Abb. 1. Von StockCharts.com generiertes Punkt- und Zeichendiagramm für leichtes Rohöl

Bull's-Eye Broker:

Abb. 2. Von Bull's-Eye Broker generiertes Punkt- und Zeichendiagramm für leichtes Rohöl

Abb. 2. Von Bull's-Eye Broker generiertes Punkt- und Zeichendiagramm für leichtes Rohöl


Ausführungsergebnisse unseres Scripts:

Abb. 3. Von unserem Script generiertes Punkt- und Zeichendiagramm für leichtes Rohöl

Abb. 3. Von unserem Script generiertes Punkt- und Zeichendiagramm für leichtes Rohöl

Alle drei Diagramme sind identisch. Glückwunsch! Wir haben uns das Zeichnen von Punkt- und Zeichendiagrammen angeeignet.


Typische Muster von Punkt- und Zeichendiagrammen

Wie können wir sie nutzen?

Sehen wir uns zunächst typische Muster an, insbesondere deshalb, weil sie sich an einer Hand abzählen lassen.

Diese sind:

Abb. 4. Preismuster: Doppelter Höchstpunkt, Dreifacher Höchstpunkt, Doppelte Basis, Dreifache Basis

Abb. 4. Preismuster: Doppelter Höchstpunkt, Dreifacher Höchstpunkt, Doppelte Basis, Dreifache Basis

außerdem:

Abb. 5. Preismuster: Bullen-Dreieck und Bären-Dreieck

Abb. 5. Preismuster: Bullen-Dreieck und Bären-Dreieck

und zu guter Letzt:

Abb. 6. Preismuster: Bullen-Katapult und Bären-Katapult

Abb. 6. Preismuster: Bullen-Katapult und Bären-Katapult

Jetzt noch ein paar Tipps.

  1. Öffnen Sie über der Unterstützungslinie nur lange Positionen und unterhalb der Widerstandslinie nur kurze. Zum Beispiel: Öffnen Sie nur lange Positionen für Futures für leichtes Rohöl ab Mitte Dezember 2011 nach dem Durchbrechen der Widerstandslinie, die sich seit Ende September 2011 geformt hat.
  2. Nutzen Sie Unterstützungs- und Widerstandslinien für das Trailing von Stop-Loss-Ordern.
  3. Zählen Sie vertikal, bevor Sie eine Position öffnen, um ein Verhältnis zwischen möglichem Gewinn und möglichem Verlust schätzen zu können.

Die vertikale Zählung lässt sich anhand des folgenden Beispiels besser veranschaulichen.

Im Dezember 2011 bewegte sich die Spalte von X vom Ausgangspreis von 76 $ nach oben, über die vorhergehende Spalte von X bei 85 $, durchbrach die Widerstandslinie bei 87 $ und erreichte 89 $. Gemäß der vertikalen Zählung deutet dies darauf hin, dass der Preis steigen und das Niveau von 76 $+(89 $-75 $)*3 (Umkehr von 3 Boxen)=118 $ erreichten könnte.

Die nächste Bewegung war korrektiv und brachte den Preis auf ein Niveau von 85 $. Spekulanten können eine Stop-Loss-Order für eine lange Position bei 1$ weniger platzieren, d. h. bei 84 $.

Der Eintritt in die lange Position kann nach einer abgeschlossenen korrektiven Bewegung eine Box höher als die vorherige Spalte von X, d. h. beim Preis von 90 $, geplant werden.

Lassen Sie uns den möglichen Verlust schätzen. Er könnte bei 90 $-84 $=6 $ liegen. Der mögliche Gewinn kann 118 $-90$=28 $ erreichen. Verhältnis möglicher Gewinn-möglicher Verlust: 28 $/6 $>4,5. Meiner Meinung nach eine gute Performance. Schon jetzt hätten wir einen Gewinn von 105 $-90 $=15 $ pro Future-Kontrakt.


Lizenzen

Das Script wurde unter BSD-Lizenz durch Roman Rich geschrieben und bereitgestellt. Den Lizenztext finden Sie in der Datei Lic.txt. Die Bibliothek cIntBMP wurde von Dmitry aka Integer erstellt. StockCharts.com und Bull's-Eye Broker sind eingetragene Schutzmarken und Eigentum ihrer jeweiligen Inhaber.


Fazit

In diesem Beitrag wurden ein Algorithmus und ein Script für das Zeichnen von Punkt- und Zeichendiagrammen ("X und O") vorgeschlagen. Es wurden diverse Preismuster betrachtet, deren praktische Nutzung in den bereitgestellten Empfehlungen umrissen wurde.


Übersetzt aus dem Russischen von MetaQuotes Software Corp.
Originalartikel: https://www.mql5.com/ru/articles/368

Beigefügte Dateien |
pnf.zip (659.49 KB)
cintbmp.mqh (39.68 KB)
pnf2.mq5 (27.36 KB)
lic.txt (1.35 KB)
Unterstützen Sie Ihre Entwicklungsprojekte mit EX5-Bibliotheken Unterstützen Sie Ihre Entwicklungsprojekte mit EX5-Bibliotheken

Indem Sie die Umsetzungsdetails von Klassen/Funktionen in einer .ex5-Datei verbergen, können Sie Ihre Know-how-Algorithmen mit anderen Entwicklern teilen, gemeinsame Projekte in die Wege leiten und sie im Internet bewerben. Und während das Team von MetaQuotes keine Mühen scheut, um die direkte Vererbung von ex5-Bibliotheksklassen zu ermöglichen, setzen wir sie jetzt schon um.

Schutz von MQL5-Programmen: Passwörter, Schlüssel, Zeitbegrenzung, Berechtigungsfernabfrage Schutz von MQL5-Programmen: Passwörter, Schlüssel, Zeitbegrenzung, Berechtigungsfernabfrage

Die Mehrzahl der Entwickler benötigt Schutz für ihren Programmcode. In diesem Beitrag werden einige unterschiedliche Möglichkeiten zum Schutz von in MQL5 geschriebenen Programmen vorgestellt, so etwa zur Ausstattung von MQL5-Skripten, automatischen Handelssystemen und Indikatoren mit Zugriffskontrollverfahren. Dazu zählen Passwortschutz, Schlüsselgeneratoren, Zugriffskonten, Zeitbegrenzungsprüfungen sowie der Schutz mittels MQL5-RPC-Aufrufen aus der Ferne.

AutoElliottWaveMaker - ein Tool für die halbautomatisierte Analyse von Elliott-Wellen in MetaTrader 5 AutoElliottWaveMaker - ein Tool für die halbautomatisierte Analyse von Elliott-Wellen in MetaTrader 5

Dieser Beitrag liefert einen Überblick über AutoElliottWaveMaker, das erste Werkzeug für die Analyse von Elliott-Wellen in MetaTrader 5, das eine Kombination aus manueller und automatischer Kennzeichnung von Wellen darstellt. Das Wellenanalyse-Tool ist ausschließlich in MQL5 geschrieben und enthält keine externen DLL-Bibliotheken. Das ist ein weiterer Beleg dafür, dass ausgeklügelte und interessante Programme in MQL5 entwickelt werden können (und sollten).

Veröffentlichen eines Produkts im Market Veröffentlichen eines Produkts im Market

Veröffentlichen Sie ihre interessanten Anwendungen im Market und sie werden sofort allen Händlern weltweit, die MetaTrader 5 nutzen, zur Verfügung gestellt. Der Market ist auch eine tolle Möglichkeit, Geld zu verdienen. Die sofortige Überweisung auf Ihr Konto und praktische Statistiken helfen Ihnen, Käufe und Downloads von Demoversionen Ihrer Produkte zu analysieren. Alle MQL5-Programme im Market werden automatisch für einen bestimmten Käufer verschlüsselt, erlauben ab fünf Aktivierungen und benötigen keinen zusätzlichen Schutz von Ihrer Seite.