- Diseño de programas MQL de varios tipos
- Hilos
- Visión general de las funciones de gestión de eventos
- Funciones de inicio y parada de programas de varios tipos
- Eventos de referencia de indicadores y Asesores Expertos: OnInit y OnDeinit
- Función principal de scripts y servicios: OnStart
- Eliminación programática de Asesores Expertos y scripts: ExpertRemove
Eventos de referencia de indicadores y Asesores Expertos: OnInit y OnDeinit
En los programas MQL interactivos (indicadores y Asesores Expertos) el entorno genera dos eventos para preparar el lanzamiento (OnInit) y la parada (OnDeinit). No existe este tipo de eventos en scripts y servicios porque no aceptan eventos asíncronos: después de pasar el control a su único manejador de eventos OnStart y hasta el final del trabajo, el contexto de ejecución del hilo de script/servicio se encuentra en el código del programa MQL. En cambio, para los indicadores y los Asesores Expertos, el curso normal de trabajo supone que el entorno llamará repetidamente a sus funciones específicas de manejo de eventos (hablaremos de ellas en las secciones sobre indicadores y Asesores Expertos), y cada vez, una vez emprendidas las acciones necesarias, los programas devolverán el control al terminal para la espera en reposo de nuevos eventos.
int OnInit()
La función OnInit es un controlador del evento del mismo nombre, que se genera después de cargar un Asesor Experto o un indicador. La función sólo puede definirse en función de las necesidades.
La función debe devolver uno de los valores de la enum ENUM_INIT_RETCODE.
Identificador |
Descripción |
---|---|
INIT_SUCEDED |
Inicialización correcta, puede continuar la ejecución del programa; corresponde al valor 0 |
INIT_FAILED |
Inicialización fallida, no puede continuar la ejecución debido a errores fatales (por ejemplo, no fue posible crear un archivo o un indicador auxiliar); valor 1 |
INIT_PARAMETERS_INCORRECT |
Conjunto incorrecto de parámetros de entrada, la ejecución del programa es imposible |
INIT_AGENT_NOT_SUITABLE |
Código específico para trabajar en el probador: por alguna razón, este agente no es adecuado para las pruebas (por ejemplo, no tiene suficiente RAM, no es compatible con OpenCL, etc.) |
Si OnInit devuelve cualquier código de retorno distinto de cero, significa que la inicialización no ha tenido éxito, y entonces se genera el evento Deinit, con el código de motivo de desinicialización REASON_INITFAILED (véase más abajo).
La función OnInit puede declararse con un tipo de resultado void: en este caso, la inicialización siempre se considera correcta.
En el manejador OnInit es importante comprobar que toda la información necesaria del entorno está presente, y si no está disponible, aplazar las acciones preparatorias para los próximos eventos de llegada de ticks o temporizadores. La cuestión es que, cuando se inicia el terminal, el evento OnInit a menudo se dispara antes de que se establezca una conexión con el servidor y, por lo tanto, muchas propiedades de los instrumentos financieros y de una cuenta de trading siguen siendo desconocidas. En concreto, el valor de un pip de un símbolo concreto puede devolverse como cero.
void OnDeinit(const int reason)
La función OnDeinit (si está definida) se llama cuando se desinicializa el Asesor Experto o el indicador. La función es opcional.
El parámetro reason contiene el código de motivo de desinicialización. Los valores posibles se muestran en la siguiente tabla:
Constante |
Valor |
Descripción |
---|---|---|
REASON_PROGRAM |
0 |
El Asesor Experto ha detenido la operación por llamada a la función ExpertRemove |
REASON_REMOVE |
1 |
Programa eliminado del gráfico |
REASON_RECOMPILE |
2 |
Programa recompilado |
REASON_CHARTCHANGE |
3 |
Periodo o símbolo de gráfico modificado |
REASON_CHARTCLOSE |
4 |
Gráfico cerrado |
REASON_PARAMETERS |
5 |
Parámetros de entrada modificados |
REASON_ACCOUNT |
6 |
Se ha activado otra cuenta o se ha producido una reconexión al servidor de trading debido a un cambio en la configuración de la cuenta. |
REASON_TEMPLATE |
7 |
Plantilla de gráfico diferente aplicada |
REASON_INITFAILED |
8 |
OnInit el manejador ha devuelto un valor no nulo |
REASON_CLOSE |
9 |
Terminal cerrado |
El mismo código puede obtenerse en cualquier parte del programa utilizando la función UninitializeReason si la bandera de parada _StopFlag está activada en el programa MQL.
El archivo AllInOne.mqh tiene la clase Finalizer que le permite «enganchar» el código de desinicialización en el destructor a través de la llamada UninitializeReason. Debemos obtener el mismo valor en el manejador OnDeinit.
class Finalizer
|
Para facilitar la traducción de los códigos en una representación de cadena (nombres de motivos) mediante EnumToString, en el archivo Uninit.mqh se describe la enumeración ENUM_DEINIT_REASON con constantes de la tabla anterior. El registro mostrará entradas como la siguiente:
OnDeinit DEINIT_REASON_REMOVE
|
Cuando se modifica el símbolo o el marco temporal del gráfico en el que se encuentra el indicador, éste se descarga y se vuelve a cargar. En este caso, la secuencia de activación del evento OnDeinit en la copia antigua y OnInit no se define en la copia nueva. Esto se debe a las particularidades del procesamiento asíncrono de eventos por parte del terminal. En otras palabras: puede que no sea del todo lógico que se cargue e inicialice una nueva copia antes de que se descargue por completo la anterior. Si el indicador realiza algún ajuste del gráfico en OnInit (por ejemplo, crea un objeto gráfico), entonces, sin adoptar medidas especiales, la copia descargada puede «limpiar» inmediatamente el gráfico (borrar el objeto, considerándolo como propio). En el caso concreto de los objetos gráficos, existe una solución particular: se puede dar a los objetos nombres que incluyan los prefijos de símbolo y marco temporal (así como la suma de comprobación de los valores de las variables de entrada), pero en el caso general no funcionará. Para darle una solución universal al problema debería implementarse algún tipo de mecanismo de sincronización, por ejemplo, en variables globales o recursos.
Al probar los indicadores en el probador, los desarrolladores de MetaTrader 5 decidieron no generar el evento OnDeinit. Su idea es que el indicador puede crear algunos objetos gráficos, que normalmente elimina en el manejador OnDeinit, pero al usuario le gustaría verlos una vez finalizada la prueba. De hecho, el autor de un programa MQL puede, si lo desea, proporcionar un comportamiento similar y dejar los objetos con una comprobación positiva del modo MQLInfoInteger(MQL_TESTER). Esto es extraño ya que el manejador OnDeinit es llamado después de la prueba del Asesor Experto, y el Asesor Experto puede borrar objetos de la misma manera en OnDeinit. Ahora, sólo para los indicadores, resulta que el comportamiento regular del manejador OnDeinit no se puede garantizar en el probador. Además, no se realizan otras finalizaciones; por ejemplo, no se llama a los destructores de objetos globales.
Por lo tanto, si necesita realizar un cálculo estadístico, guardar un archivo u otra acción después de la ejecución de prueba que originalmente estaba prevista para el indicador de OnDeinit, tendrá que transferir los algoritmos del indicador al Asesor Experto.