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

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

MetaTrader 5Exemplos |
19 0
CODE X
CODE X

Introdução

No artigo anterior Do básico ao intermediário: Arquivo template (II), vimos como poderíamos adicionar um indicador a um gráfico presente em um objeto OBJ_CHART. Se você não leu aquele artigo, sugiro que pare neste momento a leitura e primeiro leia o artigo anterior. Pois entender o que foi explicado naquele artigo, é de suma importância para acompanhar o que será visto aqui.

Lembrando que, apesar de não estarmos implementando nenhum tipo de aplicação específica. Todo e qualquer conhecimento já mencionado em artigos anteriores, não será novamente repetido aqui. Sendo assim, em caso de dúvida sobre algum ponto, volte nos artigos anteriores para tentar conseguir acompanhar o material que está sendo explorado.

Então se prepare, pois aqui aprofundaremos no que foi explicado no artigo anterior, dando enfase a resolver algumas questões de forma mais abrangente. Assim, chegou a hora de se afastar de qualquer tipo de distração e focar única e exclusivamente no que será explicado aqui. Pois agora o bicho vai pegar.


Arquivo template (III)

O que foi visto no artigo anterior é apenas e tão somente um pequeno vislumbre do que realmente podemos fazer. Apesar de muitos iniciantes, e até programadores com já alguma experiência, imaginarem ser totalmente impossível de se fazer certas coisas. A verdade, é que nem tudo é, ou poderá ser conseguido, fazendo uso única e exclusivamente da programação MQL5. Em geral, o MQL5 é ótimo para nos permitir dizer ao MetaTrader 5 como fazer as coisas. No entanto, entender como a plataforma funcionam, lhe permitirá um controle muito mais amplo, abrangente e profundo do como suas aplicações realmente trabalharão dentro do MetaTrader 5.

De fato, o que foi demostrado no artigo anterior, está longe de ser algo obvio. Tanto que quando meus primeiros artigos foram publicados aqui, muitos não conseguiram de fato entender como tais aplicações funcionavam. E isto se deve, justamente por que, tais pessoas esperavam encontrar algo no código, que realmente não estava presente no código. Porém, o segredo de tais aplicações mostradas na época, se dava justamente pelo fato de que, nem tudo pode ser conseguido fazendo uso apenas e tão somente do MQL5, ou de uma programação pura e simples.

Apesar de um ou outro, poder estar estranhando a maneira como as coisas tem sido feitas. Quero que você, compreenda que quando o assunto é programação, nem tudo, ou melhor dizendo, nem todas as respostas estará de fato no código. Muitas das vezes, entender como o sistema operacional, ou mesmo a aplicação com a qual estamos trabalhando, nos dará respostas que não conseguiríamos de outra maneira. E assim, algo que a princípio seria impossível, acaba se tornando praticável.

Já vi muita gente, quebrando a cabeça, tentando implementar algo, onde se a pessoa conhecesse a aplicação, ou mesmo o sistema operacional, não ficaria ali, lutando para codificar as coisas. Ele apenas utilizaria recursos ou mecanismos presentes no próprio sistema operacional, ou mesmo na aplicação, que seria no nosso caso o MetaTrader 5, para contornar o problema e criar a solução.

É justamente este tipo de coisa, que era explorada em meus primeiros artigos. Apesar da explicação de por que as coisas funcionarem não ter sido devidamente adequada. Isto por que imaginava erroneamente que o público alvo era outro. O que acabou gerando um vácuo de conhecimento em muitos que tentavam replicar os resultados mostrados.

Devido justamente esta falha na explicação, foi decidido voltar as origens. Assim, não darei uma explicação meia boca novamente. Quero que você, entenda cada mínimo detalhe envolvidos na criação do que será mostrado.

Para começar, existem alguns pré-requisitos para se conseguir acompanhar, perfeitamente bem, o que será feito. Entre tais pré-requisitos, está o de entender o que foi feito no artigo anterior, além da necessidade de você ter compreendido o que foi explicado nos seguintes artigos:

Do básico ao intermediário: Objetos e sub janelas (III)

Do básico ao intermediário: Sub Janelas (IV)

Do básico ao intermediário: Eventos em Objetos (IV)

Dito isto, podemos partir para a parte onde acontecerá implementação de algo meio maluco. Digo maluco, pois o que será visto, costuma dar um belo de um nó no cérebro de muito programador iniciante e deixar programadores mais experientes com a pulga atrás da orelha. Isto por que, codificaremos muito pouco, mas teremos resultados bem interessantes, e muito além daquilo que o código a princípio nos promete.

Para iniciar, criaremos um código simples e quase totalmente sem graça. Este pode ser visto logo abaixo.

