Die Sprache MQL4 für "Neulinge". Die benutzerdefinierten Indikatoren (Teil 2)

Antoniuk Oleg | 14 Februar, 2017


Einführung

Es ist der fünfte Artikel aus der Reihe "Die Sprache MQL4 für "Neulinge". Heute lernen wir, die graphischen Objekte zu verwenden - das ist ein sehr mächtiges Mittel der Entwicklung, welches ermöglicht, die Möglichkeiten der Indikatoren wesentlich zu verbreiten. Außerdem können Sie sie auch in Skripten und in den EAs verwenden. Wir erkennen, wie Objekte erstellt werden können, ihre Parameter ändern, Fehler überprüfen. Natürlich gelingt es mir nicht, vollständig alle Objekte zu beschreiben, sie sind zu viel. Aber Sie bekommen alle notwendige Information,dies alles selbst zu begreifen. Auch enthält dieser Artikel ein Anleitung-Beispiel, einen komplizierten Signalindikator Schritt um Schritt zu erstellen. Aufgrund des Letzten können Sie beliebige Signalindikatoren selbständig erstellen, die die Handelssignale auf allen Perioden nach einigen Indikatoren zeigen. Dabei werden viele Parameter dem Benutzer für die Einstellung zugänglich sein, was flexibel ermöglicht, die Aussicht zu ändern.


Was ist graphische Objekte?

Sie stoßen auf sie oft, wenn Sie im Terminal Meta Trader 4 arbeiten. Sie können die graphischen Objekte für ganz verschiedene Ziele verwenden. Die Trader stellen die Ebene der Unterstützung/Widerstand, den Punkt der Wende, die Ebene Fibonacci und anderes. Lassen Sie uns bitte ein einfaches Beispiel der Verwendung der Objekte betrachten:


Auf diesem Chart wurden 4 graphische Objekte beigefügt:

  • 2 horizontale Linien
  • Ein Textobjekt
  • Ein Objekt-Symbol(Pfeil)

Heute werden wir lernen, solche Objekte mit Hilfe MQL4 zu hinzuzufügen. Stellen Sie sich vor, wie viele die routinemäßigen Handlungen Sie automatisieren können, wenn Sie diese Objekte verwenden! Zum Beispiel, Sie müssten den Punkt der Wende, die Ebene Unterstützung / Widerstand berechnen, und sie später manuell zu zeichnen? Ja, es gibt da wenig zu tun, aber wenn dieser Prozess auf MQL4 automatisiert ist, das Terminal wird alles selbst berechnen und wird die entsprechende Ebene zeichnen. Alles, was Sie tun müssen - ist zweimal auf den Namen des Skripts zu drücken, damit alles für Sie erledigt wird. Außerdem, durch die Verwendung der graphischen Objekte kann man die sehr nützlichen Signalindikatoren schreiben.

Die Arbeitskonzeption mit den Objekten

In MQL4 mit beliebigen graphischen Objekten arbeiten ungefähr nach solcher Reihenfolge:

  • Die Erstellung des Objektes
  • Die Veränderung seiner Parameter (die Umstellung, die Veränderung der Farbe, des Stils usw.)
  • Die Entfernung des Objektes

Es entsteht eine solche "Lebensperiode". Jetzt betrachten wir jede der Stufen ins Detail.

Die Erstellung des graphischen Objektes

Um ein beliebiges graphisches Objekt zu zeichnen, verwendet man eine universelle Funktion – ObjectCreate(). Hier ist ihr Prototyp:

bool ObjectCreate(string name, int type, int window, datetime time1, 
                  double price1, datetime time2=0,double price2=0, 
                  datetime time3=0, double price3=0)

Die Funktion liefert true zurück, wenn alles in Ordnung ist, und false, wenn das Objekt nicht erstellt werden kann oder es ist ein Fehler aufgetreten. Damit man den Fehler-Code definiert, muss man die Funktion GetLastError() verwenden:

if(ObjectCreate(/* Argumente */)==false)
{
   // ein Fehler ist aufgetreten, liefern wie den Fehler-Code ins Journal zurück 
   Print("Fehler beim Aufruf ObjectCreate():",GetLastError());
}

Wieso braucht man den Code des Fehlers? Nach ihm können Sie die Beschreibung des Fehlers finden und ihn möglichst entfernen. Alle Beschreibungen der Codes sind: MQL4 Reference -> Standart Constans -> Codes of Errors .

Betrachten wir alle Argumente der Funktion ObjectCreate():

  • name – der einzigartige Name des Objektes. Sie können nicht 2 Objekte mit einem Namen erstellen. Dieser Name wird später in anderen Funktionen verwendet, um die Parameter der Anzeige des Objektes zu ändern, ihn zu verschieben.
  • type – der Typ des Objektes. Alle Typen der Objekte, die man erstellen kann, befinden sich: MQL4 Reference -> Standart Constans -> Objekt Types. Es ist sehr wichtig, zu bemerken, dass es vom Typ des Objektes abhängig ist, ob man die letzten Argumente der Funktion verwenden muss. Schauen Sie noch einmal den Prototyp an. Die letzten 4 Argumenten wurden die Werte standardmäßig zugeordnet. Und zwar: die verschiedenen Objekte fordern verschiedene Menge aus Informationen, um sie zu erstellen. Das ist ganz einfach. Angenommen müssen Sie jetzt einen Punkt zeichnen. Welche Information brauchen Sie dann? Offenbar die Koordinate dieses Punktes. Zum Beispiel, wie viele Zellen links und oben frei lassen. Alle. Es wird genug sein, nicht wahr? Und, wenn es ein Rechteck ist, wie viele Punkte dann nötig sind? Richtig, schon 2. Es sind die Koordinaten des oberen linken und recht unteren Punktes. Das gleiche ist mit der Funktion ObjectCreate(). Sie ist doch universell, deswegen, wenn sie die Horizontale-Linie zeichnet, so ist für sie die Koordinaten nur eines Punktes nötig, und wenn es ein Intervall einer gerade Linie ist, so wird es schon 2 Punkte gefordert. Und wenn Sie noch ein Dreieck zeichnen will, so werden Sie schon 3 Punkte einsetzen. Deshalb, bei der Erstellung eines irgendwelches Objektes studieren Sie aufmerksam, wie viele Punkte erstellt werden müssen, damit Sie ihn zeichnen.
  • window – die Fenster-Nummer, in der es gezeichnet wird. Wenn man das Objekt auf dem Chart der Preise zeichnen muss, das heißt im Hauptfenster, so muss nur die Werte 0 verwenden.
  • time1 – die Koordinate Х des ersten Punktes. Da die Zeit sich auf der Achse Х im Terminal befindet, so muss man die Werte der Zeit bezeichnen. Zum Beispiel so, um die Zeit der letzten zugänglichen Bar zu erfahren, kann man das vorherbestimmte Array Time[] folgendermaßen verwenden: Time[0].
  • price1 – die Koordinate У des ersten Punkts. Auf dieser Achse im Terminal wird der Preis dargestellt, deshalb muss man die Werte der Preise verwenden. Zum Beispiel, verwenden die vorherbestimmten Arrays Open[], Close[] usw.
  • die übrigen Argumente – es sind nun wieder 2 Paare ähnlich mit Koordinaten, die die Punkte für das Zeichnen der komplizierteren Objekte bestimmen. Wenn das Objekt einfach ist, so werden diese Parameter nicht verwendet.


