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

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

MetaTrader 5Exemplos |
24 0
CODE X
CODE X

Introdução

No artigo anterior Do básico ao intermediário: Objetos e sub janelas (III), demonstramos a forma de lidar, ou melhor dizendo, como poderíamos recriar um objeto que se esperar estar presente em um gráfico, devido a alguma questão que o indicador precise nos mostrar. Porém, o tal objeto, foi por algum motivo removido do gráfico, mesmo que o indicador ainda tenha permanecido ali, dando a ideia de que tudo está como foi projetado para ser utilizado, durante a fase de desenvolvimento da aplicação.

Contudo, apesar de muitos acharem que precisamos nos aprofundar ainda mais naquele assunto, por hora estou satisfeito com o que já foi abordado. Portanto, neste artigo começaremos a abordar um tema que, para quem já leu meus primeiros artigos aqui, muito provavelmente não entenderam como eu conseguia fazer certas coisas. Justamente pelo fato de que temos coisas extras sendo mostradas no gráfico, quando da verdade elas não podem ser encontradas em nenhuma parte específica do código. Tornando assim muito difícil entender por que a aplicação funciona, quando temos tão pouco código dizendo como ela deveria funcionar.

Muitos dão pouco valor a este tipo de coisa, tanto é que este é um tema muito pouco explorado. Não só aqui no MQL5, mas em diversas outras linguagens de programação. Sendo de fato um tema bastante divertido e até muito interessante de ser abordado. Então vamos dar um tempo nas distrações e focar no que será explicado aqui. Pois a coisa que começaremos a ver neste artigo envolve uso de técnicas bem inusitadas.


Arquivo template (I)

É bem provável que você deve estar olhando o título deste tópico e imaginando: Que negócio seria este do qual iremos falar? Bem, meu caro leitor, o assunto apesar de parecer, a primeira vista, algo um tanto quanto estranho e completamente diferente daquilo que você utilizaria no seu dia a dia. Contudo, e é bem verdade, esta coisa de arquivo template está muito mais presente na sua vida, do que você provavelmente deve ter notado. Principalmente se você for um operador bastante ativo no uso do MetaTrader 5. Lembrando que arquivos template são algo bem mais abrangente. Porém, aqui vamos nos limitar a tratar a coisa dentro do âmbito do MQL5. Em essência, estes tais arquivos template, nada mais seriam do que arquivos com algum tipo de configuração gráfica, ou padrão de apresentação de objetos gráficos por parte da plataforma MetaTrader 5.

Ok, mas eu nunca ouvi falar de tais arquivos, pelo menos, não que me lembre. Você tem certeza sobre isto? Pois, desconheço alguém que de alguma forma não os utilize no seu dia a dia. Isto porque dentro destes arquivos você armazena configurações gráficas que poderão ser transferidas para outro gráfico ou até mesmo guardadas para uso posterior. Assim, dentro dele você teria os indicadores presentes no momento, padrões de cores, objetos gráficos presentes, entre outras coisas relacionadas ao próprio gráfico. Estes arquivos podem ser acessados, dentro do MetaTrader 5, pelo atalho mostrado na imagem logo abaixo.


Imagem 01

Aqui temos a opção de salvar, carregar ou mesmo remover algum destes arquivo. Além é claro, de poder contar, com um acesso rápido a estes arquivos. No caso da imagem 01, temos dois arquivos. Um que contém um padrão default a ser usado pelo MetaTrader 5, quando for carregar algum gráfico, e outro usado por um indicador particular que mostrei como criar, em outro artigo.

O artigo em questão pode ser visto em Desenvolvendo um EA de negociação do zero (Parte 13): Times And Trade (II), ou seja, o que escrevo nos artigos, é de fato algo que utilizo. Não escrevo artigos apenas por escrever. De fato, quero que você aprenda com eles, ou no mínimo, que eles lhe sirvam de expiração para construir alguma coisa bacana e que lhe seja de alguma utilidade. E como grande parte de vocês, não são programadores, mas sim entusiastas. Esta serie, visa justamente ensinar como chegar lá, colocando suas ideias em prática. Sem depende da boa vontade de ninguém.

Mas antes de chegarmos ao ponto, de podermos usar as coisas de maneira espetacular. Precisamos aprender a caminhar, com algo que seja básico e simples. Para não perder muito tempo, e tão pouco deixar o artigo muito chato. Vou presumir, que todos aqui, saibam como gravar, carregar, configurar e ajustar um template a fim de o utilizar em um gráfico. E isto fazendo uso apenas, e tão somente, do que se encontra disponível no MetaTrader 5, por padrão. Que são justamente os controles que podem ser vistos na imagem 01. Além dos que são vistos na imagem logo abaixo.


Imagem 02

