
Entwicklung eines Replay Systems (Teil 48): Das Konzept eines Dienstes verstehen
Einführung
Im vorherigen Artikel Entwicklung eines Replay Systems (Teil 47): Chart Trade Project (VI) ist es uns gelungen, den Indikator Chart Trade funktionsfähig zu machen. Jetzt können wir uns wieder auf das konzentrieren, was wir tatsächlich entwickeln müssen.
Zu Beginn dieser Artikelserie über das Replay/Simulator-System habe ich einige Zeit damit verbracht, den Dienst in die Lage zu versetzen, einen Kontrollindikator auf dem Chart zu platzieren. Obwohl ich anfangs keinen Erfolg hatte, habe ich nicht aufgegeben und es weiter versucht. Trotz zahlreicher erfolgloser Versuche ist es mir nie gelungen, in dieser Sache erfolgreich zu sein. Aber da das Projekt nicht mehr aufzuhalten war, beschloss ich in diesem Moment, einen anderen Weg einzuschlagen.
Es hat mich wirklich gestört, dass ich etwas mit einem Skript tun konnte, aber als ich versuchte, dasselbe mit einem Dienst zu tun, konnte ich es nicht richtig zum Laufen bringen.
Das könnte man meinen: „Na und? Die Tatsache, dass man etwas mit einem Drehbuch machen kann, bedeutet nichts.“ Wenn Sie so denken, befürchte ich jedoch, dass dies an den mangelnden Kenntnissen in der MQL5-Programmierung liegt. Jedes in MQL5 erstellte Skript kann in einen Dienst umgewandelt werden. Im Wesentlichen gibt es zwei Unterschiede zwischen einem Dienst und einem Skript. Nun, es gibt natürlich noch mehr, aber diese beiden sind die offensichtlichsten und können von jedem bemerkt werden.
Der erste Unterschied besteht darin, dass das Skript immer mit einem bestimmten Chart verknüpft ist und dort bleibt, bis das Chart geschlossen wird. Es ist bemerkenswert, dass MetaTrader 5 beim Wechsel des Zeitrahmens tatsächlich einen Befehl zum Neuzeichnen des Charts sendet. Um diesen Vorgang zu beschleunigen, wird das grafische Objekt (nicht das Fenster, sondern das Objekt innerhalb des Fensters) geschlossen und ein neues Objekt erstellt. Dadurch kann das Chart schnell neu gezeichnet werden. Das Skript wird jedoch nicht auf dem Chart neu gestartet, da es nicht über diese Funktion verfügt (da es keine bestimmten Ereignisse hat).
Wenn Sie also ein Skript zur Überwachung eines Charts verwenden möchten, können Sie es nicht direkt im Chart verwenden. Dies kann mit Hilfe von etwas geschehen, das sich außerhalb des Charts befindet, ihn aber beobachten kann. Dies erscheint sehr kompliziert und verwirrend. In den meisten Fällen kann dies jedoch erreicht werden, indem einige Details des Codes geändert und das Skript in einen Dienst umgewandelt wird. Dann ist das Skript, das bereits ein Dienst ist, nicht mehr an ein bestimmtes Chart gebunden, sondern kann weiterhin das Asset-Chart überwachen.
Vielleicht fällt es Ihnen schwer, die Logik und die Gründe für diese Entwicklung zu verstehen. Aber ohne dies wird es unmöglich sein, zu weiteren Entwicklungsphasen überzugehen. Die Schaffung eines Dienstes, der die Vorgänge auf dem Chart überwachen kann, ist daher für unser Vorhaben von entscheidender Bedeutung. Nicht weil wir etwas schaffen müssen, sondern weil wir beobachten müssen.
Sie können diesen Artikel als wertvolle Recherchequelle nutzen, da der darin enthaltene Inhalt für das Replay-/Simulatorsystem von wesentlicher Bedeutung sein wird. Darüber hinaus wird es für komplexere und detailliertere Projekte sehr nützlich sein, bei denen wir das Chart analysieren müssen, ohne mit ihm verbunden zu sein.
Implementierung des Beispielskripts
Um wirklich zu verstehen, wie dies funktioniert und mit welchen Herausforderungen wir konfrontiert werden, lassen Sie uns mit einem sehr einfachen Beispiel beginnen. Einfach, aber funktional genug, um als Basis für etwas noch Komplexeres zu dienen, das später implementiert werden soll.
Beginnen wir damit, die Dinge auf der grundlegendsten Ebene zu verstehen. Daher werden wir zunächst ein sehr gutes, aber sehr einfaches Skript verwenden, das unten gezeigt wird:
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. #property version "1.00" 04. //+------------------------------------------------------------------+ 05. void OnStart() 06. { 07. long id; 08. string szSymbol; 09. int handle; 10. bool bRet; 11. ENUM_TIMEFRAMES tf; 12. 13. id = ChartID(); 14. szSymbol = ChartSymbol(id); 15. tf = ChartPeriod(id); 16. handle = iMA(szSymbol, tf, 9, 0, MODE_EMA, PRICE_CLOSE); 17. bRet = ChartIndicatorAdd(id, 0, handle); 18. 19. Print(ChartIndicatorName(id, 0, 0), " ", szSymbol, " ", handle, " ", bRet, " >> ",id); 20. 21. Print("*******"); 22. } 23. //+------------------------------------------------------------------+
Beispiel für einen Skript-Quellcode
Obwohl das Skript sehr einfach ist, wird es mir helfen zu erklären, was wir tatsächlich tun werden. In den Zeilen 02 und 03 finden sich Angaben zu den Eigenschaften des Codes. Sie sind für unsere Erklärung nicht so wichtig. In Zeile 05 beginnen wir mit unserem Code. Da es sich um ein sehr einfaches Skript handelt, ist die einzige wirklich benötigte Funktion OnStart.
In den Zeilen 07 bis 11 stehen unsere lokalen Variablen. Hier gibt es etwas Wichtiges zu beachten. Wir brauchen eigentlich nicht alle diese Variablen in einem Skript. Zumindest für das, was wir tun werden. Tatsächlich brauchen wir keine dieser Variablen. Aber wegen der Zeile 19 werden wir sie hier im Skript verwenden.
Im Skript geschieht Folgendes: In Zeile 13 erhalten wir die ID des Charts, auf dem das Skript platziert wird. In Zeile 14 nehmen wir dann den Namen des Vermögenswerts, der in diesem Chart zu finden ist. In Zeile 15 erhalten wir den Zeitrahmen, in dem unser Skript ausgeführt werden soll. Alle diese drei Schritte sind optional. Obwohl der Schritt in Zeile 13 erforderlich ist, sind die Schritte in den Zeilen 14 und 15 für das Skript nicht zwingend erforderlich. Es wird jedoch bald klar werden, warum sie hier sind.
In Zeile 16 weisen wir MetaTrader 5 an, einen der technischen Standardindikatoren auf dem Chart zu platzieren. In diesem Fall handelt es sich um einen gleitenden Durchschnitt. Bitte beachten Sie nun Folgendes: Der hinzugefügte gleitende Durchschnitt wird ein exponentieller MA mit 9 Periodenlängen sein, der auf der Grundlage des Schlusskurses berechnet wird. Wenn alles richtig gemacht wird, gibt dieser Indikator ein Handle zurück.
In Zeile 17 verwenden wir den in Zeile 16 erstellten Handle und teilen MetaTrader 5 mit, dass der Indikator, zu dem der Handle gehört, auf dem Chart gestartet werden soll. In Zeile 19 geben wir alle Werte aus, die vom Skript erfasst und verwendet wurden. Dies ist eine Art Skript-Debugging, das auch noch einem anderen Zweck dient, den wir gleich kennenlernen werden.
Bitte beachten Sie, dass alles, was wir getan haben, auch auf viele andere Arten hätte getan werden können. Sie denken jetzt wahrscheinlich: „Was für ein nutzloser Code! Warum sollte jemand so etwas schaffen wollen?“ Ich kann es Ihnen nicht verdenken, dass Sie so denken. Aber beim Programmieren ist nichts nutzlos, es sei denn, man schafft etwas völlig Sinnloses.
Wenn Sie dieses Skript kompilieren und in ein Chart einfügen, werden Sie sehen, dass es einen exponentiellen gleitenden Durchschnitt von 9 Periodenlängen anzeigt, der auf dem Schlusskurs basiert. Da der Skriptcode sehr schnell ausgeführt und abgeschlossen wird und hauptsächlich dazu dient, etwas anderes zu testen, enthält er keine Fehlerprüfung. Alle auftretenden Fehler werden im MetaTrader 5-Protokoll angezeigt.
Jetzt beginnt der lustige Teil. Denken wir darüber nach: Wenn wir zum Beispiel die Zeile 16 durch eine andere ersetzen:
handle = iCustom(szSymbol, tf, "Replay\\Chart Trade.ex5", id);
Wir können unseren Indikator Chart Trade mithilfe eines Skripts auf dem Chart platzieren. Aber was ist der wirkliche Nutzen davon? Wie zu Beginn dieses Artikels erwähnt, wird es interessant, wenn wir dieses Skript nicht nur als Skript, sondern auch als Dienst verwenden.
Umwandlung eines Skripts in einen Dienst
Die Umwandlung eines Skripts in einen Dienst ist nicht das Schwierigste. Zumindest in dieser Phase. Das liegt daran, dass der einzige Unterschied im Code die Verwendung einer Eigenschaft ist, die angibt, dass das Skript tatsächlich ein Dienst ist. Und das ist im Grunde alles. Doch trotz der scheinbaren Einfachheit gibt es einige Details, die man verstehen muss, um es richtig zu machen.
Kehren wir zu unserem einfachen Beispiel zurück. Wenn Sie versuchen, dieses Skript in einen Dienst umzuwandeln, indem Sie den Code unverändert lassen und lediglich eine Eigenschaft hinzufügen, die angibt, dass es sich um einen Dienst handelt, wird nichts funktionieren. Warum?
Der Grund dafür ist, dass der Dienst im Gegensatz zu einem Skript nicht wirklich mit einem Chart verbunden ist. Und dieser Umstand verkompliziert die Situation ein wenig.
Zum besseren Verständnis sollten wir zunächst verstehen, wie der MetaTrader 5 funktioniert. Beginnen wir damit, die Plattform ohne offene Charts zu starten. Wir können Dienste hinzufügen, aber wir können nichts anderes tun. Sobald der erste Chart geöffnet ist, können wir Indikatoren, Skripte und Expert Advisors darauf platzieren. Aber wir können auch einige Manipulationen mit dem Chart durchführen, indem wir den Dienst dafür nutzen.
Wahrscheinlich haben Sie das noch nie ausprobiert oder gesehen, wie es jemand anderes macht. Bis zu diesem Moment. Aber ja, Sie können den Dienst veranlassen, bestimmte Elemente auf dem Chart zu platzieren. Wir werden es schaffen, aber wir sollten nichts überstürzen. Wenn Sie diese Grundlage nicht richtig verstehen, werden Sie meine neuen Artikel nicht verstehen, denn ich werde einen ähnlichen Ansatz aktiv nutzen, um andere Dinge zu beschleunigen und zu vereinfachen.
Wenn Sie in MetaTrader 5 Charts hinzufügen, wird eine ganze Serie von Charts erstellt, wenn Sie die vorherigen Charts nicht schließen. Die Reihenfolge des Zugriffs auf sie unterscheidet sich jedoch von der Reihenfolge, in der sie im MetaTrader 5-Terminal organisiert sind. Die Reihenfolge des Zugriffs hängt von der Reihenfolge ab, in der sie geöffnet werden. Dies ist der erste Punkt. Glücklicherweise gibt uns MQL5 die Möglichkeit, durch diese Liste von Charts zu navigieren, und das wird für uns wichtig sein.
Wenn Sie also eine Möglichkeit entwickeln wollen, bestimmte Indikatoren zu bestimmten Assets hinzuzufügen, anstatt eine Vorlage zu erstellen, müssen Sie einen Dienst nutzen. Klingt kompliziert? Es ist eigentlich gar nicht so schwierig, wenn man wirklich versteht, was vor sich geht.
Kehren wir zu dem Code aus dem vorherigen Thema zurück, in dem wir einen exponentiellen gleitenden Durchschnitt von 9 Periodenlängen mithilfe eines Skripts hinzugefügt haben. Gehen wir nun wie folgt vor: Wenn das erste Chart geöffnet wird, sollte es diesen gleitenden Durchschnitt erhalten. Unabhängig davon, wie hoch das Vermögen sein wird. Wichtig ist, dass dies der erste Chart ist, der geöffnet wird. In diesem Fall müssen wir das gleiche Skript in den unten gezeigten Code des Dienstes umwandeln.
01. //+------------------------------------------------------------------+ 02. #property service 03. #property copyright "Daniel Jose" 04. #property version "1.00" 05. //+------------------------------------------------------------------+ 06. void OnStart() 07. { 08. long id; 09. string szSymbol; 10. int handle; 11. bool bRet; 12. ENUM_TIMEFRAMES tf; 13. 14. Print("Waiting for the chart of the first asset to be opened..."); 15. while ((id = ChartFirst()) < 0); 16. szSymbol = ChartSymbol(id); 17. tf = ChartPeriod(id); 18. handle = iMA(szSymbol, tf, 9, 0, MODE_EMA, PRICE_CLOSE); 19. bRet = ChartIndicatorAdd(id, 0, handle); 20. 21. Print(ChartIndicatorName(id, 0, 0), " ", szSymbol, " ", handle, " ", bRet, " >> ",id); 22. 23. Print("*******"); 24. } 25. //+------------------------------------------------------------------+
Quellcode des Dienstes
Vergleichen Sie den obigen Code mit dem Code aus dem vorherigen Thema. Worin besteht der Unterschied zwischen ihnen? Sie werden wahrscheinlich sagen, dass es die Zeile 02 ist, in der es jetzt eine Eigenschaft gibt, die diesen Code als Dienst definiert. Das ist richtig, aber es gibt noch etwas anderes. Wir haben auch zwei verschiedene Linien. In Zeile 14 geben wir eine Meldung aus, dass der Dienst darauf wartet, dass ein Chart im MetaTrader 5-Terminal platziert wird, und wir erwarten, dass der Chart in Zeile 15 geöffnet wird.
An dieser Stelle werden die Dinge sehr viel interessanter. Um zu verstehen, was tatsächlich passiert, schreiben Sie den obigen Code und kompilieren Sie ihn mit MetaEditor. Öffnen Sie MetaTrader 5 und schließen Sie alle offenen Charts, wirklich alle. Danach führen Sie den soeben erstellten Dienst aus. Öffnen Sie das Log-Fenster und Sie sehen die in Zeile 14 angezeigte Meldung. Wenn dies der Fall ist, haben Sie alles richtig gemacht. Öffnen Sie nun einen Chart eines beliebigen Symbols. Sie sehen dann sofort die Meldung aus Zeile 21 und der Dienst wird geschlossen. Aber wenn Sie sich das Chart ansehen, werden Sie feststellen, dass es wie erwartet einen exponentiellen gleitenden Durchschnitt über 9 Balken gibt. Das liegt daran, dass der Dienst sie dort platziert hat.
Ich hoffe, Sie, liebe Leserin, lieber Leser, haben aufmerksam zugehört, denn jetzt werden wir die Dinge etwas komplizierter machen.
Sicherstellung eines Standardchart
Hier beginnt der wirklich unterhaltsame Teil der Nutzung der Dienste. Viele Menschen verwenden gerne ein standardisiertes grafisches Modell, für das sie Vorlagen erstellen. Die voreingestellte Vorlage hilft uns in dieser Hinsicht ein wenig. Damit wird sichergestellt, dass alle Charts zum Zeitpunkt ihrer Erstellung dem Standard entsprechen. Aber nach dem Platzieren der Vorlage können wir versehentlich einige Indikatoren löschen oder die Einstellungen eines Indikators ändern. Dies ist in vielen Fällen kein Problem. Sie können einfach einen Indikator wiederherstellen und das war's. Aber ist es möglich, MetaTrader 5 zu verwenden, ohne dieses Problem zu haben? Damit diese Plattform dem Bloomberg-Terminal immer sehr ähnlich ist.
Ja, das ist möglich. Wir können sogar verhindern, dass der Nutzer oder wir selbst etwas im Terminal dekonfigurieren. In diesem speziellen Fall spreche ich von Indikatoren. In früheren Artikeln habe ich gezeigt, wie Sie das System zwingen können, einen bestimmten Indikator im Chart zu unterstützen. Dies wird schon seit geraumer Zeit in diesem Replay/Simulator-System gemacht, um zu vermeiden, dass der Kontrollindikator aus dem Chart entfernt wird. Es gibt jedoch eine universellere Lösung, die es Ihnen ermöglicht, beliebige Dinge auf dem Chart zu belassen oder zu verhindern, dass andere auftauchen.
Was die Vorbeugung angeht, glaube ich nicht, dass es viel Sinn macht, zu zeigen, wie es gemacht wird, aber was die Aufbewahrung angeht, finde ich das wirklich interessant. Ändert man also den im vorherigen Thema gezeigten Code erneut, erhält man den unten gezeigten Code:
01. //+------------------------------------------------------------------+ 02. #property service 03. #property copyright "Daniel Jose" 04. #property version "1.00" 05. //+------------------------------------------------------------------+ 06. void OnStart() 07. { 08. long id; 09. string szSymbol; 10. int handle; 11. 12. Print("Waiting for the chart of the first asset to be opened..."); 13. while (!_StopFlag) 14. { 15. while (((id = ChartFirst()) < 0) && (!_StopFlag)); 16. while ((id > 0) && (!_StopFlag)) 17. { 18. if (ChartIndicatorName(id, 0, 0) != "MA(9)") 19. { 20. handle = iMA(szSymbol = ChartSymbol(id), ChartPeriod(id), 9, 0, MODE_EMA, PRICE_CLOSE); 21. ChartIndicatorAdd(id, 0, handle); 22. IndicatorRelease(handle); 23. } 24. id = ChartNext(id); 25. } 26. Sleep(250); 27. } 28. Print("Service finish..."); 29. } 30. //+------------------------------------------------------------------+
Verbesserter Servicecode
Vielleicht fällt Ihnen auf, dass dieser Code Elemente enthält, die seltsam erscheinen. Jedes der Elemente hat jedoch seinen Grund, im Code vorhanden zu sein. Der Code selbst unterscheidet sich nicht wesentlich von dem, was im vorigen Thema besprochen wurde, aber er ist in der Lage, etwas sehr Interessantes zu tun. Schauen wir uns an, was dieser Code bewirkt, dann können Sie ihn an Ihre eigenen Bedürfnisse und Interessen anpassen.
In Zeile 12 geben wir eine Meldung aus, dass der Dienst wartet. Genau wie in Zeile 28 teilen wir mit, dass der Dienst entfernt wurde und nicht mehr läuft. Alles, was zwischen diesen beiden Linien passiert, ist das, was uns wirklich interessiert. Um sicherzustellen, dass der Dienst korrekt geschlossen wird, ohne Probleme im MetaTrader 5 zu verursachen, überprüfen wir die Konstante _StopFlag, die so lange gültig ist, bis wir das Schließen des Dienstes anfordern.
In Zeile 13 geraten wir also in eine Endlosschleife. Aber diese Schleife ist nicht wirklich unendlich, denn in dem Moment, in dem wir signalisieren, dass wir den Dienst schließen wollen, wird diese Schleife beendet.
In Zeile 15 haben wir alles wie im vorherigen Code. Aber jetzt fügen wir eine Prüfung hinzu, um Probleme beim Schließen des Dienstes zu vermeiden. Bitte beachten Sie: Wenn ChartFirst einen Wert zurückgibt, ist dies der Wert des ersten Fensters, das Sie im MetaTrader 5 Terminal geöffnet haben. Der Wert wird in der Variablen „id“ gespeichert. Erinnern Sie sich an diese Tatsache, denn von nun an ist es wichtig, die Reihenfolge der Aktionen zu berücksichtigen.
In Zeile 18 wird geprüft, ob das Fenster den iMA-Indikator enthält, d. h. den gleitenden Durchschnitt von 9 Periodenlängen. Wenn diese Bedingung nicht erfüllt ist, d.h. der MA nicht im Chart zu finden ist, wird er hinzugefügt. Dazu erstellen wir zunächst in Zeile 20 ein Handle und fügen dann in Zeile 21 den MA zum Chart hinzu. Sobald dies geschehen ist, löschen wir das Handle, da wir ihn nicht mehr benötigen. Wenn Sie also den MA aus dem Chart entfernen, wird er wieder hinzugefügt. Dies geschieht automatisch, während der Dienst läuft.
In Zeile 24 wird das nächste Fenster gesucht. Beachten Sie nun, dass wir den Index des aktuellen Fensters benötigen, damit MetaTrader 5 weiß, was der nächste Index sein wird. Nicht alles durcheinanderbringen. Wenn ein anderes Fenster gefunden wird, wird die Schleife wiederholt. Dieser Vorgang wird so lange wiederholt, bis ChartNext den Wert -1 zurückgibt. Wann die in Zeile 16 begonnene Schleife beendet wird.
Natürlich wollen wir nicht, dass sich der Dienst wie ein Verrückter aufführt. In Zeile 26 erzeugen wir also eine kleine Verzögerung, etwa 250 Millisekunden, vor der nächsten Iteration der Schleife. Auf diese Weise wird der Dienst 4 Mal pro Sekunde ausgeführt, wodurch sichergestellt wird, dass der angegebene gleitende Durchschnitt immer auf allen Charts, die im MetaTrader 5-Terminal geöffnet sind, vorhanden ist. Solche Dinge sind sehr interessant, nicht wahr?
Aber wir können noch ein bisschen mehr tun. Wir können erzwingen, dass Elemente in einem bestimmten Chart für ein bestimmtes Symbol platziert werden. Genau das habe ich seit Beginn dieser Artikelserie mehrfach versucht zu erreichen, aber aus dem einen oder anderen Grund hat es nicht geklappt. Nehmen wir an, Sie, ein Händler an der B3 (Brasilianische Börse), entscheiden, dass Sie einen bestimmten Indikator nur für ein bestimmtes Symbol verwenden möchten. Und immer nur für dieses Symbol. Eine Möglichkeit, dies zu tun, ist die Verwendung einer Vorlage. Es ist jedoch sehr wahrscheinlich, dass Sie in der täglichen Hektik dieses Symbol schließen und beim erneuten Öffnen des Charts das Fehlen des dringend benötigten Indikators erst bemerken, wenn es zu spät ist.
Bei Verwendung des Dienstes wird dies nicht passieren, denn sobald das Symbolchart im MetaTrader 5-Terminal geöffnet wird, kümmert sich der Dienst darum, den Indikator hinzuzufügen. Wenn Sie eine Vorlage verwenden möchten, um zusätzliche Elemente hinzuzufügen, können Sie auch das tun. Aber die Verwendung der Vorlage wird ein anderes Mal behandelt, da sie einige Dinge beinhaltet, die wir in zukünftigen Artikeln dieser Serie behandeln werden.
Schauen wir uns also an, wie man das macht. Und um Verwirrung zu vermeiden, sollten wir dies in einem neuen Thema behandeln.
Sicherstellung der Qualität der Terminals
Wenn Sie das, was Sie im vorherigen Thema gesehen haben, interessant fanden, machen Sie sich bereit, denn dieses Thema wird noch interessanter werden. Wir können nämlich genau das tun, was wir wollen, d. h. wir können dafür sorgen, dass die Symboltabelle immer dem vorkonfigurierten Terminal entspricht. Es ist fast so, als ob wir MetaTrader 5 wie das Bloomberg-Terminal aussehen lassen könnten, aber mit dem Vorteil, dass die Konfiguration nie versehentlich geändert wird, da sie nicht mit einer Vorlage verbunden ist, sondern Teil der Dienstkonfiguration ist.
Zur Veranschaulichung sehen wir uns an, wie der im vorherigen Thema besprochene Code des Dienstes geändert wurde. Der vollständige Code ist unten dargestellt:
01. //+------------------------------------------------------------------+ 02. #property service 03. #property copyright "Daniel Jose" 04. #property version "1.00" 05. //+------------------------------------------------------------------+ 06. void OnStart() 07. { 08. long id; 09. string szSymbol; 10. int handle; 11. ENUM_TIMEFRAMES tf; 12. 13. Print("Waiting for the chart of the first asset to be opened..."); 14. while (!_StopFlag) 15. { 16. while (((id = ChartFirst()) < 0) && (!_StopFlag)); 17. while ((id > 0) && (!_StopFlag)) 18. { 19. szSymbol = ChartSymbol(id); 20. tf = ChartPeriod(id); 21. if ((StringSubstr(szSymbol, 0, 3) == "WDO") && (ChartWindowFind(id, "Stoch(8,3,3)") < 0)) 22. { 23. handle = iStochastic(szSymbol, tf, 8, 3, 3,MODE_SMA, STO_CLOSECLOSE); 24. ChartIndicatorAdd(id, (int)ChartGetInteger(id, CHART_WINDOWS_TOTAL), handle); 25. IndicatorRelease(handle); 26. } 27. if (ChartIndicatorName(id, 0, 0) != "MA(9)") 28. { 29. handle = iMA(szSymbol, tf, 9, 0, MODE_EMA, PRICE_CLOSE); 30. ChartIndicatorAdd(id, 0, handle); 31. IndicatorRelease(handle); 32. } 33. id = ChartNext(id); 34. } 35. Sleep(250); 36. } 37. Print("Service finish..."); 38. } 39. //+------------------------------------------------------------------+
Dienst-Code
Die Änderungen sind zwar gering, aber die Ergebnisse sind bemerkenswert. In unserem Fall verwenden wir zur Veranschaulichung ein Symbol von B3 (brasilianische Börse). Es handelt sich um einen Mini-Dollarterminkontrakt. Dieser Vertrag läuft jeden Monat aus, aber das ist kein Problem. Um dies zu verstehen, sollten wir uns den Code selbst ansehen. Es ist nicht schwer, aber Sie müssen auf die Details achten, sonst bekommen Sie nicht, was Sie erwarten.
Ich werde nicht auf das eingehen, was ich bereits behandelt habe, sondern mich auf die neuen Teile des Codes konzentrieren. In den Zeilen 19 und 20 geben wir die Daten des Charts ein, das der Dienst überprüfen soll. Wir benötigen den Namen des Symbols sowie den Zeitrahmen des Charts, um Fehler in Zukunft zu vermeiden. Diese Werte werden dann in zwei Variablen eingetragen.
In Zeile 21 führen wir zwei Prüfungen durch:
- Die erste betrifft den Namen des Symbols, das wir konfigurieren wollen.
- Der zweite ist das Vorhandensein oder Fehlen eines bestimmten Indikators.
Wenn beide Prüfungen wahr sind, wird weiterer Code ausgeführt. Beachten Sie, dass wir nur die ersten drei Buchstaben des Symbolnamens verwenden, da es sich um einen Terminkontrakt mit einem Verfallsdatum handelt. Da wir den Namen des Symbols nicht ständig ändern wollen, verwenden wir den gemeinsamen Teil des Symbolnamens unabhängig vom aktuellen Vertrag.
Der zweite Punkt, den es zu beachten gilt, bezieht sich auf den Indikator. Wir müssen seine Kurzbezeichnung angeben. Wenn Sie diesen Namen nicht kennen, platzieren Sie diesen Indikator einfach auf dem Chart und verwenden Sie ein einfaches Skript, um seinen Namen auf dem Terminal auszugeben. Auf diese Weise wissen Sie genau, welcher Name dort verwendet werden soll. In diesem Fall verwenden wir einen stochastischen Indikator mit 8 Perioden, einem MA von 3 und einer Konstante von 3. Wenn der Indikator jedoch anders lautet, ändern Sie die Zeichenfolge in den richtigen Namen. Andernfalls werden wir im nächsten Schritt Probleme bekommen.
Kehren wir also zu der Situation zurück, in der sich der Indikator nicht auf dem Chart des angegebenen Symbols befindet. In diesem Fall führen wir zunächst Zeile 23 aus, in der wir den gewünschten Indikator einrichten. In Zeile 24 fügen wir dann den Indikator in das neue Unterfenster ein. Seien Sie an dieser Stelle vorsichtig: Wenn Sie die Nummer des Unterfensters angeben, platziert MetaTrader 5 den Indikator in dem angegebenen Fenster. Dies kann zu Verwirrung führen. Gemäß dem vorhandenen Code erstellt MetaTrader 5 jedoch ein neues Unterfenster und fügt den Indikator in dieses Fenster ein.
In Zeile 25 wird der Handle freigegeben, weil wir ihn nicht mehr brauchen. Alles, was beschrieben wurde, geschieht nur, wenn der Indikator nicht im Chart vorhanden ist. Wenn Sie versuchen, ihn zu löschen, zwingt der Dienst MetaTrader 5, ihn erneut auf dem Chart zu platzieren. Ist er jedoch bereits auf dem Chart vorhanden, wird der Dienst nicht aktiviert und beobachtet einfach, was passiert.
Wichtiger Hinweis: Obwohl der Code funktioniert und eine angemessene Leistung aufweist, wird aus praktischen Gründen empfohlen, die in Zeile 27 gezeigte Prüfung durch eine effizientere zu ersetzen. Wenn Sie mehrere Indikatoren in einem einzigen Chart verwenden, ist es am besten, nach Namen und nicht nach Index zu testen, wie es im Code der Fall ist. Ersetzen Sie also einfach Zeile 27 durch den folgenden Code:
27. if (ChartIndicatorGet(id, 0, "MA(9)") == INVALID_HANDLE)
Unabhängig davon, welchen Index der Indikator hat, wird also nur ein Indikator auf dem Chart erscheinen – derjenige, der vom Dienst auf dem Chart platziert wird.
Schlussfolgerung
In diesem Artikel habe ich Ihnen etwas gezeigt, was nur wenige Menschen wirklich können. Wenn dies bei Ihnen der Fall ist, freue ich mich sehr, Ihnen zeigen zu können, dass MetaTrader 5 ein viel leistungsfähigeres Werkzeug sein kann, als es scheint. Dies ist vielleicht die beste Plattform für diejenigen, die wirklich wissen, was sie tun, und in der Lage sind, alle ihre Möglichkeiten zu nutzen.
In dem Video sehen Sie, wie sich MetaTrader 5 bei der Nutzung des Dienstes aus diesem Artikel verhält. Aber abgesehen von dem, was hier gezeigt wurde, und dies ist nur eine Einführung in das, was wir noch zu tun haben, freue ich mich sehr, dass Sie, liebe Leserinnen und Leser, nach dem Lesen des Artikels neugierig geworden sind und versucht haben, ein wenig mehr zu erfahren. Ich möchte jedoch betonen, dass Lernen nicht nur aus der Lektüre von Bildungsartikeln besteht, sondern auch aus dem selbstständigen Finden von Lösungen.
Versuchen Sie, das Beste aus allem herauszuholen. Und wenn man an die Grenzen des Machbaren stößt, sollte man sich nach qualifizierteren Leuten umsehen, um eine Lösung zu finden, wobei man immer versucht, das bereits Erreichte zu übertreffen. Dies ist die Essenz des evolutionären Weges, und so wird man ein echter Profi.
Demo-Video
Übersetzt aus dem Portugiesischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/pt/articles/11781