Das Beispiel der Erstellung der Objekte. Wir zeichnen die Linien

Jetzt, um das gut zu begreifen, zeichnen wir ein Paar Linien. Wir markieren den minimalen und maximalen Preis vom letzten Tag. Dazu erstellen wir ein Skript und ändern die Funktion start():

int  start()
{
   double price=iHigh(Symbol(),PERIOD_D1,0);
   // Diese nützliche Funktion liefert den maximalen Preis zurück in:
   // * das angegebene Finanzinstrument, bei uns ist es Symbol() - 
   //   das aktive Finanzinstrument
   // * die angegebene Periode, bei uns ist es - PERIOD_D1 (tagsüber)
   // * die angegebene Bar, bei uns ist es 0, die letzte Bar
 
   ObjectCreate("highLine",OBJ_HLINE,0,0,price);
   // Lassen Sie uns bitte alle Parameter betrachten: 
   // "highLine" - der einzigartige Name des Objektes
   // OBJ_HLINE - der Typ des Objektes, der der Horizontale-Linie entspricht
   // 0 - zeichnen wir das Objekt im Hauptfenster (das Chart der Preise)
   // 0 - die Koordinate auf der Achse Х (die Zeit), da wir die Horizontale-Linie herausführen
   //      so muss man diese Koordinate nicht geben
   // price - die Koordinate auf der Achse Y (dem Preis). Bei uns ist es der maximale Preis
   
   price=iLow(Symbol(),PERIOD_D1,0);
   // die Funktion stimmt nach den Argumenten mit iHigh vollständig überein, aber liefert 
   // den minimalen Preis zurück
   
   ObjectCreate("lowLine",OBJ_HLINE,0,0,price);
 
   return(0);
}

Natürlich, haben wir die Prüfung auf die Fehler übersprungen. So dass, wenn Sie 2 identische Namen für beide Objekte einführen werden, bin ich nicht schuldig. In Wirklichkeit, wenn Sie einen Skript starten, soll es ungefähr so aussehen:

Die Linien sind gezeichnet, aber es gibt etwas, was mir gar nicht gefällt! Diese volle Rote Farbe, schauen Sie an, einfach eine schreckliche Farbe, verwenden Sie immer nur die Schattierungen. Es war nur zum Spass. Natürlich, noch vieles kann Ihnen nicht gefallen. Zum Beispiel, die Dicke der Linien, ihren Stil.

Die Änderung der Objekte-Eigenschaften. Wir stellen das Aussehen der Linien ein

Deshalb existiert die andere universelle Funktion, die ermöglicht, alle Parameter jeder schon früher als das graphisch erstellte Objekt zu einzustellen. Das ist – ObjectSet(). Prototyp:

bool ObjectSet( string name, int index, double value);

Wie auch die vorhergehende Funktion, diese liefert true zurück, wenn alles normal gegangen ist und es kommt false , wenn Probleme entstanden sind. Zum Beispiel, haben Sie den fehlenden Namen des Objektes eingegeben. Betrachten wir alle Argumente der Funktion:

  • name – der Titel des schon erstellten Objektes. Überzeugen sich, dass das Objekt mit dem solchen Namen schon erstellt ist, bevor Sie versuchen, etwas zu ändern.
  • index – der Index der Objekt-Eigenschaft, die man ändern muss. Alle Indexe der Eigenschaften kann man finden: MQL4 Reference -> Standart Constans -> Eigenschaften der Objekts . Es ist doch auch eine universelle Funktion. Sie arbeitet nach solchem einfachen Prinzip: Sie bezeichnen, was Sie, welche Eigenschaft ändern wollen, und später bezeichnen, welcher Wert, dieser Eigenschaft zugeordnet werden muss.
  • value – und das ist eben dieser Wert, um den man die gewählte Eigenschaft ändern muss. Zum Beispiel, wenn Sie die Farbe ändern, so soll es hier der Wert irgendwelcher Farbe eingegeben sein, logisch, nicht Wahr?

Jetzt ändern Sie unsere Linien, und zwar, die Farbe, die Dicke und den Stil. Ändern Sie die Funktion start() des gleichen Skripts:

int  start()
{
   double price=iHigh(Symbol(),PERIOD_D1,0);
 
   ObjectCreate("highLine",OBJ_HLINE,0,0,price);
   price=iLow(Symbol(),PERIOD_D1,0);
   ObjectCreate("lowLine",OBJ_HLINE,0,0,price);
   
   ObjectSet("highLine",OBJPROP_COLOR,LimeGreen);
   // Wir ändern die Farbe der oberen Linie
   ObjectSet("highLine",OBJPROP_WIDTH,3);
   // jetzt wird die Linie-Dicke in 3 Pixels sein
   
   ObjectSet("lowLine",OBJPROP_COLOR,Crimson);
   // Wir ändern die Farbe der unteren Linie
   ObjectSet("lowLine",OBJPROP_STYLE,STYLE_DOT);
   // jetzt wird die untere Linie punktiert   
 
   return(0);
}

Auf dem Chart sollten Sie etwas ähnlich damit sehen:


Die Löschung der Objekte

Sie müssen die überflüssigen, veralteten und einfach unnützen Objekte oft entfernen. Dazu existieren einige Funktionen, hier sind sie:

bool ObjectDelete(string name);

Diese Funktion entfernt das Objekt mit dem angegebenen Namen. Wenn Sie den Namen des Objektes eingeben, welcher nur in Ihrer Fantasie existiert, so wird Ihnen false zurückgegeben.

int ObjectsDeleteAll(int window=EMPTY,int type=EMPTY);

Es ist eine fortgeschrittene Funktion, die die Zahl der entfernten Objekte zurückgibt. Wie Sie sehen, hier gibt es sogar die standardmäßigen Werte. Wenn Sie keine Parameter eingeben, so wird das Terminal alle Objekte auf dem aktiven Chart entfernen:

ObjectDeleteAll();
// Wir entfernen alle nacheinander

Wenn Sie die Objekte im Unterfenster erstellt haben ( zum Beispiel, im Fenster eines irgendwelchen Indikators), so kann man durch die Eingabe der Nummer des Unterfensters im ersten Argument, den Objekten darin vollständig zu entgehen. Jetzt geben Sie im ersten Argument immer 0 ein, da wir uns mit den Unterfenstern später zurechtfinden.