Agora preste atenção, o que você está vendo nesta imagem 02, é um tipo de atalho, para se poder utilizar um tipo de recurso, ainda mais avançado presente no MQL5. Porém, talvez você ainda não tenha de fato notado isto, justamente por conta de que esteve envolto na escuridão até este momento. Contudo, chegou a hora de vir para a luz, e ver que o mundo não é coberto por sombras. Mas sim, é um mundo multicolorido com diversas possibilidades jamais imaginadas por muitos, que ainda se negam em ver a luz do dia. Preferindo viver na ignorância e com uma visão limitada das coisas.

Caso você ainda não tenha entendido, quero que olhe novamente para esta imagem 02. E responda sinceramente: Você conhece algum objeto, dentro do MQL5, que se parece com a figura do canto esquerdo desta imagem 02? Pois é isto mesmo, o objeto OBJ_CHART é o mesmo que estamos vendo no canto esquerdo desta imagem 02. Mas espere. Por que você está me chamando a atenção para este fato? Por um a caso, você está me dizendo, que podemos controlar o objeto OBJ_CHART, sem de fato precisarmos programar ele? Será que tenho perdido tempo, fazendo algo que poderia ser feito de maneira mais simples, rápida e eficiente, por este tempo? Bem, com relação a isto, não sei o que lhe responder. Mas sim, muito provavelmente, você tem perdido tempo, ficando limitado a fazer as coisas de uma certa forma, quando poderia as fazer de maneira muito mais rápida seguindo por outro caminho.

Para que você consiga entender onde estou querendo chegar, será preciso antes, que você entenda uma coisa, meu caro leitor. Tudo, e absolutamente tudo que você vê em uma tela de computador, está de alguma forma sendo abstraído a fim de tornar mais simples, lhe apresentar tais informações. Para um leigo, ou mero usuário, o fato de ele observar na tela, algo como o que é mostrado na imagem logo abaixo, representa apenas e tão somente um gráfico de algum ativo.


Imagem 03

Porém, para um programador, ou um usuário um pouco mais atento e igualmente curioso. Esta mesma imagem 03, contém elementos que já são bem conhecido e podem ser manipulados e ajustados. Para demonstrar isto, vamos criar um pequeno código, só para tornar as coisas um pouco mais claras. O código em questão pode ser 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. #define def_Prefix "DEMO_"
10. //+------------------------------------------------------------------+
11. int OnInit(void)
12. {
13.     string sz0 = def_Prefix + (string)ObjectsTotal(0, -1, -1);
14. 
15.     ObjectCreate(0, sz0 , OBJ_CHART, 0, 0, 0);
16.     ObjectSetString(0, sz0, OBJPROP_SYMBOL, _Symbol);
17.     ObjectSetInteger(0, sz0, OBJPROP_XDISTANCE, 0);
18.     ObjectSetInteger(0, sz0, OBJPROP_YDISTANCE, 0);
19.     ObjectSetInteger(0, sz0, OBJPROP_XSIZE, ChartGetInteger(0, CHART_WIDTH_IN_PIXELS) / 2);
20.     ObjectSetInteger(0, sz0, OBJPROP_YSIZE, ChartGetInteger(0, CHART_HEIGHT_IN_PIXELS));
21.     ObjectSetInteger(0, sz0, OBJPROP_PERIOD, PERIOD_M15);
22.     ObjectSetInteger(0, sz0, OBJPROP_DATE_SCALE, false);
23.     ObjectSetInteger(0, sz0, OBJPROP_PRICE_SCALE, false);
24.    
25.     return INIT_SUCCEEDED;
26. };
27. //+------------------------------------------------------------------+
28. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
29. {
30.     return rates_total;
31. };
32. //+------------------------------------------------------------------+
33. void OnDeinit(const int reason)
34. {
35.     ObjectsDeleteAll(0, def_Prefix);
36.     ChartRedraw();
37. };
38. //+------------------------------------------------------------------+

Código 01

Este código 01, que imagino não precisar ser explicado, tem como resultado o que é visto na imagem logo na sequência.


Imagem 04