01. #property copyright "Daniel Jose"
02. #property description "DEMO Indicator"
03. #property indicator_separate_window
04. #property indicator_height          100
05. #property indicator_plots           0
06. //+------------------------------------------------------------------+
07. class C_MultiChart
08. {
09. private:
10.    string            m_szObject[];
11. 
12.    void              NewObj_CHART(void)
13.      {
14.       int            nObjects = ArraySize(m_szObject) + 1;
15.       string         sz0 = "Demo_Chart #" + (string)ObjectsTotal(0, -1, -1);
16. 
17.       ArrayResize(m_szObject, nObjects);
18.       m_szObject[nObjects - 1] = sz0;
19. 
20.       ObjectCreate(0, sz0, OBJ_CHART, ChartWindowFind(), 0, 0);
21.       ObjectSetString(0, sz0, OBJPROP_SYMBOL, _Symbol);
22.       ObjectSetInteger(0, sz0, OBJPROP_YDISTANCE, 0);
23.       ObjectSetInteger(0, sz0, OBJPROP_PERIOD, PERIOD_M15);
24.       ObjectSetInteger(0, sz0, OBJPROP_DATE_SCALE, false);
25.       ObjectSetInteger(0, sz0, OBJPROP_PRICE_SCALE, false);
26.       ObjectSetInteger(0, sz0, OBJPROP_YSIZE, indicator_height);
27.      }
28. 
29. public:
30.                      C_MultiChart(void)
31.      {
32.       for(int c = 0; c < 2; c++)
33.          NewObj_CHART();
34.      }
35. 
36.    void              Resize(void)
37.      {
38.       const int      nObjects = ArraySize(m_szObject);
39.       const int      step = (int)(ChartGetInteger(0, CHART_WIDTH_IN_PIXELS) /
40.                                   (nObjects > 0 ? nObjects : 1));
41. 
42.       for(int c = 0, x = 0; c < nObjects; c++, x += step)
43.         {
44.          ObjectSetInteger(0, m_szObject[c], OBJPROP_XDISTANCE, x);
45.          ObjectSetInteger(0, m_szObject[c], OBJPROP_XSIZE, step);
46.         }
47.       ChartRedraw();
48.      }
49. };
50. //+------------------------------------------------------------------+
51. C_MultiChart *gl_Multi = NULL;
52. //+------------------------------------------------------------------+
53. int OnInit(void)
54.   {
55.    gl_Multi = new C_MultiChart();
56. 
57.    return(INIT_SUCCEEDED);
58.   }
59. //+------------------------------------------------------------------+
60. int OnCalculate(const int rates_total,
61.                 const int prev_calculated,
62.                 const int begin,
63.                 const double &price[])
64.   {
65.    return(rates_total);
66.   }
67. //+------------------------------------------------------------------+
68. void OnChartEvent(const int id,
69.                   const long &lparam,
70.                   const double &dparam,
71.                   const string &sparam)
72.   {
73.    switch(id)
74.      {
75.       case CHARTEVENT_CHART_CHANGE:
76.          if(gl_Multi != NULL)
77.             gl_Multi.Resize();
78.          break;
79.      }
80.   }
81. //+------------------------------------------------------------------+
82. void OnDeinit(const int reason)
83.   {
84.    delete gl_Multi;
85.   }
86. //+------------------------------------------------------------------+

Código 01

Apesar de ser sem graça, este código 01 nos permite criar o que pode ser visto na imagem logo abaixo.


Imagem 01

Talvez você esteja com dúvida, em relação a uma questão, vista neste código 01. E de fato, para quem vem estudando e praticando o que temos ensinando nesta série, tal dúvida, de certa maneira é relevante, devendo desta forma ser totalmente sanada. A mesma se refere ao seguinte fato: Onde está o procedimento, ou função, responsável por remover os objetos do tipo OBJ_CHART do gráfico? Bem, o detalhe, é que não precisamos nos preocupar em remover tais objetos, neste código 01. Isto por conta de que na linha seis estamos definindo que faremos uso de uma sub janela. E logo depois, na linha vinte e três, que é onde estaremos criando os objetos.

Estamos dizendo para o MetaTrader 5, para criar os objetos diretamente na sub janela, onde o indicador será colocado. Agora preste bastante atenção, como os objetos serão colocados na mesma sub janela, onde o indicador existirá, quando você remover o indicador do gráfico, o MetaTrader 5 também removerá tudo aquilo que estiver dentro da sub janela. Ou seja, mesmo que não estejamos removendo os objetos do gráfico, o MetaTrader 5 fará isto para nós, já que um objeto criando em uma sub janela, não poderá existir, caso está sub janela deixe de existir.

Porém, existe um detalhe. Observe que na linha setenta e nove, estamos pedindo para o MetaTrader 5 liberar a memória alocada para comportar a classe criada na linha cinquenta e sete. Este pedido de liberação de memória, de fato precisa ser feito. Já que sem ele, teremos um alerta vindo do MetaTrader 5, informando que existem elementos ainda presentes na memória e que não foram liberados. Agora você consegue perceber como é importante compreender, de maneira correta e adequada como a plataforma trabalha? Sem saber e conseguir compreender este funcionamento, acabaríamos criando código não necessário. E em outros momentos, deixaríamos de colocar códigos, que de fato se fazem necessários. Este tipo de conhecimento, somente nascerá com a prática e estudo. Então tenha calma se ainda não entendeu o que acabamos de fazer.