Wenn Sie alle Objekte eines bestimmten Typs entfernen müssen, so geben Sie im zweiten Argument den Typ der Objekte-Todeskandidaten ein:

ObjectsDeleteAll(0, OBJ_ARROW);
// Wir entfernen alle Pfeile

Wie soll man mit allen diesen zu Recht kommen?

Sie können nachdenken, dass man viel wissen muss, um sich in etwas ähnlich zurechtzufinden. Zum Beispiel, dass man diese alle Eigenschaften und die Typen der Objekte erlernen muss, und, sie im Kopf halten. Quatsch! Jetzt werde ich Ihnen erklären, wie Sie den ähnlichen Code schreiben sollen, dabei nichts wissen, denn es gibt die ganze Information im Reference!

Schauen Sie mal an. Als erstes öffnen Sie das Instrumentarium (CTRL+T). Dort unten gibt es viele Grundsteinlegungen, wählen Sie Hilfe. Jetzt stellen wir uns vor, dass Sie ein irgendwelches neues graphisches Objekt zeichnen wollen, aber Sie wissen noch nicht, wie. Dazu verwenden Sie die Funktion ObjectCreate(), schreiben Sie diese Funktion, die Argumente erstmal überspringen. Jetzt führen Sie den Mauszeiger in den Namen der Funktion zu und drücken Sie F1. Also fertig! Schauen Sie sich in der Hilfe an, die Informationen über diese Funktion wurden dargestellt. Das heißt, es muss sogar nichts gesucht werden. Jetzt schauen Sie sich die Beschreibung der Funktion an. Nach ihm geht die Beschreibung aller Argumente, wie es in dieser Stunde ist. Geben Sie Acht auf die Beschreibung der Argumente type:


Ja, es ist ein gewöhnlicher Link. Einfach rufen wir den auf und wir sehen, welche graphischen Objekte überhaupt existieren. Wir nehmen an, Ihnen hat die Ellipse gefallen:


Aufmerksam lesen wir die Beschreibung: uns wird es geschrieben, dass es 2 Koordinaten notwendig sind. Wir beginnen:

int  start()
{
   ObjectCreate("ellipse",OBJ_ELLIPSE,0,Time[100],Low[100],Time[0],High[0]);
   // Wir geben 2 Punkte für die Erstellung der Ellipse ein:
   // * der erste - der linke untere Punkt
   // * der zweite - der rechte obere Punkt 
 
   return(0);
}
Es wurde auch gesagt, dass die Eigenschaft OBJPROP_SCALE das Verhältnis der Seiten bestimmt, deswegen, wenn es in 1 gestellt wird, so wird sich der gewöhnliche Kreis ergeben:

int  start()
{
   ObjectsDeleteAll();
   // wir werden das Chart vor dem Zeichnen reinigen
   
   ObjectCreate("ellipse",OBJ_ELLIPSE,0,Time[100],Low[100],Time[0],High[0]);
   
   ObjectSet("ellipse",OBJPROP_SCALE,1.0);
   // wir ändern das Verhältnis der Seiten
   ObjectSet("ellipse",OBJPROP_COLOR,Gold);
   // Nebenbei ändern wir auch die Farbe 
 
   return(0);
}

Ich bin überzeugt, dass Sie einen solchen Kreis nicht erstellen, da man erstmal den einzelnen Maßstab in den Eigenschaften des Charts setzen muss (Drücken wir auf den rechten Knopf der Maus auf einer beliebigen leeren Stelle des Charts und wählen die Eigenschaften ):



Wie Sie sehen können, ist es ziemlich einfach. Es ist wichtig, zu bemerken, dass Sie den Mausanzeiger auf ein beliebiges Stichwort im Code zuführen können und, F1 drücken, wonach Sie auf den entsprechenden Artikel in der Hilfe automatisch versetzt werden. So können Sie schnell und wirksam einen Code schreiben, durch die eingebaute Hilfe, dabei von den Namen der Konstanten der Typen und der Eigenschaften keine Ahnung haben. In MetaEditor gibt es noch eine wichtige Eigenschaft, die die Schreibung des Codes vereinfacht: wenn Sie die Argumente in irgendwelcher eingebauter Funktion verordnen, drücken Sie die Kombination CTRL + SHIFT + Space. Danach wird ein Tipp mit dem Prototyp der Funktion erscheinen, sehr bequem und man muss sich nichts merken:


Die Erstellung der graphischen Objekte in Unterfenstern

Wenn Sie die graphischen Objekte in Unterfenstern des Charts zeichnen wollen, zum Beispiel, im Fenster des Anwenderindikators, so müssen Sie zuerst die Nummer dieses Unterfenster erfahren. Für das anschauliche Beispiel schreiben wir einen einfachen Indikator, der die Horizontale-Linie im eigenen Fenster zeichnen wird. Erstellen Sie den neuen Anwenderindikator und schreiben Sie den Code fertig:

//+------------------------------------------------------------------+
//|                                   creatingObjectsInSubWindow.mq4 |
//|                                                     Antonuk Oleg |
//|                                            antonukoleg@gmail.com |
//+------------------------------------------------------------------+
#property copyright "Antonuk Oleg"
#property link      "antonukoleg@gmail.com"
 
