You are on page 1of 36

'Guia passo a passo para iniciantes para escrever um Expert Advisor n... https://www.mql5.

com/pt/articles/100

Download MetaTrader 5

0 7 621
SAMUEL OLOWOYO

Introdução
Este artigo é destinado a iniciantes que desejam aprender como escrever
Consultores Especialistas simples na nova linguagem MQL5. Nós começaremos
primeiro definindo o que queremos que o nosso CE (Consultor Especialista)
faça, e descrição então passaremos para como nós queremos que o CE o faça.

1. Estratégia de negociação
O que o nosso CE fará:

Ele irá monitorar um indicador particular e, quando uma certa condição


for alcançada (ou certas condições foram alcançadas), ele irá colocar
uma negociação (tanto uma posição curta/vendida ou longa/comprada),
dependendo da condição presente que foi alcançada.

O mencionado acima é chamado de estratégia de negociação. Antes que você


possa escrever um CE, você precisa primeiro desenvolver a estratégia que você
deseja automatizar no CE. Então, neste caso, deixe-nos modificar a afirmação
acima de forma que ela reflita a estratégia que nós queremos desenvolver no
CE.

Nós utilizaremos um indicador chamado média móvel com um período de


8 (você pode escolher qualquer período, mas para os propósitos da nossa
estratégia, nós usaremos 8).

Queremos que o nosso CE ofereça uma negociação longa (compra)


quando a média móvel-8 (para o propósito neste assunto, eu irei me
referir a ela como MM-8) estiver aumentando e o preço estiver acima
dela, e oferecerá uma negociação curta (venda) quando a MM-8 estiver
diminuindo e o preço estiver abaixo dela.
Também utilizaremos outro indicador chamado movimento direcional
médio (ADX) com período 8 também para nos ajudar a determinar se o
mercado está em tendência ou não. Estamos fazendo isso porque apenas
queremos entrar na negociação quando o mercado estiver em tendência
e relaxar quando o mercado estiver variando (isto é, sem tendência).
Para alcançar isso, apenas ofereceremos a nossa negociação (comprar ou
vender) quando as condições acima forem atendidas e o valor do ADX for

1 de 36 08/12/2015 01:19
'Guia passo a passo para iniciantes para escrever um Expert Advisor n... https://www.mql5.com/pt/articles/100

maior que 22. Se o ADX for maior do que 22 porém diminuindo, ou o ADX
for menor do que 22, não negociaremos, mesmo que a condição B tenha
sido atendida.
Também queremos nos proteger definindo uma ordem para parar perda
(ou stop loss) de 30 pontos, e para o nosso alvo de lucro; definiremos
como objetivo um lucro de 100 pontos.
Também queremos que nosso CE procure por oportunidades de
compra/venda somente quando uma nova barra tenha sido formada e
também queremos nos certificar que abrimos uma posição de compra, se
as condições de compra forem atendidas e já não tivermos uma em
aberto, e abrir uma posição de venda quando as condições de venda
forem atendidas e já não tivermos uma em aberto.

Agora desenvolvemos a nossa estratégia; é a hora de começar a escrever o


nosso código.

2. Escrever um Expert Advisor


2.1 Assistente do MQL5

Inicie com a execução do editor de linguagem do MetaQuotes 5. Pressione


Ctrl+N ou clique no botão Novo na barra do menu.

Figura 1. Iniciando um novo documento do MQL5

Na janela do instalador do MQL5, selecione consultor especialista e clique em


"Próximo" como mostrado na figura 2:

2 de 36 08/12/2015 01:19
'Guia passo a passo para iniciantes para escrever um Expert Advisor n... https://www.mql5.com/pt/articles/100

Figura 2. Selecionando um tipo de programa

Na próxima janela, digite o nome que você quer dar ao seu CE na caixa Nome.
Neste caso, eu digitei My_First_EA. Você pode então digitar o seu nome na
caixa Autor e também o endereço da sua página da internet ou endereço de
e-mail na caixa Link (se você tiver um).

Figura 3. Propriedades gerais do consultor especialista

Já que queremos ser capazes de mudar alguns dos parâmetros para o nosso CE
de forma a ver quais dos valores podem nos fornecer melhor resultado, nós
iremos adicioná-los clicando no botão "Adicionar".

3 de 36 08/12/2015 01:19
'Guia passo a passo para iniciantes para escrever um Expert Advisor n... https://www.mql5.com/pt/articles/100

Figura 4. Configurando os parâmetros de entrada do CE

Em nosso CE, queremos ser capazes de experimentar com as nossas


configurações de ordem do tipo parar perda, obter lucro, período ADX e período
de média móvel, então iremos defini-los nesse momento.

Clique duas vezes sob a seção Nome e digite o nome do parâmetro, então
clique duas vezes sobre o Tipo para selecionar o tipo de dados para o
parâmetro e clique duas vezes sob a seção Valor inicial e digite o valor inicial
para o parâmetro.

Quando terminar, ele deve se parecer com isto:

Figura 5. Tipos de dados dos parâmetros de entrada do CE

4 de 36 08/12/2015 01:19
'Guia passo a passo para iniciantes para escrever um Expert Advisor n... https://www.mql5.com/pt/articles/100

Como pode ser visto acima, foi selecionado o tipo de dado inteiro (int) para
todos os parâmetros. Vamos falar um pouco sobre tipos de dados.

char: O tipo char toma 1 byte de memória (8 bits) e permite expressar


em notação binária 2^8=256 valores. O tipo char pode conter ambos
valores positivos e negativos. A mudança de valores é de -128 a 127.
uchar : O tipo inteiro uchar também ocupa 1 byte de memória, assim
como o tipo de char, mas ao contrário dele o uchar destina-se apenas a
valores positivos. O valor mínimo é zero, o valor máximo é 255. A
primeira letra u no nome do tipo uchar é a abreviação para não assinado.
short: O tamanho do tipo short é de 2 bytes (16 bits) e,
consequentemente, ele segue expressando a faixa de valores igual a 2
para a potência 16: 2^16 = 65 536. Uma vez que o tipo short é um tipo
assinado, ele contém ambos valores positivos e negativos, a faixa de
valores está entre -32 768 e 32 767.
ushort: O tipo não assinado short é o tipo ushort, que também possui
um tamanho de 2 bytes. O valor mínimo é 0, e o valor máximo é 65 535.
int : O tamanho do tipo int é de 4 bytes (32 bits). O valor mínimo é -2
147 483 648, o valor máximo é 2 147 483 647.
uint : O tipo inteiro não assinado é o uint. Ele toma 4 bytes de memória
e permite expressar inteiros de 0 a 4 294 967 295.
long : O tamanho do tipo long é de 8 bytes (64 bits). O valor mínimo é
-9 223 372 036 854 775 808, o valor máximo é 9 223 372 036 854 775
807.
ulong : O tipo ulong também ocupa 8 bytes e pode armazenar valores
de 0 a 18 446 744 073 709 551 615.

Pela descrição acima dos vários tipos de dados, os tipos inteiros não assinados
não são projetados para armazenar valores negativos, qualquer tentativa de
configurar um valor negativo pode levar a consequências inesperadas. Por
exemplo, se você quer armazenar valores negativos, você não pode
armazená-los dentro dos tipos não assinados (isto é, uchar, uint, ushort, ulong).

Voltando ao ao nosso CE. Olhando os tipos de dados, você irá concordar que
devemos utilizar os tipos de dados char ou uchar já que os dados que
pretendemos armazenar nestes parâmetros sejam menores do que 127 ou 255
respectivamente. Para bom gerenciamento da memória, essa é a melhor coisa
a se fazer. Entretanto, pelo propósito desta discussão, iremos nos ater ao tipo
int.
Uma vez que tenha acabado de configurar todos os parâmetros necessários,
clique no botão Finished e o editor do MetaQuotes criará um esqueleto do
código para você como mostrado na próxima figura.

5 de 36 08/12/2015 01:19
'Guia passo a passo para iniciantes para escrever um Expert Advisor n... https://www.mql5.com/pt/articles/100

Vamos separar o código em várias seções para melhor entendimento.

A parte superior (cabeçalho) do código é onde a propriedade do CE é definida.


Você pode ver que aqui estão os valores que você preencheu durante o
assistente do MQL5 na figura 3.

Nesta seção do código, você pode definir parâmetros adicionais como descrição
(breve descrição do texto do CE), declarar constantes, incluir arquivos adicionais
ou funções mais importantes.

Quando uma declaração começa com um símbolo #, ela é chamada de diretiva


de pré-processamento e não termina com um ponto e vírgula ‘;’ outros
exemplos de diretivas de pré-processamento incluem:

#define :

A diretiva #define é utilizada para uma declaração de constantes. É escrita na


forma

#define identificador token_string

O que isso faz é substituir cada ocorrência de identificador no seu código com o
valor token_string.

