English Русский 中文 Español Deutsch 日本語
Algoritmos de média eficiente com lag mínimo: Uso em indicadores

Algoritmos de média eficiente com lag mínimo: Uso em indicadores

MetaTrader 4Exemplos | 18 fevereiro 2016, 16:17
1 032 0
Nikolay Kositsin
Nikolay Kositsin

Introdução

Eu acredito que não é necessário explicar a importância dos algoritmos de nivelamento para as análises técnicas e para os sistemas comerciais. Os códigos de praticamente todos os indicadores contém algoritmos de cálculo de média explícitos ou implícitos. Se nós observarmos as plataformas comerciais online e dos terminais de clientes com atenção, veremos que a maioria deles e a maior parte dos indicadores usam os algoritmos mais simples (mas não os mais eficientes) de cálculo de média.

Algoritmos de cálculo de média muito mais eficientes foram desenvolvidos por mim. Contudo, devido à significativa complexidade destes algoritmos, tentativas de aplicá-los a indicadores resultaram, de modo geral, no esgotamento da paciência dos programadores, que criaram no máximo um ou dois indicadores, que nem sempre operavam corretamente. Diante disso, eles geralmente se cansam de trabalhar dessa maneira. A vantagem básica das médias simples é que elas estão sempre disponíveis como funções personalizadas simples que podem ser aplicadas em qualquer lugar e a qualquer hora.


Tema

Nesse artigo, eu gostaria de descrever aos traders que conhecem o MQL4 algoritmos de cálculo de média bastante eficientes e com atraso mínimo, representados como funções personalizadas simples. O uso dessas funções não é muito mais complicado dos que o dos indicadores técnicos. As funções foram escritas há muito tempo e a sua qualidade de operação também vem sendo verificada há bastante tempo. Nelas não foram encontradas falhas, problemas ou cálculos incorretos. Assim, iremos considerar os seguintes algoritmos:
- JJMASeries () - algoritmo de nivelamento JMA adaptativo;
- JLiteSeries() - JMA algoritmo de nivelamento sem um algoritmo adaptativo;
- JurXSeries () - algoritmo de nivelamento ultralinear tomado do indicador JRSX;
- ParMASeries() - algoritmo de nivelamento baseado em aproximação parabólica;
- LRMASeries () - algoritmo de nivelamento baseado em regressão linear;
- T3Series () - algoritmo de nivelamento baseado no algoritmo Tilson.

Realização das funções de nivelamento

As funções são representadas sob a forma dos seguintes arquivos: JJMASeries.mqh, JLiteSeries. mqh, JurXSeries. mqh, ParMASeries.mqh, LRMASeries.mqh, T3Series.mqh.

As chamadas de função em si são absolutamente iguais, a única diferença é que algumas funções não possuem algumas variáveis externas. Tais funções são normalmente utilizadas para processar matrizes padrão e de indicadores, que operam como variáveis externas. Na minha opinião, isso nem sempre é conveniente, então seria muito melhor usar tais funções para processar variáveis normais, e não matrizes. Nesse caso, poderia-se realizar uma quantidade ilimitada de nivelamentos através do uso desses algoritmos durante um ciclo de computação! Eu considero desnecessário fornecer o código das funções desse artigo. O código só seria interessante àqueles que irão criar funções semelhantes com base em outros algoritmos. Nós estamos interessados apenas no algoritmo de chamada de função do código indicador, ou seja, no uso prático das funções;

JJMASeries ()
Começaremos a aprender sobre isso com a função JJMASeries():

double JJMASeries(int number, int din, int MaxBar, int limit, 
                  int Phase, int Length, double series, int bar,
                  int& reset)

O arquivo JJMASeries.mqh contém quatro funções: JJMASeries(), JJMASeriesResize(), JJMASeriesAlert() e JMA_ErrDescr(). O arquivo também contém variáveis declaradas como globais.


A função JJMASeries() é projetada para o uso do algoritmo JMA na escrita de quaisquer indicadores técnicos ou expert advisors, e para a subsituição do nivelamento clássico de computação com esse algoritmo. A função não irá operar se o parâmetro "limite" assumir o valor de zero! Todos os indicadores que eu desenvolvi para JJMASeries foram feitos considerando essa limitação. O arquivo deverá ser salvo na pasta MetaTrader\experts\include\. Deve-se notar que, se o valor da variável "de barra" exceder o valor da variável MaxBar, a função JJMASeries() irá devolver um valor de zero para esta barra! E, portanto, esse valor pode não estar presente como um termo de uma fração em alguns cálculos do indicador! JJMASeries() irá também devolver um zero nas 30 barras consequentes.

Essa versão do JJMASeries() suporta expert advisors quando operada nos indicadores personalizados usados pelo expert advisor. Além disso, essa versão do JJMASeries() suporta expert advisors quando operada no código indicador inteiramente situado no código do expert, mantendo todas as homologações e variáveis DO salvas! Ao codificar indicadores ou expert advisors usando o JJMASeries, não é recomendável nomear variáveis com nomes que comecem com nJMA... ou dJMA... . A função JJMASeries() pode ser usada no código interno de outras funções personalizadas contanto que se considere que toda chamada para o JJMASeries() deve ter um número exclusivo em cada chamada para uma função personalizada. Essa versão do JJMASeries() é projetada para processar variáveis relacionadas a matrizes de séries de tempo do gráfico atual. Se essa função for aplicada ao processamento de variáveis computadas em matrizes de séries de tempo de outros gráficos, os cálculos serão incorretos!

Entradas:
- número - o número da função JJMASeries() chama o código do indicador (0, 1, 2, 3, ...);
- din - parâmetro que permite a modificação dos parâmetros de comprimento e fase em cada barra. 0 - os parâmetros não podem ser modificados, qualquer outro valor permite a mudança de parâmetros;
- MaxBar - valor máximo do número de barra computado. Normalmente, é Bars-1-period (barras-1-período), sendo que o "período" é a quantidade de barras, nas quais o valor da série inicial não é calculado;
- limite - quantidade de barras não calculadas mais um ou o número da última barra não calculada. Ela deve ser igual a Bars-IndicatorCounted()-1 (barras contadas pelo indicador);
- Comprimento - profundidade média;
- Fase - mudança de parâmetro na faixa entre -100 e +100. Ela influencia a qualidade do processo transitório;
- series - entrada que sustenta o cálculo do JJMASeries();
- barra - o número de barra a ser calculado. Esse parâmetro deve ser modificado pela afirmação DO do valor máximo até zero. O seu valor máximo deve ser sempre igual ao valor do "limite"!


Parâmetros de saída:
- JMASeries() - valor JMA. Se o valor do parâmetro "barra" exceder MaxBar-30, a função JJMASeries() sempre devolve zero!
- reset - parâmetro que devolve por referência um valor diferente de 0 caso um erro tiver ocorrido na computação da função, e devolve 0 caso a computação tiver sido bem sucedida. Esse parâmetro pode ser apenas uma variável, mas não um valor!


Inicialização de função
Antes de chamar a função JJMASeries(), quando a quantidade de barras já calculadas for igual a 0, as variáveis internas do buffer da função deverão ser redimensionadas (seria ainda melhor fazê-lo no bloco de inicialização do indicador personalizado ou do expert advisor). Para isso, é necessário chamar as variáveis do JJMASeries() utilizando a função auxiliar JJMASeriesResize() com os seguintes parâmetros: JJMASeriesResize(número+1); é necessário para criar o 'número' de parâmetro (número MaxJMA) igual à quantidade de chamadas ao JJMASeries, ou seja, maior do que o valor máximo do 'número' por uma margem de 1. Juntamente com o redimensionamento dos buffers do JJMASeries(), pode-se verificar, no bloco de inicialização, os valores de entrada do indicador "comprimento" e "fase", que são entradas do JJMASeries(), verificando se eles se encontram dentro de sua faixa de mudança através do uso do JJMASeriesAlert():

JJMASeriesAlert(int Number, string name, int ExternVar)

- Número - parâmetro que pode ser adquirir dois valores: 0 - para verificar se a entrada ExternVar se encontra dentro da faixa de mudança da entrada de comprimento do JJMASeries(), e 1 - para verificar se a entrada ExternVar se encontra dentro da faixa de mudança da entrada de fase do JJMASeries();
- nome - nome de string da entrada ExternVar para dar um alerta;

