English Русский Español Português
preview
Marktsimulation: Positionsanzeige (VI)

Marktsimulation: Positionsanzeige (VI)

MetaTrader 5 — Tester |
18 0
Daniel Jose
Daniel Jose

Einleitung

Herzlich willkommen zu einem neuen Artikel in unserer Reihe über das Replay-/Simulationssystem.

Im vorherigen Artikel „Marktsimulation: Positionsansicht (V)“ haben wir erläutert, wie man die Daten abruft, die erforderlich sind, um die Vorgänge in der Anwendung nachzuvollziehen. Auf diese Weise können wir das System mithilfe der Funktion OnTradeTransaction implementieren. Darin wurde lediglich gezeigt, wie man dies im Expert Advisor macht. Nachdem Sie sich diese Daten und den Expert Advisor angesehen haben, fanden Sie das Ganze wahrscheinlich ziemlich verwirrend und haben sich vermutlich gefragt, wie praktisch das Ganze eigentlich ist. Ein bisschen Skepsis kann nicht schaden. Es ist außerdem hilfreich – und sogar ratsam –, gewisse Zweifel zu hegen, wenn wir auf etwas völlig Neues stoßen.

Daher werden wir in diesem Artikel die ersten Schritte unternehmen, um die im vorherigen Artikel vorgestellten Daten besser zu verstehen. Da der behandelte Stoff auf den ersten Blick vielleicht etwas verwirrend wirkt, möchte ich Sie bitten, sich später in Ruhe diesen Artikel durchzulesen und einige Tests durchzuführen, um die Erläuterungen besser zu verstehen. Sie sollten das in diesem Artikel behandelte Material unter keinen Umständen auf ein Echtkonto anwenden, ohne vollständig zu verstehen, was dabei vor sich geht, da die Wahrscheinlichkeit hoch ist, dass Sie Verluste erleiden und Fehler bei der Interpretation der im Chart angezeigten Daten machen, was zu einer sehr unangenehmen Erfahrung bei der Arbeit mit dem von uns entwickelten System führen könnte.

Noch einmal: Verwenden Sie das System, das wir erstellen werden, nicht, ohne es vollständig verstanden zu haben. Probieren Sie dazu den Code aktiv aus und setzen Sie sich damit auseinander, denn er soll hier so verständlich und lehrreich wie möglich sein. In diesem Fall ist Effizienz nur ein nebensächliches Detail. Die wichtigste Anforderung ist, dass der Code so einfach wie möglich sein sollte, damit jeder versteht, was vor sich geht.


Schauen wir uns einmal an, was wir machen werden.

Viele von Ihnen sind wahrscheinlich daran gewöhnt, ständig dieselben Aufgaben zu sehen oder auszuführen. Es ist nicht so, dass dieser Ansatz falsch wäre, aber wenn es einen anderen Weg gibt, warum sollte man ihn dann nicht einmal ausprobieren? Genau das ist der Punkt, den man hier verstehen muss. Der Hauptzweck des Expert Advisors besteht nicht darin, Objekte auf dem Chart zu platzieren oder Berechnungen durchzuführen. Man kann es sogar auf diese Weise machen. Das ist kein Fehler. Die Hauptaufgabe des Expert Advisors besteht jedoch darin, eine ordnungsgemäße Anbindung an den Handelsserver bereitzustellen. Daher können wir auf jedem Chart nur einen Expert Advisor einsetzen. Es ist nicht die beste Lösung, den Expert Advisor Aufgaben wie das Erstellen von Objekten oder das Arbeiten mit ihnen auf dem Chart übernehmen zu lassen.

Lassen Sie mich das noch einmal betonen: Es ist absolut nichts Falsches daran, diese Aufgaben im Expert Advisor auszuführen. Beachten Sie jedoch, dass Sie möglicherweise mehr als einen Expert Advisor haben, wobei jeder für den Einsatz in einem bestimmten Szenario auf einem bestimmten Markt konzipiert ist. Alles in einem einzigen Programmteil unterzubringen, ist nicht besonders praktisch. Wenn Sie sich nämlich entscheiden, in jedem Expert Advisor ein System zur Positionsvisualisierung zu implementieren und es anschließend in einem anderen Expert Advisor zu verbessern, werden Sie mit der Verwendung der alten Version unzufrieden sein, da Sie den Code in alle bestehenden Expert Advisors übertragen müssen.

Deshalb schlage ich vor, hierfür einen Indikator zu verwenden. Aber wie Sie wahrscheinlich den letzten Artikeln entnommen haben, kann dieser Indikator bestimmte Dinge nicht tun. Es ist weder möglich noch empfehlenswert, zu versuchen, den Indikator zur Ausführung bestimmter Aufgaben zu zwingen. Wir können jedoch einen Indikator erstellen, mit dem wir offene Positionen auf dem Chart anzeigen können. Wir müssen Mechanismen entwickeln, die es uns ermöglichen, Indikatoren einheitlicher und weniger verwirrend zu nutzen.

Ein solcher Mechanismus ist der Nachrichtenaustausch zwischen dem Indikator und dem Expert Advisor. Wir nutzen diesen Mechanismus bereits seit einiger Zeit. Das liegt daran, dass sowohl der Chart Trade-Indikator als auch der Mouse Study-Indikator denselben Mechanismus nutzen, um mit dem Expert Advisor zu kommunizieren. Wir haben jedoch noch keinen Mechanismus geschaffen – oder genauer gesagt, noch nicht einmal mit seiner Entwicklung begonnen –, der es dem Positionsindikator ermöglichen würde, mit dem Expert Advisor zu interagieren.


Eine kleine Verbesserung

Als Erstes sollten wir dem Expert Advisor ermöglichen, jedes Mal, wenn eine neue Position eröffnet wird, dem Chart einen Positionsindikator hinzuzufügen. Das ist relativ einfach umzusetzen, da wir denselben Mechanismus verwenden können, der auch beim Platzieren des Expert Advisors auf dem Chart zum Einsatz kommt. Wenn Sie sich die vorherigen Artikel ansehen, werden Sie feststellen, dass der Expert Advisor, sobald er auf dem Chart platziert wurde, in den offenen Positionen nach derjenigen sucht, die dem festgelegten, erwarteten Kriterium entspricht. Dadurch kann der Expert Advisor den Positionsindikator korrekt auf dem Chart platzieren.

