preview
Do básico ao intermediário: Arquivo template (II)

Do básico ao intermediário: Arquivo template (II)

MetaTrader 5Exemplos |
52 0
CODE X
CODE X

Introdução

No artigo anterior Do básico ao intermediário: Arquivo template (I), começamos a mergulhar em algo muito pouco explorado de forma geral, por boa parte dos programadores aqui no MQL5. Visto que boa parte das pessoas não tem de fato uma ideia de como o MQL5 consegue tornar o MetaTrader 5 um tanto quanto mais interativo com muito menos esforço. Boa parte dos usuários, enxergam o MetaTrader 5 apenas aquilo que podemos observar quando instalamos a plataforma. E por conta disto, muitos não fazem ideia de como de fato o MetaTrader 5 é altamente customizável. Desde é claro você se esforce e dedique tempo para estudar alguns por menores presentes na própria plataforma.

Contudo, não culpo ninguém por não conseguir tirar mais proveito da plataforma. Visto muitos apenas enxerga o que é obvio e constante. Ou seja, a maioria das pessoas, imaginam que podemos apenas e tão somente programar indicadores e expert advisores. E mesmo tais programas, não podem gerar certos tipos de configurações. Dado que a plataforma não nos permite fazer certas coisas. Entretanto, este tipo de pensamento, muito limitado e engessado, não é digno de um verdadeiro programador, ou no mínimo de alguém com uma visão mais ampla do que está ao seu redor. Mas para conseguir fazer com que o MetaTrader 5 seja bem mais do que ele se mostra logo após a sua instalação. Você precisa entender como usar o MQL5. Pois a chave para abrir as portas do paraíso, se encontram de fato nesta local.

Muito bem, como o conteúdo que será visto, pode ser um tanto quanto confuso. Peço a você, que neste momento, se livre de toda e qualquer distração. Isto para que seu foco fique totalmente no que será explicado neste artigo. Pois aqui veremos como usar templates para conseguir acesso a certas "funcionalidades" com bem menos programação.


Arquivo template (II)

No artigo anterior, mostrei como poderíamos copiar, partes das configurações presentes no gráfico principal para um gráfico que seria apresentado no objeto OBJ_CHART. Acredito que você tenha estudado e feito algumas experiências com o que foi mostrado. Porém, aquilo é apenas e tão somente a parte chata e sem graça. A diversão realmente começa quando passamos a explorar os arquivos de configuração de forma mais profunda.

Antes de fazermos isto, preciso nivelar um pouco as coisas. Visto que a experiência de cada um pode ser um tanto quanto variável. Onde muitos podem ter um amplo e vasto conhecimento sobre arquivos de configuração e outros, não fazem a mínima ideia de como interpretar as informações presentes ali. Então antes de começarmos, precisamos antes entender como proceder à programação das configurações diretamente em MQL5. Isto por que, existem coisas que podemos fazer diretamente via arquivos de configuração, enquanto outras só podem ser realmente feitas via programação MQL5. Entender quando, onde e por que usar uma ou outra abordagem, é algo que somente com o tempo, experiência e muita prática, você conseguirá definir qual seria a melhor abordagem a ser adotada. Não estou aqui, para lhe dizer: faça isto, não faça aquilo. Aqui quero mostrar que você pode fazer assim ou daquela outra maneira. A decisão de usar uma ou outra metodologia, depende única e exclusivamente de você. Sendo uma escolha pessoal.

Em artigos anteriores, vimos como integrar indicadores a outros códigos. Os tornando assim recursos internos, de outros códigos. Até o momento, isto somente foi feito no código de indicadores. Mas apesar disto, já temos um tipo de mecanismo do qual podemos utilizar. Também, vimos que podemos manipular o próprio objeto OBJ_CHART, como se fosse uma janela gráfica. Então, que tal se pudermos unir ambas as coisas em um tipo de implementação bem mais interessante? Toda via, preciso lembrar a você, que o conhecimento é acumulativo. E como já falamos sobre classes, mesmo que de maneira bem superficial. Podemos iniciar a implementação, fazendo uso de coisas já exploradas aqui. E com tudo que será feito, já foi em algum momento explicado, não perderei tempo explicado código simples. Assim vamos iniciar com o código visto logo abaixo, sendo este mostrado na íntegra.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. #property description "DEMO Indicator"
05. //+------------------------------------------------------------------+
06. #property indicator_chart_window
07. #property indicator_plots           0
08. //+------------------------------------------------------------------+
09. class C_Chart
10. {
11.     private :
12. //+----------------+
13.         string m_szObject;
14. //+----------------+
15.     public  :
16. //+----------------+
17.         C_Chart()
18.         {
19.             m_szObject = "Demo_" + (string)ObjectsTotal(0, -1, -1);
20.             ObjectCreate(0, m_szObject , OBJ_CHART, 0, 0, 0);
21.             ObjectSetString(0, m_szObject, OBJPROP_SYMBOL, _Symbol);
22.             ObjectSetInteger(0, m_szObject, OBJPROP_XDISTANCE, 0);
23.             ObjectSetInteger(0, m_szObject, OBJPROP_YDISTANCE, 0);
24.             ObjectSetInteger(0, m_szObject, OBJPROP_PERIOD, PERIOD_M15);
25.             ObjectSetInteger(0, m_szObject, OBJPROP_DATE_SCALE, false);
26.             ObjectSetInteger(0, m_szObject, OBJPROP_PRICE_SCALE, false);
27.         }
28. //+----------------+
29.         ~C_Chart()
30.         {
31.             ObjectDelete(0, m_szObject);
32.             ChartRedraw();
33.         }
34. //+----------------+
35.         void Resize(void)
36.         {
37.             ObjectSetInteger(0, m_szObject, OBJPROP_XSIZE, ChartGetInteger(0, CHART_WIDTH_IN_PIXELS) / 2);
38.             ObjectSetInteger(0, m_szObject, OBJPROP_YSIZE, ChartGetInteger(0, CHART_HEIGHT_IN_PIXELS));
39.             ChartRedraw();
40.         }
41. //+----------------+
42. }*gl_Chart = NULL;
43. //+------------------------------------------------------------------+
44. int OnInit(void)
45. {
46.     gl_Chart = new C_Chart();
47. 
48.     return INIT_SUCCEEDED;
49. };
50. //+------------------------------------------------------------------+
51. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
52. {
53.     return rates_total;
54. };
55. //+------------------------------------------------------------------+
56. void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
57. {
58.     switch(id)
59.     {
60.         case CHARTEVENT_CHART_CHANGE:
61.             if (gl_Chart) (*gl_Chart).Resize();
62.             break;
63.     }
64. };
65. //+------------------------------------------------------------------+
66. void OnDeinit(const int reason)
67. {
68.     delete gl_Chart;
69. };
70. //+------------------------------------------------------------------+

