English Русский 中文 Español Deutsch 日本語 한국어 Français Italiano Türkçe
Uma rápida inicialização ou um guia breve para iniciantes

Uma rápida inicialização ou um guia breve para iniciantes

MetaTrader 5Exemplos | 13 janeiro 2014, 13:43
4 087 0
Dmitriy Parfenovich
Dmitriy Parfenovich

Introdução

Olá, caro leitor! Neste artigo, tentaremos explicar e mostrar como você pode facilmente e rapidamente compreender os princípios da criação de Expert Advisors, trabalhar com indicadores, etc. Este artigo é destinado a iniciantes e não apresentará nenhuma dificuldade ou exemplos de difícil entendimento. Então, este artigo pode, provavelmente, não ser tão inspirador para aqueles que já saibam como programar Expert Advisors.

Expert Advisor e sua estrutura

O Expert Advisor é um programa escrito na linguagem MQL que especifica condições para fazer o negócio ou mantê-lo.

Basicamente, a estrutura de um EA pode ser feita de um grande número de blocos, mas para facilitar o entendimento, darei um exemplo bastante simples gerado por predefinição no MetaEditor.

Todo o EA pode ser visualmente divido em 4 partes, cada uma sendo responsável por uma determinada parte do trabalho a ser realizado.

Os principais blocos do EA
Fig. 1. Os principais blocos do EA

  1. Bloco de parâmetro contém informações para o terminal permitindo que ele manipule o EA de uma maneira adequada. Os parâmetros mais comuns são a versão do EA, o nome da empresa de fabricação e uma descrição breve.

  2. Bloco OnInit() obtém controle uma vez que o EA seja carregado no terminal. Ele pode conter vários dados relacionados com a inicialização do EA - declarando variáveis e arrays, obtendo manipuladores de indicador, etc. Ou seja, este bloco não tem nenhuma função que poderia ser diretamente associada com negociação.

  3. Bloco OnDeinit() atua como inverso do bloco OnInit(). É chamado quando o EA completa sua operação (EA/desligamento do terminal ou inicialização mal sucedida de um EA). Uma das principais funções deste bloco é o deslocamento de espaço de memória ocupada pelo EA quando não é mais necessário. Em outras palavras, ele descreve processos de exclusão de variáveis, arrays e manipuladores de indicador, etc.

  4. Bloco OnTick() é chamado toda vez que uma nova informação sobre o símbolo (par de moeda) é recebida do servidor. Ele especifica as condições para fazer o negócio e as funções da negociação em si.

Exemplo de um novo documento gerado por pré-definição no MetaEditor
Fig. 2. Exemplo de um novo documento gerado por pré-definição no MetaEditor

Permita-me explicar usando o exemplo acima. Temos um código de Expert Advisor "vazio", um tipo de template de Expert Advisor que depois será necessário ser preenchido.
O que podemos ver aqui é o seguinte:

  • as primeiras cinco linhas (linhas 1 até 5) representam comentários contendo o nome do EA (nome do arquivo), o nome da empresa fabricante e seu site. Você pode escrever aqui qualquer coisa que quiser. Este texto não será visto em nenhum lugar e pode até mesmo ser pulado. As informações que contém apenas visam o desenvolvedor;

  • as próximas 3 linhas (linhas 6 a 8) representam o Bloco de parâmetro. Esta informação pode ser observada ao iniciar o EA no terminal;

  • é acompanhada pela função OnInit() (linhas 12 a 19). Este é o bloco OnInit(). Esta função não pega nenhum parâmetro, mas retorna (embora possa não retornar também) o código de inicialização;

  • a função OnDeinit(const int reason) vai a seguir (linhas 22 a 26). Este é o bloco OnDeinit(). Ele possui um parâmetro que especifica o motivo do desligamento do EA.
    Se a inicialização do EA não for bem sucedida, esta função recebe um código relevante como parâmetro;

  • a última função é OnTick() (linhas 30 a 34). Este é o bloco OnTick descrito antes. Este bloco pode se dizer que é o "cérebro" do EA porque compreende todas as funções encarregadas das negociações.