Mas apesar destas explicações. Até este momento, não fizemos absolutamente nada. No entanto, daremos um tempo neste código 01, já que ele é apenas parte do que precisamos de fato fazer aqui. E ver outra coisa, que é onde a porca torce o rabo. Isto por que, muita gente fica imaginando ser necessário criar algo, quando, na verdade, não precisamos criar as coisas, apenas adaptar o que já sabemos para conseguir o resultado desejado.

Agora, foco total no que será explicado. Pois isto no passado já foi motivo de muita confusão na cabeça das pessoas. Nosso objetivo, agora, será o de colocar dois indicadores dentro da sub janela mostrada na imagem 01. Preste muita atenção, o objetivo, é de fato colocar dois indicadores, em uma mesma sub janela. Porém, ambos indicadores são projetados para serem colocados, cada um em uma sub janela diferente. Portanto, em tese, jamais conseguiríamos colocar ambos em uma única sub janela. Pelo menos não sem que eles tivessem uma interpretação bastante confusa.

Como o objetivo é a didática, e com isto tornar as coisas o mais simples de ser entendidas. Não implementaremos neste primeiro momento nenhum código. O que faremos será usar indicadores que estão presentes e disponíveis naturalmente dentro do MetaTrader 5. Isto para que todos consigam entender, que criar o código é apenas e tão somente um mero detalhe. O que realmente importa, é que você consiga compreender até onde podemos ir, na utilização do MetaTrader 5, sem precisar fazer uso de coisas extremamente complexas e sofisticadas.

Muito bem, existem diversos pequenos macetes, ou passos, por assim dizer, que precisam ser seguidos. Isto para termos uma maior liberdade e menos necessidade de criação de código. A primeira coisa a ser feita é mostrada na animação logo abaixo.


Animação 01

Aqui estamos garantindo que toda a janela será utilizada. Isto é importante para evitar um recuo muito grande depois, quando os indicadores forem colocados nas sub janelas. Uma vez que todo o processo tenha sido feito, poderemos voltar com o recuo. Mas por hora mantenha ele desligado. Se você se esquecer de desligar o recuo, dará para desligar ele depois. Porém, será muito mais trabalhoso. Então vamos reduzir nosso trabalho e fazer as coisas com cuidado e atenção.

Ok, agora que o recuo está desligado, podemos partir para o próximo passo, que no caso é o de escolher qual indicador utilizaremos. Você pode utilizar qualquer indicador que desejar, e isto literalmente falando. Porém, dependendo do caso, pode ser necessário fazer um passo extra. Que no caso não abordaremos ainda neste momento. Isto justamente para evitar gerar uma confusão desnecessária. Assim sendo, vamos pelo caminho mais simples e fácil primeiramente.

Certo, sabendo que desejamos utilizar dois indicadores em uma mesma sub janela. Vamos devagar, fazendo primeiro a adição do primeiro indicador que desejamos. Isto é mostrado na animação logo abaixo.


Animação 02

Você pode configurar o indicador como desejar. Mas lembre-se de fazer isto aqui e agora, já que para fazer isto depois será algo muito mais trabalhoso. E como foi dito antes, queremos evitar a fadiga, de ter que ajustar as coisas posteriormente. Ok, uma vez que você o tenha configurado, como achar melhor. O próximo passo será o de salvar esta configuração em um arquivo template. Para isto, seguimos os passos vistos no artigo anterior. Mas para evitar dúvida, fazemos o seguinte:


Imagem 02

Nesta imagem selecionamos o que está sendo mostrado. Isto abrirá uma janela, onde poderemos salvar as configurações em um template. Assim que terminar, aparecerá o que é visto na imagem abaixo.


Imagem 03

Agora temos um novo arquivo template disponível e passivo de ser utilizado. Bem, o que rege nosso primeiro indicador já está feito. Agora vamos adicionar o segundo indicador. Neste ponto existe um detalhe importante. Como você já deve saber, arquivo template quando aplicados a um gráfico, recolocam toda a configuração interna no gráfico em que ele está sendo aplicado. Assim, se você não desejar que diversos indicadores compartilhem o mesmo gráfico, precisará limpar o mesmo, removendo tudo que não for necessário. Com isto, voltamos a ter algo parecido com o mostrado logo abaixo.


Imagem 04

Legal, já estamos quase lá. Agora escolhemos aquele que será nosso segundo indicador. No caso vou escolher o que estará sendo mostrado na animação logo abaixo.


Animação 03