- ExternVar - entrada do indicador

Indicação de erro

Quando estiverem sendo depurados, os códigos dos indicadores ou dos expert advisors podem conter erros. Para encontrar as causas dos erros, é necessário visualizar o arquivo log. A função JJMASeries() registra todos os erros em um arquivo log na pasta chamada \MetaTrader\EXPERTS\LOGS\. Se um erro MQL4 ocorre no código que antecede a função JJMASeries() antes de chamar essa função, a função irá registrar o código e o conteúdo do erro em um arquivo log. Se um erro MQL4 ocorre no algoritmo do JJMASeries() durante a execução da função JJMASeries(), a função também irá registrar o código do erro em um arquivo log. Se o 'número' de chamada da função JJMASeries() for especificado incorretamente ou se houver uma definição incorreta do tamanho das variáveis de buffer nJJMAResize.Size, mensagens sobre parâmetros incorretos serão registradas no arquivo log. Informações sobre definições incorretas do parâmetro 'limite' também serão registradas no arquivo log.

Se o redimensionamento dos buffers do JJMASeries falhar durante a execução da função init(), a função JJMASeriesResize() irá registrar informações sobre a falha de redimensionamento no arquivo log. Se a sequência correta da mudança do parâmetro 'barra' for violada durante a chamada da função JJMASeries() através de uma afirmação DO externa, essas informações também serão registradas no arquivo log. Deve-se considerar que alguns erros no código irão produzir novos erros em sua execução, e é por isso que, se a função JJMASeries() registrar vários erros no arquivo log de uma vez, esses erros deverão ser eliminados de acordo com a ordem de sua aparição. Em um indicador corretamente codificado, a função JJMASeries() poderá registrar no arquivo log apenas desordens no sistema operacional. Uma exceção é o registro do redimensionamento das variáveis do buffer na reinicialização do indicador ou do expert advisor, que ocorre sempre que há uma chamada da função init(). Todos os erros MQL4 são registrados no arquivo log através do uso da função JMA_ErrDescr(), que nivela o código e o conteúdo do erro de acordo com o seu código, obtido através do uso da função GetLastError() no arquivo log.

Chamada exemplificadora da função JJMASeries() (nivelamento JMA duplo do preço de entrada):

/*
For the indicator to operate, files 
JJMASeries.mqh 
PriceSeries.mqh 
must be placed into the directory: MetaTrader\experts\include\
Heiken Ashi#.mq4
into the directory: MetaTrader\indicators\
*/
//+------------------------------------------------------------------+   
//|                                                        J2JMA.mq4 | 
//|                       JMA code: Copyright © 2005, Jurik Research | 
//|                                          http://www.jurikres.com/ | 
//|    MQL4 JJMASeries+J2JMA: Copyright © 2006,     Nikolay Kositsin | 
//|                              Khabarovsk,   farria@mail.redcom.ru | 
//+------------------------------------------------------------------+   
#property copyright "Copyright © 2006, Nikolay Kositsin"
#property link "farria@mail.redcom.ru" 
//---- drawing of the indicator in the main window
#property indicator_chart_window 
//---- amount of indicator buffers
#property indicator_buffers 1 
//---- color of the indicator
#property indicator_color1 Magenta 
//---- INDICATOR INPUTS 
extern int Length1 = 5; // depth of the first smoothing 
extern int Length2 = 5; // depth of the second smoothing 
// the first smoothing parameter changing within the range between -100 and +100, 
//it influences the transient quality; 
extern int Phase1  = 100;
// the second smoothing parameter changing in the range between -100 and +100, 
//it influences the transient quality; 
extern int Phase2  = 100;
// indicator shifting along the time axis 
extern int Shift   = 0;
/* Choosing of prices to be used for indicator calculations 
(0-CLOSE, 1-OPEN, 2-HIGH, 3-LOW, 4-MEDIAN, 5-TYPICAL, 6-WEIGHTED,
7-Heiken Ashi Close, 8-SIMPL, 9-TRENDFOLLOW, 10-0.5*TRENDFOLLOW, 
11-Heiken Ashi Low, 12-Heiken Ashi High,  13-Heiken Ashi Open, 
14-Heiken Ashi Close.) */
extern int Input_Price_Customs = 0;
//---- indicator buffers
double J2JMA[];
//---- floating points variables  
double Temp_Series; 
//----+ Introducing of function JJMASeries 
//----+ Introducing of function JJMASeriesResize 
//----+ Introducing of function JJMASeriesAlert  
//----+ Introducing of function JMA_ErrDescr  
#include <JJMASeries.mqh>   
//----+ Introducing of function PriceSeries
//----+ Introducing of function PriceSeriesAlert 
#include <PriceSeries.mqh>
//+------------------------------------------------------------------+ 
//| J2JMA indicator initialization function                          | 
//+------------------------------------------------------------------+ 
int init() 
  {  
//---- defining of the chart drawing style
   SetIndexStyle (0, DRAW_LINE); 
//---- 1 indicator buffer is used for calculations
   SetIndexBuffer(0, J2JMA);
//---- horizontal shift of the indicator line 
   SetIndexShift (0, Shift);  
//---- placing of indicator values that will not be visible in the chart
   SetIndexEmptyValue(0, 0); 
//---- name for data windows and label for subwindows 
   IndicatorShortName ("J2JMA(Length1=" + Length1 + ", Phase1=" + Phase1 +
                       ", Length2=" + Length2 + ", Phase2=" + Phase2 + 
                       ", Shift=" + Shift + ")"); 
   SetIndexLabel (0, "J2JMA"); 
//---- Setting the indicator imaging precision format
   IndicatorDigits(Digits);
//----+ Resizing of buffer variables of function JJMASeries, 
//nJMAnumber=2(two calls for function JJMASeries)
   if(JJMASeriesResize(2) != 2)
       return(-1);
//---- setting alerts for nonaccepted values of external variables
   JJMASeriesAlert (0,"Length1", Length1);
   JJMASeriesAlert (0,"Length2", Length2);
   JJMASeriesAlert (1,"Phase1", Phase1 );
   JJMASeriesAlert (1,"Phase2", Phase2 );
   PriceSeriesAlert(Input_Price_Customs);
//---- complete initialization
   return(0); 
  } 
//+------------------------------------------------------------------+   
//| J2JMA iteration function                                         | 
//+------------------------------------------------------------------+ 
int start() 
  { 
//---- Bar quantity control over sufficiency for further calculations
   if(Bars - 1 < 61)
       return(0);
//----+ Introducing of integer variables and obtaining of bars already computed
   int reset, MaxBar1, MaxBar2, counted_bars = IndicatorCounted();
//---- checking for possible errors
   if(counted_bars < 0) 
       return(-1);
//---- the last counted bar should be recalculated 
//---- (without this recalculation for counted_bars, function JJMASeries will not 
//     operate correctly!!!)
   if(counted_bars > 0) 
       counted_bars--;
//---- determining of the oldest bar number, starting from which new bars
//     will be recalculated
   int limit = Bars - counted_bars - 1; 
   MaxBar1 = Bars - 1; 
   MaxBar2 = MaxBar1 - 30;
 
//----+ INDICATOR COMPUTING BASIC LOOP 
   for(int bar = limit; bar >= 0; bar--)
     {
       // Call for function PriceSeries to get the entry price Series
       Temp_Series = PriceSeries(Input_Price_Customs, bar);
       // Two calls fro function JJMASeries numbered as 0,1. Parameters 
       //nJMA.Phase and nJMA.Length 
       //do not change at each bar (nJMA.din=0)
       //(In the second call, parameter nJMA.MaxBar is decreased by 30 since it is 
       //the repeated JMA smoothing)
       Temp_Series = JJMASeries(0,0,MaxBar1,limit,Phase1,Length1,
                                Temp_Series,bar,reset);
       // checking for errors in the preceding operation
       if(reset != 0)
           return(-1);
       Temp_Series = JJMASeries(1,0,MaxBar2,limit,Phase2,Length2,
                                Temp_Series,bar,reset);
       // checking for errors in the preceding operation
       if(reset != 0)
           return(-1);
       J2JMA[bar] = Temp_Series;
     }
//---- complete calculation of indicator values
   return(0); 
  } 
//+--------------------------------------------------------+