Código 01

Ao executarmos este código 01, temos o resultado visto na imagem abaixo.

Imagem 01

Neste ponto, acredito que todos conseguem entender o que está acontecendo. Já que o conteúdo é bem recente, estando assim bem fresco nas mentes sedentas por conhecimento. Pelo menos assim espero. Agora, vamos manter este indicador, visto no código 01, presente no gráfico. E vamos criar um novo código. Este é visto abaixo.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. #property description "DEMO Indicator"
05. //+------------------------------------------------------------------+
06. #property indicator_chart_window
07. #property indicator_applied_price   PRICE_CLOSE
08. #property indicator_buffers         1
09. #property indicator_plots           1
10. #property indicator_type1           DRAW_LINE
11. #property indicator_color1          clrRed
12. #property indicator_style1          STYLE_SOLID
13. #property indicator_width1          3
14. #property indicator_label1          "EMA"
15. //+------------------------------------------------------------------+
16. input uint              def_nPeriods   = 9;           //Period:
17. input ENUM_MA_METHOD    def_MA_Method  = MODE_EMA;    //Method:
18. //+------------------------------------------------------------------+
19. double   Buff_iMA[];
20. int      Handle;
21. //+------------------------------------------------------------------+
22. int OnInit(void)
23. {
24.     SetIndexBuffer(0, Buff_iMA, INDICATOR_DATA);
25.     IndicatorSetString(INDICATOR_SHORTNAME, EnumToString(def_MA_Method) + "_" + (string)def_nPeriods + "_" + EnumToString((ENUM_APPLIED_PRICE)_AppliedTo));
26.     if ((Handle = iMA(NULL, 0, def_nPeriods, 0, def_MA_Method, _AppliedTo)) == INVALID_HANDLE)
27.     {
28.         Print("Could not start the indicator...");
29.         return INIT_FAILED;
30.     };
31. 
32.     return INIT_SUCCEEDED;
33. };
34. //+------------------------------------------------------------------+
35. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
36. {
37.     ArrayInitialize(Buff_iMA, EMPTY_VALUE);
38.     CopyBuffer(Handle, 0, 0, def_nPeriods, Buff_iMA);
39. 
40.     return rates_total;
41. };
42. //+------------------------------------------------------------------+
43. void OnDeinit(const int reason)
44. {
45.     if (Handle != INVALID_HANDLE) 
46.         IndicatorRelease(Handle);
47. };
48. //+------------------------------------------------------------------+

Código 02

Este código 02, também não deve ser difícil de entender, se bem, que a única novidade é como a linha vinte e cinco está criando um nome para a aplicação. Mas isto não deve ser problema aqui. Pelo menos para quem vem estudando o conteúdo dos artigos. Assim, não vejo motivos para mais detalhes. Podendo assim pular para a parte prática. Agora, se pedirmos para o MetaTrader 5, também incluir este código 02 ao gráfico visto na imagem 01, o resultado será este que podemos visualizar na imagem imediatamente abaixo.

Imagem 02

