English Русский 中文 Español 日本語 Português
preview
Von der Grundstufe bis zur Mittelstufe: Indikator (IV)

Von der Grundstufe bis zur Mittelstufe: Indikator (IV)

MetaTrader 5Beispiele |
105 0
CODE X
CODE X

Einführung

Im vorherigen Artikel „Von der Grundstufe zur Mittelstufe: Indikator (III)“ haben wir besprochen, wie man jede Art von Indikator auf einfache und praktische Weise mit Hilfe von Kompilieranweisungen erstellen kann. Aber wir können und sollten das nicht immer so machen. Dieser Ansatz wird als statische Implementierung bezeichnet, da der Nutzer nach der Definition des Indikatortyps die Art der Darstellung nicht mehr ändern kann (oder besser gesagt, nicht ändern darf).

Die Zahl der Indikatoren kann jedoch weitaus größer sein, als bisher dargestellt wurde. Für eine breite Palette von Tätigkeiten ist diese Art der Umsetzung bereits mehr als ausreichend. Es gibt jedoch Situationen, in denen der Handel oder die Marktanalyse etwas andere Indikatoren erfordern.

In diesem Artikel erfahren Sie, wie Sie mehrere verschiedene Indikatoren erstellen können. Diese Indikatoren sind sehr nützlich für die Kommunikation mit anderen Händlern und für die automatische Analyse bestimmter Arten von Kursbewegungen, wenn Sie so wollen.

Beginnen wir also mit etwas sehr Einfachem und, wie ich finde, sehr Interessantem. Wir können viele andere Indikatoren mit einem sehr einfachen und verständlichen Konzept erstellen.


Innerer Balkenindikator

Es gibt eine Art von Indikator bzw. eine Handelsmethodik, die einen so genannten inneren Balken verwendet. Ein innerer Balken ist buchstäblich ein Balken oder eine Kerze, die sich innerhalb des unmittelbar vorangegangenen Balkens befindet. Je nach Händler und Symbol kann jedoch jeder Balken, der sich innerhalb eines anderen Balkens – nicht notwendigerweise des unmittelbar vorhergehenden – befindet, als innerer Balken betrachtet werden, wenn die Kursbewegung nicht aus diesem Balken ausgebrochen ist und er sich in einiger Entfernung befinden kann. Diese letztere Art, etwas als einen inneren Balken zu betrachten, wird jedoch von den meisten Händlern nicht als Grundsatz akzeptiert.

In jedem Fall existiert dieses Handels-Setup und erweist sich zu verschiedenen Zeitpunkten als sehr überzeugend. Obwohl die ständige Analyse eines Charts, um zu verstehen, ob wir einen inneren Balken sehen oder nicht, ist, um es milde auszudrücken, ziemlich schwierig für viele Menschen, besonders für Anfänger. Daher können wir einen Indikator verwenden, der das Chart verfolgt und uns anzeigt, ob eine solche Formation vorhanden ist, wenn das Chart offen und aktiv ist.

Wichtiger Hinweis: Ein innerer Balken ist NICHT unbedingt ein Doji.

„Okay, aber warum haben Sie beschlossen, zu zeigen, wie man diesen Indikator erstellt?“ Der Grund ist ganz einfach, mein Freund. Viele unerfahrene Händler versuchen, Indikatoren zu erstellen, um den Kerzen oder Balken, wie sie oft genannt werden, Farbmuster hinzuzufügen. Und diese Programmieranfänger geben schließlich auf, weil sie nicht wissen, wie der Indikator deklariert werden soll. Es ist nicht so, dass das Erstellen eines Farbmusters auf Kerzen eine schwierige Aufgabe ist. Das Problem liegt woanders: Die Erstellung des Indikators selbst ist, wie man sich vorstellen kann, eine recht einfache Aufgabe.

Wie bei anderen Indikatoren, die in früheren Artikeln dargestellt wurden, ist jedoch bei der Angabe von Puffern Vorsicht geboten. Wenn Sie schon einmal versucht haben, ein Farbmuster auf Kerzen zu gestalten, wissen Sie, dass dies für jeden Anfänger eine schwierige Aufgabe sein kann. Wenn wir dies in der falschen Reihenfolge tun oder die Pufferindizes in der falschen Reihenfolge eingeben, zeigt der MetaTrader 5 auf dem Chart etwas anderes an, als wir erwartet haben. Sie können weder MetaTrader 5 noch dem Programmierer die Schuld geben, denn je nachdem, was wir implementieren wollen, wird es für die einen ein Fehler sein und für die anderen genau das, was wir brauchen.