Portanto, os seguintes pontos podem ser enfatizados em relação à aplicação dessa função:
1. Declaração das funções como sendo parte do arquivo JJMASeries.mqh com a linha #include no início do código do indicador. São declaradas as variáveis e quatro funções: JJMASeries(), JJMASeriesResize(), JJMASeriesAlert(), JMA_ErrDescr().
2. Redimensionamento dos elementos do buffer usados pela função JJMASeries() através do uso da função JJMASeriesResize() no bloco de inicialização.
3. Verificação com o uso da função JJMASeriesAlert() no bloco de inicialização, para confirmar se os valores das variáveis externas do indicador que são as variáveis externas da função JJMASeries() estão corretos.
4. As próprias chamadas para a função JJMASeries(), realizadas através do uso das afirmações DO com o controle de erros relevante.


Outras funções

O algoritmo para a chamada de outras funções é essencialmente igual ao algoritmo considerado acima, mas há algumas diferenças na quantidade das variáveis externas disponíveis nas funções:

JJMASeries (int number, int din, int MaxBar, int limit, int Phase,
            int Length, double series, int bar, int&reset)
JLiteSeries(int number, int din, int MaxBar, int limit, int Phase,
            int Length, double series, int bar, int&reset)
JurXSeries (int number, int din, int MaxBar, int limit,
            int Length, double series, int bar, int&reset)
T3Series   (int number, int din, int MaxBar, int limit, int Phase,
            int Length, double series, int bar, int&reset )
ParMASeries(int number, int MaxBar, int limit, int period, 
            double series, int bar, int&reset)
LRMASeries (int number, int MaxBar, int limit, int period, 
            double series, int bar, int&reset )

Deve-se observar que as funções JJMASeries() e JLiteSeries() não são compatíveis no mesmo expert advisor ou indicador! De fato, o mesmo código JMA com o nome de função JJMASeries() é colocado no arquivo JLiteSeries.mqh sem adaptação! Para substituir a função JJMASeries() com a função JLiteSeries() em um expert advisor ou indicador, basta substituir a linha #include por #include. Todos as chamadas para funções do arquivo JLiteSeries.mqh são consideradas chamadas para funções idênticas àquelas usados em relação às funções do arquivo JJMASeries.mqh.

Outras funções são totalmente compatíveis dentro do mesmo código do indicador ou expert advisor. Nas funções ParMASeries() eLRMASeries(), o valor do 'período' da variável externa é limitado a 501. Se valores maiores forem necessários, é preciso modificar os primeiros parâmetros (não o zero!) dos buffers dParMA.TempBuffer[][501] e dParMA.TEMPBUFFER[][501] para a função ParMASeries() ou dLRMA.TempBuffer[][501] e do dLRMA.TEMPBUFFER[][501] para a função LRMASeries() nos arquivos ParMASeries.mqh e LRMASeries.mqh, respectivamente. >


Função JurXSeries()
Abaixo temos uma chamada exemplificadora para a função JurXSeries() (nivelamento ultralinear do preço de entrada com nivelamento adicional JMA):


/*
For the indicator to operate, it is necessary to place files 

JurXSeries.mqh, 
JJMASeries.mqh, 
PriceSeries.mqh,  
to directory: MetaTrader\experts\include\
Heiken Ashi#.mq4
to directory: MetaTrader\indicators\
This indicator is based on the smoothing algorithm of indicator JRSX.
The final result of this indicator bear some resemblance to 
double JMA smoothing, but is less perfect since it is simpler.
 
*/
//+------------------------------------------------------------------+
//|                                                        JJurX.mq4 | 
//|                           Copyright © 2006,     Nikolay Kositsin | 
//|                              Khabarovsk,   farria@mail.redcom.ru | 
//+------------------------------------------------------------------+
#property copyright "Copyright © 2006, Nikolay Kositsin"
#property link "farria@mail.redcom.ru" 
//---- drawing the indicator in the main window
#property indicator_chart_window 
//---- amount of indicator buffers
#property indicator_buffers 1 
//---- color of the indicator
#property indicator_color1 Gold
//---- INDICATOR INPUTS 
extern int JurX_Length  = 5; // depth of JurX smoothing 
extern int JJMA_Length  = 4; // depth of JJMA smoothing 
// parameter of JJMA smoothing ranging between -100 and +100 
// influences the transient quality; 
extern int JJMA_Phase   = -100;
extern int Shift        = 0;      // indicator shift along the time axis 
/* Choosing of prices underlying the indicator calculations 
(0-CLOSE, 1-OPEN, 2-HIGH, 3-LOW, 4-MEDIAN, 5-TYPICAL, 6-WEIGHTED,
7-Heiken Ashi Close, 8-SIMPL, 9-TRENDFOLLOW, 10-0.5*TRENDFOLLOW, 
11-Heiken Ashi Low, 12-Heiken Ashi High,  13-Heiken Ashi Open, 
14-Heiken Ashi Close.) */
extern int Input_Price_Customs = 0;
//---- indicator buffers
double Ind_Buffer[];
//---- floating point variables  
double Price,JurX,JJurX,Error;
//+------------------------------------------------------------------+
//----+ Introducing of function JJMASeries 
//----+ Introducing of function JJMASeriesResize 
//----+ Introducing of function JJMASeriesAlert  
//----+ Introducing of function JMA_ErrDescr  
#include <JJMASeries.mqh> 
//+------------------------------------------------------------------+
//----+ Introducing of function JurXSeries
//----+ Introducing of function JurXSeriesResize
//----+ Introducing of function JurXSeriesAlert 
//----+ Introducing of function JurX_ErrDescr  
#include <JurXSeries.mqh> 
//+------------------------------------------------------------------+ 
//----+ Introducing of function PriceSeries
//----+ Introducing of function PriceSeriesAlert 
#include <PriceSeries.mqh>
//+------------------------------------------------------------------+
//| JJurX indicator initialization function                          | 
//+------------------------------------------------------------------+ 
int init() 
{  
//---- defining of the charting style
SetIndexStyle (0,DRAW_LINE); 
//---- 1 indicator buffer is used to calculate
SetIndexBuffer(0,Ind_Buffer);
//---- horizontal shift of the indicator line 
SetIndexShift (0, Shift); 
//---- setting indicator values that will not be visible in the chart
SetIndexEmptyValue(0,0); 
//---- name for data windows and label for subwindows 
IndicatorShortName ("JJurX( JurX_Length="+JurX_Length+", Shift="+Shift+")"); 
SetIndexLabel (0, "JJurX"); 
//---- Setting the indicator imaging precision format
IndicatorDigits(Digits);
//----+ Resizing buffer variables of function JurXSeries, 
//      nJurXnumber=2
//(To calls for function JurXSeries)
if (JurXSeriesResize(2)!=2)return(-1);
//----+ Resizing buffer variables of function JJMASeries,
//      nJMAnumber=1
//(One call for function JJMASeries)
if (JJMASeriesResize(1)!=1)return(-1);
//---- setting alerts for nonaccepted values of external variables  
JurXSeriesAlert(0,"JurX_Length",JurX_Length); 
JJMASeriesAlert(0,"JJMA_Length",JJMA_Length); 
JJMASeriesAlert(1,"JJMA_Phase",JJMA_Phase); 
PriceSeriesAlert(Input_Price_Customs);
//---- complete initialization
return(0); 
} 
//+-----------------------------------------------------------------------------+
//| JJurX iteration function                                                    | 
//+-----------------------------------------------------------------------------+
int start() 
{ 
//---- Bar quantity control over sufficiency for further calculations
if (Bars-1<JurX_Length+32)return(0);
//----+ Introducing of integer variables and obtaining of bars already computed
int reset,MaxBar,counted_bars=IndicatorCounted();
//---- checking for possible errors
if (counted_bars<0)return(-1);
//---- the last counted bar should be recalculated 
//(without this recalculation for counted_bars, function JurXSeries will not 
// operate correctly!!!)
if (counted_bars>0) counted_bars--;
//---- determining of the oldest bar number, starting from which new bars
//     will be recalculated
int limit=Bars-counted_bars-1; 
determining of the oldest bar number, starting from which all bars
//     will be recalculated
MaxBar=Bars-1; 
 
//----+ INDICATOR COMPUTING BASIC LOOP 
for(int bar=limit;bar>=0;bar--)
 {
  //----+ Call for function PriceSeries to get the entry
  //      price Series
  Price=PriceSeries(Input_Price_Customs,bar);
  //----+ One call for function JurXSeries numbered as 0. 
  //Parameter nJJurX.Length does not change on each bar (nJurXdin=0)
  JurX=JurXSeries(0,0,MaxBar,limit,JurX_Length,Price,bar,reset); 
  //----+ checking for errors in the preceding operation
  if(reset!=0)return(-1); 
  //----+ detection of error in calculations of parameter JurX
  //----+ the second call for function JurXSeries numbered as 1. 
  //Parameter nJJurX.Length does not change on each bar (nJurXdin=0)
  Error=JurXSeries(1,0,MaxBar,limit,JurX_Length,100,bar,reset); 
  //----+ checking for errors in the preceding operation
  if(reset!=0)return(-1);
  if(Error==0)Error=100;
  JurX*=100/Error;
  //----+ Call for function JJMASeries numbered as 0. 
  //      Parameters nJMA.Phase and nJMA.Length do not change on each bar 
  //      (nJMA.din=0)
  JJurX=JJMASeries(0,0,MaxBar,limit,JJMA_Phase,JJMA_Length,JurX,bar,reset);
  //----+ checking for errors in the preceding operation
  if(reset!=0)return(-1);
  Ind_Buffer[bar]=JJurX;                 
 }
//---- complete calculation of indicator values
return(0); 
} 
//+-------------------------------------------------------------------------+

