preview
Desenvolvendo um sistema de Replay (Parte 43): Projeto do Chart Trade (II)

Desenvolvendo um sistema de Replay (Parte 43): Projeto do Chart Trade (II)

MetaTrader 5Exemplos | 16 fevereiro 2024, 14:41
293 0
Daniel Jose
Daniel Jose

Introdução

No artigo anterior Desenvolvendo um sistema de Replay (Parte 42): Projeto do Chart Trade (I), mostrei como podemos começar a ter alguma interação entre o indicador mouse e outros indicadores.

Lá dei inicio a codificação, que será feita a fim de conseguir fazer com que o indicador Chart Trade, possa ser criado e mantido em perfeita harmonia com o indicador mouse. No entanto, diferente do que foi feito, nas primeiras versões deste indicador Chart Trade, isto lá nos artigos:

Aqui iremos fazer algo um pouco mais avançado, e por consequência diferente. Mas de qualquer maneira o resultado será o que é visto no vídeo 01. Sugiro que você veja o vídeo, antes mesmo de ler o artigo. Isto para que você tenha um noção do que será feito aqui. Não é algo que apenas olhando o código você irá compreender. Dizem que uma imagem vale mais que mil palavras. Então veja o vídeo para compreender melhor o que será explicado no artigo.


Vídeo 01 - Vídeo de demonstração sobre este artigo.

No vídeo, você pode ver que estamos informando os dados a serem visualizados na janela do Chart Trade. Deve ter notado que estamos fazendo as coisas exatamente como visto no artigo anterior. Mas mesmo assim as informações estão sendo atualizadas sem que de fato estejamos usando objetos para isto. Você já deve estar se indagando: Como isto é possível ?!?!

Este cara deve esta fazendo algum tipo de trapaça. Nunca vi ninguém fazendo este tipo de coisa. Isto não faz sentido algum. Outros devem estar achando que sou algum tipo de bruxo, ou místico. Com capacidade além da imaginação. Não. Não é nada disto. O que estou fazendo é usando tanto a plataforma MetaTrader 5, assim como a linguagem MQL5, em um nível que muitos não procuram de fato compreender. Eles simplesmente ficam falando e fazendo sempre as mesmas coisas. Não exploram o real potencial e capacidades. Tanto da linguagem MQL5, quanto da plataforma MetaTrader 5.

Espero que você tenha de fato visto o vídeo. Pois aqui irei mostrar como fazer algo que poderá mudar a sua noção do que se pode de fato fazer. Uma observação: Irei explicar apenas e somente o que está sendo mostrado no vídeo. As coisas que não estão sendo mostradas nele, serão vistas depois.


Atualizando o código do indicador

As mudanças que é preciso fazer não serão assim tão grandes. Mas mesmo assim irei ir devagar. Caso contrário todos irão ficar sem compreender o que está de fato acontecendo.

Vamos começar vendo as atualizações feitas no código do indicador. Estas podem ser vista no código que está sendo mostrado na integra logo abaixo:

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/pt/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. //+------------------------------------------------------------------+

Código fonte do Indicador Chart Trade

Se você observar o código fonte do indicador que pode ser visto no artigo Desenvolvendo um sistema de Replay (Parte 42): Projeto do Chart Trade (I). Irá notar que este código visto acima, sofreu algumas pequenas atualizações. Estas são, basicamente, a adição de meios, para que o usuário consiga informar, o valor a ser colocado inicialmente no indicador. Apesar de que entre as linhas 14 e 16, termos esta forma de interação, estes pontos não são de todo necessários. Apesar de ser interessante tê-los para fins de testes. Lembre-se o Chart Trade é um sistema de interação com o usuário do sistema.

Você pode ao invés de ter as linhas 14 a 16, simplesmente lançar um valor "padrão" ou default no indicador. Isto seria feito na linha 20. Onde ao invés de usar os valores informados pela interação com o usuário, poderíamos colocar os valores diretamente na chamada. Assim teríamos um Chart Trade com valores "padrão", e uma vez que ele estivesse no gráfico, o usuário poderia modificar tais valores.

Esta edição, não irá de fato acontecer neste artigo. O motivo é que para fazer isto iremos usar um processo ligeiramente diferente. Mas como você pode ver vídeo de demonstração. Os valores informados pelo usuário são repassados para dentro do Chart Trade e demonstrados claramente. Como falei, é interessante ter esta interação para fins de teste.

