English Русский Español Português
preview
Entwicklung eines Replay Systems (Teil 43): Chart Trader Projekt (II)

Entwicklung eines Replay Systems (Teil 43): Chart Trader Projekt (II)

MetaTrader 5Beispiele | 8 August 2024, 09:56
13 0
Daniel Jose
Daniel Jose

Einführung

Im vorherigen Artikel Entwicklung eines Replay Systems (Teil 42): Chart Trader Project (I), habe ich gezeigt, wie Sie die Interaktion zwischen dem Mausindikator und anderen Indikatoren gestalten können.

Wir haben begonnen, Code zu schreiben, um sicherzustellen, dass der Chart Trade-Indikator in perfekter Harmonie mit dem Maus-Indikator existiert. Im Gegensatz zu den ersten Versionen des Chart Trade Indikators, die in den Artikeln beschrieben wurden, ist dies jedoch nicht der Fall:

Hier werden wir etwas Fortgeschritteneres und daher etwas anderes machen. Das Ergebnis ist aber in jedem Fall dasselbe wie in Video 01. Ich schlage vor, dass Sie sich dieses Video ansehen, bevor Sie mit dem Lesen des Artikels beginnen, damit Sie eine Vorstellung davon bekommen, was wir genau tun werden. Das kann man nicht einfach durch Lesen des Codes verstehen. Man sagt, ein Bild sagt mehr als tausend Worte, also sehen Sie sich das Video an, um besser zu verstehen, was in diesem Artikel erklärt wird.


Video 01 - Demo-Video

Das Video zeigt, dass die Daten im Fenster Chart Trade angezeigt werden. Sie haben vielleicht bemerkt, dass wir alles genau so machen wie im vorherigen Artikel, aber die Informationen werden aktualisiert, ohne dass die Objekte tatsächlich verwendet werden. Und Sie fragen sich wahrscheinlich: Wie ist das möglich?

„Dieser Typ muss irgendeinen Trick anwenden. Ich habe noch nie jemanden gesehen, der so etwas tut. Das ergibt doch keinen Sinn...“ Andere denken wahrscheinlich, dass ich eine Art Zauberer oder Magier bin, mit Kräften jenseits der Vorstellungskraft. Nein, nichts dergleichen. Ich nutze einfach sowohl die MetaTrader 5-Plattform als auch die MQL5-Sprache auf einem Niveau, das viele Leute nicht verstehen wollen. Sie sagen und tun immer das Gleiche, ohne das wirkliche Potenzial und die Möglichkeiten der MQL5-Sprache oder der MetaTrader 5-Plattform zu erkunden.

Ich hoffe, alle haben das Video gesehen. Denn in diesem Artikel zeige ich Ihnen, wie Sie etwas tun können, das Ihr Denken darüber, was möglich und was unmöglich ist, grundlegend verändern wird. Das ist wichtig: Ich werde nur erklären, was in dem Video gezeigt wird. Die Dinge, die im Video nicht gezeigt werden, werden später besprochen.


Aktualisierung des Indikator-Codes

Die Änderungen, die vorgenommen werden müssen, werden nicht so groß sein. Aber wir werden trotzdem schrittweise vorankommen, weil sonst alle nicht mehr wissen, was eigentlich passiert.

Betrachten wir zunächst die Änderungen, die am Code des Indikators vorgenommen wurden. Die Änderungen sind im folgenden Code dargestellt.

Chart Trade Indikator Quellcode:

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. #property description "Base version for Chart Trade (DEMO version)"
04. #property version   "1.43"
05. #property icon "/Images/Market Replay/Icons/Indicators.ico"
06. #property link "https://www.mql5.com/es/articles/11664"
07. #property indicator_chart_window
08. #property indicator_plots 0
09. //+------------------------------------------------------------------+
10. #include <Market Replay\Chart Trader\C_ChartFloatingRAD.mqh>
11. //+------------------------------------------------------------------+
12. C_ChartFloatingRAD *chart = NULL;
13. //+------------------------------------------------------------------+
14. input int           user01 = 1;                     //Leverage
15. input double        user02 = 100.1;                 //Finance Take
16. input double        user03 = 75.4;                  //Finance Stop
17. //+------------------------------------------------------------------+
18. int OnInit()
19. {
20.     chart = new C_ChartFloatingRAD("Indicator Chart Trade", new C_Mouse("Indicator Mouse Study"), user01, user02, user03);
21.     if (_LastError != ERR_SUCCESS)
22.     {
23.             Print("Error number:", _LastError);
24.             return INIT_FAILED;
25.     }
26.     
27.     return INIT_SUCCEEDED;
28. }
29. //+------------------------------------------------------------------+
30. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
31. {
32.     return rates_total;
33. }
34. //+------------------------------------------------------------------+
35. void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
36. {
37.     (*chart).DispatchMessage(id, lparam, dparam, sparam);
38.     
39.     ChartRedraw();
40. }
41. //+------------------------------------------------------------------+
42. void OnDeinit(const int reason)
43. {
44.     delete chart;
45.     
46.     ChartRedraw();
47. }
48. //+------------------------------------------------------------------+

Vergleichen Sie dies mit dem Quellcode des Indikators, der im Artikel Entwicklung eines Replay Systems (Teil 42); Chart Trader Project (I) angegeben wurde, können Sie sehen, dass es einige Änderungen erfahren hat. Wir haben eine Möglichkeit hinzugefügt, die es dem Nutzer ermöglicht, den Wert festzulegen, der anfänglich in den Indikator eingefügt werden soll. Obwohl wir diese Form der Interaktion zwischen den Zeilen 14 und 16 haben, sind diese Punkte nicht unbedingt notwendig, obwohl sie für Tests interessant sind. Denken Sie daran, dass Chart Trade ein System der Interaktion mit dem Nutzer ist.

Anstelle der Zeilen 14 bis 16 können Sie einfach den Standardwert in den Indikator eingeben. Dies kann in Zeile 20 geschehen, wo wir anstelle von Werten, die wir aus der Nutzerinteraktion erhalten, die Werte direkt in den Aufruf eingeben können. So haben wir Chart Trade mit Standardwerten, die vom Nutzer geändert werden können, nachdem der Indikator auf dem Chart erscheint.