E mais uma vez configuramos o indicador como desejarmos, procedemos assim da mesma forma vista no primeiro indicador. Ou seja, voltamos aquilo que seria a imagem 02 e salvamos o template. No final teremos o que é mostrado na imagem logo abaixo.


Imagem 05

Agora note que temos os dois indicadores, já configurados, e dos quais queremos fazer uso. Repare que cada um, está em um template diferente. Isto facilita e ajuda bastante no que faremos em breve. Porém, nada impede que você os coloque juntos e depois os separe. No entanto, isto gerará muito mais trabalho. Trabalho este que podemos evitar, apenas por fazer as coisas da maneira como foi mostrada aqui, ou seja, deixando os arquivos em separado.

A graça de fazer desta maneira, é que isto, nos poupa bastante trabalho e esforço. E este tempo economizado, podemos gastar depois com outra coisa mais interessante. Portanto, aprender como fazer as coisas, nunca é de fato perda de tempo. Como muitos às vezes gostam de dar a entender. Mas e aí. Qual é o próximo passo? Bem, se você leu e entendeu o que foi explicado no artigo anterior, você já deve estar com a resposta na ponta da língua. Isto por que, de fato, o próximo passo será o de lançar estes templates salvos para dentro do gráfico criado e mantido pelo objeto OBJ_CHART.

Podemos fazer isto de mil maneiras diferentes, e nenhuma delas será melhor ou pior do que a outra. Tudo depende de como você queira fazer as coisas, e que tipo de comportamento você deseja que seu código tenha. Como aqui, o objetivo é didático, não vou me atrever a dizer a você, que este ou aquele caminho é o correto. Mas vou lhe mostrar que tipo de conceito deve ser adotado, para que você tenha o resultado almejado. Que no caso é justamente o de ter dois indicadores distintos em uma mesma sub janela.

Muito bem, então vamos voltar a nossa atenção ao código 01 mais uma vez. Agora pare e pense um pouco: Qual seria a melhor forma de dizer ao código da classe C_MultiChart, quais os templates que deveriam ser utilizados em cada um dos objetos do tipo OBJ_CHART? Bem, a resposta para isto é: depende. Como cada caso é um caso, você pode imaginar meios diferentes de fazer isto. Mas vamos brincar um pouco com este código para fazer algo um tanto quanto inusitado. Note que no constructor da classe, estamos informando que queremos dois objetos do tipo OBJ_CHART sendo apresentados na sub janela. Mas e se desejarmos colocar mais? E que não desejarmos dois, mas apenas um? Bem isto, talvez seja um tanto quanto estranho. Mas podemos fazer com que o código se adeque ao que desejamos criar. E fazendo desta forma, acreditamos que o código ficará bem mais legal e muito mais divertido. Já que, cada um poderá criar sua própria configuração com um mínimo de esforço.

Então buscando trabalhar com o que temos em mãos, e sem usar outros conceitos, que já foram explicados, mas não os quero aplicar aqui e agora. Vamos modificar o código 01, de forma que teremos no final o que é visto logo abaixo.

01. #property copyright "Daniel Jose"
02. #property description "DEMO Indicator"
03. #property indicator_separate_window
04. #property indicator_height          100
05. #property indicator_plots           0
06. //+------------------------------------------------------------------+
07. class C_MultiChart
08.   {
09. private:
10.    string            m_szObject[];
11. 
12.    void              NewObj_CHART(void)
13.      {
14.       int            nObjects = ArraySize(m_szObject) + 1;
15.       string         sz0 = "Demo_Chart #" + (string)ObjectsTotal(0, -1, -1);
16. 
17.       ArrayResize(m_szObject, nObjects);
18.       m_szObject[nObjects - 1] = sz0;
19. 
20.       ObjectCreate(0, sz0, OBJ_CHART, ChartWindowFind(), 0, 0);
21.       ObjectSetString(0, sz0, OBJPROP_SYMBOL, _Symbol);
22.       ObjectSetInteger(0, sz0, OBJPROP_YDISTANCE, 0);
23.       ObjectSetInteger(0, sz0, OBJPROP_PERIOD, PERIOD_M15);
24.       ObjectSetInteger(0, sz0, OBJPROP_DATE_SCALE, false);
25.       ObjectSetInteger(0, sz0, OBJPROP_PRICE_SCALE, false);
26.       ObjectSetInteger(0, sz0, OBJPROP_YSIZE, indicator_height);
27.      }
28. 
29. public:
30.                      C_MultiChart(const string &szTemplates[])
31.      {
32.       for(int c = 0; c < ArraySize(szTemplates); c++)
33.          NewObj_CHART();
34.      }
35. 
36.    void              Resize(void)
37.      {
38.       const int      nObjects = ArraySize(m_szObject);
39.       const int      step = (int)(ChartGetInteger(0, CHART_WIDTH_IN_PIXELS) /
40.                                   (nObjects > 0 ? nObjects : 1));
41. 
42.       for(int c = 0, x = 0; c < nObjects; c++, x += step)
43.         {
44.          ObjectSetInteger(0, m_szObject[c], OBJPROP_XDISTANCE, x);
45.          ObjectSetInteger(0, m_szObject[c], OBJPROP_XSIZE, step);
46.         }
47.       ChartRedraw();
48.      }
49.   };
50. //+------------------------------------------------------------------+
51. C_MultiChart *gl_Multi = NULL;
52. //+------------------------------------------------------------------+
53. //| Custom indicator initialization function                         |
54. //+------------------------------------------------------------------+
55. int OnInit(void)
56.   {
57.    const string     szTemplates[] =
58.      {
59.       "Bollinger Bands.tpl",
60.       "Parabolic SAR.tpl"
61.      };
62. 
63.    gl_Multi = new C_MultiChart(szTemplates);
64. 
65.    return(INIT_SUCCEEDED);
66.   }
67. //+------------------------------------------------------------------+
68. //| Custom indicator iteration function                              |
69. //+------------------------------------------------------------------+
70. int OnCalculate(const int rates_total,
71.                 const int prev_calculated,
72.                 const int begin,
73.                 const double &price[])
74.   {
75.    return(rates_total);
76.   }
77. //+------------------------------------------------------------------+
78. //| ChartEvent function                                              |
79. //+------------------------------------------------------------------+
80. void OnChartEvent(const int id,
81.                   const long &lparam,
82.                   const double &dparam,
83.                   const string &sparam)
84.   {
85.    switch(id)
86.      {
87.       case CHARTEVENT_CHART_CHANGE:
88.          if(gl_Multi != NULL)
89.             gl_Multi.Resize();
90.          break;
91.      }
92.   }
93. //+------------------------------------------------------------------+
94. //| Custom indicator deinitialization function                       |
95. //+------------------------------------------------------------------+
96. void OnDeinit(const int reason)
97.   {
98.    delete gl_Multi;
99.   }
100.//+------------------------------------------------------------------+

