Marktsimulation: Positionsansicht (IV)
Einführung
Hallo und herzlich willkommen zu einem weiteren Artikel in der Serie über die Erstellung eines Replikations-/Simulationssystems.
Im vorherigen Artikel „ Marktsimulation: Positionsansicht (III)“ haben wir gezeigt, wie wichtig es ist, zu wissen, wann und warum die ZOrder-Eigenschaft für Objekte festgelegt werden sollte. Bis zu diesem Punkt war ich ziemlich geduldig und habe nicht genau gezeigt, was wir tun werden. Nach dem Lesen der vorherigen Artikel denken Sie vielleicht, dass all dies sehr schön, aber völlig unpraktisch ist. Nun, der einfache Teil ist vorbei. Jetzt werden wir etwas tun, ohne das wir die Implementierung des Positionsindikators nicht fortsetzen können. Wir müssen vier bestehende Anwendungen zusammenführen, um die Implementierung des Positionsindikators fortzusetzen. Sie sollten sich jedoch, lieber Leser, noch keine Gedanken über Pending Orders machen. Wie wir mit ihnen arbeiten werden, wird in Zukunft klar werden. Wir müssen also Schritt für Schritt vorankommen.
In diesem Stadium ist der wichtigste Schritt nicht der Umgang mit Pending Orders, sondern die Sicherstellung einer ordnungsgemäßen Positionsverwaltung. Denken Sie an Folgendes: Wir haben bereits einen Expert Advisor, der Positionen zum Marktpreis eröffnen und schließen kann. Wir haben auch den Mouse Study-Indikator, der es uns bereits ermöglicht, einfache Studien und Zeichnungen im Chart zu erstellen, obwohl Sie ihn modifizieren können, um eine komplexere Studie zu erstellen. Wir haben auch Chart Trade, das es ermöglicht, Aufträge an den Expert Advisor zu senden, um anzugeben, ob gekauft oder verkauft werden soll, sowie das zu handelnde Volumen. Doch diese drei Anwendungen benötigen noch eine weitere Komponente, damit wir ein brauchbares System haben. Diese fehlende Anwendung ist genau der Indikator, den wir jetzt implementieren.
Im aktuellen Entwicklungsstadium ist der Positionsindikator kaum mehr als ein interessantes Werkzeug. Aber wenn wir ihn mit den drei anderen Anwendungen kombinieren, die bereits erstellt wurden, wird das gesamte System viel interessanter. Sie fragen sich jedoch vielleicht: Wie werden wir das machen? Werden wir die Klasse C_IndicatorPosition im Expert Advisor verwenden? Nein, das werden wir nicht tun. Wir werden den Positionsindikator getrennt vom Expert Advisor halten. Auf diese Weise können Sie ihn in Ihren eigenen Expert Advisor einbinden.
Natürlich müssen Sie einige Anpassungen vornehmen, damit Ihr Expert Advisor den Positionsindikator verwenden kann. Aber glauben Sie mir, das wird viel einfacher sein, als mehrere Expert Advisors mit denselben operativen Fähigkeiten zu erstellen. Alle Änderungen am Positionsindikator werden sofort in allen Expert Advisors übernommen, die ihn verwenden. Das ist deutlich effizienter, als wenn jeder Expert Advisor einen eigenen Positionsindikator hätte.
Die Idee, die ich vorschlage, und die Demonstration, wie man sie umsetzt, sind nichts Neues. Tatsächlich ist dies genau das, was es verschiedenen Programmen ermöglicht, gemeinsame Komponenten zu nutzen. Es ist etwas ähnlich wie bei Computerspielen, die DirectX verwenden. Wenn DirectX ein Update erhält, werden auch alle Spiele und Programme, die die DirectX-Bibliothek verwenden, aktualisiert. Stellen Sie sich nun vor, jede Anwendung müsste manuell aktualisiert werden, wann immer die DirectX-Bibliothek verbessert wurde. Das wäre völlig unpraktisch. Dieses Modell sollte also nicht als potenzielles Problem angesehen werden. Es kann als eine Lösung angesehen werden, die es uns im Laufe der Zeit ermöglichen wird, immer nützlichere und sicherere Anwendungen zu erstellen. Jede Korrektur oder Verbesserung in einer Anwendung wirkt sich auf die gesamte Kette der in MetaTrader 5 verwendeten Anwendungen aus. Fangen wir also an.
Lassen Sie uns den aktuellen Stand des Expert Advisors in Erinnerung rufen.
Bevor wir Änderungen am Code vornehmen, müssen wir uns ansehen, wie der Hauptcode des Expert Advisors aussieht. Der Grund ist, dass die letzten Änderungen schon geraume Zeit zurückliegen. Im folgenden Code können Sie also den aktuellen Stand der Implementierung des Expert Advisors sehen:
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. #property icon "/Images/Market Replay/Icons/Replay - EA.ico" 04. #property description "Demo version between interaction" 05. #property description "of Chart Trade and Expert Advisor" 06. #property version "1.84" 07. #property link "https://www.mql5.com/pt/articles/12598" 08. //+------------------------------------------------------------------+ 09. #include <Market Replay\Order System\C_Orders.mqh> 10. //+------------------------------------------------------------------+ 11. enum eTypeContract {MINI, FULL}; 12. //+------------------------------------------------------------------+ 13. input eTypeContract user00 = MINI; //Cross order in contract 14. //+------------------------------------------------------------------+ 15. C_Orders *Orders; 16. long GL_ID; 17. //+------------------------------------------------------------------+ 18. int OnInit() 19. { 20. GL_ID = 0; 21. Orders = new C_Orders(0xC0DEDAFE78514269); 22. 23. return INIT_SUCCEEDED; 24. } 25. //+------------------------------------------------------------------+ 26. void OnTick() {} 27. //+------------------------------------------------------------------+ 28. void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) 29. { 30. (*Orders).DispatchMessage(id, lparam, dparam, sparam); 31. switch (id) 32. { 33. case CHARTEVENT_CHART_CHANGE: 34. if (GL_ID > 0) break; else GL_ID = ChartID(); 35. case CHARTEVENT_CUSTOM + evChartTrade_At_EA: 36. EventChartCustom(GL_ID, evEA_At_ChartTrade, user00, 0, ""); 37. break; 38. } 39. } 40. //+------------------------------------------------------------------+ 41. void OnDeinit(const int reason) 42. { 43. switch (reason) 44. { 45. case REASON_REMOVE: 46. case REASON_INITFAILED: 47. EventChartCustom(GL_ID, evEA_At_ChartTrade, -1, 0, ""); 48. break; 49. } 50. 51. delete Orders; 52. } 53. //+------------------------------------------------------------------+
Originalcode des Expert Advisors
Wow! War Artikel 84 wirklich das letzte Mal, dass dieser Code geändert wurde? Ja, seitdem wurden keine Änderungen mehr vorgenommen. Aber jetzt ist es an der Zeit, wieder daran zu arbeiten. Bevor wir Änderungen an diesem Code vornehmen, müssen wir Folgendes verstehen. Beachten Sie, dass Zeile 13 die einzige Form der Interaktion mit dem Benutzer oder Trader enthält. Über diese Eingabe wird den anderen Anwendungen mitgeteilt, ob der Expert Advisor mit einem vollen Kontrakt oder einem Minikontrakt arbeiten soll.
Für diejenigen, die nicht an der B3 (der brasilianischen Börse) handeln, wird diese Einstellung nicht viel Sinn ergeben. Aber unabhängig davon, was Sie handeln, benötigen Sie den Chart Trade-Indikator auf dem Chart sowie diesen Expert Advisor. Sobald der Expert Advisor zum Chart hinzugefügt wurde, sendet er eine Nachricht an alle Anwendungen, die innerhalb von MetaTrader 5 ausgeführt werden. Ich habe dies bereits früher in derselben Artikelserie erklärt. Wenn Sie nicht verstehen, worum es hier geht, versuchen Sie, die vorherigen Artikel zu lesen, um ein tieferes Verständnis des Themas zu erlangen. Das Verständnis dieses Nachrichtenaustauschs wird später von grundlegender Bedeutung sein. Ohne dieses Verständnis werden Sie dem Material in den nächsten Artikeln nicht folgen können.
Großartig. Sobald diese Nachricht gesendet wurde, wissen alle Anwendungen, was der Expert Advisor von ihnen erwartet. Dieser Expert Advisor wird keine Befehle direkt vom Benutzer oder Trader empfangen. Er wird Befehle nur über Nachrichten empfangen und senden. Erwarten Sie also keinen linearen und perfekt geordneten Code. Hier gibt es eine ganze Menge ereignisgesteuerter Interaktion.
Gut. Aber wo erscheint der Positionsindikator bei alldem? Wie können wir ihn verwenden, wenn der Expert Advisor nicht weiß, dass der Indikator auf dem Chart vorhanden ist? Tatsächlich weiß der Expert Advisor, wie die anderen Anwendungen auch, nichts von der Anwesenheit der anderen. Sie alle erwarten einfach, dass der Trader sie dem Chart hinzufügt, damit sie ihre Aufgaben korrekt ausführen können. Allerdings gibt es hier ein wichtiges Detail. Da jeder Positionsindikator nur einer bestimmten Position entspricht, können wir ihn nicht an den Chart anhängen, bevor eine Position für dieses Symbol erscheint. Im Gegensatz zu anderen Indikatoren wird dieser Positionsindikator automatisch vom Expert Advisor hinzugefügt und entfernt. Die Idee ist, dass der Trader nicht in diesen Prozess eingreifen sollte. Der Expert Advisor selbst wird sich darum kümmern.
Ich werde den Positionsindikator jedoch nicht in den Expert Advisor einbetten. Die Idee ist, dass der Indikator modifiziert oder verbessert werden kann, damit er von allen Expert Advisors verwendet werden kann, ohne dass diese neu kompiliert werden müssen. Damit jedoch alles reibungslos funktioniert, sind einige Änderungen erforderlich. Gleichzeitig sollten Sie, lieber Leser, genau darauf achten, was erklärt wird. Andernfalls wird das gesamte System fehlschlagen und nicht die Daten liefern, die auf dem Chart angezeigt werden sollten. Ein weiteres Detail ist, dass Sie sich vorerst keine Gedanken über die Details der Preislinien machen müssen. Das Erste, was wir jetzt tun müssen, ist eine Möglichkeit zu schaffen, wie der Expert Advisor und der Positionsindikator interagieren können. Danach werden wir uns mit der Interaktion zwischen dem Positionsindikator und dem Mausindikator befassen, der für die Verwaltung der Preislinien verantwortlich sein wird.
Beginn der Implementierung der Interaktion
Gut, lassen Sie uns damit beginnen, einige Änderungen am Hauptcode des Positionsindikators vorzunehmen. Der Grund dafür ist, dass er nicht mehr – oder besser gesagt: sollte nicht mehr – vom Trader oder Benutzer zum Chart hinzugefügt werden muss. Der EA wird das übernehmen. Da der Expert Advisor wissen muss, welcher Indikator für welche Position steht, müssen wir einige Dinge sowohl im Indikatorcode als auch im Expert Advisor-Code ändern.
Nachdem wir nun verstehen, was wir tun müssen, lassen Sie uns mit dem neuen Code für den Positionsindikator beginnen. Sie können es unten sehen:
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. #property description "Indicator for tracking an open position on the server." 04. #property description "This should preferably be used together with an Expert Advisor." 05. #property description "For more details see the same article." 06. #property link "https://www.mql5.com/pt/articles/13168" 07. #property version "1.116" 08. #property indicator_chart_window 09. #property indicator_plots 0 10. //+------------------------------------------------------------------+ 11. #define def_ShortName "Position View" 12. //+------------------------------------------------------------------+ 13. #include <Market Replay\Order System\C_IndicatorPosition.mqh> 14. //+------------------------------------------------------------------+ 15. input ulong user00 = 0; //For Expert Advisor use 16. input color user01 = clrRoyalBlue; //Color Line Price 17. input color user02 = clrForestGreen; //Color Line Take Profit 18. input color user03 = clrFireBrick; //Color Line Stop Loss 19. //+------------------------------------------------------------------+ 20. C_IndicatorPosition *Positions = NULL; 21. //+------------------------------------------------------------------+ 22. int OnInit() 23. { 24. IndicatorSetString(INDICATOR_SHORTNAME, def_ShortName); 25. Positions = new C_IndicatorPosition(user01, user02, user03); 26. if (!Positions.CheckCatch(user00)) 27. { 28. ChartIndicatorDelete(ChartID(), 0, def_ShortName); 29. return INIT_FAILED; 30. } 31. 32. return INIT_SUCCEEDED; 33. } 34. //+------------------------------------------------------------------+ 35. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[]) 36. { 37. return rates_total; 38. } 39. //+------------------------------------------------------------------+ 40. void OnDeinit(const int reason) 41. { 42. delete Positions; 43. } 44. //+------------------------------------------------------------------+
Code des Positionsindikators Position View
Beachten Sie, dass der Code geringfügige Änderungen erfahren hat. Diese Änderungen sind unkompliziert und bedürfen keiner großen Erklärung. Sie sollten jedoch sorgfältig beachten, dass in Zeile 15 nun Daten vom Expert Advisor erwartet werden. Als Trader könnten Sie diese Daten sogar selbst eingeben. Ich rate Ihnen jedoch, diese Informationen nicht zu ändern. Sie können die Farben ändern, wenn Sie vorsichtig sind und sie nicht identisch wählen, da wir sie derzeit verwenden, um zu prüfen, welche horizontale Linie die jeweilige Farbe darstellt. Vermeiden Sie auf jeden Fall, wann immer möglich, die Änderung der Daten, die vom Expert Advisor stammen sollten. Insbesondere werden diese Daten vom Expert Advisor verwendet, um Informationen mit dem Indikator auszutauschen, wenn sich beide Komponenten auf dem Chart befinden.
Bitte beachten Sie, dass wir in Zeile 26 einen Parameter an die Prüffunktion übergeben. Zuvor existierte dieser Parameter nicht. Schauen wir uns den Code der Klasse C_IndicatorPosition an, der unten vollständig dargestellt ist:
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. //+------------------------------------------------------------------+ 04. #define def_SufixTake "Take" 05. #define def_SufixStop "Stop" 06. //+------------------------------------------------------------------+ 07. #include "..\Auxiliar\C_Terminal.mqh" 08. //+------------------------------------------------------------------+ 09. class C_IndicatorPosition : private C_Terminal 10. { 11. private : 12. struct st00 13. { 14. ulong ticket; 15. color corPrice, corTake, corStop; 16. }m_Infos; 17. //+------------------------------------------------------------------+ 18. void CreateLineInfos(const string szObjName, const double price, const color cor, const string szDescription = "\n") 19. { 20. if (price <= 0) return; 21. CreateObjectGraphics(szObjName, OBJ_HLINE, cor, (EnumPriority)(cor == m_Infos.corPrice ? ePriorityNull : (ePriorityOrders + (cor == m_Infos.corStop)))); 22. ObjectSetDouble(GetInfoTerminal().ID, szObjName, OBJPROP_PRICE, price); 23. ObjectSetString(GetInfoTerminal().ID, szObjName, OBJPROP_TEXT, szDescription); 24. ObjectSetString(GetInfoTerminal().ID, szObjName, OBJPROP_TOOLTIP, szDescription); 25. ObjectSetInteger(GetInfoTerminal().ID, szObjName, OBJPROP_SELECTABLE, cor != m_Infos.corPrice); 26. } 27. //+------------------------------------------------------------------+ 28. public : 29. //+------------------------------------------------------------------+ 30. C_IndicatorPosition(color corPrice, color corTake, color corStop) 31. :C_Terminal() 32. { 33. ZeroMemory(m_Infos); 34. m_Infos.corPrice = corPrice; 35. m_Infos.corTake = corTake; 36. m_Infos.corStop = corStop; 37. } 38. //+------------------------------------------------------------------+ 39. ~C_IndicatorPosition() 40. { 41. if (m_Infos.ticket != 0) 42. ObjectsDeleteAll(GetInfoTerminal().ID, IntegerToString(m_Infos.ticket)); 43. } 44. //+------------------------------------------------------------------+ 45. bool CheckCatch(ulong ticket) 46. { 47. string szName = IntegerToString(m_Infos.ticket = ticket); 48. 49. if (!PositionSelectByTicket(m_Infos.ticket)) return false; 50. if (ObjectFind(GetInfoTerminal().ID, szName) >= 0) 51. { 52. m_Infos.ticket = 0; 53. return false; 54. } 55. IndicatorSetString(INDICATOR_SHORTNAME, szName); 56. CreateLineInfos(szName, PositionGetDouble(POSITION_PRICE_OPEN), m_Infos.corPrice, "Position opening price."); 57. CreateLineInfos(szName + def_SufixTake, PositionGetDouble(POSITION_TP), m_Infos.corTake, "Take Profit point."); 58. CreateLineInfos(szName + def_SufixStop, PositionGetDouble(POSITION_SL), m_Infos.corStop, "Stop Loss point."); 59. 60. return true; 61. } 62. //+------------------------------------------------------------------+ 63. }; 64. //+------------------------------------------------------------------+ 65. #undef def_SufixTake 66. #undef def_SufixStop 67. //+------------------------------------------------------------------+
C_IndicatorPosition.mqh
Obwohl sich der Code etwas geändert hat, sind die Änderungen unkompliziert und bedürfen keiner großen Erklärung. Dennoch nimmt die Check-Funktion, wie bereits erwähnt, jetzt ein Argument entgegen. Schauen wir uns an, was sich in dieser Funktion geändert hat. Gehen Sie dazu zu Zeile 45, wo die Funktion CheckCatch definiert ist.
Beachten Sie, dass wir gleich zu Beginn der Funktion Zeile 47 sehen. In diesem Stadium konvertieren wir die Daten, die der Expert Advisor an uns übergibt, damit sie in den Namen der zu erstellenden Objekte verwendet werden können. Dann prüfen wir in Zeile 49, ob die Position existiert. Nun, es ist eine Erklärung wert, warum wir diese Prüfung erneut durchführen, da der Expert Advisor uns mitteilen und garantieren wird, dass die Position existiert. Gut. Der Punkt ist, dass ich nicht die Absicht habe, diesen Positionsindikator zu einem integrierten Bestandteil des Expert Advisors zu machen. Wenn also ein Trader oder sogar ein Benutzer versucht, diesen Indikator zum Chart hinzuzufügen, müssen wir bestätigen, dass die Position existiert. Bitte beachten Sie, dass wir diesen Parameter in diesem Fall nicht vom Indikator abrufen, wie wir es im vorherigen Artikel getan haben.
Sobald die Existenz der Position bestätigt wurde, wird eine neue Prüfung durchgeführt. Dies geschieht in Zeile 50. In diesem Fall dient die Prüfung jedoch dazu, sicherzustellen, dass es für jede Position im Chart nur eine Indikatorinstanz gibt. Es gibt andere Möglichkeiten, dieselbe Prüfung durchzuführen. Hier prüfen wir jedoch auf das Vorhandensein einer Linie mit einem bestimmten Namen. Wenn alles gut geht, wird der Indikator wie im vorherigen Artikel gezeigt funktionieren. Wir können daher zum Code des Expert Advisors übergehen, um zu verstehen, wie sich das System verhält, wenn der Expert Advisor zum Chart hinzugefügt wird. Der neue Expert Advisor-Code ist unten zu sehen:
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. #property icon "/Images/Market Replay/Icons/Replay - EA.ico" 04. #property description "Demo version between interaction" 05. #property description "of Chart Trade and Expert Advisor" 06. #property version "1.116" 07. #property link "https://www.mql5.com/pt/articles/13168" 08. //+------------------------------------------------------------------+ 09. #include <Market Replay\Order System\C_Orders.mqh> 10. //+------------------------------------------------------------------+ 11. enum eTypeContract {MINI, FULL}; 12. //+------------------------------------------------------------------+ 13. input eTypeContract user00 = MINI; //Cross order in contract 14. //+------------------------------------------------------------------+ 15. C_Orders *Orders; 16. long GL_ID; 17. //+------------------------------------------------------------------+ 18. int OnInit() 19. { 20. GL_ID = 0; 21. Orders = new C_Orders(0xC0DEDAFE78514269); 22. 23. return INIT_SUCCEEDED; 24. } 25. //+------------------------------------------------------------------+ 26. void OnTick() {} 27. //+------------------------------------------------------------------+ 28. void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) 29. { 30. (*Orders).DispatchMessage(id, lparam, dparam, sparam); 31. switch (id) 32. { 33. case CHARTEVENT_CHART_CHANGE: 34. if (GL_ID > 0) break; 35. else 36. { 37. GL_ID = ChartID(); 38. for (int handle, count = PositionsTotal() - 1; count >= 0; count--) 39. { 40. handle = iCustom(_Symbol, PERIOD_CURRENT, "\\Indicators\\Position View.ex5", PositionGetTicket(count)); 41. ChartIndicatorAdd(GL_ID, 0, handle); 42. IndicatorRelease(handle); 43. } 44. } 45. case CHARTEVENT_CUSTOM + evChartTrade_At_EA: 46. EventChartCustom(GL_ID, evEA_At_ChartTrade, user00, 0, ""); 47. break; 48. } 49. } 50. //+------------------------------------------------------------------+ 51. void OnDeinit(const int reason) 52. { 53. switch (reason) 54. { 55. case REASON_REMOVE: 56. case REASON_INITFAILED: 57. EventChartCustom(GL_ID, evEA_At_ChartTrade, -1, 0, ""); 58. break; 59. } 60. 61. delete Orders; 62. } 63. //+------------------------------------------------------------------+
Expert Advisor.mq5
Beachten Sie, dass sich der Code im Vergleich zu dem zu Beginn dieses Artikels gezeigten Code nur sehr wenig geändert hat. Der eigentliche Grund für die wenigen Änderungen ist, dem Leser zu zeigen, dass das System mit wenig Aufwand korrekt funktioniert. Bitte beachten Sie, dass sich alle Änderungen, oder besser gesagt Ergänzungen des Codes, zwischen den Zeilen 38 und 43 befinden. Aber das reicht bereits aus, damit der Expert Advisor zumindest eine Verbindung mit dem Positionsindikator herstellen kann. Tatsächlich wurde das, was wir hier tun, früher innerhalb des Indikator-Codes erledigt. In diesem Code wird für jede offene Position ein Positionsindikator an den Chart angehängt.
Achten Sie dennoch auf etwas Wichtiges. Wir verfolgen alle offenen Positionen, aber – und das ist wichtig – wir filtern sie nicht. Wir fügen dem Chart, auf dem der Expert Advisor läuft, einfach Indikatoren hinzu. Aber eine Position kann einem Symbol entsprechen, das sich von dem unterscheidet, das auf diesem Chart angezeigt werden soll. Gut, Sie denken vielleicht, das war mein Fehler, aber nein, ich habe es absichtlich getan, um zu zeigen, dass dieser Fehler recht häufig vorkommt. Und bis die Leute es bemerken, wird bereits ein unzuverlässiger Mechanismus verwendet.
Beachten Sie, dass das Problem nicht darin besteht, dass wir die in MQL5 verfügbare Variable _Symbol verwenden, um auf den Namen des Chart-Symbols zuzugreifen. Der Fehler besteht darin, dass wir nicht prüfen, ob die von der Funktion PositionGetTicket zurückgegebene Position eine Position ist, die zu dem Chart-Symbol gehört oder in irgendeiner Weise damit zusammenhängt, wie es im Indikator-Code geprüft wurde. Dies ist ein Fehler, auf den Sie immer achten sollten. Während des Tests mag es uns so vorkommen, als ob auf einem Demokonto alles korrekt funktioniert. Beim Wechsel auf ein Realkonto kann jedoch Geld aufgrund von unvorsichtiger Programmierung oder unzureichenden Tests während der Implementierung verloren gehen. Daher sollten Sie, lieber Leser, wenn Sie gerade erst neue Konzepte lernen oder meistern, vorsichtig sein, wenn Sie Code ändern. Überprüfen Sie die von Ihnen vorgenommenen Änderungen immer gründlich und lesen Sie die Dokumentation sorgfältig durch, um alle Zweifel auszuräumen.
Gut. Nun beginnen Sie zu erkennen, dass einige Aspekte der Programmierung etwas komplexer sind, als sie auf den ersten Blick erscheinen mögen. Dennoch ist dies kein Grund, sich entmutigen zu lassen und das Programmieren aufzugeben. Die Hauptsache ist, sich anzupassen und den richtigen Weg zu finden. Aber Sie denken sicher, dass es in diesem Fall ausreicht zu prüfen, ob das Symbol der Position, die durch das Ticket angegeben wird, mit dem übereinstimmt, das wir voraussichtlich verwenden werden. Richtig? In gewisser Weise ja.
Und ich sage das gerade deshalb, weil ich nicht weiß, auf welchem Markt Sie handeln. Dies wurde bereits zu Beginn des Artikels erwähnt. Es gibt Fälle, hauptsächlich an der B3 (der brasilianischen Börse), in denen wir einen vollen Kontrakt und einen Minikontrakt haben. Wir verfügen auch über die historischen Daten für den aktuellen Kontrakt. Einige Trader ziehen es vor, historische Daten für den Handel zu verwenden. Andere nutzen den Chart des Symbols, das sie handeln möchten.
Beachten Sie, dass dies zwar wie eine komplizierte Situation erscheinen mag und Sie sich vielleicht fragen, warum jemand sein Leben damit verkomplizieren sollte, auf einem Chart zu handeln, der sich von dem Chart des spezifischen Kontrakts oder Symbols unterscheidet, dies jedoch immer die Entscheidung des Traders ist. Wir können den Trader nicht einschränken; unsere Aufgabe als Programmierer ist es, die Bedürfnisse des Traders zu erfüllen.
Dies wirft eine weitere Frage auf: Wie gehen wir mit dieser Situation um, wenn wir keine Möglichkeit haben, zu wissen, welches Symbol korrekt ist? Doch, lieber Leser, die Situation ist nicht so kompliziert. Ja, wir wissen, wo sich die Daten für das entsprechende Symbol befinden. Sie werden im Chart-Trade-Indikator angezeigt. Und genau hier wird die Situation wirklich interessant. Der Programmierer hat zwei Möglichkeiten. Die erste Option besteht darin, das Chart Trade-Panel zu fragen, welches Symbol korrekt ist und dessen Positionen im Chart angezeigt werden sollen. Gut, vielleicht denken Sie: „Aber warum sollte ich Chart Trade diese Frage stellen? Wenn die Daten im Chart Trade-Objekt angezeigt werden, muss ich nur den Inhalt dieses Objekts lesen.“
Das könnte man meinen, lieber Leser. Die Daten befinden sich im Chart Trade-Objekt, aber der Zugriff darauf wird nicht so einfach sein. Um diese Daten von Chart Trade zu erhalten, müssten wir eine separate Nachricht erstellen, aber das würde den Code des Expert Advisors erheblich verkomplizieren. Es gibt jedoch eine andere Lösung, die viel einfacher ist, aber wir müssen korrekt vorgehen. Andernfalls brechen wir die Kapselung auf, die vor geraumer Zeit erstellt und getestet wurde. Wenn Sie in Ruhe darüber nachdenken und den Code analysieren, werden Sie feststellen, dass das Chart Trade-Panel die Symboldaten von der Klasse C_Terminal bezieht. Genauer gesagt von der Prozedur CurrentSymbol, die sich in Zeile 47 der Klasse C_Terminal befindet.
Hier liegt die Gefahr, insbesondere für diejenigen, die gerade erst mit dem Programmieren beginnen. Viele unerfahrene Entwickler werden versuchen, direkt vom Expert Advisor aus auf diese Prozedur zuzugreifen. Dies ist unmöglich, da sich die Prozedur im geschützten Bereich befindet. Also könnten Sie denken: „Ich werde diese Prozedur in den öffentlichen Bereich verschieben.“ Das ist ein Fehler. Und der zweite Fehler wäre dieser: Wenn Sie sich die Prozedur ansehen, werden Sie feststellen, dass sie keinen Wert zurückgibt oder Argumente akzeptiert. Sie entscheiden sich dann, sie so zu ändern, dass sie die Daten für das korrekte Symbol zurückgibt, aber damit zerstören Sie die Prozedur vollständig, da sich dies in Zukunft ändern könnte, was uns ermöglichen würde, weitere Funktionen hinzuzufügen. Daher ist die korrekte Lösung, die Prozedur in Zeile 47 der Klasse C_Terminal NICHT anzufassen.
Als Anfänger könnten Sie sich also vorstellen: „Nun, dieses Problem kann nicht gelöst werden, da es unmöglich ist, zu wissen, welches Symbol verwendet wird.“ Aber das ist die falsche Art, das Problem zu formulieren. Ja, es gibt eine Lösung, und sie ist einfach, elegant und effizient. Sie wird keine Nebenwirkungen in den Code einführen, der bereits erstellt und getestet wurde. Alles, was wir tun müssen, ist, zum Konstruktor der Klasse C_Terminal zu gehen und dort eine Änderung vorzunehmen. Der Quellcode ist in dem folgenden Fragment zu sehen:
106. //+------------------------------------------------------------------+ 107. C_Terminal(const long id = 0, const uchar sub = 0) 108. { 109. m_Infos.ID = (id == 0 ? ChartID() : id); 110. m_Mem.AccountLock = false; 111. m_Infos.SubWin = (int) sub; 112. CurrentSymbol(false); 113. ZeroMemory(m_Mouse); 114. m_Mem.Show_Descr = ChartGetInteger(m_Infos.ID, CHART_SHOW_OBJECT_DESCR);
Ursprüngliches Fragment der Datei C_Terminal.mqh
Die notwendigen Änderungen sind unten dargestellt:
106. //+------------------------------------------------------------------+ 107. C_Terminal(const long id = 0, const uchar sub = 0, const bool bFull = false) 108. { 109. m_Infos.ID = (id == 0 ? ChartID() : id); 110. m_Mem.AccountLock = false; 111. m_Infos.SubWin = (int) sub; 112. CurrentSymbol(bFull); 113. ZeroMemory(m_Mouse); 114. m_Mem.Show_Descr = ChartGetInteger(m_Infos.ID, CHART_SHOW_OBJECT_DESCR);
Geändertes Fragment der Datei C_Terminal.mqh
Ist Ihnen der Unterschied zwischen den beiden Code-Abschnitten aufgefallen? Es ist eine sehr kleine, einfache und elegante Änderung. Jetzt können wir die Klasse C_Terminal verwenden, um den Symbolnamen direkt im Expert Advisor zu erhalten. Oder wir können die Daten an den Positionsindikator weitergeben, damit er diese Aufgabe für uns übernimmt. In beiden Fällen kann der Expert Advisor dem Positionsindikator nun mitteilen, ob er volle Kontrakte oder Minikontrakte anzeigen soll. Dies wird durch die direkte Verwendung der Kontrakthistorie erreicht. Sie könnten denken, dass dies ein Problem verursachen würde, da es mit den Angaben in Chart Trade in Konflikt geraten könnte, aber das ist tatsächlich nicht der Fall. Die Daten werden exakt mit den Angaben in Chart Trade übereinstimmen.
Lassen Sie uns diese Lösung also implementieren. Da ich keine Tests im Indikator durchführen möchte, weil sein Zweck ein völlig anderer ist, werden wir die Daten direkt im Expert Advisor testen. Der korrigierte Expert Advisor-Code ist daher unten zu sehen:
01. //+------------------------------------------------------------------+ 02. #property copyright "Daniel Jose" 03. #property icon "/Images/Market Replay/Icons/Replay - EA.ico" 04. #property description "Demo version between interaction" 05. #property description "of Chart Trade and Expert Advisor" 06. #property version "1.116" 07. #property link "https://www.mql5.com/pt/articles/13168" 08. //+------------------------------------------------------------------+ 09. #include <Market Replay\Order System\C_Orders.mqh> 10. #include <Market Replay\Auxiliar\C_Terminal.mqh> 11. //+------------------------------------------------------------------+ 12. enum eTypeContract {MINI, FULL}; 13. //+------------------------------------------------------------------+ 14. input eTypeContract user00 = MINI; //Cross order in contract 15. //+------------------------------------------------------------------+ 16. C_Orders *Orders = NULL; 17. C_Terminal *Terminal = NULL; 18. //+------------------------------------------------------------------+ 19. int OnInit() 20. { 21. Orders = new C_Orders(0xC0DEDAFE78514269); 22. 23. return INIT_SUCCEEDED; 24. } 25. //+------------------------------------------------------------------+ 26. void OnTick() {} 27. //+------------------------------------------------------------------+ 28. void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) 29. { 30. (*Orders).DispatchMessage(id, lparam, dparam, sparam); 31. switch (id) 32. { 33. case CHARTEVENT_CHART_CHANGE: 34. if (Terminal != NULL) break; 35. else 36. { 37. ulong ul; 38. Terminal = new C_Terminal(0, 0, user00); 39. for (int handle, count = PositionsTotal() - 1; count >= 0; count--) 40. { 41. ul = PositionGetTicket(count); 42. if (PositionGetString(POSITION_SYMBOL) != (*Terminal).GetInfoTerminal().szSymbol) continue; 43. handle = iCustom(_Symbol, PERIOD_CURRENT, "\\Indicators\\Position View.ex5", ul); 44. ChartIndicatorAdd((*Terminal).GetInfoTerminal().ID, 0, handle); 45. IndicatorRelease(handle); 46. } 47. } 48. case CHARTEVENT_CUSTOM + evChartTrade_At_EA: 49. if (Terminal != NULL) 50. EventChartCustom((*Terminal).GetInfoTerminal().ID, evEA_At_ChartTrade, user00, 0, ""); 51. break; 52. } 53. } 54. //+------------------------------------------------------------------+ 55. void OnDeinit(const int reason) 56. { 57. switch (reason) 58. { 59. case REASON_REMOVE: 60. case REASON_INITFAILED: 61. if (Terminal != NULL) 62. EventChartCustom((*Terminal).GetInfoTerminal().ID, evEA_At_ChartTrade, -1, 0, ""); 63. break; 64. } 65. 66. delete Orders; 67. delete Terminal; 68. } 69. //+------------------------------------------------------------------+
Expert Advisor.mq5
Das ist das Schöne am Programmieren. Vergleichen Sie den vorherigen Code mit dem anderen in diesem Artikel gezeigten Expert Advisor-Code und bemerken Sie, wie schön und faszinierend Programmieren ist. Durch ein wenig Wissen über Zeiger in C/C++ konnten wir hier in MQL5 die globale Variable entfernen und nur die Klassendeklarationen belassen. In Wirklichkeit wären dies Zeiger auf Klassenobjekte. Aber das ist in Ordnung: MQL5 verwendet Zeiger nicht auf die gleiche Weise wie C/C++. Dennoch können wir einen Teil dessen verwenden, was in C/C++ verfügbar ist. Wenn Sie nicht verstehen, was in diesem Expert Advisor passiert, machen Sie sich keine Sorgen, denn ich bin hier, um Ihnen zu helfen, diesen Code zu verstehen.
Beachten Sie, dass wir in Zeile 10 die Header-Datei C_Terminal.mqh eingebunden haben, die wir gerade an unsere Bedürfnisse angepasst haben. In Zeile 17 deklarieren wir eine globale Variable, damit wir auf die Klasse zugreifen können. Obwohl dies nicht zwingend erforderlich ist, möchte ich jedoch explizit zeigen, dass die Zeigervariable mit dem Wert NULL initialisiert wird. Wenn Sie diesen Parameter nicht angeben, erledigt dies der Compiler implizit. Es ist jedoch auch wichtig, genau zu klären, welche Initialisierung wir durchführen.
Gut. Sobald die Funktion OnInit ausgeführt wurde, löst MetaTrader 5 das Ereignis CHART_CHANGE aus. Es wird von der Funktion OnChartEvent in Zeile 28 abgefangen, wo der Expert Advisor mit der Ereignisverarbeitung beginnt. Beim ersten Ausführen dieser Funktion hat der Terminal-Zeiger den Wert NULL. Folglich wird die Bedingung in Zeile 34 als falsch ausgewertet, wodurch Zeile 35 ausgeführt werden kann. Hier beginnt der Zauber. Beachten Sie, dass der Code hier dem Code sehr ähnlich ist, den wir zuvor im Expert Advisor gesehen haben. In Zeile 38 rufen wir jedoch den Konstruktor der Klasse C_Terminal auf und geben an, ob wir den einen oder den anderen Kontrakttyp verwenden werden.
Infolgedessen generiert der Konstruktor den korrekten Symbolnamen. Somit erhalten wir in Zeile 41 den Ticketwert. Wir müssen dies tun, bevor wir andere Funktionen aufrufen, um Positionsdaten zu erhalten. Dies wird in der MQL5-Dokumentation erwähnt; studieren Sie diese für detailliertere Informationen. Danach können wir in Zeile 42 überprüfen, ob der Name des Symbols, zu dem die Position gehört, mit dem vom Expert Advisor erwarteten Namen übereinstimmt. Falls dies nicht der Fall ist, kehren wir zu Zeile 39 zurück. Andernfalls, das heißt, wenn das Symbol den erwarteten Namen hat, rufen wir den Positionsindikator auf, wie dies zuvor geschehen ist.
Achten Sie nun auf die Zeilen 49 und 61. Beantworten Sie dies: Warum führe ich die Überprüfung in diesen Zeilen durch? Denken Sie einen Moment nach, bevor Sie die Antwort lesen, die ich unten bereitstelle. Gut, ich hoffe, Sie haben zumindest einen Versuch unternommen, bevor Sie die Antwort gelesen haben. Der Grund für die Existenz dieser Zeilen ist genau die Erhöhung der Zuverlässigkeit des Expert Advisor-Codes. Wenn Sie versuchen, eine Funktion oder Prozedur der Klasse C_Terminal aufzurufen, bevor die Klasse ordnungsgemäß initialisiert wurde, verhindert die Überprüfung des Zeigerwerts auf NULL, dass der Expert Advisor einfach einen Fehler im MetaTrader 5-Terminal generiert. Durch die Durchführung dieser Überprüfung stellen Sie sicher, dass der Programmablauf wie erwartet bleibt.
Viele C/C++-Programmierer, aber hauptsächlich C-Programmierer, führen diese Überprüfungen bei der Verwendung von Zeigern normalerweise nicht durch. Dies ist der Grund, warum viele Leute glauben, dass in C geschriebene Programme viele Startfehler enthalten. Solche Fehler hängen jedoch nicht mit der Sprache selbst zusammen, sondern damit, wie das Programm oder warum es auf diese Weise geschrieben wurde. In einigen Fällen werden Programme, die nach Schwachstellen in einem System suchen, sogar absichtlich erstellt, um eine vom Systembesitzer nicht beabsichtigte Aktion auszuführen.
Abschließende Überlegungen
In diesem Artikel haben wir begonnen, verschiedene Anwendungen zusammenzuführen, die zuvor vollständig voneinander isoliert waren. Obwohl Chart Trade, der Mausindikator und der Expert Advisor bereits eine gewisse Beziehung zueinander hatten, gab es bisher keine Möglichkeit, die auf dem Handelsserver offenen Positionen direkt im Chart anzuzeigen. Häufig wird ein Cross-Order-System verwendet. Von diesem Punkt an wird dies möglich, was viele Möglichkeiten für neue Ideen und Implementierungen eröffnet. Obwohl wir erst damit beginnen, die Komponenten in Betrieb zu nehmen, haben wir bereits eine Richtung, der wir folgen können.
Ja, auf den ersten Blick ist dieses System sehr primitiv und hätte in einem fortgeschritteneren Zustand präsentiert werden können, aber das hielt ich nicht für angemessen. Es hätte viele Programmieranfänger ohne ein wirkliches Verständnis dafür gelassen, was im Code passiert. Denken Sie daran, dass Änderungen schrittweise erfolgen, damit jeder mit ihnen Schritt halten kann. Dieses Material hat einen didaktischen Zweck; es ist nicht dazu gedacht, den einzigen Weg zu demonstrieren, wie man etwas in MetaTrader 5 umsetzt. Ich hoffe, all dieses Material hilft denjenigen, die wirklich nach Wissen suchen. Im nächsten Artikel werden wir die hier vorgestellten Ideen weiterentwickeln. Bis bald!
| Datei | Beschreibung |
|---|---|
| Experts\Expert Advisor.mq5 | Zeigt die Interaktion zwischen Chart Trade und dem Expert Advisor (für die Interaktion ist „Mouse Study“ erforderlich). |
| Indicators\Chart Trade.mq5 | Erstellt ein Fenster zur Konfiguration des zu versendenden Auftrags (für die Interaktion ist „Mouse Study“ erforderlich). |
| Indicators\Market Replay.mq5 | Erstellt Steuerelemente für die Interaktion mit dem Replikations-/Simulationsdienst (für die Interaktion ist „Mouse Study“ erforderlich). |
| Indicators\Mouse Study.mq5 | Ermöglicht die Interaktion zwischen grafischen Steuerelementen und dem Benutzer (dies ist sowohl für die Arbeit mit dem Replikations-/Simulationssystem als auch im realen Markt erforderlich). |
| Indicators\Order Indicator.mq5 | Verantwortlich für die Anzeige von Marktorders sowie die Ermöglichung der Interaktion mit ihnen und deren Steuerung. |
| Indicators\Position View.mq5 | Verantwortlich für die Anzeige von Marktpositionen sowie die Ermöglichung der Interaktion mit ihnen und deren Steuerung. |
| Services\Market Replay.mq5 | Erstellt und verwaltet den Markt-Replikations-/Simulationsdienst (die Hauptdatei des gesamten Systems). |
Übersetzt aus dem Portugiesischen von MetaQuotes Ltd.
Originalartikel: https://www.mql5.com/pt/articles/13168
Warnung: Alle Rechte sind von MetaQuotes Ltd. vorbehalten. Kopieren oder Vervielfältigen untersagt.
Dieser Artikel wurde von einem Nutzer der Website verfasst und gibt dessen persönliche Meinung wieder. MetaQuotes Ltd übernimmt keine Verantwortung für die Richtigkeit der dargestellten Informationen oder für Folgen, die sich aus der Anwendung der beschriebenen Lösungen, Strategien oder Empfehlungen ergeben.
Die Übertragung der Trading-Signale in einem universalen Expert Advisor.
Neuronale Netze im Trading: Generalisierung von Zeitreihen ohne Abhängigkeit von spezifischen Daten (Kernmodule des Modells)
Eine alternative Log-datei mit der Verwendung der HTML und CSS
Implementierung einer Schaltung für Quantum Reservoir Computing (QRC)
- 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.