Darauf soll in diesem Artikel nicht eingegangen werden. Der Grund dafür ist, dass wir dafür ein etwas anderes Verfahren verwenden. Aber wie Sie im Demo-Video sehen können, werden die vom Nutzer gemeldeten Werte an Chart Trade übertragen und übersichtlich dargestellt. Wie bereits erwähnt, ist das Vorhandensein einer solchen Wechselwirkung für Testzwecke interessant.

Wir haben gesehen, dass der Indikator in der Lage ist, eine Kommunikation herzustellen. Lassen Sie uns nun herausfinden, wie Sie Änderungen im Indikator vornehmen können, wie im Video gezeigt, allerdings ohne Objekte zu verwenden. Das einzige Objekt im Chart, das im Video zu sehen ist, ist OBJ_CHART. Hat jemand eine Idee, wie ich das geschafft habe? Wie habe ich Daten und Werte nur mit OBJ_CHART geändert?

Wenn Sie keine Ahnung haben, wie das möglich ist, müssen Sie studieren, wie die MetaTrader 5-Plattform und die MQL5-Sprache tatsächlich funktionieren. Um die Erklärung zu verdeutlichen, sollten wir ein neues Thema eröffnen.


Zielsetzung und Ziele

Die meisten Menschen, die programmieren lernen wollen oder davon träumen, haben eigentlich keine Ahnung, was sie da tun. Ihre Tätigkeit besteht darin, dass sie versuchen, Dinge auf eine bestimmte Art und Weise zu schaffen. Beim Programmieren geht es jedoch nicht darum, geeignete Lösungen zu finden. Auf diese Weise können mehr Probleme als Lösungen entstehen.

Vielleicht ist das nicht ganz klar. Nun, ich werde versuchen, ein wenig von meiner langjährigen Programmiererfahrung in verschiedenen Sprachen, Plattformen und Systemen zu vermitteln.

Wenn wir anfangen, ein System zu nutzen, was auch immer es sein mag, sollten wir als erstes seine Fähigkeiten bewerten und verstehen, was das System uns bietet. Dies ist eine allgemeine Aussage. Das heißt, wir müssen versuchen zu verstehen, warum alles so und nicht anders entstanden ist. Wenn Sie verstanden haben, wie die grundlegenden Funktionen funktionieren, können Sie sich in die Tiefe begeben.

Tiefer zu gehen bedeutet nicht, nach Möglichkeiten zu suchen, diese Funktionen zu verbessern oder einfach mit ihnen zu programmieren. Die Tiefe liegt in dem Versuch, die Ressourcen zu nutzen, die noch nicht von anderen erforscht wurden. Viele Menschen beschränken sich darauf, nur das zu nutzen, was alle anderen auch nutzen, und das ist nicht schlecht. Aber wie können Sie Verbesserungen vorschlagen, ohne sich nur oberflächlich mit den Möglichkeiten des Systems vertraut zu machen? Diese Art des Denkens macht keinen Sinn. Es ist, als würde ein Kind eine neue Produktionsmethode vorschlagen wollen, indem es sich ein laufendes Fließband ansieht. So etwas hat keine Zukunft und ist dazu verdammt, mehr Probleme als Lösungen zu schaffen.

Vielleicht habe ich mich noch nicht klar genug ausgedrückt. Wenn es um den MetaTrader 5 geht, meinen manche Leute, sie wüssten genug über die Plattform, um sagen zu können, was mit ihr möglich oder unmöglich ist. Und dann wenden sie sich an MQL5 und versuchen, einige ihrer Probleme zu lösen. Das ist ein Fehler. Sie sollten MQL5, wie jede andere Sprache auch, nicht als magischen Weg zur Befriedigung Ihrer Bedürfnisse oder Wünsche betrachten. MQL5 ist keine Zaubersprache. Diese Sprache erweitert die Möglichkeiten von MetaTrader 5. Sie ist jedoch nicht in der Lage, die Plattform anders arbeiten zu lassen als vorgesehen.

Die richtige Herangehensweise besteht darin, sich eingehend mit der Funktionsweise des MetaTrader 5 zu befassen und dann nach Möglichkeiten zu suchen, ihn an Ihre eigene Art der Marktbetrachtung und -analyse anzupassen. Bei der Erkundung von MetaTrader 5 werden Sie sehen, was Sie tun müssen, um ihn in ein Werkzeug zu verwandeln, das Ihrer Sicht des Marktes besser entspricht. Dazu müssen Sie MQL5 verwenden, das die Türen des MetaTrader 5 auf eine Weise öffnet, die Ihnen oder anderen Händlern das Leben erleichtert.

Vor diesem Hintergrund können wir uns eine Frage stellen. Viele Nutzer unterschätzen den MetaTrader 5, weil sie die grundlegenden Details seiner Funktionsweise nicht kennen. Eines dieser Details, und zwar nicht nur im MetaTrader 5, ist das Konzept der Vorlagen. Sie ermöglichen es uns, bestimmte Dinge auf einfache und praktische Art und Weise anzupassen, zu verändern und zu organisieren. Von Anmerkungen bis hin zur Vereinfachung des Prozesses, den Markt auf eine bestimmte Art und Weise zu einem bestimmten Zeitpunkt zu betrachten.

Vorlagen können eine Vielzahl von Dingen enthalten, und ich habe bereits gezeigt, wie man einige von ihnen erforscht. In dem Artikel Mehrere Indikatoren in einem Chart (Teil 03): Entwicklung von Definitionen für die Nutzer habe ich gezeigt, wie verschiedene Indikatoren nebeneinander platziert werden können, wie in Abbildung 01 dargestellt.

Abbildung 01

Abbildung 01 - Verwendung mehrerer Indikatoren in einem Teilfenster