Wie in früheren Artikeln gezeigt, führt das Entfernen des Expert Advisors vom Chart dazu, dass auch die auf dem Chart platzierten Positionsindikatoren entfernt werden. Gut. Das wird reibungslos funktionieren, wenn der Expert Advisor ordnungsgemäß entfernt wird. Sollte das Programm abstürzen, werden sie nicht entfernt. Wenn der Expert Advisor also erneut auf dem Chart ausgeführt wird, können Spuren seines vorherigen Laufs auf dem Chart verbleiben und müssen entfernt werden. Bei diesem Überbleibsel handelt es sich genau um den Positionsindikator, der auf dem Chart zurückgeblieben ist. Beachten Sie bitte Folgendes: Wir gehen davon aus, dass der Trader kein Chartelement verändert hat. Der Trader hat lediglich bemerkt, dass der Expert Advisor vom Chart entfernt worden war und eine Art Positionsindikator darauf zurückgeblieben ist.

Wenn der Trader den Expert Advisor also erneut auf dem Chart platziert, kann sich die Situation geändert haben. Oder genauer gesagt: Vor dem Absturz war der Expert Advisor so konfiguriert, dass er Mini-Kontrakte überwachte. Wenn der Trader ihn jedoch wieder auf dem Chart platziert, kann der Expert Advisor so konfiguriert sein, dass er Vollkontrakte überwacht. Einige Positionsindikatoren auf dem Chart zeigten jedoch das Vorhandensein einer Mini-Kontrakt-Position an. An dieser Stelle könnten wir auf Probleme stoßen. Um dies zu vermeiden, müssen wir eine Codezeile zur Initialisierungsprozedur des Expert Advisors hinzufügen. Diese Zeile entfernt zurückgebliebene Indikatoren aus dem Chart.

Es ist sehr einfach und leicht zu verstehen. Im folgenden Auszug können Sie sehen, wie dies umgesetzt wird.

15. //+------------------------------------------------------------------+
16. C_Orders       *Orders;
17. C_Terminal     *Terminal;
18. //+------------------------------------------------------------------+
19. int OnInit()
20. {
21.     Terminal = NULL;
22.     Orders = new C_Orders(0xC0DEDAFE78514269);
23.     
24.     return INIT_SUCCEEDED;
25. }
26. //+------------------------------------------------------------------+
27. void OnTick() {}
28. //+------------------------------------------------------------------+
29. void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
30. {
31.     int handle;
32.     
33.     (*Orders).DispatchMessage(id, lparam, dparam, sparam);
34.     switch (id)
35.     {
36.         case CHARTEVENT_CHART_CHANGE:
37.             if (Terminal != NULL) break;
38.             else
39.             {
40.                 ulong ul;
41.                 Terminal = new C_Terminal(0, 0, user00);
42.                 for (int count = PositionsTotal() - 1; count >= 0; count--)
43.                 {
44.                     ul = PositionGetTicket(count);
45.                     if (PositionGetString(POSITION_SYMBOL) != (*Terminal).GetInfoTerminal().szSymbol)
46.                     {
47.                         ChartIndicatorDelete(0, 0, IntegerToString(ul));
48.                         continue;
49.                     }
50.                     handle = iCustom(NULL, PERIOD_CURRENT, "\\Indicators\\Position View.ex5", ul);
51.                     ChartIndicatorAdd(0, 0, handle);
52.                     IndicatorRelease(handle);
53.                 }
54.             }
55.         case CHARTEVENT_CUSTOM + evChartTrade_At_EA:
56.             EventChartCustom(0, evEA_At_ChartTrade, user00, 0, "");
57.             break;
58.     }
59. }
60. //+------------------------------------------------------------------+

Codeausschnitt aus einem Expert Advisor

Bitte beachten Sie Zeile 47 des vorherigen Codeausschnitts. Genau das verhindert, dass das, was wir gerade beschrieben haben, eintritt. Mit anderen Worten: Wenn der Expert Advisor erneut in den Chart eingefügt wird, verwendet er Zeile 47, um alte Indikatoren zu entfernen, die die Initialisierungskriterien möglicherweise nicht erfüllen. Mit anderen Worten: Wenn ein Trader den Kontrakttyp ändert, erkennt der Expert Advisor dies und entfernt alle Positionsindikatoren, die nicht den erwarteten Ergebnissen entsprechen. Wenn der Indikator mit dem Kontrakttyp übereinstimmt, sind keine Maßnahmen erforderlich. Im schlimmsten Fall führt dies lediglich zu einem Fehler im Expert Advisor, was jedoch akzeptabel ist und ignoriert werden kann.

Gut. Nun weisen die Daten, die im Chart dargestellt werden können, eine gewisse Konsistenz auf, und wir können zum nächsten Schritt übergehen. Dabei werden Nachrichten zwischen dem Expert Advisor und dem Positionsindikator ausgetauscht.


Implementierung der Interaktion zwischen dem Expert Advisor und dem Positionsindikator

In dieser Phase werden wir mit dem ersten Informationsaustausch zwischen diesen beiden Anwendungen beginnen. Da jeder Nachrichtenaustausch viele Aspekte umfasst, die wir analysieren müssen, werden wir dies Schritt für Schritt tun. Fangen wir mit den Grundlagen an und gehen wir dann Schritt für Schritt ins Detail, bis wir einen voll funktionsfähigen Positionsindikator haben.