Tudo dentro do esperado e sem nenhuma surpresa. Já é de conhecimento de todos, que podemos unir dois códigos, fazendo com que um seja reconhecido um recurso interno de outro código mais elaborado. Assim, estes códigos 01 e 02, podem ser compilados de maneira separada, sendo integrados posteriormente a um terceiro código, passando a ser um recurso interno deste terceiro código. Porém, e para não complicar as coisas, mantendo naquilo que podemos chamar de um nível adequado e didático. Vamos fazer algo um pouco diferente, tornando o código 02, um recurso interno do código 01. Nascendo assim o código que podemos visualizar logo a seguir.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. #property description "DEMO Indicator"
05. //+------------------------------------------------------------------+
06. #property indicator_chart_window
07. #property indicator_plots           0
08. //+------------------------------------------------------------------+
09. class C_Chart
10. {
11.     private :
12. //+----------------+
13.         string m_szObject;
14. //+----------------+
15.     public  :
16. //+----------------+
17.         C_Chart()
18.         {
19.             m_szObject = "Demo_" + (string)ObjectsTotal(0, -1, -1);
20.             ObjectCreate(0, m_szObject , OBJ_CHART, 0, 0, 0);
21.             ObjectSetString(0, m_szObject, OBJPROP_SYMBOL, _Symbol);
22.             ObjectSetInteger(0, m_szObject, OBJPROP_XDISTANCE, 0);
23.             ObjectSetInteger(0, m_szObject, OBJPROP_YDISTANCE, 0);
24.             ObjectSetInteger(0, m_szObject, OBJPROP_PERIOD, PERIOD_M15);
25.             ObjectSetInteger(0, m_szObject, OBJPROP_DATE_SCALE, false);
26.             ObjectSetInteger(0, m_szObject, OBJPROP_PRICE_SCALE, false);
27.         }
28. //+----------------+
29.         ~C_Chart()
30.         {
31.             ObjectDelete(0, m_szObject);
32.             ChartRedraw();
33.         }
34. //+----------------+
35.         void Resize(void)
36.         {
37.             ObjectSetInteger(0, m_szObject, OBJPROP_XSIZE, ChartGetInteger(0, CHART_WIDTH_IN_PIXELS) / 2);
38.             ObjectSetInteger(0, m_szObject, OBJPROP_YSIZE, ChartGetInteger(0, CHART_HEIGHT_IN_PIXELS));
39.             ChartRedraw();
40.         }
41. //+----------------+
42. }*gl_Chart = NULL;
43. //+------------------------------------------------------------------+
44. #define def_Resource "Code 02.ex5"
45. //+------------------------------------------------------------------+
46. #resource def_Resource
47. //+------------------------------------------------------------------+
48. int OnInit(void)
49. {
50.     gl_Chart = new C_Chart();
51.     ChartIndicatorAdd(0, 0, iCustom(NULL, NULL, "::" + def_Resource));
52. 
53.     return INIT_SUCCEEDED;
54. };
55. //+------------------------------------------------------------------+
56. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
57. {
58.     return rates_total;
59. };
60. //+------------------------------------------------------------------+
61. void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
62. {
63.     switch(id)
64.     {
65.         case CHARTEVENT_CHART_CHANGE:
66.             if (gl_Chart) (*gl_Chart).Resize();
67.             break;
68.     }
69. };
70. //+------------------------------------------------------------------+
71. void OnDeinit(const int reason)
72. {
73.     delete gl_Chart;
74. };
75. //+------------------------------------------------------------------+

Código 03

Este código 03, é um tanto quanto grosseiro. Podendo e devendo ser refinado, para ser um tanto quanto mais simpático. Porém, para o que quero explicar, ele está adequado. Agora preste atenção: Se você não consegue entender o que este código 03 está fazendo, apenas olhando para ele. Peço que você procure ler e estudar os artigos anteriores. Pois entender o que este código 03 está fazendo, apenas olhando para ele, é algo muito importante aqui. Não pense que você já sabe, apenas por que imagina já saber das coisas. É realmente necessário entender o funcionamento deste código 03, para entender o restante do artigo.

Para aqueles que sabem o que este código 03 faz, não é preciso olhar o resultado da execução. Já que ele será o mesmo que pode ser visto na imagem 02. Portanto, não vou me dar ao trabalho de replicar novamente a mesma imagem novamente. Mas é aqui onde as coisas começam a ficar interessantes.

Observe atentamente a linha cinquenta e um do código 03. No artigo anterior, vimos que poderíamos copiar dados de configuração do gráfico principal para dentro do gráfico criado por um objeto OBJ_CHART. Vimos que isto seria possível, justamente por conta de um detalhe que precisa ser executado no nosso código. Onde conseguíamos pedir ao MetaTrader 5, a identidade do gráfico no objeto OBJ_CHART. Fazendo isto, poderíamos usar as mesmas chamadas que utilizávamos para ajustar as configurações do gráfico principal, para ajustar as configurações do gráfico presente no objeto OBJ_CHART. Até este ponto, acredito que estamos entendidos.