Obviamente que você, já deve saber, que podemos modificar algumas das propriedades deste objeto OBJ_CHART. Isto nos permite configurar e utilizar o gráfico de uma forma que ninguém imaginaria ser possível anteriormente. Contudo, se o gráfico sofrer alguma mudança em suas dimensões, este código 01 não acompanhará tais mudanças. Para corrigir isto, modificamos o código 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_Prefix "DEMO_"
10. //+------------------------------------------------------------------+
11. string szObject;
12. //+------------------------------------------------------------------+
13. int OnInit(void)
14. {
15.     szObject = def_Prefix + (string)ObjectsTotal(0, -1, -1);
16.     ObjectCreate(0, szObject , OBJ_CHART, 0, 0, 0);
17.     ObjectSetString(0, szObject, OBJPROP_SYMBOL, _Symbol);
18.     ObjectSetInteger(0, szObject, OBJPROP_XDISTANCE, 0);
19.     ObjectSetInteger(0, szObject, OBJPROP_YDISTANCE, 0);
20.     ObjectSetInteger(0, szObject, OBJPROP_PERIOD, PERIOD_M15);
21.     ObjectSetInteger(0, szObject, OBJPROP_DATE_SCALE, false);
22.     ObjectSetInteger(0, szObject, OBJPROP_PRICE_SCALE, false);
23.    
24.     return INIT_SUCCEEDED;
25. };
26. //+------------------------------------------------------------------+
27. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
28. {
29.     return rates_total;
30. };
31. //+------------------------------------------------------------------+
32. void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
33. {
34.     switch(id)
35.     {
36.         case CHARTEVENT_CHART_CHANGE:
37.             ObjectSetInteger(0, szObject, OBJPROP_XSIZE, ChartGetInteger(0, CHART_WIDTH_IN_PIXELS) / 2);
38.             ObjectSetInteger(0, szObject, OBJPROP_YSIZE, ChartGetInteger(0, CHART_HEIGHT_IN_PIXELS));
39.             break;
40.     }
41.     ChartRedraw();
42. };
43. //+------------------------------------------------------------------+
44. void OnDeinit(const int reason)
45. {
46.     ObjectsDeleteAll(0, def_Prefix);
47.     ChartRedraw();
48. };
49. //+------------------------------------------------------------------+

Código 02

Esta simples modificação, do código 01 para este código 02, permitirá que o objeto OBJ_CHART se ajuste automaticamente as novas dimensões do gráfico. E isto já começará a nos dar um certo controle. Apesar de que, ainda estamos apenas começando a nos aquecer.

Ok, no entanto, ainda não consegui entender, o que um arquivo template, que visa ser usado em gráficos dentro do MetaTrader 5, tem a ver com um objeto OBJ_CHART.

Bem, meu caro leitor, para entender isto, o melhor seria lhe explicar as coisas pessoalmente. Já que assim, poderíamos explicar cada um dos detalhes separadamente, até que você os entendesse. Contudo, acredito que muitos teriam alguma dificuldade em conseguir compreender, como alguns detalhes interferem no objeto OBJ_CHART. Assim, vou tentar usar outra abordagem, um tanto mais simples. Desta forma creio que ficará mais fácil entender, como arquivos template podem ser usados, sem precisar entrar nos detalhes do próprio arquivo.

Quando um objeto OBJ_CHART e colocado em algum gráfico, ele absorverá parte, e atenção a isto, daquilo que seria o template do gráfico. A palavra que nos interessa aqui é: PARTE. E por que esta palavra é importante? O motivo é que independentemente de como o template do gráfico esteja configurado, apenas parte dele será usado para se criar o template que será colocado no objeto OBJ_CHART. Isto a fim de que o objeto OBJ_CHART seja apresentado no gráfico.

Cara, não estou entendendo, esta sua colocação. Poderia ser um pouco mais claro, com relação a isto, por favor. Bem, vou tentar. Como mencionei seria mais fácil lhe mostrar isto pessoalmente. Então vamos fazer o seguinte: Uma vez que o código 02 tenha sido compilado, vamos jogar ele em um gráfico, que esteja inicialmente configurado conforme visto logo abaixo.


Imagem 05

Esta configuração vista na imagem 05, segue um padrão de cores, previamente definido dentro do MetaTrader 5. Este é visto logo abaixo, para quem tiver dúvidas a respeito.


Imagem 06

Agora preste atenção, quando o indicador for colocado no gráfico, o resultado passará a ser aquele que podemos visualizar logo abaixo.


Imagem 07

Ok, contudo não estou entendendo, já que para mim, tudo parece ser muito comum, e sem nenhuma grande novidade. Certo, agora com o indicador ainda presente no gráfico, vamos mudar o padrão de cores, para o visto na imagem 02. Com isto o resultado passará a ser o vemos na imagem logo abaixo.


Imagem 08

Hum, ainda não consegui entender onde você está querendo chegar. Até onde sei, este resultado visto na imagem 08 está normal. Tudo dentro do que seria esperado. Mas é aí que as coisas começaram a ficar um pouco mais interessantes, meu caro leitor. Isto por que, agora temos dois padrões de cores totalmente diferentes sendo apresentados no gráfico. Muitos poderiam dizer o seguinte: Bem, e daí? Se quisermos atualizar o padrão de cores, de forma que eles fiquem iguais, bastará copiar cada uma das cores para dentro do objeto OBJ_CHART. Já que temos a possibilidade de fazer este tipo de coisa de maneira muito simples. De fato, esta abordagem não estaria incorreta. Sendo perfeitamente funcional, e isto sem nenhuma sombra de dúvida, seria uma metodologia que podemos utilizar em determinados momentos.