Como disse antes, a estrutura pode ser bem mais complexa e feita de uma boa quantidade de blocos, diferente deste exemplo fácil de entender. Quando você sente que isso não é suficiente, você pode adicionar seus próprios blocos.

Indicadores e como manipulá-los

Indicadores são pequenos programas escritos no MQL que são exibidos no gráfico de preços ou em uma janela separada abaixo do gráfico de preços e nos permite realizar uma análise técnica do mercado.

Todos os indicadores podem ser classificados em dois tipos: indicadores seguidores de tendência e osciladores.

Os indicadores seguidores de tendência são, em via de regra, desenhados no gráfico de preços e são usados para identificar a direção da tendência, enquanto os osciladores podem normalmente ser vistos abaixo do gráfico de preços e servem para identificar pontos de entrada.

A maioria dos indicadores tem ao menos um buffer (buffer indicador) que contém seus dados de leitura em um determinado momento. Como um EA, o indicador tem seu símbolo e período de tempo no qual é calculado.

O buffer indicador pode ser considerado como uma coluna, o último elemento no qual está executando um valor.

Exemplo do Indicador de média móvel
Fig. 3. Exemplo do Indicador de média móvel

O buffer indicador é um array, onde o primeiro elemento (com índice 0) transporta dados no candlestick mais à direita e o seguinte elemento (com índice 1) transporta dados no segundo candlestick à direita, etc. Tal organização dos elementos é chamada de série de tempo.

Veja o seguinte exemplo:
Suponha que o par de moedas que temos seja EUR/USD, período de tempo é de 1 hora.
Primeiro de tudo, precisamos adicionar o indicador ao EA e obter seu manipulador.

O manipulador é um ponteiro único para o indicador, que nos permite abordar este indicador em qualquer parte no programa.

int iMA_handle; 
iMA_handle=iMA("EURUSD",PERIOD_H1,10,0,MODE_SMA,PRICE_CLOSE);
Vejamos de mais perto.

A primeira linha define uma variável que armazenará o manipulador do indicador. A segunda linha chama o indicador (aqui, o indicador de média móvel), especifica seus parâmetros e salva o manipulador na variável para uso futuro.
Após digitar "iMA(" no MetaEditor, uma janela pop-up aparecerá acima desta linha mostrando os parâmetros de chamada do indicador separados por vírgula.

Exemplo da janela pop-up para os parâmetros do indicador de média móvel
Fig. 4. Exemplo da janela pop-up para os parâmetros do indicador de média móvel

Podemos ver os seguintes parâmetros listados da esquerda para direita.

  1. nome do símbolo (aparece em letras em negrito na janela pop-up) é um parâmetro de texto, par de moeda (símbolo);
  2. período de tempo;
  3. período do indicador (aqui, o período médio);
  4. troca de gráfico por N barras para frente/para trás. Um número positivo denota a troca de gráfico por N barras para frente, enquanto um número negativo denota a troca do gráfico por N barras para trás;
  5. método médio;
  6. preço aplicado ou um manipulador de um indicador diferente.

Há um conjunto exclusivo de variáveis e seus tipos para cada indicador. Se você passar por um indicador desconhecido, as informações nele podem sempre ser encontradas na Ajuda em contexto anexa. Por exemplo, uma vez que tenha digitado iMA e pressionado F1, uma janela de Ajuda abrirá fornecendo informações sobre este indicador específico e uma descrição detalhada de todas suas propriedades.

Exemplo de chamada da janela Ajuda para a descrição do indicador pressionando F1
Fig. 5. Exemplo de chamada da janela Ajuda para a descrição do indicador pressionando F1

Após escrever o código e iniciar o EA no terminal, veremos (uma vez que o EA apareça no canto superior direito do gráfico de preço) que o indicador está faltando no gráfico. Isso não é um erro - foi intencional. Para aparecer, precisamos adicionar outra linha:

ChartIndicatorAdd(ChartID(),0,iMA_handle);