Agora a parte interessante: O primeiro argumento da chamada vista na linha cinquenta e um, é justamente a identidade do gráfico que receberá o indicador. Se você não entendeu, veja a documentação para mais detalhes. Agora vem a questão: O que acontece se pegarmos a identidade do gráfico, criado e mantido pelo objeto OBJ_CHART, e o repassarmos como sendo este primeiro argumento da linha cinquenta e um? Lembrando que o primeiro argumento é a identidade do gráfico no qual o indicador deverá colocado. Você poderia dizer: Bem, acredito que o MetaTrader 5 colocará o indicador que estamos informando na linha cinquenta e um, ao gráfico criado pelo objeto OBJ_CHART. O que de fato não estaria totalmente errado. Já que esta resposta demonstraria que você conseguiu compreender o funcionamento das coisas até este ponto. Porém, vamos ver se isto acontecerá na prática. Para tal, modificamos o código 03 como mostrado logo abaixo.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. #property description "DEMO Indicator"
05. //+------------------------------------------------------------------+
06. #property indicator_chart_window
07. #property indicator_plots           0
08. //+------------------------------------------------------------------+
09. #define def_Resource "Code 02.ex5"
10. //+------------------------------------------------------------------+
11. #resource def_Resource
12. //+------------------------------------------------------------------+
13. class C_Chart
14. {
15.     private :
16. //+----------------+
17.         string m_szObject;
18. //+----------------+
19.         void  Proc(long id)
20.         {
21.             Print("ID informed: ", id);
22.             Print("Result: ", ChartIndicatorAdd(id, 0, iCustom(NULL, NULL, "::" + def_Resource)));
23.             ChartRedraw(id);
24.         }
25. //+----------------+
26.     public  :
27. //+----------------+
28.         C_Chart()
29.         {
30.             m_szObject = "Demo_" + (string)ObjectsTotal(0, -1, -1);
31.             ObjectCreate(0, m_szObject , OBJ_CHART, 0, 0, 0);
32.             ObjectSetString(0, m_szObject, OBJPROP_SYMBOL, _Symbol);
33.             ObjectSetInteger(0, m_szObject, OBJPROP_XDISTANCE, 0);
34.             ObjectSetInteger(0, m_szObject, OBJPROP_YDISTANCE, 0);
35.             ObjectSetInteger(0, m_szObject, OBJPROP_PERIOD, PERIOD_M15);
36.             ObjectSetInteger(0, m_szObject, OBJPROP_DATE_SCALE, false);
37.             ObjectSetInteger(0, m_szObject, OBJPROP_PRICE_SCALE, false);
38.         }
39. //+----------------+
40.         ~C_Chart()
41.         {
42.             ObjectDelete(0, m_szObject);
43.             ChartRedraw();
44.         }
45. //+----------------+
46.         void Resize(void)
47.         {
48.             ObjectSetInteger(0, m_szObject, OBJPROP_XSIZE, ChartGetInteger(0, CHART_WIDTH_IN_PIXELS) / 2);
49.             ObjectSetInteger(0, m_szObject, OBJPROP_YSIZE, ChartGetInteger(0, CHART_HEIGHT_IN_PIXELS));
50.             ChartRedraw();
51.         }
52. //+----------------+
53.         void AddIndicator()
54.         {
55.             Proc(ObjectGetInteger(0, m_szObject, OBJPROP_CHART_ID));
56.             Proc(ChartID());
57.         }
58. //+----------------+
59. }*gl_Chart = NULL;
60. //+------------------------------------------------------------------+
61. int OnInit(void)
62. {
63.     gl_Chart = new C_Chart();
64.     (*gl_Chart).AddIndicator();
65. 
66.     return INIT_SUCCEEDED;
67. };
68. //+------------------------------------------------------------------+
69. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
70. {
71.     return rates_total;
72. };
73. //+------------------------------------------------------------------+
74. void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
75. {
76.     switch(id)
77.     {
78.         case CHARTEVENT_CHART_CHANGE:
79.             if (gl_Chart) (*gl_Chart).Resize();
80.             break;
81.     }
82. };
83. //+------------------------------------------------------------------+
84. void OnDeinit(const int reason)
85. {
86.     delete gl_Chart;
87. };
88. //+------------------------------------------------------------------+

Código 04

Agora atenção, pois entender a explicação, lhe ajudará a compreender por que precisaremos fazer as coisas de outra maneira. Isto para conseguir obter o resultado pretendido. Mas antes, de fazer isto, vamos ver o resultado da execução do código 04.

Imagem 03

Nesta imagem estou demarcando duas regiões. Cada uma está mostrando com uma seta a origem das informações destacadas. Para entender adequadamente estas informações, precisaremos voltar a nossa atenção ao código 04. Na linha sessenta e quatro, temos uma chamada a um procedimento interno da classe. Estamos fazendo assim para não precisarmos retirar, ou melhor dizendo, buscar, nenhuma informação dentro da classe. Apenas usaremos as informações contidas nela. Dentro do procedimento chamado, temos duas linhas que executarão o que está sendo implementado no procedimento da linha dezenove. Está é a parte importante do código. Note que a única diferença entre as linhas cinquenta e cinco e cinquenta e seis, é justamente o tipo de argumento que será repassado.

Mas que tipo de informação estamos repassando aqui? Bem, se você entendeu o artigo anterior, sabe que nesta linha cinquenta e cinco estamos capturando a identidade do gráfico no objeto OBJ_CHART. Já na linha cinquenta e seis, estamos capturando a identidade do gráfico principal. Resumindo, não importa o que o procedimento da linha dezenove fará. Em todos os casos, estamos repassando a informação correta e necessária para dentro do procedimento. Note que na linha vinte e um, estamos imprimindo o valor da identidade informada. Contudo, a linha vinte e dois é onde as coisas realmente se fazem necessárias.

Nos artigos onde falamos integrar um indicador a outro código, vimos uma das formas de se fazer isto. Sendo que uma delas, é justamente esta que estamos utilizando aqui. Que seria a utilização da função de biblioteca ChartIndicadorAdd. Note que se a função obtiver sucesso no processamento por parte do MetaTrader 5, termos impresso no terminal esta confirmação. Se a função falhar, por qualquer motivo, teremos também uma informação sendo impressa no terminal. No entanto, necessito que seja entendido que a única diferença na execução, se dá justamente por um canal apontarmos para o gráfico do objeto OBJ_CHART, e em outro canal, apontarmos para o gráfico principal. E com isto obtemos o que é visto na imagem 03. Mostrando que quando tentamos adicionar um indicador ao gráfico do objeto OBJ_CHART, a função falhará. Mas se tentarmos fazer o mesmo, só que apontando para o gráfico principal, a função terá sucesso.

Isto significa que não podemos adicionar um indicador a um gráfico criado e mantido por um objeto OBJ_CHART. Mas espere, isto não é de todo verdadeiro. Já que olharmos para outros artigos de sua autoria, será constatado que de alguma forma, eu conseguia adicionar um indicador a um gráfico criado e mantido por um objeto OBJ_CHART. Como isto é possível? De fato, é mesmo possível adicionar um indicador, ou vários se você assim desejar a um gráfico criado e mantido por um objeto OBJ_CHART.

Porém, os mecanismos utilizados não são estes dos quais estamos vendo neste momento. O fato de você não encontrar referências de como fazer isto, se deve justamente ao motivo que você acabou de observar sendo feito neste código 04. Muitos programadores imaginam que poderiam utilizar este mecanismo mostrado no código para conseguir adicionar um ou mais indicadores a um gráfico dentro do objeto OBJ_CHART. Entretanto, qualquer tentativa de se fazer isto, da forma como foi mostrada aqui, falhará miseravelmente. E é neste ponto em que começaremos a trabalhar com os tais arquivos de configuração.