Agora que sabemos que o indicador consegue de fato estabelecer uma comunicação. Vamos entender como é possível fazer com que tenhamos as mudanças feitas no indicador, como demonstrado no vídeo, se na verdade não estamos usando objetos para isto. O único objeto presente no gráfico, como fica claro no vídeo é o OBJ_CHART. Então você faz ideia de como consegui fazer tal coisa ?!?! Mudar os dados e valores usando para isto apenas e somente o OBJ_CHART ?!?!

Se você não tem a mínima ou menor noção de como isto é possível. Vamos então aprender como de fato a plataforma MetaTrader 5 e a linguagem MQL5 funcionam. Mas para que a explicação fique mais clara, vou criar um novo tópico.


Objetos e Objetos

Grande parte das pessoas que querem, ou desejam aprender a programar, não fazem de fato ideia, do que estão fazendo. O que elas fazem é tentar criar as coisas de uma determinada maneira. No entanto, quando programamos não estamos de fato tentando criar um solução. Se você tentar fazer isto, desta forma irá gerar mais problemas do que realmente uma solução.

Talvez isto não tenha ficado claro. Mas tentarei passar um pouco da minha experiência de anos de programação, isto em diversos tipos de linguagens, plataformas e sistemas.

Sempre que começamos usar um sistema, seja ele qual for. A primeira coisa que de fato devemos tentar fazer, é conhecer o que o sistema nos oferece. Isto em temos básico. Ou seja, você tem que tentar compreender por que ele foi criado daquela forma, e não de uma outra maneira. Depois de saber como as funcionalidades mais básicas trabalham, ai sim, você pode começar a aprofundar no mesmo.

Este aprofundamento não se dá começando a procurar formas de melhorar, ou programar algo nele. Na verdade este aprofundamento se dá tentando usar recursos pouco explorados naturalmente por outros. Muitas pessoas se limitam a usar apenas aquilo que todos usam normalmente. Isto não esta errado. Mas como você pode querer propor melhorias em algo, se você conhece apenas superficialmente o que se pode fazer naquele sistema ?!?! Este tipo de pensamento, não faz sentido. É como uma criança querendo propor um novo meio de produção, apenas olhando uma esteira funcionando. Este tipo de coisa não tem futuro e estará fardada a gerar mais problemas do que soluções.

Talvez você não tenha conseguido de fato compreender a ideia. Algumas pessoas olham o MetaTrader 5, e já logo acham saber o suficiente, sobre a plataforma, a fim de dizer que é ou não possível fazer as coisas nela. E logo partem para o MQL5 tentando solucionar algumas questões. Isto é um erro. Você não deve olhar o MQL5, assim como qualquer outra linguagem, como uma solução mágica aos seus desejos, ou vontades. O MQL5, não e vou repetir. NÃO é uma linguagem mágica. Ela é uma linguagem, que amplia o que podemos fazer no MetaTrader 5. Ela não foi construída de maneira a fazer o MetaTrader 5 funcionar de forma diferente, para aquilo que ele foi projetado.

O correto, é você compreender profundamente como o MetaTrader 5 funciona, para somente depois procurar formas de deixá-lo com a sua cara. Ou a sua maneira de olhar e analisar o mercado. Quando você compreender isto, irá ver o que será preciso fazer para tornar o MetaTrader 5 uma ferramenta mais adequada a sua forma de olhar o mercado. Para fazer isto, você irá usar o MQL5, que irá abrir as portas do MetaTrader 5 de maneira que você o deixe como ele deverá ser, a fim de que ele possa facilitar a sua vida, ou de outros operadores.

Tendo isto em mente, podemos entrar em uma questão. Muitos usuários torcem o nariz para o MetaTrader 5, por não conhecer detalhes básicos de seu funcionamento. Um destes detalhes, e não somente do MetaTrader 5, mas aqui irei focar nele, é o conceito de templates. Este são usados como forma de nos permitir configurar, ajustar e organizar de maneira prática e simples certas coisas. Tais coisas vão deste anotações, chegando em alguns momentos a tornar mais simples você olhar o mercado de uma forma especifica em um momento especifico.

Templates podem conter diversas coisas. Já mostrei como explorar algumas destas coisas antes. No artigo Indicadores múltiplos em um gráfico (Parte 03): Desenvolvendo definições para usuários, mostrei como você pode colocar diversos indicadores um ao lado do outro conforme pode ser visto na figura 01.

Figura 01

Figura 01 - Usando indicadores múltiplos em uma sub janela.

