Sincronización de Asesores expertos, script e indicadores.

Сергей Ковалев | 12 febrero, 2016

Introducción

Hay tres tipos de programas en MQL4 que se ejecutan en la Terminal de cliente de MetaTrader:
- Asesores expertos;
- scripts;
- indicadores.

Cada uno de ellos está diseñado para resolver ciertos rangos de problemas. Vamos a hacer una breve descripción de estos programas:

1. Breve descripción de los programas de usuario de MQL4

1.1. Asesores Expertos
Son los programas que se utiliza para las estrategias de trading más rentables. Las características distintivas de un AE son las siguientes:
1. Posibilidad de utilizar funciones integradas aptas para el trading.
2. Posibilidad de modificar ajustes externos de forma manual.
3. Posibilidad de crear normas que regulen el inicio de una función especial start(). Se inicia teniendo en cuenta los ticks. En el momento en el que se ingresa un tick, se actualizan los parámetros de todo el ámbito que estén disponibles para esta función. Por ejemplo, variables como oferta y pedir obtienen nuevos valores. Una vez completada la ejecución del código, concretamente tras haber alcanzado la rentabilidad del operador, la función start() termina su actividad y se detiene hasta que vuelve a entrar un tick.

1.2. Scripts
Son muy similares a los Asesores expertos, aunque sus características son ligeramente diferentes. Las características principales de los scripts son:
1. También pueden utilizar las funciones de los trades.
2. En los scripts no se pueden cambiar los ajustes exteriores.
3. La característica principal de los scripts es la norma según la cual la función especial start() de un script puede iniciarse sólo una vez, inmediatamente después de que se haya conectado al gráfico.

Los Asesores expertos y los scripts están conectados a la ventana principal de un símbolo, no pueden tener ventanas auxiliares especiales.

1.3. Indicadores
Los indicadores tienen un propósito diferente a los Asesores expertos y a los scripts:
1. La característica principal es la posibilidad de dibujar curvas continuas que muestren un principio u otro, según la idea implícita que tengan.
2. Las funciones de trade no pueden utilizarse en los indicadores.
3. Los indicadores se inician teniendo en cuenta los ticks.
4. Con respecto a los parámetros implícitos, los indicadores pueden cumplir su propósito en la ventana principal o en una ventana auxiliar.

Sólo hemos nombrado las características principales de los programas personalizados, concretamente aquellas que vamos a necesitar en futuras especulaciones.

Como se puede ver en la descripción, ningún programa personalizado tiene propiedades de todos los programas: Los Asesores expertos y los scripts no pueden dibujar, los indicadores no deben hacer trading, etc.

Si su sistema de trading necesita usar todas las propiedades de los programas personalizados durante el trading, la única solución sería utilizar de forma simultánea un Asesor experto, un script y un indicador.

2. Planteamiento del problema

Vamos a considerar cuáles son los criterios necesarios para el uso simultáneo de todos los programas personalizados.

2.1. Puntualidad
Cualquier control debe ser realizado de inmediato por el usuario. Un programa basado en un Asesor experto no siempre es adecuado para este propósito. La principal desventaja de los Asesores expertos es su vulnerabilidad a las acciones externas. La razón de esta limitación es simple: El código básico del Asesor Experto se inicia teniendo en cuenta los ticks. ¿Qué pasaría si el usuario le da al AE la orden de cerrar un pedido y el AE está esperando al siguiente tick? La respuesta a esta pregunta depende en cómo se haya escrito el AE. En algunos casos se ejecutará la orden, pero con cierto retraso.

El programa se puede organizar de manera que el código principal del Asesor experto se ejecute de forma continua, sin descanso entre los ticks. Para esto, es necesario organizar en la función especial start() un bucle infinito en el que se colocará el código principal del programa. Si la información de ambiente se actualiza a la fuerza al inicio de cada bucle, el complejo entero podría funcionar correctamente. El inconveniente de un Asesor experto en bucle es la imposibilidad de abrir el panel de configuración. Si intenta poner un AE en bucle, no podrá configurarlo.

La misma idea se puede realizar con éxito utilizando un script. Esto quiere decir que se puede organizar un bucle infinito en un script. Pero en los scripts no hay paramétros que configurar.

La personalización del sistema de trading y la puntualidad de ejecutar todas las peticiones en el modo de funcionamiento continuo, sólo se puede realizar utilizando de forma simultánea un Asesor experto para la configuración y un script para la ejecución instantánea.

2.2. Conocimiento
En algunos casos es necesario obtener algún tipo de información sobre el trading. Por ejemplo, a todos los traders les gustaría saber que, en determinado momento (digamos, dos minutos antes de que se publiquen novedades importantes), el centro de operaciones ha cambiado sus 10 puntos normales de la distancia mínima tolerable para colocar órdenes pendientes por 20 puntos. Además, como norma general, el trader quiere saber la razón por la que el servidor se niega a realizar los las órdenes. Esta y otras informaciones de interés se pueden mostrar en formato texto en la ventana del indicador. También pueden moverse constantemente los mensajes antiguos a espacios vacíos para poder recibir mensajes nuevos del sistema de trading. En este caso, es necesario combinar el trading del Asesor externo o un script con un indicador en pantalla.