Nesse exemplo, deve-se notar que a função JurXSeries() faz o cálculo da média tanto o preço de entrada quanto da constante! Dividindo o resultado do cálculo da média pelo valor constante, obteremos o erro de nivelamento. Para obter resultados mais precisos do nivelamento da série de preços, é necessário dividir o resultado do nivelamento por esse valor de erro. Isso foi feito, no nosso caso. Em dois casos abaixo, o numerador e o denominador são nivelados separadamente, de modo que o procedimento acima não se faz necessário. Tal erro não irá ocorrer em outras funções de nivelamento.

Abaixo temos uma chamada exemplificadora para as funções JJMASeries() e JurXSeries() (CCI análogo com nivelamento JMA adicional):

/*
For the indicator to operate, it is necessary to place files 
JJMASeries.mqh
JurSeries.mqh 
PriceSeries.mqh 
to directory: MetaTrader\experts\include\
Heiken Ashi#.mq4
to directory: MetaTrader\indicators\
*/
//+------------------------------------------------------------------+   
//|                                                        JCCIX.mq4 |
//|                               Copyright © 2006, Nikolay Kositsin | 
//|                              Khabarovsk,   farria@mail.redcom.ru | 
//+------------------------------------------------------------------+    
#property copyright "Copyright © 2006, Nikolay Kositsin"
#property link "farria@mail.redcom.ru" 
//---- drawing the indicator in a separate window
#property indicator_separate_window
//---- amount of indicator buffers
#property indicator_buffers  1
//---- colors of indicator
#property indicator_color1  BlueViolet
//---- parameters of the indicator horizontal levels
#property indicator_level1  0.5
#property indicator_level2 -0.5
#property indicator_level3  0.0
#property indicator_levelcolor MediumBlue
#property indicator_levelstyle 4
//---- INDICATOR INPUTS 
extern int  JJMA.Length = 8;  // depth of JJMA smoothing of entry price
// depth of JurX smoothing of the obtained indicator 
extern int  JurX.Length = 8;
// parameter ranging between -100 and +100 influences 
// the smoothing transient quality
extern int  JJMA.Phase = 100;
 /* Choosing of prices underlying the indicator calculations  
(0-CLOSE, 1-OPEN, 2-HIGH, 3-LOW, 4-MEDIAN, 5-TYPICAL, 6-WEIGHTED,
7-Heiken Ashi Close, 8-SIMPL, 9-TRENDFOLLOW, 10-0.5*TRENDFOLLOW, 
11-Heiken Ashi Low, 12-Heiken Ashi High,  13-Heiken Ashi Open, 
14-Heiken Ashi Close.) */
extern int Input_Price_Customs = 0;
//---- indicator buffers
double Ind_Buffer1[];
//---- integer constans 
int    w;
//+------------------------------------------------------------------+
//----+ Introducing of function JJMASeries 
//----+ Introducing of function JJMASeriesResize 
//----+ Introducing of function JJMASeriesAlert  
//----+ Introducing of function JMA_ErrDescr  
#include <JJMASeries.mqh> 
//+------------------------------------------------------------------+ 
//----+ Introducing of function JurXSeries
//----+ Introducing of function JurXSeriesResize
//----+ Introducing of function JurXSeriesAlert 
//----+ Introducing of function JurX_ErrDescr  
#include <JurXSeries.mqh> 
//+------------------------------------------------------------------+  
//----+ Introducing of function PriceSeries
//----+ Introducing of function PriceSeriesAlert 
#include <PriceSeries.mqh>
//+------------------------------------------------------------------+ 
//| JCCIX initialization function                                    |
//+------------------------------------------------------------------+
int init()
 {
//---- indicator drawing styles
   SetIndexStyle(0,DRAW_LINE);
//---- 1 indicator buffer is used for calculations. 
   SetIndexBuffer(0,Ind_Buffer1);
//---- setting of the indicator values that will not be visible in the chart
   SetIndexEmptyValue(0,0); 
//---- names for data windows and labels for subwindows
   SetIndexLabel(0,"JCCIX");
   IndicatorShortName("JCCIX(JJMA.Length="+JJMA.Length+", JurX.Length"+
                      JurX.Length+")");
//---- Setting imaging precision format (count of characters after decimal point) 
//to visualize the indicator values  
   IndicatorDigits(2);
//----+ Resizing buffer variables of function JurXSeries, 
//      nJurXnumber=2
//(Two calls for function JurXSeries)
   if (JurXSeriesResize(2)!=2)return(-1);
//----+ Resizing buffer variables of function JJMASeries, 
//      nJMAnumber=1
//(One call for function JJMASeries)
   if (JJMASeriesResize(1)!=1)return(-1);
//---- setting alerts for nonaccepted values of external variables
   JurXSeriesAlert (0,"JurX.Length",JurX.Length);
   JJMASeriesAlert (0,"JJMA.Length",JJMA.Length);
   JJMASeriesAlert (1,"JJMA.Phase",JJMA.Phase);
   PriceSeriesAlert(Input_Price_Customs);
//---- setting the bar number, starting from which the indicator will be 
//     drawn  
   SetIndexDrawBegin(0,JurX.Length+31);
//---- coefficients initialization to compute the indicator 
   if (JurX.Length>5) w=JurX.Length-1; else w=5;
//---- initialization complete
   return(0);
  }
//+------------------------------------------------------------------------+
//|  JCommodity Channel IndexX                                             |
//+------------------------------------------------------------------------+
int start()
  {
//---- Introducing of floating point variables    
double price,Jprice,JCCIX,UPCCI,DNCCI,JUPCCIX,JDNCCIX; 
//----+ Introducing of integer variables and getting bars already computed
int reset,MaxBar,MaxBarJ,limit,counted_bars=IndicatorCounted();
//---- check for possible errors
if (counted_bars<0)return(-1);
//---- the last counted bar must be recalculated 
//---- (without this recalculation for counted_bars, functions JJMASeries 
//and JurXSeries will not work correctly!!!)
if (counted_bars>0) counted_bars--;
//---- determining of the oldest bar number, starting from which new bars
//     will be recalculated
limit=Bars-counted_bars-1; 
//---- determining of the oldest bar number, starting from which all bars
//     will be recalculated
MaxBar=Bars-1; MaxBarJ=MaxBar-30;
//---- correction of the start calculated bar in the loop
if(limit>=MaxBar)limit=MaxBar;
 
for(int bar=limit; bar>=0; bar--)
 { 
   //----+ Call for function PriceSeries to get entry 
   //      price Series
   price=PriceSeries(Input_Price_Customs, bar);
   //+----------------------------------------------------------------
   //----+ One call for function JJMASeries numbered as 0 
   //----+ Parameters nJMA.Phase and nJMA.Length do not change within  
   //      each bar (nJMA.din=0)
   //+---------------------------------------------------------------+   
   Jprice=JJMASeries(0,0,MaxBar,limit,JJMA.Phase,JJMA.Length,price,
                     bar,reset);
   //----+ check for errors in the preceding operation
   if(reset!=0)return(-1);
   //+---------------------------------------------------------------+    
   UPCCI=price-Jprice;         
   DNCCI=MathAbs(UPCCI);
   //----+ Two calls for function JurXSeries numbered as 0 and 1. 
           Parameter nJJurXLength does not 
   //change within each bar (nJurXdin=0)
   //----+ check for errors in the preceding operation
   JUPCCIX=JurXSeries(0,0,MaxBarJ,limit,JurX.Length,UPCCI,bar,reset); 
   if(reset!=0)return(-1); 
   JDNCCIX=JurXSeries(1,0,MaxBarJ,limit,JurX.Length,DNCCI,bar,reset); 
   if(reset!=0)return(-1); 
   //----+
   if (bar>MaxBarJ-w)JCCIX=0;
   else 
     if (JDNCCIX!=0)
       {
        JCCIX=JUPCCIX/JDNCCIX;
        if(JCCIX>1)JCCIX=1;
        if(JCCIX<-1)JCCIX=-1;
       }
     else JCCIX=0;
   Ind_Buffer1[bar]=JCCIX; 
   //----+
 }
//----
   return(0);
  }