Veremos agora o que ela faz. Passe o cursor sobre o comando ChartIndicatorAdd e pressione F1 para ler as informações de Ajuda no propósito do comando. Ele diz que este comando:

Adiciona um indicador com o manipulador especificado em uma janela de gráfico específica.

O segundo parâmetro que é igual a zero é o número da subjanela. Subjanelas geralmente contêm osciladores, abaixo do gráfico de preço. Lembra? Pode haver vários deles. Para exibir o indicador na subjanela, você precisa apenas especificar o número da subjanela de modo que seja maior que o número já existente em 1, ou seja, o número seguinte ao número existente.

Mudando a linha de código da seguinte forma:

ChartIndicatorAdd(ChartID(),1,iMA_handle);

nosso indicador aparecerá na subjanela abaixo do gráfico de preço.

Agora é hora de tentar obter alguns dados do indicador. Para este propósito, declaramos um array dinâmico, organize o array indexando quantas séries de tempo for necessário para conveniência e copie os valores do indicador neste array.

double iMA_buf[];
ArraySetAsSeries(iMA_buf,true);
CopyBuffer(iMA_handle,0,0,3,iMA_buf);

O exemplo acima mostra que declaramos o array dinâmico iMA_buf[] de tipo duplo já que o indicador de média móvel é baseado em preços e preços têm frações.

A próxima linha define a indexação para o array de modo que os elementos com índices menores armazenem valores antigos, enquanto os elementos com índices maiores armazenem valores mais recentes. Isso é utilizado para conveniência e evitar confusão já que os buffers do indicador em todos os indicadores são indexados como séries de tempo.

A última linha serve para copiar os valores do indicador no array iMA_buf[]. Estes dados estão agora prontos para serem utilizados.

Ordens, negócios e posições

Vamos começar pelas ordens.

  • Ordens são solicitações de negócio aceitas pelo servidor de negociação. Se a solicitação for inválida, ela será rejeitada.
    Para evitar a dificuldade em preencher a solicitação de negócio, mostrarei depois como isso pode ser feito utilizando as bibliotecas padrão tornando essa tarefa muito mais fácil.
    Existem 2 tipos de ordens: mercado (para execução imediata) e pendente.
As ordens de mercado representam instruções para vender ou comprar determinada quantidade de um instrumento financeiro específico com o atual preço de mercado.
As ordens pendentes representam instruções para executar o negócio sujeito a determinadas condições. As ordens pendentes têm um certo tempo de vencimento onde são excluídas.
  • Negócios representam os resultados da execução das ordens (instruções para executar o negócio). Cada negócio é baseado em uma determinada ordem única, onde uma única ordem pode resultar em múltiplos negócios. Por exemplo, uma ordem para comprar 10 lotes pode ser executada por uma execução parcial de uma série de negócios consecutivos. Os negócios são sempre armazenados no histórico de negociação e não podem ser modificados. O terminal exibe negócios na guia "Histórico".
  • Posições representam o resultado das ordens em ação. Apenas uma posição, tanto Longa quanto Curta, pode ser aberta para cada símbolo único.

Para esclarecer, permita-me ilustrar com um exemplo: abrimos uma posição longa de 1 lote, ou seja, posicionamos uma ordem no preço atual de mercado (por exemplo) e o tamanho de 1 lote. Se a solicitação for válida, ela será enviada para o servidor para processamento. Assim que o processamento é concluído, uma posição com os parâmetros da ordem aparecerá na guia "Negócio" do terminal. Suponha, decidimos então abrir outra posição longa, também com tamanho de 1 lote. Após o processamento da ordem, não veremos duas ordens na guia "Negócio", mas, ao invés disso, uma posição com tamanho para 2 lotes. Ou seja, a posição é o resultado da execução de uma série de ordens.

Vamos continuar com a prática. Os seguintes campos da estrutura precisam ser preenchidos, a fim de fazer a solicitação:

struct MqlTradeRequest
{
ENUM_TRADE_REQUEST_ACTIONS action; // Type of action
ulong magic; // Expert Advisor ID (magic number)
ulong order; // Order ticket
string symbol; // Trade instrument
double volume; // Requested trade size in lots
double price; // Price 
double stoplimit; // StopLimit level of the order
double sl; // Stop Loss level of the order
double tp; // Take Profit level of the order
ulong deviation; // Maximum allowed deviation from the requested price
ENUM_ORDER_TYPE type; // Order type
ENUM_ORDER_TYPE_FILLING type_filling; // Order type by execution
ENUM_ORDER_TYPE_TIME type_time; // Order type by duration
datetime expiration; // Order expiration time (for orders of the ORDER_TIME_SPECIFIED type)
string comment; // Comment to the order
};

Por haver várias ordens, cada tipo de ordem possui seu próprio conjunto de parâmetros obrigatórios. Não vou abordar estes campos por completo. O site oferece muitas informações sobre este assunto. Se mesmo um dos parâmetros obrigatórios para um determinado tipo de ordem não for especificado ou especificado de forma errada, a solicitação falhará.

A estrutura acima está especificada apenas para demonstrar melhor a dificuldade que surge ao preencher.

Stop Loss e Take Profit

Stop Loss e Take Profit são ordens especiais posicionadas como uma "medida de retorno". Ou seja, em caso de enganos ou uma posição for aberta por um Expert Advisor que está mostrando uma perda, uma ordem Stop Loss pode limitar as perdas em um nível predefinido.

Take Profit atua de forma similar, apenas limitando o lucro neste caso. Pode ser necessário para que não nos preocupemos em fechar uma posição. Ela fechará quando atingir um determinado nível de preço. Em outras palavras, estas ordens representam nosso "plano de seguro", se o mercado se virar contra nós ou se quisermos ter lucro.

Este tipo de ordem não pode ser posicionado separadamente sozinho - pode apenas modificar posições já existentes.

Utilizando as bibliotecas padrão

Então, finalmente chegamos na Biblioteca padrão. Esta biblioteca vem junto com o terminal, por isso seu nome - Biblioteca padrão. Ela compreende funções que facilitam a programação de EAs e parcialmente realiza processos complexos, por exemplo, geração de solicitação de negócio.

As bibliotecas de negócio (veja também classes de negócio) estão localizadas no seguinte caminho: Include\Trade\ e pode ser adicionada utilizando a diretriz #include.
Exemplo:

#include 
#include 

As classes acima podem ser consideradas como básicas já que a maioria dos Expert Advisors podem ser programados utilizando apenas estas duas classes (bibliotecas). Eu as chamo de bibliotecas:

  • A primeira é designada para posicionar e modificar ordens.
  • A segunda serve para obter informações sobre as posições já existentes.

Às vezes, outra biblioteca pode ser útil:
#include 
Ela contém funções para trabalhar com ordens, se, digamos, nossa estratégia precisar do uso de ordens pendentes.

Você se lembra da estrutura de solicitação de negócio cheia de vários parâmetros que requerem conhecimento para serem utilizados adequadamente?
Agora, darei um exemplo de uma solicitação de negócio feita utilizando a biblioteca:
CTrade m_Trade;
m_Trade.Sell(lot,symbol_name,price,sl,tp,comment);

Existe um total de 6 parâmetros aqui, apenas um sendo obrigatório (o tamanho da ordem - que é o primeiro parâmetro).
Agora especificarei cada um deles:

  • lot é o tamanho da ordem a ser posicionada;
  • symbol_name é o símbolo (par de moeda) que a ordem se aplica (se nenhum for especificado, o símbolo de moeda do Expert Advisor é utilizada);
  • price é o preço de abertura (desde que esta seja a função para abrir uma ordem ativa, seu preço pode ser indefinido, neste caso irá automaticamente ser obtido diretamente do gráfico de preço);
  • sl é o preço no qual a ordem fechará, o preço não deve ser a nossa vantagem (ele deve ser deixado fora se a estratégia não implica o uso do stop loss);
  • tp é o preço no qual a ordem fechará, o preço deve tomar a direção requerida, ou seja, ele tira o lucro (ele deve ser deixado fora se a estratégia não implica o uso do take profit);
  • comment é o comentário para a ordem, ou seja, especificando o motivo para posicionar a ordem.