Tal conceito, mostrado lá atrás só é possível quando se faz uso de templates. Por mais que você seja um bom programador, tenha vasto conhecimento em MQL5, você nunca irá conseguir obter o resultado visto na figura 01, sem que de fato compreenda como o MetaTrader 5 funciona. Isto pelo motivo que nem tudo é programação. A programação ela apenas lhe ajuda a montar a solução que de outra forma não é possível. Ela não é, e não deve ser a sua primeira tentativa em tentar criar algo, mas sim uma ferramenta para conseguir chegar ao resultado desejado.

E por que estou dizendo isto ?!?! O motivo é justamente o que é visto no vídeo 01, que se encontra no inicio deste artigo. Você, por melhor que saiba programar, ou por mais que entenda como o MQL5 funciona. Não conseguirá fazer o que é visto no vídeo sem entender como o MetaTrader 5 funciona.

O detalhe nesta história, é que quando o artigo  Indicadores múltiplos em um gráfico (Parte 06): Transformando o MetaTrader 5 em um sistema RAD (II), veio a publico. Naquela época, eu não usava certos conceitos do MetaTrader 5. Ainda estava acorrentado a algumas ideias e conceitos que ao longo do tempo, se mostraram menos adequados. Não estou dizendo que eram errados, mas sim menos adequados. Existem soluções bem melhores a aquela. E esta passa justamente pelo mesmo que foi visto naquele artigo, assim como no artigo anterior,  Indicadores múltiplos em um gráfico (Parte 05): Transformando o MetaTrader 5 em um sistema RAD (I).

Em ambos os casos, pode ser notado que o template foi aberto, e houve uma tentativa de conseguir trabalhar nele. Mas todo aquele trabalho não passou de um simples arranhar de superfície, já que muito do que você vê ali, é uma reprogramação do mesmo template. Isto de forma a emular um sistema RAD que seria conseguido via programação MQL5.

Apesar de aquilo funcionar. Você pode notar que na verdade, o template criado como o MetaTrader 5, era depois, quando o indicador fosse lançado no gráfico, recriado pelo próprio indicador. Com isto, todos os objetos que existiam no template, eram recriados pelo indicador. Desta maneira o MetaTrader 5 conseguia acesso aos objetos presentes ali, podendo assim ajustar e modificar os valores presentes em cada um dos objetos.

Porém o tempo passou, e aquela ideia se mostrou passível de melhorias, por conta disto é que consegui um modelo mais adequado do Chart Trade. Onde fazemos uso de um mínimo de objetos a fim de conseguir suprir toda a demanda. É verdade que ainda será preciso fazer algumas coisas a mais, além do que será visto neste artigo. Mas mesmo assim, você pode notar no vídeo 01, que houve mudanças nos valores, e mesmo assim só temos um único objeto na tela.

E é justamente isto que a programação nos permite fazer. Sem ela, a programação, ficaríamos limitados ao que está disponível no MetaTrader 5. Mas ao fazermos uso da programação, expandimos o que o MetaTrader 5 consegue fazer. Isto usando o que já existe no MetaTrader 5. Ou seja, criamos um template, com exatamente aquilo que desejamos. Lançamos tal template em um OBJ_CHART. Mas sem uma programação adequada, não seria possível mudar os valores presentes nos objetos dentro do template. No entanto, usando a programação, e de maneira correta, resolvemos este inconveniente, expandindo assim o que pode ser possível fazer no MetaTrader 5.

Para compreender adequadamente isto. Será preciso abrir o arquivo de template usado no Chart Trade. Este pode ser visto na integra logo abaixo:

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>

Arquivo do Chart Trade ( Template )

Sei que o conteúdo pode parecer totalmente desnecessário. Mas lembre-se do seguinte: NÃO HAVERÁ ARQUIVO NO ANEXO, todo o sistema será postado de maneira que os arquivos poderão ser conseguidos ao se transcrever os códigos para os respectivos arquivos. O motivo pelo qual estou fazendo assim, é para que você de fato leia e entenda o artigo. Não quero que você simplesmente baixe os arquivo no anexo e use o sistema sem saber o que está usando. Apesar de parecer que o artigo fica consideravelmente maior, isto de fato não acontece. No entanto a explicação fica bem mais detalhada.

Agora quero que você observe com bastante atenção o arquivo de template do Chart Trade. Se você fizer isto com a devida atenção, irá notar que existem linhas onde se encontrará o seguinte conteúdo:

descr=?

Isto acontece em diversos pontos no arquivo template. E isto é feito de maneira proposital. Mas por que ?!?! Apesar de descr ser vista em diversos pontos. Os pontos em que ela aparece como mostrado acima ser referem basicamente a objetos do tipo 107. E o que são estes objetos do tipo 107 ?!?!

Esta descrição sobre os tipos de objetos, apareceu pela primeira vez no artigo:  Indicadores múltiplos em um gráfico (Parte 05): Transformando o MetaTrader 5 em um sistema RAD (I), mas para facilitar você pode ver a tabela presente naquela artigo, aqui novamente, isto logo abaixo:

Valor da variável TYPE Objeto referenciado
102 OBJ_LABEL
103 OBJ_BUTTON
106 OBJ_BITMAP_LABEL
107  OBJ_EDIT
110  OBJ_RECTANGLE_LABEL


Ou seja, um objetos 107, é um objeto OBJ_EDIT. Estes são objetos onde o usuário pode digitar alguma informação.

Tudo bem, mas não é possível você acessar, ou melhor digitar diretamente um valor em um objeto que esteja presente em um template. Isto é fato. Mas então como contornei este problema a fim de conseguir fazer com que o objeto 107, presente no template conseguisse receber valores do indicador ?!?! Para responder esta pergunta, é preciso ver o código da classe responsável por usar o template.


Atualizando a classe C_ChartFloatingRAD

Para conseguir fazer com que o Chart Trade reflita os valores repassados pelo usuário, assim que o indicador for lançado no gráfico. Precisamos fazer algumas manipulações básica. Tais manipulações, tem como finalidade resolver alguns problemas que não são possíveis de serem resolvidos sem o uso de programação. Por conta disto que você precisa compreender profundamente como o MetaTrader 5 funciona. Caso você não compreenda o funcionamento da plataforma, não conseguirá criar o código necessário para contornar estes inconvenientes, que não são possíveis de serem resolvidos sem programação.

O código na integra da classe C_ChartFloatingRAD, pode ser visto logo abaixo. Este código, da forma como se encontra atualmente, permite ao MetaTrader 5, fazer com que o indicador trabalhe como foi visto no vídeo 01. A pergunta é: Você consegue entender como isto está acontecendo ?!?!

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. //+------------------------------------------------------------------+

Código fonte da classe C_ChartFloatingRAD

Observe que praticamente o arquivo C_ChartFloatingRAD não sofreu grandes acréscimos, deste o artigo anterior. Isto também é proposital. Já que se fosse mostrada a versão final deste arquivo, você não iria conseguir compreender como e por que o MetaTrader 5 está conseguindo modificar os valores no template. Isto para que ao abrir a janela de listagem de objetos, CTRL + B, você visse apenas o OBJ_CHART sendo listado. Mas mesmo assim os valores e a janela seriam modificados.

Muito bem. Então vamos entender como e por que o MetaTrader 5 consegue nos informar o que está se passando. Isto via template. Lembre-se deste detalhe: Em nenhum momento iremos deixar de usar o template, e este estará sendo aplicado no objeto OBJ_CHART. Isto acontece no exato momento em que a linha 94 é executada e a linha 95, informa ao MetaTrader 5, para atualizar o OBJ_CHART. Se você se esquecer deste fato, irá ficar procurado coisas que não existem no código. E não existem, pois não está no código. Está de fato no arquivo de template.

Basicamente o código adicionado, pode ser visto entre as linhas 38 e 123. Mas ele está estruturado de maneira que as próximas coisas que serão feitas no próximo artigo, não necessitarão de muitas mudanças, o que é muito bom. Então preste atenção a explicação neste artigo, e você irá entender o próximo muito facilmente. Talvez até consiga prever o que irá ser feito no próximo artigo em termos de programação.

Vamos começar no constructor da classe. Isto por que facilita bastante o entendimento das demais partes. Este constructor se inicia na linha 105. Mas é na linha 109 que começa de fato as mudanças. Nesta linha garantimos que o valor de alavancagem será sempre e sempre maior ou igual a 1. Isto usando o operador ternário. Nada muito difícil ou complicado.