Wir beginnen also mit der Deklaration des Indikators selbst, noch bevor wir den inneren Balkenindikator erstellen. In der Regel kann alles auf unterschiedliche Weise deklariert werden, wie im folgenden Code gezeigt:

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. #property indicator_type1       DRAW_COLOR_CANDLES
05. #property indicator_color1      clrRed, clrRoyalBlue, clrGreen
06. //+----------------+
07. #property indicator_buffers     5
08. #property indicator_plots       1
09. //+----------------+
10. double  gl_Buff_High[],
11.         gl_Buff_Open[],
12.         gl_Buff_Close[],
13.         gl_Buff_Low[],
14.         gl_Buff_Color[];
15. //+------------------------------------------------------------------+
16. int OnInit()
17. {
18.     SetIndexBuffer(0, gl_Buff_High, INDICATOR_DATA);
19.     SetIndexBuffer(1, gl_Buff_Open, INDICATOR_DATA);
20.     SetIndexBuffer(2, gl_Buff_Close, INDICATOR_DATA);
21.     SetIndexBuffer(3, gl_Buff_Low, INDICATOR_DATA);
22.     SetIndexBuffer(4, gl_Buff_Color, INDICATOR_COLOR_INDEX);
23. 
24.     return INIT_SUCCEEDED;
25. };
26. //+------------------------------------------------------------------+
27. int OnCalculate(const int rates_total, const int prev_calculated, const datetime &Time[], const double &Open[], const double &High[], const double &Low[], const double &Close[], const long &TickVolume[], const long &Volume[], const int &Spread[])
28. {
29.     for (int c = (prev_calculated > 0 ? prev_calculated - 1 : 0); c < rates_total; c++)
30.     {
31.         gl_Buff_High[c] = High[c];
32.         gl_Buff_Open[c] = Open[c];
33.         gl_Buff_Close[c] = Close[c];
34.         gl_Buff_Low[c] = Low[c];
35. 
36.         gl_Buff_Color[c] = (Open[c] > Close[c] ? 0 : 2);
37.     }
38. 
39.     return rates_total;
40. };
41. //+------------------------------------------------------------------+

Code 01

Nun frage ich Sie, liebe Leser: Ist das, was wir in Code 01 sehen, richtig oder nicht? Die richtige Antwort auf diese Frage lautet: Es kommt auf das Ziel an, das wir verfolgen. In jedem Fall ist eine solche Implementierung von Code 01 nicht völlig falsch, da der Code kompiliert wird und nützlich sein kann. Je nach Zielsetzung kann dieser Code jedoch falsch sein. Achten Sie daher darauf, was passiert, wenn Sie diesen Code in einem beliebigen Chart verwenden. Dies ist in der folgenden Animation zu sehen:

Animation 01

Mit anderen Worten: Das Ergebnis war nicht ganz wie erwartet. Warum? „Das verstehe ich nicht. Der Code scheint korrekt zu sein. Ich habe bei der Deklaration der Puffer nichts falsch gemacht. Das Ergebnis war jedoch erwartungsgemäß: Die Balken änderten sich nicht nur in der Farbe, sondern auch im Format. Ich kann nicht herausfinden, was los ist. Gibt es einen Trick, damit alles funktioniert und das gewünschte Ergebnis erzielt wird?“ In diesem Fall ja, liebe Leser.

Obwohl der Code korrekt ist, weil er die Farbe der Balken wie erwartet geändert hat, kann das Gleiche nicht über die Änderung der Formatierung gesagt werden. Wenn das Ziel darin besteht, die Farben zu ändern und gleichzeitig die Balken zu modifizieren, dann ja. Das ist jedoch nicht das, was wir beabsichtigen. Der Grund liegt in der falschen Reihenfolge der Pufferdeklaration. Wenn MetaTrader 5 also die Puffer verwendet, geschieht dies in einer bestimmten Reihenfolge. Durch die falsche Reihenfolge wurde das Balkenformat verändert. Da wir dies wissen, müssen wir diese Reihenfolge nur noch in eine geeignete Reihenfolge ändern. Diese einfache Änderung ist im nachstehenden Code zu sehen: 

                   .
                   .
                   .
18.     SetIndexBuffer(1, gl_Buff_High, INDICATOR_DATA);
19.     SetIndexBuffer(0, gl_Buff_Open, INDICATOR_DATA);
20.     SetIndexBuffer(3, gl_Buff_Close, INDICATOR_DATA);
21.     SetIndexBuffer(2, gl_Buff_Low, INDICATOR_DATA);
                   .
                   .
                   .