#property indicator_separate_window
// Der Indikator wird in einem getrennten Unterfenster gezeichnet
#property indicator_minimum 1
// der minimale Wert des Indikators ist gleich 1
#property indicator_maximum 10
// Der maximale - 10
 
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
{
   IndicatorShortName("NiceLine");
   // Diese einfache Funktion setzt den kurzen Namen des Indikators,
   // den Namen, den Sie im linken oberen Winkel eines Indikators sehen können.
   // Warum ist das nötig? Es handelt sich darum, dass die Funktion WindowFind ein Unterfenster sucht
   // mit dem kurzen angegebenen Namen und er liefert seine Nummer zurück.
 
   int windowIndex=WindowFind("NiceLine");
   // wir finden die Nummer des Unterfensters unseres Indikators
   
   if(windowIndex<0)
   {
      // wenn die Nummer des Unterfensters -1 gleich ist, so tritt der Fehler auf
      Print("Can\'t find window");
      return(0);
   }  
 
   ObjectCreate("line",OBJ_HLINE,windowIndex,0,5.0);
   // wir zeichnen die Linie im Unterfenster unseres Indikators
               
   ObjectSet("line",OBJPROP_COLOR,GreenYellow);
   ObjectSet("line",OBJPROP_WIDTH,3);
 
   WindowRedraw();      
   // wir zeichnen das Fenster, damit wir die Linie sehen
 
   return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
{
   ObjectsDeleteAll();
   // Löschen wir alle Objekte
   
   return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
{
   return(0);
}


Starten Sie den Indikator. Und oh Gott, es gibt keine Linie!



Ruhe, wechseln Sie die Periode des Charts.



Es entsteht... Was ist passiert? Es handelt sich darum, dass man die Nummer des Unterfensters in der Funktion init() nicht erfahren kann, wenn sie das erste Mal vom Indikator gestartet wird. Wahrscheinlich, es hängt damit zusammen, weil die Unterfenster vom Terminal während der Initialization noch nicht erstellt wurden. Es klingt klug, aber wie soll man es korrigieren? Man muss einfach alles in der Funktion start() durchführen, wenn das Fenster beispielsweise schon erstellt ist:

//+------------------------------------------------------------------+
//|                                   creatingObjectsInSubWindow.mq4 |
//|                                                     Antonuk Oleg |
//|                                            antonukoleg@gmail.com |
//+------------------------------------------------------------------+
#property copyright "Antonuk Oleg"
#property link      "antonukoleg@gmail.com"
 
#property indicator_separate_window
#property indicator_minimum 1
#property indicator_maximum 10
 
bool initFinished=false;
// Wir fügen die Variable hinzu, die den Zustand der Initialisation speichern wird.
// false - es gab noch keine Initialisation
// true - gab es schon
 
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
{
   return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
{
   ObjectsDeleteAll();
   // Löschen wir alle Objekte
   
   return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
{
   if(initFinished==false)
   {
      IndicatorShortName("NiceLine");
 
      int windowIndex=WindowFind("NiceLine");
   
      if(windowIndex<0)
      {
         // wenn die Nummer des Unterfensters -1 gleich ist, so tritt der Fehler auf
         Print("Can\'t find window");
         return(0);
      }  
 
      ObjectCreate("line",OBJ_HLINE,windowIndex,0,5.0);
      // wir zeichnen die Linie im Unterfenster unseres Indikators
               
      ObjectSet("line",OBJPROP_COLOR,GreenYellow);
      ObjectSet("line",OBJPROP_WIDTH,3);
 
      WindowRedraw();      
      // wir zeichnen das Fenster, damit wir die Linie sehen   
      
      initFinished=true;
      // Das Zeichen wurde schon beendet
   }
   
   return(0);
}

Jetzt wird alles vom ersten Mal gezeichnet. Von daher sollen Sie sich merken, dass man die Nummer des Unterfensters in der Funktion start(), und nicht init() erkannt werden muss.

Üben Sie es

Probieren Sie es, durch die Verwendung der Hilfe, sich selbst in einigen neuen Typen der graphischen Objekte zurechtzufinden. Danach schreiben Sie den Skript, der sie selbst zeichnen und irgendwelche Parameter nach Ihrem Ermessen einstellen wird. Sammeln Sie Erfahrung, passen Sie sich an und nur erst dann lesen Sie es weiter.


Wir schreiben den Signalindikator. Und was ist das?

Stellen Sie sich die Situation vor. Der Trader verwendet einige Indikatoren für die Annahme der Lösungen über den Eingang in den Markt: Moving Average, Parabolic SAR und Williams’ Percent Range. Dies alles sind im Terminal eingebauten Indikatoren, die ungefähr so zusammen aussehen:



Der Trader bewertet immer die vorhandene Lage auf dem Markt auf folgender Weise. Er meint, in den Markt eingehen muss man dann, wenn es direkt 3 Signale von diesen Indikatoren gibt:

  • Wenn der schnelle Mittelwert höher als langsame hinaufsteigt, so ist es das Signal auf den Kauf. Wenn es im Gegenteil ist, so auf den Verkauf.
  • Wenn der Preis niedriger als die Kennziffer Parabolic SAR ist, so ist es das Signal auf den Verkauf und umgekehrt.
  • Wenn WPR mehr als -20 ist, so ist es das Signal auf den Kauf. Wenn WPR weniger als -80 ist, so ist es das Signal auf den Verkauf.

Der Trader muss ständig alle Bedingungen prüfen, dabei bemüht er sich, die Situation auf einigen Perioden zu kontrollieren. So verwandelt sich seine Arbeit in die endlose Folter für die Augen und ihm bleibt es nur übrig, vom Signalindikator zu träumen, der alle Prüfungen machen würde:

Heute werden wir den Traum dieses Traders verwirklichen. Wir werden den Signalindikator schreiben, der sich sehr flexibel anpassen wird (die Aussicht). Außerdem können Sie ohne Probleme auf seiner Grundlage die Modifikation mit Ihren Lieblingsindikatoren erstellen.


Die Grundlage

Bei der Schreibung des ähnlichen Indikators entsteht ein Problem mit dem Zeichnen. Doch werden alle graphischen Objekte gezeichnet, verwendend durch solche Koordinaten, wie der Preis und die Zeit. Deswegen ist es kompliziert bei der Erstellung, damit alles, was wir zeichnen, die ganze Zeit auf seiner Stelle bleibt. Man sollte ständig die Koordinaten aller Objekte ändern. Dabei, wenn Sie schauen möchten, was früher geschah und hätten das Chart abgespielt, so würde auch die ganze Tabelle der Signale geschoben. Aber aus jeder beliebigen Regel gibt es die Ausnahme. Im Arsenal der graphischen Objekte gibt es OBJ_LABEL. Es ist ein Textzeichen, welches Positionen nicht der Preise sondern der Zeit ermittelt, und die Koordinate bezüglich des Fensters in den Pixels. Das ist ganz einfach:



Wir sehen das gewöhnliche Textzeichen «Х». Wenn Sie in die Eigenschaften dieses Objektes reingehen, so werden Sie sehen, dass die Koordinaten in den Pixels eingegeben werden. Das Pixel ist ein winziger Punkt am Bildschirm. Beachten Sie, dass der linke obere Winkel des Fensters die Koordinaten x=0 und y=0 (0,0) hat. Wenn x vergrößert wird, so wird sich das Objekt nach rechts bewegen, wenn verringern – nach links . Es ist mit der Koordinate y ähnlich. Wenn es vergrößert wird, so wird das Objekt sich nach unten bewegen, wenn es verringert wird – nach oben. Es ist wichtig, zu verstehen und sich dieses Prinzip zu merken. Damit man damit schneller zu Recht kommt, erstellen Sie ein Zeichen, verschieben Sie sie und sehen Sie, wie sich die Koordinaten in den Eigenschaften ändern. Auch schauen Sie die alten Notierungen, blättern Sie das Chart durch. Beachten Sie, dass dabei das Zeichen sich nicht bewegt. Durch die Verwendung solcher Zeichen wie die Grundlage, können wir den Signalindikator erstellen, der keine Nachteile haben wird, die oben geschrieben wurden.


Die Möglichkeiten des Textzeichens

Unser Signalindikator wird nur die Textzeichen verwenden, deshalb lass uns bitte, ihre Möglichkeiten besser kennenzulernen. Als erste erstellen Sie den neuen Indikator (verwenden Sie keine Puffer von Daten und Parameter) und ändern Sie die Funktion init() :

int init()
{
   // jetzt werden wir das Textzeichen erstellen.
   // dazu wie immer verwenden wir die Funktion ObjectCreate.
   // Es müssen keine Koordinaten gegeben werden
   ObjectCreate("signal",OBJ_LABEL,0,0,0,0,0);
 
   // ändern wir die Koordinate х
   ObjectSet("signal",OBJPROP_XDISTANCE,50);
 
   // ändern wir die Koordinate у
   ObjectSet("signal",OBJPROP_YDISTANCE,50);
 
   // um den Text des Zeichens zu bezeichnen, verwenden wir diese Funktion
   ObjectSetText("signal","lambada",14,"Tahoma",Gold);
   der Name des Objektes
   // "lambada" - der Text des Zeichens
   // 14 - Schriftgröße
   // Gold - Farbe
 
   return(0);
}

Wie Sie sehen können, ist es ziemlich einfach. Die Funktion ObjectCreate() werden wir nur bei der Initialization für die Erstellung aller notwendigen Objekte verwenden. Und mit der Hilfe ObjectSetText() werden wir die Aussicht der Objekte bei jeder Veränderung des Preises in der Funktion start(). ändern. Auch jetzt muss man die Funktion deinit(): ändern

int deinit()
{
   // bei der Entfernung unseres Indikators, entfernen wir alle Objekte
   ObjectsDeleteAll();
 
   return(0);
}

Jetzt starten Sie den Indikator und schauen Sie das Ergebnis:

Wir werden die folgenden Möglichkeiten des Zeichens verwenden:

  • Wir werden die Schrift auf Wingdings ändern, damit uns die speziellen Symbole-Zeichen (von Quadraten und Kreisen bis zu Smiles) zugänglich werden :

  • Wir werden die Farbe und den Text des Zeichens ändern
  • Wir werden die Anordnung und den Umfang des Zeichens wechseln

Wir verwenden die Schrift Wingdings

Jetzt erstellen wir die Zeichen unter Verwendung der Schrift Wingdings. Ändern Sie die Funktion start():

int init()
{
 
   ObjectCreate("signal",OBJ_LABEL,0,0,0,0,0);
   ObjectSet("signal",OBJPROP_XDISTANCE,50);
   ObjectSet("signal",OBJPROP_YDISTANCE,50);
 
   // Wir verwenden die Zeichen aus der Schrift Wingdings
   ObjectSetText("signal","lambada",14,"Tahoma",Gold);
   // CharToString() - Diese Funktion gibt die Zeile mit dem einzigen
   // Symbol zurück, dessen Code Sie im einzigen Argument bezeichnen.
   // wählen Sie das Ihnen gefallende Zeichen aus der oberen Tabelle und
   // schreiben Sie seine Nummer in dieser Funktion ein
   // 60 - wird die große Schrift verwendet
   // "Wingdings" - Wir verwenden die Schrift Wingdings
 
   return(0);
}

Schauen wir auf das Ergebnis:


Wir zeichnen das Muster der Signale-Tabelle

Jetzt zeichnen wir das Muster der Signale-Tabelle. Es wird einfach der Haufen aus Quadraten sein:

int init()
{
   //Es werden 2 Loops sein. Die erste Loop, mit dem Zähler "x" zeichnet nacheinander
   // Jede Spalte von links nach rechts. Die zweite Loop zeichnet die Zeichen von jeder
   // Spalte von oben nach unten. Auf jeder Iteration der Loop wird es ein Zeichen erstellt.
   // Diese 2 Loops erstellen 9 Spalten (9 Perioden) auf 3 Zeichen (3 Typs der Signale)
   // bei jedem.
   for(intx=0;x<9;x++)
      for(inty=0;y<3;y++)
      {
         ObjectCreate("signal"+x+y,OBJ_LABEL,0,0,0,0,0);
         // Erstellen wir das nächste Zeichen. Beachten Sie, dass der Zeichensname 
         // im Laufe erstellt wird und es hängt von Zählern "x" und "y" ab
 
         ObjectSet("signal"+x+y,OBJPROP_XDISTANCE,x*20);
         // ändern wir die Koordinate х.
         // x*20 - entsteht jedes Zeichen mit dem Intervall in 20 Pixels
         // auf der Horizontal-Linie und es hängt direkt vom Zähler "x" ab
 
         ObjectSet("signal"+x+y,OBJPROP_YDISTANCE,y*20);
         // ändern wir die Koordinate Y.
         // y*20 - entsteht jedes Zeichen mit dem Intervall in 20 Pixels
         // auf der Vertikal-Linie und es hängt direkt vom Zähler "y" ab
 
         ObjectSetText("signal"+x+y,CharToStr(110),20,"Wingdings",Gold);
         // wir verwenden den 110-Code des Symbols, der dem Quadrat entspricht
      }
   
   return(0);
}



Das Muster ist fertig. Lassen Sie uns bitte die Einzüge links und oben hinzufügen, damit die Tabelle den Text des Terminalen nicht verdeckte:

int init()
{
   for(int x=0;x<9;x++)
      for(int y=0;y<3;y++)
      {
         ObjectCreate("signal"+x+y,OBJ_LABEL,0,0,0,0,0);
         ObjectSet("signal"+x+y,OBJPROP_XDISTANCE,x*20+12);
         // Wir werden den horizontalen Einzug in 12 Pixels hinzufügen
         ObjectSet("signal"+x+y,OBJPROP_YDISTANCE,y*20+20);
         // Wir werden den vertikalen Einzug in 20 Pixels hinzufügen
         ObjectSetText("signal"+x+y,CharToStr(110),20,"Wingdings",Gold);
      }
 
   return(0);
}



Muster

Jetzt lassen Sie uns bitte zwingen, mindestens einen Quadrat zu arbeiten. Wir nehmen an, der obere linke wird das Signal der gleitenden Mittelwerte auf der minutenlangen Timeframe (M1) zeigen. Wenn das Signal auf den Kauf kommt, so werden wir den Quadrat in die grüne Farbe färben, wenn auf den Verkauf in die rote Farbe färben. Dazu muss man die Funktion start() ändern, also los:

int start()
{
   // wenn  der schnelle gleitende Mittelwert  (die Periode - 13)  größer ist als  langsame ,
   // so ist es das Signal auf den Kauf. Wir prüfen die letzte Bar
   if(iMA(Symbol(),1,13,0,0,0,0)>iMA(Symbol(),1,24,0,0,0,0))
      ObjectSetText("signal00",CharToStr(110),20,"Wingdings",YellowGreen);
   // wir ändern die Farbe des Zeichens mit dem Namen "signal00" (das ganz links oben)
   um// die Grüne
 
   else
   // sonst, wenn der schnelle Mittelwert weniger als der langsame ist, so ist es das Signal auf den Verkauf
      ObjectSetText("signal00",CharToStr(110),20,"Wingdings",Tomato); 
      // Wir ändern die Farbe des Zeichens um die rote Farbe
 
   return(0);
}



Wir machen die obere Reihe an

Wir setzen die Arbeit fort. Dem linkten Quadrat entspricht die kleinere Timeframe – M1. Jetzt machen wir mal so, dass jeder folgende Quadrat (nach der Horizontale-Linie) für die größere Timeframe verantworte. So wird es zum Beispiel der zweite Quadrat die Signale auf M5 zeigen, der dritte – auf M15 und so weiter bis zu MN1. Natürlich, das alles werden wir in der Loop machen. Denken Sie selber nach. Denn, alles, was sich ändert, ist es nur der Name des Zeichens und die Periode, welches wir aufrufen. Die Quadrate sind nur 9, deshalb wird nur ein Zähler verwendet. Aber hier entsteht das Problem mit den Perioden, da es sich ohne Gesetzmäßigkeit ändert. Schauen Sie mal:


Der erste Gedanke: die Loop zieht hier nicht. Aber doch! Alles, was man machen muss, muss man bloß ein spezielles Array gleich am Anfang des Codes des Indikators erklären, Sehen Sie weiter:

//////////////////////////////////////////////////////////////////////
//
//                                                  signalTable.mq4 
//                                                     Antonuk Oleg 
//                                            antonukoleg@gmail.com 
//
//////////////////////////////////////////////////////////////////////
#property copyright "Antonuk Oleg"
#property link      "antonukoleg@gmail.com"
 
#property indicator_chart_window
 
intperiod[]={1,5,15,30,60,240,1440,10080,43200};

Alle Perioden wurden in Arrays geschrieben, nun kann man sie ohne Probleme in der Loop verwenden:

int start()
{
   // Wir verwenden die Loop, um alle Quadraten der ersten Linie anzumachen
   for(int x=0;x<9;x++)
   {
      if(iMA(Symbol(),period[x],13,0,0,0,0)>iMA(Symbol(),period[x],24,0,0,0,0))
         ObjectSetText("signal"+x+"0",CharToStr(110),20,"Wingdings",YellowGreen);
         // "signal"+x+"0" - wir erstellen dynamisch den Namen des Zeichens je nach dem
         // Zähler "х"
      else
         ObjectSetText("signal"+x+"0",CharToStr(110),20,"Wingdings",Tomato); 
   }
 
   return(0);
}

Wir verwenden das Array period[] wie die Tabelle der Werte-Übereinstimmung des Zählers «х» und der Periode. Stellen Sie sich vor, wie viel man einen Code schreiben sollte, wenn dieser kleine Arrays nicht existierte! Schauen wir auf das Ergebnis, die erste Reihe der Signal-Quadraten ist fertig:





Wir fügen die Aufschriften hinzu

Nicht schlecht, aber es ist unklar, welcher Quadrat, welcher Timeframe entspricht, deshalb werden wir die erklärenden Aufschriften über Quadraten erstellen. Hier werden wir auch «das Array der Übereinstimmungen» verwenden, das die Aufschriften für jede Spalte speichern wird:

#property indicator_chart_window
 
int period[]={1,5,15,30,60,240,1440,10080,43200};  
 
stringperiodString[]={"M1","M5","M15","M30","H1","H4","D1","W1","MN1"};

Die Aufschriften erstellen wir in init() durch die Verwendung der Loop:

int init()
{
   for(int x=0;x<9;x++)
      for(int y=0;y<3;y++)
      {
         ObjectCreate("signal"+x+y,OBJ_LABEL,0,0,0,0,0);
         ObjectSet("signal"+x+y,OBJPROP_XDISTANCE,x*20+12);
         ObjectSet("signal"+x+y,OBJPROP_YDISTANCE,y*20+20);
         ObjectSetText("signal"+x+y,CharToStr(110),20,"Wingdings",Gold);
      }
 
   // Wir erstellen die Aufschriften der Perioden von links nach rechts 
   for(x=0;x<9;x++)
   {
      // Genauso wie immer
      ObjectCreate("textPeriod"+x,OBJ_LABEL,0,0,0,0,0);
      ObjectSet("textPeriod"+x,OBJPROP_XDISTANCE,x*20+12);
      ObjectSet("textPeriod"+x,OBJPROP_YDISTANCE,10);
      ObjectSetText("textPeriod"+x,periodString[x],8,"Tahoma",Gold);
      // Wir verwenden das Array periodString[], um die Aufschriften zu bezeichnen
   }
   
   return(0);
}




Wir fügen ein wenig Parameter hinzu

Die Zeit ist, den Indikator flexibler zu machen, ein Paar Parameter hinzuzufügen, damit der Benutzer die Aussicht des Indikators selbst einstellen konnte:

#property copyright "Antonuk Oleg"
#property link      "antonukoleg@gmail.com"
 
#property indicator_chart_window
 
extern int scaleX=20, // Das horizontale Intervall, mit dem die Quadraten erstellt werden
           scaleY=20, // Das vertikale Intervall
           offsetX=35, // der horizontalen Einzug aller Quadraten
           offsetY=20, // der vertikale Einzug
           fontSize=20; // Die Schriftgröße
           
int period[]={1,5,15,30,60,240,1440,10080,43200};
string periodString[]={"M1","M5","M15","M30","H1","H4","D1","W1","MN1"};

Auch muss man den Code der Funktion init() und start() ändern, damit alles funktioniert:

int init()
{
   for(int x=0;x<9;x++)
      for(int y=0;y<3;y++)
      {
         ObjectCreate("signal"+x+y,OBJ_LABEL,0,0,0,0,0);
         ObjectSet("signal"+x+y,OBJPROP_XDISTANCE,x*scaleX+offsetX);
         ObjectSet("signal"+x+y,OBJPROP_YDISTANCE,y*scaleY+offsetY);
         ObjectSetText("signal"+x+y,CharToStr(110),fontSize,"Wingdings",Gold);
      }
 
   for(x=0;x<9;x++)
   {
      ObjectCreate("textPeriod"+x,OBJ_LABEL,0,0,0,0,0);
      ObjectSet("textPeriod"+x,OBJPROP_XDISTANCE,x*scaleX+offsetX);
      ObjectSet("textPeriod"+x,OBJPROP_YDISTANCE,offsetY-10);
      ObjectSetText("textPeriod"+x,periodString[x],8,"Tahoma",Gold);
   }
   
   return(0);
}
 
int start()
{
   for(int x=0;x<9;x++)
   {
      if(iMA(Symbol(),period[x],13,0,0,0,0)>iMA(Symbol(),period[x],24,0,0,0,0))
         ObjectSetText("signal"+x+"0",CharToStr(110),fontSize,"Wingdings",YellowGreen);
      else
         ObjectSetText("signal"+x+"0",CharToStr(110),fontSize,"Wingdings",Tomato); 
   }
 
   return(0);
}

Wir machen die anderen Reihen an

Die zweite Reihe bei uns wird für die Signale von Williams’ Percent Range verantwortlich sein, und die dritte Parabolic SAR. Ändern Sie die Funktion start():

int start()
{
   for(int x=0;x<9;x++)
   {
      if(iMA(Symbol(),period[x],13,0,0,0,0)>iMA(Symbol(),period[x],24,0,0,0,0))
         ObjectSetText("signal"+x+"0",CharToStr(110),fontSize,"Wingdings",YellowGreen);
      else
         ObjectSetText("signal"+x+"0",CharToStr(110),fontSize,"Wingdings",Tomato);
   }

   // Wir machen die zweite Reihe an
   for(x=0;x<9;x++)
   {
      // wenn der absolute Wert WPR weniger als 20 ist, so ist es das Signal auf den Kauf
      if(MathAbs(iWPR(Symbol(),period[x],13,0))<20.0)
         ObjectSetText("signal"+x+"1",CharToStr(110),fontSize,"Wingdings",YellowGreen);  
      // wenn der absolute Wert WPR größer als 80 ist, so ist es das Signal auf den Verkauf
      else if(MathAbs(iWPR(Symbol(),period[x],13,0))>80.0)
         ObjectSetText("signal"+x+"1",CharToStr(110),fontSize,"Wingdings",Tomato);  
      // Sonst, wenn es keine Signale gibt, dann färben wir die Quadraten in die braune Farbe
      else
         ObjectSetText("signal"+x+"1",CharToStr(110),fontSize,"Wingdings",DarkGray);      
   }

   // Wir machen die dritte Reihe an
   for(x=0;x<9;x++)
   {
      // Wenn der laufende Preis mehr als der Wert SAR ist, so ist es das Signal auf den Kauf
      if(iSAR(Symbol(),period[x],0.02,0.2,0)<Close[0])
         ObjectSetText("signal"+x+"2",CharToStr(110),fontSize,"Wingdings",YellowGreen);
      // sonst ist es das Signal auf den Verkauf
      else
         ObjectSetText("signal"+x+"2",CharToStr(110),fontSize,"Wingdings",Tomato);
   }

   return(0);
}




Wir fügen den Namen der Signale hinzu

Die Zeit ist, jede Reihe zu benennen. Wir erstellen 3 Aufschriften links, durch die Verwendung des Arrays wie zuvor:

int period[]={1,5,15,30,60,240,1440,10080,43200};
string periodString[]={"M1","M5","M15","M30","H1","H4","D1","W1","MN1"},
       // Wir erstellen noch ein Array mit den Namen der Indikatoren
       signalNameString[]={"MA","WPR","SAR"};

Ändern wir die Funktion init():

int init()
{
   for(int x=0;x<9;x++)
      for(int y=0;y<3;y++)
      {
         ObjectCreate("signal"+x+y,OBJ_LABEL,0,0,0,0,0);
         ObjectSet("signal"+x+y,OBJPROP_XDISTANCE,x*scaleX+offsetX);
         ObjectSet("signal"+x+y,OBJPROP_YDISTANCE,y*scaleY+offsetY);
         ObjectSetText("signal"+x+y,CharToStr(110),fontSize,"Wingdings",Gold);
      }
 
   for(x=0;x<9;x++)
   {
      ObjectCreate("textPeriod"+x,OBJ_LABEL,0,0,0,0,0);
      ObjectSet("textPeriod"+x,OBJPROP_XDISTANCE,x*scaleX+offsetX);
      ObjectSet("textPeriod"+x,OBJPROP_YDISTANCE,offsetY-10);
      ObjectSetText("textPeriod"+x,periodString[x],8,"Tahoma",Gold);
   }
   
   // Wir zeichnen den Namen der Signale von oben nach unten
   for(y=0;x<3;y++)
   {
      ObjectCreate("textSignal"+y,OBJ_LABEL,0,0,0,0,0);
      ObjectSet("textSignal"+y,OBJPROP_XDISTANCE,offsetX-25);
      ObjectSet("textSignal"+y,OBJPROP_YDISTANCE,y*scaleY+offsetY+8);
      ObjectSetText("textSignal"+y,signalNameString[y],8,"Tahoma",Gold);
   }
   
   return(0);
}




Wir fügen die Möglichkeit hinzu, den Winkel der Verankerung zu ändern

Jetzt ermöglichen wir dem Benutzer selbst die Anordnung des Signal-Indikators einzustellen. Momentan ist der Winkel der Verankerung ist der obere linke Winkel. Wenn wir die Eigenschaft des Zeichens OBJPROP_CORNER ändern, so ändert sich auch der Winkel der Verankerung. Die Eigenschaft kann die folgenden Werte annehmen:

  • 0 – der linke obere Winkel
  • 1 – der rechte obere Winkel
  • 2 – der linke untere Winkel
  • 3 – der rechte untere Winkel

Deshalb fügen wir einen neuen Parameter hinzu – corner:

#property indicator_chart_window
 
extern int scaleX=20,
           scaleY=20, 
           offsetX=35, 
           offsetY=20, 
           fontSize=20,
           corner=0; // Wir fügen den Parameter für die Auswahl des Winkels der Verankerung

Wir müssen noch die Funktion init() ändern:

int init()
{
   // Die Tabelle der Signalen
   for(int x=0;x<9;x++)
      for(int y=0;y<3;y++)
      {
         ObjectCreate("signal"+x+y,OBJ_LABEL,0,0,0,0,0);
         ObjectSet("signal"+x+y,OBJPROP_CORNER,corner);
         // Wir ändern den Winkel der Verankerung
         ObjectSet("signal"+x+y,OBJPROP_XDISTANCE,x*scaleX+offsetX);
         ObjectSet("signal"+x+y,OBJPROP_YDISTANCE,y*scaleY+offsetY);
         ObjectSetText("signal"+x+y,CharToStr(110),fontSize,"Wingdings",Gold);
      }

   // Der Name der Timeframes
   for(x=0;x<9;x++)
   {
      ObjectCreate("textPeriod"+x,OBJ_LABEL,0,0,0,0,0);
      ObjectSet("textPeriod"+x,OBJPROP_CORNER,corner);
      // Wir ändern den Winkel der Verankerung
      ObjectSet("textPeriod"+x,OBJPROP_XDISTANCE,x*scaleX+offsetX);
      ObjectSet("textPeriod"+x,OBJPROP_YDISTANCE,offsetY-10);
      ObjectSetText("textPeriod"+x,periodString[x],8,"Tahoma",Gold);
   }

   // Der Name der Indikatoren
   for(y=0;x<3;y++)
   {
      ObjectCreate("textSignal"+y,OBJ_LABEL,0,0,0,0,0);
ObjectSet("textSignal"+y,OBJPROP_CORNER,corner);// Wir ändern den Winkel der Verankerung
      ObjectSet("textSignal"+y,OBJPROP_XDISTANCE,offsetX-25);
      ObjectSet("textSignal"+y,OBJPROP_YDISTANCE,y*scaleY+offsetY+8);
      ObjectSetText("textSignal"+y,signalNameString[y],8,"Tahoma",Gold);
   }
  
   return(0);
}

wir fügen neue Parameter hinzu

Man muss noch einige Parameter für die flexible Einstellung der Aussicht unseres Indikators hinzufügen. Stellen wir in die Parameter:

  • alle möglichen Farben
  • alle Codes der Symbole

Zuerst erklären wir alle diese Parameter am Anfang des Codes:

extern int scaleX=20,
           scaleY=20,
           offsetX=35,
           offsetY=20,
           fontSize=20,
           corner=0,
           symbolCodeBuy=110, // der Code des Symbols auf de Kauf
           symbolCodeSell=110, // auf den Verkauf
           symbolCodeNoSignal=110; // wenn es kein Signal gibt
          
extern color signalBuyColor=YellowGreen, // die Symbol-Farbe für das Signal auf den Kauf
             signalSellColor=Tomato, // auf den Verkauf
             noSignalColor=DarkGray, // kein Signal
             textColor=Gold; // die Farbe aller Aufschriften

Ändern wir die Funktion init():

int init()
{
   // Die Tabelle der Signalen
   for(int x=0;x<9;x++)
      for(int y=0;y<3;y++)
      {
         ObjectCreate("signal"+x+y,OBJ_LABEL,0,0,0,0,0);
         ObjectSet("signal"+x+y,OBJPROP_CORNER,corner);
         ObjectSet("signal"+x+y,OBJPROP_XDISTANCE,x*scaleX+offsetX);
         ObjectSet("signal"+x+y,OBJPROP_YDISTANCE,y*scaleY+offsetY);
         ObjectSetText("signal"+x+y,CharToStr(symbolCodeNoSignal),
                       fontSize,"Wingdings",noSignalColor);
      }

   // Der Name der Timeframes
   for(x=0;x<9;x++)
   {
      ObjectCreate("textPeriod"+x,OBJ_LABEL,0,0,0,0,0);
      ObjectSet("textPeriod"+x,OBJPROP_CORNER,corner);
      ObjectSet("textPeriod"+x,OBJPROP_XDISTANCE,x*scaleX+offsetX);
      ObjectSet("textPeriod"+x,OBJPROP_YDISTANCE,offsetY-10);
      ObjectSetText("textPeriod"+x,periodString[x],8,"Tahoma",textColor);
   }

   // Der Name der Indikatoren
   for(y=0;x<3;y++)
   {
      ObjectCreate("textSignal"+y,OBJ_LABEL,0,0,0,0,0);
      ObjectSet("textSignal"+y,OBJPROP_CORNER,corner);
      ObjectSet("textSignal"+y,OBJPROP_XDISTANCE,offsetX-25);
      ObjectSet("textSignal"+y,OBJPROP_YDISTANCE,y*scaleY+offsetY+8);
      ObjectSetText("textSignal"+y,signalNameString[y],8,"Tahoma",textColor);
   }
  
   return(0);
}

Wir ändern die Funktion start():

int start()
{
   for(int x=0;x<9;x++)
   {
      if(iMA(Symbol(),period[x],13,0,0,0,0)>iMA(Symbol(),period[x],24,0,0,0,0))
         ObjectSetText("signal"+x+"0",CharToStr(symbolCodeBuy),fontSize,
         "Wingdings",signalBuyColor);
      else
         ObjectSetText("signal"+x+"0",CharToStr(SymbolCodeSell),fontSize,
         "Wingdings",signalSellColor);
   }

   for(x=0;x<9;x++)
   {
      if(MathAbs(iWPR(Symbol(),period[x],13,0))<20.0)
         ObjectSetText("signal"+x+"1",CharToStr(symbolCodeBuy),fontSize,
         "Wingdings",signalBuyColor);  
      else if(MathAbs(iWPR(Symbol(),period[x],13,0))>80.0)
         ObjectSetText("signal"+x+"1",CharToStr(symbolCodeSell),fontSize,
         "Wingdings",signalSellColor);  
      else
         ObjectSetText("signal"+x+"1",CharToStr(symbolCodeNoSignal),fontSize,
         "Wingdings",noSignalColor);      
   }

   for(x=0;x<9;x++)
   {
      if(iSAR(Symbol(),period[x],0.02,0.2,0)<Close[0])
         ObjectSetText("signal"+x+"2",CharToStr(symbolCodeBuy),fontSize,
         "Wingdings",signalBuyColor);
      else
         ObjectSetText("signal"+x+"2",CharToStr(symbolCodeSell),fontSize,
         "Wingdings",signalSellColor);
   }

   return(0);
}

Wir ändern die Aussicht

Der Indikator ist fertig. Durch die Änderung der Eingangsparameter kann man vollständig die Aussicht ändern:

extern int scaleX=20,
           scaleY=20,
           offsetX=35,
           offsetY=20,
           fontSize=20,
           corner=2,
           symbolCodeBuy=67,
           symbolCodeSell=68,
           symbolCodeNoSignal=73;
          
extern color signalBuyColor=Gold,
             signalSellColor=MediumPurple,
             noSignalColor=WhiteSmoke,
             textColor=Gold;



Eine Hausaufgabe

Denken Sie sich die Bedingungen der Signale aus und Fügen Sie noch eine Reihe hinzu. Erstellen Sie noch einige Parameter. Zum Beispiel, den Parameter, der die Größe der Schrift für die Aufschriften (Timeframe und die Namen der Signale) bestimmt. Stellen Sie die Aussicht des Indikators nach eigenem Ermessen ein.


Fazit

Heute haben wir gelernt, die graphischen Objekte in Skripten und Indikatoren zu verwenden. Wir haben erfahren, wie Objekte erstellt werden können, ihre Parameter ändern, Fehler überprüfen. Sie haben alle notwendige Wissen bekommen, um mit den neuen Typen der graphischen Objekte selbst klar zu kommen. Auch haben Sie Schritt um Schritt einen komplizierten Signalindikator erstellt, den man sehr flexibel einstellen kann.