Existem diversos meios de fechar uma posição:

  1. fechar a posição inteira
    CPositionInfo m_Position;
    m_Position.Select(symbol_name);
    m_Trade.PositionClose(symbol_name);
  2. fechar a posição posicionando uma ordem reversa do mesmo tamanho
    CTrade m_Trade;
    m_Trade.Buy(lot,symbol_name,price,sl,tp,comment);
  3. utilizando um método mais complicado onde todas as posições abertas são primeiro buscadas para destacar aquela que atenda aos parâmetros requeridos (símbolo, tipo, número mágico, identificador de posição, etc.) para ser, depois, fechada.
    Não vou dar exemplo do citado acima por causa de sua dificuldade para iniciantes.

Juntando tudo

Agora é o momento exato para colocar todo o conhecimento recém adquirido em um único Expert Advisor.

//+------------------------------------------------------------------+
//|                                           fast-start-example.mq5 |
//|                        Copyright 2012, MetaQuotes Software Corp. |
//|                                              https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2012, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
#include                                          //include the library for execution of trades
#include                                   //include the library for obtaining information on positions

int               iMA_handle;                              //variable for storing the indicator handle
double            iMA_buf[];                               //dynamic array for storing indicator values
double            Close_buf[];                             //dynamic array for storing the closing price of each bar

string            my_symbol;                               //variable for storing the symbol
ENUM_TIMEFRAMES   my_timeframe;                             //variable for storing the time frame

CTrade            m_Trade;                                 //structure for execution of trades
CPositionInfo     m_Position;                              //structure for obtaining information of positions
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {
   my_symbol=Symbol();                                      //save the current chart symbol for further operation of the EA on this very symbol
   my_timeframe=PERIOD_CURRENT;                              //save the current time frame of the chart for further operation of the EA on this very time frame
   iMA_handle=iMA(my_symbol,my_timeframe,40,0,MODE_SMA,PRICE_CLOSE);  //apply the indicator and get its handle
   if(iMA_handle==INVALID_HANDLE)                            //check the availability of the indicator handle
   {
      Print("Failed to get the indicator handle");              //if the handle is not obtained, print the relevant error message into the log file
      return(-1);                                           //complete handling the error
   }
   ChartIndicatorAdd(ChartID(),0,iMA_handle);                  //add the indicator to the price chart
   ArraySetAsSeries(iMA_buf,true);                            //set iMA_buf array indexing as time series
   ArraySetAsSeries(Close_buf,true);                          //set Close_buf array indexing as time series
   return(0);                                               //return 0, initialization complete
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   IndicatorRelease(iMA_handle);                             //deletes the indicator handle and deallocates the memory space it occupies
   ArrayFree(iMA_buf);                                      //free the dynamic array iMA_buf of data
   ArrayFree(Close_buf);                                    //free the dynamic array Close_buf of data
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   int err1=0;                                             //variable for storing the results of working with the indicator buffer
   int err2=0;                                             //variable for storing the results of working with the price chart
   
   err1=CopyBuffer(iMA_handle,0,1,2,iMA_buf);               //copy data from the indicator array into the dynamic array iMA_buf for further work with them
   err2=CopyClose(my_symbol,my_timeframe,1,2,Close_buf);    //copy the price chart data into the dynamic array Close_buf for further work with them
   if(err1<0 || err2<0)                                    //in case of errors
   {
      Print("Failed to copy data from the indicator buffer or price chart buffer");  //then print the relevant error message into the log file
      return;                                                               //and exit the function
   }

   if(iMA_buf[1]>Close_buf[1] && iMA_buf[0]<Close_buf[0])   //if the indicator values were greater than the closing price and became smaller
     {
      if(m_Position.Select(my_symbol))                     //if the position for this symbol already exists
        {
         if(m_Position.PositionType()==POSITION_TYPE_SELL) m_Trade.PositionClose(my_symbol);  //and this is a Sell position, then close it
         if(m_Position.PositionType()==POSITION_TYPE_BUY) return;                              //or else, if this is a Buy position, then exit
        }
      m_Trade.Buy(0.1,my_symbol);                          //if we got here, it means there is no position; then we open it
     }
   if(iMA_buf[1]<Close_buf[1] && iMA_buf[0]>Close_buf[0])  //if the indicator values were less than the closing price and became greater
     {
      if(m_Position.Select(my_symbol))                     //if the position for this symbol already exists
        {
         if(m_Position.PositionType()==POSITION_TYPE_BUY) m_Trade.PositionClose(my_symbol);   //and this is a Buy position, then close it
         if(m_Position.PositionType()==POSITION_TYPE_SELL) return;                             //or else, if this is a Sell position, then exit
        }
      m_Trade.Sell(0.1,my_symbol);                         //if we got here, it means there is no position; then we open it
     }
  }