//+-------------------------------------------------------------------+


O seguinte fato deve ser levado em consideração: Após dois nivelamentos com a função JurXSeries(), um dos valores obtidos será verificado por não ser igual a zero, por ser um denominador!

Abaixo temos uma chamada exemplar para as funções JJMASeries() e JurXSeries (RSI análogo com nivelamento JMA adicional):

/*
For the indicator to operate, it is necessary to place files  
JurXSeries.mqh
JJMASeries.mqh  
PriceSeries.mqh 
to directory: MetaTrader\experts\include\
Heiken Ashi#.mq4
to directory: MetaTrader\indicators\
*/
//+------------------------------------------------------------------+ 
//|                                                        JJRSX.mq4 |
//|    MQL4 JJRSX: Copyright © 2006,                Nikolay Kositsin | 
//|                              Khabarovsk,   farria@mail.redcom.ru | 
//+------------------------------------------------------------------+ 
#property copyright "Copyright © 2006, Nikolay Kositsin"
#property link "farria@mail.redcom.ru" 
//---- drawing of the indicator in a separate window
#property indicator_separate_window
//---- amount of indicator buffers
#property indicator_buffers  1
//---- colors of the indicator
#property indicator_color1  BlueViolet
//---- parameters of the indicator horizontal levels
#property indicator_level1  0.5
#property indicator_level2 -0.5
#property indicator_level3  0.0
#property indicator_levelcolor MediumBlue
#property indicator_levelstyle 4
//---- INDICATOR INPUTS 
extern int  Length = 8;  // depth of JurX smoothing of the indicator
// depth of JJMA smoothing of the obtained indicator
extern int  Smooth = 3;
// parameter ranging between -100 and +100, influences 
//the smoothing transient quality
extern int  Phase = 100;
/* Choosing of prices, at which the indicator is computed 
(0-CLOSE, 1-OPEN, 2-HIGH, 3-LOW, 4-MEDIAN, 5-TYPICAL, 6-WEIGHTED,
7-Heiken Ashi Close, 8-SIMPL, 9-TRENDFOLLOW, 10-0.5*TRENDFOLLOW,
11-Heiken Ashi Low, 12-Heiken Ashi High,  13-Heiken Ashi Open, 
14-Heiken Ashi Close.) */
extern int Input_Price_Customs = 0;
//---- indicator buffers
double Ind_Buffer[];
//---- integer variables 
int    w;  
//+------------------------------------------------------------------+  
//----+ Introducing of function JJMASeries 
//----+ Introducing of function JJMASeriesResize 
//----+ Introducing of function JJMASeriesAlert  
//----+ Introducing of function JMA_ErrDescr  
#include <JJMASeries.mqh> 
//+------------------------------------------------------------------+ 
//----+ Introducing of function JurXSeries
//----+ Introducing of function JurXSeriesResize
//----+ Introducing of function JurXSeriesAlert 
//----+ Introducing of function JurX_ErrDescr  
#include <JurXSeries.mqh> 
//+------------------------------------------------------------------+ 
//----+ Introducing of function PriceSeries
//----+ Introducing of function PriceSeriesAlert 
#include <PriceSeries.mqh>
//+---------------------------------------------------------------------+ 
//| JJRSX initialization function                                       |
//+---------------------------------------------------------------------+ 
int init()
  {
//---- indicator drawing styles
   SetIndexStyle(0,DRAW_LINE);
//---- 1 indicator buffer is used for counting. 
   SetIndexBuffer(0,Ind_Buffer);
//---- setting the indicator values that will not be visible in the chart
   SetIndexEmptyValue(0,0); 
//---- names for data windows and labels for subwindows
   SetIndexLabel(0,"JRSX");
   IndicatorShortName("JRSX(Length="+Length+", Input_Price_Customs="+
                      Input_Price_Customs+")");
//---- Setting imaging precision format (count of characters after decimal point) 
//to visualize the indicator values  
   IndicatorDigits(2);
//----+ Resizing buffer variables of function JurXSeries,
        nJurXnumber=2
//(Two calls for function JurXSeries)
   if (JurXSeriesResize(2)!=2)return(-1);
//----+ Resizing buffer variables of function JJMASeries,
        nJMAnumber=1
//(One call for function JJMASeries)
   if (JJMASeriesResize(1)!=1)return(-1);
//---- setting alerts for nonaccepted values of external variables
   JurXSeriesAlert (0,"Length",Length);
   JJMASeriesAlert (0,"Smooth",Smooth);
   JJMASeriesAlert (1,"Phase",Phase);
   PriceSeriesAlert(Input_Price_Customs);
//---- setting the bar number, starting from which there will be drawn the
       indicator  
   SetIndexDrawBegin(0,Length+31);
//---- correction of nonaccepted value ща parameter Length
   if(Length<1)Length=1; 
//---- coefficients initialization to compute the indicator 
   if (Length>5) w=Length-1; else w=5;
//---- initialization complete
return(0);
  }
//+-----------------------------------------------------------------------------+ 
//| JJRSX iteration function                                                    |
//+-----------------------------------------------------------------------------+ 
int start()
{
//---- Introducing floating point variables 
double dPrice,dPriceA,UPJRSX,DNJRSX,JRSX,JJRSX; 
//----+ Introducing of integer variables and obtaining of bars already computed
int bar,limit,reset,MaxBar,MaxBarJ,counted_bars=IndicatorCounted();
//---- check for possible errors
if (counted_bars<0)return(-1);
//---- the last counted bar must be recalculated
if (counted_bars>0) counted_bars--;
//---- determining of the oldest bar number, starting from which all bars
//     will be recalculated
MaxBar=Bars-2; MaxBarJ=MaxBarJ-w-1; 
//---- determining of the oldest bar number, starting from which new bars
//     will be recalculated
limit=Bars-counted_bars-1; 
//----+ 
if (limit>MaxBar){limit=MaxBar;Ind_Buffer[MaxBar]=0.0;}
 
for(bar=limit;bar>=0;bar--)
  {
   //----+ two calls for function PriceSeries to get the difference
   //      between entry prices dPrice
   dPrice = PriceSeries(Input_Price_Customs, bar)-
                        PriceSeries(Input_Price_Customs, bar+1);
   //----+  
   dPriceA=MathAbs(dPrice);
   //----+ Two calls for function JurXSeries numbered as 0 and 1. 
   //      Parameter nJJurXLength 
   //does not change on each bar (nJurXdin=0) 
   //check for errors in the preceding operation
   UPJRSX=JurXSeries(0,0,MaxBar,limit,Length,dPrice, bar,reset); 
   if(reset!=0)return(-1);
   DNJRSX=JurXSeries(1,0,MaxBar,limit,Length,dPriceA,bar,reset);
   if(reset!=0)return(-1); 
   //----+
   if (bar>MaxBar-w)JRSX=0;
   else if (DNJRSX!=0){JRSX=UPJRSX/DNJRSX;
   if(JRSX>1)JRSX=1;
   if(JRSX<-1)JRSX=-1;}else JRSX=0;
   //+---------------------------------------------------------------+ 
   //----+ One call for function JJMASeries numbered as 0 
   //----+ Parameters nJMA.Phase and nJMA.Length do not change 
   //      on each bar (nJMA.din=0)
   //+---------------------------------------------------------------+   
   JJRSX=JJMASeries(0,0,MaxBarJ,limit,Phase,Smooth,JRSX,bar,reset);
   //----+ check for errors in the preceding operation
   if(reset!=0)return(-1);
   //+---------------------------------------------------------------+  
   Ind_Buffer[bar]=JJRSX;  
}
//---- complete calculation of the indicator values
return(0);
}
//+------------------------------------------------------------------+



