preview
Do básico ao intermediário: Variáveis (III)

Do básico ao intermediário: Variáveis (III)

MetaTrader 5Exemplos | 31 julho 2024, 14:59
184 0
CODE X
CODE X

Introdução

O conteúdo exposto aqui, visa e tem como objetivo, pura e simplesmente a didática. De modo algum deve ser encarado como uma aplicação final, onde o objetivo não seja o estudo dos conceitos aqui mostrados.

No artigo anterior Do básico ao intermediário: Variáveis (II), falamos e explicamos como utilizar variáveis do tipo estática em seus códigos. Isto a fim de evitar justamente a utilização desnecessária de variáveis globais. Muito bem, o que temos a tratar sobre variáveis, pelo menos o básico sobre o assunto, está chegando ao seu final. Apesar de que, existe a questão sobre o tipo de dados que cada variável pode conter, ainda está de alguma forma relacionada ao assunto. Não vou tratar dele dentro do assunto variáveis. Iremos tratar deste tipo de coisa em um outro tópico, voltado apenas a isto.

Mas se já tratamos sobre a questão de variáveis locais e globais. Sobre como e por que declarar uma variável como sendo uma constante. E até mesmo falamos e foi explicado como utilizar variáveis do tipo estática. O que mais resta falar sobre este assunto ?!?! Bem, meu caro leitor. Apesar de muitos não considerarem desta maneira. Existe um tipo muito especial de variável. Que em muitos casos pode ser considerado como sendo uma constante. Mas ainda assim, não deixa de ser um tipo especial de variável. Neste caso, estou falando de funções. E sim, uma função é um tipo especial de variável. Mesmo que a princípio não venha a ser pensada desta maneira, por muitos programadores.

Porém para que você possa entender por que eu estou dizendo que uma função é uma variável especial. Vamos iniciar um novo tópico.


Uma variável especial: As funções

Quando se fala em funções, a primeira coisa que vem à mente, de quem tem algum tipo de conhecimento, mesmo que básico sobre programação. É a utilização de uma chamada extra para executar algum tipo de rotina em nossa aplicação. Porém esta definição não é tão adequada ao termo. Isto por conta que, podemos ter rotinas, que pode não ser funções. Mas sim procedimento. Existe uma pequena diferença conceitual entre um e outro tipo. No entanto, a principal diferença é o fato de que uma função retorna um valor, ou para ser mais preciso, um tipo de dado. Diferente de um procedimento, que não irá retornar nenhum tipo de dado, depois de ser executado. Porém, ambos tipos de rotinas, podem modificar e retornar valores diferentes para seus argumentos.

Mas não se preocupe, ou esquente a sua cabeça com isto, neste momento. Apenas estou dando uma breve descrição do que será visto em mais detalhes futuramente. Porém esta pequena distinção precisa de fato ser feita neste momento. Isto para que você consiga compreender por que digo que uma função é um tipo de variável especial.

Aqui precisamos fazer um paralelo entre algumas linguagens diferentes. Isto por que, dependendo da linguagem que você vier a desejar estudar futuramente. O conceito que será visto aqui, pode não ser aplicável. Devido justamente a forma como a linguagem é implementada para cumprir suas tarefas.

Normalmente linguagem de script, como JavaScript e Python, implementam funções de forma que elas são apenas um tipo de variável constante. Porém em C e C++, uma função pode ser tanto uma variável constante como também uma variável do tipo que você pode modificar o valor de alguma variável estática presente na função. Isto sem passar nenhum tipo de argumento para a função. Para muitos isto pode suar extremamente estranho e sinistro. Já que aparamente tal coisa não deveria ocorrer. No entanto, em C e C++ existe uma entidade chamada ponteiro. E se esta entidade for usada para retornar uma referência a uma variável estática presente na função. O código que estiver usando a função, conseguirá modificar o valor da variável estática.