2.3. Controles
Si usa un sistema de trading que contenga una interfaz mejorada, es mejor colocar los controles (objetos gráficos) en la ventana del indicador. Para que podamos estar seguros de que la evolución de las velas no solape los objetos de control y, por lo tanto, no moleste durante el control.

2.4. Requisitos del sistema
El requisito principal para el producto final, en este caso, es el funcionamiento sincronizado, por lo que es necesario desarrollar un sistema basado en los tres tipos de programas para separar las tareas a resolver por todos sus componentes. Con respecto a las características especiales de cada tipo de programa en nuestro sistema, podemos decir que tienen las siguientes propiedades:

script — ofrece códigos básicos que contienen funciones analíticas y de trading;

Asesor experto — ofrece el panel de configuración;

indicador — proporciona una subventana para mostrar los controles y la información.

3. Soluciones de software

Aquí vamos a indicar que consideramos la estructura de una aplicación basada en tres componentes con el rango mínimo requerido. Si decide utilizar la aplicación, tendrá que desarrollarla usted mismo, ya que concierne operaciones análiticas y de trading. Pero el material que se le da a continuación es más que suficiente para desarrollar una estructura.

3.1. Asesor experto
Vamos a explicar detalladamente en qué consiste un Asesor experto y cómo funciona.

// Expert.mq4
//====================================================== include =======
#include <stdlib.mqh>
#include <stderror.mqh> 
#include <WinUser32.mqh> 
//======================================================================
#include <Peremen_exp.mq4>  // Description of the EA variables.
#include <Metsenat_exp.mq4> // Predefinition of the EA variables. 
#include <Del_GV_exp.mq4>   
// Deletion of all GlobalVariables created by the Expert Advisor.
#include <Component_exp.mq4> // Checking for availability of components.
#include <Component_uni.mq4> 
// Message in the indicator that components are not available.
//======================================================================
//
// 
//======================================================================
int init()  
  {
    Fishka=1;          // We are in init()  
    Metsenat_exp();   // Predefinition of the EA variables.
    Component_exp();  // Check for availability of components
    return;
 } 
//=====================================================================
int start() 
  { 
    Fishka=2;         // We are in start()  
    Component_exp();  // Check for availability of components
    return;                                                                 
 }
//=====================================================================
int deinit() 
  {   
    Fishka=3;         // We are in deinit()  
    Component_exp();  // check for availability of components
    Del_GV_exp();     // Deletion of the Expert Advisor's GlobalVariable.
    return;
 }
//======================================================================

En la función especial init(), hay dos funciones trabajando al mismo tiempo — Metsenat_exp() y Component_exp()

Metsenat_exp() — es una función de predefinición de algunas variables.
// Metsenat_exp.mq4
//=================================================================
int Metsenat_exp()
 {
//============================================ Predefinitions =====
   Symb     = "_"+Symbol();
   GV       = "MyGrafic_GV_";
//============================================= GlobalVariable ====
   GV_Ind_Yes = GV+"Ind_Yes"   +Symb;      
// 0/1 confirms that the indicator is loaded
   GV_Scr_Yes = GV+"Scr_Yes"   +Symb;      
// 0/1 confirms that the script is loaded
//-------------------------------------------- Public Exposure ----
   GV_Exp_Yes = GV+"Exp_Yes"   +Symb;     
   GlobalVariableSet(GV_Exp_Yes, 1 ); 
   GV_Extern  = GV+"Extern"    +Symb;     
   GlobalVariableSet(GV_Extern,  1 ); 
//  AAA is used as an example:
   GV_AAA     = GV+"AAA"       +Symb;     
GlobalVariableSet(GV_AAA,   AAA ); 
//==================================================================
   return;
 }
//====================== End of Module =============================

Una de las tareas de todo el mantenimiento de la aplicación es la de rastrear la disponibilidad de todos los componentes. Por eso todos los componentes (el script, el Asesor experto y el indicador) deben rastrearse unos a otros y, si hay alguno que no está disponible, dejar de trabajar e informar al usuario. Para esto, cada programa informa sobre su disponibilidad al inicio, a través de la publicación de una variable global. Si se da el caso en la función Metsenat_exp() del Asesor experto, se explicará en la siguiente línea.

   GV_Exp_Yes = GV+"Exp_Yes"   +Symb;     
   GlobalVariableSet(GV_Exp_Yes, 1 );
La función Metsenat_exp() está controlada por la función init() del AE, es decir, se utiliza sólo una vez durante la carga o cambios de los valores de las variables externas. El script debe "conocer" los cambios en la configuración, por lo que el experto informará al script durante el cambio de valores de la variable global GV_Extern:

   GV_Extern  = GV+"Extern"    +Symb;     
   GlobalVariableSet(GV_Extern,  1 );