Da unser Positionsindikator derzeit nur horizontale Linien enthält – sogenannte HLINE-Objekte –, müssen wir nicht viele Nachrichten senden. Wir müssen jedoch noch einige weitere Änderungen am Code vornehmen. Beginnen wir mit der unten gezeigten Header-Datei „Defines.mqh“.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. #define def_VERSION_DEBUG
05. //+------------------------------------------------------------------+
06. #ifdef def_VERSION_DEBUG
07.     #define macro_DEBUG_MODE(A) \
08.                     Print(__FILE__, " ", __LINE__, " ", __FUNCTION__ + " " + #A + " = " + (string)(A));
09. #else
10.     #define macro_DEBUG_MODE(A)
11. #endif
12. //+------------------------------------------------------------------+
13. #define def_SymbolReplay          "RePlay"
14. #define def_MaxPosSlider          400
15. #define def_MaskTimeService       0xFED00000
16. #define def_IndicatorTimeFrame    (_Period < 60 ? _Period : (_Period < PERIOD_D1 ? _Period - 16325 : (_Period == PERIOD_D1 ? 84 : (_Period == PERIOD_W1 ? 91 : 96))))
17. #define def_IndexTimeFrame        4
18. //+------------------------------------------------------------------+
19. union uCast_Double
20. {
21.     double   dValue;
22.     long     _long;                                  // 1 Information
23.     datetime _datetime;                              // 1 Information
24.     uint     _32b[sizeof(double) / sizeof(uint)];    // 2 Informations
25.     ushort   _16b[sizeof(double) / sizeof(ushort)];  // 4 Informations
26.     uchar    _8b [sizeof(double) / sizeof(uchar)];   // 8 Informations
27. };
28. //+------------------------------------------------------------------+
29. enum EnumEvents     {
30.             evTicTac,                        //Event of tic-tac
31.             evHideMouse,                     //Hide mouse price line
32.             evShowMouse,                     //Show mouse price line
33.             evHideBarTime,                   //Hide bar time
34.             evShowBarTime,                   //Show bar time
35.             evHideDailyVar,                  //Hide daily variation
36.             evShowDailyVar,                  //Show daily variation
37.             evHidePriceVar,                  //Hide instantaneous variation
38.             evShowPriceVar,                  //Show instantaneous variation
39.             evCtrlReplayInit,                //Initialize replay control
40.             evChartTradeBuy,                 //Market buy event
41.             evChartTradeSell,                //Market sales event 
42.             evChartTradeCloseAll,            //Event to close positions
43.             evChartTrade_At_EA,              //Event to communication
44.             evEA_At_ChartTrade,              //Event to communication
45.             evChatWriteSocket,               //Event To Mini Chat
46.             evChatReadSocket,                //Event To Mini Chat
47.             evUpdate_Position                //Event to communication
48.                         };
49. //+------------------------------------------------------------------+
50. enum EnumPriority {                          //Priority list on objects
51.             ePriorityNull = -1,
52.             ePriorityDefault = 0,
53.             ePriorityChartTrade = 5,
54.             ePriorityOrders = 10
55.                         };
56. //+------------------------------------------------------------------+

Defines.mqh

In dieser Datei fügen wir eine neue Enumeration hinzu, die das Ereignis definiert, das einen Aufruf zur Aktualisierung des Positionsindikators auslöst. Dieses Ereignis wird in Zeile 47 definiert. Nachdem wir das nun erledigt haben, können wir uns dem Code des Expert Advisors zuwenden. Der vollständige Code für den Expert Advisor ist nachfolgend aufgeführt:

001. //+------------------------------------------------------------------+
002. #property copyright "Daniel Jose"
003. #property icon "/Images/Market Replay/Icons/Replay - EA.ico"
004. #property description "Demo version between interaction"
005. #property description "of Chart Trade and Expert Advisor"
006. #property version   "1.118"
007. #property link "https://www.mql5.com/pt/articles/13203"
008. //+------------------------------------------------------------------+
009. #include <Market Replay\Order System\C_Orders.mqh>
010. #include <Market Replay\Auxiliar\C_Terminal.mqh>
011. //+------------------------------------------------------------------+
012. enum eTypeContract {MINI, FULL};
013. //+------------------------------------------------------------------+
014. input eTypeContract user00 = MINI;                 //Cross order in contract
015. //+------------------------------------------------------------------+
016. C_Orders           *Orders;
017. C_Terminal         *Terminal;
018. //+------------------------------------------------------------------+
019. int OnInit()
020. {
021.    Terminal = NULL;
022.    Orders = new C_Orders(0xC0DEDAFE78514269);
023.    
024.    return INIT_SUCCEEDED;
025. }
026. //+------------------------------------------------------------------+
027. void OnTick() {}
028. //+------------------------------------------------------------------+
029. void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
030. {
031.    int handle;
032.    
033.    (*Orders).DispatchMessage(id, lparam, dparam, sparam);
034.    switch (id)
035.    {
036.            case CHARTEVENT_CHART_CHANGE:
037.                    if (Terminal != NULL) break;
038.                    else
039.                    {
040.                            ulong ul;
041.                            Terminal = new C_Terminal(0, 0, user00);
042.                            for (int count = PositionsTotal() - 1; count >= 0; count--)
043.                            {
044.                                    ul = PositionGetTicket(count);
045.                                    if (PositionGetString(POSITION_SYMBOL) != (*Terminal).GetInfoTerminal().szSymbol)
046.                                    {
047.                                            ChartIndicatorDelete(0, 0, IntegerToString(ul));
048.                                            continue;
049.                                    }
050.                                    handle = iCustom(NULL, PERIOD_CURRENT, "\\Indicators\\Position View.ex5", ul);
051.                                    ChartIndicatorAdd(0, 0, handle);
052.                                    IndicatorRelease(handle);
053.                            }
054.                    }
055.            case CHARTEVENT_CUSTOM + evChartTrade_At_EA:
056.                    EventChartCustom(0, evEA_At_ChartTrade, user00, 0, "");
057.                    break;
058.    }
059. }
060. //+------------------------------------------------------------------+
061. void OnTradeTransaction(const MqlTradeTransaction &trans, const MqlTradeRequest &request, const MqlTradeResult &result)
062. {
063.    if (Terminal == NULL) return;
064.    static ulong ticket = 0;
065.    switch (trans.type)
066.    {
067.            case TRADE_TRANSACTION_HISTORY_ADD:
068.                    ticket = (trans.order != trans.position ? trans.position : 0);
069.                    break;
070.            case TRADE_TRANSACTION_REQUEST:
071.                    if ((request.symbol == (*Terminal).GetInfoTerminal().szSymbol) && (result.retcode == TRADE_RETCODE_DONE)) switch (request.action)
072.                    {
073.                            case TRADE_ACTION_DEAL:
074.                                    if (ticket) EventChartCustom(0, evUpdate_Position, ticket, 0, "");
075.                                    else
076.                                    {
077.                                            int handle = iCustom(NULL, PERIOD_CURRENT, "\\Indicators\\Position View.ex5", result.order);
078.                                            ChartIndicatorAdd(0, 0, handle);
079.                                            IndicatorRelease(handle);
080.                                    }
081.                                    ticket = 0;
082.                                    break;
083.                            case TRADE_ACTION_SLTP:
084.                                    EventChartCustom(0, evUpdate_Position, request.position, 0, "");
085.                                    break;
086.                    }
087.                    break;
088.    };
089. }
090. //+------------------------------------------------------------------+
091. void OnDeinit(const int reason)
092. {
093.    ulong ul;
094.    
095.    switch (reason)
096.    {
097.            case REASON_REMOVE:
098.            case REASON_INITFAILED:
099.                    EventChartCustom(0, evEA_At_ChartTrade, -1, 0, "");
100.                    break;
101.    }
102.    if (Terminal != NULL) for (int count = PositionsTotal() - 1; count >= 0; count--)
103.    {
104.            ul = PositionGetTicket(count);
105.            if (PositionGetString(POSITION_SYMBOL) != (*Terminal).GetInfoTerminal().szSymbol) continue;
106.            ChartIndicatorDelete(0, 0, IntegerToString(ul));
107.    }
108.    delete Orders;
109.    delete Terminal;
110. }
111. //+------------------------------------------------------------------+

Expert Advisor.mq5

Der größte Teil dieses Codes wurde bereits oben erläutert. Deshalb sollten wir uns auf das konzentrieren, was hier neu ist – nämlich auf die Funktion OnTradeTransaction. Vorerst brauchen Sie sich über bestimmte Punkte, die Sie vielleicht noch nicht verstehen, keine Gedanken zu machen. Wir werden alles Schritt für Schritt erklären. An dieser Stelle möchte ich jedoch insbesondere die Funktion EventChartCustom hervorheben. Diese Funktion kommt in den Zeilen 74 und 84 vor. Über diese Zeilen kann der Expert Advisor dem Positionsindikator mitteilen, dass ein Ereignis eingetreten ist und dass der Positionsindikator aktualisiert werden muss.

Vorerst brauchen Sie sich keine Gedanken darüber zu machen, wie dies im Indikator umgesetzt wird. Beobachten Sie einfach, wann der Expert Advisor dem Indikator mitteilt, dass eine Aktualisierung erforderlich ist. Um das Thema besser zu verstehen, sollten Sie den Stoff aus dem vorherigen Artikel verinnerlicht haben. Sollten Sie Fragen zu den hier bereitgestellten Informationen haben, lesen Sie bitte den vorherigen Artikel.

Hier werden wir drei verschiedene Situationen betrachten. Der erste Fall tritt ein, wenn wir mithilfe des Chart Trade-Indikators den Expert Advisor anweisen, eine Kauf- oder Verkaufsorder zum Marktpreis auszuführen. Danach hat die statische Variable „ticket“ den Wert Null. Der Grund dafür ist, dass „trans.order“ und „trans.position“ in Zeile 68 denselben Wert haben. Gut. Wenn der Handelsserver also eine TRADE_TRANSACTION_REQUEST-Benachrichtigung sendet, wird die entsprechende Verarbeitung für diesen Vorgang durchgeführt. Hinweis: Zu diesem Zeitpunkt wird die Position gerade erst eröffnet. Wenn der Server also TRADE_ACTION_DEAL generiert, schlägt die Prüfung in Zeile 74 fehl. Und das liegt daran, dass die Variable ticket den Wert null hat. In diesem Fall wird der Code zwischen den Zeilen 76 und 80 ausgeführt. Bitte beachten Sie, dass es sich hierbei um denselben Code handelt, der bei der Initialisierung des Expert Advisors verwendet wurde, um MetaTrader 5 mitzuteilen, dass wir dem Chart einen Positionsindikator hinzufügen möchten.

Da wir nicht wissen, wodurch TRADE_ACTION_DEAL ausgelöst wurde, setzen wir die Variable ticket auf null zurück. Das war's. Auf dem Chart erscheint ein Positionsindikator, der dieselben Informationen anzeigt, die wir sehen würden, wenn MetaTrader 5 diesen Modus unterstützen würde. Ich möchte Sie noch einmal daran erinnern: Das Cross-Order-System wird in MetaTrader 5 nicht vollständig unterstützt. Aus diesem Grund müssen wir bei der Verwendung dieses Handelsmodus eine Möglichkeit schaffen, die Daten auf dem Chart anzuzeigen. Dafür ist der Positionsindikator da.

Nun wurde die Position eröffnet und wird auf dem Chart angezeigt. Nach einer Weile beschließt der Trader, das Positionsvolumen zu erhöhen. Dann wird er den Indikator Chart Trade erneut verwenden und ihn anweisen, das Positionsvolumen zu erhöhen. Dabei ist ein wichtiger Punkt zu beachten. Auf HEDGING-Konten führt diese erneute Eröffnung bzw. Anfrage zur Erhöhung des Positionsvolumens nicht zu einer tatsächlichen Änderung des Volumens. Tatsächlich wird Folgendes passieren: Es wird eine neue Position eröffnet. Da wir nicht zwischen HEDGING- und NETTING-Konten unterscheiden, verläuft der Vorgang bei einer Anfrage zur Erhöhung des Positionsvolumens auf einem HEDGING-Konto genau so, wie ich es gerade für die Eröffnung einer Position erläutert habe. Bei der Ausführung derselben Art von Anfrage – also bei der Erhöhung des Positionsvolumens auf einem NETTING-Konto – sieht die Situation jedoch etwas anders aus. In diesem Fall unterscheiden sich die Werte von trans.order und trans.position, wenn der Server das Ereignis TRADE_TRANSACTION_HISTORY_ADD generiert. Wenn dies geschieht, bedeutet dies, dass sich bei der offenen Position eine Änderung ergeben hat. Somit ist der Wert der Variablen „ticket“ nicht mehr Null. In diesem Fall wird das Ticket auf das Ticket der entsprechenden Position gesetzt. Zu einem bestimmten Zeitpunkt generiert der Handelsserver als Reaktion auf die empfangene Anfrage ein TRADE_TRANSACTION_REQUEST-Ereignis.

Wenn dies geschieht und die Aktion TRADE_ACTION_DEAL verarbeitet wird, wird die Prüfung in Zeile 74 erfolgreich durchlaufen. Zu diesem Zeitpunkt wird ein benutzerdefiniertes Ereignis ausgelöst, das dem Positionsindikator mitteilt, dass er aktualisiert werden muss. Bitte beachten Sie, dass wir dieses Ereignis nicht an einen bestimmten Indikator oder eine bestimmte Anwendung geknüpft haben. Alle auf dem Chart vorhandenen Anwendungen erhalten dasselbe benutzerdefinierte Ereignis. Da wir dieses Ereignis jedoch innerhalb jeder Anwendung filtern, wird die Nachricht nur vom richtigen Indikator oder der richtigen Anwendung verstanden. Damit ist die Arbeit des Expert Advisors abgeschlossen. Tatsächlich weiß er gar nicht, ob der Positionsindikator diese Nachricht verstehen wird oder nicht. Er weiß nicht einmal, ob sich dieser Indikator auf dem Chart befindet. Das ist für den Expert Advisor von untergeordneter Bedeutung; er hat seine Aufgabe erfüllt, und das ist alles. Das Gleiche geschieht, wenn die Werte für Take Profit und Stop Loss einer Position geändert werden. In diesem Fall sehen wir, wie die Aktion TRADE_ACTION_SLTP ausgeführt wird, die in Zeile 83 steht. Beachten Sie, dass wir in Zeile 84 genauso vorgehen wie beim Erhöhen des Positionsvolumens oder bei einer teilweisen Verringerung des Positionsvolumens. Dies gilt, wenn Sie ein NETTING-Konto nutzen. „Okay.

Aber was passiert, wenn eine Position geschlossen wird?“ Ich nehme an, lieber Leser, Sie würden hier im Code des Expert Advisors Code erwarten, der dafür zuständig ist, den Positionsindikator aus dem Chart zu entfernen. Das ist jedoch nicht ganz das, was man im Code des Expert Advisors sehen kann. Wie schafft es das Programm also, diesen Indikator aus dem Chart zu entfernen? Das ist ganz einfach. Das funktioniert genauso wie beim Ändern des Volumens in NETTING-Konten. Mit anderen Worten: In Zeile 68 unterscheiden sich die Werte von `trans.order` und `trans.position`. Dadurch kann die Prüfung in Zeile 74 erfolgreich durchlaufen werden, und es wird eine Anfrage zur Aktualisierung des Indikators gesendet. Da die Position jedoch geschlossen wurde, wird der Indikator aus dem Chart entfernt. Um dies vollständig zu verstehen, müssen wir uns den Code des Positionsindikators ansehen. Um die Themen voneinander zu trennen, werden wir sie in einem neuen Abschnitt behandeln.


Verbesserter Positionsindikator

Nun sollten Sie wissen, dass der Code des Positionsindikators derzeit aus zwei Teilen besteht. Das erste Beispiel können Sie unten in voller Länge sehen.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. #property icon "/Images/Market Replay/Icons/Positions.ico"
04. #property description "Indicator for tracking an open position on the server."
05. #property description "This should preferably be used together with an Expert Advisor."
06. #property description "For more details see the same article."
07. #property version   "1.118"
08. #property link "https://www.mql5.com/pt/articles/13203"
09. #property indicator_chart_window
10. #property indicator_plots 0
11. //+------------------------------------------------------------------+
12. #define def_ShortName "Position View"
13. //+------------------------------------------------------------------+
14. #include <Market Replay\Order System\C_IndicatorPosition.mqh>
15. #include <Market Replay\Defines.mqh>
16. //+------------------------------------------------------------------+
17. input ulong user00 = 0;                 //For Expert Advisor use
18. input color user01 = clrRoyalBlue;      //Color Line Price
19. input color user02 = clrForestGreen;    //Color Line Take Profit
20. input color user03 = clrFireBrick;      //Color Line Stop Loss
21. //+------------------------------------------------------------------+
22. C_IndicatorPosition *Positions = NULL;
23. //+------------------------------------------------------------------+
24. int OnInit()
25. {
26.     IndicatorSetString(INDICATOR_SHORTNAME, def_ShortName);
27.     Positions = new C_IndicatorPosition(user01, user02, user03);
28.     if (!Positions.CheckCatch(user00))
29.     {
30.         ChartIndicatorDelete(0, 0, def_ShortName);
31.         return INIT_FAILED;
32.     }
33. 
34.     return INIT_SUCCEEDED;
35. }
36. //+------------------------------------------------------------------+
37. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
38. {
39.     return rates_total;
40. }
41. //+------------------------------------------------------------------+
42. void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
43. {
44.     (*Positions).DispatchMessage(id, lparam, dparam, sparam);
45. };
46. //+------------------------------------------------------------------+
47. void OnDeinit(const int reason)
48. {
49.     delete Positions;
50. }
51. //+------------------------------------------------------------------+

Position View.mq5

Dies ist der Hauptcode des Indikators. Beachten Sie, dass der einzige Unterschied hier im Wesentlichen in der Funktion OnChartEvent liegt. Da wir einige interne Informationen aus der Klasse C_IndicatorPosition benötigen, werden wir in diesem Hauptcode nichts tun. Wir rufen einfach die Prozedur DispatchMessage auf. Daher können wir allein anhand dieses Codes nicht nachvollziehen, wie die Interaktion mit dem Expert Advisor funktioniert. Werfen wir nun einen Blick auf die Header-Datei C_IndicatorPosition.mqh, die 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.             string    szShortName;
17.         }m_Infos;
18. //+------------------------------------------------------------------+
19.         inline void MoveLineInfos(string szObjName, const double price)
20.         {
21.             szObjName = m_Infos.szShortName + szObjName;
22.             if (price <= 0) ObjectDelete(0, szObjName);
23.             else ObjectSetDouble(0, szObjName, OBJPROP_PRICE, price);
24.         }
25. //+------------------------------------------------------------------+
26.         void CreateLineInfos(string szObjName, const color cor, const string szDescription = "\n")
27.         {            
28.             szObjName = m_Infos.szShortName + szObjName;
29.             CreateObjectGraphics(szObjName, OBJ_HLINE, cor, (EnumPriority)(cor == m_Infos.corPrice ? ePriorityNull : (ePriorityOrders + (cor == m_Infos.corStop))));
30.             ObjectSetString(0, szObjName, OBJPROP_TEXT, szDescription);
31.             ObjectSetString(0, szObjName, OBJPROP_TOOLTIP, szDescription);
32.             ObjectSetInteger(0, szObjName, OBJPROP_SELECTABLE, cor != m_Infos.corPrice);
33.         }
34. //+------------------------------------------------------------------+
35.     public    :
36. //+------------------------------------------------------------------+
37.         C_IndicatorPosition(color corPrice, color corTake, color corStop)
38.             :C_Terminal()
39.         {
40.             ZeroMemory(m_Infos);
41.             m_Infos.corPrice = corPrice;
42.             m_Infos.corTake  = corTake;
43.             m_Infos.corStop  = corStop;
44.         }
45. //+------------------------------------------------------------------+
46.         ~C_IndicatorPosition()
47.         {
48.             if (m_Infos.ticket != 0)
49.                 ObjectsDeleteAll(0, IntegerToString(m_Infos.ticket));
50.         }
51. //+------------------------------------------------------------------+
52.         bool CheckCatch(ulong ticket)
53.         {
54.             m_Infos.szShortName = IntegerToString(m_Infos.ticket = ticket);            
55.             if (!PositionSelectByTicket(m_Infos.ticket)) return false;
56.             if (ObjectFind(0, m_Infos.szShortName) >= 0)
57.             {
58.                 m_Infos.ticket = 0;
59.                 return false;
60.             }
61.             IndicatorSetString(INDICATOR_SHORTNAME, m_Infos.szShortName);
62.             CreateLineInfos(NULL, m_Infos.corPrice, "Position opening price.");
63.             CreateLineInfos(def_SufixTake, m_Infos.corTake, "Take Profit point.");
64.             CreateLineInfos(def_SufixStop, m_Infos.corStop, "Stop Loss point.");
65.             EventChartCustom(0, evUpdate_Position, ticket, 0, "");
66.             
67.             return true;
68.         }
69. //+------------------------------------------------------------------+
70.         void DispatchMessage(const int id, const long &lparam, const double &dparam, const string &sparam)
71.         {
72.             switch (id)
73.             {
74.                 case CHARTEVENT_CUSTOM + evUpdate_Position:
75.                     if (lparam != m_Infos.ticket) return;
76.                     if (!PositionSelectByTicket(m_Infos.ticket))
77.                     {
78.                         ChartIndicatorDelete(0, 0,  m_Infos.szShortName);
79.                         return;
80.                     };
81.                     MoveLineInfos(NULL, PositionGetDouble(POSITION_PRICE_OPEN));
82.                     MoveLineInfos(def_SufixTake, PositionGetDouble(POSITION_TP));
83.                     MoveLineInfos(def_SufixStop, PositionGetDouble(POSITION_SL));
84.                 break;
85.             }
86.         }
87. //+------------------------------------------------------------------+
88. };
89. //+------------------------------------------------------------------+
90. #undef def_SufixTake
91. #undef def_SufixStop
92. //+------------------------------------------------------------------+

