
Uma rápida inicialização ou um guia breve para iniciantes
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.
Fig. 1. Os principais blocos do EA
- 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.
- 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.
- 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.
- 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.
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.
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.
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.
- nome do símbolo (aparece em letras em negrito na janela pop-up) é um parâmetro de texto, par de moeda (símbolo);
- período de tempo;
- período do indicador (aqui, o período médio);
- 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;
- método médio;
- 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.
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:
- fechar a posição inteira
CPositionInfo m_Position; m_Position.Select(symbol_name); m_Trade.PositionClose(symbol_name);
- fechar a posição posicionando uma ordem reversa do mesmo tamanho
CTrade m_Trade; m_Trade.Buy(lot,symbol_name,price,sl,tp,comment);
- 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.
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





- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Você concorda com a política do site e com os termos de uso