Component_exp() —
una función destinada a la totalidad del control. La situación futura depende de la función especial del Asesor experto, en la que se usa Component_exp().
// Component_exp.mq4 
//===============================================================================================
int Component_exp()
 {
//===============================================================================================
   while( Fishka < 3 &&     // We are in init() or in start() and..
      (GlobalVariableGet(GV_Ind_Yes)!=1 || 
       GlobalVariableGet(GV_Scr_Yes)!=1)) 
    {                            // ..while a program is not available.
      Complect=0;                // Since one is inavailable, it is a deficiency
      GlobalVariableSet(GV_Exp_Yes, 1); 
// Inform that the EA is available
//-----------------------------------------------------------------------------------------------
      if(GlobalVariableGet(GV_Ind_Yes)==1 && 
         GlobalVariableGet(GV_Scr_Yes)!=1)
        {//If there is an indicator but there is no scrip available, then..
         Graf_Text = "Script is not installed.";  
// Message text
         Component_uni();                             
// Write the message text in the indicator window.
        }
//-----------------------------------------------------------------------------------------------
      Sleep(300);
    }
//===============================================================================================
     if(Complect==0)
    {
      ObjectDelete("Necomplect_1"); 
// Deletion of unnecessary messages informing about inavailability of components  
      ObjectDelete("Necomplect_2");       
      ObjectsRedraw();              // For quick deletion 
      Complect=1;        // If we have left the loop, it means that all components are available
    }
//===============================================================================================
   if(Fishka == 3 && GlobalVariableGet(GV_Ind_Yes)==1)
// We are in deinit(), and there is space to write the indicator into
    { 
//-----------------------------------------------------------------------------------------------
      if(GlobalVariableGet(GV_Scr_Yes)!=1)  // If there is no script available,
       {
         Graf_Text = "Components Expert and Script are not installed";
// Message (since we are unloading)
         Component_uni();     // Write the message text in the indicator window
       }
//-----------------------------------------------------------------------------------------------
    }
//===============================================================================================
   return;
 }
//===================== End of the module =======================================================

La disponibilidad del script y el indicador se rastrea basándose en la lectura de los valores de las variables globales correspondientes - GV_Scr_Yes y GV_Ind_Yes. Si ninguno de los dos componentes está disponible, se le dará el control al bucle infinito hasta que se llegue a la totalidad, es decir, hasta que el indicador y el script estén instalados. La aplicación informará al usuario sobre el estado actual a través de la función Component_uni(). Es una función universal incluida en todos los componentes.


// Component_uni.mq4
//================================================================
int Component_uni()
 {
//================================================================
//----------------------------------------------------------------
   Win_ind = WindowFind("Indicator");                 
// What is our indicator's window number?
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   ObjectCreate ( "Necomplect_1", OBJ_LABEL, Win_ind, 0, 0  );
// Create an object in the indicator window
   ObjectSet    ( "Necomplect_1", OBJPROP_CORNER,        3  );
// coordinates related to the bottom-right corner
   ObjectSet    ( "Necomplect_1", OBJPROP_XDISTANCE,   450  );
// coordinates on X..
   ObjectSet    ( "Necomplect_1", OBJPROP_YDISTANCE,    16  );
// coordinates on Y..
   ObjectSetText("Necomplect_1", Graf_Text,10,"Courier New",Tomato);
// text, font, and color
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
   Graf_Text = "Application does not work.";
 // Message text
   ObjectCreate ( "Necomplect_2", OBJ_LABEL, Win_ind, 0, 0);
// Create an object in the indicator window
   ObjectSet    ( "Necomplect_2", OBJPROP_CORNER,        3);
// coordinates related to the bottom-right corner
   ObjectSet    ( "Necomplect_2", OBJPROP_XDISTANCE,   450);
// coordinates on Х..
   ObjectSet    ( "Necomplect_2", OBJPROP_YDISTANCE,     2);
// coordinates on Y..
   ObjectSetText("Necomplect_2", Graf_Text,10,"Courier New",Tomato);
// text, font, color
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
   ObjectsRedraw();                                // Redrawing.
   return;
//================================================================
 }
//===================== End of module ============================

En el momento en el que se complete la aplicación, el control del AE pasará del bucle infinito al código secuencial donde se borrarán los mensajes innecesarios sobre aquello que esté incompleto.

Cuando se descargue el AE, la función especial deinit() también llamará a Component_exp(), pero con otro propósito: informar sobre la descarga en el momento actual.

En la función deinit() del Asesor experto, también se llamará Del_GV_exp().

Se utiliza para borrar todas las VariablesGlobales abiertas por el AE. De acuerdo a una regla no escrita, cada programa descargado debe "limpiar el espacio", es decir, borrar las variables globales y objetos gráficos creados con anterioridad.

// Del_GV_exp.mq4
//=================================================================
int Del_GV_exp()
 {
//=================================================================
   GlobalVariableDel(GV_Exp_Yes      ); 
   GlobalVariableDel(GV_Extern       ); 
   GlobalVariableDel(GV_AAA          ); 
//=================================================================
   return;
 }
//====================== End of module ============================