6 de 36 08/12/2015 01:19
'Guia passo a passo para iniciantes para escrever um Expert Advisor n... https://www.mql5.com/pt/articles/100

Exemplo:

#define ABC 100


#define COMPANY_NAME "MetaQuotes Software Corp."

Ele substituirá todas as ocorrências de COMPANY_NAME pela sequência


"MetaQuotes Software Corp." ou ele substituirá todas as ocorrências de ABC
pelo char (ou inteiro) 100 em seu código.

Você pode ler mais sobre as diretivas de pré-processamento no manual do


MQL5. Vamos agora continuar com a nossa discussão.

A segunda parte do cabeçalho do nosso código é a seção parâmetros de


entrada:

Nós especificamos todos os parâmetros, que serão utilizados em nosso CE nesta


seção. Estes incluem todas as variáveis que serão utilizadas por todas as
funções que nós escreveremos em nosso CE.

Variáveis declaradas nesse nível são chamadas de Variáveis globais porque elas
são acessíveis por todas as funções em nosso CE que possam precisar delas. Os
parâmetros de entrada são parâmetros que podem apenas ser modificados fora
do nosso CE. Também podemos declarar outras variáveis que iremos manipular
no curso do nosso CE mas não estarão disponíveis fora do nosso CE nesta
seção.

A seguir está a função de inicialização do CE. Essa é a primeira função que é


chamada quando o CE é iniciado ou anexado a um gráfico e é chamado apenas
uma vez.

Essa seção é o melhor local para realizar algumas verificações importantes de


forma a se certificar de que o nosso CE funciona muito bem.

Podemos decidir se o gráfico possui barras suficientes para o nosso CE


funcionar, etc.

Também é o melhor local para pegar as cotações que utilizaremos para os


nossos indicadores (indicadores ADX e de média móvel).

A função OnDeinit é chamada quando o CE é removido do gráfico.

Para o nosso CE, nós iremos liberar as cotações criadas para os nossos
indicadores durante a inicialização nesta seção.

7 de 36 08/12/2015 01:19
'Guia passo a passo para iniciantes para escrever um Expert Advisor n... https://www.mql5.com/pt/articles/100

Essa função processa o evento NewTick, que é gerado quando uma nova
cotação é recebida para um símbolo.

Observe que o consultor especialista não pode realizar operações de negócios


se o uso dos consultores especialistas no terminal do cliente não estiver
permitido (botão "Auto Negociação").

Figura 6. Auto Negociação está ativada

A maior parte dos nossos códigos que irão implementar a nossa estratégia de
de negócios, desenvolvidos anteriormente, serão escritos nessa seção.

Agora que já observamos as várias seções do código para o nosso CE, vamos
começar a adicionar mais conteúdo a este esqueleto.

2.2 SEÇÃO DE PARÂMETROS DE ENTRADA

//--- input parameters


input int StopLoss=30; // Stop Loss
input int TakeProfit=100; // Take Profit
input int ADX_Period=8; // ADX Period
input int MA_Period=8; // Moving Average Period
input int EA_Magic=12345; // EA Magic Number
input double Adx_Min=22.0; // Minimum ADX Value
input double Lot=0.1; // Lots to Trade
//--- Other parameters
int adxHandle; // handle for our ADX indicator
int maHandle; // handle for our Moving Average indicator
double plsDI[],minDI[],adxVal[]; // Dynamic arrays to hold the values o
double maVal[]; // Dynamic array to hold the values of Moving Average f
double p_close; // Variable to store the close value of a bar
int STP, TKP; // To be used for Stop Loss & Take Profit values

Como você pode ver, nós adicionamos mais parâmetros. Antes de continuarmos
a discutir os novos parâmetros, vamos discutir algo que você pode ver agora. As
duas barras normais ‘//’ nos permitem inserir comentários em nossos códigos.
Com comentários, somos capazes de saber o que as nossas variáveis significam,
ou o que nós estamos fazendo naquele momento de tempo em nosso código.
Também fornece um melhor entendimento do nosso código. Há duas formas
básicas de escrever comentários:

// Outros parâmetros ...

Esse é um comentário de uma linha:

8 de 36 08/12/2015 01:19
'Guia passo a passo para iniciantes para escrever um Expert Advisor n... https://www.mql5.com/pt/articles/100

/*

Esse é um comentário de várias linhas

*/

Esse é um comentário de várias linhas. Comentários com várias linhas começam


com o par de símbolos /* e terminam com o par */.

O compilador ignora todos os comentários quando compilando o código.

Utilizar comentários de uma linha para os parâmetros de entrada é uma boa


forma de fazer os usuários do CE entenderem o que esses parâmetros
significam. Nas propriedades de entrada do CE, nossos usuários não irão
visualizar o parâmetro em si, ao invés disso verão os comentários como
mostrados abaixo:

Figura 7. Parâmetros de entrada do consultor especialista

Agora de volta para o nosso código...

Nós decidimos adicionar parâmetros adicionais ao nosso CE. O EA_Magic é o


número mágico para todas as ordens pelo nosso CE. O valor ADX mínimo
(Adx_Min) é declarado como um tipo de dado double. Um double é utilizado
para armazenar constantes de ponto flutuante, que contém uma parte inteira,
um ponto decimal, e uma parte de fração.

Exemplo:

double mysum = 123.5678;

double b7 = 0.09876;

O lote para negociação (Lote) representa o volume do instrumento financeiro


que nós queremos negociar. Então nós declaramos outros parâmetros que
utilizaremos:

O adxHandle deve ser utilizado para armazenar a cotação do indicador ADX,


enquanto o maHandle irá armazenar a cotação para o indicador de média
móvel. Os plsDI[], minDI[], adxVal[] são arranjos dinâmicos que irão
manter os valores de +DI, -DI e ADX principal (do indicador do ADX) para cada
barra do gráfico. O maVal[] é um arranjo dinâmico que irá manter os valores
do indicador da média móvel para cada barra do gráfico.

A propósito, o que são arranjos dinâmicos? Um arranjo dinâmico é um arranjo


declarado sem uma dimensão. Em outras palavras, nenhum valor é especificado
no par de colchetes. Um arranjo estático, por outro lado, possui suas dimensões
definidas no ponto da declaração.

Exemplo:

9 de 36 08/12/2015 01:19
'Guia passo a passo para iniciantes para escrever um Expert Advisor n... https://www.mql5.com/pt/articles/100

double allbars[20]; // this will take 20 elements

p_close é uma variável que nós utilizaremos para armazenar o preço de


fechamento para a barra que nós iremos monitorar para verificar as nossas
negociações de compra/venda.

STP e TKP serão utilizados para armazenar os valores de stop loss e take profit
em nosso CE.

2.3. Seção de inicialização do CE