Este tipo de coisa, torna programar em C e C++ uma verdadeira aventura. Apesar de ser algo muitas vezes potencialmente perigoso. Tal recurso, permite e dá um grau de liberdade muito grande ao programador. No entanto em MQL5 puro, ficamos em um meio termo, entre o que seria a forma de trabalhar de função em JavaScript e Python. E algo que seria próximo das possibilidades presentes em C e C++. Apesar de que não teremos um grau de liberdade tão grande quanto o que existe no C e C++. Mas novamente, isto nos dá um grau de segurança maior durante a codificação.

Ok. Para que não fiquemos apenas na parte teórica, que é muito chato. Vamos ver alguns exemplos simples de funções, onde podemos usar elas como sendo um tipo de variável constante. Um exemplo bastante típico, seria usar ela como sendo um tipo de definição de valor. Só que, ao invés de usar o valor, usamos um nome mais adequado e que seja representativo para nós.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     Print(One_Radian());
07. }
08. //+------------------------------------------------------------------+
09. double One_Radian()
10. {
11.     return 180. / M_PI;
12. }
13. //+------------------------------------------------------------------+

Código 01

Aqui no código 01, temos um exemplo bastante simples, para que você consiga compreender de maneira bem eficiente o que estou querendo falar. Quando este código 01 for executado, você terá o resultado visto logo abaixo.


Imagem 01

Certo. Você neste momento pode estar se perguntando: Por que fazer as coisas assim ?!?! Não seria mais fácil colocar o cálculo da linha 11 diretamente na linha 06 e imprimir o resultado ?!?! Sim, seria. Porém se você pensou isto. Significa que você não captou a ideia que quero passa ao mostrar este exemplo. A ideia NÃO é executar o cálculo em si. A ideia é gerar uma constante que possa ser utilizada de maneira global em qualquer parte de seu código. Se toda a vez que você necessitar saber o valor de uma constante, precisar digitar o código para criar tal constante. Seu trabalho no momento de melhorar ou mesmo corrigir o código será imenso. Porém, se tudo estiver contido dentro de uma função. Que tenha um nome representativo, e que gere a tal constante. Tudo será muito mais simples, rápido e tranquilo. Lhe tornando muito mais eficiente como programador.

Pense no fato de que você pode estar criado um programa 3D. E que venha a necessitar do valor em graus dentro de um radiano. Porém não apenas em uma única linha do código, mas em centenas de linhas espalhadas por todo o código. Neste ponto lhe pergunto: Qual é mais fácil. Digitar cálculo toda a vez, ou colocar tudo em uma função como mostrado no código 01 ?!?!

Bem, está seria uma aplicação. No entanto se você a considerou tola e sem muito proposito, que tal criarmos algo um pouco mais elaborado com o conhecimento que já temos dos artigos anteriores ?!?! Isto pode ser feito como mostrado logo abaixo.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     Counting();
07.     Print(Counting());
08.     Counting();
09.     Counting();
10.     Print(Counting());
11. }
12. //+------------------------------------------------------------------+
13. ulong Counting(void)
14. {
15.     static ulong Tic_Tac = 0;
16. 
17.     Tic_Tac = Tic_Tac + 1;
18. 
19.     return Tic_Tac;
20. }
21. //+------------------------------------------------------------------+

Código 02

Neste caso quando este código 02 for executado, você terá um resultado como o mostrado logo abaixo.


Imagem 02

Ou seja, se o primeiro exemplo não lhe pareceu muito adequado. Talvez este segundo possa ser. Isto por que, podemos precisar contar quantas vezes algo ocorreu em uma dada aplicação. Muitos iriam utilizar uma variável global para efetuar a contabilidade de tais eventos. No entanto, como foi visto nos artigos anteriores. Existe um porém, ao utilizar uma variável global. Entretanto usando uma função, com um objetivo parecido. Eliminamos aqueles inconvenientes de utilizar uma variável global e ao mesmo tempo, garantimos uma boa estabilidade e segurança no nosso código. Além é claro, nos permitir modificar as regras de maneira muito simples, rápida e prática.


Variáveis predefinidas

Além destas coisas das quais já falamos, sobre variáveis e constantes. Ainda existem algumas outras, dentro do MQL5, que também é necessário mencionar. Isto por que elas fazem parte de um programa que visa utilizar profundamente recursos da linguagem.