Code 02

Bitte beachten Sie, dass sich im Codefragment 02 nur der Indexwert der einzelnen Puffer geändert hat. Unter Verwendung dieser Puffersequenz (Open, High, Low und Close) ist das von Code 01 erzeugte Ergebnis unten zu sehen:

Animation 02

Ist Ihnen aufgefallen, dass MetaTrader 5 jetzt weiß, wie jeder Balken oder jede Kerze gezeichnet werden soll? Dies ist eine sehr einfache Aufgabe für diejenigen, die bereits wissen, wie sie zu lösen ist. Für diejenigen, die das nicht verstehen, kann es jedoch äußerst schwierig erscheinen. Auf jeden Fall wissen Sie jetzt, wie es geht, und können mit dem Aufbau von Farbmustern fortfahren, um Indikatoren zu erstellen und das gewünschte Handelssystem zu modellieren. Um zu demonstrieren, wie dies geschehen kann, wollen wir das Problem lösen und den inneren Balken direkt im Chart anzeigen.

Um dieses Problem zu lösen, sehen Sie sich Zeile 36 an, in der beschrieben wird, wie wir den Farbindex berechnen. Dies ist der Index Null für einen Verkaufsbalken oder der Index zwei für einen Kaufbalken. Aber was nützt uns dieser Index? Wir belassen diesen Index für das, was der innere Balken werden soll.

Jetzt kommt der entscheidende Moment. Die Schleife ab Zeile 29 beginnt an einem alten Punkt, der der erste Balken im Chart sein kann (oder auch nicht), und sucht dann nach dem letzten Balken im Chart. Dies ist wichtig zu wissen und zu verstehen, da ein innerer Balken nur dann markiert werden kann, wenn es einen vorherigen Balken mit bestimmten Merkmalen gibt. Andernfalls darf der aktuelle Balken nicht berücksichtigt und im Chart als innerer Balken angezeigt werden.

Es ist also alles klar, es müssen nur noch die Prüfkriterien umgesetzt werden. Dazu müssen wir den obigen Code so ändern, dass er den Balken und Kerzen Farben zuweisen kann und zusätzlich prüft, ob ein innerer Balken vorhanden ist oder nicht. Diese Erweiterung ist in Codefragment 03 dargestellt:

                   .
                   .
                   .
36.         gl_Buff_Color[c] = (Open[c] > Close[c] ? 0 : 2);
37.         if ((c - 1) > 0)
38.             gl_Buff_Color[c] = ((High[c - 1] > High[c]) && (Low[c - 1] < Low[c]) ? 1 : gl_Buff_Color[c]);
39.     }
40. 
41.     return rates_total;
42. };
43. //+------------------------------------------------------------------+

Code 03

Bei jedem Calculate-Ereignis, das unser Indikator empfängt, prüfen wir nun, ob ein innerer Balken im Chart vorhanden ist. Aber Moment mal, warum sollten wir das bei jedem Schritt versuchen? Der Grund dafür ist einfach: Während der Handelsphase kann ein innerer Balken auf dem Chart erscheinen. Es ist jedoch nicht ungewöhnlich, dass sie falsch konfiguriert wird. Dies liegt daran, dass wir das Vorhandensein oder Nichtvorhandensein eines inneren Balkens erst berücksichtigen können, nachdem der Balken oder die Kerze geschlossen wurde. Bis zu diesem Zeitpunkt ist es verfrüht zu behaupten, dass es einen inneren Balken im Chart gibt.

Da jedoch in Zeile 38 regelmäßig geprüft wird, ob die Bedingung des inneren Balkens angewendet werden kann oder nicht, schlägt der Test fehl, wenn der innere Balken dekonfiguriert wird. Da wir also die Farbe in Zeile 36 bereits aktualisiert haben, wird die oben genannte Anzeige nicht mehr im Chart angezeigt.

Obwohl bekannt ist, dass dies funktioniert, sollten wir sehen, wie es in der Praxis abläuft, um zu verstehen, warum wir es auf diese Weise umgesetzt haben. In der folgenden Animation können wir jedoch den Anfangsprozess beobachten. Die Darstellung des zweiten Schritts – die Dekonfiguration dessen, was ein innerer Balken sein sollte – ist jedoch nicht so einfach, da sie einen ganz bestimmten Moment erfordert, und das Erfassen des genauen Punkts würde viel Zeit in Anspruch nehmen.