Por lo tanto, el Asesor experto empieza a trabajar y a rastrear la disponibilidad de los otros dos componentes en todas las fases: una vez en init(), otra vez en deinit() y con cada tick; en start(). Está construcción del AE hace que sea posible utilizar el programa para resolver nuestra tarea: hacer que el panel de configuración esté disponible. El archivo que describe las variables contiene, por ejemplo, la variable AAA y su variable global GV_AAA, el valor que se lee del script.

Para más detalles sobre cómo funciona todo esto, vamos a explicar la estructura de un script.

3.2. Script
Código del script:

// Script.mq4
//==================================================== include ====
#include <stdlib.mqh> 
#include <stderror.mqh>
#include <WinUser32.mqh>
//=================================================================
#include <Peremen_scr.mq4>       
// File describing variables of the script. 
#include <Metsenat_scr.mq4>      
// Predefining of variables of the script.   
#include <Mess_graf_scr.mq4>     
// List of graphical messages.
#include <Novator_scr.mq4>       
// Environment scanning, obtaining new values for some variables
#include <Del_GV_scr.mq4>        
// Deletion of all GlobalVariables created by the script.
#include <Component_scr.mq4>     
// Checking for components availability.
#include <Component_uni.mq4>     
// Message in the indicator about inavailability of components.
#include <Del_Obj_scr.mq4>       
// Deletion of all objects created by the program complex.
#include <Work_scr.mq4>          
// The main working function of the script. 
//=================================================================
//
// 
//=================================================================
int init()  
 {
   Fishka = 1;                                // We are in init()  
   Metsenat_scr();       // Predefining of variables of the script.
   return;
 }
//================================================================
int start()  
 {
   Fishka = 2;                               // We are in start()  
   while(true)
    {
      Component_scr();  // Checking for availability of components
      Work_scr();       // The main working function of the script.
    }
   return;
 }
//=================================================================
int deinit() 
 {
   Fishka = 3;                                // We are in deinit()  
   Component_scr();      // Checking for availability of components
   Del_Obj_scr();          // Deletion of graphical objects created
   Del_GV_scr();        // Deletion of GlobalVariable of the script.
   return;
 }
//==================================================================

La base del código es la disponibilidad de un bucle infinito en la función especial start(). En el código del script, se aplican las funciones con nombres y contenidos similares Nos fijamos en sus características especiales. Al inicio de cada bucle, se llama ala función Component_scr().

// Component_scr.mq4   
//====================================================================
int Component_scr()
 {
//====================================================================
   Iter=0;                               // Zeroize iteration counter
   while (Fishka <3 &&              // We are in init() or in start() 
      (GlobalVariableGet(GV_Ind_Yes)!=1 || 
       GlobalVariableGet(GV_Exp_Yes)!=1)) 
    {                                 // Until a program is available
      GlobalVariableSet(GV_Scr_Yes, 1);               
// Declare about the script availability
//--------------------------------------------------------------------
      Iter++;                                    // Iteration counter
      if(Iter==1)                         // Skip the first iteration
       {
         Sleep(500);
         continue;
       }
//--------------------------------------------------------------------
      if(Iter==2)             // Take measures on the second iteration
       {
         Complect=0; // Program is not available, it is incompleteness
         for (i=0;i<=31;i++)ObjectDelete(Name_Graf_Text[i]);
// Deletion of all strings
// Here, a function can be inserted that will zeroize trade queue.
       }
//--------------------------------------------------------------------
      if(GlobalVariableGet(GV_Ind_Yes)==1 && 
          GlobalVariableGet(GV_Exp_Yes)!=1)
       {                       // If there is an indicator, but no EA
         Graf_Text = "Expert has not been installed."; 
// Message text 
         Component_uni();                             
// Write the text message in the indicator window.
       }
//-----------------------------------------------------------------
      Sleep(300);
    }
//-----------------------------------------------------------------
   if(Complect==0)                // Process it once at completing.
    {
      ObjectDelete("Necomplect_1"); 
// Deletion of unnecessary messages..
      ObjectDelete("Necomplect_2"); 
// ..about incompleteness of components        
      Mess_graf_scr(1);
// Inform the user about completeness
      if( IsExpertEnabled()) 
// The button is enabled
       {
         Mess_graf_scr(3000);
         Knopka_Old = 1;
       }
      if(!IsExpertEnabled()) 
// The button is disabled
       {
         Mess_graf_scr(4000);
         Knopka_Old = 0;
       }
      Complect=1; 
// The minimal installation completeness reached
      Redraw = 1; 
// For quick deletion 
    }
//====================================================================
   if(Fishka == 3 && GlobalVariableGet(GV_Ind_Yes)==1)      
// We are in deinit()  
    {
      for(i=0;i<=31;i++)ObjectDelete(Name_Graf_Text[i]);    
// Deletion of all strings
//--------------------------------------------------------------------
      if(GlobalVariableGet(GV_Exp_Yes)!=1)                 
// There is indicator, but no Expert Advisor
         Graf_Text="Components Expert and Script are not installed.";
// Message (as we're unloading)
      if(GlobalVariableGet(GV_Exp_Yes)==1)
// If there are both indicator and EA, then..
         Graf_Text="The Script has not been installed."; 
// Message (as we're unloading)
      Component_uni();   // Write the message in the indicator window.
//--------------------------------------------------------------------
      ObjectsRedraw();                    // For quick deletion 
    }
//====================================================================
   return;
 }