Aqui vamos dar uma rápida passada nestes tipos especiais de variáveis. Isto por que é necessário você entender que tais variáveis existem e que você pode utilizar elas para determinadas tarefas.

Na documentação, você pode as encontrar mais detalhes sobre elas em:Variáveis Predefinidas. Porém aqui não iremos falar de nenhuma específica. Mas vamos entender que apesar de serem chamadas de variáveis predefinidas, elas na verdade, não são variáveis do tipo comumente utilizadas. Para o nosso código, elas são tratadas como sendo constantes. Porém para o MetaTrader 5, elas são de fato variáveis. Porém apesar de serem vistas como sendo constantes para nosso código. Existem em alguns dos casos, a possibilidade de usarmos alguma função ou procedimento da linguagem MQL5, a fim de modificar o valor de tal variável.

É muito importante que você entenda isto meu caro leitor. Se você tentar modificar diretamente o valor de uma destas variáveis, irá estar cometendo um erro. E seu código não será compilado. Quando digo tentar modificar diretamente o valor da variável, é tentar fazer algo do tipo mostrado abaixo.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     Print(_LastError);
07.     _LastError = 2;
08.     Print(_LastError);
09. }
10. //+------------------------------------------------------------------+

Código 03

Se você está iniciando no MQL5, preste atenção ao que irei explicar. Na linha seis deste código 03 estamos pedindo para que seja impresso no terminal, o atual valor que se encontra na variável _LastError. Como esta é uma variável predefinida dentro do MQL5, não precisamos declarar ela. O compilador é capaz de entender perfeitamente a sua presença.

No entanto, no momento em que o compilador encontrar com a linha sete vista neste código 03. Um erro será disparado, como você pode observar na imagem logo abaixo.

Figura 03

Mas por que isto acontece ?!?! O motivo é que estas variáveis predefinidas, existentes no MQL5, são tratadas como constantes. Isto no nível de programação que você esteja tentando utilizar. Porém no nível de código a ser utilizado pelo MetaTrader 5, durante a fase de execução, estas mesmas variáveis não são vistas como sendo constantes.

Este tipo de coisa parece muito confuso e complicado de se entender à primeira vista. Ainda mais por quem está iniciando na programação. No entanto, antes de entrar em outras questões sobre estas variáveis predefinidas. Você meu caro leitor, deve entender o seguinte fato: Como estas variáveis irão existir em qualquer código do MQL5, você NÃO DEVE tentar colocar uma outra variável com o mesmo nome destas variáveis predefinidas. Isto por que, ao tentar fazer isto, você também estará tentando violar a própria segurança imposta pela plataforma.

Porém, toda via e, entretanto, apesar de para um acesso direto, como foi visto no código 03. Estarmos de fato cometendo um erro. A própria linguagem MQL5, nos fornece meios de ajustar algumas destas variáveis predefinidas. Isto para fins e propósitos gerais. Não existe uma regra para que você defina tais variáveis com este ou aquele valor. No entanto, qualquer mudança, quando possível de ser feita, deve ser feita por um motivo justificável. Você não deve modificar o valor de tais variáveis, apenas por ser possível de fazer. Salvo o fato de estar estudando a própria linguagem, como estamos fazendo aqui.

Por exemplo, se usarmos a função SetUserError, podemos definir um valor para a variável predefinida _LastError. Mas não qualquer valor. O valor que iremos conseguir colocar ali, estará deslocado. Já que existem uma lista de valores de erro também reservados para uso pelo próprio MQL5. Isto para muitos pode parecer um tanto quanto desanimador. Já que muitos ao ver este tipo de coisa, considera uma limitação do que podemos fazer. Sendo que não é bem assim.

Para verificar isto na prática, você pode utilizar o código visto logo abaixo.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     Print(_LastError);
07.     SetUserError(2);
08.     Print(_LastError);
09. }
10. //+------------------------------------------------------------------+

Código 04

Este código irá de fato compilar e poderá ser executado. No entanto quando você o executar no MetaTrader 5, irá ver algo parecido com o mostrado na imagem abaixo.