Porém, toda via e, entretanto, fazer este tipo de cópia, nos dará muito mais trabalho, do que fazendo uso de outras metodologias. Além é claro, tornar complicado garantir que tudo permaneça funcionando sem problemas, no decorrer do tempo. E conforme as coisas vão se tornando cada vez mais elaboradas, a possibilidade de algo dar errado começa a crescer vertiginosamente. Já que além do padrão de cores, também podemos estar modificando outras características do próprio gráfico. O que mais hora ou menos hora, acaba tornando toda a implementação, algo chato, cansativo, engessado e muito sujeito a erros.

Justamente devido a isto, podemos adotar outra metodologia, que além de ser muito mais prática, é igualmente muito mais simples. Justamente por nos garantir um controle e uma cópia mais fiel. Às vezes, fiel até demais, diga-se de passagem. Necessitando que façamos alguns ajustes para evitar dores de cabeça. Isto independentemente do tipo de coisa que estivermos fazendo no gráfico.

Mas vamos com calma. Já que este é o primeiro contato, que acredito que muitos estão tendo com este tipo de modelagem e abordagem. Não quero que aconteça o mesmo que ocorreu quando mostrei outras coisas, lá nos meus primeiros artigos. Desta vez, quero que todos realmente consigam entender o que está acontecendo. Para que ninguém fique na dúvida ou não consiga tirar proveito do que está sendo explicado.

Então vamos começar com a abordagem da modificação ou cópia física dos argumentos de cores. Ou seja, se a cor do gráfico principal mudar, o mesmo deverá acontecer com o gráfico plotado dentro do objeto OBJ_CHART. Para isto acontecer, precisamos fazer algumas coisas, e como não quero criar algo complexo e chato, vamos seguir por uma via ainda mais simples. Contudo, vamos implementar isto, nos baseando naquilo que é o código 02.

A primeira coisa que precisa ficar clara é que o objeto OBJ_CHART é um gráfico com uma identidade própria. Porém, este mesmo gráfico está presente, ou melhor dizendo, embutido em um gráfico principal. E como queremos modificar as cores das barras dentro do gráfico presente no OBJ_CHART, precisamos fazer uso de uma abordagem bem inusitada. Não se preocupe, o trabalho em si é simples de entender. Mas, precisamos ficar atentos aos detalhes, para que tudo funcione adequadamente.

Assim, não vamos começar mudando as cores no gráfico presente no objeto OBJ_CHART. Vamos mudar a cor presente no gráfico principal. Para isto o código 02 será modificado 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_Prefix "DEMO_"
10. //+------------------------------------------------------------------+
11. string szObject;
12. //+------------------------------------------------------------------+
13. void NewColors(long id)
14. {
15.     ChartSetInteger(id, CHART_COLOR_CANDLE_BULL, clrGreen);
16.     ChartSetInteger(id, CHART_COLOR_CANDLE_BEAR, clrFireBrick);
17.     ChartSetInteger(id, CHART_COLOR_CHART_UP, clrBlack);
18.     ChartSetInteger(id, CHART_COLOR_CHART_DOWN, clrBlack);
19.     ChartSetInteger(id, CHART_COLOR_CHART_LINE, clrBlue);
20. }
21. //+------------------------------------------------------------------+
22. int OnInit(void)
23. {
24.     szObject = def_Prefix + (string)ObjectsTotal(0, -1, -1);
25.     ObjectCreate(0, szObject , OBJ_CHART, 0, 0, 0);
26.     ObjectSetString(0, szObject, OBJPROP_SYMBOL, _Symbol);
27.     ObjectSetInteger(0, szObject, OBJPROP_XDISTANCE, 0);
28.     ObjectSetInteger(0, szObject, OBJPROP_YDISTANCE, 0);
29.     ObjectSetInteger(0, szObject, OBJPROP_PERIOD, PERIOD_M15);
30.     ObjectSetInteger(0, szObject, OBJPROP_DATE_SCALE, false);
31.     ObjectSetInteger(0, szObject, OBJPROP_PRICE_SCALE, false);
32.    
33.     return INIT_SUCCEEDED;
34. };
35. //+------------------------------------------------------------------+
36. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
37. {
38.     return rates_total;
39. };
40. //+------------------------------------------------------------------+
41. void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
42. {
43.     switch(id)
44.     {
45.         case CHARTEVENT_CHART_CHANGE:
46.             ObjectSetInteger(0, szObject, OBJPROP_XSIZE, ChartGetInteger(0, CHART_WIDTH_IN_PIXELS) / 2);
47.             ObjectSetInteger(0, szObject, OBJPROP_YSIZE, ChartGetInteger(0, CHART_HEIGHT_IN_PIXELS));
48.             NewColors(0);
49.             break;
50.     }
51.     ChartRedraw();
52. };
53. //+------------------------------------------------------------------+
54. void OnDeinit(const int reason)
55. {
56.     ObjectsDeleteAll(0, def_Prefix);
57.     ChartRedraw();
58. };
59. //+------------------------------------------------------------------+