Animation 03

Hervorragend, hier können wir sehen, wie ein innerer Balken aussehen sollte. Wie bereits erwähnt, gibt es jedoch Händler, die mehrere Balken berücksichtigen und alle diese neuen Balken als innere Balken betrachten, solange die neuen Balken innerhalb der vorherigen Balken bleiben. Dies wirft die Frage auf: Wie könnte man dieselbe Art von Indikator implementieren, indem man den vorherigen Indikator einfach abändert?

Auf diese Frage kann es verschiedene Antworten geben, oder genauer gesagt, verschiedene Möglichkeiten, den betreffenden Mechanismus umzusetzen. Das eigentliche Problem ist nicht die genaue Implementierung des Codes, sondern die Frage, wie ein Wert über einen längeren Zeitraum erhalten werden kann. Im Folgenden wird ein möglicher Vorschlag unterbreitet. Natürlich können Sie je nach Fall einen anderen Ansatz wählen, den Sie interessanter oder geeigneter finden.

Da wir den Prozess so weit wie möglich vereinfachen wollen, werden wir nur eine Änderung an der Implementierung des OnCalculate-Ereignishandlers vornehmen. Der Quellcode, mit dem die Animation 03 erstellt wurde, wird also wie folgt geändert:

                   .
                   .
                   .
26. //+------------------------------------------------------------------+
27. int OnCalculate(const int rates_total, const int prev_calculated, const datetime &Time[], const double &Open[], const double &High[], const double &Low[], const double &Close[], const long &TickVolume[], const long &Volume[], const int &Spread[])
28. {
29.    static double  high = DBL_MIN,
30.                   low = DBL_MAX;
31. 
32.    for (int c = (prev_calculated > 0 ? prev_calculated - 1 : 0); c < rates_total; c++)
33.    {
34.       gl_Buff_High[c] = High[c];
35.       gl_Buff_Open[c] = Open[c];
36.       gl_Buff_Close[c] = Close[c];
37.       gl_Buff_Low[c] = Low[c];
38. 
39.       gl_Buff_Color[c] = (Open[c] > Close[c] ? 0 : 2);
40.       if ((c - 1) > 0)
41.       {
42.          high = (High[c - 1] > high ? High[c - 1] : high);
43.          low = (Low[c - 1] < low ? Low[c - 1] : low);
44.          gl_Buff_Color[c] = ((high > High[c]) && (low < Low[c]) ? 1 : gl_Buff_Color[c]);
45.          if (gl_Buff_Color[c] != 1)
46.          {
47.             high = DBL_MIN;
48.             low = DBL_MAX;
49.          }
50.       }
51.    }
52. 
53.    return rates_total;
54. };
55. //+------------------------------------------------------------------+

Code 04

Und jetzt aufgepasst. Wenn das in Code 04 gezeigte Fragment in den Code eingefügt wird, der die Animation 03 erzeugt hat, wird sich das Ergebnis von der vorherigen Animation unterscheiden. Um dies zu bestätigen, schauen Sie genau hin und vergleichen Sie die untenstehende Animation mit der obigen Animation.

Animation 04

In Animation 04 tun wir genau das, was viele Händler als inneren Balken betrachten. Das heißt, solange das Hoch oder das Tief des vorangegangenen Balkens oder der vorangegangenen Kerze nicht „durchbrochen“ wird, betrachten wir den analysierten Balken als inneren Balken. Ich weiß, dass dies sehr verwirrend erscheinen mag, insbesondere wenn Sie nicht an den Handel oder die Beobachtung innerer Balken gewöhnt sind. Aber das Codefragment 04 ist in der Lage, das Muster zu erkennen, selbst wenn mehrere Balken erscheinen und alle innerhalb eines viel älteren Balkens liegen.

Aber wie funktioniert dann dieses Codeschnipsel, und wie gelingt es ihm, innere Balken zu erkennen, wie in Animation 04 gezeigt? Um dies zu verstehen, müssen Sie zunächst die Funktionsweise des früheren, einfacheren Indikators begreifen. Nur dann können Sie diese Angelegenheit verstehen. Außerdem müssen Sie verstehen, wie statische Variablen funktionieren. Da dieses Thema bereits in einem anderen Artikel behandelt wurde, gehe ich davon aus, dass Sie mit statischen Variablen bereits vertraut sind.