Das oben dargestellte Konzept ist nur mit Vorlagen möglich. Ganz gleich, wie gut Sie programmieren können und wie umfangreich Ihre Kenntnisse über MQL5 sind, Sie werden niemals das in Abbildung 01 gezeigte Ergebnis erzielen können, wenn Sie nicht verstehen, wie MetaTrader 5 funktioniert. Das liegt daran, dass nicht alles auf das Schreiben von Code hinausläuft. Programmieren hilft nur, eine Lösung zu finden, die sonst nicht möglich wäre. Es sollte jedoch nicht der erste Versuch sein, wenn man etwas Neues braucht, sondern eher ein Werkzeug, um das gewünschte Ergebnis zu erzielen.

Warum sage ich das? Der Grund dafür ist genau das, was in Video 01 am Anfang dieses Artikels gezeigt wird. Egal wie gut Sie programmieren können oder verstehen, wie MQL5 funktioniert, Sie werden nicht in der Lage sein, das zu tun, was in dem Video gezeigt wird, ohne zu verstehen, wie MetaTrader 5 funktioniert.

Ein wichtiger Punkt dieser Geschichte ist, dass ich bei der Veröffentlichung des Artikels „Mehrere Indikatoren auf einem Chart (Teil 06): Verwandlung von MetaTrader 5 in ein RAD-System (II)“, damals habe ich bestimmte MetaTrader 5-Konzepte noch nicht verwendet. Ich steckte noch immer in einigen Ideen und Konzepten fest, die sich schließlich als ungeeignet erwiesen. Ich will damit nicht sagen, dass sie falsch waren, aber sie waren weniger geeignet. Es gibt viel bessere Lösungen. Dies ist genau auf das zurückzuführen, was in diesem Artikel sowie im vorhergehenden Artikel „Mehrere Indikatoren in einem Chart (Teil 05): Umwandlung von MetaTrader 5 in ein RAD-System (I)“ gezeigt wurde.

In beiden Fällen haben wir die Vorlage geöffnet und versucht, sie zu bearbeiten. Aber all diese Arbeit war nicht mehr als ein Kratzer an der Oberfläche, denn vieles von dem, was Sie sehen, ist eine Neuprogrammierung derselben Vorlage. Dies geschah so, dass das RAD-System emuliert wurde, das durch Programmierung in MQL5 implementiert werden kann.

Obwohl dies funktioniert hat, werden Sie feststellen, dass die Vorlage, die wie in MetaTrader 5 erstellt wurde, später vom Indikator selbst neu erstellt wurde, als der Indikator auf dem Chart platziert wurde. Folglich wurden alle Objekte, die in der Vorlage vorhanden waren, durch den Indikator neu erstellt. Auf diese Weise erhielt MetaTrader 5 Zugang zu den dort befindlichen Objekten und konnte die darin enthaltenen Werte konfigurieren und ändern.

Im Laufe der Zeit wurde jedoch deutlich, dass die Idee verbessert werden konnte. Daher habe ich ein geeigneteres Chart Trade-Modell gefunden, das ein Minimum an Objekten verwendet. Nun, wir müssen noch etwas mehr tun als das, was in diesem Artikel gezeigt wird. Das Video 01 zeigt jedoch, dass sich die Werte geändert haben. Gleichzeitig haben wir nur ein Objekt auf dem Bildschirm.

Genau das ermöglicht uns das Programmieren. Ohne sie wären wir auf das beschränkt, was in MetaTrader 5 verfügbar ist. Durch Programmierung erweitern wir die Möglichkeiten der Plattform. Dies wird erreicht, indem wir nutzen, was bereits in MetaTrader 5 vorhanden ist. Wir erstellen eine Vorlage mit genau dem, was wir brauchen, und platzieren sie in OBJ_CHART. Ohne entsprechende Programmierung wäre es jedoch unmöglich, die Werte in den Objekten innerhalb der Vorlage zu ändern. Durch die richtige Programmierung lösen wir dieses Problem und erweitern so die Möglichkeiten des MetaTrader 5.

Um dies zu verdeutlichen, öffnen Sie die in Chart Trade verwendete Vorlagendatei. Er wird im Folgenden vollständig wiedergegeben.

Chart Trade Datei (Vorlage):