Funções T3Series()
Abaixo temos uma chamada exemplificadora para a função T3Series() (três bandas Bollinger com nivelamento adicional T3):

/*
To work with the indicator, files 
T3Series.mqh 
PriceSeries.mqh 
must be placed in directory: MetaTrader\experts\include\
Heiken Ashi#.mq4
in directory: MetaTrader\indicators\
*/
//+------------------------------------------------------------------+ 
//|                                          T3.6Bollinger Bands.mq4 | 
//|                        Copyright © 2006,        Nikolay Kositsin | 
//|                              Khabarovsk,   farria@mail.redcom.ru | 
//+------------------------------------------------------------------+ 
#property copyright "Copyright © 2006, Nikolay Kositsin"
#property link "farria@mail.redcom.ru" 
//---- drawing of the indicator in the main window
#property indicator_chart_window 
//---- amount of indicator buffers
#property indicator_buffers 7
//---- indicator color
#property indicator_color1 Gray 
#property indicator_color2 Red
#property indicator_color3 Blue 
#property indicator_color4 Lime
#property indicator_color5 Blue
#property indicator_color6 Red
#property indicator_color7 Gray 
//---- indicator line style
#property indicator_style1 4
#property indicator_style2 2
#property indicator_style3 4
#property indicator_style4 4
#property indicator_style5 4
#property indicator_style6 2
#property indicator_style7 4
//---- INDICATOR INPUTS 
// averaging period of J2Bollinger Bands
extern int        Bands_Period = 100;
extern double Bands_Deviations = 2.0; // deviation 
extern int         MA_method = 0;   // averaging method
// smoothing depth of the obtained Moving Avereges
extern int         MA_Smooth = 20;
// smoothing depth of the obtained Bollinger Bands
extern int        Bands_Smooth = 20;
// smoothing parameter ranging between -100 and +100, 
// influences the transient quality; 
extern int    Smooth_Curvature = 100;
// indicator shift along the time axis 
extern int         Bands_Shift = 0;
//Choosing of prices, on which the indicator is calculated 
/*(0-CLOSE, 1-OPEN, 2-HIGH, 3-LOW, 4-MEDIAN, 5-TYPICAL, 6-WEIGHTED,
7-Heiken Ashi Close, 8-SIMPL, 9-TRENDFOLLOW, 10-0.5*TRENDFOLLOW,
11-Heiken Ashi High, 12-Heiken Ashi Low, 13-Heiken Ashi Open, 
14-Heiken Ashi Close.)*/
extern int Input_Price_Customs = 0;
//---- indicator buffers
double UpperBuffer3  [];
double UpperBuffer2  [];
double UpperBuffer1  [];
double T3MovingBuffer[];
double LowerBuffer1  [];
double LowerBuffer2  [];
double LowerBuffer3  [];
double Series_buffer [];
//+------------------------------------------------------------------+ 
//----+ Introducing of function T3Series 
//----+ Introducing of function T3SeriesResize 
//----+ Introducing of function T3SeriesAlert 
//----+ Introducing of function T3_ErrDescr  
#include <T3Series.mqh> 
//+------------------------------------------------------------------+ 
//----+ Introducing of function PriceSeries
//----+ Introducing of function PriceSeriesAlert 
#include <PriceSeries.mqh>
//+------------------------------------------------------------------+  
//| T3.6Bollinger Bands initialization function        | 
//+------------------------------------------------------------------+  
int init()
  {
//---- defining the chart drawing style
   SetIndexStyle(0,DRAW_LINE); 
   SetIndexStyle(1,DRAW_LINE);
   SetIndexStyle(2,DRAW_LINE);
   SetIndexStyle(3,DRAW_LINE); 
   SetIndexStyle(4,DRAW_LINE);
   SetIndexStyle(5,DRAW_LINE); 
   SetIndexStyle(6,DRAW_LINE);
//---- 4 indicator buffers are used for calculations  
   IndicatorBuffers(8);
   SetIndexBuffer(0,UpperBuffer3 );
   SetIndexBuffer(1,UpperBuffer2 );
   SetIndexBuffer(2,UpperBuffer1 );
   SetIndexBuffer(3,T3MovingBuffer);
   SetIndexBuffer(4,LowerBuffer1 );
   SetIndexBuffer(5,LowerBuffer2 );
   SetIndexBuffer(6,LowerBuffer3 );
   SetIndexBuffer(7,Series_buffer);
//---- setting up indicator values that will not be visible in the chart
   SetIndexEmptyValue(0,0);
   SetIndexEmptyValue(1,0);
   SetIndexEmptyValue(2,0);
   SetIndexEmptyValue(3,0);
   SetIndexEmptyValue(4,0);
   SetIndexEmptyValue(5,0);
   SetIndexEmptyValue(6,0);
//---- setting up the bar number, starting from which the indicator
//     will be drawn  
   int drawbegin=100+Bands_Shift;
   SetIndexDrawBegin(0,drawbegin);
   SetIndexDrawBegin(1,drawbegin);
   SetIndexDrawBegin(2,drawbegin);
   SetIndexDrawBegin(3,drawbegin);
   SetIndexDrawBegin(4,drawbegin);
   SetIndexDrawBegin(5,drawbegin);
   SetIndexDrawBegin(6,drawbegin);
//---- horizontal shift of the indicator lines  
   SetIndexShift (0, Bands_Shift); 
   SetIndexShift (1, Bands_Shift); 
   SetIndexShift (2, Bands_Shift); 
   SetIndexShift (3, Bands_Shift); 
   SetIndexShift (4, Bands_Shift); 
   SetIndexShift (5, Bands_Shift); 
   SetIndexShift (6, Bands_Shift); 
//---- name for data windows and labels for subwindows
   IndicatorShortName ("T3.4Bollinger Bands( Period="+Bands_Period+
        ", Deviations="+Bands_Deviations+")"); 
   SetIndexLabel (0, "Upper3 Bands");
   SetIndexLabel (1, "Upper2 Bands");
   SetIndexLabel (2, "Upper1 Bands"); 
   SetIndexLabel (4, "Lower1 Bands"); 
   SetIndexLabel (5, "Lower2 Bands"); 
   SetIndexLabel (6, "Lower3 Bands"); 
   string Moving;
   switch(MA_method)
       {
        case  0: Moving= "T3SMA";break;
        case  1: Moving= "T3EMA";break;
        case  2: Moving="T3SSMA";break;
        case  3: Moving="T3LWMA";break;
        default: Moving="T3SMA";
       }
   SetIndexLabel (3, "Moving Avereges "+Moving+" ("+Bands_Period+")");
//---- Setting imaging precision format for the indicator 
   IndicatorDigits(Digits);
//----+ Resizing of buffer variables of function T3Series, 
//nT3.number=7(Seven calls for function T3Series)
   if (Bands_Smooth<=1){if (T3SeriesResize(1)!=1)return(-1);}
   else if (T3SeriesResize(7)!=7)return(-1);
//---- setting alerts for nonaccepted values of external variables
   T3SeriesAlert(0,"MA_Smooth",MA_Smooth);
   T3SeriesAlert(0,"Bands_Period",Bands_Period);
   PriceSeriesAlert(Input_Price_Customs);
   if((MA_method<0)||(MA_method>3))
        Alert("Parameter MA_method must range between 0 and 3" 
        + " You input a nonaccepted " 
       +MA_method+ "0 will be used");
//---- correction of the nonaccepted value of parameter Bands_Period
   if(Bands_Period<1)Bands_Period=1; 
//---- initialization complete
   return(0);
  }