//+------------------------------------------------------------------+

Vamos testar nosso Expert Advisor com os parâmetros da seguinte forma:

  • símbolo - EURUSD;
  • período de tempo - H1;
  • modo de negociação "Abrindo apenas preços".

Devido a utilização dos valores do indicador e dos preços de fechamento começarem com a primeira barra (barra zero é uma moeda, barra ativa), o gráfico não será redesenhado. Isso significa que podemos usar o modo de negociação "Abrindo apenas preços". Isso não afetará a qualidade de teste, mas fará com que ele rode mais rápido.

E aqui estão os rápidos resultados utilizando dados do histórico.

Nossos resultados de teste do Expert Advisor
Fig. 6. Nossos resultados de teste do Expert Advisor

Os rebaixamentos certamente não podem passar despercebidos. Porém, este artigo não foca na programação de um "super Expert Advisor" que teria um grande potencial de lucro com mínimo rebaixamento, mas sim, demonstrar quão fácil é para uma pessoa fazer um EA quando provido de conhecimento básico.
Temos o Expert Advisor consistindo em menos de cem linhas de código.

Conclusão

Este artigo cobriu os princípios fundamentais a serem considerados ao programar um EA. Aprendemos como utilizar a Ajuda em contexto anexa no MetaEditor 5 para obter informações sobre várias funções, temos uma ideia geral das ordens e posições e abrangemos o uso de bibliotecas padrão.

Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/496

Arquivos anexados |

Outros artigos do autor

MQL5 Wizard: nova versão MQL5 Wizard: nova versão
O artigo contém descrições dos novos recursos disponíveis no MQL5 Wizard. A arquitetura modificada dos sinais permite criar robôs de negócio com base na combinação de vários padrões de mercado. O exemplo contido no artigo explica o procedimento da criação interativa de um Expert Advisor.
Estratégias de ordem. Expert Advisor de propósito múltiplo. Estratégias de ordem. Expert Advisor de propósito múltiplo.
Este artigo centraliza estratégias que usam ativamente ordens pendentes, uma metalinguagem que pode ser criada para formalmente descrever tais estratégias e uso de um Expert Advisor de propósito múltiplo em que a operação baseia-se nestas descrições.
Controles gráficos personalizados. Parte 1: criando um controle simples Controles gráficos personalizados. Parte 1: criando um controle simples
Este artigo cobre os princípios gerais para desenvolvimento de controles gráficos. Vamos preparar ferramentas para um trabalho rápido e conveniente com objetos gráficos, analisar um exemplo de criação de um simples controle para inserir texto ou dados numéricos, bem como os meios para usá-los.
Operações de negócios no MQL5 - São fáceis Operações de negócios no MQL5 - São fáceis
Quase todos os negociadores chegam ao mercado para fazer dinheiro, mas alguns também apreciam o processo em si. No entanto, não é apenas a negociação manual que pode lhe proporcionar uma experiência emocionante. O desenvolvimento de sistemas automatizados de negociação também pode ser bastante impressionante. Criar uma negociação automática pode ser tão interessante quanto ler um bom romance de mistério.