Agora começaremos a seguir por um caminho totalmente diferente. Contudo, o resultado será muito interessante. Além é claro, permitir que criemos quase qualquer tipo de coisa imaginada.

Agora esqueça a programação por um instante. Vamos entender outra coisa antes. Muitos operadores e usuários de plataformas de negociação, assim como o MetaTrader 5, tem em seu domínio diversas configurações diferentes, de diferentes setups, para conseguir ter agilidade ao precisar trocar as configurações do gráfico. Dentro destes arquivos de configuração, podemos ter diversas coisas sendo embutidas. Mas vamos ficar apenas no básico por hora.

Dentre estas coisas, estão listas de indicadores que podem ou não estar sendo colocados em uma sub janela, entre outras coisas. Acredito que mesmo você, já deve ter criado tais configurações gráficas. Mas no geral elas não se limitam a serem aplicadas apenas e tão somente no gráfico principal. Podemos, desde que tomemos alguns cuidados, serem aplicadas também em um objeto OBJ_CHART.

Cara, que coisa maluca é esta que você está me dizendo. Se entendi bem, você está dizendo que podemos criar uma daquelas configurações, usando diversos indicadores diferentes e depois adicionar isto a um objeto OBJ_CHART. É isto mesmo? Sim, meu caro leitor. É isto mesmo que você entendeu. Aqueles arquivos de configuração, podem desde que tomados certos cuidados, serem aplicados a um objeto OBJ_CHART. E para provar que isto é verdade, vamos ver o passo a passo de como fazer isto. Detalhe: Aqui considerarei que você não faz a mínima ideia de como criar e acessar um arquivo de configuração. Então vamos ver como fazer as coisas.

Em primeiro lugar, utilizaremos o gráfico o mais limpo possível. Ou seja, não temos nenhum indicador presente nele. Sendo apresentando como mostrado logo abaixo.

Imagem 04

Ótimo. Agora adicionamos apenas e somente um único indicador a este gráfico. No caso, adicionaremos o indicador criado no código 02. Já que o objetivo é demonstrar como fazer as coisas, na prática. Assim o resultado é o que podemos ver logo abaixo.

Animação 01

Muito bem, agora preste atenção, pois cada caso é um caso. Em alguns casos, precisaremos manipular a janela, antes mesmo de salvarmos esta configuração criada nisto que podemos ver sendo feito na animação 01. Em outros casos não precisaremos manipular nenhuma outra coisa, podendo salvar logo em seguida a configuração que acabamos de criar. E este é um destes casos, onde podemos salvar logo depois a configuração criada. Para fazermos isto, selecionamos o que é visto na imagem logo a seguir.

Imagem 05

Isto abrirá a janela para poderemos informar o nome do arquivo template. Você pode dar qualquer nome. Porém, como você está aprendendo a fazer as coisas, sugiro dar um nome fácil de lembrar, para depois lembrar o motivo pelo qual o template foi criado. Assim no final teremos o que é visto na imagem logo abaixo.

Imagem 06

Agora temos um novo template disponível, e este está sendo mostrado nesta região demarcada em verde na imagem 06. Sempre que você criar um novo template, ele aparecerá aqui. Podendo assim ser aplicado a qualquer gráfico sempre que necessário. Porém, e é importante que você entenda isto, um template somente será aplicado de maneira plena, se todos os códigos presentes nele estiverem disponíveis no momento de sua colocação no gráfico. Mas como aqui estamos apenas praticando. Não existem efeitos colaterais dos quais precisaremos nos preocupar. Tendo feito isto, estamos prontos para a segunda parte. E esta vez voltarmos a nossa atenção para a parte referente a codificação em MQL5.

Para tornar as coisas simples de serem entendida, faremos uma pequena brincadeira aqui. Já sabemos que o código 04, não consegue efetuar o tipo de atividade que desejamos implementar. Isto é fato. Porém, se o modificarmos de maneira controlada, podemos fazer com que ele consiga gerar o tipo de resultado que pretendemos. No entanto, como quero que você, compreenda como as coisas funcionam, não faremos a mudança em um único passo. Primeiro, criaremos um código para demonstrar o tipo de resultado que pretendemos gerar. Mesmo que a implementação não seja algo assim tão utilizável no dia a dia, ela servirá para que você entenda o conceito a ser adotado. Para isto, usaremos o código visto logo abaixo.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. #property description "DEMO Indicator"
05. //+------------------------------------------------------------------+
06. #property indicator_chart_window
07. #property indicator_plots           0
08. //+------------------------------------------------------------------+
09. int OnInit(void)
10. {
11.     ChartApplyTemplate(0, "Testing.tpl");
12. 
13.     return INIT_SUCCEEDED;
14. };
15. //+------------------------------------------------------------------+
16. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
17. {
18.     return rates_total;
19. };
20. //+------------------------------------------------------------------+

Código 05

Este código 05 servirá muito bem para você entender uma coisa importante sobre templates. Note que este código é realmente muito simples. Porém, esta linha onze, tem um peso muito grande no resultado que apresentado quando este código for aplicado a algum gráfico. Nesta linha estamos dizendo para o MetaTrader 5 aplicar ao gráfico o template que salvamos a pouco. Agora preste muita atenção, pois isto é muito importante mesmo. Quando o MetaTrader 5, aplicar o template ao gráfico, ele fará com que toda e qualquer configuração do gráfico, antes da execução da linha onze, seja descartada. Assim, a própria presença do indicador criado neste código será considerada algo descartável. Ou seja, assim que o template estiver ativo, a presença deste código já não será mais observada. Para entender isto veja a animação logo a seguir.

