Desenhando emissões de indicador no MQL5
Sergey Pavlov | 30 dezembro, 2013
Introdução
Com certeza, muitos comerciantes e desenvolvedores de estratégias de comércio estão interessados nestas questões:- Como os movimentos fortes de mercado estão emergindo?
- Como determinar a direção atual das mudanças futuras?
- Como abrir uma posição lucrativa para o comércio?
- Como fechar uma posição com lucro máximo?
Achar as respostas para estas perguntas me levou à criação de uma nova aproximação à pesquisa de mercado: construção e análise de de emissões do indicador. Para deixar mais claro, dê uma olhada nas figuras a seguir:
Fig. 1 Emissão do indicador DCMV
Fig. 2. Emissão do indicador baseada em envelopes iMA
Ela mostra a emissão de indicadores diferentes mas o princípio da sua construção é o mesmo. Mais e mais pontos com cores e formatos diferentes aparecem depois de cada marcação. Eles formam vários clusters na forma de uma nebulosa, nuvens, pistas, linhas, arcos, etc. Estas formas podem ajudar a detectar as molas e forças invisíveis que afetam o movimento dos preços do mercado. A pesquisa e análise destas emissões são como quiromancia.
Emissão e suas propriedades
A emissão é um conjunto de pontos, localizados nos pontos de intersecção de linhas específicas do indicador.
As propriedades das emissões ainda não foram esclarecidas, elas ainda estão esperando pelas pesquisas. Aqui está uma lista das propriedades conhecidas:
- Os pontos de mesmo tipo tendem a se agrupar;
- A emissão tem uma direção - do presente para o futuro ou para o passado;
- Os clusters são importantes - os clusters densos podem atrair ou, pelo contrário, repelir o preço.
Cálculo da emissão do indicador
Vamos considerar os fundamentos do cálculo de emissão usando um exemplo. Vamos pegar dois indicadores - iBands e iMA - e descobrir as intersecção das suas linhas. Nós os usaremos para desenhar os pontos de emissão. Para isso precisaremos objetos gráficos. O algoritmo é implementado para conselheiros experientes mas pode ser feito nos indicadores.
Os indicadores iniciais são apresentados na Fig. 3.:
Fig. 3. Os indicadores iBands (verde) e iMA (vermelho)
Precisamos um conselheiro experiente para criar os pontos de emissão. é melhor usar o assistente do MQL5 para criar um modelo de conselheiro experiente.
Fig. 4. Criando um modelo de conselheiro experiente usando o assistente do MQL5
//+------------------------------------------------------------------+ //| Emission of Bands && MA.mq5 | //| Copyright DC2008 | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "DC2008" #property link "https://www.mql5.com" #property version "1.00" //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- //--- return(0); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- } //+------------------------------------------------------------------+
Primeiro, precisamos algumas tramas auxiliares. Precisamos continuar as linhas do indicador usando raios (Fig. 5.). Isto permitirá controlar a exatidão do cálculo e visualização dos pontos de emissão. Depois, removeremos estas linhas do gráfico.
Fig. 5. Tramas auxiliares. Continuação das linhas do indicador usando raios
Então, vamos adicionar os objetos gráficos (linhas horizontais e inclinadas) ao código do nosso Expert Advisor.
input bool H_line=true; // flag to enable drawing of the horizontal lines input bool I_line=true; // flag to enable drawing of the indicator's lines //--- string name; //---- indicator buffers double MA[]; // array for iMA indicator double BBH[]; // array for iBands indicator - UPPER_BAND double BBL[]; // array for iBands indicator - LOWER_BAND double BBM[]; // array for iBands indicator - BASE_LINE datetime T[]; // array for time coordinates //---- handles for indicators int MAHandle; // iMA indicator handle int BBHandle; // iBands indicator handle //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- MAHandle=iMA(Symbol(),0,21,0,MODE_EMA,PRICE_CLOSE); BBHandle=iBands(Symbol(),0,144,0,2,PRICE_CLOSE); //--- if(H_line) // Horizontal lines of iBands indicator { //--- iBands - UPPER_BAND name="Hi"; ObjectCreate(0,name,OBJ_HLINE,0,0,0); ObjectSetInteger(0,name,OBJPROP_COLOR,Red); ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_DOT); ObjectSetInteger(0,name,OBJPROP_WIDTH,1); //--- iBands - LOWER_BAND name="Lo"; ObjectCreate(0,name,OBJ_HLINE,0,0,0); ObjectSetInteger(0,name,OBJPROP_COLOR,Blue); ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_DOT); ObjectSetInteger(0,name,OBJPROP_WIDTH,1); //--- iBands - BASE_LINE name="MIDI"; ObjectCreate(0,name,OBJ_HLINE,0,0,0); ObjectSetInteger(0,name,OBJPROP_COLOR,DarkOrange); ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_DOT); ObjectSetInteger(0,name,OBJPROP_WIDTH,1); } //--- if(I_line) // Indicator lines { //--- iMA name="MA"; ObjectCreate(0,name,OBJ_TREND,0,0,0,0); ObjectSetInteger(0,name,OBJPROP_COLOR,Red); ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_SOLID); ObjectSetInteger(0,name,OBJPROP_WIDTH,2); ObjectSetInteger(0,name,OBJPROP_RAY_RIGHT,1); ObjectSetInteger(0,name,OBJPROP_RAY_LEFT,1); //--- iBands - UPPER_BAND name="BH"; ObjectCreate(0,name,OBJ_TREND,0,0,0,0); ObjectSetInteger(0,name,OBJPROP_COLOR,MediumSeaGreen); ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_SOLID); ObjectSetInteger(0,name,OBJPROP_WIDTH,1); ObjectSetInteger(0,name,OBJPROP_RAY_RIGHT,1); ObjectSetInteger(0,name,OBJPROP_RAY_LEFT,1); //--- iBands - LOWER_BAND name="BL"; ObjectCreate(0,name,OBJ_TREND,0,0,0,0); ObjectSetInteger(0,name,OBJPROP_COLOR,MediumSeaGreen); ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_SOLID); ObjectSetInteger(0,name,OBJPROP_WIDTH,1); ObjectSetInteger(0,name,OBJPROP_RAY_RIGHT,1); ObjectSetInteger(0,name,OBJPROP_RAY_LEFT,1); //--- iBands - BASE_LINE name="BM"; ObjectCreate(0,name,OBJ_TREND,0,0,0,0); ObjectSetInteger(0,name,OBJPROP_COLOR,MediumSeaGreen); ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_SOLID); ObjectSetInteger(0,name,OBJPROP_WIDTH,1); ObjectSetInteger(0,name,OBJPROP_RAY_RIGHT,1); ObjectSetInteger(0,name,OBJPROP_RAY_LEFT,1); } return(0); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- filling the arrays with current values CopyBuffer(MAHandle,0,0,2,MA); ArraySetAsSeries(MA,true); CopyBuffer(BBHandle,0,0,2,BBM); ArraySetAsSeries(BBM,true); CopyBuffer(BBHandle,1,0,2,BBH); ArraySetAsSeries(BBH,true); CopyBuffer(BBHandle,2,0,2,BBL); ArraySetAsSeries(BBL,true); CopyTime(Symbol(),0,0,10,T); ArraySetAsSeries(T,true); //--- Horizontal lines of iBands indicator (correction) if(H_line) { name="Hi"; ObjectSetDouble(0,name,OBJPROP_PRICE,BBH[0]); name="Lo"; ObjectSetDouble(0,name,OBJPROP_PRICE,BBL[0]); name="MIDI"; ObjectSetDouble(0,name,OBJPROP_PRICE,BBM[0]); } //--- Indicator's lines (correction) if(I_line) { name="MA"; //--- iMA ObjectSetInteger(0,name,OBJPROP_TIME,T[1]); ObjectSetDouble(0,name,OBJPROP_PRICE,MA[1]); ObjectSetInteger(0,name,OBJPROP_TIME,1,T[0]); ObjectSetDouble(0,name,OBJPROP_PRICE,1,MA[0]); name="BH"; //--- iBands - UPPER_BAND ObjectSetInteger(0,name,OBJPROP_TIME,T[1]); ObjectSetDouble(0,name,OBJPROP_PRICE,BBH[1]); ObjectSetInteger(0,name,OBJPROP_TIME,1,T[0]); ObjectSetDouble(0,name,OBJPROP_PRICE,1,BBH[0]); name="BL"; //--- iBands - LOWER_BAND ObjectSetInteger(0,name,OBJPROP_TIME,T[1]); ObjectSetDouble(0,name,OBJPROP_PRICE,BBL[1]); ObjectSetInteger(0,name,OBJPROP_TIME,1,T[0]); ObjectSetDouble(0,name,OBJPROP_PRICE,1,BBL[0]); name="BM"; //--- iBands - BASE_LINE ObjectSetInteger(0,name,OBJPROP_TIME,T[1]); ObjectSetDouble(0,name,OBJPROP_PRICE,BBM[1]); ObjectSetInteger(0,name,OBJPROP_TIME,1,T[0]); ObjectSetDouble(0,name,OBJPROP_PRICE,1,BBM[0]); } } //+------------------------------------------------------------------+Já que a emissão continua para o passado e para o futuro, as propriedades da linha inclinada devem ser as seguintes:
- OBJPROP_RAY_LEFT = 1, (Raio vai para a esquerda);
- OBJPROP_RAY_RIGHT = 1, (Raio vai para a direita).
Como resultado, o gráfico com as linhas adicionais se apresentará como exibido na Fig. 6.
A fase preparatória está completa, agora vamos prosseguir com a emissão. Vamos criar as primeiras séries de pontos na intersecção das seguintes linhas:
- Entre a linha "MA" (iMA) e linha "BH" (iBands = UPPER_BAND);
- Entre a linha "MA" (iMA) e linha "BL" (iBands = LOWER_BAND);
- Entre a linha "MA" (iMA) e linha "BM" (iBands = BASE_BAND).
Fig. 6. Tramas auxiliares. Continuação das linhas do indicador usando linhas retas
Agora é hora de calcular as coordenadas de intersecção para desenhar os pontos da emissão. Vamos criar a função:
void Draw_Point( string P_name, // Object name (OBJ_ARROW) double P_y1, // Y-coordinate of the 1st line at the [1] bar double P_y0, // Y-coordinate of the 1st line at the [0] bar double P_yy1, // Y-coordinate of the 2nd line at the [1] bar double P_yy0, // Y-coordinate of the 2nd line at the [0] bar char P_code1, // Char at the right side of the [0] bar char P_code2, // Char at the left side of the [0] bar color P_color1, // Color of point at the right side of the [0] bar color P_color2 // color of point at the left side of the [0] bar ) { double P,X; datetime P_time; if(MathAbs((P_yy0-P_yy1)-(P_y0-P_y1))>0) { P=P_y1+(P_y0-P_y1)*(P_y1-P_yy1)/((P_yy0-P_yy1)-(P_y0-P_y1)); X=(P_y1-P_yy1)/((P_yy0-P_yy1)-(P_y0-P_y1)); if(X>draw_period) { P_time=T[0]+(int)(X*PeriodSeconds()); ObjectCreate(0,P_name,OBJ_ARROW,0,0,0); ObjectSetDouble(0,P_name,OBJPROP_PRICE,P); ObjectSetInteger(0,P_name,OBJPROP_TIME,P_time); ObjectSetInteger(0,P_name,OBJPROP_WIDTH,0); ObjectSetInteger(0,P_name,OBJPROP_ARROWCODE,P_code1); ObjectSetInteger(0,P_name,OBJPROP_COLOR,P_color1); if(X<0) { ObjectSetInteger(0,P_name,OBJPROP_ARROWCODE,P_code2); ObjectSetInteger(0,P_name,OBJPROP_COLOR,P_color2); } } } }
E adicionar as seguintes linhas de código à função OnTick:
//+------------------------------------------------------------------+ int GTC=GetTickCount(); //+------------------------------------------------------------------+ name="H"+(string)GTC; Draw_Point(name,BBH[1],BBH[0],MA[1],MA[0],170,178,Red,Red); name="L"+(string)GTC; Draw_Point(name,BBL[1],BBL[0],MA[1],MA[0],170,178,Blue,Blue); name="M"+(string)GTC; Draw_Point(name,BBM[1],BBM[0],MA[1],MA[0],170,178,Green,Green); //--- ChartRedraw(0);
Agora vamos executar o Expert Advisor e ver o resultado. (Fig. 7.)
É bom, mas existem alguns outros casos de intersecção que nós não consideramos. Por exemplo, o indicador iBands tem três linhas que se cruzam e podem complementar o quadro geral.
Fig. 7. A emissão dos indicadores iMA e iBands (3 intersecções)
Agora, vamos tentar adicionar outra série de pontos na emissão calculada, a intersecção entre as seguintes linhas:- Entre a linha "BH" (iBands = UPPER_BAND) e a linha "BL" (iBands = LOWER_BAND);
- Entre a linha "BH" (iBands = UPPER_BAND) e a linha "BM" (iBands = BASE_BAND);
- Entre a linha "BL" (iBands = LOWER_BAND) e linha "BM" (iBands = BASE_BAND).
Devido a essas intersecções, nós conseguiríamos 3 pontos mas todos eles têm as mesmas coordenadas. Então, é suficiente usar uma única intersecção, entre a linha "BH" e "BL".
Vamos adicionar estas linhas do código ao nosso Expert Advisor e ver o resultado. (Fig. 8.)
name="B"+(string)GTC; Draw_Point(name,BBH[1],BBH[0],BBL[1],BBL[0],170,178,Magenta,Magenta);
Fig. 8. Emissão dos indicadores iMA e iBands (4 intersecções)
Então, conseguimos a emissão mas há uma sensação de que esquecemos de algo importante. Todavia, o que esquecemos?
Porquê usamos tais parâmetros de entrada? O que conseguiremos se os modificarmos? E, afinal, qual o papel deles nas emissões?
Certo, a emissão que conseguimos corresponde a uma frequência simples, resultante dos parâmetros de entrada do indicador. Para calcular o espectro total de multi-frequência será necessário executar os mesmos cálculos para outras frequências. Como um exemplo, aqui está a minha versão do espectro de emissão possível:
//---- handles for indicators int MAHandle[5]; // handles array of iMA indicators int BBHandle[7]; // handles array of iBands indicator //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- MAHandle[0]=iMA(NULL,0,21,0,MODE_EMA,PRICE_CLOSE); MAHandle[1]=iMA(NULL,0,34,0,MODE_EMA,PRICE_CLOSE); MAHandle[2]=iMA(NULL,0,55,0,MODE_EMA,PRICE_CLOSE); MAHandle[3]=iMA(NULL,0,89,0,MODE_EMA,PRICE_CLOSE); MAHandle[4]=iMA(NULL,0,144,0,MODE_EMA,PRICE_CLOSE); //--- BBHandle[0]=iBands(NULL,0,55,0,2,PRICE_CLOSE); BBHandle[1]=iBands(NULL,0,89,0,2,PRICE_CLOSE); BBHandle[2]=iBands(NULL,0,144,0,2,PRICE_CLOSE); BBHandle[3]=iBands(NULL,0,233,0,2,PRICE_CLOSE); BBHandle[4]=iBands(NULL,0,377,0,2,PRICE_CLOSE); BBHandle[5]=iBands(NULL,0,610,0,2,PRICE_CLOSE); BBHandle[6]=iBands(NULL,0,987,0,2,PRICE_CLOSE); //--- return(0); }
Para considerar todas as combinações possíveis, vamos adicionar o seguinte código ao Expert Advisor:
//+------------------------------------------------------------------+ CopyTime(NULL,0,0,10,T); ArraySetAsSeries(T,true); int GTC=GetTickCount(); //+------------------------------------------------------------------+ int iMax=ArraySize(BBHandle)-1; int jMax=ArraySize(MAHandle)-1; for(int i=0; i<iMax; i++) { for(int j=0; j<jMax; j++) { //--- filling the arrays with current values CopyBuffer(MAHandle[j],0,0,2,MA); ArraySetAsSeries(MA,true); CopyBuffer(BBHandle[i],0,0,2,BBM); ArraySetAsSeries(BBM,true); CopyBuffer(BBHandle[i],1,0,2,BBH); ArraySetAsSeries(BBH,true); CopyBuffer(BBHandle[i],2,0,2,BBL); ArraySetAsSeries(BBL,true); name="H"+(string)GTC+(string)i+(string)j; Draw_Point(name,BBH[1],BBH[0],MA[1],MA[0],250,158,Aqua,Aqua); name="L"+(string)GTC+(string)i+(string)j; Draw_Point(name,BBL[1],BBL[0],MA[1],MA[0],250,158,Blue,Blue); name="M"+(string)GTC+(string)i+(string)j; Draw_Point(name,BBM[1],BBM[0],MA[1],MA[0],250,158,Green,Green); name="B"+(string)GTC+(string)i+(string)j; Draw_Point(name,BBH[1],BBH[0],BBL[1],BBL[0],250,158,Magenta,Magenta); } } //--- ChartRedraw(0);
Quanto mais frequências forem envolvidas no espectro de emissão melhor a figura ficará no gráfico mas você não deve abusar - esta é a forma mais simples de exaurir os recursos do computador e criar o caos no gráfico. O número de frequências pode ser determinado de forma experimental. Para uma percepção melhor dos gráficos, devemos prestar atenção especial ao estilo do desenho.
Fig. 9. Espectro de emissão de multi-frequência
Dos estilos de desenho de emissão
A linguagem MQL5 fornece uma ampla gama de Cores da web e Caracteres de curva para a emissão de desenhos. Eu gostaria de compartilhar os meus pensamentos sobre isso.- Cada pessoa tem sua própria percepção de imagens de gráficos, então você precisará de algum tempo para personalizar as emissões.
- O "caos" na Fig. 9 não permite reconhecer nenhuma regularidade ou padrão nas imagens. Este é um exemplo de desenho ruim.
- Tente usar cores vizinhas no espectro do arco-íris.
- Os códigos de caracteres para o passado (do lado esquerdo da barra [0]) e para o futuro (do lado direito da barra [0]) devem ser diferentes.
- A combinação bem sucedida de cores e formas de pontos pode transformar a emissão em obras primas, que não apenas ajudarão no comércio mas também darão prazer aos olhos.
name="H"+(string)GTC+(string)i+(string)j; Draw_Point(name,BBH[1],BBH[0],MA[1],MA[0],250,158,Aqua,Aqua); name="L"+(string)GTC+(string)i+(string)j; Draw_Point(name,BBL[1],BBL[0],MA[1],MA[0],250,158,Blue,Blue); name="M"+(string)GTC+(string)i+(string)j; Draw_Point(name,BBM[1],BBM[0],MA[1],MA[0],250,158,Magenta,Magenta); name="B"+(string)GTC+(string)i+(string)j; Draw_Point(name,BBH[1],BBH[0],BBL[1],BBL[0],250,158,DarkOrchid,DarkOrchid);
A galeria de emissões iMA e iBands
As imagens com estas emissões são apresentadas neste capítulo.
Fig. 10
Fig. 11
Fig. 12
Fig. 13
Fig. 14
Fig. 15
Fig. 16
Fig. 17
Análise de emissão
A análise de emissões é uma tarefa separada. A coisa mais útil é olhar para a sua dinâmica em tempo real, é a melhor maneira de entender muitos efeitos e padrões.
Preste atenção às correções de preços - parece que a emissão "sabe" o preço alvo. Além disso, você pode ver os níveis de preço de suporte, resistência e equilíbrio.
Conclusão
- As emissões dos indicadores podem ser interessantes para comerciantes e desenvolvedores de sistemas de comércio que procuram abordagens novas na pesquisa e análise de mercado.
- Como um artigo introdutório, ele não contém as soluções prontas. Entretanto, a tecnologia apresentada para o cálculo de emissão pode ser aplicada em outros indicadores ou suas combinações.
- Preparando este artigo, eu juntei mais dúvidas que respostas. Aqui estão algumas delas: como otimizar o algoritmo do desenho de emissão; qual o papel das características do espectro de emissão na estrutura da emissão; como usar as emissões no comércio automatizado?