Código 03

A ideia é bem simples. Dado o gráfico visto na imagem 03, queremos que ao adicionarmos este código 03, as cores das barras sejam modificadas. Este tipo de coisa, que estamos fazendo aqui, se parece muito com o que foi feito, em outro artigo nesta mesma sequência Do básico ao intermediário: Indicador (IV). No entanto, diferente do que acontecia no artigo mencionado. Aqui estamos fazendo a mudança de cor na unha, por assim dizer. Ou seja, o MetaTrader 5, não tem nenhum envolvimento direto, sendo apenas o responsável por apresentar os resultados para nós. Como resultado da execução deste código 03, temos o que é visto na imagem logo na sequência.


Imagem 09

Ótimo, temos a confirmação de que as cores estão sendo modificadas. O detalhe, é que se você remover o indicador do gráfico, o padrão de cores permanecerá. Visto que não salvamos o padrão antigo, para poder o repor no gráfico. Esta talvez seja a maior diferença entre fazer as coisas como mostrado aqui, e as fazer como foi mostrado no passado. Onde usávamos o MetaTrader 5, para que o padrão de cores nos fosse apresentado.

Ok, como aqui o objetivo é didático, não me preocuparei em recuperar, ou mesmo salvar o padrão de cores original. Assim sendo, podemos passar para o próximo passo. Este consiste em fazer com que o procedimento visto na linha treze deste código 03 seja aplicado ao objeto OBJ_CHART. Fazendo assim com que o padrão de cores seja aplicado aos elementos plotados no objeto OBJ_CHART. A ideia é simples, mas como faremos isto, na prática? Bem, você precisa se lembrar que um objeto OBJ_CHART é, na verdade, um gráfico, e como tal, ele tem uma identidade. Assim, perceba o seguinte: se na linha quarenta e oito do código 03, indicarmos qual a identidade do gráfico a receber os valores do procedimento da linha treze. Naturalmente o MetaTrader 5 deverá saber a qual gráfico aplicar aqueles mesmos valores.

Concorda comigo a este respeito? Pois bem, e como podemos saber qual é a identidade do gráfico presente no objeto OBJ_CHART? De certa maneira, esta é a parte fácil, já que na biblioteca do MQL5, temos os mecanismos necessários para que isto seja efetivado. Assim sendo, a única coisa que precisamos mudar no código 03 é justamente a linha quarenta e oito. E esta deverá ser substituída pela linha mostrada logo a seguir.

NewColors(ObjectGetInteger(0, szObject, OBJPROP_CHART_ID));

Agora executando novamente o código 03, depois desta pequena modificação, temos como resultado o que é visto na animação logo abaixo.


Animação 01

Mas o que aconteceu aqui? Bem, isto foi um tanto quanto inusitado, devo confessar que não estava esperando que o resultado fosse justamente este. Esperava que as coisas ficassem diferentes. Ou pelo menos que fosse feita alguma mudança nas cores dos elementos plotados no gráfico do objeto OBJ_CHART. Mas aparentemente não funcionou, como esperado.

De fato, meu amigo, este tipo de coisa costuma acontecer bastante. Ainda mais quando estamos aprendendo como as coisas funcionam. Quem já tem experiência logo percebe o problema, já que terá passado por este tipo de situação por diversas vezes. No entanto, para quem está começando, este resultado visto na animação, não é nada animador. Muito pelo contrário, ele acaba nos broxando e nos deixando meio sem uma direção, já que aquilo que achávamos que funcionaria, se mostrou nada funcional.

Porém, se você estudar a documentação, verá que é mencionado um fato um tanto quanto interessante. Mudanças feitas no gráfico são colocados em uma fila de execução, para serem apresentadas em algum momento no futuro. Mas, e esta é a parte importante de entender, normalmente estas mudanças somente são enfileiradas, em certas situações. Em outras elas podem simplesmente ficarem perdidas, não sendo nunca executadas. Um destes casos é justamente este que você observa na animação 01. A identidade do gráfico presente no objeto OBJ_CHART, é diferente da que usualmente o MetaTrader 5 estará de fato tomando conta, por padrão. Por este motivo a mudança, que desejamos que ocorresse não será devidamente colocada na fila de execução. Ela precisa ser executada de forma explicita por nosso código, somente assim ela será aplicada. E é assim que surge a experiência daquilo que precisa ser feito neste código 03, para que a modificação desejada tenha efeito no gráfico.