Código 02

Que coisa mais linda é este código 02! Isto por que, com quase nenhuma modificação sobre o que seria o código 01, conseguimos implementar um método de dizer quantos objetos do tipo OBJ_CHART, queremos na sub janela. E tudo que foi preciso fazer foi uma simples mudança no código. Porém, ele ainda continua tendo o mesmo resultado que seria visto no código 01. Agora vem a questão: Quando aplicar o template? Novamente a resposta para isto é: depende. Cara, você é muito chato. Para toda pergunta a resposta é sempre: depende, depende e depende. Será que você não pode ser um pouco mais direto? E dizer qual seria de fato o melhor momento para se fazer as coisas? Apesar de isto parecer um tanto quanto estranho e chato, a questão é que tudo depende do tipo de coisa que você planeja fazer. Não existe certo ou errado, quando o assunto é programação.

O que existe é: Funciona, ou não funciona. Mas a melhor hora de fazer as coisas, não tem como definir, sem entender qual o objetivo a ser alcançado, e de quanto trabalho e esforço você está disposto a colocar na mesa de trabalho. Por isto, a melhor resposta que alguém pode lhe dar, quando o assunto é programação, é de fato, depende.

Mas voltando ao assunto, como aqui queremos ser o mais direto possível, já que a princípio, não temos como objetivo, modificar o template aplicado a um determinado gráfico mantido e criado por um objeto do tipo OBJ_CHART. Podemos fazer, com que durante o processo de construção, o template seja carregado e a aplicado ao gráfico do objeto. Assim, como a modificação é com base no que está sendo feito no código 02, não vejo sentido em replicar todo o código novamente. Então a mudança a ser feita é mostrada no fragmento logo abaixo.

                                   .
                                   .
                                   .
15. 
16.    void              NewObj_CHART(const string szTemplate)
17.      {
18.       int            nObjects = ArraySize(m_szObject) + 1;
19.       string         sz0 = "Demo_Chart #" + (string)ObjectsTotal(0, -1, -1);
20.       long           id;
21. 
22.       ArrayResize(m_szObject, nObjects);
23.       m_szObject[nObjects - 1] = sz0;
24. 
25.       ObjectCreate(0, sz0, OBJ_CHART, ChartWindowFind(), 0, 0);
26.       ObjectSetString(0, sz0, OBJPROP_SYMBOL, _Symbol);
27.       ObjectSetInteger(0, sz0, OBJPROP_YDISTANCE, 0);
28.       ObjectSetInteger(0, sz0, OBJPROP_PERIOD, PERIOD_M15);
29.       ObjectSetInteger(0, sz0, OBJPROP_DATE_SCALE, false);
30.       ObjectSetInteger(0, sz0, OBJPROP_PRICE_SCALE, false);
31.       ObjectSetInteger(0, sz0, OBJPROP_YSIZE, indicator_height);
32. 
33.       id = ObjectGetInteger(0, sz0, OBJPROP_CHART_ID);
34.       ChartApplyTemplate(id, szTemplate);
35.       ChartRedraw(id);
36.      }
37. 
38. public:
39.                      C_MultiChart(const string &szTemplates[])
40.      {
41.       for(int c = 0; c < ArraySize(szTemplates); c++)
42.          NewObj_CHART(szTemplates[c]);
43.      }
44. 
                                   .
                                   .
                                   .