//+------------------------------------------------------------------------+  
//| T3.6Bollinger Bands iteration function                                 | 
//+------------------------------------------------------------------------+  
int start()
  {
//---- check for whether the amount of bars is sufficient for calculations
if(Bars-1<=Bands_Period) return(0);
//---- Introducing of floating point variables  
double deviation1,deviation2,deviation3,Temp_Series,sum,midline,
       priceswing,Resalt;
//----+ Introducing of integer variables and getting the bars already calculated
int reset,MaxBar,MaxBarBB,MaxBarBB1,bar,kk,counted_bars=IndicatorCounted();
//---- check for possible errors
if (counted_bars<0)return(-1);
//---- the last counted bar must be recalculated 
// (without this recalculation for counted_bars, function T3Series will not work
// correctly!!!)
if (counted_bars>0) counted_bars--;
//---- determining of the oldest bar number, starting from which new bars
//     will be recalculated
int limit=Bars-counted_bars-1;
//---- determining of the oldest bar number, starting from which all bars
//     will be recalculated
MaxBar=Bars-1-Bands_Period; MaxBarBB=MaxBar-30-Bands_Period; 
MaxBarBB1=MaxBarBB-1;
//----+ loading of entry prices into the buffer for calculations       
for(bar=limit;bar>=0;bar--)
    Series_buffer[bar]=PriceSeries(Input_Price_Customs,bar);
//---- checking whether the bars are sufficient for calculation of Bollinger Bands 
//---- zero initialization        
if (limit>MaxBar)
     {
      for(bar=limit;bar>=MaxBar;bar--)T3MovingBuffer[bar]=0;
      limit=MaxBar;
     }
//----+ Moving Averages calculation loop
for(bar=limit;bar>=0;bar--)
     {
      //----+ Moving Averages calculation formula
      Temp_Series=iMAOnArray(Series_buffer,0,Bands_Period,0,
                             MA_method, bar);
      //----+ smoothing of the obtained Moving Averages
      //----+ call for function T3Series numbered as 0. 
      // Parameters nT3.Curvature and nT3.Length do not change on 
      // each bar (nT3.din=0)
      Resalt=T3Series(0,0,MaxBar,limit,Smooth_Curvature,MA_Smooth,
                      Temp_Series,bar,reset);
      //----+ check for error in the preceding operation
      if(reset!=0)return(-1); 
      T3MovingBuffer[bar]=Resalt; 
     }     
//---- CALCULATION of Bollinger Bands 
//---- zero initialization      
if (limit>MaxBarBB)
     {
      for(bar=limit;bar>=MaxBarBB;bar--)
       {
        UpperBuffer2[bar]=0;
        UpperBuffer1[bar]=0;
        LowerBuffer1[bar]=0;
        LowerBuffer2[bar]=0;
       }
      limit=MaxBarBB;
     }
for(bar=limit;bar>=0;bar--)
   {       
     sum=0.0;
     midline=T3MovingBuffer[bar];
     kk=bar+Bands_Period-1;
     while(kk>=bar)
      {
       priceswing=PriceSeries(Input_Price_Customs,kk)-midline;
       sum+=priceswing*priceswing;
       kk--;
      }
     deviation2=Bands_Deviations*MathSqrt(sum/Bands_Period);     
     deviation1=0.5*deviation2;
     deviation3=1.5*deviation2;
     if (Bands_Smooth>1)
      {
       //----+ calculation and T3 smoothing of Bollinger Bands      
       //----+ ------------------------------------------------------+        
       //----+ six parallel calls for function T3Series numbered 
       //      as 1, 2, 3, 4, 5, 6. 
       //----+ Parameters nT3.Length do not change on each bar 
       //      (nT3.din=0)
       //----+ ------------------------------------------------------+ 
       Resalt=T3Series(1,0,MaxBarBB1,limit,Smooth_Curvature,Bands_Smooth,
                       midline+deviation3,bar,reset);
       //----+ check for errors in the preceding operation
       if(reset!=0)return(-1); 
       UpperBuffer3[bar]=Resalt; 
       //----+ ------------------------------------------------------+ 
       Resalt=T3Series(2,0,MaxBarBB1,limit,Smooth_Curvature,Bands_Smooth,
                       midline+deviation2,bar,reset);
       //----+ check for errors in the preceding operation
       if(reset!=0)return(-1); 
       UpperBuffer2[bar]=Resalt; 
       //----+ ------------------------------------------------------+       
       Resalt=T3Series(3,0,MaxBarBB1,limit,Smooth_Curvature,Bands_Smooth,
                       midline+deviation1,bar,reset);
       //----+ check for errors in the preceding operation
       if(reset!=0)return(-1); 
       UpperBuffer1[bar]=Resalt; 
       //----+ ------------------------------------------------------+ 
       Resalt=T3Series(4,0,MaxBarBB1,limit,Smooth_Curvature,Bands_Smooth,
                       midline-deviation1,bar,reset);
       //----+ check for errors in the preceding operation
       if(reset!=0)return(-1); 
       LowerBuffer1[bar]=Resalt; 
       //----+ ------------------------------------------------------+ 
       Resalt=T3Series(5,0,MaxBarBB1,limit,Smooth_Curvature,Bands_Smooth,
                       midline-deviation2,bar,reset);
       //----+ check for errors in the preceding operation
       if(reset!=0)return(-1); 
       LowerBuffer2[bar]=Resalt; 
       //----+ ------------------------------------------------------+ 
       Resalt=T3Series(6,0,MaxBarBB1,limit,Smooth_Curvature,Bands_Smooth,
                       midline-deviation3,bar,reset);
       //----+ check for errors in the preceding operation
       if(reset!=0)return(-1); 
       LowerBuffer3[bar]=Resalt;        
       //----+ ------------------------------------------------------+ 
      }
     else 
      {
       //----+ calculation of Bollinger Bands without T3 smoothing 
       UpperBuffer3[bar]=midline+deviation3; 
       UpperBuffer2[bar]=midline+deviation2;
       UpperBuffer1[bar]=midline+deviation1;
       LowerBuffer1[bar]=midline-deviation1;
       LowerBuffer2[bar]=midline-deviation2;
       LowerBuffer3[bar]=midline-deviation3;
      }
      
   }
//---- complete indicator calculations
   return(0);
  }
//+-------------------------------------------------------------------+



Funções ParMASeries()
Abaixo temos uma chamada exemplificadora para a função ParMASeries() (ParMA móvel com nivelamento adicional JMA):