Imagem 04

Epá. Mas que número doido é este ?!?! Espere um pouco aí. De fato, na linha sete do código 04 estamos colocando o mesmo valor que na mesma linha do código 03. Tudo bem, que o código 03 não tenha sido compilado pelos motivos que você explicou. Mas ainda assim este valor na imagem quatro não é o que eu estava esperando.

De fato, meu caro leitor. Este valor, é o que você colocou, ou desejou colocar na variável _LastError, só que ele foi deslocado. Isto para impedir que ele entrasse em conflito com algum valor predefinido de erro. Para que você reveja o valor que você desejou colocar na variável _LastError, é preciso fazer um pequeno ajuste. Mas antes de ver que ajuste é este, vamos entender uma outra coisa. Normalmente, para muitos programadores, não é muito comum usar o nome da variável predefinida diretamente no código. Muitos preferem, e de fato é o mais indicado ser feito, usar uma função que nos retorne o valor de uma variável predefinida. Mas nada impede de você usar o código como foi mostrado acima. Porém o mais comum, e para muitos o mais correto seria usar um código como mostrado logo abaixo.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     Print(GetLastError());
07.     SetUserError(2);
08.     Print(GetLastError());
09. }
10. //+------------------------------------------------------------------+

Código 05

Note que basicamente o código irá executar a mesma coisa. Porém para muitos, este código 05 é mais legível que o código 04. Isto justamente por conta do fato, de que estaremos deixando claro para todos os demais programadores, que vierem a ler o código. De que estamos lendo um valor de alguma variável. Notaram como o que foi visto no tópico anterior se aplica aqui também ?!?! A forma como você irá acessar, para fins de leitura, as variáveis predefinidas não importa. Porém a forma de modificar os valores das mesmas, será sempre o mesmo. Como por exemplo: Para remover qualquer valor presente na variável _LastError, você NÃO DEVE usar o procedimento visto na linha sete destes últimos código. Pois se fizer isto, irá anotar um novo valor de erro. O correto para limpar, ou remover qualquer erro que esteja em _LastError, é usando um outro procedimento fornecido pelo MQL5. Este pode ser visto logo abaixo.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     Print(GetLastError());
07.     SetUserError(2);
08.     Print(GetLastError());
09.     SetUserError(0);
10.     Print(GetLastError());
11.     ResetLastError();
12.     Print(GetLastError());
13. }
14. //+------------------------------------------------------------------+

Código 06

Agora, se é a primeira vez que você está vendo isto, preste atenção meu caro leitor. Quando este código for executado, o resultado será o que é visto logo abaixo.


Imagem 05

Note o seguinte: Quando a linha seis executar, será impresso a primeira linha que você vê na imagem 05. Indicando que de fato não temos nenhum erro, ou valor na variável _LastError. Assim que a linha sete executar, iremos colocar um valor na variável _LastError. Como foi visto anteriormente. Porém, muitos iniciantes tentam fazer uso da linha nove a fim de limpar a variável _LastError. No entanto, ao fazer isto, e imprimir o resultado teremos um valor diferente de zero. Por que ?!?! O motivo é o mesmo que já falei anteriormente. Quando usamos SetUserError, para definir um valor em _LastError, este valor será deslocado. Por isto, tentar colocar qualquer valor usando esta função não irá resultar no valor imaginado. Mas, como nosso objetivo aqui é colocar o valor zero na variável _LastError. A forma correta é usando a linha 11. Quando este procedimento da linha 11 é executado, de fato o valor zero será atribuído a _LastError.

E isto dever ser observado para todas as demais variáveis predefinidas. Claro que aqui não irei mostrar um por um, os procedimentos envolvidos. Já que bastará que você consulte a documentação para entender quais os procedimentos corretos, caso existam, para definir valores a tais variáveis. No entanto o processo de leitura de tais valores podem ser feito de maneira direta, como foi mostrado no começo do tópico. Ou seja, usando o próprio nome da variável predefinida.