Animação 02

Note que, no indicador, temos como nome CODE 05. Porém, devido à linha onze, assim que verificamos quais indicadores estão presentes no gráfico, notaremos que não se trata do CODE 05, mas sim do CODE 02. Por quê? O motivo é justamente que ao aplicamos o template na linha onze do código 05, o mesmo será removido do gráfico. E toda e qualquer configuração do gráfico, incluindo indicadores ou Expert Advisor, que estiverem presentes no gráfico, serão removidos e no lugar será aplicada as configurações presentes no arquivo template.

Esta é a parte conceitual que você precisa compreender. Existem algumas pequenas limitações na utilização deste conceito. Porém, tais limitações não nos atrapalharão naquilo que desejamos fazer neste momento. Agora a parte divertida. Esta função ChartApplyTemplate, necessita de dois parâmetros. Sendo que o segundo parâmetro, obviamente se refere ao template que será aplicado ao gráfico. Mas, e quanto ao primeiro parâmetro. A que ele se refere? Bem, este primeiro parâmetro indica qual a identidade do gráfico receberá o template. E por que isto pode ser considerado a parte divertida?

O motivo é simples. Lembra da demonstração que o código 04 NÃO CONSEGUE adicionar um indicador ao gráfico criado e mantido por um objeto OBJ_CHART? Pois bem, se modificarmos o código 04, de maneira a podermos utilizar o que é visto na linha onze deste código 05, passaremos a ter a possibilidade de manipular, mesmo que com algumas limitações, algumas coisas, no gráfico do objeto OBJ_CHART. E como o código 05 funcionou, e apenas queremos levar o mesmo conceito para dentro do código 04. Modificaremos o código 04 de forma que ele ficará como mostrado logo abaixo.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. #property description "DEMO Indicator"
05. //+------------------------------------------------------------------+
06. #property indicator_chart_window
07. #property indicator_plots           0
08. //+------------------------------------------------------------------+
09. #define def_Resource "Code 02.ex5"
10. //+------------------------------------------------------------------+
11. #resource def_Resource
12. //+------------------------------------------------------------------+
13. class C_Chart
14. {
15.     private :
16. //+----------------+
17.         string m_szObject;
18. //+----------------+
19.         void  Proc(long id)
20.         {
21.             Print("ID informed: ", id);
22.             Print("Result: ", ChartIndicatorAdd(id, 0, iCustom(NULL, NULL, "::" + def_Resource)));
23.             ChartApplyTemplate(id, "Testing.tpl");
24.             ChartRedraw(id);
25.         }
26. //+----------------+
27.     public  :
28. //+----------------+
29.         C_Chart()
30.         {
31.             m_szObject = "Demo_" + (string)ObjectsTotal(0, -1, -1);
32.             ObjectCreate(0, m_szObject , OBJ_CHART, 0, 0, 0);
33.             ObjectSetString(0, m_szObject, OBJPROP_SYMBOL, _Symbol);
34.             ObjectSetInteger(0, m_szObject, OBJPROP_XDISTANCE, 0);
35.             ObjectSetInteger(0, m_szObject, OBJPROP_YDISTANCE, 0);
36.             ObjectSetInteger(0, m_szObject, OBJPROP_PERIOD, PERIOD_M15);
37.             ObjectSetInteger(0, m_szObject, OBJPROP_DATE_SCALE, false);
38.             ObjectSetInteger(0, m_szObject, OBJPROP_PRICE_SCALE, false);
39.         }
40. //+----------------+
41.         ~C_Chart()
42.         {
43.             ObjectDelete(0, m_szObject);
44.             ChartRedraw();
45.         }
46. //+----------------+
47.         void Resize(void)
48.         {
49.             ObjectSetInteger(0, m_szObject, OBJPROP_XSIZE, ChartGetInteger(0, CHART_WIDTH_IN_PIXELS) / 2);
50.             ObjectSetInteger(0, m_szObject, OBJPROP_YSIZE, ChartGetInteger(0, CHART_HEIGHT_IN_PIXELS));
51.             ChartRedraw();
52.         }
53. //+----------------+
54.         void AddIndicator()
55.         {
56.             Proc(ObjectGetInteger(0, m_szObject, OBJPROP_CHART_ID));
57.             Proc(ChartID());
58.         }
59. //+----------------+
60. }*gl_Chart = NULL;
61. //+------------------------------------------------------------------+
62. int OnInit(void)
63. {
64.     gl_Chart = new C_Chart();
65.     (*gl_Chart).AddIndicator();
66. 
67.     return INIT_SUCCEEDED;
68. };
69. //+------------------------------------------------------------------+
70. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
71. {
72.     return rates_total;
73. };
74. //+------------------------------------------------------------------+
75. void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
76. {
77.     switch(id)
78.     {
79.         case CHARTEVENT_CHART_CHANGE:
80.             if (gl_Chart) (*gl_Chart).Resize();
81.             break;
82.     }
83. };
84. //+------------------------------------------------------------------+
85. void OnDeinit(const int reason)
86. {
87.     delete gl_Chart;
88. };
89. //+------------------------------------------------------------------+

Código 06

Agora preste atenção, pois isto costuma dar uma bela surra em muita gente. Tudo que foi modificado no código 04 a fim de criar este código 06, foi a adição da linha vinte e três neste código 06. Porém, toda via e, entretanto, você precisa lembrar do que aconteceu quando o código 05 foi executado. Entender isto, é de suma importância. Pois apesar de este código 06, estar tentando fazer uso de um conceito que realmente pode ser aplicado. Fazer as coisas como mostrado aqui no código 06, não implicará na correta resposta que você espera obter do código. Ou seja, apesar de tudo parecer perfeito e muito funcional.

