- 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
Seguimiento de formación de barras
El indicador IndUnityPercent.mq5 comentado en la sección anterior se recalcula en la última barra de cada tick, ya que utiliza los precios de Close. Algunos indicadores y Asesores Expertos se han desarrollado especialmente con un estilo más económico, con un único cálculo en cada barra. Por ejemplo, podríamos calcular la fórmula de Unity a precios de apertura, y entonces tiene sentido saltarse los ticks. Hay varias formas de detectar una nueva barra:
- Recordar la hora de la barra 0 actual (a través del parámetro time de la función OnCalculate - time[0] o, en general, iTime(symbol, period, 0)) y esperar a que cambie.
- Memorizar el número de barras rates_total (o iBars(symbol, period)) y responder a un aumento de 1 (un cambio a una cantidad diferente en un sentido u otro es sospechoso y puede indicar una modificación del historial).
- Esperar una barra con un volumen de ticks igual a 1 (el primer tick de la barra).
Sin embargo, con la naturaleza multidivisa del indicador, el propio concepto de formación de una nueva barra no resulta tan unívoco.
En cada símbolo, la barra siguiente aparece a la llegada de sus propios ticks, y estos suelen tener tiempos de llegada diferentes. En este caso, el desarrollador del indicador debe determinar cómo actuar: si esperar a la aparición de barras con la misma hora en todos los símbolos o recalcular el indicador en las últimas barras varias veces tras la aparición de una nueva barra en cualquiera de los símbolos.
En esta sección introduciremos una clase simple MultiSymbolMonitor (véase el archivo MultiSymbolMonitor.mqh) para seguir la formación de nuevas barras según una lista dada de símbolos.
El marco temporal requerido puede pasarse al constructor de la clase. Por defecto, sigue el marco temporal del gráfico actual, en el que se está ejecutando el programa.
class MultiSymbolMonitor
|
Para almacenar la lista de símbolos rastreados utilizaremos una clase auxiliar MapArray de la sección anterior. En este array escribiremos los pares [nombre del símbolo;marca de tiempo de la última barra], es decir, los tipos de plantilla <string,datetime>. El método attach rellena el array.
protected:
|
Para un array dado, la clase puede actualizar y comprobar las marcas de tiempo en el método check llamando a la función iTime en un bucle sobre símbolos.
ulong check(const bool refresh = false)
|
El código de llamada debe llamar a check a su propia discreción, que suele ser a la llegada de ticks, o en un temporizador. Estrictamente hablando, ambas opciones no proporcionan una reacción instantánea a la aparición de ticks (y nuevas barras) en otros instrumentos, ya que el evento OnCalculate sólo aparece en los ticks del símbolo de trabajo del gráfico, y si entre ellos hubiera un tick de algún otro símbolo, no lo sabríamos hasta el siguiente tick «propio».
Abordaremos el seguimiento en tiempo real de los ticks de varios instrumentos en el capítulo sobre eventos gráficos interactivos (véase el indicador espía EventTickSpy.mq5 en la sección Generación de eventos personalizados).
Por ahora, comprobaremos las barras con la precisión disponible. Así pues, procedamos con el método check.
Cada punto en el tiempo se caracteriza por su propio estado de las marcas de tiempo establecidas para todos los símbolos del array. Por ejemplo, una nueva barra puede formarse a las 12:00 sólo para el instrumento más líquido, y para varios otros instrumentos, los ticks aparecerán en unos pocos milisegundos o incluso segundos. Durante este intervalo, se actualizará un elemento del array y el resto serán antiguos. Luego, gradualmente, todos los símbolos tendrán barras de 12:00.
Para todos los símbolos cuya hora de apertura de la última barra no sea igual a la guardada, el método fija el bit con el número de símbolo, formando así una máscara de bits con cambios. La lista no debe contener más de 64 símbolos.
Si el valor de retorno es cero, no se ha registrado ningún cambio.
El parámetro refresh especifica si el método check sólo registrará los cambios (false), o si actualizará el estado según la situación actual del mercado (true).
El método describe permite obtener una lista de símbolos modificados por una máscara de bits.
string describe(ulong flags = 0)
|
A continuación, utilizaremos inSync para determinar si todos los símbolos del array tienen la misma hora de la última barra. Tiene sentido utilizarlo sólo para un conjunto de divisas con las mismas sesiones de trading.
bool inSync() const
|
Utilizando la clase descrita, implementamos un sencillo indicador multidivisa IndMultiSymbolMonitor.mq5, cuya única tarea será detectar nuevas barras para una lista de símbolos.
Dado que no se proporciona ningún dibujo para el indicador, el número de búferes y gráficos es 0.
#property indicator_chart_window
|
La lista de instrumentos se especifica en la variable de entrada correspondiente y, a continuación, se convierte en un array registrado en el objeto monitor.
input string Instruments = "EURUSD,GBPUSD,USDCHF,USDJPY,AUDUSD,USDCAD,NZDUSD";
|
El manejador OnCalculate llama al monitor cuando se producen ticks y envía los cambios de estado al registro.
int OnCalculate(const int rates_total,
|
Para comprobar este indicador tendríamos que pasar mucho tiempo en línea en el terminal. Sin embargo, MetaTrader 5 le permite hacer esto mucho más fácilmente: con la ayuda de un probador. Lo haremos en la próxima sección.