Observe que, pelo motivo da linha quarenta e oito, ter sido modificada com o conteúdo mostrado acima. Temos dentro do procedimento da linha treze, o valor da identidade do gráfico que precisa ser redesenhado. Para efetuarmos este redesenho, ou melhor dizendo, para podermos forçar o MetaTrader 5, a redesenhar o gráfico presente no objeto OBJ_CHART, precisamos dizer a função de biblioteca ChartRedraw, qual a identidade do gráfico a ser redesenhado imediatamente. Sabendo disto, podemos modificar o código 03 para conseguir o que é visto no código 04. Que é o código mostrado na íntegra 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. #define def_Prefix "DEMO_"
10. //+------------------------------------------------------------------+
11. string szObject;
12. //+------------------------------------------------------------------+
13. void NewColors(long id)
14. {
15.     ChartSetInteger(id, CHART_COLOR_CANDLE_BULL, clrGreen);
16.     ChartSetInteger(id, CHART_COLOR_CANDLE_BEAR, clrFireBrick);
17.     ChartSetInteger(id, CHART_COLOR_CHART_UP, clrBlack);
18.     ChartSetInteger(id, CHART_COLOR_CHART_DOWN, clrBlack);
19.     ChartSetInteger(id, CHART_COLOR_CHART_LINE, clrBlue);
20.     ChartRedraw(id);
21. }
22. //+------------------------------------------------------------------+
23. int OnInit(void)
24. {
25.     szObject = def_Prefix + (string)ObjectsTotal(0, -1, -1);
26.     ObjectCreate(0, szObject , OBJ_CHART, 0, 0, 0);
27.     ObjectSetString(0, szObject, OBJPROP_SYMBOL, _Symbol);
28.     ObjectSetInteger(0, szObject, OBJPROP_XDISTANCE, 0);
29.     ObjectSetInteger(0, szObject, OBJPROP_YDISTANCE, 0);
30.     ObjectSetInteger(0, szObject, OBJPROP_PERIOD, PERIOD_M15);
31.     ObjectSetInteger(0, szObject, OBJPROP_DATE_SCALE, false);
32.     ObjectSetInteger(0, szObject, OBJPROP_PRICE_SCALE, false);
33.    
34.     return INIT_SUCCEEDED;
35. };
36. //+------------------------------------------------------------------+
37. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
38. {
39.     return rates_total;
40. };
41. //+------------------------------------------------------------------+
42. void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
43. {
44.     switch(id)
45.     {
46.         case CHARTEVENT_CHART_CHANGE:
47.             ObjectSetInteger(0, szObject, OBJPROP_XSIZE, ChartGetInteger(0, CHART_WIDTH_IN_PIXELS) / 2);
48.             ObjectSetInteger(0, szObject, OBJPROP_YSIZE, ChartGetInteger(0, CHART_HEIGHT_IN_PIXELS));
49.             NewColors(ObjectGetInteger(0, szObject, OBJPROP_CHART_ID));
50.             break;
51.     }
52.     ChartRedraw();
53. };
54. //+------------------------------------------------------------------+
55. void OnDeinit(const int reason)
56. {
57.     ObjectsDeleteAll(0, def_Prefix);
58.     ChartRedraw();
59. };
60. //+------------------------------------------------------------------+

Código 04

Consequentemente, ao compilarmos este código 04 e o executarmos. Passaremos a ter como resultado o que é observado na animação logo abaixo.


Animação 02

Caramba, que coisa mais maluca e sem noção. Definitivamente, nunca imaginaria que seria tão simples assim. Chega a ser até mesmo algo, que se você não tivesse esta calma em me explicar, eu não prestaria a devida atenção e acabaria passando batido. Já que tudo não passou de um simples detalhe que precisou ser modificado no código. Porém, este simples detalhe fez toda a diferença no final das contas. De fato, agora consigo entender, porque não nunca conseguia fazer algumas coisas. E muito menos conseguia entender aqueles seus primeiros artigos. Já que você, não explicava estes detalhes antes. Fico feliz por você mudar a forma de explicar as coisas e de fazer os artigos.

Ok, mas não me agradeça. Agradeça aqueles que insistiram e me pediram para fazer artigos voltados a iniciantes. Pois sem estas pessoas terem mostrado interesse neste tipo de artigo. Esta sequência, jamais seria escrita.