No final este código 06, com toda a sua complexidade, terá como resultado o mesmo obtenível com um código consideravelmente mais simples. Visto que quando ele for executado, o resultado será o mesmo que obteremos ao executar o código 05. Mas, e então, como podemos fazer com que as coisas funcionem como desejamos? Onde possamos conseguir incluir um indicador a um gráfico criado e mantido em um objeto OBJ_CHART? Bem, esta é a parte confusa, que muitos não compreendem. E a resposta é:

Não tente criar algo genérico. Para conseguir resultados específicos, você precisará utilizar mecanismos específicos.

E o que esta frase que nos dizer? Ela nos diz que para cada tipo de problema, precisamos de um tipo de solução que atenda e consiga resolver aquele e tão somente aquele problema especificamente. Muitos iniciantes têm como praxe, copiar e colar trechos de código em seus próprios códigos, e isto tem se agravado graças ao uso de inteligência artificial para codificar as coisas. Apesar de isto funcionar, e em muitas das vezes, este tipo de coisa falha miseravelmente, quando precisamos que as coisas funcionem de uma maneira muito específica.

Por conta disto, apesar da euforia de muita gente com relação as tais inteligências artificiais, para ajudar na programação, tais sistema são pouco viáveis. Já que eles tendem a criar soluções genéricas. E quando precisamos de algo específico, tais sistemas não passam de pura perda de tempo. Já que sem entender o conceito que precisa ser utilizado, você acabará em uma rua sem saída, esperando que tais GPT's gerem uma resposta adequada e resolva o seu problema. Coisa que não acontecerá.

Então como podemos resolver esta questão mostrado neste artigo? Para conseguir isto, precisemos abandonar a esperança de usar qualquer GPT para criar códigos. E procurar estudar e praticar programação como era feito no passado. Sei que isto pode parecer uma tarefa cansativa e tediosa. Mas no final, você conseguirá enxergar a solução, enquanto todos estão lutando para tentar entender por que a solução funciona ou não funciona.

O problema do código 06 não está na utilização da linha vinte e três em si. O problema está na interação do próprio código com ele mesmo. Mas como assim? Agora fiquei confuso. Veja bem, meu caro leitor, por que motivos a linha cinquenta e sete está sendo executada neste código 06? Bem, ela está sendo executada, justamente para que na linha vinte e dois tenhamos a aplicação do indicador integrado ao gráfico. Porém, se este é o objetivo, por que então, mesmo sabendo que o indicador integrado será colocado no gráfico, precisamos da linha vinte e três sendo executada neste? Isto não faz muito sentido. Já que a linha vinte e dois conseguiu obter sucesso devido justamente ao fato de que estamos adicionando algo, que se encontra embutido no código, no caso o indicador CODE 02. Como você claramente deve notar ao olhar a linha onze. Novamente, estou considerando que você tenha lido e compreendido os artigos anteriores, para entender do que estou falando neste momento.

Sabendo que a linha vinte e dois terá sucesso, quando aplicarmos as coisas ao gráfico principal. Não faz sentido usar a linha vinte e três para aplicar o template, que fatalmente removerá o código do gráfico. Impedindo assim que o gráfico criado pelo objeto OBJ_CHART receba o template que estamos querendo utilizar, certo? Então apenas para demonstrar que de fato este código 06 funciona, modificamos o mesmo, como mostrado logo abaixo.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. #property description "DEMO Indicator"
05. //+------------------------------------------------------------------+
06. #property indicator_chart_window
07. #property indicator_plots           0
08. //+------------------------------------------------------------------+
09. #define def_Resource "Code 02.ex5"
10. //+------------------------------------------------------------------+
11. #resource def_Resource
12. //+------------------------------------------------------------------+
13. class C_Chart
14. {
15.     private :
16. //+----------------+
17.         string m_szObject;
18. //+----------------+
19.         void  Proc(long id)
20.         {
21.             if (!ChartIndicatorAdd(id, 0, iCustom(NULL, NULL, "::" + def_Resource)))
22.                 ChartApplyTemplate(id, "Testing.tpl");
23.             ChartRedraw(id);
24.         }
25. //+----------------+
26.     public  :
27. //+----------------+
28.         C_Chart()
29.         {
30.             m_szObject = "Demo_" + (string)ObjectsTotal(0, -1, -1);
31.             ObjectCreate(0, m_szObject , OBJ_CHART, 0, 0, 0);
32.             ObjectSetString(0, m_szObject, OBJPROP_SYMBOL, _Symbol);
33.             ObjectSetInteger(0, m_szObject, OBJPROP_XDISTANCE, 0);
34.             ObjectSetInteger(0, m_szObject, OBJPROP_YDISTANCE, 0);
35.             ObjectSetInteger(0, m_szObject, OBJPROP_PERIOD, PERIOD_M15);
36.             ObjectSetInteger(0, m_szObject, OBJPROP_DATE_SCALE, false);
37.             ObjectSetInteger(0, m_szObject, OBJPROP_PRICE_SCALE, false);
38.         }
39. //+----------------+
40.         ~C_Chart()
41.         {
42.             ObjectDelete(0, m_szObject);
43.             ChartRedraw();
44.         }
45. //+----------------+
46.         void Resize(void)
47.         {
48.             ObjectSetInteger(0, m_szObject, OBJPROP_XSIZE, ChartGetInteger(0, CHART_WIDTH_IN_PIXELS) / 2);
49.             ObjectSetInteger(0, m_szObject, OBJPROP_YSIZE, ChartGetInteger(0, CHART_HEIGHT_IN_PIXELS));
50.             ChartRedraw();
51.         }
52. //+----------------+
53.         void AddIndicator()
54.         {
55.             Proc(ObjectGetInteger(0, m_szObject, OBJPROP_CHART_ID));
56.             Proc(ChartID());
57.         }
58. //+----------------+
59. }*gl_Chart = NULL;
60. //+------------------------------------------------------------------+
61. int OnInit(void)
62. {
63.     gl_Chart = new C_Chart();
64.     (*gl_Chart).AddIndicator();
65. 
66.     return INIT_SUCCEEDED;
67. };
68. //+------------------------------------------------------------------+
69. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
70. {
71.     return rates_total;
72. };
73. //+------------------------------------------------------------------+
74. void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
75. {
76.     switch(id)
77.     {
78.         case CHARTEVENT_CHART_CHANGE:
79.             if (gl_Chart) (*gl_Chart).Resize();
80.             break;
81.     }
82. };
83. //+------------------------------------------------------------------+
84. void OnDeinit(const int reason)
85. {
86.     delete gl_Chart;
87. };
88. //+------------------------------------------------------------------+

