Estudo dos padrões de Merrill
Conteúdo
Introdução
A primeira tentativa de criar um sistema de padrões de preços foi feita por Robert Levy em 1971. Ele aplicou os padrões de flutuação de preço de cinco pontos e depois verificou se eles tinham algum significado. Ele não obteve resultados notáveis, mas Arthur Merrill continuou com o seu trabalho 10 anos depois.
Ele dividiu os padrões em duas categorias que se assemelham às letras M e W. Cada categoria contém 16 padrões e suas próprias subcategorias. Merrill destacou 6 subcategorias:
- Tendência de alta
- Tendência de baixa
- Triângulo
- Expansão
- Ombro, cabeça e ombro
- Ombro, cabeça e ombro invertidos
Nós vamos definir a relevância atual dos padrões de Merrill usando um aplicativo para testá-los. Além disso, seria interessante aplicar esse modelo a vários tipos de dados — como os preços de fechamento, máxima e mínima, além dos osciladores.
Definição e aplicação
Para esclarecer como e para quais dados nós vamos aplicar os padrões de Merrill, nós precisamos entender o que eles realmente são. As duas principais categorias são os padrões que se assemelham às letras M e W. Eles são chamados de padrões M e W. Cada uma das categorias contém 16 padrões.
Fig. 1 Representação visual dos 16 padrões M. Como nós podemos ver, a diferença está no arranjo mútuo dos cinco pontos que compõem o padrão.
Fig. 1. Representação visual dos padrões М
Fig. 2 Representação visual dos 16 padrões W. Nós vamos buscar esses dois grupos nos gráficos de preço e indicadores, além de estudar, avaliar e buscar possíveis regularidades.
Fig. 2. Representação visual dos padrões W
A ideia por trás de qualquer padrão se resume ao fato de que, quando uma formação específica aparece, nós podemos esperar que o preço se mova em uma determinada direção e obter lucro com isso.
Para deixar o mais claro possível em que área e como os padrões de Merrill devem ser estudados, aqui estão alguns exemplos. Fig. 3 Gráfico de preços linear de USDCAD, em H1. Esse tipo de representação é usado com menos frequência, pois as velas e barras se tornaram mais populares.
Fig. 3. Gráfico linear com base nos preços de fechamento de USDCAD, em H1
Aqui nós já podemos ver alguns padrões descritos acima. Essa deve ser a primeira área de estudo — aplicando ao gráfico linear com base nos preços de fechamento. Além disso, nós vamos verificar gráficos lineares com base nos preços de abertura (Open), máxima (High) e mínima (Low).
A segunda área de estudo deve ser composta por osciladores, como:
- Average True Range (ATR) — indicador de volatilidade do mercado.
- Commodity Channel Index (CCI) — mede o desvio do preço em relação a sua média.
- DeMarker (DeM) — indicador de DeMarker.
- Force Index (FRC) — indicador Índice de Força.
- Williams’ Percent Range (WPR) — indicador dinâmico que define o estado de sobrecomprado/sobrevendido.
- Relative Strength Index (RSI) — Indicador Índice de Força Relativa.
- Momentum — variação do preço de um instrumento financeiro durante um determinado período de tempo.
O método que eu sugeri no artigo Estudo das técnicas de análise de velas (Parte I): Verificação de padrões existentes deve ser usado como um método de avaliação de padrões a serem aplicados ao preço e aos osciladores mencionados acima. A ideia por trás disso é simples:
- Identificação do padrão analisado em uma parte específica da amostra.
- Análise do movimento dos preços após a sua identificação.
- Coleta dos dados e o cálculo da eficiência do padrão.
Desenvolvimento da ferramenta de teste
Antes de iniciar o desenvolvimento, nós precisamos definir quais configurações ele deve conter. A ferramenta consiste no painel com as guias Analysis e Settings. Os parâmetros da janela de configurações do EA também devem ser usados. Em seguida, nós teremos três seções com as ferramentas para trabalhar com os padrões. Agora, vamos descrever as configurações em cada uma das seções.
A guia Analysis contém:
- Dois conjuntos de botões para selecionar os tipos de padrões testados. Existem também os botões All M e All W para a seleção/desmarcação rápida dos padrões М e W.
- O conjunto de botões para a seleção dos períodos gráficos testados e o botão ALL para selecionar/desmarcar todo o grupo de botões.
- O campo de entrada "Trend threshold (points)". É o lucro em pontos que o preço deve atingir dentro de no máximo três velas após a identificação do padrão de Merrill analisado.
- O botão que abre a janela de diálogo para a seleção das datas de início e término, além do horário de teste.
- O campo de entrada com a caixa de seleção e o botão é um filtro para encontrar os símbolos de negociação necessários. Ele possui uma predefinição — Major. Ele exibe os principais pares de moedas. A caixa de seleção desativa o filtro e mostra todos os símbolos de negociação disponíveis.
- Símbolos de negociação selecionados na tabela com o filtro. Após a seleção deles da lista, a análise de padrões é realizada.
- A tabela de resultados consiste em sete colunas:
- Nome da figura. A coluna exibe o nome do padrão de Merrill analisado, por exemplo, M10 ou W12.
- Encontrado. Número de padrões detectados de um tipo especificado em uma amostra selecionada.
- Período gráfico. O período gráfico em que foi analisado um padrão especificado.
- P, Uptrend. A probabilidade do preço subir para o valor do "Limiar de tendência (pontos)" após o padrão ser exibido.
- P, Dntrend. A probabilidade do preço cair para o valor do "Limiar de tendência (pontos)" após o padrão ser exibido.
- K, UpTrend/K, DnTrend. Esta é uma taxa descrita no meu artigo Estudo das técnicas de análise de velas (Parte I): Verificação dos padrões existentes. Ele avalia o quão rápido o preço atinge um lucro especificado após o padrão analisado aparecer na direção ascendente ou descendente de uma tendência.
A Fig. 4 forence a implementação visual de todos os símbolos e parâmetros descritos acima.
Fig. 4. Guia Analysis
Agora vamos considerar a guia Settings:
- Indicador usado. Permite selecionar um indicador que a busca e a análise dos padrões de Merrill devem ser aplicadas.
- Os coeficientes de ponderação são usados no cálculo das taxas de K, UpTrend/DnTrend descritas acima.
- Idioma da interface. A lista suspensa da seleção do idioma da interface: inglês ou russo.
A aparência da guia com as configurações é exibida na Fig. 5 abaixo:
Fig. 5. Guia Settings
A última seção aplica a janela "EA Settings" (tecla de atalho F7) e apresenta as configurações dos indicadores aplicados que foram listados em "Indicador usado". A Fig. 6 mostra a janela da última seção de configurações.
Fig. 6. Janela de configuração dos indicadores usados
Nós devemos considerar as seguintes nuances ao definir as configurações na janela:
- O primeiro ("Preço aplicado") aplica à variável de enumeração ENUM_APPLIED_PRICE com sete valores: preço de abertura, preço de fechamento, máxima e mínima, além dos preços médio, típico e médio ponderado. Ao executar uma análise com base no preço do gráfico, os quatro primeiros valores devem ser usados pois os três últimos são projetados para o cálculo dos indicadores.
- Se você deseja usar os indicadores na análise de padrões, a configuração "Preço aplicado" afeta os indicadores usando a variável do tipo ENUM_APPLIED_PRICE em seus cálculos, a saber: ATR, CCI e RSI.
Agora, vamos considerar a implementação da interface do aplicativo, além dos métodos de busca e análise dos padrões de Merrill.
Para desenvolver a GUI, nós usamos o método CreateGUI() que consiste nos métodos CreateWindow() para a criação da janela principal da interface e a janela de diálogo CreateWindowSetting1() para a seleção do intervalo de tempo para o estudo.
//+------------------------------------------------------------------+ //| Create the program GUI | //+------------------------------------------------------------------+ bool CProgram::CreateGUI(void) { //--- Create the panel if(!CreateWindow("Merrill Patterns")) return(false); //--- Create the dialog window if(!CreateWindowSetting1("Setting dates")) return(false); //--- Complete GUI creation CWndEvents::CompletedGUI(); return(true); }
Agora, vamos ver no que cada método consiste. Primeiro, nós vamos focar nossa atenção na janela principal da interface. Ele consiste na implementação da guia Analysis feita dos elementos descritos na Fig. 4.
//+------------------------------------------------------------------+ //| Analyze tab | //+------------------------------------------------------------------+ //--- Create the pattern set buttons if(!CreatePatternSet(m_patterns,10,10)) return(false); //--- Timeframe header if(!CreateTFLabel(m_text_labels[1],10,105,0)) return(false); //--- Create the timeframe set buttons if(!CreateTimeframeSet(m_timeframes,10,125,0)) return(false); //--- Field for searching the symbol filter if(!CreateSymbolsFilter(m_symb_filter1,m_request1,10,180,0)) return(false); //--- Create the button for selecting a date range if(!CreateDateRange(m_request3,280,180,0)) return(false); //--- Create the field for entering the profit threshold value if(!CreateThresholdValue(m_threshold1,400,180,100,0)) return(false); //--- Create the symbol table if(!CreateSymbTable(m_symb_table1,10,225,0)) return(false); //--- Create the result table if(!CreateTable1(m_table1,120,225,0)) return(false);
E da guia Settings descrita na Fig. 5.
//+------------------------------------------------------------------+ //| Settings tab | //+------------------------------------------------------------------+ //--- if(!CreateButtonsGroup1(10,50)) return(false); //--- Text labels if(!CreateTextLabel(m_text_labels[0],10,100)) return(false); if(!CreateTextLabel(m_text_labels[3],10,10)) return(false); //--- Input fields if(!CreateCoef(m_coef1,10,140,"K1",1)) return(false); if(!CreateCoef(m_coef2,100,140,"K2",0.5)) return(false); if(!CreateCoef(m_coef3,200,140,"K3",0.25)) return(false); if(!CreateLanguageSetting(m_lang_setting,10,180,1)) return(false); //--- Status bar if(!CreateStatusBar(1,26)) return(false); //--- return(true); }
Uma implementação mais detalhada de cada um dos métodos aplicados que adicionam elementos de interface, pode ser encontrada nos códigos-fonte anexados.
O método que implementa a janela de diálogo para definir uma amostra temporária é o seguinte:
//+---------------------------------------------------------------------------------+ //| Create the dialog window for selecting the range of dates in the Analysis tab | //+---------------------------------------------------------------------------------+ bool CProgram::CreateWindowSetting1(const string caption_text) { //--- Add the window pointer to the window array CWndContainer::AddWindow(m_window[2]); //--- Coordinates int x=m_request3.X(); int y=m_request3.Y()+m_request3.YSize(); //--- Properties m_window[2].XSize(372); m_window[2].YSize(230); m_window[2].WindowType(W_DIALOG); //--- Create the form if(!m_window[2].CreateWindow(m_chart_id,m_subwin,caption_text,x,y)) return(false); //--- if(!CreateCalendar(m_calendar1,m_window[2],10,25,D'01.01.2019',1)) return(false); if(!CreateCalendar(m_calendar2,m_window[2],201,25,m_calendar2.Today(),1)) return(false); //--- if(!CreateTimeEdit(m_time_edit1,m_window[2],10,200,"Time",1)) return(false); if(!CreateTimeEdit(m_time_edit2,m_window[2],200,200,"Time",1)) return(false); //--- return(true); }
Agora, nós vamos voltar nossa atenção para os métodos de busca, estudo e avaliação dos padrões. Para conseguir isso, nós precisamos monitorar toda a sequência de ações do algoritmo. Primeiro, vamos examinar o arquivo MerrillPatterns.mq5 onde esse algoritmo é iniciado.
//--- Include the application class #include "Program.mqh" CProgram program; //+------------------------------------------------------------------+ //| EA inputs | //+------------------------------------------------------------------+ input ENUM_APPLIED_PRICE Inp_Price1 = PRICE_CLOSE; // Applied price input int Inp_ATR_Peroid = 5; // ATR Period input int Inp_CCI_Peroid = 5; // CCI Period input int Inp_DeM_Peroid = 5; // DeMarker Period input int Inp_ForcePeriod = 13; // ForceIndex Period input ENUM_MA_METHOD Inp_ForceMAMethod = MODE_SMA; // ForceIndex MA method input ENUM_APPLIED_PRICE Inp_ForceAppliedPrice = PRICE_CLOSE; // ForceIndex Applied price input ENUM_APPLIED_VOLUME Inp_ForceAppliedVolume = VOLUME_TICK; // ForceIndex Volumes input int Inp_WPR_Period = 5; // WPR Period input int Inp_RSI_Period = 5; // RSI Period //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit(void) { //--- program.OnInitEvent(); //--- Set the trading panel if(!program.CreateGUI()) { ::Print(__FUNCTION__," > Failed to create GUI!"); return(INIT_FAILED); } //--- program.InitializePrice(Inp_Price1); program.InitializeATR(Inp_ATR_Peroid); program.InitializeCCI(Inp_CCI_Peroid); program.InitializeDeM(Inp_DeM_Peroid); program.InitializeForce(Inp_ForcePeriod,Inp_ForceMAMethod,Inp_ForceAppliedPrice,Inp_ForceAppliedVolume); program.InitializeWPR(Inp_WPR_Period); program.InitializeRSI(Inp_RSI_Period); return(INIT_SUCCEEDED); }
Além das entradas do indicador, a busca de uma interface gráfica é realizada na seção OnInit() seguido pela inicialização do conjunto de dados definido na janela de Propriedades. Todos os métodos passam as configurações externas para as variáveis internas.
//--- void InitializePrice(ENUM_APPLIED_PRICE price) { m_applied_price=price; } void InitializeATR(int period) { m_atr_period=period; } void InitializeCCI(int period) { m_cci_period=period; } void InitializeDeM(int period) { m_dem_period=period; } void InitializeWPR(int period) { m_wpr_period=period; } void InitializeRSI(int period) { m_rsi_period=period; } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CProgram::InitializeForce(int period,ENUM_MA_METHOD ma_method,ENUM_APPLIED_PRICE price,ENUM_APPLIED_VOLUME volume) { m_force_period=period; m_force_ma_method=ma_method; m_force_applied_price=price; m_force_applied_volume=volume; } //+-----------------------------------------------------------------
Após isso, o aplicativo está pronto para ser usado, enquanto as configurações restantes são passadas para a GUI criada. Eu já mencionei que a execução do cálculo é realizada escolhendo um símbolo de moeda na tabela de símbolos (pos. 6 na Fig. 4). Ele é realizado também após a definição do "Limiar de tendência" (pos. 3 na Fig. 4). Ambos os eventos iniciam o método ChangeSymbol1() para começar a coleta de dados detectados para prepará-los para a análise.
//+------------------------------------------------------------------+ //| Select a symbol in the Analysis tab | //+------------------------------------------------------------------+ bool CProgram::ChangeSymbol1(const long id) { //--- Check the element ID if(id!=m_symb_table1.Id()) return(false); //--- Exit if the string is not highlighted if(m_symb_table1.SelectedItem()==WRONG_VALUE) { //--- Show full description of a symbol in the status bar m_status_bar.SetValue(0,"Symbol for analysis not selected"); m_status_bar.GetItemPointer(0).Update(true); return(false); } //--- Get a selected symbol string symbol=m_symb_table1.GetValue(0,m_symb_table1.SelectedItem()); //--- Show the full symbol description in the status bar string val=(m_lang_index==0)?"Выбранный символ: ":"Selected symbol: "; m_status_bar.SetValue(0,val+::SymbolInfoString(symbol,SYMBOL_DESCRIPTION)); m_status_bar.GetItemPointer(0).Update(true); //--- GetResult(symbol); return(true); }
A essência de seu trabalho foi definir um símbolo de negociação selecionado da tabela de símbolos e passar o seu valor para a barra de estado e o método GetResult(). Vamos considerar o método em mais detalhes, pois todo o trabalho principal ocorre nele.
//+------------------------------------------------------------------+ //| Handle pattern search results | //+------------------------------------------------------------------+ bool CProgram::GetResult(const string symbol) { //--- Structure for evaluating pattern efficiency RATING_SET m_coef[]; //--- Figure types PATTERN_TYPE pattern_types[]; //--- ArrayResize(pattern_types,33); for(int i=0;i<33;i++) { if(i==16) pattern_types[i]=-1; if(i<16) pattern_types[i]=PATTERN_TYPE(i); if(i>16) pattern_types[i]=PATTERN_TYPE(i-1); } //--- Define selected timeframes GetTimeframes(m_timeframes,m_cur_timeframes); int total=ArraySize(m_cur_timeframes); //--- Check for at least one selected timeframe if(total<1) { if(m_lang_index==0) MessageBox("Вы не выбрали рабочий таймфрейм!","Ошибка",MB_OK); else if(m_lang_index==1) MessageBox("You have not selected working timeframe!","Error",MB_OK); return(false); } int count=0; m_total_row=0; //--- Remove all strings m_table1.DeleteAllRows(); //--- Get date range datetime start=StringToTime(TimeToString(m_calendar1.SelectedDate(),TIME_DATE)+" "+(string)m_time_edit1.GetHours()+":"+(string)m_time_edit1.GetMinutes()+":00"); datetime end=StringToTime(TimeToString(m_calendar2.SelectedDate(),TIME_DATE)+" "+(string)m_time_edit2.GetHours()+":"+(string)m_time_edit2.GetMinutes()+":00"); //--- Check selected dates if(start>end || end>TimeCurrent()) { if(m_lang_index==0) MessageBox("Неправильно выбран диапазон дат!","Ошибка",MB_OK); else if(m_lang_index==1) MessageBox("Incorrect date range selected!","Error",MB_OK); return(false); } //--- for(int k=0;k<33;k++) { if(k==16) continue; //--- Get selected patterns for analysis if(m_patterns[k].IsPressed()) { ArrayResize(m_m_total,total); ArrayResize(m_coef,total); ZeroMemory(m_m_total); ZeroMemory(m_coef); count++; //--- Calculate by timeframes for(int j=0;j<total;j++) { double arr[]; //--- Get data for analysis int copied=GetData(m_buttons_group1.SelectedButtonIndex(),symbol,m_cur_timeframes[j],start,end,arr); //--- if(copied<9) MessageBox("Insufficient data for analysis","Error",MB_OK); for(int i=0;i<copied;i++) { if(i>copied-9) continue; //--- Pattern search condition double A=arr[i]; double B=arr[i+1]; double C=arr[i+2]; double D=arr[i+3]; double E=arr[i+4]; if(GetPatternType(A,B,C,D,E)==pattern_types[k]) { m_m_total[j]++; GetCategory(symbol,i+5,m_coef[j],m_cur_timeframes[j],m_threshold_value1); } } //--- Add the result to the table AddRow(m_table1,m_patterns[k].LabelText(),m_coef[j],m_m_total[j],m_cur_timeframes[j]); } } } //--- if(count>0) { //--- m_table1.DeleteRow(m_total_row); //--- Update the table m_table1.Update(true); m_table1.GetScrollVPointer().Update(true); } else { if(m_lang_index==0) MessageBox("Вы не выбрали паттерн!","Ошибка",MB_OK); else if(m_lang_index==1) MessageBox("You have not chosen a pattern!","Error",MB_OK); } return(true); }
Primeiro, eu preciso explicar os tipos de variáveis inseridas no início do método. O primeiro é a estrutura RATING_SET.
struct RATING_SET { int a_uptrend; int b_uptrend; int c_uptrend; int a_dntrend; int b_dntrend; int c_dntrend; };
Ele contém 6 variáveis do tipo int e ela é responsável para adicionar os dados sobre a frequência com que o preço se move em uma direção especificada após a identificação de um padrão e o quão rápido o preço atinge ela. Por exemplo, suponha que nós temos uma tendência de alta e o limiar de tendência está definido para 100 pontos em 5 dígitos, enquanto o preço estiver dentro desse valor em uma única vela. Nesse caso, a variável a_uptrend recebe o valor igual a um. Se o preço atingir 100 pontos em 2 velas, o valor será passado para a variável b_uptrend. Nós usaremos o array da estrutura m_coef[] em nosso método.
O segundo tipo de variável é a PATTERN_TYPE. Esta é uma enumeração que reúne todos os tipos de padrões de Merrill.
//+------------------------------------------------------------------+ //| Figure type | //+------------------------------------------------------------------+ enum PATTERN_TYPE { M1,M2,M3,M4,M5,M6,M7,M8, M9,M10,M11,M12,M13,M14,M15,M16, W1,W2,W3,W4,W5,W6,W7,W8, W9,W10,W11,W12,W13,W14,W15,W16 };
O array de enumeração pattern_types[] é aplicado ao método Em seguida, temos a verificação — quais períodos gráficos foram selecionados para trabalhar no aplicativo. Esses dados são manipulados pelo método GetTimeframes().
//+------------------------------------------------------------------+ //| Get the array of selected timeframes | //+------------------------------------------------------------------+ void CProgram::GetTimeframes(CButton &buttons[],ENUM_TIMEFRAMES &timeframe[]) { string tf[22]= { "M1","M2","M3","M4","M5","M6","M10","M12","M15","M20","M30", "H1","H2","H3","H4","H6","H8","H12","D1","W1","MN" }; int j=0; ArrayResize(timeframe,22); for(int i=0;i<22;i++) { if(buttons[i].IsPressed()) { timeframe[j]=StringToTimeframe(tf[i]); j++; } } ArrayResize(timeframe,j); }
O método escreve isso no array de período gráfico preliminar m_cur_timeframes[]. Em seguida, obtemos o intervalo de tempo para o trabalho.
Na primeira iteração, nós começamos a verificar através do pressionamento do botão selecionado responsável pelos tipos de padrão e que definem um conjunto de padrões estudados. Na próxima iteração, cada um dos padrões é estudado nos períodos gráficos selecionados antes. Nesse estágio, surge a pergunta: em quais dados os padrões preliminares e as configurações do período gráfico devem ser aplicados. O método GetData() é responsável por isso, já que ele define as configurações definidas na janela de propriedades do EA, bem como o indicador aplicado (pos. 1 na Fig. 5) na guia de configurações do aplicativo.
//+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int CProgram::GetData(int index,string symb,ENUM_TIMEFRAMES tf,datetime start,datetime end,double &arr[]) { //--- int Handle=INVALID_HANDLE,copied; //--- Close price if(index==0) { MqlRates rt[]; ZeroMemory(rt); copied=CopyRates(symb,tf,start,end,rt); ArrayResize(arr,copied); for(int i=0;i<copied;i++) { arr[i]=rt[i].close; if(m_applied_price==PRICE_OPEN) arr[i]=rt[i].open; else if(m_applied_price==PRICE_CLOSE) arr[i]=rt[i].close; else if(m_applied_price==PRICE_HIGH) arr[i]=rt[i].high; else if(m_applied_price==PRICE_LOW) arr[i]=rt[i].low; } return(copied); } //--- ATR if(index==1) Handle=iATR(symb,tf,m_atr_period,m_applied_price); //--- CCI if(index==2) Handle=iCCI(symb,tf,m_cci_period,m_applied_price); //--- DeMarker if(index==3) Handle=iDeMarker(symb,tf,m_dem_period); //--- Force Index if(index==4) Handle=iForce(symb,tf,m_force_period,m_force_ma_method,m_force_applied_volume); //--- WPR if(index==5) Handle=iWPR(symb,tf,m_wpr_period); //--- RSI if(index==6) Handle=iRSI(symb,tf,m_rsi_period,m_applied_price); //--- if(Handle==INVALID_HANDLE) { Print("Failed to get indicator handle"); return(-1); } copied=CopyBuffer(Handle,0,start,end,arr); return(copied); }
Após receber os dados para análise, o algoritmo passa para o método GetPatternType(), ele é usado para buscar todos os padrões definidos anteriormente nos períodos gráficos selecionados.
//+------------------------------------------------------------------+ //| Define the patterns | //+------------------------------------------------------------------+ PATTERN_TYPE CProgram::GetPatternType(double A,double B,double C,double D,double E) { //--- M1 if(B>A && A>D && D>C && C>E) return(M1); //--- M2 if(B>A && A>D && D>E && E>C) return(M2); //--- M3 if(B>D && D>A && A>C && C>E) return(M3); //--- M4 if(B>D && D>A && A>E && E>C) return(M4); //--- M5 if(D>B && B>A && A>C && C>E) return(M5); //--- M6 if(D>B && B>A && A>E && E>C) return(M6); //--- M7 if(B>D && D>C && C>A && A>E) return(M7); //--- M8 if(B>D && D>E && E>A && A>C) return(M8); //--- M9 if(D>B && B>C && C>A && A>E) return(M9); //--- M10 if(D>B && B>E && E>A && A>C) return(M10); //--- M11 if(D>E && E>B && B>A && A>C) return(M11); //--- M12 if(B>D && D>C && C>E && E>A) return(M12); //--- M13 if(B>D && D>E && E>C && C>A) return(M13); //--- M14 if(D>B && B>C && C>E && E>A) return(M14); //--- M15 if(D>B && B>E && E>C && C>A) return(M15); //--- M16 if(D>E && E>B && B>C && C>A) return(M16); //--- W1 if(A>C && C>B && B>E && E>D) return(W1); //--- W2 if(A>C && C>E && E>B && B>D) return(W2); //--- W3 if(A>E && E>C && C>B && B>D) return(W3); //--- W4 if(A>C && C>E && E>D && D>B) return(W4); //--- W5 if(A>E && E>C && C>D && D>B) return(W5); //--- W6 if(C>A && A>B && B>E && E>D) return(W6); //--- W7 if(C>A && A>E && E>B && B>D) return(W7); //--- W8 if(E>A && A>C && C>B && B>D) return(W8); //--- W9 if(C>A && A>E && E>D && D>B) return(W9); //--- W10 if(E>A && A>C && C>D && D>B) return(W10); //--- W11 if(C>E && E>A && A>B && B>D) return(W11); //--- W12 if(E>C && C>A && A>B && B>D) return(W12); //--- W13 if(C>E && E>A && A>D && D>B) return(W13); //--- W14 if(E>C && C>A && A>D && D>B) return(W14); //--- W15 if(C>E && E>D && D>A && A>B) return(W15); //--- W16 if(E>C && C>D && D>A && A>B) return(W16); return(-1); }
Ao detectar o padrão, ele é avaliado usando o método GetCategory(). O array de estrutura do tipo RATING_SET, que foi definido anteriormente, é utilizado aqui.
//+------------------------------------------------------------------+ //| Define the profit categories | //+------------------------------------------------------------------+ bool CProgram::GetCategory(const string symbol,const int shift,RATING_SET &rate,ENUM_TIMEFRAMES timeframe,int threshold) { MqlRates rt[]; datetime start=StringToTime(TimeToString(m_calendar1.SelectedDate(),TIME_DATE)+" "+(string)m_time_edit1.GetHours()+":"+(string)m_time_edit1.GetMinutes()+":00"); start+=PeriodSeconds(timeframe)*shift; int copied=CopyRates(symbol,timeframe,start,4,rt); //--- Get the data of previous candles if(copied<4) return(false); double high1,high2,high3,low1,low2,low3,close0,point; close0=rt[0].close; high1=rt[1].high; high2=rt[2].high; high3=rt[3].high; low1=rt[1].low; low2=rt[2].low; low3=rt[3].low; if(!SymbolInfoDouble(symbol,SYMBOL_POINT,point)) return(false); //--- Check for Uptrend if((int)((high1-close0)/point)>=threshold) { rate.a_uptrend++; } else if((int)((high2-close0)/point)>=threshold) { rate.b_uptrend++; } else if((int)((high3-close0)/point)>=threshold) { rate.c_uptrend++; } //--- Check for Downtrend if((int)((close0-low1)/point)>=threshold) { rate.a_dntrend++; } else if((int)((close0-low2)/point)>=threshold) { rate.b_dntrend++; } else if((int)((close0-low3)/point)>=threshold) { rate.c_dntrend++; } return(true); }
Os dados de avaliação tratados são passados para o método AddRow(), que calcula os valores da probabilidade e das taxas de eficiência, fazendo a adição deles à tabela de resultados.
//+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ void CProgram::AddRow(CTable &table,string pattern_name,RATING_SET &rate,int found,ENUM_TIMEFRAMES timeframe) { int row=m_total_row; double p1,p2,k1,k2; int sum1=0,sum2=0; sum1=rate.a_uptrend+rate.b_uptrend+rate.c_uptrend; sum2=rate.a_dntrend+rate.b_dntrend+rate.c_dntrend; //--- p1=(found>0)?(double)sum1/found*100:0; p2=(found>0)?(double)sum2/found*100:0; k1=(found>0)?(m_k1*rate.a_uptrend+m_k2*rate.b_uptrend+m_k3*rate.c_uptrend)/found:0; k2=(found>0)?(m_k1*rate.a_dntrend+m_k2*rate.b_dntrend+m_k3*rate.c_dntrend)/found:0; //--- table.AddRow(row); table.SetValue(0,row,pattern_name); table.SetValue(1,row,(string)found); table.SetValue(2,row,TimeframeToString(timeframe)); table.SetValue(3,row,DoubleToString(p1,2),2); table.SetValue(4,row,DoubleToString(p2,2),2); table.SetValue(5,row,DoubleToString(k1,2),2); table.SetValue(6,row,DoubleToString(k2,2),2); ZeroMemory(rate); m_total_row++; }
Para eliminar as possíveis perguntas relacionadas ao uso do aplicativo, o vídeo abaixo exibe os exemplos de cálculos com diferentes configurações.
Recomendações para o teste dos padrões de Merrill:
- Para permitir que o aplicativo funcione corretamente, nós precisamos dos dados históricos baixados para testar o símbolo de negociação selecionado.
- Não é recomendável fazer o download de todos os padrões e períodos gráficos ao mesmo tempo, pois o tratamento dos resultados pode demorar muito tempo.
- Os cenários mais comuns que podem causar dificuldades são acompanhados de dicas. Esses cenários incluem a não definição do período gráfico ou padrão, além de uma data inválida.
- Tenha cuidado ao definir as propriedades do EA (Fig. 6). Se as configurações não estiverem claras, releia o artigo.
- Neste artigo, o tema sobre o método de cálculo da eficiência de padrão foi discutido duas vezes Aqui, fornecemos o link para o artigo que aborda em detalhes o tópico. Lembre-se de que você precisa entender claramente como os coeficientes de ponderação na guia configurações afetam a avaliação dos padrões.
Conclusão
O arquivo anexado abaixo contém todos os arquivos descritos, que foram organizados em pastas correspondentes. Para uma execução correta do aplicativo, coloque a pasta MQL5 para o diretório raiz do terminal. Para abrir o diretório raiz do terminal, onde a pasta MQL5 está localizada, pressione a combinação de teclas Ctrl+Shift+D na plataforma MetaTrader 5 ou use o menu de contexto como é exibido na Fig. 7 abaixo.
Fig. 7. Abrindo a pasta MQL5 no diretório raiz da plataforma MetaTrader 5
Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/7022
- 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