English Русский Español Deutsch 日本語
preview
Introdução ao MQL5 (Parte 3): Estudando os elementos básicos do MQL5

Introdução ao MQL5 (Parte 3): Estudando os elementos básicos do MQL5

MetaTrader 5Experts | 3 julho 2024, 10:41
257 0
Israel Pelumi Abioye
Israel Pelumi Abioye

Introdução

Bem-vindos de volta, colegas traders e entusiastas iniciantes do algotrading! Chegamos ao terceiro capítulo da nossa jornada pelo MQL5. Agora estamos na encruzilhada entre teoria e prática — desta vez, vamos abordar arrays, funções personalizadas, pré-processadores e manipulação de eventos. O objetivo desta série de artigos é proporcionar a cada leitor, independentemente de sua experiência em programação, uma compreensão profunda dos elementos fundamentais do MQL5.

É precisamente esse princípio de compromisso com uma explicação clara e concisa que confere grande utilidade a esses artigos. Os artigos explicam cada linha de código, garantindo que você não apenas compreenda os conceitos, mas também veja sua aplicação prática em exemplos reais. Queremos criar um espaço informativo onde a linguagem MQL5 seja acessível a todos. Qualquer dúvida que você tiver, é claro, será bem-vinda. Este é apenas o começo, que estabelece a base para um estudo mais profundo da programação em MQL5. Por isso, é importante ser o mais atento possível e não ignorar as descrições desses artigos.

Então, vamos nos concentrar e começar. Agora, vamos começar a transformar o conhecimento teórico em prático, de maneira acessível a todos. Tudo pronto, o código está pronto, então vamos começar a estudar.

Neste artigo, vamos abordar os seguintes tópicos:

  • Array
  • Funções personalizadas
  • Pré-processador
  • Manipulação de eventos

Antes de embarcarmos na nossa jornada prática nas profundezas da programação MQL5 na Parte 3, vamos revisar o material coberto. Abaixo está um pequeno vídeo que resume brevemente os conceitos chave e os pontos principais da Parte 2 desta série. Vamos relembrar o que já estudamos e depois passar para novos tópicos.



1. Array

O que são arrays?

Os arrays são conceitos fundamentais da programação que proporcionam maneiras eficientes de organizar e armazenar dados. Eles permitem armazenar e organizar múltiplos valores sob um único nome de variável. Em vez de criar variáveis separadas para cada pedaço de dados, pode-se usar um array para armazenar uma coleção de elementos de um mesmo tipo. O acesso e a manipulação dos elementos de um array são feitos por meio de índices.

Analogias

Um array é como uma caixa onde se pode armazenar um monte de objetos semelhantes. Imagine que você tem uma série de caixas, e cada caixa tem seu próprio número. Com esses números, você pode facilmente encontrar e organizar suas coisas. Suponha que você tenha uma série de caixas numeradas 0, 1, 2, 3 e assim por diante (a numeração sempre começa do 0). Em cada caixa, você pode guardar algo especial, como seus brinquedos favoritos ou doces. Se você quiser brincar com um brinquedo específico, basta dizer o número da caixa. Pelo número, você obterá a caixa desejada. Assim, um array na programação é semelhante a uma fileira de caixas numeradas. Eles permitem armazenar muitos itens semelhantes em um único lugar e encontrá-los facilmente por meio de números específicos. É uma maneira conveniente e eficiente de sistematizar.

1.1. Como declarar um array

No MQL5, um array é declarado especificando seu tipo de dado, nome e também os tamanhos do array (se houver).

Sintaxe básica:

data_type array_name[array_size];

  • data_type — tipo de dado que o array conterá (int, double, string, etc.)
  • array_name — nome do array.
  • array_size — tamanho ou comprimento do array, determinando quantos elementos ele pode conter.
Exemplo:
void OnStart()
  {

   int closePrices[5]; // An integer array with a size of 5, means the array has 5 integer elements
   double prices[10];  // A double-precision floating-point array with a size of 10

  }

1.2. Atribuição de valores ao array

No MQL5, os valores podem ser atribuídos ao array durante sua declaração ou separadamente após sua declaração. Vamos analisar ambos os métodos:

1.2.1. Atribuição de valores após a declaração

Aqui você primeiro declara o array e depois atribui valores a cada elemento separadamente. Isso permite atribuir valores dinamicamente durante a execução do programa ou com base em determinadas condições. 

Exemplo:

void OnStart()
  {

   int closePrices[5];
   closePrices[0] = 10;
   closePrices[1] = 20;
   closePrices[2] = 30;
   closePrices[3] = 40;
   closePrices[4] = 50;

  }

1.2.2. Atribuição de valores durante a declaração

Neste método, você declara o array e especifica os valores dentro de chaves {}. O tamanho do array é determinado pelo número de valores especificados. Neste exemplo, o array closePrices é declarado com tamanho 5 e inicializado com os valores 10, 20, 30, 40 e 50. Ambos os métodos são válidos, e você pode escolher o que preferir ou que melhor atenda aos requisitos de um programa específico.

Exemplo:

void OnStart()
  {

   int closePrices[5] = {10, 20, 30, 40, 50};

  }

1.3. Como acessar elementos do array

Na maioria das linguagens de programação, incluindo o MQL5, os índices dos arrays começam do 0. Portanto, por padrão, quando você declara um array e acessa seus elementos, a contagem começa do 0.

Figura 1. Acesso a elementos do array

Exemplo:

void OnStart()
  {
  
// Declare an integer array with a size of 5
   int closePrices[5];

// Assign values to array elements
   closePrices[0] = 10;
   closePrices[1] = 20;
   closePrices[2] = 30;
   closePrices[3] = 40;
   closePrices[4] = 50;
   
   // Access and print array elements
   Print("Element at index 0: ", closePrices[0]); // Output: 10
   Print("Element at index 1: ", closePrices[1]); // Output: 20
   Print("Element at index 2: ", closePrices[2]); // Output: 30
   Print("Element at index 3: ", closePrices[3]); // Output: 40
   Print("Element at index 4: ", closePrices[4]); // Output: 50

  }

Explicação:

Declaração do array:

int closePrices[5];

Nesta linha, um array de inteiros chamado closePrices é declarado com um tamanho fixo de 5 elementos. No MQL5, os arrays podem armazenar elementos de um único tipo de dado, e a indexação começa do 0, então nosso array tem índices de 0 a 4.

Atribuição de valores aos elementos do array:

   closePrices[0] = 10;
   closePrices[1] = 20;
   closePrices[2] = 30;
   closePrices[3] = 40;
   closePrices[4] = 50;

Aqui, valores são atribuídos a cada elemento do array usando índices. O array closePrices agora contém os valores 10, 20, 30, 40 e 50 nas posições correspondentes.

Acesso e exibição de elementos do array:

   Print("Element at index 0: ", closePrices[0]); // Output: 10
   Print("Element at index 1: ", closePrices[1]); // Output: 20
   Print("Element at index 2: ", closePrices[2]); // Output: 30
   Print("Element at index 3: ", closePrices[3]); // Output: 40
   Print("Element at index 4: ", closePrices[4]); // Output: 50
Acima, no exemplo Print, é mostrado como acessar e exibir valores armazenados em determinados índices no array. Aqui, o acesso é feito aos índices de 0 a 4, e os valores correspondentes são exibidos no console.

Então, vimos os fundamentos dos arrays no MQL5, usando a metáfora de contêineres organizados para dados. Nos exemplos de código, vimos como declarar, inicializar e acessar elementos do array. Vale notar que no MQL5 já existe um conjunto de funções para trabalhar com arrays. Mas falaremos sobre essas funções mais tarde em outros artigos — por enquanto, as noções básicas são suficientes.


2. Funções personalizadas

O que são funções personalizadas?

Funções personalizadas (funções definidas pelo usuário) são segmentos de código específicos que você cria para realizar uma tarefa ou conjunto de tarefas em uma linguagem de programação. No contexto do MQL5, que é usado para trading algorítmico, o programador escreve funções personalizadas para encapsular uma série de ações, cálculos ou operações. Essas funções permitem estruturar o código de forma modular, tornando-o mais legível, reutilizável e fácil de manter. Em vez de duplicar o mesmo código em vários lugares do seu programa, você pode criar uma função específica que encapsula essa lógica e, em seguida, chamá-la sempre que precisar realizar uma tarefa específica.

No artigo anterior, ao estudar funções básicas, já conhecemos as funções comuns Alert, Comment e Print. Agora, veremos como expandir as possibilidades de criação de funções no MQL5. Assim como um especialista aprimora suas ferramentas, criar funções personalizadas permite adaptar o código exatamente às necessidades das suas estratégias de trading.

Analogias

Imagine que você está na cozinha preparando uma refeição deliciosa (seu código). As funções são como receitas, fornecendo instruções passo a passo para criar pratos específicos. Agora, vamos ver exemplos de funções personalizadas e comuns. No espaço culinário, funções comuns podem ser vistas como receitas bem conhecidas, publicadas em livros de culinária. Essas receitas são padrão e frequentemente usadas, como uma receita de arroz cozido ou ovos fritos. Do ponto de vista da programação, funções como Alert, Comment e Print são semelhantes a essas receitas populares. Elas têm objetivos específicos, estão prontas para uso e podem ser utilizadas imediatamente.

As funções personalizadas são como suas receitas familiares únicas e secretas. São pratos que você criou com base no seu gosto e preferências. Da mesma forma, funções personalizadas na programação são conjuntos personalizados de instruções, criados pelo programador para realizar tarefas específicas. Elas incluem uma sequência de etapas para alcançar um resultado específico — assim como na sua receita secreta de bolo de chocolate perfeito. A principal diferença está no nível de personalização. Funções comuns podem ser comparadas a refeições prontas: são convenientes, rápidas e amplamente utilizadas. São maneiras eficientes de realizar tarefas diárias, como um jantar pronto que você pode aquecer. No lado oposto estão as funções personalizadas, que oferecem precisão e personalização. É como cozinhar do zero: você pode ajustar os ingredientes, sabores e métodos de acordo com os requisitos únicos da sua cozinha.