Mas espere um pouco. Até consegui acompanhar e compreender o que foi explicado aqui. Porém ainda não entendi a questão do deslocamento de valor que você mencionou por diversas vezes durante o tópico. Poderia me explicar isto melhor. Assim quem sabe eu possa usar os valores que coloquei na variável _LastError. Ao invés de usar estes valores doidos que aparecem no terminal, quando imprimimos o valor da variável.

De fato, este é um pedido valido e que merece de fato ser explicado. Sendo assim vamos explicar ele em um novo tópico. Já que poderemos falar de outras coisas também envolvidas aqui.


Enumerações e definições de constantes

Uma das questões que ao meu ver é a mais difícil de definir. Seja em qualquer linguagem de programação. É o fato de existirem definições e enumerações na linguagem. E não me entenda mal, meu caro leitor. Ambas são muito utilizadas e ajudam bastante durante a programação. Porém é difícil de definir, apenas olhando a documentação, o que poderia ser uma enumeração e o que seria uma definição. Isto por que não tem como saber disto, salvo o fato de a documentação mencionar que tipo de modelagem está sendo utilizada.

Porém sem entrar em detalhes ainda sobre tais coisas. Já que iremos fazer isto em um outro momento. Podemos entrar na questão de entender, o que cada valor representa. Mas principalmente entender algumas coisas que normalmente aparecem nos códigos. Como textos que não fazem muito sentido à primeira vista. Um exemplo disto pode ser visto no código logo abaixo.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. int OnInit()
05. {
06.    return INIT_SUCCEEDED;
07. };
08. //+------------------------------------------------------------------+
09. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
10. {
11.    return rates_total;
12. };
13. //+------------------------------------------------------------------+

Código 07

Aqui temos na linha seis algo que para muitos não faz muito sentido. Apesar de ser visto em praticamente todo código de indicador. Iremos falar mais sobre isto em um momento oportuno meu caro leitor. Mas estou mostrando este código 07, apenas para exemplificar algo que você irá ver em muitos códigos. Apesar da palavra reservada return, esperar uma variável ou um valor. Aqui estamos usando um texto. Mas o que este texto significa e por que usamos ele e não outro qualquer ?!?! Na verdade, podemos usar outra coisa. Mas vamos dar um passo de cada vez.

Se você olhar em Constantes, Enumeradores e Estruturas, irá ver que existem muitas constantes e enumerações sendo definidas dentro do MQL5. Estas enumerações e constantes, como a que você pode ver na linha seis do código 07, recebem um nome na programação. Tais entidades são conhecidas como: Alias. E sim, a forma de escrever é esta mesma. Já que não podemos usar acentos em uma linguagem de programação. O objetivo é criar uma representação mais adequada para nos lembrarmos, ou facilitar a leitura do código. Tanto por que o criou, como também por parte de outros programadores.

Para que isto de fato fique claro, pense no seguinte meu caro leitor. Supondo que você esteja programando algo. E para dizer que seu código teve sucesso ao efetuar uma operação você queira voltar um valor verdadeiro, ou true, como é conhecido dentro do código. Como você faria isto ?!?!

Bem você poderia usar um valor maior que zero ou mesmo escrever a palavra true. Ambos funcionariam. EM TESE. Ou seja, aquele mesmo valor no código 07, na linha seis poderia ser escrito como mostrado abaixo.

//+------------------------------------------------------------------+
#property copyright "Daniel Jose"
//+------------------------------------------------------------------+
int OnInit()
{
   return true;
};
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
{
   return rates_total;
};
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
    Print(reason);
};
//+------------------------------------------------------------------+

Código 08

Porém ao fazer isto, seu código irá falhar. Mas por que ele irá falhar ?!?! Isto não faz o menor sentido. Já que ao usarmos o valor true, estamos dizendo que OnInit de fato foi concluído com sucesso. Sim meu caro leitor. De fato, quando retornamos true, estamos dizendo que algo foi executado sem erros. No entanto, mesmo assim seu código irá falhar, sendo fechado imediatamente depois que OnInit tenha sido executado. E o motivo para isto, está justamente no valor presente no alias INIT_SUCCEEDED.