Falls Sie diesen Artikel noch nicht gelesen haben, hier ist er: „Von der Grundstufe zur Mittelstufe: Variablen (II)“. Betrachtet man nun den Code 04, so wird deutlich, dass die notwendige Änderung genau im inneren Balken-Test vorgenommen wurde. Der Test wird dort immer noch durchgeführt. Sie hat jedoch ihre Position geändert, weil wir jetzt, bevor dies geschieht, zwei weitere Tests durchführen. Die erste ist in Zeile 42, wo wir prüfen, ob der Höchststand überschritten wurde. In Zeile 43 führen wir eine ähnliche Prüfung durch, aber in diesem Fall überprüfen wir den niedrigen Verstoß. Wir berücksichtigen also die Grenze, innerhalb derer ein innerer Balken über mehrere verschiedene Balken hinweg bestehen kann, nicht nur über den unmittelbar vorangegangenen. Nur wenn wir diese Grenzen kennen, können wir prüfen, ob der analysierte Balken ein Fortsetzungsbalken ist. Dies geschieht in Zeile 44.

Ein weiterer wichtiger Punkt ist Zeile 45. Hier wird geprüft, ob der Test in Zeile 44 das Vorhandensein eines inneren Balkens anzeigt. Wenn es keinen inneren Balken gibt, müssen die auferlegten Grenzen zerstört werden, um nach der Bildung eines neuen inneren Balkens zu suchen. Würde diese Prüfung in Zeile 45 nicht durchgeführt, käme es ständig zu falschen Messwerten.

Um zu verstehen, was der hier gezeigte innere Balkenindikator ist, sehen wir uns die folgende Animation an.

Animation 05

In Animation 05 können wir etwas sehr Interessantes beobachten: das Vorhandensein eines inneren Balkens zu einem bestimmten Zeitpunkt. Da es jedoch zu einem Durchbruch kam – in diesem Fall wurde das Tief durchbrochen – hörte das, was einmal ein innerer Balken war, auf, ein innerer Balken zu sein und wurde wie jeder andere Balken. Und selbst wenn der Kurs wieder an den Punkt zurückkehrt, an dem wir glauben könnten, dass wir wieder einen inneren Balken haben, zeigt der Indikator ihn nicht an, wie in der Abbildung unten zu sehen ist.

Abbildung 01

Bitte beachten Sie, dass sich das Symbol in den Balken oder die Kerze zurückkehrt, der/die die drei vorherigen inneren Balkenindikationen erzeugt hat. Nach den im Indikator implementierten Kriterien konnte der letzte Balken jedoch nicht mehr als innerer Balken betrachtet werden. Kurz gesagt, der Indikator funktioniert, aber wir müssen die akzeptierten Kriterien definieren und klar formulieren, damit wir die gewünschten Informationen erhalten.

Nun gut, es wurde bereits ausführlich erklärt, wie man Farbindikatoren auf Kerzen anwendet. Nun können wir uns anderen Fragen zuwenden, die mit Indikatoren zu tun haben können (oder auch nicht). Aufgrund der Natur des Begriffs „Indikator“ halte ich es jedoch für angebracht, in diesem Szenario auch andere Dinge zu zeigen.


Was angezeigt werden soll und was nicht

Es ist nicht ungewöhnlich, dass wir für ein und dieselbe Handelsmethodik auf dem Markt unterschiedliche Profile verwenden. Viele Händler bevorzugen es, verschiedene Arten von Informationen ständig auf dem Chart angezeigt zu bekommen. Andere bevorzugen minimale Informationen. Die Entscheidung, was angezeigt werden soll, hängt vom jeweiligen Händler oder Arbeitsprofil ab. Für uns als Programmierer ist dies jedoch völlig irrelevant. Es ist uns egal, wie wir unser eigenes Chart erstellen. Uns geht es nur darum, einfache und bequeme Tools bereitzustellen, damit jeder das Chart nach seinen Wünschen anpassen kann.

Mit MetaTrader 5 können wir vieles davon konfigurieren, ohne dass wir externe Anwendungen benötigen. Es gibt jedoch Elemente, die mit den Optionen des MetaTrader 5 nicht entfernt oder geändert werden können – hier kommt die Programmierung zum Einsatz. Sie als Programmierer müssen verstehen, dass es KEINE EINSCHRÄNKUNGEN dafür gibt, was wir tun können oder nicht. Was es tatsächlich gibt, sind die mehr oder weniger großen technischen Fähigkeiten der einzelnen Programmierer. Einige werden mit einfacheren Methoden auskommen, während andere anspruchsvollere Instrumente benötigen.