Agora vamos fazer uma última modificação, por assim dizer, a este código 04. Esta mudança, visa fazer justamente a tal cópia dos valores, que estão presentes no gráfico principal, para dentro do gráfico que estará sendo plotado dentro do objeto OBJ_CHART. O código que faz isto é 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_Prefix "DEMO_"
10. //+------------------------------------------------------------------+
11. string szObject;
12. //+------------------------------------------------------------------+
13. void NewColors(long id)
14. {
15.     ChartSetInteger(id, CHART_COLOR_CANDLE_BULL, ChartGetInteger(0, CHART_COLOR_CANDLE_BULL));
16.     ChartSetInteger(id, CHART_COLOR_CANDLE_BEAR, ChartGetInteger(0, CHART_COLOR_CANDLE_BEAR));
17.     ChartSetInteger(id, CHART_COLOR_CHART_UP, ChartGetInteger(0, CHART_COLOR_CHART_UP));
18.     ChartSetInteger(id, CHART_COLOR_CHART_DOWN, ChartGetInteger(0, CHART_COLOR_CHART_DOWN));
19.     ChartSetInteger(id, CHART_COLOR_CHART_LINE, ChartGetInteger(0, CHART_COLOR_CHART_LINE));
20.     ChartRedraw(id);
21. }
22. //+------------------------------------------------------------------+
23. int OnInit(void)
24. {
25.     szObject = def_Prefix + (string)ObjectsTotal(0, -1, -1);
26.     ObjectCreate(0, szObject , OBJ_CHART, 0, 0, 0);
27.     ObjectSetString(0, szObject, OBJPROP_SYMBOL, _Symbol);
28.     ObjectSetInteger(0, szObject, OBJPROP_XDISTANCE, 0);
29.     ObjectSetInteger(0, szObject, OBJPROP_YDISTANCE, 0);
30.     ObjectSetInteger(0, szObject, OBJPROP_PERIOD, PERIOD_M15);
31.     ObjectSetInteger(0, szObject, OBJPROP_DATE_SCALE, false);
32.     ObjectSetInteger(0, szObject, OBJPROP_PRICE_SCALE, false);
33.    
34.     return INIT_SUCCEEDED;
35. };
36. //+------------------------------------------------------------------+
37. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
38. {
39.     return rates_total;
40. };
41. //+------------------------------------------------------------------+
42. void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
43. {
44.     switch(id)
45.     {
46.         case CHARTEVENT_CHART_CHANGE:
47.             ObjectSetInteger(0, szObject, OBJPROP_XSIZE, ChartGetInteger(0, CHART_WIDTH_IN_PIXELS) / 2);
48.             ObjectSetInteger(0, szObject, OBJPROP_YSIZE, ChartGetInteger(0, CHART_HEIGHT_IN_PIXELS));
49.             NewColors(ObjectGetInteger(0, szObject, OBJPROP_CHART_ID));
50.             break;
51.     }
52.     ChartRedraw();
53. };
54. //+------------------------------------------------------------------+
55. void OnDeinit(const int reason)
56. {
57.     ObjectsDeleteAll(0, def_Prefix);
58.     ChartRedraw();
59. };
60. //+------------------------------------------------------------------+

Código 05

Apesar de funcionar, este código 05 é pavoroso e horrendo. Não gosto de criar coisas desta maneira. Pois dá a impressão de que não sabemos o que estamos de fato fazendo. Além é claro, tornar tudo muito mais trabalhoso e cansativo. Isto conforme nova coisas vão sendo necessárias e sendo implementadas. E o motivo está no fato de que dentro do procedimento da linha treze, estamos duplicando as coisas de uma maneira muito arriscada. O que acaba deixando o código muito suscetível a erros de digitação ou a falhas de edição ao longo do tempo.

Na minha humilde e modesta opinião, este código 05, ficaria muito mais bem escrito, se ele fosse feito 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_Prefix "DEMO_"
10. //+------------------------------------------------------------------+
11. string szObject;
12. //+------------------------------------------------------------------+
13. void NewColors(long id)
14. {
15.     const ENUM_CHART_PROPERTY_INTEGER list[] = {
16.         CHART_COLOR_CANDLE_BULL,
17.         CHART_COLOR_CANDLE_BEAR,
18.         CHART_COLOR_CHART_UP,
19.         CHART_COLOR_CHART_DOWN,
20.         CHART_COLOR_CHART_LINE
21.     };
22.     
23.     for (uint c = 0; c < list.Size(); c++)
24.         ChartSetInteger(id, list[c], ChartGetInteger(0, list[c]));
25.     ChartRedraw(id);
26. }
27. //+------------------------------------------------------------------+
28. int OnInit(void)
29. {
30.     szObject = def_Prefix + (string)ObjectsTotal(0, -1, -1);
31.     ObjectCreate(0, szObject , OBJ_CHART, 0, 0, 0);
32.     ObjectSetString(0, szObject, OBJPROP_SYMBOL, _Symbol);
33.     ObjectSetInteger(0, szObject, OBJPROP_XDISTANCE, 0);
34.     ObjectSetInteger(0, szObject, OBJPROP_YDISTANCE, 0);
35.     ObjectSetInteger(0, szObject, OBJPROP_PERIOD, PERIOD_M15);
36.     ObjectSetInteger(0, szObject, OBJPROP_DATE_SCALE, false);
37.     ObjectSetInteger(0, szObject, OBJPROP_PRICE_SCALE, false);
38.    
39.     return INIT_SUCCEEDED;
40. };
41. //+------------------------------------------------------------------+
42. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
43. {
44.     return rates_total;
45. };
46. //+------------------------------------------------------------------+
47. void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
48. {
49.     switch(id)
50.     {
51.         case CHARTEVENT_CHART_CHANGE:
52.             ObjectSetInteger(0, szObject, OBJPROP_XSIZE, ChartGetInteger(0, CHART_WIDTH_IN_PIXELS) / 2);
53.             ObjectSetInteger(0, szObject, OBJPROP_YSIZE, ChartGetInteger(0, CHART_HEIGHT_IN_PIXELS));
54.             NewColors(ObjectGetInteger(0, szObject, OBJPROP_CHART_ID));
55.             break;
56.     }
57.     ChartRedraw();
58. };
59. //+------------------------------------------------------------------+
60. void OnDeinit(const int reason)
61. {
62.     ObjectsDeleteAll(0, def_Prefix);
63.     ChartRedraw();
64. };
65. //+------------------------------------------------------------------+