001. <chart>
002. fore=0
003. grid=0
004. volume=0
005. ticker=0
006. ohlc=0
007. one_click=0
008. one_click_btn=0
009. bidline=0
010. askline=0
011. lastline=0
012. descriptions=0
013. tradelines=0
014. tradehistory=0
015. background_color=16777215
016. foreground_color=0
017. barup_color=16777215
018. bardown_color=16777215
019. bullcandle_color=16777215
020. bearcandle_color=16777215
021. chartline_color=16777215
022. volumes_color=16777215
023. grid_color=16777215
024. bidline_color=16777215
025. askline_color=16777215
026. lastline_color=16777215
027. stops_color=16777215
028. windows_total=1
029. 
030. <window>
031. height=100.000000
032. objects=18
033. 
034. <indicator>
035. name=Main
036. path=
037. apply=1
038. show_data=1
039. scale_inherit=0
040. scale_line=0
041. scale_line_percent=50
042. scale_line_value=0.000000
043. scale_fix_min=0
044. scale_fix_min_val=0.000000
045. scale_fix_max=0
046. scale_fix_max_val=0.000000
047. expertmode=0
048. fixed_height=-1
049. </indicator>
050. 
051. <object>
052. type=110
053. name=MSG_NULL_000
054. color=0
055. pos_x=0
056. pos_y=0
057. size_x=170
058. size_y=210
059. bgcolor=16777215
060. refpoint=0
061. border_type=1
062. </object>
063. 
064. <object>
065. type=110
066. name=MSG_NULL_001
067. color=0
068. pos_x=5
069. pos_y=30
070. size_x=152
071. size_y=26
072. bgcolor=12632256
073. refpoint=0
074. border_type=1
075. </object>
076. 
077. <object>
078. type=110
079. name=MSG_NULL_002
080. color=0
081. pos_x=5
082. pos_y=58
083. size_x=152
084. size_y=26
085. bgcolor=15130800
086. refpoint=0
087. border_type=1
088. </object>
089. 
090. <object>
091. type=110
092. name=MSG_NULL_003
093. color=0
094. pos_x=5
095. pos_y=86
096. size_x=152
097. size_y=26
098. bgcolor=10025880
099. refpoint=0
100. border_type=1
101. </object>
102. 
103. <object>
104. type=110
105. name=MSG_NULL_004
106. color=0
107. pos_x=5
108. pos_y=114
109. size_x=152
110. size_y=26
111. bgcolor=8036607
112. refpoint=0
113. border_type=1
114. </object>
115. 
116. <object>
117. type=102
118. name=MSG_NULL_007
119. descr=Lever ( x )
120. color=0
121. style=1
122. angle=0
123. pos_x=10
124. pos_y=63
125. fontsz=16
126. fontnm=System
127. anchorpos=0
128. refpoint=0
129. </object>
130. 
131. <object>
132. type=102
133. name=MSG_NULL_008
134. descr=Take ( $ )
135. color=0
136. style=1
137. angle=0
138. pos_x=10
139. pos_y=91
140. fontsz=16
141. fontnm=System
142. anchorpos=0
143. refpoint=0
144. </object>
145. 
146. <object>
147. type=102
148. name=MSG_NULL_009
149. descr=Stop ( $ )
150. color=0
151. style=1
152. angle=0
153. pos_x=10
154. pos_y=119
155. fontsz=16
156. fontnm=System
157. anchorpos=0
158. refpoint=0
159. </object>
160. 
161. <object>
162. type=107
163. name=MSG_TITLE_IDE
164. descr=Chart Trade
165. color=16777215
166. style=1
167. pos_x=0
168. pos_y=0
169. size_x=164
170. size_y=28
171. bgcolor=16748574
172. fontsz=16
173. fontnm=System
174. refpoint=0
175. readonly=1
176. align=0
177. </object>
178. 
179. <object>
180. type=106
181. name=MSG_BUY_MARKET
182. size_x=70
183. size_y=25
184. offset_x=0
185. offset_y=0
186. pos_x=5
187. pos_y=145
188. bmpfile_on=\Images\Market Replay\Chart Trade\BUY.bmp
189. bmpfile_off=\Images\Market Replay\Chart Trade\BUY.bmp
190. state=0
191. refpoint=0
192. anchorpos=0
193. </object>
194. 
195. <object>
196. type=106
197. name=MSG_SELL_MARKET
198. size_x=70
199. size_y=25
200. offset_x=0
201. offset_y=0
202. pos_x=85
203. pos_y=145
204. bmpfile_on=\Images\Market Replay\Chart Trade\SELL.bmp
205. bmpfile_off=\Images\Market Replay\Chart Trade\SELL.bmp
206. state=0
207. refpoint=0
208. anchorpos=0
209. </object>
210. 
211. <object>
212. type=103
213. name=MSG_CLOSE_POSITION
214. descr=Close Position
215. color=0
216. style=1
217. pos_x=5
218. pos_y=173
219. fontsz=16
220. fontnm=System
221. state=0
222. size_x=152
223. size_y=26
224. bgcolor=1993170
225. frcolor=-1
226. refpoint=0
227. </object>
228. 
229. <object>
230. type=107
231. name=MSG_NAME_SYMBOL
232. descr=?
233. color=0
234. style=1
235. pos_x=7
236. pos_y=34
237. size_x=116
238. size_y=20
239. bgcolor=12632256
240. fontsz=14
241. fontnm=Tahoma
242. refpoint=0
243. readonly=1
244. align=1
245. </object>
246. 
247. <object>
248. type=107
249. name=MSG_LEVERAGE_VALUE
250. descr=?
251. color=0
252. style=1
253. pos_x=80
254. pos_y=61
255. size_x=70
256. size_y=18
257. bgcolor=15130800
258. fontsz=12
259. fontnm=Tahoma
260. refpoint=0
261. readonly=0
262. align=1
263. </object>
264. 
265. <object>
266. type=107
267. name=MSG_TAKE_VALUE
268. descr=?
269. color=0
270. style=1
271. pos_x=80
272. pos_y=91
273. size_x=70
274. size_y=18
275. bgcolor=10025880
276. fontsz=12
277. fontnm=Tahoma
278. refpoint=0
279. readonly=0
280. align=1
281. </object>
282. 
283. <object>
284. type=107
285. name=MSG_STOP_VALUE
286. descr=?
287. color=0
288. style=1
289. pos_x=80
290. pos_y=119
291. size_x=70
292. size_y=18
293. bgcolor=8036607
294. fontsz=12
295. fontnm=Tahoma
296. refpoint=0
297. readonly=0
298. align=1
299. </object>
300. 
301. <object>
302. type=106
303. name=MSG_DAY_TRADE
304. size_x=32
305. size_y=22
306. offset_x=0
307. offset_y=0
308. pos_x=123
309. pos_y=33
310. bmpfile_on=\Images\Market Replay\Chart Trade\DT.bmp
311. bmpfile_off=\Images\Market Replay\Chart Trade\SW.bmp
312. state=0
313. refpoint=0
314. anchorpos=0
315. </object>
316. 
317. <object>
318. type=106
319. name=MSG_MAX_MIN
320. size_x=20
321. size_y=20
322. offset_x=0
323. offset_y=0
324. pos_x=140
325. pos_y=3
326. bmpfile_on=\Images\Market Replay\Chart Trade\Maximize.bmp
327. bmpfile_off=\Images\Market Replay\Chart Trade\Minimize.bmp
328. state=1
329. refpoint=0
330. anchorpos=0
331. </object>
332. 
333. </window>
334. </chart>

Ich weiß, der Inhalt mag völlig unnötig erscheinen. Bitte beachten Sie, dass es keine Dateien im Anhang geben wird. Das gesamte System wird so veröffentlicht, dass die Dateien durch Umschreiben der Codes in die entsprechenden Dateien erhalten werden können. Ich tue dies, um sicherzustellen, dass Sie den Artikel lesen und verstehen. Ich möchte nicht, dass Sie die angehängten Dateien einfach herunterladen und das System nutzen, ohne zu wissen, was Sie tun. Auch wenn es den Anschein hat, dass der Artikel dadurch wesentlich länger wird, ist das nicht der Fall, sondern die Erklärung wird nur viel ausführlicher.