In jedem Fall ist es das Ziel, eine Anwendung zu entwickeln, die das Chart in das umwandelt, was wir brauchen, auch wenn es für andere Händler wie ein völliges Chaos erscheinen mag. Aber wenn man versteht, was man geschaffen hat, und vom Handel profitiert, dann ist es das, was wirklich zählt.

Mit MQL5 können wir also verschiedene Chart-Elemente definieren und steuern. Zu Beginn werden wir einige einfache Änderungen vornehmen, die zu bestimmten Zeiten von Interesse sein können. Ziel ist es, zu zeigen, dass wir bei der Verwendung von MQL5 völlige Freiheit und Kontrolle über jedes Chart-Element haben. Wussten Sie zum Beispiel, dass wir den Bereich, in dem die Kurse und die Zeitzone angezeigt werden, aus dem Chart entfernen können? Wenn wir versuchen, dies direkt von MetaTrader 5 aus zu tun, werden wir nicht erfolgreich sein. Eine Möglichkeit, dies zu erreichen, ist jedoch der Code. Übrigens ist der Code, den wir implementieren müssen, recht einfach. Fangen wir also hier an. Der ursprüngliche Code ist unten dargestellt:

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. int OnInit()
05. {
06.     ChartSetInteger(0, CHART_SHOW_DATE_SCALE, false);
07.     ChartSetInteger(0, CHART_SHOW_PRICE_SCALE, false);
08.     
09.     return INIT_SUCCEEDED;
10. };
11. //+------------------------------------------------------------------+
12. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
13. {
14.     return rates_total;
15. };
16. //+------------------------------------------------------------------+

Code 05

Beachten Sie, wie einfach der Code 05 ist. Wir brauchen nichts zu erklären; es ist klar, was wir tun. Wenn wir diesen Code in einem Chart ausführen, erhalten wir das folgende Ergebnis:

Animation 06

In der Tat sind wir ziemlich grob, denn wenn wir die Preis- und Zeitskalen ohne Erlaubnis des Nutzers entfernen, werden sie im Chart nicht wiederhergestellt, selbst wenn der Indikator entfernt wird. Während viele dies für angemessen halten, betrachten andere solche Aktionen als respektlos gegenüber der Anwendung, da die Wiederherstellung der Zeit- und Preisskala das Schließen und erneute Öffnen des Charts erfordert, was die meisten Nutzer nicht tun wollen.

Es stellt sich jedoch die Frage: Wie kann man das Chart in ihren ursprünglichen Zustand zurückversetzen? Und wenn möglich, wann ist der beste Zeitpunkt, um dies zu tun? Nun, es gibt tatsächlich eine Möglichkeit, dies zu erreichen, indem man das Ereignis Deinit abfängt. Wir müssen uns jedoch darüber im Klaren sein, dass es keinen „besten“ Zeitpunkt gibt, sondern nur den „richtigen“ Zeitpunkt. Ich sage dies, weil es passieren kann, dass unsere Anwendung etwas tut, das MetaTrader 5 dazu zwingt, sie aus dem Chart zu entfernen. In diesem Fall wird das Deinit-Ereignis nicht ausgelöst, da die Entfernung erzwungen wird. Folglich bleiben alle von unserer Anwendung vorgenommenen Änderungen im Chart erhalten, und wir müssen es schließen und erneut öffnen, um den ursprünglichen Zustand wiederherzustellen.

Daher sollten solche Änderungen immer mit Bedacht vorgenommen werden. Und wann immer es möglich ist, sollten Sie dem Nutzer die Möglichkeit geben, auszuwählen, was aus dem Chart entfernt werden soll, insbesondere wenn Ihre Anwendung seine Arbeit erleichtern soll.

Nun gut, lassen Sie uns einen höflicheren Weg finden, um das in Animation 06 Gezeigte umzusetzen. Zu diesem Zweck wird Code 05 wie folgt geändert:

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. input bool user01 = true;       //Show time scale
05. input bool user02 = true;       //Show price scale
06. //+----------------+
07. struct st_Mem
08. {
09.     long    View_DateScale,
10.             View_PriceScale;
11. }gl_StyleGraphic;
12. //+------------------------------------------------------------------+
13. int OnInit()
14. {
15.     gl_StyleGraphic.View_DateScale = ChartGetInteger(0, CHART_SHOW_DATE_SCALE);
16.     gl_StyleGraphic.View_PriceScale = ChartGetInteger(0, CHART_SHOW_PRICE_SCALE);
17. 
18.     ChartSetInteger(0, CHART_SHOW_DATE_SCALE, user01);
19.     ChartSetInteger(0, CHART_SHOW_PRICE_SCALE, user02);
20. 
21.     return INIT_SUCCEEDED;
22. };
23. //+------------------------------------------------------------------+
24. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
25. {
26.     return rates_total;
27. };
28. //+------------------------------------------------------------------+
29. void OnDeinit(const int reason)
30. {
31.     ChartSetInteger(0, CHART_SHOW_DATE_SCALE, gl_StyleGraphic.View_DateScale);
32.     ChartSetInteger(0, CHART_SHOW_PRICE_SCALE, gl_StyleGraphic.View_PriceScale);    
33. };
34. //+------------------------------------------------------------------+