/*
Moving average ParMA calculated on parabolic 
regression with bands 
 
for the indicator to work, one should place files 
JJMASeries.mqh 
ParMASeries.mqh 
PriceSeries.mqh 
to directory: MetaTrader\experts\include\
Heiken Ashi#.mq4
to directory: MetaTrader\indicators\
*/
//+------------------------------------------------------------------+ 
//|                                                       JParMA.mq4 |
//|                       ParMA MQL4 CODE: Copyright © 2006, alexjou |
//|             JParMA Indicator: Copyright © 2006, Nikolay Kositsin |
//+------------------------------------------------------------------+ 
#property copyright "Copyright © 2006, Nikolay Kositsin"
#property link "farria@mail.redcom.ru" 
//---- drawing the indicator in the main window
#property indicator_chart_window
//---- amount of indicator buffers
#property indicator_buffers 1
//---- color of the indicator 
#property indicator_color1 Red
//---- INDICATOR INPUTS 
extern int MA_Period  = 8; // ParMA period
extern int Length = 3;   // smoothing depth 
// parameter ranging between -100 and +100, 
//it influences the transient quality; 
extern int Phase  = 100;
extern int Shift  = 0;   // indicator shift along the time axis 
//Choosing of prices, at which the indicator is calculated 
/*(0-CLOSE, 1-OPEN, 2-HIGH, 3-LOW, 4-MEDIAN, 5-TYPICAL, 6-WEIGHTED,
7-Heiken Ashi Close, 8-SIMPL, 9-TRENDFOLLOW, 10-0.5*TRENDFOLLOW, 
11-Heiken Ashi High, 12-Heiken Ashi Low, 13-Heiken Ashi Open, 
14-Heiken Ashi Close.) */
extern int Input_Price_Customs = 0;
//---- indicator buffers
double IndBuffer[];
//---- float point variables 
double JResalt, Price, Resalt;
//+------------------------------------------------------------------+  
//----+ Introducing of function JJMASeries 
//----+ Introducing of function JJMASeriesResize 
//----+ Introducing of function JJMASeriesAlert  
//----+ Introducing of function JMA_ErrDescr  
#include <JJMASeries.mqh> 
//+------------------------------------------------------------------+ 
//----+ Introducing of function ParMAMASeries 
//----+ Introducing of function ParMASeriesResize 
//----+ Introducing of function ParMASeriesAlert 
//----+ Introducing of function ParMA_ErrDescr 
#include <ParMASeries.mqh> 
//+------------------------------------------------------------------+  
//----+ Introducing of function PriceSeries
//----+ Introducing of function PriceSeriesAlert 
#include <PriceSeries.mqh>
//+------------------------------------------------------------------+   
//| JParMA initialization function                                   |
//+------------------------------------------------------------------+ 
int init()
 {
  //---- Setting imaging precision format for the indicator
  IndicatorDigits(Digits);
  //---- defining the chart drawing style
  SetIndexStyle(0, DRAW_LINE);
  //---- 1 indicator buffer is used for calculations
  SetIndexBuffer(0, IndBuffer);
  //---- horizontal shift of the indicator line 
  SetIndexShift (0, Shift); 
  //---- setting the indicator values that will not be visible in
  //     the chart
  SetIndexEmptyValue(0, 0.0); 
  //---- name for data windows and label for subwindows 
  IndicatorShortName ("JParMA( Length="+Length+", Phase="+Phase+", 
                      Shift="+Shift+")");   
  SetIndexLabel(0, "JParMA Line");
  //---- setting the bar number, starting from which there will be drawn
         indicator 
  SetIndexDrawBegin(0, MA_Period);
  //----+ Resizing buffer variables of function JJMASeries, 
  //nJMAnumber=1(One call for function JJMASeries)
  if (JJMASeriesResize(1)!=1)return(-1);
  //----+ Resizing buffer variables of function ParMASeries, 
  //nParMAnumber=1(One call for function ParMASeries)
  if (ParMASeriesResize(1)!=1)return(-1);
  //---- setting alerts for nonaccepted values of external variables
  JJMASeriesAlert (0,"Length",Length);
  JJMASeriesAlert (1,"Phase", Phase );
  ParMASeriesAlert(0,"MA_Period",MA_Period);
  PriceSeriesAlert(Input_Price_Customs);
  return(0);
 }
//+-----------------------------------------------------------------------+ 
//| JParMA iteration function                                             |
//+-----------------------------------------------------------------------+ 
int start()
 {
 //---- check whether the amount of bars is sufficient for calculations
if (Bars-1<MA_Period)return(0);
//----+ Introducing of integer variables and getting bars already counted
int reset,MaxBar,MaxBarP,bar,Limit,counted_bars=IndicatorCounted();
//---- check for possible errors
if (counted_bars<0)return(-1);
//---- the last counted bar must be recalculated 
if (counted_bars>0) counted_bars--;
//---- defining the oldest bar number, starting from which all bars 
//will be recalculated
MaxBar=Bars-1; MaxBarP=MaxBar-MA_Period;

//---- defining the oldest bar number, starting from which new bars 
//will be recalculated 
Limit=Bars-counted_bars-1; 
 
//---- Indicator calculation
for (bar=Limit; bar>=0; bar--)
   { 
    //----+ 
     Price=PriceSeries(Input_Price_Customs,bar);
     //----+ getting the initial indicator
     //----+ Call for function ParMASeries numbered as 0
     Resalt=ParMASeries(0,MaxBar,Limit,MA_Period,Price,bar,reset); 
     //----+ check for errors in the preceding operation
     if(reset!=0)return(-1);
     //----+ JMA smoothing of the obtained indicator, 
     //parameter nJMA.MaxBar is decreased by MA_Period 
     //----+ Call for function JJMASeries numbered as 0, 
     // parameters nJMA.Phase and nJMA.Length do not change on each bar
     // (nJMA.din=0)
     JResalt=JJMASeries(0,0,MaxBarP,Limit,Phase,Length,Resalt,bar,reset);
     //----+ check for errors in the preceding operation
     if(reset!=0)return(-1);
     IndBuffer[bar]=JResalt;
   }
 //----
  return(0);
 }
 
//+-------------------------------------------------------------------+

Em todos os indicadores, a matriz de série de tempo geralmente aplicada Close[] é substituída pela função PriceSeries(). O seu uso não deve causar quaisquer problemas:

double  PriceSeries(int Input_Price_Customs, int bar)

O parâmetro Input_Price_Customs pode variar entre 0 e 14. Dependendo do valor desse parâmetro, a função irá devolver o valor do preço relativo ao gráfico atual pelo número da barra usada como o segundo parâmetro: 0-CLOSE (FECHADO), 1-OPEN (ABERTO), 2-HIGH (ALTO), 3-LOW (BAIXO), 4-MEDIAN (MÉDIO), 5-TYPICAL (TÍPICO), 6-WEIGHTED (PONDERADO), 7-Heiken Ashi Close, 8-SIMPL, 9-TRENDFOLLOW, 10-0. 5*TRENDFOLLOW, 11-Heiken Ashi High, 12-Heiken Ashi Low, 13-Heiken Ashi Open, 14-Heiken Ashi Close. Se necessário, algumas outras expressões algébricas podem ser escritas nos casos das funções para definir os preços de entrada com base nas matrizes de série de tempo. Indicadores o uso da função PriceSeries() é de grande valia na otimização e teste dos expert advisors.

Conclusão

Em NK_library.zip, temos mais de uma centena de indicadores escritos através do uso desses algoritmos. Esses exemplos são mais do que suficientes para aprendermos como usar as funções descritas nesse artigo para a escrita de quaisquer outros indicadores. Todos os indicadores contidos no arquivo zip com essas versões de funções de nivelamento suportam expert advisors e trabalham com eles sem falhas. Exceções são os indicadores contendo HTF no fim de seus nomes. Esses indicadores, devido à especificidade de seus cálculos, não podem ser usados com expert advisors! Os indicadores das pastas de arquivos zip file devem ser colocados na pasta de programas do terminal do cliente MetaTrader4: \MetaTrader\EXPERTS\indicators. As funções propriamente ditas estão em um arquivo zip na pasta INCLUDE. Todo o conteúdo dessa pasta deve ser colocado na pasta de programas do terminal do cliente MetaTrader4: \MetaTrader\EXPERTS\INCLUDE.

Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/1450

Arquivos anexados |
NK_library.zip (1939.17 KB)
Indicadores tricolores e algumas oportunidades para a simplificação máxima de indicadores de escrita Indicadores tricolores e algumas oportunidades para a simplificação máxima de indicadores de escrita
Neste artigo o autor se debruça sobre algumas maneiras de aumentar o valor informacional dos indicadores para negociações visuais. O autor analisa a realização de indicadores tricolores, indicadores, para descobrir quais dados de outros períodos de tempo são usados, e continua a se debruçar na biblioteca de indicadores, descrita no artigo "Cálculo efetivo da média com atraso mínimo: Uso em indicadores"
Funcionamento do MetaTrader 4 na presença de anti-vírus e firewalls Funcionamento do MetaTrader 4 na presença de anti-vírus e firewalls
A maioria dos traders utiliza programas especiais para proteger os seus PCs. Infelizmente, estes programas não somente protegem os computadores contra invasões, vírus e trojans, mas também consomem uma quantidade significativa de recursos. Isto tem a ver com o tráfego da rede, antes de tudo, que é completamente controlado por vários anti-vírus e firewalls inteligentes. O motivo da escrita deste artigo foram as reclamações dos traders com relação ao funcionamento lento do terminal de cliente do MetaTrader 4 na preseça do firewall "Outpost". Nós decidimos realizar a nossa própria pesquisa usando o Kaspersky Antivirus 6.0 e o Outpost Firewall Pro 4.0.
O ABC das negociações no Forex O ABC das negociações no Forex
O trabalho em mercados financeiros representa, antes de tudo, operações de comércio. Todos nós, desde a infância, temos uma ideia intuitiva do que significa comprar e vender. Mas as negociações no Forex são algo especial. Este artigo trata das ideias necessárias à explicação de alguns termos. Nós também vamos abordar as funções do MQL4 que correspondem a esses termos.
Alertas sonoros em indicadores Alertas sonoros em indicadores
Como criar indicadores de "voz" para uso diário.