Desenhando emissões de indicador no MQL5

30 dezembro 2013, 11:23
Sergey Pavlov
0
1 043

Introdução

Com certeza, muitos comerciantes e desenvolvedores de estratégias de comércio estão interessados nestas questões:

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.
  1. 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.
  2. O "caos" na Fig. 9 não permite reconhecer nenhuma regularidade ou padrão nas imagens. Este é um exemplo de desenho ruim.
  3. Tente usar cores vizinhas no espectro do arco-íris.
  4. 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.
  5. 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.
Como exemplo, aqui está a minha versão de estilo de desenho para a emissão (consulte Figuras 10-17):
         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

  1. 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.
  2. 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.
  3. 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?

Traduzido do russo pela MetaQuotes Software Corp.
Artigo original: https://www.mql5.com/ru/articles/26

Troca de dados entre indicadores: é fácil! Troca de dados entre indicadores: é fácil!

Queremos criar um ambiente que fornecesse acesso aos dados de indicadores anexos ao gráfico e que teria as seguintes propriedades: ausência de cópia de dados; modificação mínima do código dos métodos disponíveis, se precisarmos usá-los; preferencialmente código MQL (claro, temos que usar o DLL, mas usaremos apenas algumas strings do código C++). O artigo descreve um método fácil para desenvolver um ambiente de programa para o terminal MetaTrader, que poderia fornecer meios para acessar os buffers dos indicadores de outros programas MQL.

Como trocar dados: um DLL para o MQL5 em 10 minutos Como trocar dados: um DLL para o MQL5 em 10 minutos

Agora, não muitos desenvolvedores lembram como escrever um simples DLL e quais são os recursos especiais da diferente ligação do sistema. Usando vários exemplos, vou tentar mostrar todo o processo da criação de um simples DLL em 10 minutos, bem como discutir alguns detalhes técnicos da nossa implementação de ligação. Mostrarei o processo passo-a-passo da criação de DLL no Visual Studio com exemplos de troca de diferentes tipos de variáveis (números, arrys, strings, etc.). Além disso, explicarei como proteger seu terminal do cliente de travamentos nos DLLs personalizados.

Como exportar cotações do MetaTrader5 para aplicações .NET usando serviços WCF Como exportar cotações do MetaTrader5 para aplicações .NET usando serviços WCF

Quer organizar a exportação de cotas do MetaTrader 5 para sua própria aplicação? A junção MQL5-DLL permite criar essas soluções! Este artigo mostrará a você um dos meios de exportação de cotas do MetaTrader 5 para aplicações escritas no .NET. Para mim, é mais interessante, racional e fácil implementar a exportação de cotas usando esta mesma plataforma. Infelizmente, a versão 5 ainda não suporta .NET, então, como antigamente, usaremos o win32 dll com suporte .NET como intercamada.

Implementação prática dos filtros digitais no MQL5 para principiantes Implementação prática dos filtros digitais no MQL5 para principiantes

A ideia da filtragem de sinal digital foi amplamente discutida em tópicos de fóruns sobre a construção dos sistemas de negócio. E seria imprudente não criar um código padrão de filtros digitais no MQL5. Neste artigo, o autor descreve a transformação de um simples código do indicador SMA em seu artigo "Indicadores personalizados no MQL5 para iniciantes" em um código do mais complicado e universal filtro digital. Este artigo é uma sequência lógica do artigo anterior. Ele também fala como substituir o texto no código e como corrigir erros de programação.