Code 06

Wir sind inzwischen viel höflicher geworden. Dies geschieht, weil wir in den Zeilen 04 und 05 den Nutzer um Erlaubnis bitten, sowohl die Preis- als auch die Zeitskala zu entfernen. In Zeile 07 verwenden wir eine Struktur, um die ursprünglichen Werte zu speichern, sodass wir das Chart in den Zustand zurückversetzen können, in dem es sich vor der Anwendung des Indikators befand, unabhängig von den vom Nutzer vorgenommenen Änderungen.

Hier handeln wir ähnlich wie bei Code 05, der einfach und klar war. Ich möchte Ihre Aufmerksamkeit jedoch auf etwas anderes lenken: die Ereignisbehandlung von Deinit. Es steht in Zeile 29. Das Problem besteht darin, dass MetaTrader 5 auch nach dem Entfernen des Indikators aus dem Chart einige Zeit benötigt, um das Chart an der Stelle zu aktualisieren, an der sich der Indikator befand – manchmal Sekunden, manchmal etwas länger. Während dieser kurzen Zeitspanne können einige Informationen fehlen, während andere Informationen noch nicht entfernt worden sind. Dies kann den Eindruck erwecken, dass die Plattform langsam läuft oder dass die Hardware des Nutzers veraltet ist. Das eigentliche Problem liegt jedoch darin, dass MetaTrader 5 mit anderen Aufgaben beschäftigt ist.

Um den Prozess reibungsloser zu gestalten, schlage ich vor, einen Aufruf der MQL5-Standardbibliothek zu bestimmten Zeitpunkten zu verwenden, um MetaTrader 5 zu zwingen, das Chart so schnell wie möglich zu aktualisieren. Zu anderen Zeiten kann dies völlig unnötig sein. Wenn Sie jedoch eine Verzögerung zwischen den Ereignissen feststellen, können Sie diesen Aufruf verwenden, um die Ereigniswarteschlange, die MetaTrader 5 gerade verarbeitet, zu überspringen.

Die Änderungen, die vorgenommen werden müssen, sind im folgenden Codefragment zu sehen:

                   .
                   .
                   .
28. //+------------------------------------------------------------------+
29. void OnDeinit(const int reason)
30. {
31.     ChartSetInteger(0, CHART_SHOW_DATE_SCALE, gl_StyleGraphic.View_DateScale);
32.     ChartSetInteger(0, CHART_SHOW_PRICE_SCALE, gl_StyleGraphic.View_PriceScale);
33.     ChartRedraw();
34. };
35. //+------------------------------------------------------------------+

Code 07

Das Hinzufügen der Zeile 33, die in Code 07 zu sehen ist, reicht aus, damit der Nutzer – und auch Sie – eine spürbare Verbesserung der Leistung von MetaTrader 5 wahrnehmen können, wobei zu beachten ist, dass diese Verbesserung nur scheinbar ist. Eine tatsächliche Leistungssteigerung findet nicht statt. Der Aufruf in Zeile 33 teilt MetaTrader 5 mit, dass wir die Ereignis-Warteschlange überspringen wollen, damit das Chart so schnell wie möglich aktualisiert wird. Aber bedenken Sie: Wenn wir die Warteschlange überspringen, verschieben wir ein Ereignis, das wichtig sein könnte und zu einem anderen Zeitpunkt ausgelöst werden könnte. Seien Sie daher vorsichtig, wenn Sie die Reihenfolge der Ausführung ändern.


Abschließende Gedanken

In diesem Artikel haben wir gesehen, wie einfach es ist, einen operativen Ansatz zur Färbung von Kerzen zu erstellen und umzusetzen – ein Konzept, das von vielen Händlern sehr geschätzt wird. Bei der Umsetzung muss darauf geachtet werden, dass die Balken oder Kerzen ihr ursprüngliches Aussehen behalten und das Lesen von Kerze zu Kerze nicht behindern.