//====================== End of module ===============================
La primera orden en un script es la continuidad de su operación. Durante la actualización de las variables externas, el Asesor experto se instala por completo. Cuando se pulsa OK en el panel de configuración del AE, se descargará y le dará el control a deinit(), luego se volverá a cargar inmediatamente a través de init() y start() sucesivamente. Como resultado, el Asesor experto, aunque durante un corto periodo de tiempo, borra de deinit() la variable global que confirma su disponibilidad.

Para que el script no crea que el AE no lo ha borrado todo, la función Component_scr() contiene un pequeño bloque que deshabilita la toma de decisiones en la primera iteración.

      Iter++;                         // Iteration counter
      if(Iter==1)              // Skip the first iteration
        {
          Sleep(500);
          continue;
        }


Quinientos milisegundos serán, en la mayoría de los casos, suficientes para completar la carga del Asesor experto. Si utiliza un código que consume más en el init() del Asesor experto, el tiempo debe prolongarse. Si el AE no se ha detectado en la segunda iteración, se considerará que el AE no está disponible, y el script dejará de funcionar.

  Complect = 0;    // A program is not available, incompleteness


La expresión "el script deja de funcionar" se utiliza en el párrafo anterior. En nuestro ejemplo no hay ningún código responsable de este hecho, simplemente porque está más allá del alcance de este artículo. En el lugar donde puede colocar las llamadas a las funciones correspondientes, hay un comentario sobre el código.

// Here, a function zeroizing trade counter can be inserted.

En la función Work_scr() de un programa que funciona de verdad, excepto en las funciones utilizadas en nuestro ejemplo, hay otras funciones que se consideran responsables de cierto número de eventos. Por ejemplo, si su programa se ajusta para modificar varios pedidos, seguramente contendrá una selección en la que se almacenará la cola de ejecución de trades, si están teniendo lugar un número de esos trades en el tick actual.

Si tiene lugar un estado incompleto (por ejemplo, el Asesor experto o el script se ha descargado involuntariamente) en el momento en el que tiene lugar dicha cola, es necesario deshabilitar el trading, que puede hacerse reseteando la selección de la cola de trade mencionada arriba y, quizás, algunas de las otras variables, según cuál sea la situación.

El bucle infinito del script también contiene la función Work_scr(). Es la función principal del script, en la que todo debe colocarse todo su código principal.

// Work_scr.mq4
//=================================================================
int Work_scr()  
 {
   Novator_scr();
//-----------------------------------------------------------------
   // Basic code of the entire application.
//------------------------------------------------ For example ----
   if(New_Tick==1)                             // At every new tick
    {                                                                    
      Alert ("The current value of ААА = ", AAA);
    }                                                                    
//-----------------------------------------------------------------
   if(Redraw==1)
    {
      ObjectsRedraw();                    // To display immediately
      Redraw=0;                         // Unflag objects redrawing
    }
//-----------------------------------------------------------------
   Mess_graf_scr(0);
   Sleep(1);                           // Just in case, from reload
   return;
 }
//====================== End of module ============================

La Work_scr() contiene la función Novator_scr(), destinada a la actualización de las variables del entorno utilizadas en el código básico.

// Novator_scr.mq4  
//===================================================================
int Novator_scr()  
 {
//===================================================================
//---------------------------------------- Updating of settings -----
   if(GlobalVariableGet(GV_Extern)==1) 
// There is an update in the EA
    {
      Metsenat_scr();         // Updating of the script variables.
      Mess_graf_scr(5000);    // Message about a new setting.
      Redraw=1;               // Redrawing at the end of the loop.
    }                                                                    
//--------------------------------- EA button state -----------------
   Knopka = 0;                                         // Preset
   if( IsExpertEnabled()) Knopka = 1; 
// Check for the real state of the button
 
   if(Knopka==1 && Knopka_Old==0) 
// If the state has changed for ON
    {
      Knopka_Old = 1;                // This will be the old one
      Mess_graf_scr(3);              // Inform the user about changes
    }
   if(Knopka==0 && Knopka_Old==1) 
// If the state has changed for OFF
    {
      Knopka_Old = 0;                 // This will be the old one
      Mess_graf_scr(4);              // Inform the user about changes
    }
//-------------------------------------------------- New tick --------
   New_Tick=0;                              // First of all, zeroize
   if (RefreshRates()==true) New_Tick=1; 
// It is easy to catch a new tick if you know how to do it
//--------------------------------------------------------------------
//====================================================================
   return;
 }
//=====================; End of module ===============================


Vamos a explicar la necesidad de esta función con más detalle. Mencionamos al principio del artículo que, cada vez que se carga el AE, así como cuando se actualizan sus variables, su función subordinada Metsenat_exp() establece el valor de la variable GV_Extern en 1. Para el script significa que se deben actualizar los ajustes. Para esto, la función Novator_scr() contiene el siguiente bloque:

//---------------------------------------- Updating settings ----
   if (GlobalVariableGet(GV_Extern)==1) 
// An update has taken place in the EA
    {
      Metsenat_scr();              // Updating script settings.
      Mess_graf_scr(5000);         // New setting message.
      Redraw=1;                    // Redrawing at the end of the loop.
    }

Aquí se analiza el valor de la variable de arriba y, en caso de que sea necesario actualizar, se llama a la función Metsenat_scr(), que realiza la actualización (leyendo los nuevos valores de las variables globales).

// Metsenat_scr.mq4
//===================================================================
int Metsenat_scr()
  {
//========================================================== int ====
//======================================================= double ====
//======================================================= string ====
      MyGrafic    = "MyGrafic_";
    Mess_Graf   = "Mess_Graf_";
    Symb        = "_"+Symbol();
    GV          = "MyGrafic_GV_";
//=============================================== GlobalVariable ====
     GV_Ind_Yes  = GV+"Ind_Yes" +Symb;       
// 0/1 confirms that the indicator has been loaded
     GV_Exp_Yes  = GV+"Exp_Yes" +Symb;       
// 0/1 confirms that the EA has been loaded
//-------------------------------------------------- Publishing -----
     GV_Scr_Yes  = GV+"Scr_Yes" +Symb;     
    GlobalVariableSet(GV_Scr_Yes,          1 ); 
    GV_Extern   = GV+"Extern"  +Symb;     
    GlobalVariableSet(GV_Extern,           0 ); 
//--------------------------------------------------- Reading -------
                                             //  AAA is used as an example:
     GV_AAA      = GV+"AAA"     +Symb;     
   AAA  = GlobalVariableGet(GV_AAA); 
//===================================================================
     return;
 }
//======================== End of module ============================

La función Metsenat_scr(), cuando llega su turno, establece el valor de la variable global GV_Extern en 0. En el siguiente historial, esta variable se mantiene igual a 0 hasta que el usuario abre la ventana de configuración del AE.

Tenga en cuenta que, a pesar de que, debido al cambio de su configuración, el AE pasa por todas las fases de descarga y carga, el script no deja de trabajar mientras el usuario cambia la configuración o tras haberla cambiado. Por lo tanto, el uso combinado del Asesor experto y el script, ayuda a conseguir el requisito de la continuidad de funcionamiento de la aplicación, y permite al usuario cambiar los ajustes, es decir, controlar el proceso.

En el siguiente bloque de la función Novator_scr(), el botón del AE se controla de manera que permite el trading. Luego se detecta un nuevo tick. Si su sistema de trading admite el uso de esos parámetros o similares, es la función Novator_scr() la que tiene que está destinada a realizar dichos cálculos.

Por ejemplo, puede completar esta función con bloques que detecten si ha aparecidocompruebe si ha llegado el momento de comprobar si hay un evento crítico, compruebe si los términos de trade se han cambiado (por ejemplo, han aumentado de tamaño, la distancia mínima a la que se deben colocar as órdenes detenidas, etc.), así como otros cálculos necesarios antes de que se inicie la función analítica básica.

Las funciones que realizan el contenido básico del programa no se muestran en la función Work_scr(). En el artículo Cómo funcionan las órdenes en los programas complejos, tratamos la función Terminal(), que considera las órdenes. Si utiliza el mismo principio de consideración en su sistema de trading, la función Terminal() debe incluirse dentro de la función Work_scr() inmediatamente después de la función Novator_scr().

El script tiene una función auxiliar más a su disposición: Mess_graf_scr(), destinada a mostrar mensajes en la ventana del indicador.