2.1. Como criar uma função

Criar uma função no MQL5 envolve especificar o nome da função, definir seus parâmetros (se houver), especificar o tipo de valor de retorno (se a função retornar um valor) e fornecer um bloco de código que constitui o corpo da função.

Passo 1. Definição do objetivo da função

Decida qual tarefa ou cálculo a função irá executar. Isso ajudará a escolher o nome da função, os parâmetros de entrada e o tipo de valor retornado (se houver). Como exemplo, criaremos uma função que multiplica 2 números.

Passo 2. Declaração da função

Declare a função com o nome escolhido, parâmetros de entrada e tipo de valor retornado (se houver). A declaração deve ser feita na área de visibilidade global, fora de qualquer função específica ou manipulador de eventos.

Nota. Os manipuladores de eventos no MQL5 são funções que respondem automaticamente a determinados eventos, como mudanças no preço de mercado (OnTick), interações com gráficos (OnChartEvent) e intervalos de tempo (OnTimer). Eles otimizam a execução do código com base em eventos em tempo real ou programados na plataforma MetaTrader 5. Discutiremos isso em mais detalhes no futuro.

Sintaxe:

return_type FunctionName(parameter1_type parameter1, parameter2_type parameter2, ...) 
   {
    // Function body (code block)
    // Perform actions or calculations
    // Optionally, return a value using the 'return' keyword if the function has a return type
   }

Passo 3. Definição do corpo da função

Dentro da função, adicione o código que realiza a tarefa ou cálculo necessário. Inclua todas as variáveis e lógicas necessárias.

Exemplo:

double MyFunction(int param1, double param2)
     {
      // Function body: Calculate the product of the two parameters
      double result = param1 * param2;

      // Return the result
      return result;
     }

Explicação:

“double MyFunction(int param1, double param2)”:

  • Esta linha define uma função chamada MyFunction. Ela aceita dois parâmetros: param1 do tipo int (número inteiro) e param2 do tipo double (número de ponto flutuante). Espera-se que a função retorne um valor do tipo double.

{:

  • A chave de abertura “{” marca o início do corpo da função, onde está o código real da função.

“double result = param1 * param2;”:

  • Esta linha calcula o produto dos valores de param1 e param2 e armazena o resultado em uma variável chamada result. Como param1 e param2 são de tipos numéricos, a operação de multiplicação (*) resulta em um valor do tipo double.

“return result;”:

  • Esta linha finaliza a função (MyFunction) e retorna o valor armazenado na variável result de volta ao código que chamou a função. Como o tipo de valor retornado da função é double, isso significa que a parte chamadora espera receber um valor double.

“}”:

  • A chave de fechamento “}” marca o fim do corpo da função.

Passo 4: Uso da função

Chame a função nos lugares necessários do seu código. A função pode ser usada em manipuladores de eventos, outras funções ou em qualquer contexto apropriado.

Exemplo:
void OnStart()
  {

// Calling the custom function
   double result = MyFunction(5, 3.5);

// Printing the result
   Print("The result is: ", result); // The output will be 17.5

  }

A função do nosso exemplo, MyFunction, destina-se a multiplicar automaticamente dois números. Chamando esta função e inserindo os valores numéricos necessários como argumentos, podemos obter rapidamente o resultado do cálculo. Essa abstração simplifica o processo de multiplicação de números, melhorando a legibilidade do código e a reutilização.

Se algo não estiver claro para você, não hesite em fazer perguntas. É muito importante entender tudo sobre o que estamos falando aqui. Estou pronto para adicionar quaisquer explicações adicionais, se necessário. As perguntas sempre ajudam no aprendizado, então, sinta-se à vontade para perguntar. Tentarei responder rapidamente.


3. Pré-processadores

O que são pré-processadores?

No dinâmico mundo da programação MQL5, os pré-processadores atuam como ferramentas importantes que definem a maneira como o código é interpretado e executado. O pré-processador é um componente de software especializado que trabalha com o código-fonte antes do início do processo de compilação propriamente dito. Sua função principal é processar instruções e diretivas que influenciam o comportamento, a estrutura e as características do programa resultante.