Außerdem haben wir gezeigt, wie verschiedene Chart-Elemente verändert werden können, obwohl der Artikel nur zwei Eigenschaften zeigte: die Zeit- und die Preisskala. Diese Skalen wiederum können nicht mit den Mitteln beseitigt werden, die dem Durchschnittsnutzer direkt zur Verfügung stehen. Dies ist jedoch durchaus möglich und kann durch Code erreicht werden. Es ist wichtig, daran zu denken, dass das Chart, wann immer es möglich ist, in seinem ursprünglichen Zustand wiederhergestellt werden sollte, da dies die Nutzererfahrung verbessert und zeigt, dass die Anwendung gut gestaltet ist.

Da es mehrere Attribute und Eigenschaften gibt, die geändert werden können, und es umständlich wäre, sie einzeln anzusprechen, möchte ich Sie ermutigen, mit der Verwendung und Änderung dieser Eigenschaften durch MQL5-Code zu üben und zu experimentieren. Um dies zu erleichtern, können Sie auf die Liste der Chart-Eigenschaften verweisen, da viele angezeigte Elemente und Werte nur über MQL5-Code zugänglich sind. Denken Sie daran, dass die Anwendung nur Codes enthalten sollte, die wirklich zum Üben und Lernen dessen, was in dem Artikel gezeigt wird, notwendig sind.

Übersetzt aus dem Portugiesischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/pt/articles/15833

Beigefügte Dateien |
Anexo.zip (2.12 KB)
Neuroboids Optimierungsalgorithmus 2 (NOA2) Neuroboids Optimierungsalgorithmus 2 (NOA2)
Der neue proprietäre Optimierungsalgorithmus NOA2 (Neuroboids Optimization Algorithm 2) kombiniert die Prinzipien der Schwarmintelligenz mit neuronaler Steuerung. NOA2 kombiniert die Mechanik eines Neuroboidenschwarms mit einem adaptiven neuronalen System, das es den Agenten ermöglicht, ihr Verhalten selbst zu korrigieren, während sie nach dem Optimum suchen. Der Algorithmus wird derzeit aktiv weiterentwickelt und zeigt sein Potenzial für die Lösung komplexer Optimierungsprobleme.
Algorithmische Handelsstrategien: KI und ihr Weg zu den goldenen Zinnen Algorithmische Handelsstrategien: KI und ihr Weg zu den goldenen Zinnen
In diesem Artikel wird ein Ansatz zur Erstellung von Handelsstrategien für Gold mithilfe von maschinellem Lernen vorgestellt. Betrachtet man den vorgeschlagenen Ansatz zur Analyse und Prognose von Zeitreihen aus verschiedenen Blickwinkeln, so lassen sich seine Vor- und Nachteile im Vergleich zu anderen Methoden zur Erstellung von Handelssystemen, die ausschließlich auf der Analyse und Prognose von Finanzzeitreihen beruhen, feststellen.
Einführung in MQL5 (Teil 28): Beherrschung der API- und WebRequest-Funktion in MQL5 (II) Einführung in MQL5 (Teil 28): Beherrschung der API- und WebRequest-Funktion in MQL5 (II)
In diesem Artikel erfahren Sie, wie Sie mit Hilfe von APIs und der Funktion WebRequest in MQL5 Preisdaten von externen Plattformen abrufen und extrahieren können. Sie lernen, wie URLs strukturiert sind, wie API-Antworten formatiert werden, wie man Serverdaten in lesbare Strings umwandelt und wie man bestimmte Werte aus JSON-Antworten identifiziert und extrahiert.
Marktsimulation: (Teil 11): Sockets (V) Marktsimulation: (Teil 11): Sockets (V)
Wir beginnen mit der Implementierung der Verbindung zwischen Excel und MetaTrader 5, aber zunächst müssen wir einige wichtige Punkte verstehen. Auf diese Weise müssen Sie sich nicht den Kopf darüber zerbrechen, warum etwas funktioniert oder nicht funktioniert. Und bevor Sie die Stirn runzeln bei der Aussicht auf die Integration von Python und Excel, lassen Sie uns sehen, wie wir (bis zu einem gewissen Grad) MetaTrader 5 durch Excel mit xlwings steuern können. Was wir hier zeigen, wird sich in erster Linie auf die Bildungsziele konzentrieren. Denken Sie aber nicht, dass wir nur das tun können, was hier behandelt wird.