Fragmento 01

Agora preste muita atenção, pois isto é muito importante. Note que estamos passando o nome do template diretamente via chamada na linha quarenta e um. Na linha trinta e um, deste fragmento 01, estamos capturando a identidade do gráfico, presente e criado pelo objeto OBJ_CHART. Esta informação é usada na linha trinta e dois, para carregar e atribuir o template ao gráfico. Já na linha trinta e três, garantimos a primeira atualização. Visto que as demais acontecerão, assim que o time frame indicar que precisará atualizar o gráfico novamente, mas isto será feito pelo próprio MetaTrader 5. E apesar de tudo funcionar, como você pode observar na animação logo abaixo. É preciso que você saiba que neste código, não estamos fazendo nenhum teste a fim de verificar possíveis erros.

Ou seja, se você apontar para algum template, que não existe, nenhuma falha será reportada. Visto que não estamos testando o resultado da operação feita na linha trinta e dois. Que é justamente onde o template está sendo aplicado no gráfico. Então para que tudo aconteça perfeitamente bem, você precisa seguir à risca o que foi mostrado aqui. Até conseguir de fato, entender como as coisas funcionam. Somente depois pode se aventurar, e tentar criar as coisas de uma maneira mais exótica e elaborada. Até lá, procure usar apenas o que foi mostrado aqui.



Animação 04

Este tipo de coisa é bem legal mesmo de ser feita. Mas que tal estendermos um pouco mais as coisas? Isto por que, podemos desejar utilizar algum indicador um pouco mais complexo, como, por exemplo, um estocástico ou outro indicador, que naturalmente faça uso natural de uma sub janela. Bem neste caso, precisamos, ou dependendo do caso, até que não será necessário, ajustar um pouco mais as coisas.

E é nestas horas que a confusão começa a se estabelecer na mente de muita gente boa. Porém, que não prestaram a devida atenção ao que foi explicado até este momento. Se este foi o seu caso, pare, relaxe um pouco, e volte ao início do artigo. Isto para que você consiga entender, porque o resultado obtido ao executar o código 02, foi justamente este que podemos ver na animação 04. Quando você entender isto, poderá passa para o próximo nível. Que é justamente o de usar indicadores, que fazem uso natural de uma sub janela.

Para este tipo de indicador, precisamos na maior parte das vezes, fazer uso de um passo extra. Isto entre o que implica colocar o indicador no gráfico, e salvar a configuração como sendo um arquivo template. Este passo extra, não é obrigatório, mas torna os resultados mais atraentes no logo prazo. Certo, considerando que desejamos adicionar o estocástico como sendo um indicador extra, temos os seguintes passos a serem dados.


Animação 05

Agora atenção ao seguinte detalhe. Se você salvar este gráfico como mostrado no final da animação 05, terá o gráfico do estocástico sendo mostrado. Porém, com um pequeno inconveniente, que é justamente o gráfico contendo as cotações. Mas espere um pouco. Não entendi. Como assim teremos o gráfico de cotação junto? Bem, para demonstrar isto, vamos modificar algumas coisas no código 02. E não se preocupe, no anexo, você terá acesso a estes códigos. Somente a parte referente aos templates que não colocarei junto, já que isto pode sobrescrever algum template que você tenha em sua instalação do MetaTrader 5. Acredito que não será problema, para ninguém, cria o que está sendo demostrado no artigo. De qualquer forma, salve o template visto na animação 05, com o nome mostrado na imagem logo abaixo.


Imagem 06

Feito isto, vamos voltar a questão do código. Para tornar as coisas um pouco menos desagradáveis, permitiremos que o usuário, ou operador, mude a altura da sub janela. Ao mesmo tempo, vamos adicionar este template salvo e visto na imagem 06, como carga para o indicador, o colocar no gráfico do objeto OBJ_CHART. O código em si pode ser visto logo abaixo na íntegra.