C_IndicatorPosition.mqh

Auch wenn man vielleicht meinen könnte, dass alles auf eine bestimmte Art und Weise gemacht werden sollte, werden wir es hier etwas anders umsetzen, als es viele gewohnt sind. Tatsächlich haben wir an dieser Stelle noch nicht viele Änderungen am Code vorgenommen, aber Sie können sehen, dass hier verschiedene Elemente vorhanden sind. Zunächst einmal haben wir in Zeile 19 eine neue Prozedur. Sie dient dazu, den Punkt zu ändern, an dem sich die horizontale Preislinie befindet. Zu dieser Prozedur gibt es nicht viel zu sagen, da das Linienobjekt gelöscht wird, wenn der Preis null oder negativ ist. Dies geschieht in Zeile 22 des oben gezeigten Codes.

Man sollte jedoch bedenken, dass negative Preise zwar in der Regel nicht möglich sind, dies jedoch nicht für Indizes gilt – oder, genauer gesagt: Wenn man eine Kombination aus zwei oder mehr Assets verwendet, um einen neuen Wert zu erzeugen, können durchaus negative Werte auftreten. Dieser Wert bezieht sich jedoch nicht auf einen negativen Preis, sondern auf einen negativen Index oder Koeffizienten. Sollten Sie Probleme bei der Verwendung von Charts haben, die auf Wertverhältnissen beruhen, müssen Sie diesen Positionsindikator anpassen. Derzeit konzentrieren wir uns eher auf Preise als auf Verhältnisse. Später werde ich Ihnen zeigen, wie man in MetaTrader 5 mit Verhältnissen arbeitet.