// Mess_graf_scr.mq4
//====================================================================
int Mess_graf_scr(int Mess_Number)
 {
//====================================================================
   if(Mess_Number== 0)        // This happens in every loop Work
    {
      if(Time_Mess>0 && GetTickCount()-Time_Mess>15000) 
// Color print has outdated within the last 
       {                       // ..15 sec, let's color lines gray
         ObjectSet(Name_Graf_Text[1],OBJPROP_COLOR,Gray);
// Last 2 lines
         ObjectSet(Name_Graf_Text[2],OBJPROP_COLOR,Gray);
// The last 2 lines
         Time_Mess=0;         // Additional flag not to color in vain
         Redraw=1;            // Then redraw
       }
      return;                 // It was a little step into 
    }
//--------------------------------------------------------------------
   Time_Mess=GetTickCount(); // Remember the message publishing time
   Por_Nom_Mess_Graf++;      // Count lines. This is just a name part.
   Stroka_2=0;            // Presume that message in one line
   if(Mess_Number>1000)      
// If a huge number occurs, the number will be brought to life, 
// understand that the previous line is from the same message, i.e.,it 
// should not be colored gray 
    {
      Mess_Number=Mess_Number/1000; 
      Stroka_2=1; 
    } 
//====================================================================
   switch(Mess_Number)
    {
//--------------------------------------------------------------------
      case 1:
         Graf_Text = "All necessary components installed.";
         Color_GT = LawnGreen; 
         break;
//--------------------------------------------------------------------
      case 2:
         Graf_Text = " ";
         break;
//--------------------------------------------------------------------
      case 3:
         Graf_Text = "Expert Advisors enabled.";
         Color_GT = LawnGreen; 
         break;
//--------------------------------------------------------------------
      case 4:
         Graf_Text = "Expert Advisors disabled.";
         Color_GT = Tomato; 
         break;
//--------------------------------------------------------------------
      case 5:
         Graf_Text = "Expert Advisor settings have been updated.";
         Color_GT = White; 
         break;
//---------------------------------------------------- default -------
      default:
         Graf_Text = "Line default "+ DoubleToStr( Mess_Number, 0);
         Color_GT = Tomato;
         break;
    }
//====================================================================
   ObjectDelete(Name_Graf_Text[30]); 
// the 30th object is preempted, delete it
   int Kol_strok=Por_Nom_Mess_Graf;
   if(Kol_strok>30) Kol_strok=30;
//-----------------------------------------------------------------
   for(int lok=Kol_strok;lok>=2;lok--)
// Go through graphical text names
    {
      Name_Graf_Text[lok]=Name_Graf_Text[lok-1];        
// Reassign them (normalize)
      ObjectSet(Name_Graf_Text[lok],OBJPROP_YDISTANCE,2+14*(lok-1));
//Change Y value (normalize)
      if(lok==3 || lok==4 || (lok==2 && Stroka_2==0))
         ObjectSet(Name_Graf_Text[lok],OBJPROP_COLOR,Gray);
//Color old lines gray.. 
    }
//-------------------------------------------------------------------
   Graf_Text_Number=DoubleToStr( Por_Nom_Mess_Graf, 0); 
//The unique part of the name unite with the message number
   Name_Graf_Text[1] = MyGrafic + Mess_Graf + Graf_Text_Number;
// Form the message name.
   Win_ind= WindowFind("Indicator");                    
//What is the window number of our indicator?
 
   ObjectCreate ( Name_Graf_Text[1],OBJ_LABEL, Win_ind,0,0);
// Create an object in the indicator window
   ObjectSet    ( Name_Graf_Text[1],OBJPROP_CORNER, 3   );  
// ..with coord, from the bottom-right corner..
   ObjectSet    ( Name_Graf_Text[1],OBJPROP_XDISTANCE,450); 
// ..with coordinates on X..
   ObjectSet    ( Name_Graf_Text[1],OBJPROP_YDISTANCE, 2);  
// ..with coordinates on Y..
   ObjectSetText(Name_Graf_Text[1],Graf_Text,10,"Courier New",
                 Color_GT);
//text font color
   Redraw=1;                                  // Then redraw
//=================================================================
   return;
 }
//====================== End of module ============================

No es necesario explicar esta función en detalle. Simplemente podemos mencionar algunas de sus características especiales:


1. Todos los mensajes se muestran a través de gráficos.
2. El parámetro formal que hay que trasladar a la función, corresponde con el número del mensaje.
3. Si el valor del parámetro trasladado se encuentra entre 1 y 999, el renglón anterior en la ventana del indicador perderá su color. Si este valor sobrepasa 1 000, el mensaje se mostrará, número que iguala el valor trasladado dividido entre 1 000. En este último caso, el renglón anterior no perderá el color.
4. Tras pasar quince segundos tras el último mensaje, todos los renglones perderán el color.
5. Manteniendo la posibilidad de decolorar los renglones, la función se debería activar de vez en cuando. Por eso hay una llamada al final de la función Work_scr():

   Mess_graf_scr(0);


En el artículo Autograf, un Asesor Experto gráfico, se representa un complejo de programa que funciona muy bien, donde usamos una función similar que contiene más de 250 mensajes diferentes. Puede consultar este ejemplo para utilizar todos o varios de los mensajes en su trading.

3.3. Indicador

Para terminar nuestra presentación, vamos a hablar también del indicador, aunque su código es más bien simple.

// Indicator.mq4
//===================================================; include ==========
#include <stdlib.mqh>
#include <stderror.mqh>
#include <WinUser32.mqh>
//=======================================================================
#include <Peremen_ind.mq4>       
// Description of the indicator variables.
#include <Metsenat_ind.mq4>      
// Predefining the indicator variables. 
#include <Del_GV_ind.mq4>        
// Deletion of all GlobalVariables created by the indicator.
#include <Component_ind.mq4>     
// Check components for availability.
#include <Component_uni.mq4>     
// Message in the indicator about inavailability of components.
//=======================================================================
//
// 
//=======================================================================
#property indicator_separate_window
//=======================================================================
//
//
//=======================================================================
int init()  
 {
   Metsenat_ind();
   return;
 }
//=======================================================================
int start() 
 {
   if(Component_ind()==0) return; // Check for availability of components
   //...
   return;                                                           
 }
//=======================================================================
int deinit() 
 {
   Del_GV_ind();             // Deletion of the indicator GlobalVariable.
   return;
 }