01. #property copyright "Daniel Jose"
02. #property description "DEMO Indicator"
03. #property indicator_separate_window
04. #property indicator_plots           0
05. //+------------------------------------------------------------------+
06. class C_MultiChart
07.   {
08. private:
09.    string            m_szObject[];
10.    int               m_Sub;
11. 
12.    void              NewObj_CHART(const string szTemplate)
13.      {
14.       int            nObjects = ArraySize(m_szObject) + 1;
15.       string         sz0 = "Demo_Chart #" + (string)ObjectsTotal(0, -1, -1);
16.       long           id;
17. 
18.       ArrayResize(m_szObject, nObjects);
19.       m_szObject[nObjects - 1] = sz0;
20. 
21.       ObjectCreate(0, sz0, OBJ_CHART, m_Sub = ChartWindowFind(), 0, 0);
22.       ObjectSetString(0, sz0, OBJPROP_SYMBOL, _Symbol);
23.       ObjectSetInteger(0, sz0, OBJPROP_YDISTANCE, 0);
24.       ObjectSetInteger(0, sz0, OBJPROP_PERIOD, PERIOD_M15);
25.       ObjectSetInteger(0, sz0, OBJPROP_DATE_SCALE, false);
26.       ObjectSetInteger(0, sz0, OBJPROP_PRICE_SCALE, false);
27. 
28.       id = ObjectGetInteger(0, sz0, OBJPROP_CHART_ID);
29.       ChartApplyTemplate(id, szTemplate);
30.       ChartRedraw(id);
31.      }
32. 
33. public:
34.                      C_MultiChart(const string &szTemplates[])
35.      {
36.       for(int c = 0; c < ArraySize(szTemplates); c++)
37.          NewObj_CHART(szTemplates[c]);
38.      }
39. 
40.    void              Resize(void)
41.      {
42.       const int      nObjects = ArraySize(m_szObject);
43.       const int      step = (int)(ChartGetInteger(0, CHART_WIDTH_IN_PIXELS) /
44.                                   (nObjects > 0 ? nObjects : 1));
45. 
46.       for(int c = 0, x = 0; c < nObjects; c++, x += step)
47.         {
48.          ObjectSetInteger(0, m_szObject[c], OBJPROP_YSIZE,
49.                           ChartGetInteger(0, CHART_HEIGHT_IN_PIXELS, m_Sub));
50.          ObjectSetInteger(0, m_szObject[c], OBJPROP_XDISTANCE, x);
51.          ObjectSetInteger(0, m_szObject[c], OBJPROP_XSIZE, step);
52.         }
53.       ChartRedraw();
54.      }
55.   };
56. //+------------------------------------------------------------------+
57. C_MultiChart *gl_Multi = NULL;
58. //+------------------------------------------------------------------+
59. //| Custom indicator initialization function                         |
60. //+------------------------------------------------------------------+
61. int OnInit(void)
62.   {
63.    const string     szTemplates[] =
64.      {
65.       "Stochastic.tpl"
66.      };
67. 
68.    gl_Multi = new C_MultiChart(szTemplates);
69. 
70.    return(INIT_SUCCEEDED);
71.   }
72. //+------------------------------------------------------------------+
73. //| Custom indicator iteration function                              |
74. //+------------------------------------------------------------------+
75. int OnCalculate(const int rates_total,
76.                 const int prev_calculated,
77.                 const int begin,
78.                 const double &price[])
79.   {
80.    return(rates_total);
81.   }
82. //+------------------------------------------------------------------+
83. //| ChartEvent function                                               |
84. //+------------------------------------------------------------------+
85. void OnChartEvent(const int id,
86.                   const long &lparam,
87.                   const double &dparam,
88.                   const string &sparam)
89.   {
90.    switch(id)
91.      {
92.       case CHARTEVENT_CHART_CHANGE:
93.          if(gl_Multi != NULL)
94.             gl_Multi.Resize();
95.          break;
96.      }
97.   }
98. //+------------------------------------------------------------------+
99. //| Custom indicator deinitialization function                       |
100.//+------------------------------------------------------------------+
101. void OnDeinit(const int reason)
102.   {
103.    delete gl_Multi;
104.   }
105.//+------------------------------------------------------------------+

Código 03

Ao executar este código você terá como resultado o que pode ser visto na animação logo abaixo.


Animação 06

Perceba como ficou um tanto quanto estranho esta questão da sub janela. Apesar de tudo, você pode notar que o código em si não sofreu grandes modificações. Mas a questão da sub janela está realmente muito estranha, já que temos a cotação presente na mesma. Coisa que não existiria se adicionássemos o indicador estocástico diretamente aqui. Porém, toda via e, entretanto, ao fazermos isto de adicionarmos o indicador estocástico diretamente, não seria possível que pudéssemos colocar dois indicadores em uma mesma sub janela. Então somente a título de aprendizagem mesmo, vamos criar uma segunda configuração para este indicador estocástico. Isto é feito seguindo uma série de pequenos passos. Começando com o que podemos ver na animação logo abaixo.


Animação 07

Aqui estamos carregando o template que usamos no código 03. Isto deixa as configurações preparadas para o próximo passo que precisaremos dar a seguir. Logo após termos feito isto, fazemos o que é mostrado na animação vista na sequência.


Animação 08

Este passo feito nesta animação 08 é que é o pulo do gato. Uma vez feito isto, que está sendo demostrado na animação, podemos passar para o próximo e derradeiro passo. Que é justamente o de salvar esta configuração em um template. No caso teremos algo como mostrado na figura logo abaixo.