Os pré-processadores operam transformando ou pré-processando o código-fonte. Eles interpretam certas diretivas precedidas pelo símbolo cerquilha (#) e agem de acordo, alterando o conteúdo do código antes da sua compilação. Essas diretivas são chamadas de diretivas de pré-processador e abrangem uma variedade de funções, incluindo definição de constantes, inclusão de arquivos externos, configuração de propriedades do programa e compilação condicional. Cada diretiva serve a um propósito específico, moldando o código conforme os requisitos do desenvolvedor.

A característica única dos pré-processadores é a sua capacidade de execução antes da compilação real. Essa etapa inicial de manipulação do código permite aos desenvolvedores estabelecer condições, configurações ou inclusões que afetarão o programa compilado final.

Figura 2. Pré-processadores no MetaEditor

Nota. Ao escrever programas em MQL5, é importante lembrar que, após as diretivas de pré-processador, não se usa ponto e vírgula (;), como nos comandos comuns, e elas são declaradas no espaço global do código. Instruções como #define para macros ou #include para inclusão de arquivos definem o comportamento e a estrutura do programa. Portanto, novamente ao trabalhar com pré-processadores, não coloque ponto e vírgula!

Analogia

Comparemos escrever código a dar instruções a um robô. Antes de dizermos algo ao robô, temos um amigo chamado "Pré-processador". Esse amigo ajuda a preparar tudo para que o robô entenda nossas instruções. O pré-processador é como um assistente que examina nossas instruções antes do robô. Sua tarefa é simplificar e organizar as coisas. Às vezes, precisamos usar palavras especiais que significam algo importante, como dizer MAGIC_NUMBER em vez de 10. O pré-processador entende essas palavras especiais e as substitui por números reais.

Exemplo:

#define MAGIC_NUMBER 10

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnStart()
  {

   int result = MAGIC_NUMBER + 5;
   Comment(result); // Output will be 15

  }

Explicação:

“#define MAGIC_NUMBER 10”:

  • Aqui estamos dizendo: “Pré-processador, sempre que você vir a palavra MAGIC_NUMBER no meu código, substitua-a pelo número 10”. Isso é semelhante a criar uma palavra especial que representa um valor específico.

“void OnStart()”:

  • Nesta parte, começa a ação principal. OnStart é uma função especial no MQL5, que é executada ao iniciar seu script.

“int result = MAGIC_NUMBER + 5;”:

  • Aqui usamos nossa palavra especial MAGIC_NUMBER. O pré-processador vê isso e substitui MAGIC_NUMBER por 10. Assim, esta linha é equivalente a "int result = 10 + 5;"

“Comment(result); // Output will be 15”:

  • A função Comment é como pedir ao robô para dizer algo. Neste caso, estamos pedindo ao robô para mencionar o valor de result, que é 15. Então, quando você executar este script, ele exibirá "15" nos comentários do seu gráfico.

O mais incrível é que o pré-processador entra em ação antes mesmo de dizermos ao robô o que fazer! Ele verifica nossas palavras especiais e prepara tudo, para que quando o robô comece a trabalhar, ele já saiba o que fazer. Assim, o pré-processador é um assistente que garante que as instruções sejam claras, o código esteja organizado e tudo esteja perfeitamente configurado para execução pelo robô. Eles são usados frequentemente na programação.


3.1. Categorias de pré-processadores

3.1.1. Macro substituição (#define)

As macros são usadas para criar constantes. As constantes são valores imutáveis. Com as macros, você pode criar palavras especiais que representam esses valores.

Exemplo:

#define MAGIC_NUMBER 10

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnStart()
  {

   int result = MAGIC_NUMBER + 5;

  }

Aqui, em vez de usar o valor 10 toda vez, usamos a palavra MAGIC_NUMBER, o que torna nosso código mais limpo e legível.

3.1.1.1.  Macros parametrizados

Voltando à analogia da receita. Suponha que você precise, às vezes, alterar um ingrediente chave. Macros parametrizados permitem criar instruções flexíveis.

Exemplo:

#define MULTIPLY(x, y) (x * y)

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnStart()
  {

   int result = MULTIPLY(3, 5); // Result is 15

  }

Aqui, o macro MULTIPLY pega dois ingredientes (números) e os multiplica. É como uma função no seu código.

Explicação:

“#define MULTIPLY(x, y) (x * y)”:

  • Esta linha diz ao computador: “Sempre que eu disser MULTIPLY, pegue dois números (chamados de x e y) e os multiplique. Ou seja, usando essa palavra mágica, criamos uma máquina de multiplicação.

“int result = MULTIPLY(3, 5);”:

  • Aqui usamos a palavra especial MULTIPLY. O computador vê isso e sabe que significa “pegue os números 3 e 5 e multiplique-os”. Então, ele substitui MULTIPLY(3, 5) por (3 * 5).

“// O resultado é 15”:

  • O resultado da multiplicação de 3 e 5 é 15. Assim, depois que o computador realizar o cálculo, o valor da variável result será 15.

Essencialmente, esse código simplifica o processo de multiplicação. Em vez de escrever “3 * 5” diretamente, usamos a palavra MULTIPLY para tornar o código mais legível e fácil de entender. Um assistente muito conveniente e útil.

3.1.1.2. Diretiva #undef

A diretiva #undef diz: “Esqueça o que eu disse antes, vamos começar de novo”. Na programação em MQL5, isso permite cancelar a definição ou remover um macro definido anteriormente. É como apagar escritas de um quadro.

Exemplo:

#define MAGIC_NUMBER 10

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnStart()
  {

   int result = MAGIC_NUMBER + 5;
#undef MAGIC_NUMBER // Undefining MAGIC_NUMBER


  }

Explicação:

“#define MAGIC_NUMBER 10”:

  • Primeiro, definimos um macro chamado MAGIC_NUMBER e atribuímos o valor 10. Estamos dizendo: “Sempre que eu usar MAGIC_NUMBER, quero dizer o número 10”.

“int result = MAGIC_NUMBER + 5;”:

  • MAGIC_NUMBER é usado no cálculo, o resultado será 15.

“#undef  MAGIC_NUMBER”:

  • Com “#undef MAGIC_NUMBER” estamos dizendo: “Esqueça o que MAGIC_NUMBER significava antes”. Assim, apagamos a definição e MAGIC_NUMBER se torna indefinido.
Se você tentar usar MAGIC_NUMBER após a linha #undef, isso resultará em um erro, pois o computador não saberá mais o que MAGIC_NUMBER significa. Isso pode ser útil se você quiser redefinir ou parar de usar um macro em uma parte específica do seu código. Ou seja, usamos uma palavra especial por um tempo, mas não precisamos mais dela e podemos passar para outra coisa.

3.1.2. Propriedades de programa (#property)

No mundo da programação, cada programa tem suas características únicas, como um personagem em uma história. Com a diretiva #property, podemos dar ao nosso programa funções e qualidades especiais. Assim, dizemos ao computador que existem certas coisas que tornam o programa especial. Imagine que você está escrevendo um livro ou uma música e deseja informar às pessoas quem a criou e quando foi criada. É mais ou menos isso que você faz nos programas usando #property. Adicionamos uma pequena nota no início do código: "Este programa é a versão 1.0, e eu o escrevi em 2022."

Exemplo:

#property copyright "crownsoyin"
#property version   "1.00"

Resultado após a execução do código

Figura 3. Resultado após a execução do código no MetaTrader 5

Aqui, a diretiva #property cria como que uma capa de livro ou créditos iniciais de um filme. Ela define o tom, fornece informações sobre o programa e ajuda todos, incluindo o próprio programador e outros usuários que possam ler o código posteriormente, a entender o que está acontecendo.

3.1.3 Diretiva de inclusão (#include)

O que é um arquivo incluído?

Voltando aos nossos exemplos de receitas. Imagine que você tem um livro de receitas, mas algumas receitas estão armazenadas em outro livro. A diretiva #include indica "pegue receitas adicionais de outro livro e combine-as em uma grande coleção de receitas". Ao escrever código, isso permite combinar arquivos externos com o código principal, tornando tudo acessível em um só lugar. Neste caso, programar é como construir uma casa com diferentes cômodos. Cada cômodo tem funções específicas, como cozinha ou quarto. A diretiva #include permite reutilizar esses cômodos (funções e estruturas) em outras casas (programas). Na construção, isso seria como: "Eu construí uma cozinha excelente e agora posso usá-la em todas as minhas casas, em vez de construí-la do zero toda vez".

Exemplo:

#include "extraRecipes.mqh" // Include external file with extra recipes

Explicação:

“#include”:

  • A instrução #include diz: "Traga algo de outro lugar e adicione isso aqui".

‘"extraRecipes.mqh"’:

  • O texto entre aspas duplas é o nome do arquivo externo a ser incluído. Neste caso, é "extraRecipes.mqh". Este arquivo contém receitas adicionais (código) que serão usadas no programa principal.

Então, quando escrevemos "#include "extraRecipes.mqh"", é como se abríssemos o livro de receitas e disséssemos: "Vamos adicionar essas receitas adicionais às nossas instruções principais de preparo". Isso ajuda a manter o código principal limpo e organizado, enquanto mantém o acesso a funções adicionais do "extraRecipes.mqh". Quando você usa #include para incluir um arquivo externo no seu código, quaisquer funções ou estruturas definidas nesse arquivo externo tornam-se acessíveis e podem ser usadas no código principal.

Exemplos:

Arquivo externo: “extraRecipes.mqh”

// extraRecipes.mqh
int MultiplyByTwo(int number) // function from an external file  
{
    return number * 2;
}

Código principal:

// Your main code
#include "extraRecipes.mqh" // Include external file with extra recipes
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnStart()
  {

   int result = MultiplyByTwo(5);  // Using the function from the included file
   Print("Result: ", result);      // Output: Result: 10

  }


Neste exemplo, a função MultiplyByTwo é definida no arquivo externo extraRecipes.mqh. Usando #include "extraRecipes.mqh" no código principal, podemos chamar e usar a função MultiplyByTwo, como se ela estivesse definida diretamente no código principal.

Compreender as nuances da inclusão de código e do uso de funções pode parecer um pouco complicado à primeira vista, e isso é normal! Ao explorar novos campos, sempre surgem dificuldades. E se algo ainda não estiver claro, não hesite em fazer perguntas. Perguntas e a busca por explicações adicionais alimentam o processo de aprendizagem. Lembre-se de que estamos discutindo os fundamentos da linguagem agora, e sem compreendê-los, não poderemos avançar. Não se acanhe em fazer qualquer pergunta.

3.1.4. Compilação Condicional (#ifdef, #ifndef, #else, #endif)

As diretivas de compilação condicional permitem incluir ou excluir partes do código durante o processo de compilação. Essas são instruções especiais que indicam ao compilador o que incluir, dependendo de certas condições.

3.1.4.1. Diretiva #ifdef

No MQL5, #ifdef é uma diretiva de pré-processador que verifica se um símbolo específico está definido. Se o símbolo estiver definido, o bloco de código após #ifdef é incluído durante a compilação. Caso contrário, o bloco de código após #else ou #endif é incluído.

Exemplo:

#define MAGIC_NUMBER 10
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnStart()
  {

#ifdef MAGIC_NUMBER
   Print(MAGIC_NUMBER);
#else
   Print(MAGIC_NUMBER);
#endif


  }

Explicação:

  • Neste exemplo, MAGIC_NUMBER é definido usando a diretiva #define.
  • A diretiva “#ifdef MAGIC_NUMBER” verifica se MAGIC_NUMBER está definido.
  • Como ele está definido, o bloco de código após #ifdef é incluído, resultando na compilação da primeira instrução Print.
  • Se MAGIC_NUMBER não estivesse definido, o bloco de código após #else seria incluído, e a segunda instrução Print seria compilada.

#ifdef é usado para compilação condicional, permitindo aos desenvolvedores incluir ou excluir seções específicas do código com base em símbolos predefinidos. Esta é uma ferramenta valiosa para criar código personalizável, permitindo que os desenvolvedores adaptem suas aplicações com base em símbolos ou condições específicas durante o processo de compilação.

3.1.4.2. Diretiva #ifndef

No MQL5, #ifndef é uma diretiva de pré-processador que verifica se um símbolo específico não está definido. Se o macro não estiver definido, o bloco de código após #ifndef é incluído durante a compilação. Caso contrário, o bloco de código após #else ou #endif é incluído.

Exemplo:

void OnStart()
  {

#ifndef MAGIC_NUMBER
   Print(MAGIC_NUMBER);
#else
   Print(MAGIC_NUMBER);
#endif


  }

Explicação:

  • #ifndef MAGIC_NUMBER verifica se "MAGIC_NUMBER" não está definido.
  • Se o macro MAGIC_NUMBER não estiver definido, o bloco de código após #ifndef é incluído, e uma mensagem é exibida indicando que o macro MAGIC_NUMBER não está definido.
  • Se MAGIC_NUMBER estiver definido, o bloco de código após #else é incluído, e ele exibe o valor de MAGIC_NUMBER.

Este código demonstra o uso de compilação condicional com base na definição ou não de um macro específico (neste caso, MAGIC_NUMBER). Dependendo da presença ou ausência do macro durante a compilação, diferentes blocos de código são incluídos.

Nota. MAGIC_NUMBER não foi definido neste exemplo.

3.1.4.3. Diretiva #endif

A diretiva #endif no MQL5 marca o fim de um bloco de código condicional iniciado pelas diretivas #ifdef ou #ifndef. Ela serve como um sinal para o pré-processador de que a seção de compilação condicional está concluída e que o código subsequente deve ser processado para compilação. Ela não tem condições ou parâmetros; seu propósito é simplesmente indicar o final do bloco de compilação condicional.

Exemplo:

#define MAGIC_NUMBER 10
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnStart()
  {

#ifndef MAGIC_NUMBER
   Print(MAGIC_NUMBER);
#else
   Print(MAGIC_NUMBER);
#endif

  }

Explicação:

  • #endif marca o fim do bloco condicional, e o código subsequente é processado normalmente.

Nota. Sempre combine #endif com a diretiva condicional de abertura (#ifdef ou #ifndef) para manter a sintaxe correta e evitar erros de compilação.

Em um breve resumo dos pré-processadores MQL5, abordamos macros para criação de constantes, propriedades de programa (#properties) para definir características, inclusão de arquivos para modularidade e compilação condicional para flexibilidade de código. Isso é apenas uma introdução, e há muito mais por vir. No entanto, essas ferramentas formam a base da programação eficaz em MQL5, garantindo versatilidade e adaptabilidade. E tudo isso é muito importante em nosso caminho para criar algoritmos de negociação poderosos. Mais uma vez, se algo não estiver claro, não hesite em fazer perguntas nos comentários.


4. Manipulação de eventos

O que são eventos?

Um evento na programação refere-se a uma ocorrência ou acontecimento específico (event) que ocorre durante a execução de um programa. Eventos podem ser desencadeados por várias ações, como interações do usuário e mudanças no estado do sistema. No contexto do MQL5, eventos são cruciais no desenvolvimento de programas para trading algorítmico, que respondem dinamicamente às condições do mercado.

O que são manipuladores de eventos?

Um manipulador de eventos é uma seção dedicada de código responsável por responder a um evento específico. No MQL5, manipuladores de eventos são funções destinadas a serem executadas quando um determinado evento ocorre. Essas funções são predefinidas e projetadas para reagir a diferentes eventos. Cada tipo de evento tem uma função de manipulador de eventos correspondente.

Analogia

Imagine que você está em um show de marionetes, e os bonecos se movem e falam sempre que certos eventos ocorrem, como quando o público aplaude ou quando um botão especial é pressionado. Nesta analogia, os bonecos são diferentes partes do programa de computador, e o botão é o evento. O manipulador de eventos é como o marionetista nos bastidores, esperando por momentos específicos (eventos). Quando o evento ocorre, o manipulador de eventos entra em ação, fazendo com que o programa faça algo especial. Por exemplo, quando o público aplaude ou pressiona o botão, o marionetista faz os bonecos dançarem ou falarem. Assim, o manipulador de eventos dá vida às ações necessárias quando certos eventos acontecem.

4.1. Tipos de manipuladores de eventos

Figura 4. Tipos de manipuladores de eventos


4.1.1. OnInit

No MQL5, OnInit é uma função especial usada em Expert Advisors (EAs) para inicialização quando são carregados pela primeira vez no gráfico.

Analogia:

Imagine que você tem um assistente robótico. Antes que o robô comece a fazer coisas interessantes, como se mover ou emitir sons divertidos, ele precisa se preparar. A parte de "preparação" é semelhante ao momento OnInit do robô. Então, quando o robô é ligado pela primeira vez, ele entra em uma sala especial (função OnInit) onde se prepara. Aqui, ele define suas cores favoritas, decide a velocidade com que deve se mover e verifica se tudo está correto. Depois que tudo está configurado, o robô está pronto para sair e começar a fazer truques, como dançar ou contar piadas.

Nos programas de computador, a função OnInit funciona de maneira semelhante. É uma sala especial onde o programa se prepara antes de começar a executar suas tarefas. É como uma cerimônia de abertura para o programa: garantir que tudo esteja pronto para funcionar!

Exemplos:

// Declare global variables
double LotSize;
int TakeProfit;
int StopLoss;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
// OnInit function
int OnInit()
  {
// Set EA parameters
   LotSize = 0.1;
   TakeProfit = 50;
   StopLoss = 30;

// Display initialization message
   Print("EA is getting ready. Lot Size: ", LotSize, ", Take Profit: ", TakeProfit, ", Stop Loss: ", StopLoss);

   return(INIT_SUCCEEDED);
  }

Explicação:

  • Declaramos algumas variáveis globais que o EA pode usar.
  • A função OnInit é o lugar onde inicializamos essas variáveis e realizamos todas as configurações necessárias. Em nosso exemplo, definimos os valores de LotSize, TakeProfit e StopLoss.
  • O comando Print é uma mensagem que o EA pode enviar para o console para informar sobre sua inicialização. O programa diz: "Estou me preparando, e estas são minhas configurações."

Quando você executa o EA no gráfico, a função OnInit é executada uma vez, e a mensagem de inicialização é exibida no console. Isso garante que o EA tenha concluído as configurações antes de começar a negociar ou realizar outras ações.

4.1.2. OnStart

No MQL5, a função OnStart é uma parte importante dos scripts e EAs. Seu papel principal é executar comandos apenas uma vez ao ativar ou iniciar o script. É o ponto de entrada inicial para a execução do script. No caso de um script, a função OnStart executa a lógica definida, que pode incluir colocação de negociações, realização de cálculos ou outras ações. No entanto, ao contrário de um EA, que é executado continuamente e reavalia condições na função OnStart, o script executa sua lógica apenas uma vez e depois termina.

Assim, se você tiver ações relacionadas a negociações na função OnStart de um script MQL5, essas ações serão executadas quando o script for ativado, mas o script não monitorará o mercado continuamente ou fará negociações adicionais.

Exemplo:

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
// This script prints a message to the console when activated

// Entry point when the script is started
void OnStart()
  {
// Print a message to the console
   Print("Script Activated! Hello, Traders!");
  }

Explicação:

  • A função OnStart é o ponto de entrada do script.
  • A função Print é usada para exibir uma mensagem na guia "Experts" da janela do terminal no MetaTrader.
  • Quando você executa o script no gráfico ou no MetaEditor, verá a mensagem indicada no console. Você pode modificar o comando Print e adicionar lógica mais complexa conforme necessário para o seu script.

Ao executar o script no gráfico, a função OnStart será executada uma vez. O objetivo da função OnStart em um script geralmente é realizar tarefas de inicialização ou executar ações específicas quando o script é anexado ao gráfico. Depois que o script executar sua lógica, ele encerrará sua execução.

 

4.1.3. OnTick

No MQL5, a função OnTick é uma parte crucial dos Expert Advisors (EAs). Ela contém a lógica de negociação principal e as ações que devem ser executadas a cada tick. Os EAs usam OnTick para monitorar as mudanças de preço, analisar as condições do mercado e tomar decisões com base em estratégias de negociação predefinidas. Ações relacionadas a ordens, como abrir, modificar ou fechar posições, geralmente são colocadas na função OnTick.

Analogia

OnTick funciona como um assistente TickTrader, que monitora um mercado movimentado. Cada tick é uma nova oportunidade ou mudança. TickTrader está sempre à procura de boas negociações, da mesma forma que você busca as melhores ofertas em um mercado movimentado.

Quando o mercado está calmo, TickTrader pode agir lentamente, apenas observando, sem comprar ou vender rapidamente. Da mesma forma, se a função OnTick percebe que a situação permanece calma a cada tick, ela pode sugerir cautela, como observar o mercado. Se os preços subirem repentinamente, TickTrader pode ver uma boa negociação e decidir fazer uma compra. Da mesma forma, quando a função OnTick nota uma grande mudança de preço a cada tick, ela pode sugerir aproveitar boas oportunidades, como comprar ou vender um ativo.

Neste mercado movimentado, TickTrader está sempre pronto para a próxima oportunidade, tomando decisões conforme os ticks chegam. Da mesma forma, a função OnTick trabalha em tempo real, ajustando-se a cada tick e gerenciando ações de negociação em um mercado dinâmico.

Exemplo:
// Declare a variable to store the last tick's close price
double lastClose;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
// OnInit function
int OnInit()
  {

// Initialize the variable with the current close price
   lastClose = iClose(_Symbol, PERIOD_CURRENT, 0);

   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {

// Get the current close price
   double currentClose = iClose(_Symbol, PERIOD_CURRENT, 0);

// Check if the close price has changed
   if(currentClose != lastClose)
     {
      // Print a message when the close price changes
      Print("Close price changed! New close price: ", currentClose);

      // Update the last close price
      lastClose = currentClose;
     }


  }

Explicação:

Declaração de variável:

// Declare a variable to store the last tick's close price
double lastClose;

Declaramos a variável lastClose do tipo double para armazenar o preço de fechamento do último tick.

Inicialização (função OnInit):

int OnInit()
  {

// Initialize the variable with the current close price
   lastClose = iClose(_Symbol, PERIOD_CURRENT, 0);

   return(INIT_SUCCEEDED);
  }

Na função OnInit, inicializamos lastClose com o preço de fechamento da vela mais recente, usando a função iClose. Os parâmetros _Symbol, PERIOD_CURRENT e 0 indicam o símbolo atual, o período atual e a vela mais recente, respectivamente.

Função OnTick:

void OnTick()
  {

// Get the current close price 
   double currentClose = iClose(_Symbol, PERIOD_CURRENT, 0);

// Check if the close price has changed
   if(currentClose != lastClose)
     {
      // Print a message when the close price changes
      Print("Close price changed! New close price: ", currentClose);

      // Update the last close price
      lastClose = currentClose;
     }


  }

  • Na função OnTick, obtemos o preço de fechamento atual usando iClose e armazenamos na variável currentClose.
  • Em seguida, verificamos se o preço de fechamento atual difere do último preço de fechamento registrado (currentClose != LastClose).
  • Se houver uma mudança, exibimos uma mensagem indicando a alteração e atualizamos a variável lastClose.

Este código monitora e exibe uma mensagem sempre que o preço de fechamento muda a cada tick. Ele demonstra como a função OnTick pode ser usada para reagir à dinâmica do mercado em tempo real.


Considerações finais

Neste artigo, examinamos detalhadamente os aspectos fundamentais do MQL5: arrays, funções personalizadas, pré-processadores e manipulação de eventos. Espero que as descrições apresentadas tenham sido claras e úteis. Compreender esses elementos básicos é essencial para a próxima etapa de criação de robôs de negociação. O conhecimento cresce com a curiosidade, então explore, teste e não hesite em fazer perguntas. Acompanhe as próximas partes, onde avançaremos passo a passo na criação de robôs de negociação. Enquanto isso, dedique um tempo para assimilar com confiança os conceitos básicos. Boa sorte na programação e sucesso no caminho para a negociação algorítmica completa!

Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/14099

Redes neurais de maneira fácil (Parte 74): previsão adaptativa de trajetórias Redes neurais de maneira fácil (Parte 74): previsão adaptativa de trajetórias
Proponho a você conhecer um método bastante eficaz de previsão de trajetórias multiagentes, que é capaz de se adaptar a diferentes condições ambientais.
Tipo de desenho DRAW_ARROW em indicadores multissímbolos e multiperíodos Tipo de desenho DRAW_ARROW em indicadores multissímbolos e multiperíodos
No artigo, vamos considerar o desenho de indicadores multissímbolos e multiperíodos com setas. Aprimoraremos os métodos da classe para a correta exibição das setas, que exibem dados dos indicadores de seta calculados em símbolo/período diferentes do símbolo/período do gráfico atual.
Algoritmos de otimização populacionais: evolução de grupos sociais (Evolution of Social Groups, ESG) Algoritmos de otimização populacionais: evolução de grupos sociais (Evolution of Social Groups, ESG)
Neste artigo, consideraremos o princípio de construção de algoritmos multipopulacionais e, como exemplo desse tipo de algoritmos, analisaremos a Evolução de Grupos Sociais (ESG), um novo algoritmo autoral. Analisaremos os conceitos principais, os mecanismos de interação entre populações e as vantagens desse algoritmo, bem como examinaremos seu desempenho em tarefas de otimização.
Redes neurais de maneira fácil (Parte 73): AutoBots para previsão de movimentos de preço Redes neurais de maneira fácil (Parte 73): AutoBots para previsão de movimentos de preço
Continuamos a análise dos algoritmos de aprendizado de modelos de previsão de trajetórias. E neste artigo, proponho que você conheça o método chamado “AutoBots”.