Código 07

Observe o que foi feito no código 07. Antes a função ChartApplyTemplate era executada independentemente da função ChartIndicatorAdd ter tido ou não sucesso. Agora a mesma chamada ChartApplyTemplate somente será executada, caso ChartIndicadorAdd não tenha sucesso. Lembrando que o objetivo a didática. Então não tente usar o que foi visto aqui, em algo mais complexo. Pois não funcionará. E volto a ressaltar que, cada caso é um caso. No entanto, apesar da descrença de muitos a respeito do tipo de resultado que poderemos conseguir. O resultado é mesmo bastante surpreendente, podendo ser visto na animação logo abaixo.

Animação 03

Observe que de fato conseguimos, com que o indicador do código 02, fosse aplicado a um gráfico de um objeto OBJ_CHART. E apesar de muitos imaginarem que este indicador não seja funcional. Ele de fato funcionará perfeitamente bem. Mas tem um detalhe:

O indicador presente em um gráfico mantido e criado por um objeto OBJ_CHART, NÃO SERÁ LISTADO em meio a outros indicadores.

Isto que foi dito, pode ser observado ao pedirmos para ver a lista de indicadores. No caso da animação 03, a lista é a que podemos ver na imagem logo abaixo.

Imagem 07


Considerações finais

Neste artigo, vimos que nem tudo é como parecer ser à primeira vista. Apesar do que foi visto aqui, ser algo que a princípio possa parecer ser muito complicado e difícil de ser feito. Acredito ter alcançado o objetivo de mostrar e explicar que entender MQL5 é primordial para se conseguir usar o MetaTrader 5 de uma forma melhor.

Apesar de conseguirmos colocar indicadores em um gráfico pertencente a um objeto OBJ_CHART, a solução adotada não é adequada a todas as situações.

No próximo artigo exploraremos ainda mais o que foi mostrado aqui, permitindo criar soluções ainda melhores e com muito menos trabalho.
Arquivo MQ5Descrição
Indicators\Code 01 Demonstração básica
Indicators\Code 02 Demonstração básica
Indicators\Code 03 Demonstração básica
Indicators\Code 04 Demonstração básica
Indicators\Code 05 Demonstração básica
Indicators\Code 06 Demonstração básica
Indicators\Code 07 Demonstração básica
Arquivos anexados |
Estratégias de Reversão à Média com RSI2 de Larry Connors para Day Trading Estratégias de Reversão à Média com RSI2 de Larry Connors para Day Trading
Larry Connors é um trader e autor renomado, mais conhecido por seu trabalho em trading quantitativo e estratégias como o RSI de 2 períodos (RSI2), que ajuda a identificar condições de sobrecompra e sobrevenda de curto prazo no mercado. Neste artigo, primeiro explicaremos a motivação por trás de nossa pesquisa, depois recriaremos três das estratégias mais famosas de Connors em MQL5 e as aplicaremos ao trading intradiário do CFD do índice S&P 500.
Rede neural na prática: Retro propagação manual Rede neural na prática: Retro propagação manual
Neste artigo, começaremos a ter uma base de como a retro propagação funciona. Entender esta base, é necessária para se conseguir compreender, como diversos perceptrons conseguem ajustar seus parâmetros individualmente, mesmo quando temos uma quantidade arbitrária deles presentes em uma rede. O objetivo aqui, não será implementar a retro propagação, mas criar um mecanismo simples para que você consiga entender como ela funciona.
Introdução ao MQL5 (Parte 14): Guia para Iniciantes na Criação de Indicadores Personalizados (III) Introdução ao MQL5 (Parte 14): Guia para Iniciantes na Criação de Indicadores Personalizados (III)
Aprenda a construir um indicador de Padrões Harmônicos em MQL5 usando objetos de gráfico. Descubra como detectar pontos de swing, aplicar retrações de Fibonacci e automatizar o reconhecimento de padrões.
Rede neural na prática: Iniciando a corrente Rede neural na prática: Iniciando a corrente
Chegou a hora de começarmos a ver e entender como ligar perceptrons em uma cadeia. Isto a fim de conseguir implementar o que conhecemos como sendo rede perceptron. Esta rede é a base de tudo aquilo que você conhece e utiliza como sendo algum tipo de "inteligência artificial". Mas construir tal rede envolve diversos desafios. Aqui vamos começar a ver que desafios são estes.