Promediación efectiva de algoritmos con retraso mínimo: Uso en indicadores
Nikolay Kositsin | 11 mayo, 2016
Introducción
Creo que no es necesario explicar lo importante que es refinar los algoritmos para el análisis técnico y los sistemas de trading. Los códigos de casi todos los indicadores contienen algoritmos de promediación explícitos o implícitos. Si miramos más de cerca las plataformas de trading y los terminales de cliente en línea, la mayoría de ellos y la mayoría de indicadores resultan ser los más sencillos (aunque no los más efectivos) algoritmos de promediación.
Actualmente se han desarrollado algoritmos de promediación mucho más efectivos. No obstante, el intento de aplicarlos a los indicadores suele, debido a la gran complejidad de los algoritmos, dar como resultado que los programadores no tengan la paciencia suficiente y que creen como mucho uno o dos indicadores que de ningún modo operan siempre de forma correcta. Después de todo, suelen estar cansados de trabajar en este sentido. La ventaja básica de las medias simples es que siempre están disponibles como funciones personalizadas sencillas que pueden aplicarse en cualquier lugar y en cualquier momento.
Tema central
En este artículo me gustaría explicar a los traders que conocen MQL4 los algoritmos de promediación efectivos con un retraso mínimo representados como simples funciones personalizadas. El uso de estas funciones no es mucho más complejo que el de los indicadores técnicos. Las funciones se escribieron mucho antes y la calidad de su funcionamiento también ha sido comprobada durante bastante tiempo. En ellos no se han encontrado fallos, problemas ni cálculos incorrectos. Por ello, vamos a considerar los siguientes algoritmos:- JJMASeries () - algoritmo adaptativo de ajuste de JMA;
- JLiteSeries() - algoritmo de ajuste de JMA sin algoritmo adaptativo;
- JurXSeries () - algoritmo de ajuste ultralineal obtenido del indicador JRSX;
- ParMASeries() - algoritmo de ajuste basado en una aproximación parabólica;
- LRMASeries () - algoritmo de ajuste basado en una progresión lineal;
- T3Series () - algoritmo de ajuste basado en el algoritmo Tilson.
Ajuste de funciones
Las funciones se representan en los archivos siguientes: JJMASeries.mqh, JLiteSeries. mqh, JurXSeries. mqh, ParMASeries.mqh, LRMASeries.mqh, T3Series.mqh.Las llamadas a las propias funciones son absolutamente idénticas, la única diferencia es que algunas funciones no tienen algunas variables externas. Dichas funciones se suelen utilizar para procesar matrices personalizadas y de indicadores que operan como variables externas. En mi opinión, no siempre es adecuado, por lo que sería mucho mejor usar estas funciones para procesar variables normales, no matrices. En este caso, podemos hacer una cantidad ilimitada de ajustes usando estos algoritmos en un solo ciclo de cómputo. Creo que no es necesario proporcionar el código de estas funciones en este artículo. El código será interesante solo para aquellos que vayan a crear funciones similares basadas en otros algoritmos. Nos interesa solo el algoritmo de llamada a la función en el código del indicador, es decir, en el uso práctico de las funciones.
JJMASeries ()
Empezaremos aprendiéndolas con la función JJMASeries():
double JJMASeries(int number, int din, int MaxBar, int limit, int Phase, int Length, double series, int bar, int& reset)
El archivo JJMASeries.mqh contiene cuatro funciones: JJMASeries(), JJMASeriesResize(), JJMASeriesAlert() y JMA_ErrDescr(). El archivo contiene también las variables declaradas como globales.
La función JJMASeries() tiene por finalidad usar el algoritmo JMA al escribir cualquier indicador técnico o asesor experto, para sustituir el clásico cálculo de promediación con este algoritmo. La función no opera si el parámetro 'limit' toma el valor cero. Todos los indicadores que he desarrollado para JJMASeries están diseñados teniendo en cuenta esta limitación. El archivo debe guardarse en la carpeta MetaTrader\experts\include\. Debe recordarse que si el valor de la variable 'bar' supera el de la variable MaxBar, la función JJMASeries() devolverá un valor cero para esta barra. Y, por tanto, este valor puede no estar presente como término de una fracción en los cálculos de algunos indicadores. JJMASeries() también devolverá cero en las consiguientes 30 barras.
Esta versión de JJMASeries() ayuda a los asesores expertos cuando funciona en los indicadores personalizados usados por el asesor experto. Además, esta versión de JJMASeries() ayuda a los asesores expertos cuando funciona en el código del indicador colocado completamente en el código del experto y manteniendo todas las declaraciones y variables DO. Al escribir código para los indicadores o asesores expertos usando JJMASeries, no se recomienda nombrar las variables con nombre que comiencen por nJMA o dJMA. . La función JJMASeries() puede utilizarse en el código interno de otras funciones personalizadas siempre que se tenga en cuenta que cada llamada a JJMASeries() debe tener su número único en cada llamada para dicha función personalizada. Esta versión de JJMASeries() tiene por finalidad procesar variables relativas a matrices de series de tiempo del gráfico actual. Si se utiliza esta función para procesar variables en matrices de series de tiempo de otros gráficos, los cálculos serán incorrectos.
Entradas:
- number - el número de la llamada a la función JJMASeries() en el código del indicador (0, 1, 2, 3, ...);
- din - parámetro que permite modificar los parámetros Longitud y Fase en cada barra. 0 - los parámetros no pueden cambiarse, cualquier otro valor permite cambiar los parámetros;
- MaxBar - valor máximo del número de barra calculado. Normalmente, es en Bars-1-period donde "período" es la cantidad de barras en que el valor de las series iniciales no se calcula;
- limit - cantidad de barras no calculadas más una o el número de la última barra no calculada. Debe ser igual a Bars-IndicatorCounted()-1;
- Length - profundidad de promediación;
- Phase - parámetro que cambia en el rango comprendido entre -100 y +100. Afecta a la calidad del proceso transitorio;
- series - entrada subyacente al cálculo de JJMASeries();
- bar - el número de la barra a calcular. Este parámetro debe ser cambiado por la declaración DO desde el valor máximo a cero. Su valor máximo siempre debe ser igual al valor de 'limit'.
Parámetros de salida:
- JMASeries() - valor de JMA. Si el valor del parámetro 'bar' supera MaxBar-30, la función JJMASeries() siempre devuelve cero.
- reset - parámetro que devuelve por referencia un valor distinto a 0 si se produce un error en el cálculo de la función y devuelve 0 si el cálculo fue correcto. Este parámetro solo puede ser variable, pero no un valor.
Inicialización de la función
Antes de llamar a la función JJMASeries(), cuando la cantidad de barras ya calculadas es igual a 0, las variables del búfer interno de la función deben redimensionarse (sería incluso mejor hacerlo en el bloque de inicialización del indicador personalizado o del asesor experto). Para ello, es necesario llamar a las variables de JJMASeries() usando la función de ayuda JJMASeriesResize() con los parámetros siguientes: JJMASeriesResize(número+1); es necesaria para hacer que el parámetro 'number' (MaxJMA.number) sea igual a la cantidad de llamadas para JJMASeries, es decir, superior en 1 al valor máximo de 'number'. Junto con el redimensionamiento de los búferes de JJMASeries(), es posible comprobar en el bloque de inicialización los valores de entrada del indicador Length y Phase que son entradas de JJMASeries(), para ver si quedan dentro de su rango de cambio usando JJMASeriesAlert():
JJMASeriesAlert(int Number, string name, int ExternVar)
- Number - parámetro que puede tomar dos valores: 0 - para comprobar la entrada ExternVar para ver si cae dentro del rango de cambio de la entrada Length de JJMASeries() y 1 - para comprobar la entrada ExternVar para ver si cae dentro del rango de cambio de la entrada Phase de JJMASeries();
- name - nombre de la entrada ExternVar para proporcionar una alerta;
- ExternVar - entrada del indicador
Indicación del error
Cuando se depuran, los códigos de los indicadores o asesores expertos pueden contener errores. Para encontrar las causas de los errores es necesario ver el archivo de registro. La función JJMASeries() registra todos los errores en un archivo de registro en la carpeta llamada \MetaTrader\EXPERTS\LOGS\. Si se produce un error de MQL4 en el código que precede a la función JJMASeries() antes de llamar a esta función, la función registrará el código de error y el contenido de este en un archivo de registro. Si se produce un error de MQL4 en el algoritmo de JJMASeries() durante la ejecución de esta función, la función registrará también el código de error y el contenido de este en un archivo de registro. Si la llamada a la función JJMASeries() 'number' se especificó de forma incorrecta o definiendo incorrectamente el tamaño de las variables del búfer nJJMAResize.Size, los mensajes sobre los parámetros incorrectos serán grabados en el archivo de registro. La información sobre las definiciones incorrectas del parámetro 'limit' se grabarán también en el archivo de registro.
Si hay un fallo en el redimensionamiento de los búferes de JJMASeries durante la ejecución de la función init(), la función JJMASeriesResize() registrará información sobre el redimensionamiento fallido en el archivo de registro. Si se incumple la secuencia correcta de cambio del parámetro 'bar' al llamar a la función JJMASeries() a través de una declaración DO externa, esta información quedará grabada también en el archivo de registro. Debe tenerse en cuenta que algunos errores en el código producirán más errores en su ejecución, por ello, si la función JJMASeries() registra varios errores en el archivo de registro al mismo tiempo, estos errores deberán ser eliminados por orden de aparición. En un indicador escrito correctamente, la función JJMASeries() puede realizar registros en el archivo de registro utilizando solo desajustes del sistema. Una excepción es el registro del redimensionamiento de las variables del búfer en el reinicio del indicador o asesor experto que ocurre en cada llamada a la función init(). Todos los errores MQL4 se graban en el archivo de registro usando la función JMA_ErrDescr() limpia el código y el contenido del error de acuerdo a su código obtenido usando la función GetLastError() en el archivo de registro.
Llamada a la función JJMASeries() de ejemplo (doble ajuste JMA del precio 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); } //+--------------------------------------------------------+
De este modo, pueden destacarse los siguientes puntos en la aplicación de esta función:
1. Declaración de funciones que son parte del archivo JJMASeries.mqh con la línea #include al comienzo del código del indicador. Se declaran las variables y cuatro funciones: JJMASeries(), JJMASeriesResize(), JJMASeriesAlert(), JMA_ErrDescr().
2. Redimensionamiento de los elementos del búfer por la función JJMASeries() usando la función JJMASeriesResize() en el bloque de inicialización.
3. Comprobar usando la función JJMASeriesAlert() en el bloque de inicialización si los valores de las variables externas del indicador que son variables externas de la función JJMASeries() son correctos.
4. Llamadas a la propia función JJMASeries() realizadas mediante el uso de declaraciones DO con control de error relevante.
Otras funciones
El algoritmo para la llamada a otras funciones es muy similar al algoritmo anterior, pero hay algunas diferencias en la cantidad de variables externas disponibles en las funciones: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 )
Debe observarse que las funciones JJMASeries() y JLiteSeries() no son compatibles en el mismo asesor experto o indicador. De hecho, el propio código JMA con el nombre de la función de JJMASeries() se coloca en el archivo JLiteSeries.mqh sin ninguna adaptación. Para sustituir la función JJMASeries() por la función JLiteSeries() en un asesor experto o indicador, es suficiente con sustituir la línea #include por #include. Todas las llamadas a las funciones del archivo JLiteSeries.mqh se consideran llamadas a las funciones idénticas a aquellas usadas para las funciones del archivo JJMASeries.mqh.
Otras funciones son totalmente compatibles dentro del mismo código del indicador o asesor experto. En las funciones ParMASeries() y LRMASeries(), el valor de la variable externa 'period' está limitado a 501. Si son necesarios valores mayores, es necesario cambiar los primeros (no cero) de los búferes dParMA.TempBuffer[][501] y dParMA.TEMPBUFFER[][501] para la función ParMASeries() o dLRMA.TempBuffer[][501] y dLRMA.TEMPBUFFER[][501] para la función LRMASeries() en los archivos ParMASeries.mqh y LRMASeries.mqh, respectivamente. >
Función JurXSeries()
A continuación se muestra una llamada a la función JurXSeries() de ejemplo (ajuste ultralineal del precio de entrada con ajuste 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); } //+-------------------------------------------------------------------------+
En este ejemplo, debe recordarse que la función JurXSeries() promedia el precio de entrada y la constante. Al haber dividido el resultado promedio por el valor de la constante, obtendremos el error de ajuste. Para obtener resultados más precisos del ajuste de las series de precios, es necesario dividir el resultado del ajuste por el valor de este error. En nuestro caso esto ya lo hemos hecho. En los dos casos siguientes, el numerador y el denominador se ajustan de forma independiente, por lo que no es necesario el procedimiento anterior. Dicho error no se produce para las demás funciones de ajuste.
A continuación se muestra un ejemplo de llamada a las funciones JJMASeries() y JurXSeries() (CCI análogo con ajuste 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); } //+-------------------------------------------------------------------+
Debe tenerse en cuenta el hecho siguiente: Después de dos ajuste en la función JurXSeries(), uno de los valores obtenidos será comprobado por si no es igual a cero, ya que es un denominador.
A continuación se muestra un ejemplo de llamada a las funciones JJMASeries() y JurXSeries() (RSI análogo con ajuste 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); } //+------------------------------------------------------------------+
Funciones T3Series()
A continuación se muestra una llamada a la función T3Series() de ejemplo (tres bandas de Bollinger con ajuste T3 adicional):
/* 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); } //+-------------------------------------------------------------------+
Funciones ParMASeries()
A continuación se muestra una llamada a la función ParMASeries() de ejemplo (ParMA moviéndose con ajuste JMA adicional):
/* 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); } //+-------------------------------------------------------------------+
En todos los indicadores, la matriz de series de tiempo normalmente utilizada Close[] es sustituida por la función PriceSeries(). Su uso no debe causar ningún problema.
double PriceSeries(int Input_Price_Customs, int bar)
El parámetro Input_Price_Customs puede variar entre 0 y 14. Dependiendo del valor de este parámetro, la función devuelve el valor del precio para el gráfico actual por el número de barras usadas como segundo parámetro: 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. Si es necesario, pueden escribirse algunas expresiones en las instancias de la función para definir los precios de entrada sobre la base de las matrices de series de tiempo. Los indicadores que usan la función PriceSeries() son de mucha ayuda en la optimización y prueba de los asesores expertos.
Conclusión
En NK_library.zip hay más de un centenar de indicadores escritos usando estos algoritmos. Estos ejemplos son más que suficientes para aprender a usar las funciones descritas en estos artículos para escribir cualquier otro indicador. Todos los indicadores del archivo zip con estas versiones de funciones de ajuste ayudan a los asesores expertos y colaboran con ellos sin fallar. Las excepciones son los indicadores con las letras HTF al final. Estos indicadores, debido a lo específico de su cálculo, no pueden utilizarse con los asesores expertos. Los indicadores de las carpetas del archivo zip deben colocarse en la carpeta del programa del terminal de cliente de MetaTrader 4: \MetaTrader\EXPERTS\indicators. Las propias funciones están en un archivo zip en la carpeta INCLUDE. Todo el contenido de esa carpeta debe colocarse en la carpeta del programa del terminal de cliente de MetaTrader 4: \MetaTrader\EXPERTS\INCLUDE.