Agora vamos na linha 110. Esta linha, assim como a linha 111, executam na verdade um ajuste no valor a ser mostrado na janela do Chart Trade. O motivo disto é que o usuário, pode lançar um valor que para o ativo no qual o indicador de Chart Trade se encontra, não faz sentido. Por exemplo no caso do dólar futuro, os movimentos são sempre de R$ 5,00 em R$ 5,00 por contrato. Neste caso, não faz sentido você dizer que o take profit ou stop loss será um valor não múltiplo de 5, por exemplo indicar um take profit de R$ 76,00 não faz sentido, pois este valor jamais será alcançado.

Então as linhas 110 e 111, fazem duas chamadas. A primeira irá converter o valor financeiro em pontos. A segunda irá reverter isto, tornando o valor em pontos em um valor financeiro. Você pode achar que isto faz com que o valor retorne ao valor original. Sim é verdade, mas aqui a matemática estará sendo manipulada de forma a converter e ajustar os valores. A primeira chamada irá fazer uso de uma função presente na classe C_Terminal. Mas no caso da segunda, teremos a execução da função presente na linha 98.

Esta função na linha 98 faz uso de apenas uma única linha. A linha 100, esta é na verdade um calculo que irá transformar uma dada quantidade de pontos, em um valor financeiro.

Esta foi a parte fácil. Agora vamos ver a parte mais complicada deste sistema atual.

Uma vez que o constructor alcance a linha 113, teremos algo bastante curioso. Esta linha 113 estará criando um nome de arquivo temporário. Lembre-se este arquivo é, e será temporário. Tal arquivo estará presente na área definida em MQL5\Files, mais uma outra informação, esta informação é criada justamente nesta linha 113.

Uma vez que já temos o nome do arquivo, este criado na linha 113. Passamos para a linha 114. Nesta linha iremos copiar integralmente o conteúdo do arquivo de template ( que pode ser visto no tópico anterior ) para um novo nome. Se tivermos sucesso iremos seguir em frente. Caso esta copia falhe iremos informar isto ao chamador.

Entre as linhas 116 e 119 é onde a mágica acontece. É justamente nesta parte que fazemos com que o indicador Chart Trade, receba os valores que estará sendo informados pelo MetaTrader 5 e/ou pelo usuário. Estas linhas fazem a chamada para a linha 60 do código da classe. Então a partir de agora iremos trabalhar nesta parte do código, já que o restante do constructor foi explicado no artigo anterior. Mas antes de saltar definitivamente para a linha 60, tem um outra linha que foi adicionada no código, a linha 128. Esta irá remover o arquivo criado no constructor. Por conta disto é que informei o fato do arquivo criado ser temporário.

Bem, mas vamos passar para a linha 60. Aqui vamos fazer algo um pouco repetitivo ( ainda estou explicando o básico, então tenha calma ). A primeira coisa será abrir o arquivo "original" ( notem as aspas na palavra ), isto é feito na linha 66. Se tivermos sucesso iremos continuar. Em caso de falha iremos retornar ao chamador.

Na linha 71, iremos criar um arquivo temporário do arquivo temporário, ( isto ficou estanho, mas não tem outra forma de dizer isto ). Caso isto falhe, iremos fechar o arquivo que foi aberto, e retornar ao chamador. Então até a linha 77, tudo que fizemos foi abrir um arquivo e criar um outro. No entanto, se a execução atingir a linha 77, iremos entrar em um loop a fim de copiar todo o arquivo.

Mas espera um pouco. Copiar todo o arquivo ?!?! De novo ?!?! Sim, mas desta vez na linha 81 iremos testar uma condição, esta condição irá verificar se o processo de cópia encontrou um objeto no arquivo de template. Quando isto ocorrer, iremos passar para a linha 38, onde iremos tratar do objeto encontrado. De qualquer forma, se o template que está sendo analisado for o que está no tópico anterior, iremos com toda a certeza fazer este salto para a linha 38. Então mesmo que você queira usar o seu próprio template, poderá faze-lo, desde é claro defina corretamente os nomes que são usados nos objetos.

Uma vez que a rotina presente na linha 38 tenha sido chamada, iremos navegar até a execução chegar na linha 44. Aqui iremos continuar o processo de copiar o arquivo. Da mesma forma como estava sendo feito antes. Porém quando nesta mesma linha 44 for encontrada a linha que fecha o objeto, iremos retornar para o chamador, ou seja a linha 81. Mas vamos no ater por uns instantes nesta rotina presente na linha 38.

Durante o processo de copia, iremos ler o arquivo de origem, na linha 46. Depois disto, iremos decompor o conteúdo desta linha. Caso a linha 47, que faz esta decomposição, informe que temos 2 informações presentes, teremos um novo fluxo de execução. Caso contrário, a linha lida será gravada, e isto é feito na linha 56.