Não é que não podemos usar outro valor ali, apenas você precisa entender que é o valor de INIT_SUCCEEDED está substituindo, de forma mais legível para nós humanos. Se você consultar a documentação irá ver que o valor de INIT_SUCCEEDED é na verdade zero. Sendo que em lógica booleana o valor zero representa um valor falso, ou false. Quando você usar um valor true, ou verdadeiro, o código 08 irá com certeza falhar, mesmo que não existe nenhum erro nele.

Um detalhe, se você executar este código 08, irá ver no terminal a seguinte mensagem sendo impressa. Imediatamente após o código ter sido executado.


Imagem 06

Sei que isto parece não fazer nenhum sentido, neste momento. Mas garanto que com o tempo, fará todo o sentido. Assim sendo, você poderia usar no código 08 o valor zero, ou false na linha seis. Que ele iria funcionar perfeitamente, esperando que você remova o indicador do gráfico. Porém não é somente este tipo de coisa, que pode ser usado. Você também poderia usar algo do tipo mostrado abaixo.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. int OnInit()
05. {
06.    return ERR_SUCCESS;
07. };
08. //+------------------------------------------------------------------+
09. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
10. {
11.    return rates_total;
12. };
13. //+------------------------------------------------------------------+
14. void OnDeinit(const int reason)
15. {
16.     Print(reason);
17. };
18. //+------------------------------------------------------------------+

Código 09

Neste caso mostrado no código 09, assim como no caso de usar o valor zero ou false, na linha seis do código 08. Você irá obter o resultado visto abaixo, assim que o indicador for removido do gráfico.


Imagem 07

Observe que não existe de fato uma regra rígida de como um código deve ser criado. Apenas regras que você deve entender, para que tudo funcione perfeitamente bem. Agora suponhamos que você de fato é um programador, extremamente rígido e que não aceita nenhum erro em suas aplicações. Neste caso, você poderia usar o código visto logo abaixo na mesma linha seis.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. int OnInit()
05. {
06.    return GetLastError();
07. };
08. //+------------------------------------------------------------------+
09. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
10. {
11.    return rates_total;
12. };
13. //+------------------------------------------------------------------+
14. void OnDeinit(const int reason)
15. {
16.     Print(reason);
17. };
18. //+------------------------------------------------------------------+

Código 10

Este seria um caso extremo, já que se durante a execução de qualquer parte do código presente em OnInit, houver a incidência de algum erro. O valor a ser retornado será diferente de zero, ou de alguns dos rótulos visto anteriormente que indicariam o valor zero. Isto por que GetLastError, que foi visto anteriormente, iria dizer que _LastError, tem algum valor dentro dela. Porém, você precisa entender, que o erro pode estar ocorrendo em qualquer ponto do código. E este pode ou não ser parte do que você programou. As vezes alguns erros ocorrem não devido a falha no código. Mas sim por conta de alguma interação entre valores. E isto pode fazer com que a variável _LastError, venha a ter um valor diferente de zero por qualquer motivo. Por isto este tipo de tratamento é um do tipo extremo. Raramente você irá ver algum tipo de código que venha a de fato usar este tipo de coisa. Mas se você desejar experimentar, irá ver que coisas engraçadas costumam acontecer.

Isto irá lhe dar maturidade e um melhor entendimento sobre como lidar com situações inesperadas. Mas faça isto com calma e muita paciência, meu caro leitor. Pois como ainda não explicamos como filtrar as coisas. Qualquer mínimo detalhe poderá lhe deixar completamente desorientado, tentando entender por que hora uma aplicação funciona, hora ela deixa de funcionar. Isto sem nenhum motivo aparente.

Muito bem, como última coisa a ser dita e mostrada neste artigo, vamos ver como o uso das constantes e enumerações definidas internamente pelo MQL5, pode influenciar nossa vida. Como foi mostrado no tópico anterior, ao usarmos o procedimento SetUserError, conseguimos colocar um valor qualquer na variável de sistema _LastError. Mas e se desejarmos saber qual foi exatamente o valor colocado em SetUserError. Como fazer ?!?! Esta é a parte simples meu caro leitor. Na própria documentação sobre SetUserError, está descrito como deve ser feito o ajuste. Segue parte do texto da documentação:

Define a variável predefinida _LastError para o valor igual a ERR_USER_ERROR_FIRST + user_error

Ou seja, se subtrairmos ERR_USER_ERROR_FIRST do valor encontrado em _LastError, saberemos qual o valor que foi definido em SetUserError. Então veja um exemplo de aplicação no código logo abaixo.

01. //+------------------------------------------------------------------+
02. #property copyright "Daniel Jose"
03. //+------------------------------------------------------------------+
04. void OnStart(void)
05. {
06.     Print(GetLastError());
07.     SetUserError(2);
08.     Print(GetLastError());
09.     Print(GetLastError() - ERR_USER_ERROR_FIRST);
10. }
11. //+------------------------------------------------------------------+

Código 11

Ao executar este código 11, você irá poder visualizar no terminal, o que é mostrado na imagem logo a seguir.


Imagem 08

Observe que temos três valores sendo impressos. Porém o que nos interessa é o segundo e o terceiro valor. Já que neste caso está sendo feita justamente a correção do valor a fim de saber qual foi o exato valor colocado no procedimento SetUserError, a fim de indicar um erro.


Considerações finais

Existe uma pequena observação a ser feita sobre o que foi mostrado aqui. Você, muito provavelmente, pode estar pensando que se usar um valor negativo em SetUserError, poderia entrar no range do que seria valores de erro definidos pelo MQL5. Isto a fim de reportar algo especial. Porém valores negativos NÃO terão nenhum efeito como este que você espera obter. Isto por conta do tipo de dado esperado pelo procedimento SetUserError.

Justamente este tipo de coisa é que será vista e explicada no próximo artigo. Com relação aos códigos visto aqui. No anexo você terá acesso a parte deles. Isto para que você possa estudar com calma tudo que foi mostrado no artigo. Então bons estudos e nos vemos no próximo artigo.

Arquivos anexados |
Anexo.zip (2.11 KB)
Desenvolvendo um sistema de Replay (Parte 59): Um novo futuro Desenvolvendo um sistema de Replay (Parte 59): Um novo futuro
O correto entendimento das coisas, nos permite fazer mais e com menos esforço. Neste artigo irei explicar por que temos que temporizar a colocação do template, antes do serviço realmente começar a mexer no gráfico. Além disto, que tal melhorar o indicador de mouse, para podermos fazer mais coisas com ele.
O Problema da Discordância: Mergulhando Mais Fundo na Complexidade da Explicabilidade em IA O Problema da Discordância: Mergulhando Mais Fundo na Complexidade da Explicabilidade em IA
Neste artigo, exploramos o desafio de entender como a IA funciona. Modelos de IA frequentemente tomam decisões de maneiras que são difíceis de explicar, levando ao que é conhecido como o "problema da discordância". Esta questão é fundamental para tornar a IA mais transparente e confiável.
Redes neurais de maneira fácil (Parte 79): consultas agregadas de características (FAQ) Redes neurais de maneira fácil (Parte 79): consultas agregadas de características (FAQ)
No artigo anterior, nos familiarizamos com um dos métodos de detecção de objetos em imagens. No entanto, o processamento de imagens estáticas é um pouco diferente do trabalho com séries temporais dinâmicas, como aquelas relacionadas à dinâmica dos preços que estamos analisando. Neste artigo, quero apresentar a você o método de detecção de objetos em vídeo, que é mais relevante para a nossa tarefa atual.
Desenvolvendo um cliente MQTT para Metatrader 5: uma abordagem TDD — Parte 6 Desenvolvendo um cliente MQTT para Metatrader 5: uma abordagem TDD — Parte 6
Este artigo é a sexta parte de uma série que descreve nossas etapas de desenvolvimento de um cliente MQL5 nativo para o protocolo MQTT 5.0. Nesta parte, comentamos as principais mudanças em nosso primeiro refatoramento, como chegamos a um modelo viável para nossas classes de construção de pacotes, como estamos construindo pacotes PUBLISH e PUBACK, e a semântica por trás dos Códigos de Motivo PUBACK.