MetaTrader 5
METATRADER 5 — EXEMPLOS
Exemplos
Indicadores
CRIE O SEU PRÓPRIO ROBÔ DE NEGOCIAÇÃO EM 6 PASSOS!
21 janeiro 2014, 13:53
Especialistas
Testador
Negociação 3 30 774
METAQUOTES SOFTWARE CORP.
Sistemas de Negociação
Estatísticas e análises
Gostou do artigo?
Compartilhe com outras pessoas -
poste um link para eles!
Índices de moedas no
MetaTrader 5
Crie instrumentos sintéticos a
partir de qualquer moeda com
histórico de minutos e ticks
BAIXAR
Neste artigo iremos através de estágios de criação de um módulo de sinais de negociação e você verá como fazer isso sem ter que aprender a OOP
(POO) ou as classes. Mas se desejar, você pode ir um pouco mais além.
Dê duplo clique com o botão direito do mouse na pasta que criamos, selecione "novo arquivo" e crie uma nova classe para nosso módulo de sinais de
negociação.
Nome da classe - o nome da classe. Esse será o módulo para gerenciar sinais no cruzamento de duas médias móveis, então vamos chamá-la
MA_Cross;
Nome de base é a classe na qual nossa classe é derivada. E devemos derivá-la a partir da classe de base CExpertSignal.
Clique "terminar" e um projeto do nosso modelo estará pronto. Está tudo fácil até agora. Nós só precisamos adicionar a declaração #include ao
arquivo resultante para que o compilador saiba onde encontrar a classe de base CExpertSignal:
O resultado:
//+------------------------------------------------------------------+
//| MA_Cross.mqh |
//| 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"
public:
MA_Cross();
~MA_Cross();
};
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
MA_Cross::MA_Cross()
{
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
MA_Cross::~MA_Cross()
{
}
//+------------------------------------------------------------------+
Verifique a classe resultante (deve estar livre de erros de compilação) e clique em F7. Não há erros e podemos prosseguir.
E como pode estar lá? Não adicionamos nenhuma indicação para o Assistente MQL5 entender que a nossa classe poderia ser algo útil. Vamos arrumar
isso. Se você olhar para os módulos do pacote padrão, você verá que cada um deles contém um cabeçalho no início do arquivo. Este é o
identificador do módulo compilado de acordo com certas regras. E as regras são muito simples.
Abra, por exemplo, o código-fonte do módulo de AMA com base nos sinais de negociação (veja a descrição da lógica em Sinais da Média móvel
adaptativa). Execute o Assistente MQL5 escolhendo este módulo. Compare:
O último bloco no identificador refere-se aos parâmetros do módulo, a primeira linha contém o nome do módulo a ser exibido no Assistente MQL5.
Como você pode ver, não há nada de complicado. Assim, o identificador de cada módulo contém as seguintes entradas:
Em seguida, chega a descrição dos parâmetros na forma de parâmetro=list_of_values, em que a seguir é especificado (separados por vírgula):
Agora, sabendo de tudo isso, vamos criar o identificador do nosso módulo de sinais de negociação. Então, escrevemos um módulo para obter sinais
de negociação no cruzamento de duas médias móveis. Precisamos definir pelo menos quatro parâmetros externos:
Você também pode adicionar uma mudança e o tipo de preços para calcular cada uma das médias móveis, mas isso não muda nada
fundamentalmente. Assim, a versão atual é a seguinte:
Salve as alterações e compile. Não deve haver nenhum erro. Execute o Assistente MQL5 para verificar. Veja bem, nosso módulo está agora
disponível para seleção e mostra todos os nossos parâmetros!
Mas como os valores dos parâmetros externos do módulo aparecem nos membros apropriados da nossa classe MA_Cross? É tudo muito simples, você
precisa apenas declarar os métodos públicos de mesmo nome na classe, em outras palavras, adicionar quatro linhas à seção pública:
public:
//--- Constructor of class
MA_Cross();
//--- Destructor of class
~MA_Cross();
//--- Methods for setting
void FastPeriod(int value) { m_period_fast=value; }
void FastMethod(ENUM_MA_METHOD value) { m_method_fast=value; }
void SlowPeriod(int value) { m_period_slow=value; }
void SlowMethod(ENUM_MA_METHOD value) { m_method_slow=value; }
};
Quando você gera um Expert Advisor com base neste módulo usando o Assistente MQL5 e executa-o no gráfico, estes quatro métodos são chamados
automaticamente ao inicializar o Expert Advisor. Então aqui está uma regra simples:
A regra de criação de parâmetro no módulo - para cada parâmetro que declaramos no identificador, devemos criar um membro privado na
classe para armazenar o seu valor e um membro público para definir um valor a ele. O nome do método deve ser compatível com o nome do
parâmetro.
E o último momento é definir valores padrão para os nossos parâmetros que serão utilizados no caso dos métodos de definição de valor não forem
chamados. Cada variável declarada ou membro de classe deve ser inicializado. Esta técnica permite evitar muitos erros difíceis de se encontrar.
Para a inicialização automática, o mais apropriado é o construtor de classe, é sempre o primeiro a ser chamado ao criar um objeto. Para valores
padrão, usaremos aqueles escritos no identificador de módulo.
public:
//--- Constructor of class
MA_Cross(void);
//--- Destructor of class
~MA_Cross(void);
//+------------------------------------------------------------------+
//| Constructor |
//+------------------------------------------------------------------+
MA_Cross::MA_Cross(void) : m_period_fast(13), // Default period of the fast MA is 3
m_method_fast(MODE_SMA), // Default smoothing method of the fast MA
m_period_slow(21), // Default period of the slow MA is 21
m_method_slow(MODE_SMA) // Default smoothing method of the slow MA
{
}
Como você pode ver, na parte pública da classe MA_Cross, adicionamos declaração do método ValidationSettings() e então adicionamos o corpo do
método no formulário a seguir:
Primeiro chega o tipo de retorno, em seguida o nome de classe e, então, o operador de resolução de escopo e tudo isso é seguido pelo nome do
método anteriormente declarado. Não se esqueça que o nome e o tipo de parâmetros devem ser compatíveis na declaração e descrição do método
de classe. Entretanto, o compilador lhe avisará de tal erro.
Observe que primeiro o método de classe de base é chamado, e, em seguida, os parâmetros de entrada são verificados.
Se você não adicionar essa linha, o Expert Advisor gerado não será capaz de inicializar o módulo de sinais de negociação.
public:
//--- Constructor of class
MA_Cross(void);
//--- Destructor of class
~MA_Cross(void);
//--- Methods for setting
void FastPeriod(int value) { m_period_fast=value; }
void FastMethod(ENUM_MA_METHOD value) { m_method_fast=value; }
void SlowPeriod(int value) { m_period_slow=value; }
void SlowMethod(ENUM_MA_METHOD value) { m_method_slow=value; }
//--- Checking correctness of input data
bool ValidationSettings();
//--- Creating indicators and timeseries for the module of signals
bool InitIndicators(CIndicators *indicators);
};
...
//+------------------------------------------------------------------+
//| Creates indicators |
//| Input: a pointer to a collection of indicators |
//| Output: true if successful, otherwise false |
//+------------------------------------------------------------------+
bool MA_Сross::InitIndicators(CIndicators* indicators)
{
//--- Standard check of the collection of indicators for NULL
if(indicators==NULL) return(false);
//--- Initializing indicators and timeseries in additional filters
if(!CExpertSignal::InitIndicators(indicators)) return(false);
//--- Creating our MA indicators
... Some code here
//--- Reached this part, so the function was successful, return true
return(true);
}
Então, não há nada de complicado, nós declaramos o método e, em seguida, basta criar o corpo do método, como fizemos para o método
ValidationSettings(). Além de tudo, não esqueça de inserir o nome de classe e do operador: na definição da função. Temos um projeto no qual
podemos inserir um código para criar médias móveis. Vamos fazer isso adequadamente - para cada indicador, criamos uma função separada na
classe, que retorne verdadeira, se bem sucedida. A função pode ter qualquer nome, mas deixe-a refletir sua finalidade, então, vamos chamar as
funções CreateFastMA() e CreateSlowMA().
protected:
//--- Creating MA indicators
bool CreateFastMA(CIndicators *indicators);
bool CreateSlowMA(CIndicators *indicators);
};
//+------------------------------------------------------------------+
//| Creates indicators |
//| Input: a pointer to a collection of indicators |
//| Output: true if successful, otherwise false |
//+------------------------------------------------------------------+
bool MA_Cross::InitIndicators(CIndicators *indicators)
{
//--- Standard check of the collection of indicators for NULL
if(indicators==NULL) return(false);
//--- Initializing indicators and timeseries in additional filters
if(!CExpertSignal::InitIndicators(indicators)) return(false);
//--- Creating our MA indicators
if(!CreateFastMA(indicators)) return(false);
if(!CreateSlowMA(indicators)) return(false);
//--- Reached this part, so the function was successful, return true
return(true);
}
//+------------------------------------------------------------------+
//| Creates the "Fast MA" indicator |
//+------------------------------------------------------------------+
bool MA_Cross::CreateFastMA(CIndicators *indicators)
{
... Some code
//--- Reached this part, so the function was successful, return true
return(true);
}
//+------------------------------------------------------------------+
//| Creates the "Slow MA" indicator |
//+------------------------------------------------------------------+
bool MA_Cross::CreateSlowMA(CIndicators *indicators)
{
... Some code
//--- Reached this part, so the function was successful, return true
return(true);
}
Isso é tudo, só precisamos escrever o código que gera os indicadores MA e que de alguma forma integra os identificadores destes indicadores no
módulo de negociação, para que o módulo possa usar os valores os valores destes indicadores. Por isso que um ponteiro à uma variável de tipo
CIndicators é transmitida como um parâmetro. O seguinte é escrito em Documentação sobre o assunto:
CIndicators é uma classe para a coleta de instâncias de classes de séries temporais e indicadores técnicos. A classe CIndicators fornece
criação de instâncias de classes de indicadores técnicos, seu armazenamento e gerenciamento (sincronização, identificador e
gerenciamento de memória de dados).
Isto significa que devemos criar nossos indicadores e colocá-los nesta coleção. Uma vez que apenas os indicadores da forma CIndicator e suas filhas
podem ser armazenados na coleção, devemos usar este fato. Usaremos CiCustom, que é a filha acima mencionada. Para cada média móvel
anunciamos um objeto de tipo CiCustom na parte privada da classe:
Claro, você pode criar sua própria classe de indicador, que será derivada do CIndicator, e implementar todos os métodos necessários para usar com
o Assistente MQL5. Mas no caso de desejarmos mostrar como você pode usar qualquer indicador personalizado no módulo de sinais de negociação
utilizando CiCustom.
Aqui está como parece no código:
//+------------------------------------------------------------------+
//| Creates the "Fast MA" indicator |
//+------------------------------------------------------------------+
bool MA_Cross::CreateFastMA(CIndicators *indicators)
{
//--- Checking the pointer
if(indicators==NULL) return(false);
//--- Adding an object to the collection
if(!indicators.Add(GetPointer(m_fast_ma)))
{
printf(__FUNCTION__+": Error adding an object of the fast MA");
return(false);
}
//--- Setting parameters of the fast MA
MqlParam parameters[4];
//---
parameters[0].type=TYPE_STRING;
parameters[0].string_value="Examples\\Custom Moving Average.ex5";
parameters[1].type=TYPE_INT;
parameters[1].integer_value=m_period_fast; // Period
parameters[2].type=TYPE_INT;
parameters[2].integer_value=0; // Shift
parameters[3].type=TYPE_INT;
parameters[3].integer_value=m_method_fast; // Averaging method
//--- Object initialization
if(!m_fast_ma.Create(m_symbol.Name(),m_period,IND_CUSTOM,4,parameters))
{
printf(__FUNCTION__+": Error initializing the object of the fast MA");
return(false);
}
//--- Number of buffers
if(!m_fast_ma.NumBuffers(1)) return(false);
//--- Reached this part, so the function was successful, return true
return(true);
}
No método CreateFastMA(), primeiro verifique o ponteiro da coleção de indicadores e então adicione um ponteiro do MA rápido m_fast_ma à esta
coleção. Em seguida, declare a estrutura MqlParam, que é especialmente criada para armazenar parâmetros dos indicadores personalizados, e a
preencha com valores.
Usamos Média móvel personalizada do pacote de entrega do terminal padrão como indicador MA personalizado. O nome do indicador deve ser
indicado relativamente à pasta data_folder/MQL5/Indicators/. Devido à Custom Moving Average.mq5 do pacote padrão estar localizado em
data_folder/MQL5/Indicators/Examples/, especificamos seu caminho incluindo a pasta Examples:
Se você olhar o código para este indicador, você consegue ver todos os dados necessários:
Após preencher a estrutura, o indicador é inicializado pelo método Create() de todos os parâmetros necessários: nome do símbolo e o período de
tempo no qual é calculado, o tipo do indicador a partir da enumeração ENUM INDICATOR, o número de parâmetros de indicador e a estrutura
MqlParam com valores de parâmetro. E o último passo é especificar o número de buffers de indicador utilizando o método NumBuffers().
O método CreateSlowMA() para criar a média móvel lenta é simples. Ao utilizar indicadores personalizados no módulo, não se esqueça que o Expert
Advisor gerado pelo Assistente MQL5 também será executado no testador. Assim, no início do nosso arquivo, adicionamos #property tester_indicator
que comunica ao testador a localização de indicadores necessários:
Se usarmos vários indicadores diferentes, devemos adicionar esta linha para cada um deles. Então, adicionamos os indicadores. Para maior
comodidade, vamos fornecer dois métodos de receber valores MA:
Como você pode ver, os métodos são muito simples, eles usaram o método GetData() da classe pai, que retorna um valor a partir do buffer de
indicador especificado na posição especificada.
Se você precisar de classes para trabalhar com indicadores clássicos do pacote padrão, elas estão disponíveis na seção Classes para trabalhar com
indicadores. Estamos prontos para prosseguir para o estágio final.
Se a função retorna um valor nulo, significa que não há um sinal de negociação. Se há condições para o sinal, então você pode estimar a força do
sinal e retornar qualquer valor que seja inferior a 100. A avaliação da força do sinal permite que você construa de forma flexível sistemas de
negociação com base em vários módulos e modelos de mercado. Leia mais sobre isso no Assistente MQL5: Nova Versão.
Uma vez que estamos escrevendo um simples módulo de sinais de negociação, podemos concordar que os sinais de compra e venda são avaliados
igualmente (100). Vamos adicionar métodos necessários na declaração de classe.
...
bool InitIndicators(CIndicators *indicators);
//--- Access to data of the indicators
double FastMA(const int index) const { return(m_fast_ma.GetData(0,index)); }
double SlowMA(const int index) const { return(m_slow_ma.GetData(0,index)); }
//--- Checking buy and sell conditions
virtual int LongCondition();
virtual int ShortCondition();
Além disso, vamos criar a descrição de funções. É assim que o sinal de compra é verificado (é tudo igual com o sinal de venda):
//+------------------------------------------------------------------+
//| Returns the strength of the buy signal |
//+------------------------------------------------------------------+
int MA_Cross::LongCondition()
{
int signal=0;
//--- For operation with ticks idx=0, for operation with formed bars idx=1
int idx=StartIndex();
//--- Values of MAs at the last formed bar
double last_fast_value=FastMA(idx);
double last_slow_value=SlowMA(idx);
//--- Values of MAs at the last but one formed bar
double prev_fast_value=FastMA(idx+1);
double prev_slow_value=SlowMA(idx+1);
//---If the fast MA crossed the slow MA from bottom upwards on the last two closed bars
if((last_fast_value>last_slow_value) && (prev_fast_value<prev_slow_value))
{
signal=100; // There is a signal to buy
}
//--- Return the signal value
return(signal);
}
Observe que declaramos a variável idx, na qual o valor retornado pela função StartIndex() da classe pai CExpertBase está determinado. A função
StartIndex() retorna 0, se o Expert Advisor estiver determinado para trabalhar em todos ticks, nesse caso a análise começa com a barra atual. Se o
Expert Advisor estiver determinado para trabalhar em preços abertos, StartIndex() retorna 1 e a análise começa com a última barra formada.
Por padrão, o StartIndex() retorna 1, o que significa que o Expert Advisor gerado pelo Assistente MQL5 só será executado na abertura de uma
nova barra e ignorará ticks recebidos durante a formação da barra atual.
Como ativar este modo e como ele pode ser utilizado será descrito mais tarde no toque final.
O módulo está pronto para uso, então vamos criar um robô de negociação no Assistente MQL5 com base neste módulo.
Todos os outros parâmetros também foram adicionados pelo Assistente MQL5 ao gerar o EA com base no módulo de gerenciamento de dinheiro
selecionado e módulo de manutenção de posição (Trailing Stop). Assim, nós só tivemos que escrever um módulo de sinais de negociação e
recebemos uma solução pronta. Esta é a principal vantagem de usar o Assistente MQL5!
Agora vamos testar o robô de negociação no Testador de estratégia do MetaTrader 5. Vamos tentar executar uma otimização rápida de parâmetros-
chave.
Nessas configurações de parâmetros de entrada, mais de meio milhão de transmissões são necessárias para otimização completa. Portanto,
escolhemos otimização rápida (algoritmo genético) e utilizamos adicionalmente MQL5 Cloud Network para acelerar a otimização. A otimização foi
feita em 10 minutos e temos os resultados.
Como você pode ver, a criação de um robô de negociação no MQL5 e otimização de parâmetros de entrada levaram muito menos tempo do que seria
necessário para escrever a lógica de serviço de gerenciamento de posição, depurar e procurar pelos melhores algoritmos.
Toque final
Você pode pular este item ou voltar a ele mais tarde, quando você estiver completamente confortável com a técnica de escrever um módulo de
sinais de negociação.
Se você abrir o código-fonte do Expert Advisor gerado pelo Assistente MQL5, você vai encontrar a variável global Expert_EveryTick com o valor
falso. Baseado nessa variável, a função StartIndex() retorna o seu valor. Ela comunica ao Expert Advisor o modo que ele deve executar.
//+------------------------------------------------------------------+
//| TestMA_Cross.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"
//+------------------------------------------------------------------+
//| Include |
//+------------------------------------------------------------------+
#include <Expert\Expert.mqh>
//--- available signals
#include <Expert\MySignals\MA_Cross.mqh>
//--- available trailing
#include <Expert\Trailing\TrailingNone.mqh>
//--- available money management
#include <Expert\Money\MoneyFixedLot.mqh>
//+------------------------------------------------------------------+
//| Inputs |
//+------------------------------------------------------------------+
//--- inputs for expert
input string Expert_Title ="TestMA_Cross"; // Document name
ulong Expert_MagicNumber =22655; // Expert Advisor ID
bool Expert_EveryTick =false; // Work of the EA inside the bar
//--- inputs for main signal
input int Signal_ThresholdOpen =10; // Signal threshold value to open [0...100]
input int Signal_ThresholdClose =10; // Signal threshold value to close [0...100]
Se você definir Expert_EveryTick como verdadeiro e compilar o código, o robô de negociação analisará cada tick de entrada e, desta forma, tomar
decisões sobre os valores da barra incompleta atualmente. Faça isso somente se você entender como funciona. Nem todos os sistemas de
negociação são projetados para trabalhar no interior da barra.
Você pode também adicionar uma entrada no teclado para o parâmetro Expert_EveryTick e então você terá um novo parâmetro de entrada do
Expert Advisor, que você pode estabelecer na inicialização do EA em um gráfico ou no testador:
1. Crie uma nova classe utilizando o Assistente MQL5 em um arquivo separado MQL5/Include/MySignals/. Nosso módulo de sinais de negociação
será armazenado lá.
2. Crie um identificador de módulo que descreve os parâmetros, valores padrão e de tipo.
3. Declare parâmetros de módulo na classe e adicione métodos para inicialização no construtor.
4. Verifique os parâmetros de entrada e não esqueça de chamar ValidationSettings() da classe de base CExpertSignal.
5. Crie indicador-objeto e adicione um método de inicialização predeterminado InitIndicators().
6. Identifique condições de sinais de negociação nos métodos LongCondition() e ShortCondition().
Cada passo é simples e requer pouca habilidade na programação MQL5. Você só precisa escrever o seu módulo uma vez, seguindo as instruções e a
verificação posterior de qualquer ideia de negociação não levará mais de uma hora, sem horas exaustivas de codificação e depuração.
Do simples ao complexo
Lembre-se que a estratégia de negociação implementada pelo seu robô de negociação criado utilizando o Assistente MQL5, é tão complexa quanto o
módulo de sinais de negociação que ele utiliza. Mas antes de começar a construir um sistema de negociação complexo baseado em um conjunto de
regras para a entrada e saída, divida-o em vários sistemas simples e verifique cada um separadamente.
Baseado em módulos simples, você pode criar estratégias de negociação complexas, utilizando os módulos prontos para uso de sinais de negociação,
mas isso é assunto para um outro artigo!
Aviso: Todos os direitos a estes materiais são reservados a MQL5 Ltd. A cópia ou reimpressão destes materiais, no todo ou em parte é proibida.
Se eu executar em um par de forex, a mesma otimização parece ser concluída (não esperei concluir pq demora muito no agente local).
O erro que aparece no diário do testador, neste caso de Vale5, tem alguma coisa a ver com OnInit. Alguém aí detectou o mesmo
problema? Se sim chegou a alguma solução e/ou conclusão?
fspyna:
Se eu mandar rodar este exemplo no strategy tester do mt5, e escolher o ativo como pex. Vale5, algoritmo genético, d1, ohlc 1
minuto, max balance, vai dar erro!
Se eu executar em um par de forex, a mesma otimização parece ser concluída (não esperei concluir pq demora muito no
agente local).
O erro que aparece no diário do testador, neste caso de Vale5, tem alguma coisa a ver com OnInit. Alguém aí detectou o
mesmo problema? Se sim chegou a alguma solução e/ou conclusão?
Olá, por favor coloque informações adicionais, como log de erros ou screenshots, pra podermos tentar analisar melhor o problema.
Uma descrição simples como a que você fez acima não ajuda muito na identificação do problema.
Abraços,
Malacarne
Abraço
Carlos F.
Visualizar uma estratégia no Tester do MetaTrader 5 Sistema de negociação simples com o uso de indicadores
semáforo
Todos conhecemos o ditado "é melhor ver uma vez do que
ouvir cem vezes". Você pode ler diversos livros sobre Paris Se examinarmos por completo qualquer sistema de negócio
ou Veneza, mas com base nas imagens mentais, você não complexo, veremos que é baseado em um conjunto simples de
teria os mesmos sentimentos do que se estivesse sinais de negócio. Consequentemente, não há necessidade
caminhando à noite por essas cidades fabulosas. A para que novos desenvolvedores comecem imediatamente a
vantagem da visualização pode ser facilmente projetada escrever algoritmos complexos. Este artigo fornece um
em qualquer aspecto de nossas vidas, incluindo trabalho exemplo de um sistema de negócio que utiliza indicadores
no mercado, por exemplo, a análise de preço em gráficos semáforo para realizar negócios.
utilizando indicadores e, é evidente, a visualização de
teste de estratégia. Este artigo contém descrições de
Abordagem orientada a objetos para construção de
todos os recursos de visualização do Strategy Tester do
painéis de múltiplos períodos de tempo e múltiplas
MetaTrader 5.
moedas
Algoritmos que empregam limite móvel para fazer Este artigo descreve como a programação orientada a objetos
dinheiro pode ser usada para criar painéis de múltiplos períodos de
tempo múltiplas moedas para o MetaTrader 5. O principal
O objetivo deste artigo é estudar a rentabilidade dos objetivo é construir um painel universal, que pode ser
algoritmos com diferentes entradas em negócios e saídas utilizado para exibição de diversos tipos diferentes de dados,
usando um limite móvel. Os tipos de entrada a serem tal como preços, variação de preços, valores de indicador ou
usados são entradas aleatórias e entradas reversas. As condições personalizadas de compra/venda, sem a necessidade
ordens de parada a serem usadas são limite móvel e de modificar o código do painel em si.
tomada móvel. O artigo demonstra os algoritmos para
fazer dinheiro com uma rentabilidade de cerca de 30% por
ano.