Aber gehen wir Schritt für Schritt vor. Zunächst werden wir besprechen, wie man den Positionsindikator zum Laufen bringt. „Okay. Wenn der Preis gültig ist, teilen wir dem HLINE-Objekt in Zeile 23 mit, wo es platziert werden soll. Das ist ganz einfach. Nun wollen wir uns einem interessanten Punkt bezüglich der Funktion in Zeile 52 zuwenden. Beachten Sie, dass das benutzerdefinierte Ereignis in Zeile 65 ausgelöst wird. Aber warum wird das so gemacht? Der Grund ist einfach: einmal schreiben, immer wieder testen. Da dieser Indikator benutzerdefinierte Nachrichten oder Ereignisse empfängt, können wir ihn so konfigurieren, dass er sich, wenn er in einem Chart platziert wird, genauso verhält wie beim Empfang einer Aktualisierungsanfrage von einem Expert Advisor.

Wie ich im vorherigen Abschnitt bereits erwähnt habe, überprüft der Expert Advisor nicht, ob der Positionsindikator seine Funktion erfüllt hat oder nicht. Es erzeugt einfach ein Ereignis und fährt dann mit anderen Aufgaben fort. Der Positionsindikator ist für die Ausführung aller übrigen Aufgaben zuständig. Daher ist es ratsam, eine klare Implementierungsmethodik zu haben. Wenn der Positionsindikator ordnungsgemäß funktioniert, wenn er manuell zum Chart hinzugefügt wird, die Anfragen des Expert Advisors jedoch nicht interpretieren kann, lässt sich schnell schließen, dass ein Kommunikationsfehler zwischen dem Expert Advisor und dem Indikator vorliegt. Wir können diese Schlussfolgerung ziehen, da Ereignisse korrekt verarbeitet werden, wenn der Indikator manuell zum Chart hinzugefügt wird.