Schauen wir uns nun die Chart Trade-Vorlagendatei genauer an. Achten Sie auf die Zeilen mit den folgenden Angaben:

descr=?

Sie kommt an mehreren Stellen in der Vorlagendatei vor und ist absichtlich so gewählt. Warum? Obwohl descr an verschiedenen Stellen erscheint, beziehen sich diese Stellen, wie oben gezeigt, hauptsächlich auf Objekte des Typs 107. Was sind Objekte des Typs 107?

Eine Beschreibung dieser Arten von Objekten erschien zuerst im Artikel „Mehrere Indikatoren in einem Chart (Teil 05): MetaTrader 5 in ein RAD (I)-System verwandeln“. Der Einfachheit halber werde ich die in diesem Artikel vorgestellte Tabelle nachstehend wiedergeben:

Der Wert der Variablen TYPE Referenziertes Objekt
102 OBJ_LABEL
103 OBJ_BUTTON
106 OBJ_BITMAP_LABEL
107  OBJ_EDIT
110  OBJ_RECTANGLE_LABEL

Objekt 107 ist also OBJ_EDIT. Dies sind Objekte, in die der Nutzer Informationen eingeben kann.

Es ist jedoch nicht möglich, direkt auf ein Objekt zuzugreifen, das sich in einer Vorlage befindet, oder dort einen Wert einzugeben. Das ist eine Tatsache. Wie habe ich dieses Problem gelöst, sodass das in der Vorlage vorhandene Objekt 107 Werte vom Indikator erhalten kann? Um diese Frage zu beantworten, müssen Sie sich den Code der Klasse ansehen, die für die Verwendung der Vorlage verantwortlich ist.


Aktualisieren der Klasse C_ChartFloatingRAD

Damit Chart Trade die vom Nutzer eingegebenen Werte anzeigt, müssen Sie unmittelbar nach dem Start des Indikators im Chart einige grundlegende Operationen durchführen. Diese Operationen zielen darauf ab, bestimmte Probleme zu lösen, die ohne den Einsatz von Programmierung nicht gelöst werden können. Aus diesem Grund ist es sehr wichtig, dass Sie die Funktionsweise des MetaTrader 5 gut verstehen. Ohne die Prinzipien der Plattformbedienung zu kennen, werden Sie nicht in der Lage sein, den erforderlichen Code zu erstellen, um solche Hindernisse zu überwinden, die ohne Programmierung nicht zu lösen sind.

Der vollständige Code für die Klasse C_ChartFloatingRAD ist unten zu sehen. Dieser Code in seiner jetzigen Form ermöglicht es dem Indikator, wie in Video 01 gezeigt zu funktionieren. Können Sie verstehen, wie das geschieht?

Quellcode der Klasse C_ChartFloatingRAD:

001. //+------------------------------------------------------------------+
002. #property copyright "Daniel Jose"
003. //+------------------------------------------------------------------+
004. #include "../Auxiliar/C_Terminal.mqh"
005. #include "../Auxiliar/C_Mouse.mqh"
006. //+------------------------------------------------------------------+
007. class C_ChartFloatingRAD : private C_Terminal
008. {
009.    private :
010.            struct st00
011.            {
012.                    int     x, y, cx, cy;
013.                    string  szObj_Chart,
014.                            szFileNameTemplate;
015.                    long    WinHandle;
016.                    double  FinanceTake,
017.                            FinanceStop;
018.                    int     Leverage;
019.            }m_Info;
020. //+------------------------------------------------------------------+
021.            C_Mouse *m_Mouse;
022. //+------------------------------------------------------------------+
023.            void CreateWindowRAD(int x, int y, int w, int h)
024.                    {
025.                            m_Info.szObj_Chart = (string)ObjectsTotal(GetInfoTerminal().ID);
026.                            ObjectCreate(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJ_CHART, 0, 0, 0);
027.                            ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_XDISTANCE, m_Info.x = x);
028.                            ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_YDISTANCE, m_Info.y = y);
029.                            ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_XSIZE, w);
030.                            ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_YSIZE, h);
031.                            ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_DATE_SCALE, false);
032.                            ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_PRICE_SCALE, false);
033.                            m_Info.WinHandle = ObjectGetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_CHART_ID);
034.                            m_Info.cx = w;
035.                            m_Info.cy = 26;
036.                    };
037. //+------------------------------------------------------------------+
038.            void Level_1(int &fpIn, int &fpOut, const string szFind, const string szWhat, const string szValue)
039.                    {
040.                            string sz0 = "";
041.                            int i0 = 0;
042.                            string res[];
043.                            
044.                            while ((!FileIsEnding(fpIn)) && (sz0 != "</object>"))
045.                            {
046.                                    sz0 = FileReadString(fpIn);
047.                                    if (StringSplit(sz0, '=', res) > 1)
048.                                    {
049.                                            i0 = (res[1] == szFind ? 1 : i0);
050.                                            if ((i0 == 1) && (res[0] == szWhat))
051.                                            {
052.                                                    FileWriteString(fpOut, szWhat + "=" + szValue + "\r\n");
053.                                                    return;
054.                                            }
055.                                    }
056.                                    FileWriteString(fpOut, sz0 + "\r\n");
057.                            };
058.                    }
059. //+------------------------------------------------------------------+
060.            void SwapValueInTemplate(const string szFind, const string szWhat, const string szValue)
061.                    {
062.                            int fpIn, fpOut;
063.                            string sz0;
064.                            
065.                            if (_LastError != ERR_SUCCESS) return;
066.                            if ((fpIn = FileOpen(m_Info.szFileNameTemplate, FILE_READ | FILE_TXT)) == INVALID_HANDLE)
067.                            {
068.                                    SetUserError(C_Terminal::ERR_FileAcess);
069.                                    return;
070.                            }
071.                            if ((fpOut = FileOpen(m_Info.szFileNameTemplate + "_T", FILE_WRITE | FILE_TXT)) == INVALID_HANDLE)
072.                            {
073.                                    FileClose(fpIn);
074.                                    SetUserError(C_Terminal::ERR_FileAcess);
075.                                    return;
076.                            }
077.                            while (!FileIsEnding(fpIn))
078.                            {
079.                                    sz0 = FileReadString(fpIn);
080.                                    FileWriteString(fpOut, sz0 + "\r\n");
081.                                    if (sz0 == "<object>") Level_1(fpIn, fpOut, szFind, szWhat, szValue);
082.                            };
083.                            FileClose(fpIn);
084.                            FileClose(fpOut);
085.                            if (!FileMove(m_Info.szFileNameTemplate + "_T", 0, m_Info.szFileNameTemplate, FILE_REWRITE))
086.                            {
087.                                    FileDelete(m_Info.szFileNameTemplate + "_T");
088.                                    SetUserError(C_Terminal::ERR_FileAcess);
089.                            }
090.                    }
091. //+------------------------------------------------------------------+
092. inline void UpdateChartTemplate(void)
093.                    {
094.                            ChartApplyTemplate(m_Info.WinHandle, "/Files/" + m_Info.szFileNameTemplate);
095.                            ChartRedraw(m_Info.WinHandle);
096.                    }
097. //+------------------------------------------------------------------+
098. inline double PointsToFinance(const double Points)
099.                    {                               
100.                            return Points * (GetInfoTerminal().VolumeMinimal + (GetInfoTerminal().VolumeMinimal * (m_Info.Leverage - 1))) * GetInfoTerminal().AdjustToTrade;
101.                    };
102. //+------------------------------------------------------------------+
103.    public  :
104. //+------------------------------------------------------------------+
105.            C_ChartFloatingRAD(string szShortName, C_Mouse *MousePtr, const int Leverage, const double FinanceTake, const double FinanceStop)
106.                    :C_Terminal()
107.                    {
108.                            m_Mouse = MousePtr;
109.                            m_Info.Leverage = (Leverage < 0 ? 1 : Leverage);
110.                            m_Info.FinanceTake = PointsToFinance(FinanceToPoints(MathAbs(FinanceTake), m_Info.Leverage));
111.                            m_Info.FinanceStop = PointsToFinance(FinanceToPoints(MathAbs(FinanceStop), m_Info.Leverage));
112.                            if (!IndicatorCheckPass(szShortName)) SetUserError(C_Terminal::ERR_Unknown);
113.                            m_Info.szFileNameTemplate = StringFormat("Chart Trade/%u.tpl", GetInfoTerminal().ID);
114.                            if (!FileCopy("Chart Trade/IDE_RAD.tpl", 0, m_Info.szFileNameTemplate, FILE_REWRITE)) SetUserError(C_Terminal::ERR_FileAcess);
115.                            if (_LastError != ERR_SUCCESS) return;
116.                            SwapValueInTemplate("MSG_NAME_SYMBOL", "descr", GetInfoTerminal().szSymbol);
117.                            SwapValueInTemplate("MSG_LEVERAGE_VALUE", "descr", (string)m_Info.Leverage);
118.                            SwapValueInTemplate("MSG_TAKE_VALUE", "descr", (string)m_Info.FinanceTake);
119.                            SwapValueInTemplate("MSG_STOP_VALUE", "descr", (string)m_Info.FinanceStop);
120.                            if (_LastError != ERR_SUCCESS) return;
121.                            CreateWindowRAD(0, 0, 170, 210);
122.                            UpdateChartTemplate();
123.                    }
124. //+------------------------------------------------------------------+
125.            ~C_ChartFloatingRAD()
126.                    {
127.                            ObjectDelete(GetInfoTerminal().ID, m_Info.szObj_Chart);
128.                            FileDelete(m_Info.szFileNameTemplate);
129.                            
130.                            delete m_Mouse;
131.                    }
132. //+------------------------------------------------------------------+
133.            void DispatchMessage(const int id, const long &lparam, const double &dparam, const string &sparam)
134.                    {
135.                            static int sx = -1, sy = -1;
136.                            int x, y, mx, my;
137.    
138.                            switch (id)
139.                            {
140.                                    case CHARTEVENT_MOUSE_MOVE:
141.                                            if ((*m_Mouse).CheckClick(C_Mouse::eClickLeft))
142.                                            {
143.                                                    x = (int)lparam;
144.                                                    y = (int)dparam;
145.                                                    if ((x > m_Info.x) && (x < (m_Info.x + m_Info.cx)) && (y > m_Info.y) && (y < (m_Info.y + m_Info.cy)))
146.                                                    {
147.                                                            if (sx < 0)
148.                                                            {
149.                                                                    ChartSetInteger(GetInfoTerminal().ID, CHART_MOUSE_SCROLL, false);
150.                                                                    sx = x - m_Info.x;
151.                                                                    sy = y - m_Info.y;
152.                                                            }
153.                                                            if ((mx = x - sx) > 0) ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_XDISTANCE, m_Info.x = mx);
154.                                                            if ((my = y - sy) > 0) ObjectSetInteger(GetInfoTerminal().ID, m_Info.szObj_Chart, OBJPROP_YDISTANCE, m_Info.y = my);
155.                                                    }
156.                                            }else if (sx > 0)
157.                                            {
158.                                                    ChartSetInteger(GetInfoTerminal().ID, CHART_MOUSE_SCROLL, true);                                                
159.                                                    sx = sy = -1;
160.                                            }
161.                                            break;
162.                            }
163.                    }
164. //+------------------------------------------------------------------+
165. };
166. //+------------------------------------------------------------------+

Bitte beachten Sie, dass die Datei C_ChartFloatingRAD seit dem letzten Artikel praktisch keine wesentlichen Ergänzungen erfahren hat. Dies ist beabsichtigt. Wenn ich Ihnen die endgültige Version dieser Datei zeigen würde, könnten Sie nicht verstehen, wie und warum MetaTrader 5 es schafft, die Werte in der Vorlage zu ändern. Dies geschieht, damit Sie beim Öffnen des Objektlistenfensters mit STRG+B nur OBJ_CHART in der Liste sehen, aber die Werte und das Fenster trotzdem geändert werden.

