English Русский 中文 Español Deutsch 日本語
Linguagem MQL4 para Iniciantes. Perguntas difíceis em frases simples

Linguagem MQL4 para Iniciantes. Perguntas difíceis em frases simples

MetaTrader 4Exemplos | 22 fevereiro 2016, 11:43
1 742 0
Antoniuk Oleg
Antoniuk Oleg

Introdução

Este é o segundo artigo da série "Linguagem MQL4 para Iniciantes". O primeiro artigo "Linguagem MQL4 para iniciantes. Introdução" descreveu o que pode ser feito usando MQL4, aprendemos a escrever scripts simples, estudamos o que uma variável é, aprendemos a trabalhar com variáveis, funções analisadas, matrizes, matrizes e variáveis integradas, ciclos ''para'' e condições simples e complexas. Agora vamos examinar mais construções complexas e avançadas da linguagem, aprender novas opções e ver, como elas podem ser aplicadas na prática diária. Você vai se familiarizar com um novo tipo de ciclo ''enquanto'', um novo tipo de condição ''troca'', operadores ''pausa'' e ''continuação". Além disso, você vai aprender a escrever suas próprias funções e trabalhar com matrizes multidimensionais. E de bônus, preparei uma explicação sobre um pré-processador.


Conselho

Não começar a ler este artigo caso não tenha compreendido totalmente o primeiro. Você irá cometer muitos erros e não vai entender nada. Este artigo é baseado no material antigo, por isso não se apresse! Eu quero facilitar as coisas, as dificuldades que você irá encontrar quando aprender o novo material, são enganosas. Chegará o tempo que você não terá que pensar sobre a forma como os ciclos são escritos, que condições colocar, tudo será feito mecanicamente. Quanto mais você trabalhar com linguagem MQL4, mais fácil será utilizá-la.

Novo tipo de ciclos - enquanto

Gostaria de mencionar, que o ciclo 'para', descrito no artigo anterior, é universal e pode substituir qualquer outro tipo de ciclo que vamos aprender agora. Mas nem sempre é conveniente e apropriado. Às vezes, é mais eficiente usar o ciclo enquanto. Logo você entenderá, o uso de qual tipo de ciclo é mais racional. Vamos fazer uma tarefa de duas maneiras: vamos encontrar um volume total de todas as barras, usando ambos os ciclos e ver a diferença:

// using the cycle for
double sum = 0.0;
 
for(int a = 0; a < Bars; a++)
    sum += Volume[a];
 
// now using while, the result is the same
double sum = 0.0;
int a = 0;
 
while(a < Bars)
  {
    sum += Volume[a];
    a++;
  }

Veja, agora o contador é declarado e usado separadamente. ''Enquanto'' mostra que enquanto a condição for verdadeira, o ciclo continua. Aqui está uma forma geral:


while(condition of cycle fulfillment)
  {
    code
  }


Aqui está um exemplo simples:

while(I haven't eaten up the apple) // condition
  {
    // what to do, if the condition is not fulfilled
    bite more;                 
  }

De fato, o ciclo ''enquanto" difere do ciclo ''para'' somente na ausência de um contador. Se você não precisar dele, use o ciclo "enquanto", embora não seja necessário. Por exemplo, muitas vezes eu uso "enquanto" com um contador, é uma questão de gosto. Com o ciclo "para'', se o corpo do ciclo incluir apenas uma instrução, você pode omitir as chaves. Também para o seu desenvolvimento, lembre-se do significado da palavra iteração. É uma das várias operações (repetições), levadas pelo ciclo. Isto é, realizar o corpo do ciclo uma vez significa que uma iteração é realizada.

Novo tipo de condições - troca

Tal como no caso dos ciclos, deve-se notar que a troca pode ser substituída por uma combinação de condições que lhe são familiares "se" e "outra". A construção "troca'' é usada quando você precisa executar algumas ações dependendo do valor de uma variável. Isto é como um interruptor comum em um forno de microondas. Por exemplo, imagine que você escreveu um Expert Advisor, e muda o seu comportamento em função da situação do mercado. Deixe uma variável int marketState ser responsável por isto. Isto pode ter os seguintes significados:

  • 1 - tendência de alta
  • 2 - tendência de baixa
  • 3 - estabilidade

Não importa como esta posição é definida, a nossa tarefa é realizar algum tipo de mecanismo, de modo que, dependendo da situação do mercado o Expert Advisor realize ações correspondentes. Você sabe como fazer isso. A variante mais evidente é a seguinte:

if(marketState == 1)
  {
    // trading strategy for an uptrend
  }
else 
    if(marketState == 2)
      {
        // strategy for a downtrend
      }
    else 
        if(marketState == 3)
          {
            // strategy for a flat
          }
        else
          {
            // error: this state is not supported!
          }

Aqui estão algumas peculiaridades:

  • todas as condições são realizadas com uma e a mesma variável;
  • todas as condições comparam a variável com um dos significados da variável que a variável pode aceitar.

Então, tudo isso remete igualmente para a estrutura de troca. Aqui está um código, usando a troca, o resultado é o mesmo:

switch(marketState)
  {
    case 1:  // trading strategy for an uptrend
             break;
    case 2:  // strategy for a downtrend
             break;
    case 3:  // strategy for a flat
             break;
    default: // error: this state is not supported!
             break;
  }

Observe que primeiro definimos qual variável será comparada:

// switch - key word, marketState - 
// a variable for comparison
switch(marketState)

e, em seguida, indicamos, o que deve ser feito em casos específicos:

 
case 1:                        // case - key word; 
   // trading strategy         // if marketState is equal to 1, then 
   // for an uptrend           // perform this code
   break;                      // key word that indicates  
                               // the end of actions in this case
 
case 2:                        // if marketState is equal to 2, then
    // startegy for            // perform this
    // a downtrend          
    break;                     // end
 
case 3:                        // identical
    // strategy for flat
    break;
 
default:                       // otherwise, perform this
    // error: this   
    // state is not 
    // supported!
    break;

Na visão geral a troca tem a seguinte forma:

switch(a variable for comparison)
  {
    case [a variable value]:
    // a code for this case 
    break;
   
    case [another value of the variable]
    // a code for this case
    break;
   
    default:
    // a code for all other cases
    break;
  }

Ao comparar uma variável para vários valores e um determinado bloco de código corresponde a um valor use a troca. Em outros casos, utilize uma combinação comum das condições ''se'' e ''outra''. Às vezes você precisa executar um código em vários valores de uma variável. Por exemplo, se marketState == 1 ou 2, em seguida, execute um determinado código. Isto pode ser feito através da troca:

switch(marketState)
  {
    case 1:  // if marketState is equal to 1
    case 2:  // or if marketState is equal to 2, then
             // perform this
             break;
 
    default: // in any other case perform 
             // this code
             break;
  }

Operadores: continuação e pausa

Acabamos e ver o operador pausa. Ele é utilizado para escapar do corpo da troca. Além disso você pode usá-lo para escapar de um ciclo. Por exemplo, se você não precisar executar um ciclo em algumas condições. Suponha que precisamos encontrar a quantidade das primeiras barras necessários para encerrar 1000 pontos. Podemos escrever o seguinte código:

int a = 0;
double volume = 0.0;
 
while(volume < 1000.0)
  {
    volume += Volume[a]; // equivalent to volume = volume + Volume[a]; 
    a++;
  }
 
// now variable "a" includes the amount of bars, the volume of their sums 
// is no less than 1000 points

Agora vamos escrever um código análogo usando o operador pausa:

int a = 0;
double volume = 0.0;
 
while(a < Bars)
  {
    // if the volume is exceeds 1000 points, then
    if(volume > 1000.0) // exit the cycle   
        break;            
 
    volume += Volume[a];
    a++;
  }

Veja, o operador pausa é fácil de usar e permite evitar iterações de ciclo indesejadas. Mais um operador útil continuação destina-se a ''omitir'' iterações indesejadas. Suponha que precisamos calcular um volume total, mas não devemos levar em consideração o volume das barras nos momentos de notícias importantes. Como você sabe, notícias importantes envolvem grandes volumes de pontos. Vamos fingir ser crianças ingênuas e suponha que o volume da barra seja 50 pontos e mais seja notícias. Para resolver esta tarefa, vamos usar o operador de continuação:

int a = -1;
double volume = 0.0;
 
while(a < Bars)
  {
    a++;
    // if the volume exceeds 50 points, then it must 
    // be news, omit it 
    if(Volume[a] > 50.0)          
        continue;          
    volume += Volume[a];
  }

O uso do operador continuação é bastante trivial, mas às vezes pode ajudá-lo. É claro que este script é destinado para pequenos intervalos de tempo.


Escrevendo suas próprias funções

Mas por que precisamos deles? O fato é que muitas vezes você pode encontrar seu código duplicado. Isto é, você vai utilizar um único e mesmo conjunto de instruções em casos diferentes. Para economizar tempo e força, você pode escrever este código duplicado em uma função separada. E quando você precisar dele, você pode simplesmente escrever o nome da função e ele fará tudo para você. Vamos ver como isto funciona. Suponha que você precise encontrar a cor de um castiçal. Sabe-se que um castiçal branco é aquele que fecha mais alto que a abertura e o preto, vice-versa. Vamos escrever um código para determinar a cor de um castiçal;

bool color; // as there are only 2 variants 
            // (white or black candlestick), 
            // then suppose that the velue 
            // false corresponds to a black 
            // candlestick, and true - white
 
if(Close[0] > Open[0])
    color = true;      // white candlestick
    
if(Open[0] > Close[0])
    color = false;     // black candlestick

Isso é tudo, agora a cor variável contém a cor do último castiçal. Para determinar a cor de outro castiçal, por exemplo, a penúltima, você precisa alterar o índice de 0 para 1. Mas você vai colocar este código cada vez que você precisar encontrar a cor de um castiçal? E se houverem dúzias de casos assim? É por isso que precisamos das funções. Vamos pensar, como isso deve funcionar. Tal função deve aceitar um argumento - o índice de um castiçal, a cor que você precisa para determinar, retornar a cor - uma variável booleana. Vamos imaginar que a função está escrita e ativá-la:

bool color; // here will be the color of a wanted candlestick
 
color = GetColor(0);

Como você deve ter adivinhado, a função chama-se GetColor. Nesta chamada de função queríamos encontrar a cor do último castiçal. É por isso que o único argumento é igual a zero. A função retorna a cor de um castiçal, então fazemos um trabalho de uma só vez. É um momento muito importante! Uma variável é criada dentro da função, então o seu valor irá substituir a chamada da função. Ultimamente a função chamada e o código da função determinante, descrito acima, fornecerão o mesmo resultado - a cor variável irá conter a cor do último castiçal, mas usando funções, gastamos menos força.

E agora vamos inesperadamente voltar ao código de um script vazio. O fato é, que já contém uma descrição completa da função start(). A coisa mais interessante é que todo esse tempo que você tem escrito scripts nesta função! Quando você inicia seu script, o terminal ativa a função start(). Vamos examinar o código de um script vazio:

int start()

Esta linha é muito importante! Ela inclui o nome da função, isto é, uma palavra-chave que você escreverá para ativar esta função. No nosso caso, é "start". Ela também contém o tipo de um valor de retorno - int. Isso significa que após o desempenho da função ela irá nos retornar algum valor do tipo int. Os parênteses contém a lista de argumentos, mas no nosso caso, a função não aceita parâmetros.

Depois, nas chaves, você vê a descrição da função, isto é, um código que realizará a chamada da função:

  {
    //----
    // a code that will be performed 
    // at the function call.
    //----
    return(0);
  }

Logicamente, escrevemos um código no corpo da função start(). No final da função vemos o retorno do operador que devolve o valor da função. No nosso caso ele retorna zero.

Agora veja a forma geral de escrever uma função:

[type of return value] [function name] ([list of arguments])
  {
    // function code
    return([a value, which the function returns]);
  }

Agora, vamos voltar para nossos castiçais e para a função GetColor. Veja o código desta função:

bool GetColor(int index)
  {
    bool color;
    if(Close[index] > Open[index])
        color = true;      // white candlestick
    if(Open[index] > Close[index])
        color = false;     // black candlestick
    return(color);
  }

Vamos analisar a primeira linha:

bool GetColor(int index)

Aqui temos: bool - tipo de um valor de retorno; GetColor - nome da função; int - tipo de argumento; index - nome do argumento. Observe, usamos index dentro do corpo da função, mas na chamada de função este nome nunca é mencionado. Por exemplo:

bool lastColor = GetColor(0);

Depois:

{
   bool color;
   if(Close[index]>Open[index])
       color=true;      // white candlestick
   if(Open[index]>Close[index])
       color=false;     // black candlestick

Este corpo da função é um código geral que será realizado a cada chamada de função. Depois disso:

   return(color);
}

O operador retorna os indicadores que a função deve retornar. O valor de retorno deve corresponder ao tipo determinado no início. Se necessário, você pode usar vários operadores "retorno" em uma função, por exemplo:

bool GetColor(int index)
  {
   if(Close[index] > Open[index])
       return(true);      // white candlestick
   if(Open[index] > Close[index])
       return(false);     // black candlestick
  }

É evidente que a utilização de vários operadores de retorno permite a evitar a variação da cor. Além disso, no retorno do operador você poderá utilizar expressões lógicas:

return(Close[index] > Open[index]);

Isto é possível pois os operadores de comparação também retornam variáveis booleanas (verdadeiras ou falsas) como algumas outras funções comuns. Parece difícil, mas em breve você vai se acostumar com isso.

Agora vamos voltar para uma lista de argumentos. Apenas o argumento int index é utilizado na nossa função. Se você precisa usar vários argumentos, enumere-os separados por vírgula:

bool SomeСomplicatedFunction(int fistArgument, int secondArgument, 
                             sting stringArgument)

Para se referir aos argumentos, utilize seus nomes como na função anterior. Quando for uma chamada de função com vários argumentos, preste atenção na sequência da ordem dos argumentos: não misture! Se a função não deve retornar qualquer valor, use a palavra-chave vazio, para indicar isso. Observe que o operador de retorno neste caso não é utilizado:

void function()
  {
    // code
  }

mais um detalhe: você pode definir os valores para os argumentos da função no padrão. O que é isso? Suponha que você tenha escrito uma função complexa que inclui 5 argumentos que influenciam seu comportamento. Mas vários dos últimos argumentos são quase sempre usados com os mesmos valores. Você precisa usar valores diferentes para apenas duas dúzias de chamadas de função. A fim de não indicar cada vez os valores dos últimos argumentos, que são quase sempre os mesmos, são utilizados os valores padrões. Neste caso, você simplesmente omite os últimos argumentos, como se eles não existissem, embora eles sejam usados, os valores são atribuídos por padrão. Quando você encontra esse caso especial, você indica todos os argumentos. Vamos ver como podemos declarar uma função com argumentos padrão:

void someFunction(int argument1, int argument2, 
                  int specialArgument = 1)
  {
    // code
  }

Tudo é fácil: vamos atribuir um valor necessário para um argumento necessário e agora ele pode ser omitido na chamada da função:

someFunction(10,20);   // we omitted the last argument, but 
                       // actually it is assigned a value by default
 
someFunction(10,20,1); // this activation is fully identical to the previous one
 
someFunction(10,20,2); // here we indicate another value,  
                       // it is a rare case

Você pode indicar quantos valores padrão de argumentos você desejar. Mas lembre-se de uma regra importante: todos devem ser colocados no final. Por exemplo:

void someFunction(int argument1, int argument2, 
                  int specialArgument = 1)   // all right
 
void someFunction(int argument1, int argument2 = 10, 
                  int specialArgument=1)     // all right
 
void someFunction(int argument1, int argument2 = 10, 
                  int specialArgument)     // wrong! default
                                           // values must stay
                                           // at the end of the 
                                           // list of arguments
                                                                           
void someFunction(int argument1 = 0, int argument2 = 10, 
                  int specialArgument = 1) // you can assign  
                                           // default values  
                                           // to all arguments

Matrizes multidimensionais

Você usará, com frequência, matrizes durante a programação e, em casos mais importantes, matrizes unidimensionais serão suficientes. Mas, em alguns casos, você precisará de matrizes bidimensionais ou tridimensionais. Agora você vai aprender a usá-las.

Para começar, vamos apresentar visualmente as matrizes unidimensionais, revisar a declaração, inicialização, índices e valor:

Qualquer matriz unidimensional pode ser apresentada como uma linha de valores de um tipo. Veja como as diferentes referências a uma matriz unidimensional serão processadas:

Matrizes bidimensionais são como tabelas comuns, veja:

Como pode ser visto na imagem, matrizes bidimensionais já tem dois índices de referência anexados ao valor: o primeiro índice determina a linha e o segundo índice determina a coluna. Como em uma matriz unidirecional, uma lista de valores é usada para inicialização. Esta é a forma como os valores das células da tabela são referidos:

Veja, tudo está claro. Vamos ver como podemos passar por todos os valores de uma matriz bidimensional. 2 ciclos devem ser usados:

int array2D[3][3]={10,20,30,
                   40,50,60,
                   70,80,90};
 
for(int y=0;y<3;y++)
   for(int x=0;x<3;x++)
      MessageBox("array2D["+y+"]["+x+"]="+array2D[y][x]);

Neste exemplo, a referência vai para baixo da esquerda para a direita. Apenas para treinar, tente mudar a direção, por exemplo, para cima.

As matrizes tridimensionais diferem somente na presença de mais um índice para fazer referência aos valores das células. Uma matriz tridimensional pode ser facilmente apresentada como várias tabelas (matrizes bidimensionais). Desta forma podemos passar por todos os elementos de uma matriz tridimensional:

int array3D[3][3][3] = {11, 12, 13,
                        14, 15, 16,
                        17, 18, 19,
 
                        21, 22, 23,
                        24, 25, 26,
                        27, 28, 29,
 
                        31, 32, 33,
                        34, 35, 36,
                        37, 38, 39};
 
for(int z = 0; z < 3; z++)
    for(int y = 0; y < 3; y++)
        for(int x = 0; x < 3; x++)
            MessageBox("array3D["+z+"]["+y+"]["+x+"]=" + 
                       array3D[z][y][x]);

Estudar matrizes bidimensionais e tridimensionais é muito importante. Mais uma vez, com muita atenção, olhe as imagens explicativas. Um monte de tarefas diferentes são resolvidas usando matrizes, então, dedique tempo suficiente para elas, assim, elas serão muito úteis para você no futuro. Se você entender o princípio de trabalhar com matrizes, você não terá problemas para trabalhar com qualquer matriz n-dimensional.


Algumas funções para trabalhar com matrizes

Vamos começar com funções simples.

int ArraySize(object array[]);
Esta função retorna a quantidade de elementos contidos na matriz. Ela funciona com todos os tipos. Por exemplo:
// create two different arrays
int arrayInt[] = {1, 2, 3, 4};           
double arrayDouble[] = {5.9, 2.1, 4.7};
// here store the amount of elements 
int amount;                        
 
amount = ArraySize(arrayInt);      // note: 
                                   // to define a specific 
                                   // array, you need to indicate
                                   // only its name.
                                   // Now amount is equal to 4
 
 
amount = ArraySize(arrayDouble);   // amount is equal to 3

Próxima função:

int ArrayInitialize(object array[],double value);
ArrayInitialize

atribui um valor para todos os elementos da matriz, retorna a quantidade de elementos para qual um valor foi atribuído. Use esta função com matrizes de tipo int e de tipo duplo.



Próximo:

int ArrayMaximum(double array[], int count = WHOLE_ARRAY, 
                 int start = 0);
int ArrayMinimum(double array[], int count = WHOLE_ARRAY, 
                 int start = 0);

Estas duas funções retornam o índice do valor de uma célula de máxima ou mínima. Para usá-los, basta indicar em que matriz eles devem ser procurados:

int array[] = {10, 100, 190, 3, 1};
// will be returned 1, because array[1] - maximal value 
ArrayMaximum(array); 
// will be returned 4, because array[4] - minimal value
ArrayMinimum(array);

Próximo:


int ArrayDimension(object array[]);

Usando estas funções você pode terminar a dimensionalidade de uma matriz, isto é, pode determinar se ela é unidimensional, bidimensional ou n-dimensional. Por exemplo:

int array1D[15];
int array4D[3][3][3];
 
ArrayDimension(array1D); // get 1
ArrayDimension(array3D); // 3

Aqui estão funções mais complexas e úteis:

int ArraySort(double&array[], int count = WHOLE_ARRAY, int start = 0,
              int sort_dir = MODE_ASCEND);

Esta função ordena elementos. Se você não indicar diretamente os argumentos no padrão, por exemplo, da seguinte maneira:

int array[5] = {1, 10, 5, 7, 8};
 
ArraySort(array);

os elementos serão ordenados ascendente. Você pode usar parâmetros adicionais para especificar o comportamento da função:

  • int count - o número de elementos que devem ser classificados
  • int start - o índice de um elemento, a partir do qual a triagem deve ser iniciada
  • int sort_dir - a direção da ordenação (ascendente - MODE_ASCEND ou descendente - MODE_DESCEND)

Aqui você deve se perguntar: o que é MODE_ASCEND e MODE_DESCEND?? De acordo com int, ele deve ser um número inteiro! Não fique nervoso, tudo vai endireitar na próxima parte - "Pré-processador". Por exemplo, se você precisar classificar descendente 5 elementos a partir do segundo, indique algo como isto:

ArraySort(array, 5, 1, MODE_DESCEND);

E a última função para hoje:

int ArrayCopy(object&dest[], object source[], int start_dest = 0,
              int start_source=0, int count=WHOLE_ARRAY);

Ela é usada para copiar uma matriz para outra. Vamos ver os parâmetros obrigatórios:

  • dest[] - em qual matriz copiar
  • source[] - de qual matriz copiar

Parâmetros opcionais:

  • start_dest - índice de um elemento da matriz, no qual a cópia é realizada
  • start_source - índice de um elemento da matriz, do qual a cópia é realizada
  • int count - a quantidade de elementos para cópia

A função retorna com a quantidade de elementos copiados. Utilize a função ArrayCopy com muito cuidado: Ao copiar para as matrizes, certifique-se de que elas tenham capacidade suficiente!


Pré-processador

O que é isso? O Pré-processador é um mecanismo especial destinado ao processamento de um código fonte. Isto é, primeiro um pré-processador prepara um código e depois o transmite para compilação. Hoje aprenderemos mais uma opção útil - constantes.

Qual é o ponto principal? Para entender isso, vamos lembrar um exemplo da parte sobre mudança:

switch(marketState)
  {
    case 1:
    // trading strategy for an uptrend
    break;
 
    case 2:
    // strategy for a downtrend
    break;
 
    case 3:
    // strategy for a flat
    break;
 
    default:
    // error: this state is not supported!
    break;
  }

Aqui, ativamos um mecanismo que atua em diferentes formas dependendo do estado do mercado. Lembra? Assim, seria mais fácil e mais descritivo escrever algo como TENDÊNCIA_ALTA, TENDÊNCIA_BAIXA, ESTABILIDADE ao invés de 1, 2 e 3:

switch(marketState)
  {
    case TREND_UP:
    // trading strategy for an uptrend
    break;
 
    case TREND_DOWN:
    // strategy for a downtrend
    break;
 
    case FLAT:
    // strategy for a flat
    break;
 
    default:
    // error: this state is not supported!
    break;
  }

Neste caso, um código fonte parece muito mais fácil de entender, não é? Assim, as constantes permitem substituir TENDÊNCIA_ALTA, TENDÊNCIA_BAIXA e ESTABILIDADE por valores correspondentes 1, 2 e 3 antes da compilação. Tudo que você precisa é indicar o que o pré-processador deve mudar. Isso é feito por meio das diretivas do pré-processador, que começam a partir de um símbolo especial "#". As diretivas do pré-processador devem ser colocadas no início de um arquivo de origem juntamente com outras diretivas. Vejamos um exemplo completo do uso de constantes:

//+------------------------------------------------------------------+
//|                                                 preprocessor.mq4 |
//|         Copyright © 2007, Antonio Banderass. All rights reserved |
//|                                               banderassa@ukr.net |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007, Antonio Banderass. All rights reserved"
#property link      "banderassa@ukr.net"
 
#define TREND_UP   1
#define TREND_DOWN 2
#define FLAT       3
 
//+------------------------------------------------------------------+
//| script program start function                                    |
//+------------------------------------------------------------------+
int start()
  {
   MessageBox("TREND_UP=" + TREND_UP + " TREND_DOWN=" + TREND_DOWN + 
              " FLAT=" + FLAT);
 
   return(0);
  }

Note que nós colocamos a declaração de constantes no início do arquivo, sob outras diretivas do pré-processador. Vamos examinar a declaração mais de perto:

#define TREND_UP 1

Primeiro, escrevemos a palavra-chave #define. Isto mostra ao pré-processador que depois disso vem a declaração constante. Depois, escrevemos o nome da constantee seu identificador, isto é, uma palavra através da qual você vai se referir ao valor constante. No nosso caso, é TENDÊNCIA_ALTA. O valor - 1 vem depois disso. Agora, quando o pré-processador vê TENDÊNCIA_ALTA no código-fonte, ele irá substituí-la por 1, o mesmo é feito com todas as outras constantes. Aqui está o código fonte do nosso exemplo, antes de processado por um pré-processador:

int start()
  {
   MessageBox("TREND_UP=" + TREND_UP + " TREND_DOWN=" + 
              TREND_DOWN + " FLAT=" + FLAT);
   return(0);
  }

e depois:

int start()
  {
   MessageBox("TREND_UP=" + 1 + " TREND_DOWN=" + 2 + 
              " FLAT=" + 3);
   return(0);
  }

Agora você deve compreender o que significa MODE_ASCEND e MODE_DESCEND. São constantes com valores correspondentes.



Conclusão

Você aprendeu muita coisa nova neste artigo: novo tipo de ciclo - enquanto; novo tipo de condição - troca; operadores pausa e continuação. Você aprendeu a escrever suas próprias funções e a trabalhar com matrizes multidimensionais, também aprendeu a usar constantes. Tudo isso é o seu instrumento principal, uma base para escrever as coisas mais avançadas, como indicadores do usuário e expert advisors. Por isso, certifique-se que você tenha estudado o material do artigo, ele é muito importante e vai ser constantemente usado no futuro.



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

Arquivos anexados |
preprocessor.mq4 (0.86 KB)
Trading automatizado não padrão Trading automatizado não padrão
Trading bem sucedido e confortável utilizando a plataforma MT4 sem análise detalhada do mercado - é possível? Esse tipo de trading pode ser implementado na prática? Acredito que sim. Especialmente em termos de trading automatizado!
Previsão de preços utilizando redes neurais Previsão de preços utilizando redes neurais
Muitos operadores falam sobre redes neurais, mas o que elas são e o que elas realmente podem fazer é conhecido por poucas pessoas. Este artigo lança alguma luz sobre o mundo da inteligência artificial. Ele descreve como devemos preparar corretamente os dados para a rede. Você também encontrará um exemplo de previsão por meio do programa Matlab.
Teste de Visualização: Gráficos do status da conta Teste de Visualização: Gráficos do status da conta
Aproveite o processo de testes com gráficos exibindo o balanço, agora toda a informação necessária está sendo visualizada!
O que é Martingale? É sensato utilizá-lo? O que é Martingale? É sensato utilizá-lo?
Este artigo contém uma descrição detalhada do sistema Martingale, bem como cálculos matemáticos precisos necessários para responder a pergunta: "É sensato utilizar o sistema Martingale?"