So wie ein Expert Advisor ein Ereignis auslöst, damit der Positionsindikator seine Aufgabe ausführen kann, löst auch der Positionsindikator selbst ein ähnliches Ereignis aus, um zu prüfen, ob er auf dem Chart platziert werden kann. Das bedeutet, dass die Funktion in beiden Fällen aus Zeile 70 des oben gezeigten Codes aufgerufen wird.

Der Code in Zeile 70 ist ziemlich interessant. Vorerst interessiert uns nur die Behandlung eines einzigen Ereignisses: des Ereignisses evUpdate_Position, dessen Behandlung in Zeile 74 beginnt. In Zeile 75 prüfen wir, ob das im Ereignisaufruf angegebene Positions-Ticket mit dem vom Indikator erwarteten Ticket übereinstimmt. Wenn sich die Tickets unterscheiden, wird die Bearbeitung an dieser Stelle abgebrochen. Es ist wichtig zu überprüfen, ob die Ticketnummer übereinstimmt, da die Ereignisbenachrichtigung an alle Anwendungen auf dem Chart gesendet wird. Deshalb ist es wichtig, die Ereignisse vor der Verwendung der Daten sorgfältig zu filtern. Sobald die Filterung abgeschlossen ist, können wir in Zeile 76 prüfen, ob diese Position existiert. Denken Sie daran: Der Expert Advisor teilt uns nicht mit, ob wir eine Position aktualisieren, schließen oder eine neue Position eröffnen. Er sagt lediglich: Positionsindikator, ich habe etwas für dich. Erledige alles, was erledigt werden muss. Und das war's.