Versuchen wir nun zu verstehen, wie und warum der MetaTrader 5 uns über das Geschehen in einem Template informieren kann. Denken Sie daran, dass die Vorlage weiter verwendet wird und auf das Objekt OBJ_CHART angewendet wird. Dies geschieht, wenn Zeile 94 ausgeführt wird und Zeile 95 MetaTrader 5 anweist, OBJ_CHART zu aktualisieren. Wenn Sie diese Tatsache nicht berücksichtigen, können Sie viel Zeit damit verbringen, etwas im Code zu suchen, das nicht vorhanden ist. Zum Beispiel für die Dinge, die tatsächlich in der Vorlagendatei stehen.

Der hinzugefügte Code ist zwischen den Zeilen 38 und 123 zu sehen. Er ist so aufgebaut, dass die weiteren Schritte, die im nächsten Artikel durchgeführt werden, keine großen Änderungen erfordern, was sehr gut ist. Achten Sie also auf die Erklärungen in diesem Artikel, und Sie werden die nächste sehr leicht verstehen. Vielleicht können Sie sogar vorhersagen, was im nächsten Artikel aus der Sicht der Programmierung getan werden wird.

Beginnen wir mit dem Klassenkonstruktor, da dies das Verständnis der anderen Teile wesentlich erleichtert. Dieser Konstruktor beginnt in Zeile 105. Aber die wirkliche Veränderung beginnt in Zeile 109. In dieser Zeile garantieren wir, dass der Wert der Hebelwirkung immer größer oder gleich 1 sein wird. Hierfür verwenden wir den ternären Operator. Hier gibt es also nichts besonders Kompliziertes oder Verwirrendes.

Gehen wir nun zu Zeile 110. In dieser Zeile wird, wie in Zeile 111, eine Anpassung des im Chart Trade-Fenster angezeigten Wertes vorgenommen. Der Grund dafür ist, dass der Nutzer einen Wert eingeben kann, der nicht für den Vermögenswert gültig ist, für den der Chart Trade Indikator läuft. Im Falle von Dollar-Futures beispielsweise erfolgen die Bewegungen immer alle 5,00 $ pro Kontrakt. In diesem Fall ist die Angabe von Take-Profit oder Stop-Loss als Wert, der kein Vielfaches von 5 ist, z. B. Take-Profit=R$76,00, nicht sinnvoll, da dieser Wert nie erreicht wird.

Die Zeilen 110 und 111 führen also zwei Gespräche. Die erste wandelt den finanziellen Wert in Punkte um, die zweite macht das Gegenteil und wandelt den Punktwert in einen finanziellen Wert um. Man könnte meinen, dass dies den Wert auf seinen ursprünglichen Wert zurücksetzt. Das ist richtig, aber hier werden mathematische Methoden zur Umrechnung und Anpassung der Werte verwendet. Beim ersten Aufruf wird die Funktion in der Klasse C_Terminal verwendet. In der zweiten führen wir die Funktion aus, die in Zeile 98 steht.

Diese Funktion bei 98 benötigt nur eine Zeile. In Zeile 100 wird eine Berechnung durchgeführt, die die angegebene Anzahl von Pips in einen finanziellen Wert umwandelt.

Das war der einfache Teil. Betrachten wir nun den schwierigsten Teil des derzeitigen Systems.

Sobald der Konstruktor die Zeile 113 erreicht, erhalten wir etwas sehr Interessantes. In dieser Zeile 113 wird der Name der temporären Datei erstellt. Denken Sie daran, dass diese Datei nur vorübergehend ist. Sie befindet sich in dem in MQL5\Files definierten Bereich zusammen mit anderen Informationen, die speziell für diese Zeile 113 erstellt wurden.

Sobald wir den Dateinamen in Zeile 113 erstellt haben, gehen wir zu Zeile 114 über. In dieser Zeile wird der Inhalt der Vorlagendatei (die im vorherigen Thema zu sehen ist) vollständig unter einem neuen Namen kopiert. Wenn wir Erfolg haben, werden wir weitermachen. Wenn das Kopieren jedoch fehlschlägt, werden wir dies dem Initiator mitteilen.

Der eigentliche Zauber findet zwischen den Zeilen 116 und 119 statt. Hier sorgen wir dafür, dass der Chart Trade-Indikator die vom MetaTrader 5 und/oder dem Nutzer bereitgestellten Werte empfängt. Diese Zeilen rufen die Zeile 60 des Klassencodes auf. Von nun an werden wir an diesem Teil des Codes arbeiten, da der Rest des Konstruktors im vorherigen Artikel erklärt wurde. Bevor wir jedoch zu Zeile 60 übergehen, möchte ich Ihre Aufmerksamkeit auf eine weitere Zeile lenken, die dem Code hinzugefügt wurde: Zeile 128. Dort wird die im Konstruktor erstellte Datei gelöscht. Deshalb habe ich betont, dass die erstellte Datei temporär ist.

Gehen wir weiter zu Zeile 60. Ich muss hier etwas wiederholen (ich bin noch dabei, die Grundlagen zu erklären, haben Sie also etwas Geduld). Der erste Schritt besteht darin, die „Original“-Datei zu öffnen (beachten Sie die Anführungszeichen in dem Wort); dies geschieht in Zeile 66. Wenn wir Erfolg haben, werden wir weitermachen. Wenn wir scheitern, kehren wir zum Anrufer zurück.

In Zeile 71 erstellen wir eine temporäre Datei aus einer temporären Datei (klingt seltsam, aber anders kann man es nicht sagen). Wenn dies fehlschlägt, schließen wir die geöffnete Datei und kehren zum Aufrufer zurück. Bis Zeile 77 haben wir nur eine Datei geöffnet und eine weitere erstellt. Wenn die Ausführung die Zeile 77 erreicht, wird eine Schleife gestartet, um die gesamte Datei zu kopieren.

Moment, die gesamte Datei kopieren? Schon wieder? Ja, aber dieses Mal werden wir eine Bedingung in Zeile 81 testen. Diese Bedingung prüft, ob ein Objekt in der Vorlagendatei während des Kopiervorgangs gefunden wurde. Wenn dies geschieht, gehen wir zu Zeile 38 über, wo wir uns mit dem gefundenen Objekt befassen. Wenn es sich bei dem analysierten Muster um ein Muster aus dem vorherigen Thema handelt, springen wir in jedem Fall zu Zeile 38. Auch wenn Sie Ihre eigene Vorlage verwenden möchten, können Sie dies tun, solange Sie die Namen der Objekte korrekt definieren.

