- Principales características de los indicadores
- Evento indicador principal: OnCalculate
- Dos tipos de indicadores: para la ventana principal y para la subventana
- Ajuste del número de buffers y gráficos
- Asignación de un array como buffer: SetIndexBuffer
- Configuración de plot: PlotIndexSetInteger
- Reglas de asignación de buffers y gráficos
- Aplicación de directivas para personalizar plots
- Configuración de nombres de plots
- Visualización de las carencias de datos (elementos vacíos)
- Indicadores de subventanas independientes: tamaños y niveles
- Propiedades generales de los indicadores: precisión del título y del valor
- Coloreado de gráficos por elementos
- Omitir dibujo en barras iniciales
- Esperar datos y gestionar la visibilidad (DRAW_NONE)
- Indicadores multidivisa y multitemporal
- Seguimiento de formación de barras
- Comprobación de indicadores
- Limitaciones y ventajas de los indicadores
- Crear un borrador de indicador en el Asistente MQL
Omitir dibujo en barras iniciales
En muchos casos, según las condiciones del algoritmo, el cálculo de los valores del indicador no puede iniciarse desde la primera barra (la más a la izquierda disponible), ya que se requiere garantizar el número mínimo especificado de barras anteriores en el historial. Por ejemplo, muchos tipos de suavizado implican que el valor actual se calcula utilizando un array de precios para las N barras anteriores.
En tales casos, puede que no sea posible calcular los valores de los indicadores en las primeras barras, o que estos valores no estén destinados a mostrarse en el gráfico y sólo sean auxiliares para calcular los valores posteriores.
Para desactivar la visualización del indicador en las primeras N-1 barras del historial, establezca la propiedad PLOT_DRAW_BEGIN en N para el índice del trazado correspondiente: PlotIndexSetInteger(index, PLOT_DRAW_BEGIN, N). Por defecto, esta propiedad es 0, lo que significa que los datos se muestran desde el principio.
Podemos desactivar la visualización de líneas en las barras necesarias estableciéndolas en un valor vacío (EMPTY_VALUE por defecto). No obstante, la llamada a la función PlotIndexSetInteger hace algo más con la propiedad PLOT_DRAW_BEGIN. De este modo, indicamos a los programas externos el número de primeros valores insignificantes de nuestro búfer de indicadores. En concreto, otros indicadores que potencialmente puedan construirse basándose en las series temporales de nuestro indicador recibirán el valor de la propiedad PLOT_DRAW_BEGIN en el parámetro begin de su manejador OnCalculate. Así, tendrán la oportunidad de saltarse barras.
En el ejemplo del indicador IndColorWPR.mq5, añadamos una configuración similar a la función OnInit.
input int WPRPeriod = 14; // Period
|
Ahora, en la función OnCalculate, sería posible eliminar el borrado forzado de las primeras barras, ya que siempre estarán ocultas.
if(prev_calculated == 0)
|
Pero esto funcionará correctamente sólo cuando el usuario haya seleccionado manualmente nuestro indicador como fuente de series temporales para otro indicador. Si algún programador decide utilizar nuestro indicador en sus desarrollos, entonces existe un mecanismo diferente para obtener los datos (hablaremos de ello en el próximo capítulo), y no le permitirá averiguar la propiedad PLOT_DRAW_BEGIN. Por lo tanto, es mejor utilizar una inicialización explícita del búfer.
Para demostrar cómo se puede utilizar esta propiedad en otro indicador calculado utilizando los datos de nuestro indicador vamos a preparar otro indicador: se trata del conocido algoritmo de la Media Móvil Exponencial Triple integrado en el indicador IndTripleEMA.mq5. Cuando esté listo, será fácil aplicarlo tanto a series temporales de precios como a indicadores arbitrarios, como el indicador IndColorWPR.mq5 anterior.
Además, nos familiarizaremos con la posibilidad técnica de describir búferes auxiliares para cálculos (INDICATOR_CALCULATIONS).
La triple fórmula EMA consta de varios pasos computacionales. El suavizado exponencial simple del período P para la serie temporal inicial T se expresa del siguiente modo:
K = 2.0 / (P + 1)
|
donde K es el factor de ponderación para tener en cuenta los elementos de la serie original, calculado después de un período determinado P; (1 - K) es el coeficiente de inercia aplicado a los elementos de la serie suavizada A. Para obtener el elemento i-ésimo de la serie A, sumamos la parte K-ésima del elemento i-ésimo de la serie original T[i] y la parte (1 - K)-ésima del elemento anterior A[i - 1].
Si denotamos el suavizado según las fórmulas indicadas como el operador E, entonces la EMA triple incluye, como su nombre indica, la aplicación de E tres veces, tras lo cual las tres filas suavizadas resultantes se combinan de un modo especial.
EMA1 = E(A, P), for all i
|
La EMA triple proporciona un retraso menor respecto a la serie original en comparación con la EMA normal del mismo periodo. Sin embargo, se caracteriza por una mayor capacidad de respuesta, lo que puede provocar irregularidades en la línea resultante y dar señales falsas.
El suavizado EMA permite obtener una estimación aproximada de la media, ya a partir del segundo elemento de la serie, y para ello no es necesario cambiar el algoritmo. Esto distingue a la EMA de otros métodos de suavizado que requieren P elementos previos o un algoritmo modificado para las muestras iniciales si se dispone de menos de P elementos. Algunos desarrolladores prefieren invalidar los primeros elementos P-1 de una fila suavizada incluso cuando se utiliza la EMA. Sin embargo, debe tenerse en cuenta que la influencia de los elementos anteriores de la serie en la fórmula EMA no se limita a P elementos, y se vuelve despreciable sólo cuando el número de elementos tiende a infinito (en otros algoritmos MA bien conocidos, exactamente P elementos anteriores tienen una influencia).
A los efectos de este libro, para investigar el impacto de omitir los datos iniciales, no desactivaremos la salida de los valores iniciales de la EMA.
Para calcular los tres niveles de EMA necesitamos búferes auxiliares y uno más para la serie final: se mostrará como un gráfico de líneas.
#property indicator_chart_window
|
Una variable de entrada InpPeriodEMA permite establecer el periodo de suavizado. La segunda variable, InpHandleBegin, es un conmutador de modo con el que podemos explorar cómo reacciona el indicador al tener en cuenta, o ignorar, el parámetro begin en el manejador OnCalculate. Los modos disponibles se resumen en la enumeración BEGIN_POLICY y significan lo siguiente (en el orden en que están dispuestos):
- turno estricto según begin
- validación personalizada de los datos iniciales, sin tener en cuenta begin
- sin manipulación, es decir, ignorando begin y calculando directamente todos los datos
enum BEGIN_POLICY
|
El segundo modo CUSTOM (personalizado) se basa en una comparación preliminar de cada elemento fuente con EMPTY_VALUE y su sustitución por un valor adecuado para el algoritmo. Esto funcionará correctamente sólo con aquellos indicadores que inicialicen honestamente el comienzo no utilizado de los búferes sin dejar basura allí. Nuestro indicador IndColorWPR rellena el búfer según sea necesario, por lo que puede esperar resultados casi idénticos con los modos STRICT (estricto) y CUSTOM.
Se prepara la constante K para calcular la EMA a partir de InpPeriodEMA.
const double K = 2.0 / (InpPeriodEMA + 1); |
La función EMA en sí es bastante sencilla (aquí se omite el fragmento de protección para la variante CUSTOM con comprobaciones EMPTY_VALUE).
void EMA(const double &source[], double &result[], const int pos, const int begin = 0)
|
Y aquí está el cálculo completo del triple suavizado en OnCalculate.
int OnCalculate(const int rates_total,
|
Durante el primer arranque o cuando se actualiza el historial, el valor recibido del parámetro begin junto con el modo de procesamiento seleccionado por el usuario se escriben en el registro.
Tras la correcta compilación, todo está listo para los experimentos.
En primer lugar, vamos a ejecutar el indicador IndColorWPR (por defecto, su período es 14, lo que significa, de acuerdo con los códigos fuente, establecer la propiedad PLOT_DRAW_BEGIN a 1 menos, ya que la indexación comienza a partir de 0 y la 13ª barra será la primera para la que aparecerá un valor). A continuación, arrastre el indicador IndTripleEMA a la subventana que muestra WPR. En el cuadro de diálogo de configuración de propiedades que se abre, en la pestaña Options, seleccione Previous indicator data en la lista desplegable Apply to. Deje los valores por defecto en la pestaña Inputs.
En la siguiente imagen se muestra el inicio del gráfico. El registro tendrá la siguiente entrada: begin=13 STRICT.
Indicador EMA triple aplicado al WPR dado el inicio de los datos
Tenga en cuenta que la línea promediada comienza a una distancia del inicio, así como WPR.
¡Atención! El número de barras disponibles para el cálculo del indicador rates_total (o iBars(_Symbol, _Period)) puede superar el número máximo de barras permitido en el gráfico desde la configuración del terminal si existe un historial local de cotizaciones más largo. En este caso, los elementos vacíos al principio de la línea WPR (o cualquier otro indicador que se salte los primeros elementos, como MA) se volverán invisibles: se ocultarán tras el borde izquierdo del gráfico. Para reproducir la situación de ausencia de líneas en las barras iniciales, deberá aumentar el número de barras del gráfico o cerrar el terminal y borrar el historial local de un símbolo determinado.
Ahora vamos a cambiar al modo CUSTOM en los ajustes del indicador IndTripleEMA (el registro mostrará begin=0 CUSTOM). No debería haber ningún cambio importante en las lecturas de los indicadores.
Por último, activamos el modo NONE (ninguno). El registro mostrará begin=0 NONE.
En este caso, la situación en el gráfico parecerá extraña, ya que la línea de hecho desaparecerá. En la ventana de datos puede ver que los valores de los elementos son muy grandes.
Indicador EMA triple aplicado a WPR sin inicio de datos
Esto se debe a que los valores de EMPTY_VALUE son iguales al número real máximo DBL_MAX. Por lo tanto, sin tener en cuenta el parámetro begin, los cálculos con tales valores también generan números muy grandes. Dependiendo de las particularidades del cálculo, el desbordamiento puede hacer que recibamos un NaN especial (Not A Number, véase Comprobación de la normalidad de los números reales). Uno de ellos, -nan(ind), está resaltado en la imagen (Data Window ya sabe cómo mostrar algunos tipos de NaN, como por ejemplo, «inf» e «-inf», pero esto todavía no se aplica a «-nan(ind)»). Como sabemos, estos valores NaN son peligrosos, ya que los cálculos que los incluyan también seguirán dando NaN. Si no se genera ningún NaN, entonces, a medida que se desplace hacia la derecha a través de las barras, el «proceso transitorio» en el cálculo de números grandes se desvanece (debido al factor de reducción (1 - K) en la fórmula EMA), y el resultado se estabiliza, volviéndose razonable. Si se desplaza por el gráfico hasta el momento actual, verá una EMA triple normal.
Tener en cuenta el parámetro begin es una buena práctica, pero no garantiza que el proveedor de datos (si se trata de un indicador de terceros) haya rellenado correctamente esta propiedad. Por lo tanto, es deseable proporcionar cierta protección en su código. En esta implementación de IndTripleEMA, se implementa en el nivel inicial.
Si ejecutamos el indicador IndTripleEMA en el gráfico de precios, siempre recibirá begin = 0, ya que las series temporales de precios se rellenan con datos reales desde el principio, incluso en las barras más antiguas.