Der Indikator übernimmt den Rest; er muss alle erforderlichen Aktionen ausführen und überprüfen. Wenn keine Position vorhanden ist, stoppen wir den Indikator in Zeile 78, und er wird aus dem Chart entfernt. Wird jedoch eine Position angelegt oder aktualisiert, verschieben sich die Preislinien. Dies geschieht in den Zeilen 81 bis 83. So funktioniert dieser Mechanismus. Allerdings gibt es ein Problem mit dem oben gezeigten Code. Es ist wichtig, dies zu verstehen, bevor wir den Code durcharbeiten, den wir im nächsten Abschnitt behandeln werden.


Muss das wirklich so sein?

Im Code der oben gezeigten Klasse C_IndicatorPosition wurde ein Problem festgestellt. Genau genommen handelt es sich eher um eine Einschränkung als um einen Fehler. Der Haken dabei ist jedoch: Wenn Sie die Linien für Stop Loss und Take Profit entfernen oder gar nicht erst hinzufügen und sich später entscheiden, sie doch dem Chart hinzuzufügen, wird die Position aktualisiert, und Sie können die Linien nachträglich nicht direkt hinzufügen. Die zuvor erwähnte Klasse ist dazu nicht in der Lage. Durch ein paar Änderungen am Code können wir dies jedoch ermöglichen. Diese Änderungen sind im folgenden Code dargestellt:

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.             string    szShortName;
17.         }m_Infos;
18. //+------------------------------------------------------------------+
19.         inline void MoveLineInfos(const string szDefine, const double price)
20.         {
21.             string szName = m_Infos.szShortName + szDefine;
22.             if (price <= 0) ObjectDelete(0, szName);
23.             else
24.             {
25.                 if (ObjectFind(0, szName) < 0)
26.                 {
27.                     if (szDefine == def_SufixTake) CreateLineInfos(def_SufixTake, m_Infos.corTake, "Take Profit point."); else
28.                     if (szDefine == def_SufixStop) CreateLineInfos(def_SufixStop, m_Infos.corStop, "Stop Loss point."); else
29.                     CreateLineInfos(NULL, m_Infos.corPrice, "Position opening price.");
30.                 }                    
31.                 ObjectSetDouble(0, szName, OBJPROP_PRICE, price);
32.             }
33.         }
34. //+------------------------------------------------------------------+
35.         void CreateLineInfos(string szObjName, const color cor, const string szDescription = "\n")
36.         {            
37.             szObjName = m_Infos.szShortName + szObjName;
38.             CreateObjectGraphics(szObjName, OBJ_HLINE, cor, (EnumPriority)(cor == m_Infos.corPrice ? ePriorityNull : (ePriorityOrders + (cor == m_Infos.corStop))));
39.             ObjectSetString(0, szObjName, OBJPROP_TEXT, szDescription);
40.             ObjectSetString(0, szObjName, OBJPROP_TOOLTIP, szDescription);
41.             ObjectSetInteger(0, szObjName, OBJPROP_SELECTABLE, cor != m_Infos.corPrice);
42.         }
43. //+------------------------------------------------------------------+
44.     public    :
45. //+------------------------------------------------------------------+
46.         C_IndicatorPosition(color corPrice, color corTake, color corStop)
47.             :C_Terminal()
48.         {
49.             ZeroMemory(m_Infos);
50.             m_Infos.corPrice = corPrice;
51.             m_Infos.corTake  = corTake;
52.             m_Infos.corStop  = corStop;
53.         }
54. //+------------------------------------------------------------------+
55.         ~C_IndicatorPosition()
56.         {
57.             if (m_Infos.ticket != 0)
58.                 ObjectsDeleteAll(0, IntegerToString(m_Infos.ticket));
59.         }
60. //+------------------------------------------------------------------+
61.         bool CheckCatch(ulong ticket)
62.         {
63.             m_Infos.szShortName = IntegerToString(m_Infos.ticket = ticket);            
64.             if (!PositionSelectByTicket(m_Infos.ticket)) return false;
65.             if (ObjectFind(0, m_Infos.szShortName) >= 0)
66.             {
67.                 m_Infos.ticket = 0;
68.                 return false;
69.             }
70.             IndicatorSetString(INDICATOR_SHORTNAME, m_Infos.szShortName);
71.             EventChartCustom(0, evUpdate_Position, ticket, 0, "");
72.             
73.             return true;
74.         }
75. //+------------------------------------------------------------------+
76.         void DispatchMessage(const int id, const long &lparam, const double &dparam, const string &sparam)
77.         {
78.             switch (id)
79.             {
80.                 case CHARTEVENT_CUSTOM + evUpdate_Position:
81.                     if (lparam != m_Infos.ticket) return;
82.                     if (!PositionSelectByTicket(m_Infos.ticket))
83.                     {
84.                         ChartIndicatorDelete(0, 0,  m_Infos.szShortName);
85.                         return;
86.                     };
87.                     MoveLineInfos(NULL, PositionGetDouble(POSITION_PRICE_OPEN));
88.                     MoveLineInfos(def_SufixTake, PositionGetDouble(POSITION_TP));
89.                     MoveLineInfos(def_SufixStop, PositionGetDouble(POSITION_SL));
90.                 break;
91.             }
92.             ChartRedraw();
93.         }
94. //+------------------------------------------------------------------+
95. };
96. //+------------------------------------------------------------------+
97. #undef def_SufixTake
98. #undef def_SufixStop
99. //+------------------------------------------------------------------+

C_IndicatorPosition.mqh

Der oben gezeigte Code sollte den im vorherigen Abschnitt besprochenen ursprünglichen Code ersetzen. Wie Sie sehen können, wurden nur wenige Änderungen vorgenommen. Sie reichen jedoch aus, damit der Positionsindikator mit der zu Beginn dieses Abschnitts beschriebenen Situation umgehen kann. Schauen wir uns an, was sich im Vergleich zu vorher geändert hat.

Tatsächlich erstellen wir in der in Zeile 61 gezeigten Funktion keine HLINE-Objekte mehr. Die Codezeilen, die zu diesem Ergebnis geführt haben, wurden entfernt. Tatsächlich wurden sie nicht gelöscht, sondern verschoben. Beachten Sie, dass der gesamte Code unverändert bleibt. Wenn wir jedoch zu Zeile 19 gehen, werden wir etwas sehr Seltsames feststellen, das zuvor nicht passiert war.

