- Manejadores y contadores de propietarios de indicadores
- Una forma sencilla de crear instancias de indicadores: iCustom
- Comprobación del número de barras calculadas: BarsCalculated
- Obtención de datos de series temporales a partir de un indicador: CopyBuffer
- Soporte para múltiples símbolos y marcos temporales
- Visión general de los indicadores integrados
- Utilización de los indicadores integrados
- Forma avanzada de crear indicadores: IndicatorCreate
- Creación flexible de indicadores con IndicatorCreate
- Visión general de las funciones de gestión de indicadores en el gráfico
- Combinar salida a ventanas principal y auxiliar
- Leer datos de gráficos que tienen un desplazamiento
- Borrar instancias de indicadores: IndicatorRelease
- Obtener la configuración del indicador por su manejador
- Definir la fuente de datos de un indicador
Borrar instancias de indicadores: IndicatorRelease
Como se ha mencionado en la parte introductoria de este capítulo, el terminal mantiene un contador de referencia para cada indicador creado y lo deja en funcionamiento mientras al menos un programa MQL o gráfico lo utilice. En un programa MQL, una señal de la necesidad de un indicador es un manejador válido. Normalmente, pedimos un manejador durante la inicialización y lo utilizamos en algoritmos hasta el final del programa.
En el momento en que se descarga el programa, todos los manejadores únicos creados se liberan automáticamente, es decir, sus contadores se decrementan en 1 (y si llegan a cero, esos indicadores también se descargan de la memoria). Por lo tanto, no es necesario liberar explícitamente el manejador.
No obstante, hay situaciones en las que un subindicador resulta innecesario durante el funcionamiento del programa. Entonces, el indicador inútil sigue consumiendo recursos. Por lo tanto, usted debe liberar explícitamente el manejador con IndicatorRelease.
bool IndicatorRelease(int handle)
La función borra el manejador del indicador especificado y descarga el propio indicador si nadie más lo utiliza. La descarga se produce con un ligero retraso.
La función devuelve un indicador de éxito (true) o de errores (false).
Tras la llamada a IndicatorRelease, el manejador que se ha pasado deja de ser válido, aunque la propia variable conserva su valor anterior. Un intento de utilizar tal manejador en otras funciones de indicador como CopyBuffer fallará con el error 4807 (ERR_INDICATOR_WRONG_HANDLE). Para evitar malentendidos, es conveniente asignar el valor INVALID_HANDLE a la variable correspondiente inmediatamente después de liberar el manejador.
No obstante, si a continuación el programa solicita un manejador para un nuevo indicador, lo más probable es que ese manejador tenga el mismo valor que el liberado anteriormente, pero ahora estará asociado a los datos del nuevo indicador.
Cuando se trabaja en el comprobador de estrategias, no se realiza la función IndicatorRelease.
Para demostrar la aplicación de IndicatorRelease, vamos a preparar una versión especial de UseDemoAllLoop.mq5, que recreará periódicamente un indicador auxiliar en un ciclo de la lista, que incluirá sólo indicadores para la ventana principal (para mayor claridad).
IndicatorType MainLoop[] =
|
El primer elemento del array contiene un indicador personalizado como excepción, LifeCycle de la sección Funciones de inicio y parada de programas de diferentes tipos. Aunque este indicador no muestra ninguna línea, es apropiado aquí porque muestra mensajes en el registro cuando se llama a sus manejadores OnInit/OnDeinit, lo que le permitirá rastrear su ciclo de vida. Los ciclos de vida de otros indicadores son similares.
En las variables de entrada, dejaremos sólo los ajustes de renderización. La salida por defecto de las etiquetas DRAW_ARROW es óptima para mostrar diferentes tipos de indicadores.
input ENUM_DRAW_TYPE DrawType = DRAW_ARROW; // Drawing Type
|
Para recrear los indicadores «sobre la marcha» , vamos a ejecutar el temporizador de 5 segundos en OnInit, y toda la inicialización anterior (con algunas modificaciones que se describen a continuación) se trasladará al manejador OnTimer.
int OnInit()
|
La principal diferencia es que el tipo del indicador creado actualmente IndicatorSelector ahora no lo establece el usuario, sino que se selecciona secuencialmente del array MainLoop en el índice Cursor. Cada vez que se llama al temporizador, este índice aumenta cíclicamente, es decir, cuando se llega al final del array, saltamos a su principio.
Para todos los indicadores, la línea con los parámetros está vacía. Esto se hace para unificar su inicialización. Como resultado, cada indicador se creará con sus propios valores por defecto.
Al principio del manejador OnTimer, llamamos a IndicatorRelease para el manejador anterior. Sin embargo, hemos proporcionado una variable de entrada ClearHandles para desactivar la rama de operadores if dada y ver lo que sucede si no limpia los manejadores.
input bool ClearHandles = true; |
Por defecto, ClearHandles es igual a true, es decir, los indicadores se borrarán como se espera.
Por último, otro ajuste adicional son las líneas que permiten borrar los búferes y solicitar un redibujado completo del gráfico. Ambas son necesarias, pues hemos sustituido el indicador esclavo que suministra los datos visualizados.
El manejador OnCalculate no ha cambiado.
Vamos a ejecutar UseDemoAllLoop con la configuración por defecto. En el registro aparecerán las siguientes entradas (sólo se muestra el principio):
UseDemoAllLoop (EURUSD,H1) Initializing LifeCycle() EURUSD, PERIOD_H1 UseDemoAllLoop (EURUSD,H1) Handle=10 LifeCycle (EURUSD,H1) Loader::Loader() LifeCycle (EURUSD,H1) void OnInit() 0 DEINIT_REASON_PROGRAM UseDemoAllLoop (EURUSD,H1) Initializing iAlligator_jawP_jawS_teethP_teethS_lipsP_lipsS_method_price() EURUSD, PERIOD_H1 UseDemoAllLoop (EURUSD,H1) iAlligator_jawP_jawS_teethP_teethS_lipsP_lipsS_method_price requires 8 parameters, 0 given UseDemoAllLoop (EURUSD,H1) Handle=10 LifeCycle (EURUSD,H1) void OnDeinit(const int) DEINIT_REASON_REMOVE LifeCycle (EURUSD,H1) Loader::~Loader() UseDemoAllLoop (EURUSD,H1) Initializing iAMA_period_fast_slow_shift_price() EURUSD, PERIOD_H1 UseDemoAllLoop (EURUSD,H1) iAMA_period_fast_slow_shift_price requires 5 parameters, 0 given UseDemoAllLoop (EURUSD,H1) Handle=10 UseDemoAllLoop (EURUSD,H1) Initializing iBands_period_shift_deviation_price() EURUSD, PERIOD_H1 UseDemoAllLoop (EURUSD,H1) iBands_period_shift_deviation_price requires 4 parameters, 0 given UseDemoAllLoop (EURUSD,H1) Handle=10 ... |
Fíjese en que obtenemos siempre el mismo «número» de manejador (10) porque lo liberamos antes de crear un nuevo manejador.
También es importante que el indicador LifeCycle se descargue poco después de que lo hayamos liberado (suponiendo que no se haya añadido al mismo gráfico por sí mismo, porque entonces su cuenta de referencia no se pondría a cero).
En la siguiente imagen se muestra el momento en que nuestro indicador muestra los datos de Alligator.
UseDemoAllLoop en el paso de demostración de Alligator
Si cambia el valor de ClearHandles a false, veremos una imagen completamente diferente en el registro. A partir de ahora, los números de los manejadores aumentarán constantemente, lo que indica que los indicadores permanecen en el terminal y siguen trabajando, consumiendo recursos en vano. En concreto, no se recibe ningún mensaje de desinicialización del indicador LifeCycle.
UseDemoAllLoop (EURUSD,H1) Initializing LifeCycle() EURUSD, PERIOD_H1 UseDemoAllLoop (EURUSD,H1) Handle=10 LifeCycle (EURUSD,H1) Loader::Loader() LifeCycle (EURUSD,H1) void OnInit() 0 DEINIT_REASON_PROGRAM UseDemoAllLoop (EURUSD,H1) Initializing iAlligator_jawP_jawS_teethP_teethS_lipsP_lipsS_method_price() EURUSD, PERIOD_H1 UseDemoAllLoop (EURUSD,H1) iAlligator_jawP_jawS_teethP_teethS_lipsP_lipsS_method_price requires 8 parameters, 0 given UseDemoAllLoop (EURUSD,H1) Handle=11 UseDemoAllLoop (EURUSD,H1) Initializing iAMA_period_fast_slow_shift_price() EURUSD, PERIOD_H1 UseDemoAllLoop (EURUSD,H1) iAMA_period_fast_slow_shift_price requires 5 parameters, 0 given UseDemoAllLoop (EURUSD,H1) Handle=12 UseDemoAllLoop (EURUSD,H1) Initializing iBands_period_shift_deviation_price() EURUSD, PERIOD_H1 UseDemoAllLoop (EURUSD,H1) iBands_period_shift_deviation_price requires 4 parameters, 0 given UseDemoAllLoop (EURUSD,H1) Handle=13 UseDemoAllLoop (EURUSD,H1) Initializing iDEMA_period_shift_price() EURUSD, PERIOD_H1 UseDemoAllLoop (EURUSD,H1) iDEMA_period_shift_price requires 3 parameters, 0 given UseDemoAllLoop (EURUSD,H1) Handle=14 UseDemoAllLoop (EURUSD,H1) Initializing iEnvelopes_period_shift_method_price_deviation() EURUSD, PERIOD_H1 UseDemoAllLoop (EURUSD,H1) iEnvelopes_period_shift_method_price_deviation requires 5 parameters, 0 given UseDemoAllLoop (EURUSD,H1) Handle=15 ... UseDemoAllLoop (EURUSD,H1) Initializing iVIDyA_momentum_smooth_shift_price() EURUSD, PERIOD_H1 UseDemoAllLoop (EURUSD,H1) iVIDyA_momentum_smooth_shift_price requires 4 parameters, 0 given UseDemoAllLoop (EURUSD,H1) Handle=22 UseDemoAllLoop (EURUSD,H1) Initializing LifeCycle() EURUSD, PERIOD_H1 UseDemoAllLoop (EURUSD,H1) Handle=10 UseDemoAllLoop (EURUSD,H1) Initializing iAlligator_jawP_jawS_teethP_teethS_lipsP_lipsS_method_price() EURUSD, PERIOD_H1 UseDemoAllLoop (EURUSD,H1) iAlligator_jawP_jawS_teethP_teethS_lipsP_lipsS_method_price requires 8 parameters, 0 given UseDemoAllLoop (EURUSD,H1) Handle=11 UseDemoAllLoop (EURUSD,H1) Initializing iAMA_period_fast_slow_shift_price() EURUSD, PERIOD_H1 UseDemoAllLoop (EURUSD,H1) iAMA_period_fast_slow_shift_price requires 5 parameters, 0 given UseDemoAllLoop (EURUSD,H1) Handle=12 UseDemoAllLoop (EURUSD,H1) Initializing iBands_period_shift_deviation_price() EURUSD, PERIOD_H1 UseDemoAllLoop (EURUSD,H1) iBands_period_shift_deviation_price requires 4 parameters, 0 given UseDemoAllLoop (EURUSD,H1) Handle=13 UseDemoAllLoop (EURUSD,H1) Initializing iDEMA_period_shift_price() EURUSD, PERIOD_H1 UseDemoAllLoop (EURUSD,H1) iDEMA_period_shift_price requires 3 parameters, 0 given UseDemoAllLoop (EURUSD,H1) Handle=14 UseDemoAllLoop (EURUSD,H1) void OnDeinit(const int) ... |
Cuando el índice en el bucle sobre el array de tipos de indicadores alcanza el último elemento y dibuja un círculo desde el principio, el terminal empezará a devolver a nuestro código manejadores de indicadores ya existentes (los mismos valores: al manejador 22 le sigue de nuevo el 10).