Imagem 07

Com tudo isto em mãos, podemos voltar ao código 03, e o modificar como mostrado no fragmento abaixo. Não se esqueça de que não estamos testando falhas de carregamento. Então, confira os nomes usados, para não haver erros posteriores.

                                   .
                                   .
                                   .
58. //+------------------------------------------------------------------+
59. //| Custom indicator initialization function                         |
60. //+------------------------------------------------------------------+
61. int OnInit(void)
62.   {
63.    const string     szTemplates[] =
64.      {
65.       "Stochastic.tpl",
66.       "Stochastic FULL.tpl"
67.      };
68. 
69.    gl_Multi = new C_MultiChart(szTemplates);
70. 
71.    return(INIT_SUCCEEDED);
72.   }
73. //+------------------------------------------------------------------+
                                   .
                                   .
                                   .

Fragmento 02

Veja como foi super fácil modificar o código, já que tudo que precisamos fazer, é adicionar o nome do template. E isto é feito na linha sessenta e quatro. Porém, o resultado é muito, mas muito interessante, como você pode ver na animação logo abaixo.


Animação 09

E como a animação pode não ser o suficiente, para você observar os mínimos detalhes. Podemos parar as coisas, e ver tais detalhes na imagem logo abaixo.


Imagem 08

Ou seja, temos algo maravilhoso, agora em nossas mãos. Mas para saber como utilizar isto, é preciso que você pratique e tente seguir os passos explicados aqui.


Considerações finais

Finalmente, demos uma explicação descente sobre algo que foi mostrado, em um dos meus primeiros artigos. Porém, aqui foi dada uma total ênfase a questão da didática. Mostrando como podemos aplicar múltiplos indicadores em uma mesma sub janela. Sei que muitos podem achar estranho, ou algo completamente absurdo. Já que não é um tipo de coisa que vemos a todo momento sendo feito. Contudo, este tipo de conhecimento é a diferença entre saber e achar que já sabe das coisas.

Espero que tenham conseguido acompanhar a explicação. Contudo, como mencionei, no anexo, NÃO HAVERÁ TEMPLATES, mas seguindo as orientações dadas aqui, qualquer um conseguirá resultados bem interessantes. Lembrando que os códigos disponíveis no anexo, não farão nenhum teste a fim de verificar possiveis erros. Como, por exemplo, o fato de você tentar usar um arquivo template que não existe. Este tipo de checagem, deixo a cargo de cada um implementar da melhor maneira que desejar.

Arquivo MQ5 Descrição
Indicators\Code 01  Demonstração básica
Indicators\Code 02  Demonstração básica
Indicators\Code 03  Demonstração básica


Arquivos anexados |
Rede neural na prática: Lendo PNG do MNIST Rede neural na prática: Lendo PNG do MNIST
Aqui veremos como implementar um algorítimo simples de leitura de imagens no formato PNG. Conseguir efetuar a leitura do conteúdo destas imagens será importante para podermos avançar no desenvolvimento de uma topologia de rede perceptron. Isto por conta de que começaremos a fazer uso do banco de dados MNIST no treinamento da rede que será implementada.
Técnicas do MQL5 Wizard que você deve saber (Parte 59): Aprendizado por Reforço (DDPG) com Padrões da Média Móvel e do Oscilador Estocástico Técnicas do MQL5 Wizard que você deve saber (Parte 59): Aprendizado por Reforço (DDPG) com Padrões da Média Móvel e do Oscilador Estocástico
Continuamos nosso último artigo sobre DDPG com indicadores de Média Móvel e Estocástico, examinando outras classes-chave de Aprendizado por Reforço cruciais para a implementação do DDPG. Embora estejamos codificando principalmente em Python, será exportado para o formato ONNX para o MQL5, onde a integraremos como um recurso em um Expert Advisor montado pelo Wizard.
Está chegando o novo MetaTrader 5 e MQL5 Está chegando o novo MetaTrader 5 e MQL5
Esta é apenas uma breve resenha do MetaTrader 5. Eu não posso descrever todos os novos recursos do sistema por um período tão curto de tempo - os testes começaram em 09.09.2009. Esta é uma data simbólica, e tenho certeza que será um número de sorte. Alguns dias passaram-se desde que eu obtive a versão beta do terminal MetaTrader 5 e MQL5. Eu ainda não consegui testar todos os seus recursos, mas já estou impressionado.
Gerenciamento Avançado de Memória e Técnicas de Otimização em MQL5 Gerenciamento Avançado de Memória e Técnicas de Otimização em MQL5
Descubra técnicas práticas para otimizar o uso de memória em sistemas de negociação MQL5. Aprenda a construir Expert Advisors e indicadores eficientes, estáveis e com alto desempenho. Exploraremos como a memória realmente funciona no MQL5, as armadilhas comuns que desaceleram seus sistemas ou causam falhas e, mais importante ainda, como corrigi-las.