Früher wies der Code, wenn wir das Verschieben einer Preislinie anforderten, einfach das Objekt an, sich zu verschieben. Aber jetzt kommt ein zusätzlicher Schritt hinzu. Das steht in Zeile 25. Dieser Schritt ermöglicht es uns, die Linie bei Bedarf neu zu erstellen. Mit anderen Worten: Wenn ein Trader eine Linie löscht, weist der Expert Advisor den Positionsindikator an, die Daten zu aktualisieren. Der Indikator löscht dieselbe Linie, die der Trader gelöscht hat. Wenn der Trader die Linie jedoch erneut festlegt und damit den Preis angibt, der nun als Stop Loss oder Take Profit verwendet werden soll, weist der Expert Advisor den Positionsindikator an, die Daten erneut zu aktualisieren. In dieser Phase, wenn Zeile 25 ausgeführt wird, erkennt der Positionsindikator, dass das HLINE-Objekt nicht existiert, und erstellt es passend zum neuen Positionszustand. Erst dann platziert der Positionsindikator die Linie an der richtigen Stelle. Dies geschieht mithilfe von Zeile 31.

Was ich gerade erklärt habe, können Sie im folgenden Video sehen; es macht deutlich, wie dieser Positionsindikator derzeit funktioniert.


Abschließende Gedanken

In diesem Artikel haben wir eine Reihe von Verbesserungen vorgenommen, damit der Positionsindikator sowohl hinsichtlich der Positionen als auch ihres aktuellen Zustands die tatsächliche Situation auf dem Handelsserver widerspiegelt. Bitte beachten Sie, dass die hier vorgestellten Anwendungen keineswegs dazu gedacht sind, irgendwelche in MetaTrader 5 verfügbaren Elemente zu ersetzen. Sie sollten zudem nicht ohne die gebotene Vorsicht und ohne Einhaltung der erforderlichen Kriterien verwendet werden, da ihr Zweck darin besteht, Lehrcode bereitzustellen – also Code zu Unterrichtszwecken, der vermitteln soll, wie alles funktioniert.

Ich bezeichne diesen Code deshalb als Lehrcode, weil die Verwendung von Nachrichten in manchen Fällen nicht die beste Methode ist, um bestimmte Funktionen zu implementieren. Bitte beachten Sie, dass der auf dem Chart platzierte Positionsindikator eine Nachricht erzeugt, auf die er selbst reagiert. Diese Funktion verringert die Reaktionsfähigkeit des Codes etwas, da wir einen Aufruf hinzufügen, wo er nicht benötigt wird.

Auf jeden Fall habe ich nicht vor, die Art und Weise zu ändern, wie der Code präsentiert wird. Wenn Sie diesen Code ausprobieren möchten, aber nicht sicher sind, wie Sie alle Dateien erstellen sollen (obwohl der vollständige Code hier bereitgestellt wird), finden Sie die vorkompilierten Anwendungen in den angehängten Dateien. Auf diese Weise müssen Sie sie lediglich in MetaTrader 5 verwenden und können sich selbst ein Bild davon machen, wie der Nachrichtenaustausch funktioniert. Diese Anwendungen wurden auf HEDGING- und NETTING-Konten getestet und funktionieren einwandfrei. Sie müssen nichts ändern; entpacken Sie einfach die angehängte Datei in den MQL5-Ordner. Sie erhalten dasselbe Ergebnis wie im Video gezeigt.

Datei Beschreibung
Experts\Expert Advisor.mq5
Zeigt die Interaktion zwischen Chart Trade und dem Expert Advisor auf dem Chart. (Für diese Interaktion ist Mouse Study erforderlich.)
Indicators\Chart Trade.mq5 Erstellt ein Fenster zur Konfiguration der Einstellungen für das Absenden von Orders. (Für die Interaktion ist Mouse Study erforderlich.)
Indicators\Market Replay.mq5 Erstellt Steuerelemente für die Interaktion mit dem Replay-/Simulationsdienst. (Für die Interaktion ist Mouse Study erforderlich.)
Indicators\Mouse Study.mq5 Ermöglicht die Interaktion zwischen den grafischen Steuerelementen und dem Benutzer. (Dies ist sowohl für das Replay-/Simulationssystem als auch im realen Handel erforderlich.)
Indicators\Order Indicator.mq5 Ist für die Anzeige von Market-Orders zuständig und ermöglicht die Interaktion mit ihnen sowie ihre Steuerung.
Indicators\Position View.mq5 Ist für die Anzeige von offene Positionen zuständig und ermöglicht die Interaktion mit ihnen sowie ihre Steuerung.
Services\Market Replay.mq5 Erstellt und verwaltet den Markt-Replay-/Simulationsdienst. (Hauptdatei des Systems.)

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

Beigefügte Dateien |
Anexo.zip (779.24 KB)
Duellanten-Algorithmus Duellanten-Algorithmus
Was wäre, wenn Ihre Handelsstrategien voneinander lernen könnten, so wie echte Kämpfer? Der Duellanten-Algorithmus ist eine neue Optimierungsmethode, bei der die Parameter von Handelssystemen buchstäblich gegeneinander antreten, um als die besten ausgezeichnet zu werden.
Neuronale Netze im Trading: Zerlegen statt Skalieren (Fazit) Neuronale Netze im Trading: Zerlegen statt Skalieren (Fazit)
Wir laden Sie ein, einen Algorithmus kennenzulernen, mit dem eine Zeitreihe in aussagekräftige Schichten zerlegt und daraus ein sparsames Modell aufgebaut wird. Wir stellen systematisch die Architektur, die praktische Umsetzung in MQL5/OpenCL sowie Praxistests unter Verwendung historischer Marktdaten vor.
Neuronale Netze im Trading: Das Temporal-Query-Modell (TQNet) Neuronale Netze im Trading: Das Temporal-Query-Modell (TQNet)
Das TQNet-Framework eröffnet durch die Kombination von Modularität, Flexibilität und hoher Leistungsfähigkeit neue Möglichkeiten für die Modellierung und Prognose von Finanzzeitreihen. Der Artikel untersucht die Möglichkeit, komplexe Mechanismen zur Verarbeitung globaler Korrelationen zu implementieren, darunter auch fortgeschrittene Methoden zur Parameterinitialisierung.
Neuronale Netze im Trading: Zerlegung strukturierter Komponenten (Fazit) Neuronale Netze im Trading: Zerlegung strukturierter Komponenten (Fazit)
Der Artikel enthält eine ausführliche Erläuterung der SCNN-Architektur und zeigt eine Möglichkeit auf, diese mit MQL5 zu implementieren. Wir werden zeigen, wie sich die Zerlegung von Zeitreihen mit Methoden neuronaler Netze und Attention-Mechanismen kombinieren lässt.