//=======================================================================


Sólo vamos a recalcar una característica importante: El indicador se muestra en una ventana a parte:

#property indicator_separate_window

Los contenidos de las funciones Metsenat_ind() y Del_GV_ind() son parecidos a los de las funciones explicadas anteriormente en el Asesor experto y el script.

El contenido de la función Component_ind() también es poco sofisticado:

// Component_ind.mq4
//===================================================================
int Component_ind()
 {
//===================================================================
   if(GlobalVariableGet(GV_Exp_Yes)==1 && 
      GlobalVariableGet(GV_Scr_Yes)==1)
//If all components are available
    {                        // State about the indicator available
      if(GlobalVariableGet(GV_Ind_Yes)!=1)
          GlobalVariableSet(GV_Ind_Yes,1);
      return(1);
    }
//--------------------------------------------------------------------
   if(GlobalVariableGet(GV_Scr_Yes)!=1 && 
      GlobalVariableGet(GV_Exp_Yes)!=1)
    {                           // If there is neither script nor EA  
      Graf_Text = "Components Expert and Script are not installed.";            
// Message text
      Component_uni();        // Write the info message in ind. window
    }
//=====================================================================
   return(0);
 }
//=====================; End of module ================================



Como podemos ver por su código, la función

Component_ind() sólo ofrece un mensaje si hay otros dos componentes que no se han cargado: tanto el script como el Asesor experto. Si sólo hay un programa no disponible, no se realizará ninguna acción. Esto supone que, si están disponibles en la ventana del símbolo, estos programas rastrearán la composición del complejo de programa e informará al usuario de los resultados.

Si es necesario, también se puede utilizar la propiedad principal del indicador: dibujar. En términos de complejo de programa, no es necesaria esta propiedad, pero puede utilizarse en trading real, por ejemplo, para dividir en zonas la ventana auxiliar.

4. Uso práctico

La orden de adjuntar los componentes de la aplicación a la ventana del símbolo no es muy importante. Sin embargo, se recomienda adjuntar el indicador al principio, ya que nos permite leer los comentarios en el momento en el que se adjunta.

Por lo tanto, debe hacerse lo siguiente:

1. Adjunte el indicador en la ventana del símbolo. Aparecerá inmediatamente esto en la ventana del indicador.

Los componentes experto y script no están instalados
La aplicación no funciona.


2. Adjunte el Asesor experto en la ventana del símbolo. Se iniciará la función Component_exp() y aparecéra el siguiente mensaje en la ventana del indicador:

El script no está instalado
La aplicación no funciona.

3. Adjunte el script en la ventana del símbolo. Esto se procesará en la función Component_scr() del script y en la ventana del indicador aparecerá el siguiente mensaje:


Todos los componentes necesarios están instalados.
El Asesor experto está habilitado.


Si el Asesor experto no estuviera habilitado, el mensaje sería así:

Todos los componentes necesarios están instalados.
El Asesor experto está deshabilitado.


4. Puede pulsar varias veces el botón del AE para asegurarse de que la aplicación procesa inmediatamente esta secuencia y se muestra en los mensajes:

El Asesor experto está deshabilitado.
El Asesor experto está habilitado.

El Asesor experto está deshabilitado.
El Asesor experto está habilitado.
El Asesor experto está deshabilitado.


Por favor, tenga en cuenta que, debido al script con código básico en bucle que se utiliza en el complejo de programa, el programa no responde al control del usuario no es en varios ticks, sino que lo hace de inmediato.

Por ejemplo, colocamos en la función Work_scr() la muestra de variables que tienen en cuenta los ticks desde la configuración del AE con la función Alert().



Vamos a explicar esta característica. La función Work_scr() forma parte del script. El bucle básico del script tiene tiempo para girar cientos de veces entre ticks, mientras que la función Alert() da el mensaje en varios ticks.

5. Abra la barra de configuración del AE y sustituya el valor AAA por 3. El script rastreará este evento y mandará un mensaje a la ventana del indicador:

El Asesor experto está habilitado.
El Asesor experto está deshabilitado.
El Asesor experto está habilitado.

El Asesor experto está deshabilitado.
Se ha actualizado la configuración del AE.


En la ventana de la función Alert() se mostrará el nuevo valor de la variable AAA teniendo en cuenta los ticks:


6. Ahora puede cargar y descargar cualquier componente en cualquier secuencia, juegue con el botón AE, cambie el valor de la variable ajustable, y fórmese su propia opinión sobre la calidad del complejo de programa.

Conclusión

Lo principal que hemos conseguido utilizando la tecnología que hemos descrito, es que el script no deje de funcionar, independientemente de si tiene lugar o no algún evento en este ambiente. El script dejará de funcionar si se da cuenta de que uno o dos de los otros componentes (el indicador o el Asesor experto) no están disponibles.

El principio de crear un complejo de programa es, con alguna modificación, utilizado en una aplicación que funciona muy bien, AutoGraf, que se describió en el artículo Graphic Expert Advisor: AutoGraf .

SK. Dnepropetrovsk. 2006