Nach dem Aufruf der in Zeile 38 vorgestellten Funktion gehen wir weiter bis zur Zeile 44. Hier setzen wir das Kopieren der Datei auf die gleiche Weise fort wie zuvor. Wenn jedoch die Zeile, die das Objekt schließt, genau in dieser Zeile 44 zu finden ist, kehren wir zum aufrufenden Objekt zurück, d. h. zur Zeile 81. Halten wir einen Moment inne und sehen uns die Funktion an, die in Zeile 38 erscheint.

Während des Kopiervorgangs lesen wir die Quelldatei in Zeile 46. Danach werden wir den Inhalt dieser Zeile erweitern. Wenn Zeile 47, die diese Zerlegung durchführt, meldet, dass zwei Anweisungen verfügbar sind, wird ein neuer Ausführungsfaden erstellt. Andernfalls wird die gelesene Zeile geschrieben, und das geschieht in Zeile 56.

Beachten Sie nun den folgenden Punkt: Bei der in Zeile 47 durchgeführten Zerlegung hat die Variable i0 den Anfangswert 0. Achten Sie hierauf besonders. Sobald der Objektname gefunden ist, wird die Variable i0 auf 1 gesetzt. Genau hier liegt die Gefahr. Wenn Sie eine Vorlagendatei manuell bearbeiten, müssen Sie sicherstellen, dass der Objektname vor den Parametern erscheint. Der einzige Parameter, der vor dem Namen erscheinen kann, ist der Typ des Objekts. Vor dem Namen sollten keine weiteren Parameter stehen. Wenn dies geschieht, wird der gesamte Prozess fehlschlagen.

In Zeile 50 wird geprüft, ob i0 anzeigt, dass das gewünschte Objekt gefunden wurde. In diesem Fall ist der Wert dieser Variablen 1. Es gibt aber noch eine zweite Bedingung, die den gesuchten Parameter betrifft. In diesem Fall suchen wir immer nach descr. Wenn diese beiden Bedingungen erfüllt sind, schreiben wir den gewünschten Wert während des Kopiervorgangs. Diese Art der Änderung erfolgt in Zeile 52. Danach kehren wir zum Aufrufer zurück, d. h. zur Zeile 81.

Beobachten Sie, wie dieser Prozess abläuft. Wir kopieren die gesamte Datei, mit Ausnahme einer bestimmten Zeile. Diese Zeile wird geändert, sodass neue Daten in der Vorlage erscheinen oder diese ein anderes Aussehen erhält.

Wenn die gesamte Datei kopiert und geändert wurde, schließen wir beide Dateien, was in den Zeilen 83 und 84 geschieht. Danach, in Zeile 85, versuchen wir, die temporäre Datei in die Datei umzubenennen, die die Klasse zu verwenden erwartet. Der Vorgang ist genau derselbe wie in Video 01 gezeigt.


Schlussfolgerung

In diesem Material habe ich die ersten Schritte erläutert, die Sie befolgen müssen, um die Vorlage verwalten zu können. Auf diese Weise passt es sich an unsere Bedürfnisse an. Dadurch können wir die Möglichkeiten von MetaTrader 5 mit einer relativ einfachen Programmierung besser nutzen. Wichtig ist jedoch, dass Sie nicht mehr oder weniger Objekte auf dem Chart verwenden. Was wirklich wichtig ist, ist zu verstehen, dass MQL5 es jedem ermöglicht, MetaTrader 5 in eine Plattform zu verwandeln, die für seine Bedürfnisse geeignet ist, und nicht, eine andere konkurrierende Plattform zu schaffen.


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

Beigefügte Dateien |
Anexo.zip (420.65 KB)
Die Übertragung der Trading-Signale in einem universalen Expert Advisor. Die Übertragung der Trading-Signale in einem universalen Expert Advisor.
In diesem Artikel wurden die verschiedenen Möglichkeiten beschrieben, um die Trading-Signale von einem Signalmodul des universalen EAs zum Steuermodul der Positionen und Orders zu übertragen. Es wurden die seriellen und parallelen Interfaces betrachtet.
Entwicklung eines Wiedergabesystems (Teil 42): Chart Trader Projekt (I) Entwicklung eines Wiedergabesystems (Teil 42): Chart Trader Projekt (I)
Lassen Sie uns etwas Interessanteres schaffen. Ich möchte die Überraschung nicht verderben, also folgen Sie dem Artikel, um ein besseres Verständnis zu erhalten. Gleich zu Beginn dieser Serie über die Entwicklung des Replay/Simulator-Systems habe ich gesagt, dass die MetaTrader 5-Plattform sowohl in dem von uns entwickelten System als auch auf dem realen Markt auf die gleiche Weise verwendet werden soll. Es ist wichtig, dass dies richtig gemacht wird. Niemand möchte trainieren und lernen, mit einem Werkzeug zu kämpfen, während er während des Kampfes ein anderes nutzen muss.
Eine alternative Log-datei mit der Verwendung der HTML und CSS Eine alternative Log-datei mit der Verwendung der HTML und CSS
In diesem Artikel werden wir eine sehr einfache, aber leistungsfähige Bibliothek zur Erstellung der HTML-Dateien schreiben, dabei lernen wir auch, wie man eine ihre Darstellung einstellen kann (nach seinem Geschmack) und sehen wir, wie man es leicht in seinem Expert Advisor oder Skript hinzufügen oder verwenden kann.
MQL5-Assistenten-Techniken, die Sie kennen sollten (Teil 24): Gleitende Durchschnitte MQL5-Assistenten-Techniken, die Sie kennen sollten (Teil 24): Gleitende Durchschnitte
Gleitende Durchschnitte sind ein sehr verbreiteter Indikator, der von den meisten Händlern verwendet und verstanden wird. Wir erforschen mögliche Anwendungsfälle, die in den mit dem MQL5-Assistenten zusammengestellten Expert Advisors vielleicht nicht so häufig vorkommen.