Código 06

O resultado será exatamente, o mesmo. Porém, note que o risco de ter alguma falha da digitação ou na edição do código ao longo do tempo, cai consideravelmente. E isto, pelo simples fato de que mudamos, a forma de estruturar os próprios dados. De fato, quando percebermos que estamos lendo uma informação de um local e aplicando o resultado em outro local, fica mais fácil simplificarmos as coisas. Portanto, ao colocar tudo em uma lista de informações a serem tratadas, tornamos um tanto quanto menos arriscado fazer alguma bobagem no futuro.

Está definitivamente não seria a minha primeira escolha. Isto por conta justamente do fato de que, precisaremos colocar na lista, todo e qualquer tipo de argumento que precisará ser copiado de um local para outro. E como aqui, queremos copiar absolutamente todos os argumentos presentes em um gráfico. Manter e criar esta lista, se torna uma tarefa um tanto quanto cansativa e sujeita a erros. Mesmo que você faça tudo com a maior calma e prestando a máxima atenção, não é garantido que não haverá erros. De qualquer forma, este código 06, é bem mais simples e seguro do que o código 05, apesar de ambos fazerem o mesmo.

Justamente por este motivo, é que esta abordagem em que fazemos a cópia de valores não é a minha preferida. Prefiro utilizar outros métodos. Além do que, fazer as coisas como foi visto aqui, acaba nos limitando, a poder ou não fazer alguns tipos de escolhas. Onde surge a ideia que muitos têm sobre o fato de acreditarem ser necessário um código imenso e todo rebuscado, para obter algum resultado prático. Que, no entanto, pode ser feito, com um código mínimo e muito mais simples. O que por um lado, facilita para quem entende o que está sendo feito, mas dificulta enormemente para aquele que esperavam encontrar outro tipo de coisa presente no código. E é por conta disto, que daremos cada um dos passos, com bastante calma e com muita atenção. Pois este tipo de coisa apesar de ser muito legal, acaba tornando tudo muito mais confuso, para quem esteja esperando a implementação de um determinado tipo de código.


Considerações finais

Neste artigo vimos a base inicial daquilo que seria um template e como poderíamos usá-lo para transferir as configurações do gráfico principal, para dentro do gráfico criado e mantido por um objeto OBJ_CHART. Mesmo que você imagine ter entendido perfeitamente o que se passou aqui. Gostaria que você fizesse uma pequena experiência. Procure digitar os códigos vistos aqui, e os experimente conforme você vai adicionando cada uma das chamadas que os códigos estarão fazendo a biblioteca do MQL5. Isto permitirá que você, veja na prática, como de fato seu código precisa ser construído e pensado. Apesar de no anexo, você ter os códigos na íntegra, ver e entender o tipo de problema e defeito que a presença ou não de alguma chamada faz no código, lhe ajudará imensamente a entender melhor como a programação MQL5 precisa ser pensada e implementada. O que lhe dará uma experiência muito maior como programador.
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
Indicators\Code 04  Demonstração básica
Arquivos anexados |
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.
Redes neurais em trading: Desvendando os componentes estruturais (Final) Redes neurais em trading: Desvendando os componentes estruturais (Final)
O artigo apresenta em detalhes a arquitetura SCNN e uma das opções de implementação com recursos do MQL5. Mostraremos como a decomposição de séries temporais se combina com métodos de redes neurais e mecanismos de atenção.
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.
Componentes View e Controller para tabelas no paradigma MVC em MQL5: dimensões ajustáveis dos elementos Componentes View e Controller para tabelas no paradigma MVC em MQL5: dimensões ajustáveis dos elementos
No artigo, adicionaremos a funcionalidade de redimensionamento dos elementos de controle por meio do arrasto das bordas e dos cantos do elemento com o mouse.