int OnInit()
{
//--- Get handle for ADX indicator
adxHandle=iADX(NULL,0,ADX_Period);
//--- Get the handle for Moving Average indicator
maHandle=iMA(_Symbol,_Period,MA_Period,0,MODE_EMA,PRICE_CLOSE
//--- What if handle returns Invalid Handle
if(adxHandle<0 || maHandle<0)
{
Alert("Error Creating Handles for indicators - error: ",GetLastEr
}

Aqui nós obtemos as cotações do nosso indicador utilizando as funções do


indicador respectivo.

A cotação do indicador ADX é obtida utilizando a função iADX. Ele toma o


símbolo do gráfico (NULL também significa o símbolo atual no gráfico atual), o
período do gráfico/cronograma (0 também significa o cronograma atual no
gráfico atual), o período de média do ADX para calcular o índice (que nós
definimos antes sob a seção de parâmetros de entrada) como parâmetros ou
argumentos.

int iADX(
string symbol, // symbol name
ENUM_TIMEFRAMES period, // period
int adx_period // averaging period
);

A cotação do indicador da média móvel é obtida utilizando a função iMA.


Ela possui os seguintes argumentos:

o símbolo do gráfico (que pode ser obtido utilizando _symbol, symbol()


ou NULL para o símbolo atual no gráfico atual),
o gráfico do período/cronograma (que pode ser obtido utilizando
_period, period(), ou 0 para o cronograma atual no gráfico atual),
O período médio da média móvel (que nós definimos antes sob a seção
parâmetros de entrada),
a mudança do indicador relativa ao gráfico de preços (a mudança aqui é
0),
o tipo de suavização da média móvel (poderia ser qualquer um dos
seguintes métodos de cálculo da média: Média Simples-MODE_SMA,
Média exponencial-MODE_EMA, Média suavizada-MODE_SMMA
ou Média ponderada linear-MODE_LWMA), e
o preço utilizado para o cálculo da média (aqui utilizamos o preço de
fechamento).

int iMA(
string symbol, // symbol name
ENUM_TIMEFRAMES period, // period
int ma_period, // averaging period
int ma_shift, // horizontal shift
ENUM_MA_METHOD ma_method, // smoothing type
ENUM_APPLIED_PRICE applied_price // type of price or handle
);

10 de 36 08/12/2015 01:19
'Guia passo a passo para iniciantes para escrever um Expert Advisor n... https://www.mql5.com/pt/articles/100

Por favor, leia o manual do MQL5 para obter mais detalhes sobre essas funções
do indicador. Ele lhe dará um melhor entendimento de como utilizar cada
indicador.

Nós novamente tentamos verificar a presença de qualquer erro caso a função


não tenha devolvido a cotação com sucesso, nós receberemos um erro
INVALID_HANDLE. Usamos a função de alerta para exibir o erro utilizando a
função GetlastError.

//--- Let us handle currency pairs with 5 or 3 digit prices instead of


STP = StopLoss;
TKP = TakeProfit;
if(_Digits==5 || _Digits==3)
{
STP = STP*10;
TKP = TKP*10;
}

Decidimos armazenar os valores de parar perdas e obter lucros nas variáveis


STP e TKP que declaramos anteriormente. Por que estamos fazendo isso?

É porque os valores armazenados nos parâmetros de ENTRADA são somente


para leitura, eles não podem ser modificados. Então aqui nós queremos nos
certificar de que o nosso CE funciona bem com todos os corretores. Digits ou
Digits() retorna o número de dígitos decimais determinando a precisão do preço
do símbolo do gráfico atual. Para um gráfico de preços com 5 dígitos ou 3
dígitos, nós multiplicamos ambos o parar perdas e o obter lucros por 10.

2.4. SEÇÃO DE DESINICIALIZAÇÃO DO CE

Uma vez que essa função é utilizada sempre que o CE é desativado ou


removido de um gráfico, nós iremos liberar todas as cotações de indicadores
que foram criadas durante o processo de inicialização aqui. Nós criamos duas
cotações, uma para o indicador do ADX e outra cotação para o indicador da
média móvel.

Nós utilizaremos a função IndicatorRelease() para conseguir isso. Leva apenas


um argumento (a cotação do indicador).

bool IndicatorRelease(
int indicator_handle, // indicator handle
);

A função remove uma cotação do indicador e libera o bloco de cálculo do


indicador, se ele não foi utilizado.

2.5 A SEÇÃO ONTICK DO CE

A primeira coisa que precisamos fazer é verificar se temos barras suficientes no


gráfico atual. Podemos obter o total de barras no histórico de qualquer gráfico
utilizando a função Bars. São necessários dois parâmetros, o símbolo (pode ser
obtido utilizando _Symbol ou Symbol(). Esses dois retornam o símbolo atual
para o gráfico atual no qual o nosso CE está anexado) e o período ou
cronograma do gráfico presente (pode ser obtido utilizando Period ou Period().
Esses dois irão retornar o cronograma do gráfico atual no qual o CE está
anexado).

Se o total disponível de barras é menos do que 60, nós queremos que o nosso

11 de 36 08/12/2015 01:19
'Guia passo a passo para iniciantes para escrever um Expert Advisor n... https://www.mql5.com/pt/articles/100

CE relaxe até que nós tenhamos barras o suficiente disponíveis no gráfico. A


função Alert exibe uma mensagem em uma janela separada. Ela toma
quaisquer valores separados por vírgulas como parâmetros/argumentos. Neste
caso, nós possuímos apena um valor de cadeia (string). O retorno sai da
inicialização do nosso CE.

//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// Do we have enough bars to work with
if(Bars(_Symbol,_Period)<60) // if total bars is less than 60 bars
{
Alert("We have less than 60 bars, EA will now exit!!");
return;
}
// We will use the static Old_Time variable to serve the bar time.
// At each OnTick execution we will check the current bar time with the
// If the bar time isn't equal to the saved time, it indicates that we
static datetime Old_Time;
datetime New_Time[1];
bool IsNewBar=false;

// copying the last bar time to the element New_Time[0]


int copied=CopyTime(_Symbol,_Period,0,1,New_Time);
if(copied>0) // ok, the data has been copied successfully
{
if(Old_Time!=New_Time[0]) // if old time isn't equal to new bar t
{
IsNewBar=true; // if it isn't a first call, the new bar has
if(MQL5InfoInteger(MQL5_DEBUGGING)) Print("We have new bar her
Old_Time=New_Time[0]; // saving bar time
}
}
else
{
Alert("Error in copying historical times data, error =",GetLastEr
ResetLastError();
return;
}

//--- EA should only check for new trade if we have a new bar
if(IsNewBar==false)
{
return;
}

//--- Do we have enough bars to work with


int Mybars=Bars(_Symbol,_Period);
if(Mybars<60) // if total bars is less than 60 bars
{
Alert("We have less than 60 bars, EA will now exit!!");
return;
}

//--- Define some MQL5 Structures we will use for our trade
MqlTick latest_price; // To be used for getting recent/latest pr
MqlTradeRequest mrequest; // To be used for sending our trade reque
MqlTradeResult mresult; // To be used to get our trade results
MqlRates mrate[]; // To be used to store the prices, volumes
ZeroMemory(mrequest); // Initialization of mrequest structure

O consultor especialista realizará operações de negociação no início de uma


nova barra, então é necessário resolver o problema com a nova identificação da
barra. Em outras palavras, nós queremos nos certificar de que o nosso CE não
verifique as configurações longas/curtas a cada variação, nós apenas queremos
que o nosso CE verifique as posições longas/curtas quando houver uma nova
barra.

Começamos declarando uma variável datetime estática Old_Time, que irá


armazenar o tempo da barra. Declaramos ela como estática porque nós
queremos que o valor seja retido na memória até a próxima utilização da

12 de 36 08/12/2015 01:19
'Guia passo a passo para iniciantes para escrever um Expert Advisor n... https://www.mql5.com/pt/articles/100

função OnTick. Então seremos capazes de comparar o seu valor com a variável
New_Time (também do tipo de dados datetime), que é um arranjo de um
elemento para manter o novo (atual) tempo da barra. Também declaramos
uma variável de tipo de dados bool IsNewBar e configuramos seu valor para
false. Isto é porque queremos que esse valor seja VERDADEIRO apenas quando
nós possuirmos uma nova barra.

Utilizamos a função CopyTime para conseguir o tempo da barra atual. Ela copia
o tempo da barra para o arranjo New_Time com um elemento, se ele for bem
sucedido, nós comparamos o tempo de uma nova barra com o tempo da barra
anterior. Se os tempos não forem iguais, isso significa que temos uma nova
barra, e configuramos a variável IsNewBar para VERDADEIRO e salvamos o
valor do tempo da barra atual para a variável Old_Time.

A variável IsNewBar indica que temos uma barra nova. Se for falso,
terminamos a execução da função OnTick.

Dê uma olhada no código:

if(MQL5InfoInteger(MQL5_DEBUGGING)) Print("We have new bar here "

Ele verifica a execução do modo de depuração, ele irá imprimir uma mensagem
sobre os tempos da barra quando em modo de depuração, nós iremos
considerá-lo mais a frente.

A próxima coisa que queremos fazer aqui é verificar se nós temos barras
suficientes para trabalhar. Por que repetir isso? Só queremos nos certificar de
que o nosso CE funciona corretamente. Deve-se notar que enquanto a função
OnInit é chamada apenas uma vez quando o CE está anexado a um gráfico, a
função OnTick é chamada toda vez que há um novo ponto (cotação de preço).

Você pode notar que fizemos de forma diferente novamente aqui. Decidimos
armazenar as barras totais no histórico que obtivemos da expressão:

int Mybars=Bars(_Symbol,_Period);

em uma nova variável, Mybars, declarada dentro da função OnTick. Esse tipo
de variável é uma variável local, ao contrário da variável que nós declaramos na
seção de PARÂMETROS DE ENTRADA do nosso código. Enquanto as variáveis,
declaradas na seção de parâmetros de entrada do nosso código, estão
disponíveis para todas as funções dentro do nosso código que possam precisar
delas, variáveis declaradas dentro de uma única função são limitadas e
disponíveis para aquela função somente. Ela não pode ser utilizada fora daquela
função.

A seguir, nós declaramos algumas variáveis do tipo de estrutura do MQL5


que serão utilizadas nessa seção do nosso CE. O MQL5 possui um número
grande de estruturas integradas que torna as coisas bem fáceis para os
desenvolvedores do CE. Vamos fazer as estruturas uma após a outra.

MqlTick

Essa é uma estrutura utilizada para armazenar os preços mais recentes de


símbolos.

struct MqlTick
{
datetime time; // Hora da última atualização dos preços
double bid; // preço de compra (Bid) atual
double ask; // Preço de venda (Ask) atual
double last; // Preço da última negociação (Last)
ulong volume; // Volume para o último preço atual
};

Qualquer variável declarada como sendo do tipo MqlTick pode ser facilmente
utilizada para obter os valores atuais de Venda (Ask), Compra (Bid), Última

13 de 36 08/12/2015 01:19
'Guia passo a passo para iniciantes para escrever um Expert Advisor n... https://www.mql5.com/pt/articles/100

(Last) eVolume uma vez que você chama a função SymbolInfoTick().


Então nós declaramos latest_price como do tipo MqlTick de forma que
pudéssemos utilizá-la para conseguir os preços de venda (Ask) e compra (Bid).

MqlTradeRequest

Esta estrutura é utilizada para realizar todos os pedidos de negociação para


uma operação de negociação. Ele contém, em sua estrutura, todos os campos
necessários para realizar um acordo de negociação.

struct MqlTradeRequest
{
ENUM_TRADE_REQUEST_ACTIONS action; // Trade operation type
ulong magic; // Expert Advisor ID (magic number)
ulong order; // Order ticket
string symbol; // Trade symbol
double volume; // Requested volume for a deal 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; // Maximal possible deviation from the
requested price
ENUM_ORDER_TYPE type; // Order type
ENUM_ORDER_TYPE_FILLING type_filling; // Order execution type
ENUM_ORDER_TYPE_TIME type_time; // Order execution time
datetime expiration; // Order expiration time (for the orders
of ORDER_TIME_SPECIFIED type)
string comment; // Order comment
};

Qualquer variável declarada como do tipo MqlTradeRequest pode ser utilizada


para enviar pedidos para nossas operações de negociação. Aqui nós declaramos
o mrequest como do tipo MqlTradeRequest.

MqlTradeResult

O resultado de qualquer operação de negociação é retornado como uma


estrutura especial pré-definida do tipo MqlTradeResult. Qualquer variável
declarada como do tipo MqlTradeResult será capaz de acessar os resultados do
pedido de negociação.

struct MqlTradeResult
{
uint retcode; // Operation return code
ulong deal; // Deal ticket, if it is performed
ulong order; // Order ticket, if it is placed
double volume; // Deal volume, confirmed by broker
double price; // Deal price, confirmed by broker
double bid; // Current Bid price
double ask; // Current Ask price
string comment; // Broker comment to operation (by default it
is filled by the operation description)
};

Aqui nós declaramos mresult como sendo do tipo MqlTradeResult.

MqlRates

O preço (aberto, fechado, alto, baixo), a hora, os volumes de cada barra e a


distribuição de um símbolo são armazenados nessa estrutura. Qualquer arranjo
declarado como sendo do tipo MqlRates pode ser utilizado para armazenar
preço, volumes e histórico de diferenças (spread) de um símbolo.

struct MqlRates
{
datetime time; // Period start time
double open; // Open price

14 de 36 08/12/2015 01:19
'Guia passo a passo para iniciantes para escrever um Expert Advisor n... https://www.mql5.com/pt/articles/100

double high; // The highest price of the period


double low; // The lowest price of the period
double close; // Close price
long tick_volume; // Tick volume
int spread; // Spread
long real_volume; // Trade volume
};

Aqui nós declaramos um arranjo mrate[] que irá ser utilizado para armazenar
essas informações.

/*
Let's make sure our arrays values for the Rates, ADX Values and MA
is store serially similar to the timeseries array
*/
// the rates arrays
ArraySetAsSeries(mrate,true);
// the ADX DI+values array
ArraySetAsSeries(plsDI,true);
// the ADX DI-values array
ArraySetAsSeries(minDI,true);
// the ADX values arrays
ArraySetAsSeries(adxVal,true);
// the MA-8 values arrays
ArraySetAsSeries(maVal,true);

Em seguida nós decidimos configurar todos os arranjos que nós utilizaremos


para armazenar os detalhes das barras como série. Isso é para nos certificar de
que os valores que serão copiados para os arranjos serão indexados como a
timeseries, isto é, 0, 1, 2, 3, (para corresponder com o índice das barras. Então
nós utilizamos a função ArraySetAsSeries().

bool ArraySetAsSeries(
void array[], // array by reference
bool set // true denotes reverse order of indexing
);

Deve-se notar que isso também pode ser feito uma vez na seção de
inicialização do nosso código. No entanto, eu decidi mostrar isso nesse
momento para o bem da nossa explicação.

//--- Get the last price quote using the MQL5 MqlTick Structure
if(!SymbolInfoTick(_Symbol,latest_price))
{
Alert("Error getting the latest price quote - error:",GetLastErro
return;
}

Agora nós utilizamos a função SymbolInfoTick para obter a cotação de preço


mais recente. Essa estrutura toma dois argumentos – símbolo do gráfico e a
variável de estrutura MqlTick (latest_price). Novamente, se houver erros, nós
o reportamos.

//--- Get the details of the latest 3 bars


if(CopyRates(_Symbol,_Period,0,3,mrate)<0)
{
Alert("Error copying rates/history data - error:",GetLastError
return;
}

Em seguida, nós copiamos a informação sobre as três últimas barras em noso


arranjo do tipo Mqlrates utilizando a função CopyRates. A função CopyRates é
utilizada para conseguir dados de histórico da estrutura do MqlRates de um
período/símbolo em quantidade específica dentro do arranjo do tipo MqlRates.

int CopyRates(

15 de 36 08/12/2015 01:19
'Guia passo a passo para iniciantes para escrever um Expert Advisor n... https://www.mql5.com/pt/articles/100

string symbol_name, // symbol name


ENUM_TIMEFRAMES timeframe, // period
int start_pos, // start position
int count, // data count to copy
MqlRates rates_array[] // target array to copy
);

O nome do símbolo é obtido utilizando ‘_symbol’, o período/cronograma atual é


obtido utilizando ‘_period’. Para a posição de início, nós começaremos da barra
atual, barra 0 e nós contaremos apenas três barras, barras 0, 1, e 2. O
resultado será armazenado em nosso arranjo, mrate[].

O arranjo mrate[] agora contém todas as informações de preço, tempo,


volumes e distribuição para as barras 0, 1 e 2. Dessa forma para conseguir
detalhes de qualquer barra, nós utilizaremos o seguinte:

mrate[bar_number].bar_property

Por exemplo, nós podemos ter a seguinte informação em cada barra.

mrate[1].time // Bar 1 Start time


mrate[1].open // Bar 1 Open price
mrate[0].high // Bar 0 (current bar) high price, etc

Em seguida nós copiamos todos os valores indicadores nos arranjos dinâmicos


que nós declaramos utilizando a função CopyBuffer.

int CopyBuffer(
int indicator_handle, // indicator handle
int buffer_num, // indicator buffer number
int start_pos, // start position
int count, // amount to copy
double buffer[] // target array to copy
);

A cotação do indicador é a cotação que nós criamos na seção OnInit. Quanto a


números de amortecimento, o indicador ADX possui três amortecimentos:

0 - MAIN_LINE,
1 - PLUSDI_LINE,
2 - MINUSDI_LINE.

O indicador da média móvel possui apenas um (1) amortecimento:

0 – MAIN_LINE.

Nós copiamos da barra atual (0) nas duas últimas barras. Então a quantidade
de registros para copiar é 3 (barras 0, 1, e 2). O buffer[] são os arranjos
dinâmicos alvo que nós declaramos anteriormente – adxVal, plsDI, minDI e
maVal.

Como você pode ver aqui novamente, nós tentamos capturar qualquer erro que
possa ocorrer em nosso processo de cópia. Se houver um erro, não há
necessidade de prosseguir.

É importante observar que as funções CopyBuffer() e CopyRates() retornam ao


número total de registros copiados com sucesso enquanto ela retorna -1 em
caso de um erro. É por isso que nós verificamos valores menores que 0 (zero)
nas funções verificadores de erro aqui.

//--- Copy the new values of our indicators to buffers (arrays) using t
if(CopyBuffer(adxHandle,0,0,3,adxVal)<0 || CopyBuffer(adxHandle,
|| CopyBuffer(adxHandle,2,0,3,minDI)<0)

16 de 36 08/12/2015 01:19
'Guia passo a passo para iniciantes para escrever um Expert Advisor n... https://www.mql5.com/pt/articles/100

{
Alert("Error copying ADX indicator Buffers - error:",GetLastError
return;
}
if(CopyBuffer(maHandle,0,0,3,maVal)<0)
{
Alert("Error copying Moving Average indicator buffer - error:"
return;
}

Nesse momento, queremos verificar se nós já possuímos uma posição de


compra ou venda aberta, em outras palavras, nós queremos nos certificar de
que nós possuímos UMA negociação de compra ou venda aberta de cada vez.
Nós não queremos abrir uma nova compra se nós já possuímos uma, e nós não
queremos abrir uma nova venda se nós já abrimos uma.

Para alcançar isso primeiramente declaramos dois tipos de dados bool variáveis
(Buy_opened e Sell_opened) que manterão um valor REAL se já
possuirmos uma posição aberta tanto para compra ou venda.

//--- we have no errors, so continue


//--- Do we have positions opened already?
bool Buy_opened=false; // variable to hold the result of Buy opene
bool Sell_opened=false; // variable to hold the result of Sell open

if (PositionSelect(_Symbol) ==true) // we have an opened position


{
if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY
{
Buy_opened = true; //It is a Buy
}
else if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SEL
{
Sell_opened = true; // It is a Sell
}
}

Nós usamos a função de negociação PositionSelect para saber se possuímos


uma posição aberta. Essa função retorna VERDADEIRA se já possuímos uma
posição aberta e FALSA se não possuímos nenhuma.

bool PositionSelect(
string symbol // Symbol name
);

Ela toma, como o maior argumento/parâmetro, o símbolo (par de moedas) que


nós queremos verificar. Aqui nós utilizamos _symbol porque estamos verificando
o símbolo atual (par de moedas).

Se a expressão voltar VERDADEIRA então queremos verificar se a posição


aberta é uma compra ou uma venda. Nós utilizamos a função
PositionGetInteger para isso. Ela nos dá o tipo de posição aberta quando nós
utilizamos ela com o modificadorPOSITION_TYPE. Ela retorna o Position type
identifier que pode tanto serPOSITION_TYPE_BUY ou
POSITION_TYPE_SELL

long PositionGetInteger(
ENUM_POSITION_PROPERTY property_id // Property identifier
);

Em nosso caso, a utilizamos para determinar qual posição já abrimos. Se for


uma venda, armazenamos um valor VERDADEIRO em Sell_opened e se for
uma compra, armazenamos um valor VERDADEIRO em Buy_opened.
Seremos capazes de utilizar essas duas variáveis posteriormente quando
verificarmos as condições de compra e venda posteriormente em nosso código.

Agora é hora de armazenar o preço de fechamento para a barra que


utilizaremos para a nossa configuração de compra/venda. Lembre-se que

17 de 36 08/12/2015 01:19
'Guia passo a passo para iniciantes para escrever um Expert Advisor n... https://www.mql5.com/pt/articles/100

declaramos uma variável para isso anteriormente

// Copy the bar close price for the previous bar prior to the current b

p_close=mrate[1].close; // bar 1 close price

Tendo feito isso, iremos agora proceder para o próximo passo.

/*
1. Check for a long/Buy Setup : MA-8 increasing upwards,
previous price close above it, ADX > 22, +DI > -DI
*/
//--- Declare bool type variables to hold our Buy Conditions
bool Buy_Condition_1 = (maVal[0]>maVal[1]) && (maVal[1]>maVal[
bool Buy_Condition_2 = (p_close > maVal[1]); // previuos pri
bool Buy_Condition_3 = (adxVal[0]>Adx_Min); // Current ADX
bool Buy_Condition_4 = (plsDI[0]>minDI[0]); // +DI greater

//--- Putting all together


if(Buy_Condition_1 && Buy_Condition_2)
{
if(Buy_Condition_3 && Buy_Condition_4)
{
// any opened Buy position?
if (Buy_opened)
{
Alert("We already have a Buy Position!!!");
return; // Don't open a new Buy Position
}
mrequest.action = TRADE_ACTION_DEAL;
mrequest.price = NormalizeDouble(latest_price.ask,_Digits
mrequest.sl = NormalizeDouble(latest_price.ask - STP*_Point
mrequest.tp = NormalizeDouble(latest_price.ask + TKP*_Point
mrequest.symbol = _Symbol;
mrequest.volume = Lot;
mrequest.magic = EA_Magic;
mrequest.type = ORDER_TYPE_BUY;
mrequest.type_filling = ORDER_FILLING_FOK;
mrequest.deviation=100;
//--- send order
OrderSend(mrequest,mresult);

Agora é hora de iniciar a verificação para uma oportunidade de compra.

Vamos organizar a expressão acima conforme ela representa a estratégia que


nós projetamos anteriormente. Nós estamos declarando uma variável do tipo
bool para cada uma de nossas condições que devem ser atendidas antes que
uma ordem possa ser feito. Uma variável do tipo boll pode apenas conter
VERDADEIRO ou FALSO. Então, a nossa estratégia de compra foi dividida em
quatro condições. Se qualquer uma das condições for atendida ou satisfeita,
então um valor de VERDADEIRO é armazenado em nossa variável do tipo
bool, de modo contrário, um valor de FALSO será armazenado. Vamos olhar
pra elas mais uma vez.

bool Buy_Condition_1 = (maVal[0]>maVal[1]) && (maVal[1]>maVal[2

Aqui nós estamos olhando para os valores MA-8 nas barras 0, 1 e 2. Se o


valor de MA-8 na barra atual for maior do que seu valor na barra Barra 1
anterior e também o valor de MA-8 na barra 1 for maior do que sei valor na
barra 2, significa que o MA-8 está crescendo para cima. Isso satisfaz uma
das nossas condições para uma configuração de compra.

bool Buy_Condition_2 = (p_close > maVal[1]);

Essa expressão está verificando para ver se o preço de fechamento da barra 1


é maior do que o valor de MA-8 no mesmo período (período da barra). Se o
preço for maior, então a nossa segunda condição também foi satisfeita, e nós
podemos verificar as outras condições. No entanto, se as duas condições que

18 de 36 08/12/2015 01:19
'Guia passo a passo para iniciantes para escrever um Expert Advisor n... https://www.mql5.com/pt/articles/100

acabamos de considerar não foram atendidas, então não há necessidade de


verificar outras condições. É por isso que decidimos incluir as próximas
expressões dentro dessas duas condições iniciais (expressões).

bool Buy_Condition_3 = (adxVal[0]>Adx_Min);

Agora queremos verificar se o valor atual de ADX (valor de ADX na barra 0) é


maior do que o valor de ADX máximo declarado nos parâmetros de entrada. Se
essa expressão for verdadeira, isto é, o valor atual de ADX é maior do que o
valor mínimo necessário; nós também queremos nos certificar de que o valor
plusDI é maior do que o valor minusDI. Isso é o que alcançamos na próxima
expressão.

bool Buy_Condition_4 = (plsDI[0]>minDI[0]);

Se todas essas condições forem atendidas, isto é, se eles retornam verdadeiras,


então nós queremos nos certificar de que nós não vamos abrir uma nova
posição de compra se nós já possuímos uma. É hora de verificar o valor da
variável Buy_opened que declaramos anteriormente em nosso código.

// any opened Buy position?


if (Buy_opened)
{
Alert("We already have a Buy Position!!!");
return; // Don't open a new Buy Position
}

Se Buy_opened for verdadeira, nós não queremos abrir outra posição de


compra, então, exibimos um alerta para nos informar e aí retornar de forma que
o nosso CE irá agora esperar pela próxima variação. No entanto, se Buy_opened
é FALSO, então preparamos os nossos registros utilizando a variável do tipo
MqlTradeRequest (mrequest) que declaramos anteriormente para enviar a
nossa ordem.

A ação aqui, que é o tipo de operação de negociação, é


TRADE_ACTION_DEAL porque nós estamos fazendo uma ordem de
negociação para uma execução imediata. Se estamos modificando uma
ordem, então utilizaremosTRADE_ACTION_MODIFY. Para deletar uma
ordem vamos utilizar TRADE_ACTION_REMOVE. Nós utilizamos o
nosso tipo MqlTick latest_price para conseguir o preço preço de venda
mais atual. O preço da ordem stop loss é obtido ao subtrair nosso
StopLoss em pontos do Preço de Venda enquanto o preço da ordem
obter lucros é obtido ao adicionar nosso TakeProfit em pontos ao Preço
de Venda. Você também observará que utilizamos a função
NormalizeDouble para os valores de preço de venda, valores de parar
perdas e obter lucros, é uma boa prática sempre normalizar esses preços
para o número de dígitos do par de moedas de câmbio antes de enviá-los
para o servidor de comercialização.
O symbol é o atual símbolo (_Symbol ou Symbol()). O tipo de ordem é o
tipo de ordem que nós estamos colocando, aqui nós estamos colocando
uma ordem de compra ORDER_TYPE_BUY. Para uma ordem de venda,
será ORDER_TYPE_SELL.
A ordem type_filling é o tipo de execução da ordem;
ORDER_FILLING_FOK significa que o acordo pode ser executado
exclusivamente com um volume específico no preço igual ou melhor do
que o preço especificado pela ordem. Se não houver volume de ordens
suficiente no símbolo ordem, a ordem não será executada.

A função OrderSend() toma dois argumentos, a variável tipo MqlTradeRequest e


a variável tipo MqlTradeResult.

bool OrderSend(
MqlTradeRequest& request // query structure

19 de 36 08/12/2015 01:19
'Guia passo a passo para iniciantes para escrever um Expert Advisor n... https://www.mql5.com/pt/articles/100

MqlTradeResult& result // structure of the answer


);

Como você pode ver, nós utilizamos o nosso tipo variável MqlTradeRequest e a
variável tipo MqlTradeResult ao colocar a nossa ordem utilizando OrderSend.

// get the result code


if(mresult.retcode==10009 || mresult.retcode==10008) //Request
{
Alert("A Buy order has been successfully placed with Ticket
}
else
{
Alert("The Buy order request could not be completed -error:
ResetLastError();
return;
}

Tendo enviado a nossa ordem, utilizaremos a variável tipo MqlTradeResult para


verificar o resultado da nossa ordem. Se a nossa ordem é executada com
sucesso, queremos ser informados, se não, nós queremos saber também. Com
o tipo MqlTradeResult variável ‘mresult’ podemos acessar o código de
retorno da operação e também o número do ticket da ordem se a ordem foi
colocada.

O código de retorno 10009 mostra que a ordem OrderSend foi completada com
sucesso, enquanto que 10008 mostra que a nossa ordem foi colocada. É por
isso que verificamos para qualquer um desses dois códigos de retorno. Se
possuímos qualquer um deles, temos certeza de que a nossa ordem foi
completa ou foi feita.

Para verificar se há uma oportunidade de venda, verificamos o oposto do que


fizemos para oportunidade de compra exceto o nosso ADX que deve ser maior
do que o valor minimo especificado.

/*
2. Check for a Short/Sell Setup : MA-8 decreasing downwards,
previous price close below it, ADX > 22, -DI > +DI
*/
//--- Declare bool type variables to hold our Sell Conditions
bool Sell_Condition_1 = (maVal[0]<maVal[1]) && (maVal[1]<maVal[
bool Sell_Condition_2 = (p_close <maVal[1]);
bool Sell_Condition_3 = (adxVal[0]>Adx_Min);
bool Sell_Condition_4 = (plsDI[0]<minDI[0]);

//--- Putting all together


if(Sell_Condition_1 && Sell_Condition_2)
{
if(Sell_Condition_3 && Sell_Condition_4)
{
// any opened Sell position?
if (Sell_opened)
{
Alert("We already have a Sell position!!!");
return; // Don't open a new Sell Position
}
mrequest.action = TRADE_ACTION_DEAL;
mrequest.price = NormalizeDouble(latest_price.bid,_Digits
mrequest.sl = NormalizeDouble(latest_price.bid + STP*
mrequest.tp = NormalizeDouble(latest_price.bid - TKP*
mrequest.symbol = _Symbol;
mrequest.volume = Lot;
mrequest.magic = EA_Magic;
mrequest.type= ORDER_TYPE_SELL;
mrequest.type_filling = ORDER_FILLING_FOK;
mrequest.deviation=100;
//--- send order
OrderSend(mrequest,mresult);

Assim, como fizemos na seção de compra, estamos declarando uma variável do

20 de 36 08/12/2015 01:19
'Guia passo a passo para iniciantes para escrever um Expert Advisor n... https://www.mql5.com/pt/articles/100

tipo bool para cada uma de nossas condições que devem ser atendidas antes
que uma ordem possa ser colocada. Uma variável do tipo boll pode apenas
conter VERDADEIRO ou FALSO. Então a nossa estratégia de venda foi
quebrada em quatro condições. Se qualquer uma das condições for atendida ou
satisfeita, então um valor de VERDADEIRO é armazenado em nossa variável
do tipo bool, de modo contrário, um valor de FALSO será armazenado. Vamos
olhar para elas uma a uma como nós fizemos para a seção de compra.

bool Sell_Condition_1 = (maVal[0]<maVal[1]) && (maVal[1]<maVal[

Aqui nós estamos olhando para os valores MA-8 nas barras 0, 1 e 2. Se o


valor de MA-8 na barra atual for menor do que seu valor na barra 1 anterior e
também o valor de MA-8 na barra 1 for menor do que seu valor na Barra 2,
significa que o MA-8 está decrescendo para baixo. Isso satisfaz uma das
nossas condições para uma configuração de venda.

bool Sell_Condition_2 = (p_close <maVal[1]);

Essa expressão está verificando para ver se o preço de fechamento da barra 1 é


menor do que o valor de MA-8 no mesmo período (período da barra 1). Se o
preço for menor, então a nossa segunda condição também foi satisfeita, e
podemos verificar as outras condições. No entanto, se as duas condições que
acabamos de considerar não foram atendidas, então não há necessidade de
verificar outras condições. É por isso que decidimos incluir as próximas
expressões dentro dessas duas condições iniciais (expressões).

bool Sell_Condition_3 = (adxVal[0]>Adx_Min);

Agora queremos verificar se o valor atual de ADX (valor de ADX na barra 0) é


maior do que o valor de ADX máximo declarado nos parâmetros de entrada. Se
essa expressão for verdadeira, isto é, o valor atual de ADX é maior do que o
valor mínimo necessário; também queremos nos certificar de que o valor
MinusDI é maior do que o valor plusDI. Isso é o que alcançamos na próxima
expressão.

bool Sell_Condition_4 = (plsDI[0]<minDI[0]);

Se todas essas condições forem atendidas, isto é, se elas retornam verdadeiras,


então nós queremos nos certificar de que não vamos abrir uma nova posição de
compra se nós já possuímos uma. É hora de verificar o valor da variável
Buy_opened que declaramos anteriormente em nosso código.

// any opened Sell position?


if (Sell_opened)
{
Alert("We already have a Sell position!!!");
return; // Don't open a new Sell Position
}

Se Sell_opened for verdadeira, nós não queremos abrir outra posição de venda,
então, exibimos um alerta para nos informar e aí retornar de forma que o nosso
CE irá agora esperar pela próxima variação. No entanto, se Sell_opened for
FALSO, então configuramos a nossa ordem de negociação de venda como
fizemos para a ordem de compra.

A maior diferença aqui é a forma como calculamos o nosso preço stop loss e o
preço take profit. Também já que estamos vendendo, nós vendemos no preço
de cotação; é por isso que utilizamos o nosso tipo MqlTick variável
latest_price para conseguir o preço de cotação mais recente. O outro tipo
aqui, conforme explicado anteriormente, é ORDER_TYPE_SELL.

Também aqui, utilizamos a função NormalizeDouble para o preço de compra,


valor do stop loss (parar perdas) e take profit (obter lucros), é boa prática

21 de 36 08/12/2015 01:19
'Guia passo a passo para iniciantes para escrever um Expert Advisor n... https://www.mql5.com/pt/articles/100

sempre normalizar estes preços ao número de dígitos do par de moedas antes


de enviar para o servidor de negociação.

Assim, como fizemos com a nossa ordem de compra, precisamos também


verificar se a nossa ordem de venda foi bem sucedida ou não. Então utilizamos
a mesma expressão do que na nossa ordem de compra.

if(mresult.retcode==10009 || mresult.retcode==10008) //Request


{
Alert("A Sell order has been successfully placed with Ticke
}
else
{
Alert("The Sell order request could not be completed -error
ResetLastError();
return;
}
}

3. Depurando e testando o nosso consultor especialista


Nesse momento, precisamos testar o nosso CE pra sabermos se a nossa
estratégia funciona ou não. Também é possível que haja um ou dois erros no
código do nosso CE. Isso será descoberto no próximo passo.

3.1 Depurando

Depurar o nosso código nos ajuda a ver como o nosso código se desempenha
linha por linha (se nós configurarmos pontos de parada (breakpoints)) e lá
podemos notar quaisquer erros ou bugs no nosso código e rapidamente fazer as
correções necessárias antes de utilizar nosso código em uma negociação real.

Aqui vamos passar pelo processo passo a passo de depurar o nosso consultor
especialista, primeiramente, configurando breakpoints e em segundo lugar, sem
breakpoints. Para fazer isso, certifique-se de que você não fechou o editor.
Primeiramente, vamos selecionar o gráfico que queremos utilizar para testar o
nosso CE. Na barra do menu do editor, clique em ferramentas e clique em
Opções como mostrado abaixo:

Figura 8. Configurando opções de depuração

Uma vez que a janela de opções aparece, selecione o par de moeda, e o


período/cronograma para utilizar e clique no botão OK:

22 de 36 08/12/2015 01:19
'Guia passo a passo para iniciantes para escrever um Expert Advisor n... https://www.mql5.com/pt/articles/100

Antes de iniciarmos o depurador, vamos configurar os breakpoints.


Breakpoints nos permitem monitorar o comportamento/desempenho do nosso
código em certas localizações ou linhas selecionadas. Ao invés de percorrer todo
o código de uma vez, o depurador para sempre que ver um breakpoint,
esperando a sua próxima ação. Com isso, seremos capazes de analisar o nosso
código e monitorar seu comportamento conforme ele alcança cada conjunto de
breakpoints. Nós também seremos capazes de avaliar os valores de algumas
das nossas variáveis para ver se as coisas de fato estão da forma como foram
visionadas.

Para inserir um breakpoint, vá na linha em seu código na qual você quer inserir
o breakpoint. No lado da mão esquerda, no campo cinza perto da borda da linha
do código, clique duas vezes e você verá um pequeno botão azul redondo com
um quadrado branco dentro dele. Ou alternativamente, posicione o cursor do
seu mouse em qualquer lugar na linha do código onde você quer que o
breakpoint apareça e aperte F9. Para remover o breakpoint, pressione F9
novamente ou clique nele duas vezes.

Figura 10. Configurando um breakpoint

Para o nosso código, nós vamos configurar breakpoints em cinco linhas


diferentes.

23 de 36 08/12/2015 01:19
'Guia passo a passo para iniciantes para escrever um Expert Advisor n... https://www.mql5.com/pt/articles/100

Eu também identificarei eles de 1 a 5 para o bem da explicação.

Para continuar, configure o breakpoint nas sete linhas de código como mostrado
na figura abaixo. O breakpoint 1 é o que nós criamos acima.

Figura 11. Configurando breakpoints adicionais

Uma vez que tenhamos terminado de configurar os nossos breakpoints,


estamos agora prontos para começar a depurar o nosso código.

Para iniciar o depurador, pressione F5 ou clique no botão verde na barra de


ferramentas do MetaEditor.

Figura 12. Iniciando o depurador

A primeira coisa que o editor faz é compilar o código, se houver qualquer erro
no ponto, ele irá exibi-lo e se não houver erro, ele irá lhe avisar que o código foi
compilado com sucesso.

Figura 13. Relatório de compilação

Por favor observe que o fato de que o código compilou com sucesso não
significa que não existem erros no seu código. Dependendo de como o código é
escrito, podem haver erros de execução. Por exemplo, se qualquer uma das
nossas expressões não avalia corretamente devido a qualquer pequeno
descuido, o código irá compilar corretamente porém pode não executar
corretamente. Muita conversa, vamos ver em ação...

24 de 36 08/12/2015 01:19
'Guia passo a passo para iniciantes para escrever um Expert Advisor n... https://www.mql5.com/pt/articles/100

Uma vez que o depurador terminou de compilar o código, ele leva você para o
terminal de comercialização, e anexa o CE ao gráfico que você especificou nas
configurações das opções do MetaEditor. Ao mesmo tempo, ele mostra para
você a seção de parâmetros de entrada do EA. Já que não ainda não estamos
ajustando nada, apenas clique no botão OK.

Figura 14. Parâmetros de entrada do consultor especialista para depuração

Você vai agora ver o CE claramente no canto superior direito do gráfico.

Uma vez que ele inicia o OnTick(), ele irá parar assim que ele chegar no nosso
breakpoint 1.

Figura 15. Depurador para no primeiro breakpoint

Você notará uma seta verde na linha do código. Isso lhe diz que a linha de
código anterior foi executada; estamos agora prontos para executar a linha
atual.

Deixe-me fazer algumas explicações antes de prosseguirmos. Se você olhar a


barra de ferramentas do editor, você observará que os três botões com setas
curvas que estavam anteriormente em cinza agora estão ativados. Isso é
porque estamos agora executando o depurador. Esses botões são utilizados

25 de 36 08/12/2015 01:19
'Guia passo a passo para iniciantes para escrever um Expert Advisor n... https://www.mql5.com/pt/articles/100

para percorrer o nosso código (entrar, passar ou cima ou sair)

Figura 16. Comando entrar

O entrar é utilizado para ir de um passo na execução do programa para o


próximo passo, entrando em qualquer função chamada dentro daquela linha de
código. Clique no botão ou pressione F11 para invocar o comando (utilizaremos
esse comando em nossa depuração passo a passo para o nosso código).

Figura 17. Comando passar por cima

O passar por cima, por outro lado não entra na chamada função dentro
daquela linha de código. clique no botão ou pressione F10 para invocar o
comando

Figura 18. Comando sair

Par executar o passo do programa que é um nível acima, você clica nesse botão
ou pressiona Shift+F11.

Também, na parte inferior do editor, você verá a janela da caixa de


ferramentas. A aba de depuração nessa janela possui os seguintes
cabeçalhos:

Arquivo: Isso exibe o nome do arquivo chamado;


Função: Isso exibe a função presente do arquivo chamado;
Linha: Isso exibe o número da linha de código no arquivo do qual a
função é chamada;
Expressão: Isso é onde você pode digitar o nome de qualquer
expressão/variável que você está interessado em monitorar do nosso
código;
Valor: Isso irá exibir o valor da expressão/variável que nós digitamos na
área de expressão;
Tipo: Isso exibirá o tipo de dados da expressão/variável que foi
monitorada.

De volta ao processo de depuração...

A próxima coisa que queremos fazer é agora inserir as variáveis/expressões do


nosso código que nós estamos interessados em monitorar. Certifique-se de
apenar monitorar variáveis/expressões que realmente importam para o seu
código. Por exemplo, monitoraremos as seguintes:

Old_Time (tempo antigo da barra);


New_Time[0] (tempo atual da barra);
IsNewBar (bandeira que indica a nova barra);
Mybars (total de barras no histórico) – O nosso CE depende disso.

Você pode adicionar outras como os valores ADX, os valores MA-8, etc.

26 de 36 08/12/2015 01:19
'Guia passo a passo para iniciantes para escrever um Expert Advisor n... https://www.mql5.com/pt/articles/100

Para adicionar a expressão/variável, clique duas vezes sob a área de


expressões ou cliquei direito sob a área de expressões e selecione Adicionar
como mostrado na figura acima.

Digite a expressão/variável para monitorar ou observar.

Figura 19. A janela de observação das expressões

Digite todas as variáveis/expressões necessárias...

Figura 20. Adicionando expressões ou variáveis para observar

Se a variável não foi declarada ainda, seu tipo é "identificador desconhecido"


(exceto as variáveis estáticas).

Agora, vamos prosseguir...

Figura 21. Comando entrar em ação

Clique no botão entrar ou pressione F11 e observe o que acontece. Continue


pressionando esse botão ou F11 até que você chegue no breakpoint no 2,
continue até que você chegue no breakpoint no 4 como mostrado abaixo e

27 de 36 08/12/2015 01:19
'Guia passo a passo para iniciantes para escrever um Expert Advisor n... https://www.mql5.com/pt/articles/100

observe a janela de observação de expressões.

Figura 22. Observando as expressões ou variáveis

Figura 23. Observando as expressões ou variáveis

28 de 36 08/12/2015 01:19
'Guia passo a passo para iniciantes para escrever um Expert Advisor n... https://www.mql5.com/pt/articles/100

Figura 24. Observando as expressões ou variáveis

Uma vez que há uma nova variação, ela retornará para a primeira linha do
código na função OnTick(). E todos os valores das nossas variáveis/expressões
agora serão reiniciados porque essa é uma nova variável se qualquer um deles
for declarado como uma variável estática. Em nosso caso possuímos uma
variável estática Old_Time.

Figura 25. Valores das variáveis no evento NewTick

Para revisar o processo novamente, continue pressionando a tecla F11 e


continue monitorando as variáveis na janela de observação de expressões. Você
pode parar o depurador e então remover todos os breakpoints.

Como podemos ver, em modo de depuração ele publica a mensagem "Nós

29 de 36 08/12/2015 01:19
'Guia passo a passo para iniciantes para escrever um Expert Advisor n... https://www.mql5.com/pt/articles/100

temos uma nova barra aqui...".

Figura 26. Expert Advisor imprime a mensagem no modo de depuração

Iniciando o processo de depuração novamente; mas dessa vez sem breakpoints.


Fique observando a cada variação e se qualquer uma das nossas condições de
compra/venda for satisfeita, ele oferecerá uma negociação e já que escrevemos
o nosso código para nos dizer se uma ordem é feita com sucesso ou não,
veremos um alerta.

Figura 27. Expert Advisor oferece uma negociação durante a depuração

Acho que você pode deixar o CE (EA) trabalhando por mais alguns minutos
enquanto você toma um café. Quando você estiver de volta e tiver ganhado
algum dinheiro (brincadeira), então clique no botão PARAR (vermelho) no
MetaEditor para parar a depuração.

Figura 28. Parando o depurador

30 de 36 08/12/2015 01:19
'Guia passo a passo para iniciantes para escrever um Expert Advisor n... https://www.mql5.com/pt/articles/100

O que nós fizemos de fato aqui é ver que o nosso CE apenas procura uma
operação de comercialização na abertura de uma nova barra e que o nosso CE
funciona de fato. Há muito espaço para ajustes ao código do nosso CE.

Preciso deixar claro, nesse ponto, que o terminal de comercialização deve ser
conectado à internet, caso contrário, a depuração não funcionará porque o
terminal não é capaz de comercializar.

3.2 Testando a nossa estratégia de CE

Agora nesse momento queremos testar o nosso CE utilizando o verificador de


estratégia integrado no terminal de comercialização. Para iniciar o testador de
estratégia, pressione CONTROL+R ou clique no menu Visualizar na barra do
menu do terminal e clique em verificador de estratégia como mostrado abaixo.

Figura 26. Iniciando o teste da estratégia

O verificador (verificador de estrategia) é mostrado na parte mais baixa do


terminal. Para você ver todas as configurações do verificador, é preciso
expandir/redimensionar ele. Para fazer isso, mova o ponteiro do seu mouse
para a ponta mostrada pela seta vermelha (como mostrado abaixo):

Figura 27. Janela do verificador de estratégia

O ponteiro do mouse muda para uma seta com ponta dupla, segure o mouse e
arraste a linha para cima. Pare quando você descobrir que você pode ver tudo
na aba de configurações.

31 de 36 08/12/2015 01:19
'Guia passo a passo para iniciantes para escrever um Expert Advisor n... https://www.mql5.com/pt/articles/100

Figura 28. Aba de configurações do verificador de estratégia

1. Selecione o CE que você quer testar.


2. Selecione o par de moedas que você quer utilizar para o teste.
3. Selecione um período/cronograma para utilizar para o teste.
4. Selecione o período personalizado e configure as datas em 5.
5. Configure as datas para o período personalizado a ser utilizado no teste.
6. Execução é normal.
7. Selecione a quantidade depositada em USD a ser utilizada para o teste.
8. Configure a otimização para desabilitar (nós não estamos otimizando
agora, só queremos testar).
9. Clique nesse botão quando você estiver pronto para começar.

Antes de clicarmos no botão iniciar, vamos olhar as outras abas no verificador.

Aba agentes

O processador utilizado pelo verificador para o teste. Dependendo do tipo de


processador do seu computador. O meu é apenas um processador de um (1)
núcleo.

Figura 29. Aba agentes do verificador de estratégia

Uma vez no agente, você verá algo similar a figura abaixo:

Figura 30. A aba agentes do verificador de estratégia durante um teste

Aba jornal

É aonde todos os eventos ocorrendo durante o período de teste são exibidos

32 de 36 08/12/2015 01:19
'Guia passo a passo para iniciantes para escrever um Expert Advisor n... https://www.mql5.com/pt/articles/100

Figura 31. Aba jornal do verificador de estratégia mostrando atividades de comercialização

Aba de entradas

Aqui é onde você pode especificar os parâmetros de entrada para o CE.

Figura 32. Aba entradas do verificador de estratégia

Se nós estamos otimizando o nosso CE, então nós precisaremos configurar os


valores na área circulada.

O Start é o valor que você quer que comece com o verificador.


O Step é a taxa de incremento para o valor que você selecionou, e
O Stop é o valor no qual o verificador irá parar de incrementar o valor
para aquele parâmetro.

No entanto, em nosso caso, não estamos otimizando o nosso CE, então não
precisaremos tocar nisso por enquanto.

Uma vez que tudo estiver pronto, podemos agora voltar a aba de
Configurações e clicar no botão iniciar. Então o verificador começa o seu
trabalho. Tudo que você precisa fazer agora é ir e tomar outra xícara de café,
se quiser, ou, se você for como eu, pode querer monitorar cada evento e,
então, ir para a aba jornal.

Aba gráfico

Uma vez que você começar a ver mensagens sobre ordens sendo enviadas para
a aba jornal, você pode querer voltar-se para uma nova aba chamada gráfico
que acabou de ser criada. Uma vez que você mude para a aba gráfico, verá o
gráfico aumentando ou diminuindo cada vez mais conforme o caso dependendo
do resultado das suas comercializações.

Figura 33. O resultado do gráfico para o teste do consultor especialista

Aba resultados

33 de 36 08/12/2015 01:19
'Guia passo a passo para iniciantes para escrever um Expert Advisor n... https://www.mql5.com/pt/articles/100

Uma vez que o teste estiver completo, você verá outra aba chamada
resultados. Mude para a aba resultados e você verá o resumo do teste que
nós acabamos de fazer.

Figura 34. A aba dos resultados do verificador de estratégia mostrando o resumo dos resultados do teste

Você pode ver o lucro bruto total, lucro líquido, comercializações totais,
comercializações de perda total e muito mais. É muito interessante ver que
temos cerca de out USD 1,450.0 dentro do período que foi selecionado para o
nosso teste. Ao menos temos um poco de lucro.

Deixe-me tornar uma coisa muito clara para você aqui. Você descobrirá que as
configurações para os parâmetros CE que você vê no verificador de estratégia é
diferente das configurações iniciais nos parâmetros de entrada do CE. Eu acabei
de demonstrar para você que é possível mudar qualquer um desses parâmetros
de entrada para conseguir o melhor do seu CE. Ao invés de utilizar um período
de 8 cada para a média móvel e ADX, eu mudei para 10 para a média móvel e
14 para o ADX. Eu também mudei a stop loss de 30 para 35. Por último, mas
não menos importante, decidi utilizar um cronograma de 2 horas. Lembre-se,
esse é o verificador de estratégia.

Se você quer visualizar um relatório completo do teste, então clique direito em


qualquer local da aba resultados, você verá um menu. Desse menu, selecione
‘Salvar e relatar’.

Figura 35. Salvando o resultado do teste

A janela de diálogo salvo aparecerá, digite um nome para o seu relatório (se
quiser, caso contrário deixe o nome padrão) e clique no botão salvar. Todo o
relatório será salvo no formato HTML para você.

Para visualizar o gráfico para o teste que foi realizado, clique em abrir gráfico
e você verá o gráfico exibido.

34 de 36 08/12/2015 01:19
'Guia passo a passo para iniciantes para escrever um Expert Advisor n... https://www.mql5.com/pt/articles/100

Figura 36. O gráfico mostrando o teste

Pronto, escrevemos e testamos o nosso CE com sucesso e agora possuímos um


resultado para trabalhar. Você pode agora voltar para a aba de configurações
de estratégia do verificador de estratégia e testar outros cronogramas/períodos.

Tarefa

Quero que você conduza o teste utilizando diferentes pares de moedas,


diferentes cronogramas, diferentes stop loss, diferentes take profit e veja como
o CE se desempenha. Você pode até tentar a nova média móvel e os valores
ADX. Como eu disse anteriormente, isso é a essência do verificador de
estratégia. Eu também gostaria que você compartilhasse os seus resultados
comigo.

Conclusão
Nesse guia passo a passo nós conseguimos visualizar as etapas básicas
necessárias para escrever um consultor especialista simples baseado em uma
estratégia de comercialização desenvolvida. Nós também vimos como verificar o
nosso CE para erros utilizando o depurador. Também discutimos como testar o
desempenho do nosso CE utilizando o verificador de estratégia. Com isso,
conseguimos ver o poder e robustez da nova linguagem MQL5. O nosso CE
ainda não é perfeito ou completo já que muitos outros ajustes precisam ainda
ser feitos de forma a utilizar ele para comercializações reais.

Ainda há mais a aprender e eu quero que você leia o artigo várias vezes
juntamente com o manual do MQL5, e tente tudo que você aprendeu nesse
artigo, eu posso lhe assegurar que você será um ótimo desenvolvedor de CE em
um futuro próximo.

Feliz programação.

Traduzido do Inglês por MetaQuotes Software Corp.


Artigo original: https://www.mql5.com/en/articles/100

Arquivos anexados | Download ZIP


my_first_ea.mq5 (11.86 KB)

Aviso: Todos os direitos a estes materiais são reservados a MQL5 Ltd. A cópia ou reimpressão destes materiais, no todo

Junte-se a nós — download MetaTrader 5!

35 de 36 08/12/2015 01:19
'Guia passo a passo para iniciantes para escrever um Expert Advisor n... https://www.mql5.com/pt/articles/100

Windows iPhone/iPad Mac OS Android Linux

Estratégia para Linguagem MQL5 | Biblioteca de Código Fonte | Como escrever um Expert Advisor ou um
indicador | Encomendar o Desenvolvimento de um Expert Advisor
Download MetaTrader 5 | Plataforma de Negociação MetaTrader 5 | Loja de Aplicativos | MQL5 Cloud Network
Sobre | História do Site | Termos e Condições | Política de Privacidade | Contatos
Copyright 2000-2015, MQL5 Ltd.

36 de 36 08/12/2015 01:19

You might also like