Agora preste atenção ao seguinte ponto: Durante a decomposição que é feita na linha 47, temos no primeiro momento, a variável i0, com um valor igual a zero. Muita atenção a isto. Pois no momento que o nome do objeto for encontrado, a variável i0 passará a ter um valor igual a 1. É neste ponto que mora o perigo. Se você editar manualmente o arquivo de template, deve se certificar que o nome do objeto, irá ser encontrado, antes de qualquer parâmetro do mesmo. O único parâmetro que pode vim antes do nome é o tipo de objeto. Nenhum outro parâmetro deve vim antes do nome. Caso isto aconteça todo o processo irá falhar.

Na linha 50, iremos verificar se i0, está indicando que o objeto procurado foi encontrado. Isto acontece, quando o valor desta variável for igual a 1. Mas temos uma segunda condição, que é o parâmetro procurado, no caso em questão, estaremos sempre procurando a string descr. Quando estas duas condições ocorrerem, iremos gravar o valor que queremos, isto durante o processo de copia. Este tipo de modificação acontece justamente na linha 52. Depois de isto feito iremos retornar ao chamador, ou seja iremos retornar a linha 81.

Observaram como o processo se dá. Iremos copiar todo o arquivo, com exceção de uma linha especifica. Justamente esta linha, irá ser modificada, fazendo com que o template passe a ter novos dados, ou uma aparência diferente.

Quando todo o arquivo tiver sido copiado e modificado, iremos fechar ambos, isto é feito nas linhas 83 e 84. E logo depois na linha 85 iremos tentar renomear o arquivo temporário para o arquivo que a classe espera usar. E o funcionamento será exatamente como visto no vídeo 01.


Conclusão

Neste post expliquei os primeiros passos, que precisamos fazer a fim de conseguir manipular um template. Deste modo ele passará a se adequar ao que precisamos e queremos. Nos permitindo usar uma programação bem mais simples, ao mesmo tempo que usamos de uma forma melhor o MetaTrader 5. Mas a grande sacada, não é exatamente usar o não menos objetos no gráfico. E sim compreender que o MQL5 existe, não para que possamos criar uma plataforma concorrente ao MetaTrader 5, e sim que consigamos tornar o MetaTrader 5, uma plataforma adequada as nossas necessidades.


Arquivos anexados |
Anexo.zip (420.65 KB)
Regressão rede elástica usando descida de coordenadas no MQL5 Regressão rede elástica usando descida de coordenadas no MQL5
Neste artigo, exploraremos a implementação prática da regressão rede elástica (elastic net regularization) para minimizar o sobreajuste e, ao mesmo tempo, separar automaticamente preditores úteis daqueles que possuem pouca força preditiva.
Anotação de dados na análise de série temporal (Parte 2): Criação de conjuntos de dados com rótulos de tendência usando Python Anotação de dados na análise de série temporal (Parte 2): Criação de conjuntos de dados com rótulos de tendência usando Python
Esta série de artigos apresenta várias técnicas destinadas a rotular séries temporais, técnicas essas que podem criar dados adequados à maioria dos modelos de inteligência artificial (IA). A rotulação de dados (ou anotação de dados) direcionada pode tornar o modelo de IA treinado mais alinhado aos objetivos e tarefas do usuário, melhorar a precisão do modelo e até mesmo ajudar o modelo a dar um salto qualitativo!
Desenvolvimento de um Cliente MQTT para o MetaTrader 5: Metodologia TDD (Parte 2) Desenvolvimento de um Cliente MQTT para o MetaTrader 5: Metodologia TDD (Parte 2)
Este artigo faz parte de uma série que descreve as etapas do desenvolvimento de um cliente MQL5 nativo para o protocolo MQTT. Nesta parte, descrevemos como está organizando nosso código, os primeiros arquivos de cabeçalho e classes, e como escrever testes. Este artigo também inclui notas breves sobre o desenvolvimento orientado por testes (Test-Driven Development) e sua aplicação neste projeto.
Redes neurais de maneira fácil (Parte 57): Stochastic Marginal Actor-Critic (SMAC) Redes neurais de maneira fácil (Parte 57): Stochastic Marginal Actor-Critic (SMAC)
Apresentamos um algoritmo relativamente novo, o Stochastic Marginal Actor-Critic (SMAC), que permite a construção de políticas de variáveis latentes no contexto da maximização da entropia.