- Freie Handelsapplikationen
- Über 8.000 Signale zum Kopieren
- Wirtschaftsnachrichten für die Lage an den Finanzmärkte
Sie stimmen der Website-Richtlinie und den Nutzungsbedingungen zu.
Hochinteressantes Projekt, aber alle 48 Artikel zu lesen, um den Hinweis für jede Komponente zu bekommen, ist wirklich harte Arbeit.
Ich bitte Sie, den nächsten Artikel 49 "Benutzerhandbuch" zu schreiben und darin die einzelnen Komponenten dieses Projekts zu erläutern.
Außerdem - wenn dieses Projekt für die praktische Umsetzung bereit ist, fügen Sie bitte ein praktisches Beispiel für seine Verwendung hinzu, z.B. "Replaying and re-trading Brexit case on GBPUSD in educational purpose". Es wird erwartet, dass in diesem praktischen Beispiel dieses Projekt verwendet wird, um historische Daten von "GBPUSD" von einem realen Symbol (von einem beliebigen verbundenen Forex-Konto) plus/minus 1 Tag nach dem Brexit abzurufen, die extrahierten Daten zu verwenden, um ein benutzerdefiniertes Symbol wie "repGBPUSD" im Replay-Modus zu füttern, einige generische Indikatoren (RSI(14), MA(50) usw.) hinzuzufügen und dem Benutzer eine Echtzeit-Erfahrung des Re-Tradings dieses historischen Ereignisses zu bieten.
Dieses Benutzerhandbuch mit einem praktischen Beispiel für das Re-Traden des Brexit in Echtzeit ist ein wirklich großartiger Abschluss dieses Projekts!