
Estudo de técnicas de análise de velas (parte III): Biblioteca para trabalhar com os padrões
Índice
- Introdução
- Estrutura da biblioteca
- Desenvolvimento da biblioteca
- CandleType. Tipo da vela selecionada
- PatternType. Tipo do padrão
- Found. O número de padrões encontrados do tipo especificado
- Coincidence. Com que frequência o tipo de padrão especificado é encontrado
- Probability. A probabilidade de movimento após a ocorrência do padrão
- Efficiency. O coeficiente de eficiência do padrão
- Uso prático
- CandleDetector. Indicador de busca de velas
- PatternDetector. Indicador de busca do padrão
- PatternExpert. Expert Advisor para negociação de padrões
- Conclusões
Introdução
Nós já consideramos as técnicas de análise de velas: a existência dos padrões sob as condições atuais de mercado foi verificada no primeiro artigo, e a tentativa de expansão dessas pesquisas foi feita no segundo artigo. Usando os critérios de avaliação de desenvolvimento, nós estudamos, testamos e comparamos uma ampla gama de possíveis combinações de padrões. Para este propósito, nós desenvolvemos uma aplicação personalizada Pattern Analyzer com um grande conjunto de configurações para o estudo de padrões. No entanto, a teoria e pesquisa só podem fornecer informações e conclusões. A continuação lógica da tarefa é usá-los em condições reais.
Portanto, o objetivo deste artigo é criar uma ferramenta personalizada, que permita aos usuários receber e usar todo array de informações sobre os padrões discutidos anteriormente. Nós vamos criar uma biblioteca que você poderá usar em seus próprios indicadores, painéis de negociação, Expert Advisors, etc.
Estrutura da biblioteca
Antes de procedermos para a criação da estrutura da biblioteca, classes e os arquivos de inclusão, vamos definir os dados que nós usaremos. Ou seja, nós precisamos separar os métodos responsáveis pelos dados de entrada e os métodos que fornecerão os resultados. A estrutura geral da biblioteca será baseada na solução visual desenvolvida nos artigos anteriores — o Pattern Analyzer.
Vamos começar com os dados de entrada do aplicativo que podem influenciar o resultado ao testar os padrões.
Fig.1 Parâmetros de entrada na guia Setting.
Bloco 1. Este bloco apresenta a lista dos tipos de velas que consistem os padrões existentes e gerados. Cada um dos tipos tem suas configurações, que você pode visualizar clicando no ícone da engrenagem no canto superior direito da página de visualização da vela. Os tipos de vela de 1-5 possuem apenas uma configuração, enquanto o martelo (Hammer) possui duas delas.
Bloco 2 Coeficientes de peso. Existem três parâmetros К1, К2, К3 que afetam o resultado da avaliação da eficiência do padrão.
Bloco 3 Valor do limiar da tendência em pontos.
Bloco 4 Velas usadas ao testar os padrões gerados. Aqui, nós precisaremos dos números da sequência ou dos índices da vela. Usando esses dados, nós poderemos obter as informações sobre qualquer padrão de qualquer tamanho, até três velas.
Bloco 5 Número de velas no padrão. Esta configuração é aplicável apenas para os padrões personalizados.
Em seguida, nós vamos ver a guia Analyze e os parâmetros de entrada contidos nela.
Fig.2 Parâmetros de entrada na guia Analyze.
Bloco 6 este bloco contém as configurações do período gráfico atual e o intervalo da amostra de dados usada para a análise do padrão.
Bloco 7 Nomes dos padrões existentes. Ele também possui uma entrada que não pode ser editada a partir da aplicação, mas é necessária para acessar um padrão e obter as informações dele.
Vamos enumerar aqui os dados que podem ser obtidos a partir da análise de padrões. Isso é necessário para a criação de uma estrutura de métodos correta em uma classe.
- Padrões encontrados. O número de padrões encontrados do tipo especificado.
- Ocorrência. A porcentagem do número de padrões encontrados no intervalo da amostra total.
- Probabilidade de um movimento altista ou baixista.
- Taxa de eficiência durante o movimento altista e baixista para este padrão de vela.
Desenvolvimento da biblioteca
Depois de determinar os pontos básicos, vamos proceder para a criação da biblioteca. Vamos começar com a criação de um arquivo com as enumerações necessárias Enums.mqh
//+------------------------------------------------------------------+ //| Enums.mqh | //| Copyright 2018, MetaQuotes Software Corp. | //| https://www.mql5.com/en/users/alex2356 | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Tipo da vela | //+------------------------------------------------------------------+ enum TYPE_CANDLESTICK { CAND_NONE, // Indefinido CAND_MARIBOZU, // Marubozu CAND_DOJI, // Doji CAND_SPIN_TOP, // Spinning Top CAND_HAMMER, // Martelo CAND_INVERT_HAMMER, // Martelo Invertido CAND_LONG, // Vela de Alta CAND_SHORT // Vela de Baixa }; //+------------------------------------------------------------------+ //| Tipo do padrão | //+------------------------------------------------------------------+ enum TYPE_PATTERN { NONE, HUMMER, INVERT_HUMMER, HANDING_MAN, SHOOTING_STAR, ENGULFING_BULL, ENGULFING_BEAR, HARAMI_BULL, HARAMI_BEAR, HARAMI_CROSS_BULL, HARAMI_CROSS_BEAR, DOJI_STAR_BULL, DOJI_STAR_BEAR, PIERCING_LINE, DARK_CLOUD_COVER }; //+------------------------------------------------------------------+ //| Tipo da tendência | //+------------------------------------------------------------------+ enum TYPE_TREND { UPPER, //Tendência de alta DOWN, //Tendência de baixa FLAT //Lateralizado }; //+------------------------------------------------------------------+
Aqui, nós determinaremos a lista dos tipos de vela simples usados, os tipos de padrões existentes e o tipo da tendência - os dados são necessários para identificar os padrões existentes no gráfico.
Depois disso, nós vamos criar o arquivo Pattern.mqh. A classe CPattern será criada nela e, em sua seção privada, nós declararemos as variáveis para os parâmetros mencionados na seção anterior. Nós também precisamos incluir o arquivo com as enumerações.
//+------------------------------------------------------------------+ //| Pattern.mqh | //| Copyright 2018, MetaQuotes Software Corp. | //| https://www.mql5.com/en/users/alex2356 | //+------------------------------------------------------------------+ #include "Enums.mqh" //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ class CPattern { private: //--- Pesos double m_k1; double m_k2; double m_k3; //--- Valor do limiar da tendência em pontos int m_threshold_value; //--- Configuração do coeficiente da vela de alta double m_long_coef; //--- Configuração do coeficiente da vela de baixa double m_short_coef; //--- Configuração do coeficiente da vela Doji double m_doji_coef; //--- Configuração do coeficiente da vela Marubozu double m_maribozu_coef; //--- Configuração do coeficiente da vela Spinning Top double m_spin_coef; //--- Configuração do coeficiente da vela Martelo double m_hummer_coef1; double m_hummer_coef2; //--- Faixa de amostragem para os padrões predefinidos int m_range_total; //--- Período para determinar a tendência int m_trend_period; //--- Padrões encontrados int m_found; //--- Ocorrência dos padrões double m_coincidence; //--- Probabilidade do movimento de alta ou baixa double m_probability1; double m_probability2; //--- Eficiência double m_efficiency1; double m_efficiency2; //--- Padrões simples de velas struct CANDLE_STRUCTURE { double m_open; double m_high; double m_low; double m_close; // OHLC TYPE_TREND m_trend; // Tendência bool m_bull; // Vela de Alta double m_bodysize; // Tamanho do corpo TYPE_CANDLESTICK m_type; // Tipo da vela }; //--- Propriedades da avaliação da eficiência do padrão struct RATING_SET { int m_a_uptrend; int m_b_uptrend; int m_c_uptrend; int m_a_dntrend; int m_b_dntrend; int m_c_dntrend; };
Como pode ser visto no código acima, duas estruturas foram adicionadas ao nosso programa. A primeira estrutura, CANDLE_STRUCTURE, é necessária para determinar o tipo de vela no gráfico. Observe que os dois tipos de enumerações da tendência são usados nessa estrutura: TYPE_TREND e TYPE_CANDLESTICK do arquivo Enums.mqh que foi considerado anteriormente e criado para essa estrutura. A segunda estrutura, RATING_SET, armazena os registros das estimativas do movimento de preço após o surgimento do padrão. Por favor, leia o primeiro artigo para mais detalhes.
Agora, considere a parte da seção public da classe, que descreve os métodos para customizar e recuperar os valores dos parâmetros de entrada, que são descritos na seção estrutura da biblioteca.
public: CPattern(void); ~CPattern(void); //--- Define e retorna os coeficientes de peso void K1(const double k1) { m_k1=k1; } double K1(void) { return(m_k1); } void K2(const double k2) { m_k2=k2; } double K2(void) { return(m_k2); } void K3(const double k3) { m_k3=k3; } double K3(void) { return(m_k3); } //--- Define e retorna o valor da tendência do limiar void Threshold(const int threshold) { m_threshold_value=threshold; } int Threshold(void) { return(m_threshold_value); } //--- Define e retorna o coeficiente de configuração da vela de alta void Long_coef(const double long_coef) { m_long_coef=long_coef; } double Long_coef(void) { return(m_long_coef); } //--- Define e retorna o coeficiente de configuração da vela de baixa void Short_coef(const double short_coef) { m_short_coef=short_coef; } double Short_coef(void) { return(m_short_coef); } //--- Define e retorna o coeficiente de configuração da vela doji void Doji_coef(const double doji_coef) { m_doji_coef=doji_coef; } double Doji_coef(void) { return(m_doji_coef); } //--- Define e retorna o coeficiente de configuração da vela marubozu void Maribozu_coef(const double maribozu_coef) { m_maribozu_coef=maribozu_coef; } double Maribozu_coef(void) { return(m_maribozu_coef); } //--- Define e retorna o coeficiente de configuração da vela Spinning Top void Spin_coef(const double spin_coef) { m_spin_coef=spin_coef; } double Spin_coef(void) { return(m_spin_coef); } //--- Define e retorna o coeficiente de configuração da vela Martelo void Hummer_coef1(const double hummer_coef1) { m_hummer_coef1=hummer_coef1; } void Hummer_coef2(const double hummer_coef2) { m_hummer_coef2=hummer_coef2; } double Hummer_coef1(void) { return(m_hummer_coef1); } double Hummer_coef2(void) { return(m_hummer_coef2); } //--- Define e retorna a faixa de amostragem para os parâmetros predefinidos void Range(const int range_total) { m_range_total=range_total; } int Range(void) { return(m_range_total); } //--- Define e retorna o número de velas para o cálculo da tendência void TrendPeriod(const int period) { m_trend_period=period; } int TrendPeriod(void) { return(m_trend_period); }
No construtor de classe, nós descreveremos os parâmetros padrão, conforme especificado na aplicação, nas guias Settings.
//+------------------------------------------------------------------+ //| Construtor | //+------------------------------------------------------------------+ CPattern::CPattern(void) : m_k1(1), m_k2(0.5), m_k3(0.25), m_threshold_value(100), m_long_coef(1.3), m_short_coef(0.5), m_doji_coef(0.04), m_maribozu_coef(0.01), m_spin_coef(1), m_hummer_coef1(0.1), m_hummer_coef2(2), m_range_total(8000), m_trend_period(5) { }
A segunda parte da seção public da classe CPattern fornece uma descrição dos métodos para processar os parâmetros de entrada declarados e para obter as propriedades e características dos padrões.
Vamos ver cada um deles em detalhes. É importante entender o algoritmo operacional para poder usá-los de maneira eficiente na criação de indicadores, painéis de negociação ou Expert Advisors.
CandleType
TYPE_CANDLESTICK CandleType(const string symbol,const ENUM_TIMEFRAMES timeframe,const int shift);
Parâmetros
- symbol — Símbolo selecionado para a busca
- timeframe — Período gráfico selecionado
- shift — Índice da vela selecionada para iniciar a análise.
Valor de Retorno
O tipo da vela selecionada da enumeração TYPE_CANDLESTICK.
//+------------------------------------------------------------------+ //| Tipo da vela | //+------------------------------------------------------------------+ enum TYPE_CANDLESTICK { CAND_NONE, // Indefinido CAND_MARIBOZU, // Marubozu CAND_DOJI, // Doji CAND_SPIN_TOP, // Spinning Top CAND_HAMMER, // Martelo CAND_INVERT_HAMMER, // Martelo Invertido CAND_LONG, // Vela de Alta CAND_SHORT // Vela de Baixa };
Implementação
//+------------------------------------------------------------------+ //| Retorna o tipo da vela selecionada | //+------------------------------------------------------------------+ TYPE_CANDLESTICK CPattern::CandleType(const string symbol,const ENUM_TIMEFRAMES timeframe,const int shift) { CANDLE_STRUCTURE res; if(GetCandleType(symbol,timeframe,res,shift)) return(res.m_type); return(CAND_NONE); } //+------------------------------------------------------------------+ //| Reconhecimento do tipo da vela | //+------------------------------------------------------------------+ bool CPattern::GetCandleType(const string symbol,const ENUM_TIMEFRAMES timeframe,CANDLE_STRUCTURE &res,const int shift) { MqlRates rt[]; int aver_period=m_trend_period; double aver=0; SymbolSelect(symbol,true); int copied=CopyRates(symbol,timeframe,shift,aver_period+1,rt); //--- Obtém os detalhes da vela anterior if(copied<aver_period) return(false); //--- res.m_open=rt[aver_period].open; res.m_high=rt[aver_period].high; res.m_low=rt[aver_period].low; res.m_close=rt[aver_period].close; //--- Determina a direção da tendência for(int i=0;i<aver_period;i++) aver+=rt[i].close; aver/=aver_period; if(aver<res.m_close) res.m_trend=UPPER; if(aver>res.m_close) res.m_trend=DOWN; if(aver==res.m_close) res.m_trend=FLAT; //--- Determina se é uma vela de alta ou de baixa res.m_bull=res.m_open<res.m_close; //--- Obtém o tamanho absoluto do corpo da vela res.m_bodysize=MathAbs(res.m_open-res.m_close); //--- Obtém os tamanhos das sombras double shade_low=res.m_close-res.m_low; double shade_high=res.m_high-res.m_open; if(res.m_bull) { shade_low=res.m_open-res.m_low; shade_high=res.m_high-res.m_close; } double HL=res.m_high-res.m_low; //--- Calcula o tamanho médio do corpo das velas anteriores double sum=0; for(int i=1; i<=aver_period; i++) sum=sum+MathAbs(rt[i].open-rt[i].close); sum=sum/aver_period; //--- Determina o tipo de vela res.m_type=CAND_NONE; //--- alta if(res.m_bodysize>sum*m_long_coef) res.m_type=CAND_LONG; //--- baixa if(res.m_bodysize<sum*m_short_coef) res.m_type=CAND_SHORT; //--- doji if(res.m_bodysize<HL*m_doji_coef) res.m_type=CAND_DOJI; //--- marubozu if((shade_low<res.m_bodysize*m_maribozu_coef || shade_high<res.m_bodysize*m_maribozu_coef) && res.m_bodysize>0) res.m_type=CAND_MARIBOZU; //--- martelo if(shade_low>res.m_bodysize*m_hummer_coef2 && shade_high<res.m_bodysize*m_hummer_coef1) res.m_type=CAND_HAMMER; //--- martelo invertido if(shade_low<res.m_bodysize*m_hummer_coef1 && shade_high>res.m_bodysize*m_hummer_coef2) res.m_type=CAND_INVERT_HAMMER; //--- spinning top if(res.m_type==CAND_SHORT && shade_low>res.m_bodysize*m_spin_coef && shade_high>res.m_bodysize*m_spin_coef) res.m_type=CAND_SPIN_TOP; //--- ArrayFree(rt); return(true); }
O método de reconhecimento da vela GetCandleType() é usado no método público GetCandleType(). GetCandleType() é um método privado. Seus argumentos incluem o símbolo atual, o período gráfico e o número de velas, bem como um ponteiro para a estrutura. O cálculo e a identificação do padrão são realizados com base nesses parâmetros.
PatternType
Reconhece o tipo de padrão com a vela selecionada. Ele tem 5 sobrecargas de método porque os argumentos podem ser de padrões existentes da enumeração TYPE_PATTERN ou padrões gerados que consistem em uma, duas ou três velas. Um argumento também pode ser um array de padrões da enumeração TYPE_PATTERN.
//--- Reconhecendo o tipo do padrão bool PatternType(const string symbol,const ENUM_TIMEFRAMES timeframe,TYPE_PATTERN pattern,int shift); bool PatternType(const string symbol,const ENUM_TIMEFRAMES timeframe,int index,const int shift); bool PatternType(const string symbol,const ENUM_TIMEFRAMES timeframe,int index1,int index2,const int shift); bool PatternType(const string symbol,const ENUM_TIMEFRAMES timeframe,int index1,int index2,int index3,const int shift); //--- Reconhecendo o conjunto de padrões bool PatternType(const string symbol,const ENUM_TIMEFRAMES timeframe,TYPE_PATTERN &pattern[],int shift);
Parâmetros
- symbol — Símbolo selecionado para a busca.
- timeframe — Período gráfico selecionado.
- pattern,pattern[] — Tipo de padrão existente da TYPE_PATTERN.
Um ponteiro para o array de padrões existentes da lista TYPE_PATTERN.
//+------------------------------------------------------------------+ //| Tipo do padrão | //+------------------------------------------------------------------+ enum TYPE_PATTERN { NONE, HUMMER, INVERT_HUMMER, HANDING_MAN, SHOOTING_STAR, ENGULFING_BULL, ENGULFING_BEAR, HARAMI_BULL, HARAMI_BEAR, HARAMI_CROSS_BULL, HARAMI_CROSS_BEAR, DOJI_STAR_BULL, DOJI_STAR_BEAR, PIERCING_LINE, DARK_CLOUD_COVER };
- index,index1,index2,index3 — Índice da vela de tipo simples (bloco 4 na Fig.1).
- shift — Índice da vela selecionada para o início da análise, começando com 0.
Valor de Retorno
Um valor booleano.
Implementação
Como existem 5 tipos de implementações do método PatternType, nós vamos analisá-lo separadamente com vários argumentos. O primeiro deles buscar por um padrão existente da enumeração TYPE_PATTERN. Como pode ser visto abaixo, isso é feito usando o método privado CheckPattern.
//+------------------------------------------------------------------+ //| Reconhecendo um padrão pré-definido | //+------------------------------------------------------------------+ bool CPattern::PatternType(const string symbol,const ENUM_TIMEFRAMES timeframe,TYPE_PATTERN pattern,const int shift) { if(CheckPattern(symbol,timeframe,shift)==pattern) return(true); return(false); } //+------------------------------------------------------------------+ //| Verifica e retorna o tipo do padrão | //+------------------------------------------------------------------+ TYPE_PATTERN CPattern::CheckPattern(const string symbol,const ENUM_TIMEFRAMES timeframe,int shift) { CANDLE_STRUCTURE cand1,cand2; TYPE_PATTERN pattern=NONE; ZeroMemory(cand1); ZeroMemory(cand2); GetCandleType(symbol,timeframe,cand2,shift); // Vela anterior GetCandleType(symbol,timeframe,cand1,shift-1); // Vela atual //--- Martelo invertido, modelo altista if(cand2.m_trend==DOWN && // Verifica a direção da tendência cand2.m_type==CAND_INVERT_HAMMER) // Verifica o "Martelo invertido" pattern=INVERT_HUMMER; //--- Enforcado, baixista else if(cand2.m_trend==UPPER && // Verifica a direção da tendência cand2.m_type==CAND_HAMMER) // Verifica o "Martelo" pattern=HANDING_MAN; //--- Martelo, modelo altista else if(cand2.m_trend==DOWN && // Verifica a direção da tendência cand2.m_type==CAND_HAMMER) // Verifica o "Martelo" pattern=HUMMER; //--- Estrela Cadente, modelo baixista else if(cand1.m_trend==UPPER && cand2.m_trend==UPPER && // Verifica a direção da tendência cand2.m_type==CAND_INVERT_HAMMER && cand1.m_close<=cand2.m_open) // Verifica o "Martelo invertido" pattern=SHOOTING_STAR; //--- Engolfo de alta, modelo altista else if(cand1.m_trend==DOWN && cand1.m_bull && cand2.m_trend==DOWN && !cand2.m_bull && // Verifica a direção da tendência e da vela cand1.m_bodysize>cand2.m_bodysize && cand1.m_close>=cand2.m_open && cand1.m_open<cand2.m_close) pattern=ENGULFING_BULL; //--- Engolfo de baixa, modelo baixista else if(cand1.m_trend==UPPER && cand1.m_bull && cand2.m_trend==UPPER && !cand2.m_bull && // Verifica a direção da tendência e da vela cand1.m_bodysize<cand2.m_bodysize && cand1.m_close<=cand2.m_open && cand1.m_open>cand2.m_close) pattern=ENGULFING_BEAR; //--- Harami Cross, altista else if(cand2.m_trend==DOWN && !cand2.m_bull && // Verifica a direção da tendência e da vela (cand2.m_type==CAND_LONG || cand2.m_type==CAND_MARIBOZU) && cand1.m_type==CAND_DOJI && // Verifica a primeira vela de "alta" e o Doji cand1.m_close<cand2.m_open && cand1.m_open>=cand2.m_close) // Doji está dentro do corpo da primeira vela pattern=HARAMI_CROSS_BULL; //--- Harami Cross, modelo baixista else if(cand2.m_trend==UPPER && cand2.m_bull && // Verifica a direção da tendência e da vela (cand2.m_type==CAND_LONG || cand2.m_type==CAND_MARIBOZU) && cand1.m_type==CAND_DOJI && // Verifica a primeira vela de "alta" e o Doji cand1.m_close>cand2.m_open && cand1.m_open<=cand2.m_close) // Doji está dentro do corpo da primeira vela pattern=HARAMI_CROSS_BEAR; //--- Harami de alta, altista else if(cand1.m_trend==DOWN && cand1.m_bull && !cand2.m_bull && // Verifica a direção da tendência e da vela (cand2.m_type==CAND_LONG || cand2.m_type==CAND_MARIBOZU) && // Verifica a primeira vela de "alta" cand1.m_type!=CAND_DOJI && cand1.m_bodysize<cand2.m_bodysize && // A segunda vela não é Doji e a primeira vela é maior que a segunda cand1.m_close<cand2.m_open && cand1.m_open>=cand2.m_close) // O corpo da segunda vela está dentro do corpo da primeira pattern=HARAMI_BULL; //--- Harami de baixa, baixista else if(cand1.m_trend==UPPER && !cand1.m_bull && cand2.m_bull && // Verifica a direção da tendência e da vela (cand2.m_type==CAND_LONG || cand2.m_type==CAND_MARIBOZU) && // Verifica a primeira vela de "alta" cand1.m_type!=CAND_DOJI && cand1.m_bodysize<cand2.m_bodysize && // A segunda vela não é Doji e a primeira vela é maior que a segunda cand1.m_close>cand2.m_open && cand1.m_open<=cand2.m_close) // O corpo da segunda vela está dentro do corpo da primeira pattern=HARAMI_BEAR; //--- Estrela Doji, altista else if(cand1.m_trend==DOWN && !cand2.m_bull && // Verifica a direção da tendência e da vela (cand2.m_type==CAND_LONG || cand2.m_type==CAND_MARIBOZU) && cand1.m_type==CAND_DOJI && // Verifica a primeira vela de "alta" e o Doji cand1.m_close<=cand2.m_open) // Abertura do Doji é menor ou igual ao fechamento da primeira vela pattern=DOJI_STAR_BULL; //--- Estrela Doji, baixista else if(cand1.m_trend==UPPER && cand2.m_bull && // Verifica a direção da tendência e da vela (cand2.m_type==CAND_LONG || cand2.m_type==CAND_MARIBOZU) && cand1.m_type==CAND_DOJI && // Verifica a primeira vela de "alta" e o Doji cand1.m_open>=cand2.m_close) //Abertura do Doji é maior ou igual ao fechamento da primeira vela pattern=DOJI_STAR_BEAR; //--- Piercing, modelo altista else if(cand1.m_trend==DOWN && cand1.m_bull && !cand2.m_bull && // Verifica a direção da tendência e da vela (cand1.m_type==CAND_LONG || cand1.m_type==CAND_MARIBOZU) && (cand2.m_type==CAND_LONG || cand2.m_type==CAND_MARIBOZU) && // Verifica a vela de "alta" cand1.m_close>(cand2.m_close+cand2.m_open)/2 && // Fechamento da segunda vela está acima do meio da primeira vela cand2.m_open>cand1.m_close && cand2.m_close>=cand1.m_open) pattern=PIERCING_LINE; //--- Núvem Negra, baixista else if(cand1.m_trend==UPPER && !cand1.m_bull && cand2.m_bull && // Verifica a direção da tendência e da vela (cand1.m_type==CAND_LONG || cand1.m_type==CAND_MARIBOZU) && (cand2.m_type==CAND_LONG || cand2.m_type==CAND_MARIBOZU) && // Verifica a vela de "alta" cand1.m_close<(cand2.m_close+cand2.m_open)/2 && // Fechamento 2 está abaixo do meio do primeiro corpo da vela cand1.m_close<cand2.m_open && cand2.m_close<=cand1.m_open) pattern=DARK_CLOUD_COVER; return(pattern); } //+------------------------------------------------------------------+
O próximo tipo do método PatternType difere do anterior, já que o array de padrões buscados é passado em vez do argumento do tipo do padrão:
//+------------------------------------------------------------------+ //| Reconhecendo o array de padrões | //+------------------------------------------------------------------+ bool CPattern::PatternType(const string symbol,const ENUM_TIMEFRAMES timeframe,TYPE_PATTERN &pattern[],int shift) { for(int i=0;i<ArraySize(pattern);i++) { if(CheckPattern(symbol,timeframe,shift)==pattern[i]) return(true); } return(false); }
Em seguida, vamos considerar a implementação do método PatternType para trabalhar com os padrões gerados a partir dos tipos simples de velas. Existem três tipos desses padrões: consistindo de um, dois ou três velas. Vamos considerá-los um por um:
//+------------------------------------------------------------------+ //| Reconhecendo um padrão pelo índice da vela | //+------------------------------------------------------------------+ bool CPattern::PatternType(const string symbol,const ENUM_TIMEFRAMES timeframe,int index,int shift) { //--- Verifica o índice das velas if(index<0 || index>11) return(false); //--- CANDLE_STRUCTURE cand,cur_cand; RATING_SET ratings; ZeroMemory(cand); IndexToPatternType(cand,index); //--- Obtém o tipo de vela atual GetCandleType(symbol,timeframe,cur_cand,shift); // Vela atual //--- if(cur_cand.m_type==cand.m_type && cur_cand.m_bull==cand.m_bull) return(true); return(false); }
Esta é a implementação de um método buscando por um padrão de uma vela, que é muito semelhante ao método CandleType(), embora o tipo e o intervalo de argumentos passados sejam diferentes. Preste atenção ao método privado IndextoPatternType() que não foi usado anteriormente:
//--- Converte o índice da vela para o seu tipo void IndexToPatternType(CANDLE_STRUCTURE &res,int index);
Converte o índice de um tipo simples de vela no seu tipo e passa para a estrutura especificada.
Aqui está o método para o padrão de duas velas:
//+------------------------------------------------------------------+ //| Reconhecendo um padrão pelo índice da vela | //+------------------------------------------------------------------+ bool CPattern::PatternType(const string symbol,const ENUM_TIMEFRAMES timeframe,int index1,int index2,int shift) { //--- Verifica o índice das velas if(index1<0 || index1>11 || index2<0 || index2>11) return(false); //--- CANDLE_STRUCTURE cand1,cand2,cand3,cur_cand,prev_cand; RATING_SET ratings; ZeroMemory(cand1); ZeroMemory(cand2); IndexToPatternType(cand1,index1); IndexToPatternType(cand2,index2); //--- Obtém o tipo de vela atual GetCandleType(symbol,timeframe,prev_cand,shift+1); // Vela anterior GetCandleType(symbol,timeframe,cur_cand,shift); // Vela atual //--- if(cur_cand.m_type==cand1.m_type && cur_cand.m_bull==cand1.m_bull && prev_cand.m_type==cand2.m_type && prev_cand.m_bull==cand2.m_bull) return(true); return(false); }
A implementação do código é muito semelhante à anterior. No entanto, observe que o seguinte recurso deve ser levado em consideração ao selecionar o índice de velas para análise: como o padrão consiste de duas velas, o tipo da vela 'index1' será deslocado por 'shift' e para index2 - por 'shift+1 '. A mesma peculiaridade diz respeito à implementação do método para os padrões de três velas:
//+------------------------------------------------------------------+ //| Reconhecendo um padrão pelo índice da vela | //+------------------------------------------------------------------+ bool CPattern::PatternType(const string symbol,const ENUM_TIMEFRAMES timeframe,int index1,int index2,int index3,int shift) { CANDLE_STRUCTURE cand1,cand2,cand3,cur_cand,prev_cand,prev_cand2; RATING_SET ratings; //--- ZeroMemory(cand1); ZeroMemory(cand2); ZeroMemory(cand3); //--- IndexToPatternType(cand1,index1); IndexToPatternType(cand2,index2); IndexToPatternType(cand3,index3); //--- Obtém o tipo de vela atual GetCandleType(symbol,timeframe,prev_cand2,shift+2); // Vela anterior GetCandleType(symbol,timeframe,prev_cand,shift+1); // Vela anterior GetCandleType(symbol,timeframe,cur_cand,shift); // Vela atual //--- if(cur_cand.m_type==cand1.m_type && cur_cand.m_bull==cand1.m_bull && prev_cand.m_type==cand2.m_type && prev_cand.m_bull==cand2.m_bull && prev_cand2.m_type==cand3.m_type && prev_cand2.m_bull==cand3.m_bull) return(true); return(false); }
Found
Retorna o número de padrões encontrados do tipo especificado. Ele possui 3 sobrecargas de métodos para os padrões existentes TYPE_PATTERN, bem como para padrões gerados que consistem de 1-3 tipos simples de velas.
//--- Retorna o número de padrões encontrados do tipo especificado int Found(const string symbol,const ENUM_TIMEFRAMES timeframe,TYPE_PATTERN pattern); int Found(const string symbol,const ENUM_TIMEFRAMES timeframe,int index); int Found(const string symbol,const ENUM_TIMEFRAMES timeframe,int index1,int index2); int Found(const string symbol,const ENUM_TIMEFRAMES timeframe,int index1,int index2,int index3);
Parâmetros
- symbol — Símbolo selecionado para a busca.
- timeframe — Período gráfico selecionado.
- pattern — Tipo de padrão existente da TYPE_PATTERN.
- index,index1,index2,index3 — Índice da vela de tipo simples (bloco 4 na Fig.1).
Valor de Retorno
O número de padrões encontrados do tipo especificado.
Implementação
A implementação deste método é bastante simples. As principais operações relacionadas à coleta de estatísticas são realizadas pelo método privado PatternStat().
//+------------------------------------------------------------------+ //| Retorna o número de padrões encontrados do tipo especificado | //+------------------------------------------------------------------+ int CPattern::Found(const string symbol,const ENUM_TIMEFRAMES timeframe,TYPE_PATTERN pattern) { PatternStat(symbol,timeframe,pattern); return(m_found); } //+------------------------------------------------------------------+ //| Retorna o número de padrões encontrados do tipo especificado | //+------------------------------------------------------------------+ int CPattern::Found(const string symbol,const ENUM_TIMEFRAMES timeframe,int index1) { PatternStat(symbol,timeframe,index1); return(m_found); } //+------------------------------------------------------------------+ //| Retorna o número de padrões encontrados do tipo especificado | //+------------------------------------------------------------------+ int CPattern::Found(const string symbol,const ENUM_TIMEFRAMES timeframe,int index1,int index2) { PatternStat(symbol,timeframe,index1,index2); return(m_found); } //+------------------------------------------------------------------+ //| Retorna o número de padrões encontrados do tipo especificado | //+------------------------------------------------------------------+ int CPattern::Found(const string symbol,const ENUM_TIMEFRAMES timeframe,int index1,int index2,int index3) { PatternStat(symbol,timeframe,index1,index2,index3); return(m_found); }
O método PatternStat() possui dois tipos: para padrões existentes e gerados. Vamos examiná-los em detalhes. O primeiro é destinado a padrões da enumeração TYPE_PATTERN:
//+------------------------------------------------------------------+ //| Obtém estatísticas sobre o padrão dado | //+------------------------------------------------------------------+ CPattern::PatternStat(const string symbol,const ENUM_TIMEFRAMES timeframe,TYPE_PATTERN pattern) { //--- int pattern_counter=0; //--- RATING_SET pattern_coef={0,0,0,0,0,0}; //--- for(int i=m_range_total;i>4;i--) { if(CheckPattern(symbol,timeframe,i)==pattern) { pattern_counter++; if(pattern==HUMMER || pattern==INVERT_HUMMER || pattern==HANDING_MAN) GetCategory(symbol,timeframe,pattern_coef,i-3); else GetCategory(symbol,timeframe,pattern_coef,i-4); } } //--- CoefCalculation(pattern_coef,pattern_counter); }
O segundo é usado para padrões gerados que consistem em índices de tipos simples de velas.
//+------------------------------------------------------------------+ //| Obtém estatísticas sobre o padrão dado | //+------------------------------------------------------------------+ void CPattern::PatternStat(const string symbol,const ENUM_TIMEFRAMES timeframe,int index1,int index2=0,int index3=0) { CANDLE_STRUCTURE cand1,cand2,cand3,cur_cand,prev_cand,prev_cand2; RATING_SET rating={0,0,0,0,0,0}; int pattern_total=0,pattern_size=1; //--- ZeroMemory(cand1); ZeroMemory(cand2); ZeroMemory(cand3); ZeroMemory(cur_cand); ZeroMemory(prev_cand); ZeroMemory(prev_cand2); //--- if(index2>0) pattern_size=2; if(index3>0) pattern_size=3; //--- if(pattern_size==1) IndexToPatternType(cand1,index1); else if(pattern_size==2) { IndexToPatternType(cand1,index1); IndexToPatternType(cand2,index2); } else if(pattern_size==3) { IndexToPatternType(cand1,index1); IndexToPatternType(cand2,index2); IndexToPatternType(cand3,index3); } //--- for(int i=m_range_total;i>5;i--) { if(pattern_size==1) { //--- Obtém o tipo de vela atual GetCandleType(symbol,timeframe,cur_cand,i); // Vela atual //--- if(cur_cand.m_type==cand1.m_type && cur_cand.m_bull==cand1.m_bull) { pattern_total++; GetCategory(symbol,timeframe,rating,i-3); } } else if(pattern_size==2) { //--- Obtém o tipo de vela atual GetCandleType(symbol,timeframe,prev_cand,i); // Vela anterior GetCandleType(symbol,timeframe,cur_cand,i-1); // Vela atual //--- if(cur_cand.m_type==cand1.m_type && cur_cand.m_bull==cand1.m_bull && prev_cand.m_type==cand2.m_type && prev_cand.m_bull==cand2.m_bull) { pattern_total++; GetCategory(symbol,timeframe,rating,i-4); } } else if(pattern_size==3) { //--- Obtém o tipo de vela atual GetCandleType(symbol,timeframe,prev_cand2,i); // Vela anterior GetCandleType(symbol,timeframe,prev_cand,i-1); // Vela anterior GetCandleType(symbol,timeframe,cur_cand,i-2); // Vela atual //--- if(cur_cand.m_type==cand1.m_type && cur_cand.m_bull==cand1.m_bull && prev_cand.m_type==cand2.m_type && prev_cand.m_bull==cand2.m_bull && prev_cand2.m_type==cand3.m_type && prev_cand2.m_bull==cand3.m_bull) { pattern_total++; GetCategory(symbol,timeframe,rating,i-5); } } } //--- CoefCalculation(rating,pattern_total); }
Essas duas implementações do método contêm um novo método. Este é o método privado CoefCalculation():
//--- Calcula os coeficientes bool CoefCalculation(RATING_SET &rate,int found);
Ele processa todos os resultados obtidos ao buscar e testar padrões. Seus argumentos contêm um ponteiro para a estrutura RATING_SET, que é responsável pela coleta de dados referentes aos resultados do teste da eficiência padrão e ao número de padrões encontrados. Todos os outros parâmetros e propriedades dos padrões analisados são calculados no método CoefCalculation().
//+------------------------------------------------------------------+ //| Cálculo dos coeficientes de avaliação de eficiência | //+------------------------------------------------------------------+ bool CPattern::CoefCalculation(RATING_SET &rate,int found) { int sum1=0,sum2=0; sum1=rate.m_a_uptrend+rate.m_b_uptrend+rate.m_c_uptrend; sum2=rate.m_a_dntrend+rate.m_b_dntrend+rate.m_c_dntrend; //--- m_probability1=(found>0)?NormalizeDouble((double)sum1/found*100,2):0; m_probability2=(found>0)?NormalizeDouble((double)sum2/found*100,2):0; m_efficiency1=(found>0)?NormalizeDouble((m_k1*rate.m_a_uptrend+m_k2*rate.m_b_uptrend+m_k3*rate.m_c_uptrend)/found,3):0; m_efficiency2=(found>0)?NormalizeDouble((m_k1*rate.m_a_dntrend+m_k2*rate.m_b_dntrend+m_k3*rate.m_c_dntrend)/found,3):0; m_found=found; m_coincidence=((double)found/m_range_total*100); return(true); }
Coincidence
Retorna a frequência da ocorrência do padrão. Ele possui 3 sobrecargas de métodos para os padrões existentes TYPE_PATTERN, bem como para padrões gerados que consistem de 1-3 tipos simples de velas.
//--- Retorna a frequência da ocorrência do padrão double Coincidence(const string symbol,const ENUM_TIMEFRAMES timeframe,TYPE_PATTERN pattern); double Coincidence(const string symbol,const ENUM_TIMEFRAMES timeframe,int index); double Coincidence(const string symbol,const ENUM_TIMEFRAMES timeframe,int index1,int index2); double Coincidence(const string symbol,const ENUM_TIMEFRAMES timeframe,int index1,int index2,int index3);
Parâmetros
- symbol — Símbolo selecionado para a busca.
- timeframe — Período gráfico selecionado.
- pattern — Tipo de padrão existente da TYPE_PATTERN.
- index,index1,index2,index3 — Índice da vela de tipo simples (bloco 4 na Fig.1).
Valor de Retorno
A frequência de ocorrência do padrão em porcentagem.
Implementação
Semelhante ao método Found(). A única diferença é que ele retorna o valor da variável m_coincidence.
//+------------------------------------------------------------------+ //| Retorna a frequência da ocorrência do padrão | //+------------------------------------------------------------------+ double CPattern::Coincidence(const string symbol,const ENUM_TIMEFRAMES timeframe,TYPE_PATTERN pattern) { PatternStat(symbol,timeframe,pattern); return(m_coincidence); } //+------------------------------------------------------------------+ //| Retorna a frequência da ocorrência do padrão | //+------------------------------------------------------------------+ double CPattern::Coincidence(const string symbol,const ENUM_TIMEFRAMES timeframe,int index1) { PatternStat(symbol,timeframe,index1); return(m_coincidence); } //+------------------------------------------------------------------+ //| Retorna a frequência da ocorrência do padrão | //+------------------------------------------------------------------+ double CPattern::Coincidence(const string symbol,const ENUM_TIMEFRAMES timeframe,int index1,int index2) { PatternStat(symbol,timeframe,index1,index2); return(m_coincidence); } //+------------------------------------------------------------------+ //| Retorna a frequência da ocorrência do padrão | //+------------------------------------------------------------------+ double CPattern::Coincidence(const string symbol,const ENUM_TIMEFRAMES timeframe,int index1,int index2,int index3) { PatternStat(symbol,timeframe,index1,index2,index3); return(m_coincidence); }
Probability
Retorna a probabilidade percentual do movimento após o padrão especificado. Ele possui 3 sobrecargas de métodos para os padrões existentes TYPE_PATTERN, bem como para padrões gerados que consistem de 1-3 tipos simples de velas.
//--- Retorna a probabilidade do movimento após o padrão especificado double Probability(const string symbol,const ENUM_TIMEFRAMES timeframe,TYPE_PATTERN pattern,TYPE_TREND trend); double Probability(const string symbol,const ENUM_TIMEFRAMES timeframe,int index,TYPE_TREND trend); double Probability(const string symbol,const ENUM_TIMEFRAMES timeframe,int index1,int index2,TYPE_TREND trend); double Probability(const string symbol,const ENUM_TIMEFRAMES timeframe,int index1,int index2,int index3,TYPE_TREND trend);
Parâmetros
- symbol — Símbolo selecionado para a busca.
- timeframe — Período gráfico selecionado.
- pattern — Tipo de padrão existente da TYPE_PATTERN.
- index,index1,index2,index 3— Índice da vela de tipo simples (bloco 4 na Fig.1).
-
- trend— TYPE_TREND
//+------------------------------------------------------------------+ //| Tipo da tendência | //+------------------------------------------------------------------+ enum TYPE_TREND { UPPER, //Tendência de alta DOWN, //Tendência de baixa FLAT //Lateralizado }; //+------------------------------------------------------------------+
Valor de Retorno
A probabilidade percentual do movimento após o padrão dado.
Implementação
Semelhante ao método Found(). A única diferença é que ele retorna o valor da variável m_probability1 ou m_probability2, dependendo do tipo da tendência selecionada.
//+------------------------------------------------------------------+ //| Retorna a probabilidade do movimento após o padrão dado | //+------------------------------------------------------------------+ double CPattern::Probability(const string symbol,const ENUM_TIMEFRAMES timeframe,TYPE_PATTERN pattern,TYPE_TREND trend) { PatternStat(symbol,timeframe,pattern); if(trend==UPPER) return(m_probability1); if(trend==DOWN) return(m_probability2); return(0); } //+------------------------------------------------------------------+ //| Retorna a probabilidade do movimento após o padrão dado | //+------------------------------------------------------------------+ double CPattern::Probability(const string symbol,const ENUM_TIMEFRAMES timeframe,int index1,TYPE_TREND trend) { PatternStat(symbol,timeframe,index1); if(trend==UPPER) return(m_probability1); if(trend==DOWN) return(m_probability2); return(0); } //+------------------------------------------------------------------+ //| Retorna a probabilidade do movimento após o padrão dado | //+------------------------------------------------------------------+ double CPattern::Probability(const string symbol,const ENUM_TIMEFRAMES timeframe,int index1,int index2,TYPE_TREND trend) { PatternStat(symbol,timeframe,index1,index2); if(trend==UPPER) return(m_probability1); if(trend==DOWN) return(m_probability2); return(0); } //+------------------------------------------------------------------+ //| Retorna a probabilidade do movimento após o padrão dado | //+------------------------------------------------------------------+ double CPattern::Probability(const string symbol,const ENUM_TIMEFRAMES timeframe,int index1,int index2,int index3,TYPE_TREND trend) { PatternStat(symbol,timeframe,index1,index2,index3); if(trend==UPPER) return(m_probability1); if(trend==DOWN) return(m_probability2); return(0); }
Efficiency
Retorna o coeficiente de eficiência do padrão. Ele possui 3 sobrecargas de métodos para os padrões existentes TYPE_PATTERN, bem como para padrões gerados que consistem de 1-3 tipos simples de velas.
//--- Retorna o coeficiente de eficiência do padrão double Efficiency(const string symbol,const ENUM_TIMEFRAMES timeframe,TYPE_PATTERN pattern,TYPE_TREND trend); double Efficiency(const string symbol,const ENUM_TIMEFRAMES timeframe,int index,TYPE_TREND trend); double Efficiency(const string symbol,const ENUM_TIMEFRAMES timeframe,int index1,int index2,TYPE_TREND trend); double Efficiency(const string symbol,const ENUM_TIMEFRAMES timeframe,int index1,int index2,int index3,TYPE_TREND trend);
Parâmetros
- symbol — Símbolo selecionado para a busca.
- timeframe — Período gráfico selecionado.
- pattern — Tipo de padrão existente da TYPE_PATTERN.
- index,index1,index2,index3 — Índice da vela de tipo simples (bloco 4 na Fig.1).
- trend — trend type, TYPE_TREND
//+------------------------------------------------------------------+ //| Tipo da tendência | //+------------------------------------------------------------------+ enum TYPE_TREND { UPPER, //Tendência de alta DOWN, //Tendência de baixa FLAT //Lateralizado }; //+------------------------------------------------------------------+
Valor de Retorno
O coeficiente de eficiência do padrão.
Implementação
Semelhante ao método Found(). A única diferença é que ele retorna o valor da variável m_efficiency1 ou m_efficiency2 dependendo do tipo da tendência selecionada.
//+------------------------------------------------------------------+ //| Retorna a probabilidade do movimento após o padrão dado | //+------------------------------------------------------------------+ double CPattern::Efficiency(const string symbol,const ENUM_TIMEFRAMES timeframe,TYPE_PATTERN pattern,TYPE_TREND trend) { PatternStat(symbol,timeframe,pattern); if(trend==UPPER) return(m_efficiency1); if(trend==DOWN) return(m_efficiency2); return(0); } //+------------------------------------------------------------------+ //| Retorna a probabilidade do movimento após o padrão dado | //+------------------------------------------------------------------+ double CPattern::Efficiency(const string symbol,const ENUM_TIMEFRAMES timeframe,int index1,TYPE_TREND trend) { PatternStat(symbol,timeframe,index1); if(trend==UPPER) return(m_efficiency1); if(trend==DOWN) return(m_efficiency2); return(0); } //+------------------------------------------------------------------+ //| Retorna a probabilidade do movimento após o padrão dado | //+------------------------------------------------------------------+ double CPattern::Efficiency(const string symbol,const ENUM_TIMEFRAMES timeframe,int index1,int index2,TYPE_TREND trend) { PatternStat(symbol,timeframe,index1,index2); if(trend==UPPER) return(m_efficiency1); if(trend==DOWN) return(m_efficiency2); return(0); } //+------------------------------------------------------------------+ //| Retorna a probabilidade do movimento após o padrão dado | //+------------------------------------------------------------------+ double CPattern::Efficiency(const string symbol,const ENUM_TIMEFRAMES timeframe,int index1,int index2,int index3,TYPE_TREND trend) { PatternStat(symbol,timeframe,index1,index2,index3); if(trend==UPPER) return(m_efficiency1); if(trend==DOWN) return(m_efficiency2); return(0); }
Uso prático
Tendo considerado as ferramentas para o trabalho com os padrões, vamos implementar dois indicadores e um Expert Advisor para demonstrar o uso da biblioteca.
CandleDetector
Vamos começar com o indicador que mostra em um gráfico uma vela do tipo selecionado da enumeração TYPE_CANDLESTICK. Crie a pasta Pattern na pasta de Indicators. Nesta pasta, crie o arquivo CandleDetector.mq5 no qual o indicador será criado. Vamos incluir a biblioteca Pattern.mqh para trabalhar com padrões e definir as propriedades iniciais do futuro indicador:
//+------------------------------------------------------------------+ //| CandleDetector.mq5 | //| Copyright 2019, MetaQuotes Software Corp. | //| https://www.mql5.com/en/users/alex2356 | //+------------------------------------------------------------------+ #property copyright "Copyright 2019, MetaQuotes Software Corp." #property link "https://www.mql5.com/en/users/alex2356" #property version "1.00" #property indicator_chart_window #property indicator_buffers 1 #property indicator_plots 1 #include <Pattern/Pattern.mqh> //+----------------------------------------------+ //| Parâmetros de desenho do indicador | //+----------------------------------------------+ //---- Exibição do rótulo do indicador #property indicator_type1 DRAW_ARROW //---- Largura da linha do indicador #property indicator_width1 1
O próximo passo é determinar as principais configurações que afetarão a exibição deste ou daquele tipo de vela.
//+----------------------------------------------+ //| Parâmetros de entrada do indicador | //+----------------------------------------------+ input TYPE_CANDLESTICK CandleType=1; // Tipo de vela input color LabelColor=clrCrimson; input double LongCoef=1.3; input double ShortCoef=0.5; input double DojiCoef=0.04; input double MaribozuCoef=0.01; input double SpinCoef=1; input double HummerCoef1=0.1; input double HummerCoef2=2; input int TrendPeriod=5;
Em seguida, na inicialização, configure a aparência do indicador e determine todos os valores dos parâmetros de entrada para a busca.
//+------------------------------------------------------------------+ //| Função de inicialização do indicador personalizado | //+------------------------------------------------------------------+ int OnInit() { //---- Inicializa as variáveis de início do cálculo de dados min_rates_total=TrendPeriod+1; //---- Define a precisão dos valores dos indicadores a serem exibidos IndicatorSetInteger(INDICATOR_DIGITS,_Digits); //---- Configura o array dinâmico Signal[] como um buffer do indicador SetIndexBuffer(0,Signal,INDICATOR_DATA); //---- Desloca por 1 o início do desenho do indicador PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,min_rates_total); //---- Define a indexação de elementos nos buffers como na série temporal ArraySetAsSeries(Signal,true); //---- Define os valores do indicador que não serão visíveis no gráfico PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,EMPTY_VALUE); //---- símbolo do indicador PlotIndexSetInteger(0,PLOT_ARROW,108); //--- PlotIndexSetInteger(0,PLOT_LINE_COLOR,LabelColor); //---- Pat.Long_coef(LongCoef); Pat.Short_coef(ShortCoef); Pat.Doji_coef(DojiCoef); Pat.Maribozu_coef(MaribozuCoef); Pat.Spin_coef(SpinCoef); Pat.Hummer_coef1(HummerCoef1); Pat.Hummer_coef2(HummerCoef2); Pat.TrendPeriod(TrendPeriod); return(INIT_SUCCEEDED); }
Preste atenção ao método CandleType() — ele é usado para buscar o tipo da vela selecionado no gráfico.
//+------------------------------------------------------------------+ //| Função de iteração do indicador personalizado | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]) { //---- Verifica se existem barras suficientes para o cálculo if(rates_total<min_rates_total) return(0); //---- Declara as variáveis locais int limit,bar; //---- Define a indexação de elementos nos buffers como na série temporal ArraySetAsSeries(low,true); //---- Calcula o 'primeiro' número inicial para o ciclo de recálculo das barras if(prev_calculated>rates_total || prev_calculated<=0) // Verifica o primeiro início do cálculo do indicador limit=rates_total-min_rates_total; // Inicia o índice para calcular todas as barras else limit=rates_total-prev_calculated; // Inicia o índice para calcular novas barras //---- Loop de cálculo do indicador principal for(bar=limit; bar>=0; bar--) { Signal[bar]=0.0; if(Pat.CandleType(Symbol(),PERIOD_CURRENT,bar)==CandleType) Signal[bar]=low[bar]-200*_Point; } return(rates_total); } //+------------------------------------------------------------------+
O exemplo de funcionamento do indicador é mostrado na Fig.3 (Busca por uma vela de alta).
Fig.3 Exemplo do funcionamento do indicador CandleDetector.
PatternDetector
O segundo indicador buscará um padrão especificado da enumeração TYPE_PATTERN. A implementação é muito semelhante à anterior. Este código difere em um parâmetro de entrada e no método usado na parte do cálculo.
//+----------------------------------------------+ //| Parâmetros de entrada do indicador | //+----------------------------------------------+ input TYPE_PATTERN PatternType=1; // Tipo do padrão input color LabelColor=clrCrimson; input double LongCoef=1.3; input double ShortCoef=0.5; input double DojiCoef=0.04; input double MaribozuCoef=0.01; input double SpinCoef=1; input double HummerCoef1=0.1; input double HummerCoef2=2; input int TrendPeriod=5; //--- CPattern Pat; double Signal[]; //---- Declara as variáveis inteiras para o início do cálculo de dados int min_rates_total; //+------------------------------------------------------------------+ //| Função de inicialização do indicador personalizado | //+------------------------------------------------------------------+ void OnInit() { //---- Inicializa as variáveis de início do cálculo de dados min_rates_total=TrendPeriod+2; //---- Define a precisão dos valores dos indicadores a serem exibidos IndicatorSetInteger(INDICATOR_DIGITS,_Digits); //---- Configura o array dinâmico SignUp[] como um buffer do indicador SetIndexBuffer(0,Signal,INDICATOR_DATA); //---- Desloca por 1 o início do desenho do indicador PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,min_rates_total); //---- Define a indexação de elementos nos buffers como na série temporal ArraySetAsSeries(Signal,true); //---- Define os valores do indicador que não serão visíveis no gráfico PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,EMPTY_VALUE); //---- símbolo do indicador PlotIndexSetInteger(0,PLOT_ARROW,108); //--- PlotIndexSetInteger(0,PLOT_LINE_COLOR,LabelColor); //---- Pat.Long_coef(LongCoef); Pat.Short_coef(ShortCoef); Pat.Doji_coef(DojiCoef); Pat.Maribozu_coef(MaribozuCoef); Pat.Spin_coef(SpinCoef); Pat.Hummer_coef1(HummerCoef1); Pat.Hummer_coef2(HummerCoef2); Pat.TrendPeriod(TrendPeriod); } //+------------------------------------------------------------------+ //| Função de iteração do indicador personalizado | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]) { //---- Verifica se existem barras suficientes para o cálculo if(rates_total<min_rates_total) return(0); //---- Declara as variáveis locais int limit,bar; //---- Define a indexação de elementos nos buffers como na série temporal ArraySetAsSeries(low,true); //---- Calcula o 'primeiro' número inicial para o ciclo de recálculo das barras if(prev_calculated>rates_total || prev_calculated<=0) // Verifica o primeiro início do cálculo do indicador limit=rates_total-min_rates_total; // Inicia o índice para calcular todas as barras else limit=rates_total-prev_calculated; // Inicia o índice para calcular novas barras //---- Loop de cálculo do indicador principal for(bar=limit; bar>0; bar--) { Signal[bar]=0.0; if(Pat.PatternType(_Symbol,_Period,PatternType,bar)) Signal[bar]=low[bar]-200*_Point; } return(rates_total); } //+------------------------------------------------------------------+
Os resultados do funcionamento do PatternDetector são mostrados na Fig.4 (busca pelo padrão Engolfo de alta).
Fig.4 Exemplo do funcionamento do indicador PatternDetector.
Agora vamos criar um Expert Advisor, que pode encontrar padrões no gráfico e posições abertas, dependendo do padrão selecionado. Tipos de padrão individuais podem ser usados para cada tipo de negócio. Um modo adicional permitirá a escolha entre padrões existentes e padrões gerados usando os tipos simples de velas.
Vamos criar a pasta Pattern na pasta Experts e adicionar o PatternExpert.mq5, em que o código do EA será escrito. No primeiro estágio, inclua a biblioteca Pattern.mqh para trabalhar com os padrões e a biblioteca de operações de negociação Trade.mqh. Declare as instâncias de classe e introduza a enumeração PATTERN_MODE, que permite alternar entre os padrões existentes e gerados.
//+------------------------------------------------------------------+ //| PatternExpert.mq5 | //| Copyright 2019, MetaQuotes Software Corp. | //| https://www.mql5.com/en/users/alex2356 | //+------------------------------------------------------------------+ #property copyright "Copyright 2018, MetaQuotes Software Corp." #property link "https://www.mql5.com/en/users/alex2356" #property version "1.00" #include <Pattern/Pattern.mqh> #include "Trade.mqh" CTradeBase Trade; CPattern Pat; //+------------------------------------------------------------------+ //| Modo de busca do padrão | //+------------------------------------------------------------------+ enum PATTERN_MODE { EXISTING, GENERATED };
Agora defina os parâmetros de entrada do Expert Advisor. Os parâmetros do EA são fornecidos no primeiro bloco:
//+------------------------------------------------------------------+ //| Parâmetros de entrada do Expert Advisor | //+------------------------------------------------------------------+ input string Inp_EaComment="Pattern Strategy"; // Comentário do EA input double Inp_Lot=0.01; // Lote input MarginMode Inp_MMode=LOT; // Gestão de capital //--- Parâmetros do EA input string Inp_Str_label="===EA parameters==="; // Rótulo input int Inp_MagicNum=1111; // Número mágico input int Inp_StopLoss=40; // Stop Loss(pontos) input int Inp_TakeProfit=30; // Take Profit(pontos)
A segunda parte contém as configurações e os parâmetros de negociação.
//--- Parâmetros de negociação input ENUM_TIMEFRAMES Timeframe=PERIOD_CURRENT; // Período gráfico atual input PATTERN_MODE PatternMode=0; // Modo do padrão input TYPE_PATTERN BuyPatternType=ENGULFING_BULL; // Tipo do padrão de compra input TYPE_PATTERN SellPatternType=ENGULFING_BEAR; // Tipo do padrão de venda input uint BuyIndex1=1; // BuyIndex do candle1 simples input uint BuyIndex2=0; // BuyIndex do candle2 simples input uint BuyIndex3=0; // BuyIndex do candle3 simples input uint SellIndex1=1; // SellIndex do candle1 simples input uint SellIndex2=0; // SellIndex do candle2 simples input uint SellIndex3=0; // SellIndex do candle3 simples input double LongCoef=1.3; // Coeficiente da vela de alta input double ShortCoef=0.5; // Coeficiente da vela de baixa input double DojiCoef=0.04; // Coeficiente da vela Doji input double MaribozuCoef=0.01; // Coeficiente da vela Maribozu input double SpinCoef=1; // Coeficiente da vela Spin input double HummerCoef1=0.1; // Coeficiente da vela Martelo input double HummerCoef2=2; // Coeficiente da vela Martelo input int TrendPeriod=5; // Período da tendência
Vamos considerar alguns desses parâmetros em mais detalhes:
- Período gráfico atual — período gráfico selecionado para as operações. Permite a seleção do período gráfico durante a otimização. O período gráfico atual do gráfico é selecionado por padrão.
- Modo do padrão — modo de seleção do padrão. EXISTING — padrões existentes; duas configurações para o Tipo Padrão de Compra e Padrão de Venda são aplicáveis neste modo. GENERATED - padrões gerados. Neste modo, as configurações de Tipo de Padrão de Compra/Venda são ignoradas e BuyIndex1-3 e SellIndex1-3 são usadas no lugar.
- Tipo do Padrão de Compra/ Tipo do Padrão de Venda — seleciona os padrões para abrir as operações de negociação apropriadas.
- BuyIndex1-3/SellIndex1-3 — seleciona um padrão gerado dos tipos de vela simples (Fig.1 Bloco 4), no momento em que uma posição comprada/vendida será aberta.
Outros parâmetros são semelhantes aos indicadores considerados acima. Além da verificações, defina nos blocos de inicialização o valor do período da tendência que afeta a detecção dos padrões no gráfico.
//+------------------------------------------------------------------+ //| Função de inicialização do Expert | //+------------------------------------------------------------------+ int OnInit() { //--- Verifica a conexão com o servidor de negociação if(!TerminalInfoInteger(TERMINAL_CONNECTED)) { Print(Inp_EaComment,": No Connection!"); return(INIT_FAILED); } //--- Verifica a permissão da negociação automatizada if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) { Print(Inp_EaComment,": Trade is not allowed!"); return(INIT_FAILED); } //--- Pat.TrendPeriod(TrendPeriod); //--- return(INIT_SUCCEEDED); }
A parte do cálculo é fácil de entender. Vamos considerar as funções de busca do sinal de compra e venda.
//+------------------------------------------------------------------+ //| Função Tick do Expert | //+------------------------------------------------------------------+ void OnTick() { if(!Trade.IsOpenedByMagic(Inp_MagicNum)) { //--- Abrindo uma ordem se houver um sinal de compra if(BuySignal()) Trade.BuyPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss,Inp_TakeProfit,Inp_MagicNum,Inp_EaComment); //--- Abrindo uma ordem se houver um sinal de venda if(SellSignal()) Trade.SellPositionOpen(Symbol(),Inp_Lot,Inp_StopLoss,Inp_TakeProfit,Inp_MagicNum,Inp_EaComment); } }
Essas funções são semelhantes e, portanto, vamos considerar apenas uma delas, a BuySignal(), que procura por um sinal de compra.
//+------------------------------------------------------------------+ //| Condições de Compra | //+------------------------------------------------------------------+ bool BuySignal() { if(PatternMode==0) { if(BuyPatternType==NONE) return(false); if(Pat.PatternType(_Symbol,Timeframe,BuyPatternType,1)) return(true); } else if(PatternMode==1) { if(BuyIndex1>0 && BuyIndex2==0 && BuyIndex3==0) { if(Pat.PatternType(_Symbol,Timeframe,BuyIndex1,1)) return(true); } else if(BuyIndex1>0 && BuyIndex2>0 && BuyIndex3==0) { if(Pat.PatternType(_Symbol,Timeframe,BuyIndex1,BuyIndex2,1)) return(true); } else if(BuyIndex1>0 && BuyIndex2>0 && BuyIndex3>0) { if(Pat.PatternType(_Symbol,Timeframe,BuyIndex1,BuyIndex2,BuyIndex3,1)) return(true); } } return(false); }
A função contém uma verificação do modo atual selecionado, padrões existentes ou padrões gerados. Os parâmetros de entrada são selecionados de acordo: TYPE_PATTERN ou um conjunto de índices do padrão gerado.
Vamos testar e otimizar o Expert Advisor resultante em dois modos: com padrões existentes da enumeração TYPE_PATTERN e com padrões gerados que consistem nos tipos de velas simples mostrados no Bloco 4 da Fig.1.
O Expert Advisor será testado com os seguintes parâmetros:
- Intervalo: para o modo Uptrend 01.01.2018 — 15.03.2018.
- Par de moeda: EURUSD.
- Modo de negociação: Sem atraso. Estas não são estratégias de negociação de alta frequência, portanto o efeito dos atrasos é mínimo.
- Teste: 1 Minuto OHLC.
- Depósito inicial: 1000 USD.
- Alavancagem: 1:500.
- Servidor: MetaQuotes-Demo.
- Cotação: 5-digit.
Modo Padrões Gerados.
Vamos determinar os parâmetros a serem testados e otimizados.
Fig.5 Conjunto de parâmetros para otimização no modo Padrões Gerados.
A Fig.5 mostra as condições de teste e otimização. Os melhores parâmetros obtidos como resultado do teste são mostrados na segunda coluna Value. Os resultados do teste e o gráfico são mostrados na Figura 6 abaixo.
Fig.6 Resultado do teste de melhor parâmetro no modo Padrões Gerados.
Modo Padrões Existentes.
Defina os parâmetros para teste e otimização.
Fig.7 Conjunto de parâmetros para a otimização no modo Padrões Existentes.
Novamente, os parâmetros do melhor resultado de otimização são mostrados na segunda coluna. Agora vamos realizar um único teste. Os resultados são mostrados abaixo, na Figura 8.
Fig.8 Resultado do teste de melhor parâmetro no modo Padrões Existentes.
Conclusões
O arquivo anexado abaixo contém todos os arquivos descritos corretamente organizados em pastas. Para uma operação correta, você deve salvar a pasta MQL5 na pasta raiz do terminal Para encontrar essa pasta raiz na qual a pasta MQL5 está localizada, pressione Ctrl+Shift+D na MetaTrader 5 ou use o menu de contexto conforme mostrado na Figura 9.
Fig.9 Como encontrar a pasta MQL5 na pasta raiz da MetaTrader5.
Programas utilizados no artigo
# |
Nome |
Tipo |
Descrição |
---|---|---|---|
1 |
Pattern.mqh | Biblioteca | Biblioteca para trabalhar com os padrões |
2 | CandleDetector.mq5 | Indicador | Indicador de busca de velas |
3 | PatternDetector.mq5 | Indicador | Indicador de busca do padrão |
4 | PatternExpert.mq5 | Expert Advisor | Um Expert Advisor de negociação que trabalha com os padrões |
5 | Trade.mqh | Biblioteca | Classe de funções de negociação |
Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/5751





- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Você concorda com a política do site e com os termos de uso
Boa noite.
Infelizmente não consegui faze-lo funcionar no meu MT5.
Fis o procedimento certo, mas não aparece no MT% para testar.