English Русский 中文 Deutsch 日本語 Português 한국어 Français Italiano Türkçe
Cómo desarrollar un asesor experto usando las herramientas de UML

Cómo desarrollar un asesor experto usando las herramientas de UML

MetaTrader 5Integración | 8 mayo 2014, 10:23
3 255 0
Denis Kirichenko
Denis Kirichenko

Los científicos investigan lo que ya existe, los ingenieros crean lo que no ha existido nunca.

Albert Einstein

Introducción

En mi artículo Simulink: una guía para los desarrolladores de asesores expertos recomiendo modelar un asesor experto usando sistemas dinámicos. Sin embargo, este enfoque representa solo un aspecto del diseño de sistemas de trading: el comportamiento dinámico del sistema. Los profesionales tienen herramientas específicas que amplían la metodología de un desarrollador de sistemas de trading. En este artículo veremos cómo desarrollar un asesor experto usando una herramienta universal: el lenguaje gráfico UML.

En general, al ser un lenguaje gráfico, UML se utiliza para el modelado visual de los sistemas de software orientados a objetos. Pero, tal y como yo lo veo, podemos utilizar sus herramientas para desarrollar un sistema de trading. Es más, MQL5 pertenece a la familia de lenguajes orientados a objetos y esto hace que nuestra tarea sea más sencilla.

Con vistas al modelado, elijo el software libre y no comercial Software Ideas Modeler.


1. Fundamentos de UML

¿Cómo puede ayudarnos UML a crear un asesor experto? En primer lugar, con los gráficos, ya que el problema del modelado multifacético puede resolverse utilizando las imágenes gráficas disponibles en el lenguaje. En segundo lugar, la legibilidad. Incluso si el asesor experto es grande y complejo, la universalidad de UML permite mostrar su modelo usando diagramas.

Como dicen los desarrolladores de UML, la característica específica de la percepción humana se apoya en el hecho de que un texto con imágenes se percibe con mayor precisión que solo un texto.

Vamos a ver brevemente los fundamentos de UML. Si está interesado en la materia puede aprender sobre las herramientas de UML a partir de las numerosas publicaciones gratuitas disponibles en la web.

La estructura de UML puede mostrarse en un diagrama (Fig. 1).

Fig. 1. Estructura de UML

Fig. 1. Estructura de UML

La construcción de bloques incluye lo siguiente: entidades (elementos del modelo), relaciones (que unen los elementos) y diagramas (que representan los modelos de UML).

Los diagramas de UML permiten visualizar la representación del sistema en cuestión desde diferentes puntos de vista.

Los mecanismos habituales incluyen: especificaciones (descripción de la semántica), adornos, (destacando las características importantes del modelo) divisiones comunes (abstracción y sus instancias, interfaces e implementación), mecanismos de extensión (restricciones, estereotipos y valores etiquetados).

La arquitectura es la responsable de la presentación de alto nivel del sistema en su entorno. La arquitectura UML puede describirse mejor por la "visión de la arquitectura 4+1" (Fig. 2):

  • Visión de la lógica
  • Visión del proceso
  • Visión del desarrollo
  • Visión física
  • Escenarios

Fig. 2. Visión de la arquitectura 4+1

Fig. 2. Visión de la arquitectura 4+1


Debe señalarse también que UML tiene su propia jerarquía de diagramas canónicos (Fig. 3). La versión 2.2 del lenguaje usa 14 tipos de diagramas UML.

Fig. 3. Diagramas canónicos de UML


Fig. 3. Diagramas canónicos de UML

Además, propongo considerar algunos casos especiales del uso de los diagramas UML. De esta forma, podemos ir de una abstracción a una variante específica del uso de cualquier diagrama con la finalidad de desarrollar asesores expertos. Una vez más, el principio del diseño multifacético de sistemas de trading proporcionado por la jerarquía de los diagramas de UML contribuye a la solución sistemática e integral de la tarea de creación de sistemas de trading.


2. Diagramas de UML


2.1 Diagramas de casos de uso

Como dice el refrán, un buen comienzo es la mitad de la batalla. Normalmente, aunque no es necesario, el trabajo analítico comienza con los diagramas de casos de uso. Describen el sistema desde la perspectiva de los usuarios.

Al crearlos, podemos:

  • especificar las variantes del uso de sistemas de trading
  • especificar los límites del sistema de trading
  • determinar los actores del sistema de trading
  • definir la relación entre los actores y las versiones de los sistemas de trading.

Los casos de uso son una lista de pasos que definen las interacciones entre un papel (conocido en UML como "actor") y un sistema, para alcanzar un objetivo.

Un actor es un papel desempeñado por un usuario o cualquier otro sistema que interacciona con el sujeto. Los actores representar papeles habituales de usuarios humanos, hardware externo u otros sujetos.

Un relación es una conexión semántica entre elementos individuales de un modelo.

Puede que este tipo de diagramas le parezcan muy generales y reflejen la naturaleza del concepto de sistema de trading en lugar de su implementación. Pero esa es la cuestión, ir de lo general a lo específico, de lo abstracto a lo concreto. ¿Quién dijo que no somos artistas? Dibujamos un cuadro, comenzando con ideas generales y esquemas. En primer lugar, dibujamos trazos sobre un lienzo. Luego añadimos colores. Dibujamos los detalles...

Por tanto, vamos a crear un diagrama de casos de uso para un sistema de trading.

He elegido como actores de entrada los siguientes papeles: Desarrollador, analista de sistemas, gestor de riesgo y administrador. Debe recordarse que estos papeles pueden ser desempeñados por una o más personas. ¿Qué acciones lleva a cabo nuestro sistema de trading y qué otras se ejecutan con relación a las mismas?

De esta forma, el desarrollador puede crear e implementar un sistema de trading. Adicionalmente, él o ella pueden participar en la optimización del sistema de trading. El analista del sistema optimiza el sistema de trading. El gestor de riesgo es responsable de gestionar el riesgo. El administrador supervisa el trabajo del sistema de trading. En la salida vemos que el usuario consigue un beneficio como resultado del funcionamiento del sistema de trading. Este papel es la suma de los papeles del operador y el inversor. Y el gestor, así como el administrador supervisan el trabajo del sistema de trading.

El diagrama contiene el bloque "Trading System". Representa la frontera del sistema de trading y lo separa del mundo exterior.

Ahora unas palabras sobre la relación entre los actores y los casos de uso, así como entre los actores y otros actores y los casos de uso y otros casos de uso. La mayoría de las relaciones se representan mediante asociaciones y se marcan con una línea continua. Esto significa que un actor determinado inicia un caso de uso. De esta forma, el gestor de riesgo inicia el proceso de gestión de riesgo, etc. Los actores que inician los casos de uso son de primer rango y los que utilizan los resultados de las acciones que se han ejecutado son secundarios. Por ejemplo, un actor secundario es el jefe en la salida. 

La asociación puede indicar que el actor inicia el caso de uso adecuado.

La generalización simula la generalidad adecuada de los papeles.

La extensión es un tipo de relación de dependencia entre el caso de uso base y su caso especial.

Include define la relación del caso de uso base con otro caso de uso, el comportamiento funcional que no es siempre realizado por el vaso base, sino solo bajo condiciones adicionales.

Sin embargo, debe saber que un papel secundario en relación al caso de uso no significa que este papel tenga una importancia secundaria. Además, vemos que en el diagrama el papel del usuario del sistema de trading comprende los papeles del operador y el inversor a través de las relaciones de generalización mostradas como una línea con la punta de la flecha triangular "sin pintar".

Fig. 4. Diagrama de caso de uso del sistema de trading

Fig. 4. Diagrama de caso de uso del sistema de trading

Los casos de uso "Open position" y "Close position", a su vez, están relacionados por una generalización con "Trading". El último caso es la base para los otros dos. De esta forma, incluye el caso de uso "Manage risk". Y su comportamiento es complementario al del caso dependiente "Profit".

Como el beneficio del sistema de trading se forma sobre la condición de que el precio de venta de un activo sea mayor que el precio de compra, he usado la relación "extend" para estos casos. El diagrama también muestra el punto de extensión, es decir, una condición específica bajo la que se utiliza el caso "To profit". Las relaciones de dependencia se muestran como líneas discontinuas con una flecha con los estereotipos correspondientes "include" y "extend".

Para cada caso de uso necesitamos crear un escenario para describir una serie de pasos que conducen al objetivo perseguido. El caso de uso puede describirse de varias formas. Las formas habitualmente aceptadas incluyen: descripciones de texto, seudocódigo, diagrama de actividad y diagrama de interacción.

Debe señalarse que un operador está interesado en un sistema de trading en sentido estricto y no en el sentido que se muestra en la Figura 4. Por tanto, recomiendo centrar los esfuerzos en el caso de uso "Trading" con la extensión "To profit".


2.2 Diagrama de clase

Con el uso del diagrama de clase describiremos la estructura del sistema de trading. Es decir, vamos a presentar un modelo de estructura estática del sistema de trading en términos de las clases de programación orientada a objeto. De esta forma, reflejaremos la lógica de la programación del sistema de trading.

En UML un diagrama de clase es un tipo de diagrama de estructura estática. Describe la estructura del sistema mostrando sus clases, atributos y operadores, así como la relación de las clases.

¿Cuáles son las ventajas de este tipo de diagramas? Quienes están algo familiarizados con los lenguajes de programación orientada a objeto se darán cuenta inmediatamente del concepto familiar de "clase". La clase funciona en el diagrama de clase de UML como un bloque de construcción básico. Por ejemplo, al crear código C++ se crea automáticamente el bloque de la clase UML en forma de plantilla de clase. Solo es necesario que finalicemos la implementación de cada método y propiedad.

Vamos ahora a intentar diseñar algo como ejemplo. Pero antes me gustaría que recordaran el artículo prototipo de un robot de trading, en el que el autor describe las ventajas del uso de una lógica directa. En mi opinión, el principio de anidado es muy efectivo y productivo: "módulos de macros-funciones-transacciones".

Por ejemplo, necesitamos un asesor experto que utilice la capacidad de as clases de trading de la librería estándar.

Utilizando el bloque de la clase creamos un modelo de clase en el diagrama de clase. Lo he llamado CTradeExpert. Añadimos algunos atributos (en MQL5 son miembros de datos de la clase) para la nueva clase. Son los siguientes: Magic_No, e_trade, e_account, e_deal, e_symbol, e_pnt. También insertamos un método de la clase constructor CTradeExpert. Gráficamente, la operación es como se muestra en la Fig. 5.

Fig. 5. Modelo UML de la clase CTradeExpert

Fig. 5. Modelo UML de la clase CTradeExpert

El carácter "-" en frente de un atributo indica que este tiene el acceso en modo «privado», «#» sería «protegido» y «+» «público». De esta forma, para el atributo Magic_No el especificador de acceso se establece como privado, para e_pnt como público, y para los demás protegido. Dos puntos a continuación del nombre del atributo indica un tipo de dato para los atributos y el tipo de dato devuelto para los métodos. Por ejemplo, el atributo Magic_No es de tipo int, e_trade es CTrade, etc.

No estamos añadiendo métodos ni atributos ahora, simplemente mostramos cómo nuestra clase CTradeExper se conecta con las clases de la librería estándar. Para hacer esto añadimos 6 bloques de clases al diagrama y las llamamos de la siguiente forma: CTrade, CAccountInfo, CDealInfo, CSymbolInfo y CObject. Ahora asociamos el modelo de la clase CTradeExpert con 4 bloques de las clases de transacciones a través de las relaciones de dependencia con el "uso" estereotipo (la línea de trazos y puntos con una flecha). 

Dependencia es una relación semántica entre dos entidades en las que un cambio en la que es independiente puede afectar a la semántica de la otra dependiente.

En UML, estereotipo es una descripción del comportamiento del objeto.

A continuación, enlazamos estos bloques con el bloque CObject mediante la relación de generalización usando una línea con una punta de flecha "sin relleno". Añadimos comentarios a las clases de la librería estándar. Ahora, nuestro diagrama UML tiene el aspecto mostrado en la Figura 6.

Fig. 6. Diagrama de clase de UML

Fig. 6. Diagrama de clase de UML

Ahora, solo necesitamos generar el código usando la función "Generate" de la pestaña "Generate" en la barra lateral (Fig. 7).

Fig. 7. Código generado

Fig. 7. Código generado

El más adecuado es el lenguaje C++. Usaremos C++ para generar el código de la clase del asesor experto y luego lo podremos traducir fácilmente a MQL5.

Para este diagrama, el código generado es el siguiente:

//
class CTradeExpert
{

private:
        int Magic_No;

protected:
        CTrade e_trade;

protected:
        CAccountInfo e_account;

protected:
        CDealInfo e_deal;

protected:
        CSymbolInfo e_symbol;

public:
        double e_pnt;

public:
        void CTradeExpert () 
    {

    }

};


//
class CObject
{
};

//
class CTrade : public CObject
{
};

//
class CDealInfo : public CObject
{
};

//
class CSymbolInfo : public CObject
{
};

//
class CAccountInfo : public CObject
{
};

Una sintaxis muy familiar, ¿verdad? Ahora necesitamos adaptar el cuerpo de la clase. Para ello creamos en MetaEditor un archivo para la nueva clase TradeExpert.mqh. Copiamos en él el código previamente generado. Para facilitar su lectura borramos el especificador de acceso repetido protected para los miembros de la clase CTradeExpert.

Borramos las líneas conectadas con la declaración de las clases de la librería estándar. Después de esto, añadimos el archivo con la instrucción # Include para cada clase usada de la librería estándar, ya que estas clases han sido ya definidas por el desarrollador. Y añadimos nuestros comentarios. Como resultado obtenemos el siguiente código:

//includes
#include <Trade\Trade.mqh>
#include <Trade\AccountInfo.mqh>
#include <Trade\DealInfo.mqh>
#include <Trade\SymbolInfo.mqh>
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class CTradeExpert
  {
private:
   int               Magic_No;   // Expert Advisor magic

protected:
   CTrade            e_trade;    // An object for executing trade orders
   CAccountInfo      e_account;  // An object for receiving account properties
   CDealInfo         e_deal;     // An object for receiving deal properties
   CSymbolInfo       e_symbol;   // An object for receiving symbol properties

public:
   double            e_pnt;      // Value in points

public:
                     CTradeExpert()
     {
     }
  };
//+------------------------------------------------------------------+

ahora añadimos algunos módulos de funciones de trading más a nuestra clase del asesor experto.

Estos pueden ser: CheckSignal, OpenPosition, CheckPosition, ClosePosition etc. Espero que ya conozca el principio de "condición en funcionamiento". En este caso nuestra clase de prueba CTradeExpert no le resultará difícil. Me he centrado especialmente en algunos ejemplos ya familiares de asesores expertos para facilitarle el conocimiento de los mecanismos de UML.

Ahora el modelo de la clase tiene el aspecto que se muestra en la Fig. 8.

Fig. 8. Modelo UML de la clase CTradeExpert

Fig. 8. Modelo UML de la clase CTradeExpert

Para el modelo de la clase actualizado podemos generar también un código usando el método ya descrito.


2.3 Diagrama de actividad

Al usar este tipo de diagramas UML podemos estudiar el comportamiento del sistema utilizando modelos de flujo de datos y de control de flujo. Los diagramas de actividad son representaciones gráficas de flujos de trabajo de actividades y acciones paso a paso.

Los diagramas de actividad se diferencian de los diagramas de flujo en que estos últimos describen solo los pasos del algoritmo. La notación en el diagrama de actividad es más extensa. Por ejemplo, es posible especificar el estado de los objetos en ellos.

Los diagramas de actividad son utilizados por los desarrolladores para describir:

  • reglas en los negocios
  • casos de uso únicos
  • series complejas de casos de uso múltiples
  • procesos con soluciones y flujos de datos alternativos
  • operaciones paralelas
  • flujos de programa y estructuras de control lógicas

Asumiremos que la clase de experto creada CTradeExpert se usará en el archivo del asesor experto Test_TradeExpert.mq5. Recordemos que la plantilla por defecto al crear un asesor experto en MetaEditor 5 proporciona tres funciones del controlador de evento por defecto: OnInit, OnDeinit y OnTick. Vamos a hacer hincapié en ellas.

Vamos a intentar visualizar un diagrama con la contabilidad de nuestro asesor experto para el archivo Test_TradeExpert.mq5. Debe destacarse aquí que el asesor experto, o más bien su estructura, es muy primitivo. Ahora solo estamos practicando. Para esta finalidad es suficiente una estructura del asesor experto simple.

Vamos a diseñar un diagrama para utilizar nuestro asesor experto cuyo algoritmo está incluido en el archivo Test_TradeExpert.mq5.

Todo comienza con el nodo inicial (Fig. 9). A partir de este nodo una señal de control se desplaza al nodo llamando a la acción "crear una instancia de asesor experto". Esta acción inicia el flujo del objeto (flecha azul) que cambia el estado del nodo del objeto (myTE=created) y controla el flujo a un nodo que llama a "inicializar el asesor experto". 

Un flujo de control se representa en forma de conexión de que une los dos nodos de actividad y sobre al mismo solo se pasan las señales de control. 

Un flujo de objeto se representa como una conexión de actividad a la que solo se pasan señales de objeto o datos.

Un nodo de actividad es una clase abstracta para puntos individuales en el flujo de actividades conectadas por extremos.

Un nodo de decisión es un nodo de control que selección entre flujos de salida.

Un nodo de objeto representa objetos usados en la actividad.

Un borde de actividad es una clase abstracta para conexiones entre dos nodos de actividad.

El nodo inicial muestra dónde comienza la actividad.

El nodo final de una actividad completa todos los flujos de actividad.

Este, a su vez, cambia el estado del objeto myTE (myTE=initialized) y pasa la señal de control al nodo de decisión. Si el asesor experto se inicializa con éxito, el flujo de control va al nodo "procesar el evento de trading NewTick". Si falla la inicialización la señal de control entra primero en el nodo de generalización y luego el nodo de acción "deinicializa el asesor experto".

Las señales (tokens) son construcciones abstractas introducidas para facilitar la descripción del proceso dinámico de ejecución de un gráfico de actividad estadísticamente definido. La señal no puede contener ninguna información adicional (una señal vacía), ya que en este caso se llama una señal de flujo de control o puede contener una referencia a un objeto o una estructura de datos y, en este caso, se denomina una señal de flujo de datos.

Vamos a ver el primer flujo de control obtenido en el nodo de decisión. Se dirige a un área con una acción interrumpida, según indica el rectángulo con esquinas redondeadas dibujado mediante la línea roja punteada y el estereotipo "interrumpible". Cuando el flujo de control se encuentra en esta área, puede pararse inesperadamente. Si activamos el nodo de acción (flag naranja) que recibe el evento "Unload Expert Advisor" (descargar asesor experto), interrumpirá todos los flujos. La señal de control se desplaza al borde de la interrupción (flecha naranja en zigzag) y luego al nodo de conexión. Después de esto se deinicializa el asesor experto. A continuación, la señal de control va al nodo Delete global variables" (borrar las variables globales) y luego se completa el flujo en el nodo de actividad final.

El nodo de acción "Deinitilize Expert Advisor" (deinicializar asesor experto) también cambia el estado del objeto myTE (myTE=deinitsialized) por un flujo de objeto. El nodo "Delete global variables", a su vez, elimina el objeto myTE (myTE=deinitsialized).

Fig. 9. Diagrama de actividad para Test_TradeExpert.mq5

Fig. 9. Diagrama de actividad para Test_TradeExpert.mq5

Asumimos que el flujo de control es estable: el asesor experto no se descarga. Desde el nodo "Process the trade event NewTick" (procesar el evento de trading NewTick) el flujo se desplaza a otro bloque, área de expansión, cuyo estereotipo se define como "iterativo" (rectángulo verde con líneas de puntos).

A esta área la llamo "Trading block" (bloque de trading) para reflejar las características básicas y mejorar la percepción del diagrama. Un rasgo característico del bloque es la ejecución cíclica de las operaciones para los objetos entrantes. Solo necesitamos 2 ciclos: controlar las direcciones largas y cortas. A la entrada y la salida del bloque hay nodos de expansión que incluyen objetos de dirección de transacciones (largas o cortas). 

Un nodo de expansión es una colección de objetos que entran o salen del área de expansión y que son ejecutados una solo vez.

El nodo de acción que envía una señal (acción de enviar señal) representa el envío de una señal.

El nodo de acción que acepta un evento (acción aceptar un evento), espera a recibir un evento del tipo apropiado.

De esta forma, cada dirección es controlada por nodos tales como: "Check signal" (nodo de envío de señal), "Receive signal" (nodo de recepción de señal), "Open position" (nodo de envío de señal), "Check position" (nodo de envío de señal), "Close position" (nodo de envío de señal). Debe señalarse que el objeto de dirección (dir) puede pasarse en el flujo de objeto entre nodos de acción, tal y como se indicó mediante flechas violetas. Las operaciones en un bloque continuarán mientras que el asesor experto siga descargado.


2.4 Diagrama de secuencia

Utilizamos el diagrama de secuencia para describir la secuencia de interacción del objeto. Un aspecto muy importante de este tipo de diagramas es el tiempo.

Por tanto, el diagrama tiene dos escalas de forma implícita. La horizontal es responsable de las interacciones de la secuencia del objeto. La vertical es un eje de tiempo. El principio del intervalo de tiempo está en la parte superior del diagrama.

Esta parte contiene los objetos del diagrama que interactúan. Un objeto tiene su propia línea de tiempo como una línea de puntos vertical. Los objetos intercambian mensajes. Estos están representados por flechas. Cuando un objeto está activo, recibe el foco de control. Gráficamente, este foco se expresa como un rectángulo estrecho en la línea de tiempo.

Un objeto es un rectángulo que contiene un nombre de objeto y de clase subrayados (opcional) separados por dos puntos.

Un objeto de línea de vida es una línea que muestra la existencia de un objeto durante un periodo de tiempo y, cuanto más larga es la línea, mayor es la duración del objeto.

El foco de control se dibuja como un rectángulo estrecho cuya parte superior muestra el principio de la recepción del foco de control por el objeto (inicio de la actividad) y su parte inferior muestra el final del foco de control (final de la actividad).

En UML, cada interacción es descrita como un conjunto de mensajes, con los objetos participando en el intercambio.

Vamos a practicar un poco.

El terminal es un actor. Este inicial la operación del asesor experto. Otros objetos marcados con el estereotipo "evento" son eventos del terminal de cliente: Init, Deinit, NewTick. Por supuesto, si queremos es posible ampliar el rango de eventos. Al iniciar un asesor experto se crea el objeto myTE a nivel global. Es una instancia de la clase CTradeExpert. El objeto de la clase está ligeramente más abajo en el diagrama que otros objetos que indican que se ha creado después de la función del constructor.

Se marca un comando de creación con una línea de trazos y puntos y con una flecha abierta y el mensaje 1.1 CTradeExpert(). La línea de trazos y puntos con una flecha indica el tipo "create" por defecto del constructor CTradeExpert(). Después de crear una instancia de CTradeExpert se activa el paso 1.2 y el foco de control se devuelve al terminal. Para facilitar la lectura, indico mensajes síncronos en el formato #.#, como 1.1 y asíncronos como #. Luego, el terminal controla el evento Init usando la función OnInit() en el paso 2.1, el foco se devuelve en el paso 2.2. Los mensajes de tipo "call" se muestran como líneas con una flecha en forma de triángulo "pintada" en el extremo.

Si el evento Init devuelve un valor distinto a cero al terminal, significa que la inicialización ha fallado: se utiliza el paso 3.1 que lleva a la generación y control del evento Deinit . En el paso 3.2 el foco de control se devuelve al terminal. Luego, se borra el objeto de la clase CTradeExpert (paso 4.1). Por cierto, al crear un diagrama de clase, no he incluido la función destructor CTradeExpert en la clase. Esto puede hacerse posteriormente. Esta es una de las ventajas de la construcción de un diagrama: el proceso de construcción de varios diagramas es iterativo. Los que se ha hecho en primer lugar para el diagrama puede realizarse luego para otro, y después podemos modificar el primero.

Debe señalarse que el código de MQL5 para una plantilla de asesor experto estándar no contiene un bloque que controle la inicialización fallida. Lo he especificado para guardar la secuencia lógica. El diagrama de secuencia de UML utiliza el bloque opt con una condición de vigilancia OnInit()!=0, que es equivalente a la construcción de MQL5 if(OnInit()!= 0) {}.

En el paso 4.2 el foco de control se devuelve al terminal.

Ahora, el terminal está listo para controlar el evento NewTick.

El procesamiento de este evento se encuentra en el bucle del bloque y significa un bucle infinito. Es decir, el asesor experto controlará este evento hasta que lo desactivemos. El terminal procesa el evento NewTick usando la función OnTick (paso 5). En el paso 6 el foco de control se devuelve al asesor experto myTE. Este implementa las siguientes funciones usando 4 mensajes reflexivos: CheckSignal, OpenPosition, CheckPosition y ClosePosition. La reflexividad se debe al hecho de que el objeto del asesor experto envía se mensajes a sí mismo.

Además, estas funciones de la clase CTradeExpert se incluyen en el bloque loop(2). Dos significa que el bucle comprende dos fases. ¿Por qué dos? Porque controla dos dirección de las transacciones: largas y cortas (del paso 7 al 10). En el paso 11 el foco se pasa al terminal.

Los pasos 12 y 13 son responsables de la deinicialización y borrado del objeto del asesor experto, respectivamente.

Fig. 10. Diagrama SD para Test_TradeExpert.mq5

Fig. 10. Diagrama SD para Test_TradeExpert.mq5

De esta forma, hemos adquirido las principales habilidades de diseño. Con la ayuda de los diagramas creados se optimiza el trabajo del desarrollador. Ahora podemos comenzar a escribir código para el archivo Test_TradeExpert.mq5. Por supuesto, lo podemos hacer sin los diagramas. Pero cuando tenemos un asesor experto complejo, el uso de los diagramas reduce la probabilidad de errores y nos permite gestionar eficientemente el desarrollo de nuestro sistema de trading.

Usando la plantilla del asesor experto creamos ahora Test_TradeExpert.mq5

Creamos una instancia de la clase CTradeExpert myTE a nivel global.

Ahora vamos a completar el cuerpo de la función OnTick().

Escribimos las funciones de la clase de la forma siguiente:

for(long dir=0;dir<2;dir++)

     {

      myTE.CheckSignal(dir);

      myTE.OpenPosition(dir);

      myTE.CheckPosition (dir);

      myTE.ClosePosition(dir);

     }

El control del evento NewTick será algo similar a esto. Por supuesto, necesitamos aún especificar cada una de las funciones que serán utilizadas por los miembros de los datos de la clase, entre otros. Pero vamos a dejar este trabajo para un futuro. Ahora, nuestro objetivo es transferir la lógica de los diagramas UML al código de MQL5.


3. Desarrollo y presentación de un asesor experto basado en diagramas UML

Como ejemplo, vamos a crear diagramas para un asesor experto complejo. Vamos a definir sus características en el contexto de una determinada estrategia implementada en MQL5. En general, nuestro asesor experto realizará las operaciones de trading y, en particular, generará las señales de trading y mantendrá posiciones abiertas y la gestión del dinero. Es más bien una plantilla de estrategia de trading. Sin embargo, intentaremos trabajar con ella para poder realizar ejercicios prácticos.

En primer lugar, creamos un diagrama de caso de uso para nuestro asesor experto. Será diferente del que hemos visto anteriormente solo hasta cierto punto. Presté atención al entorno interno del sistema de trading, ignorando el exterior (Fig. 11) ya que implementaremos en el código solo las tareas de trading.

Fig. 11. Diagrama de caso de uso del sistema de trading

Fig. 11. Diagrama de caso de uso del sistema de trading

Vamos ahora a definir la estructura del asesor experto. Asumimos que vamos a utilizar los desarrollos de la librería estándar ya que son consistentes con los objetivos establecidos para el sistema de trading. Ha sido ampliada de forma sustancial recientemente. Y sobre todo afecta a las clases de estrategias de trading. Por tanto, nuestro objetivo es crear un diagrama de clase. No será sencillo, así que tenga paciencia.

Aquí me gustaría mencionar que hemos usado la librería estándar por varias razones. Primero, con ella intentamos crear un robot de trading. Y, segundo, que también es importante, tenemos algo de práctica trabajando con diagramas UML. En tercer lugar, quizás la propia librería es de gran valor. Podemos aprender muchas cosas útiles de la librería y, al mismo tiempo, intentar aprender su no tan simple estructura.

La conversión de código en la estructura de un diagrama UML se llama ingeniería inversa. De hecho, es lo que estamos haciendo manualmente. Existe un software profesional que nos permite hacer esto automáticamente (IBM Rational Rose, Visual Paradigm for UML, etc.). Pero por razones prácticas creo que necesitamos trabajar "manualmente".

Vamos a crear un modelo de la clase básica para implementar estrategias de trading CExpert usando el bloque "Class". Vamos a ver qué otras clases y construcciones se utilizan en el cuerpo de la clase CExpert . Primero debe señalarse que la clase CExpert deriva de la clase básica CExpertBase, que, a su vez, deriva de la clase básica CObject.

En el diagrama creamos bloques para estas clases y definimos la relación entre las clases usando una línea con una punta de flecha triangular "sin pintar" (generalización). Añadimos un comentario al modelo de la clase CExpert (un rectángulo amarillo con una esquina doblada). Ahora, la estructura de la clase intermedia es como esta, Fig. 12. Vamos a llamar al diagrama Expert.

Fig. 12. El diagrama Expert, la vista inicial

Fig. 12. El diagrama Expert, la vista inicial

Vamos a ver el código en el archivo Expert.mqh . La clase CExpert, entre otras cosas, implica las enumeraciones ENUM_TRADE_EVENTS y ENUM_TIMEFRAMES, una de las 8 estructuras predefinidasMqlDateTime. La clase también utiliza otras instancias de clase como: CExpertTrade, CExpertSignal, CExpertMoney, CExpertTrailing, CIndicators, CPositiontInfo, COrderInfo.

Ahora necesitamos realizar algunos cambios en el diagrama. Primero especificamos que las clases CExpertSignal, CExpertMoney, CExpertTrailing derivan de la clase básica CExpertBase, y las clases CPositiontInfo, COrderInfo derivan de CObject (he establecido el estereotipo "metaclass" para ellas).

Vamos a marcar las relaciones de dependencia con el "uso" estereotipo entre el bloque de la clase CExpert y otras clases sin olvidarnos de la estructura y enumeraciones de MqlDateTime . Cambiamos el estilo de color de los bloques y obtenemos la siguiente estructura, Fig. 13.

Fig. 13. El diagrama Expert, la vista inicial

Fig. 13. El diagrama Expert, la vista inicial


No obstante, esta estructura no proporciona una visión completa, ya que hay una serie de clases que son utilizadas indirectamente por las clases ya citadas. ¿Qué tipo de clases son? En primer lugar, la clase CExpertTrade deriva de CTrade. La última es una subclase de CObject.

La clase CExpertTrade utiliza la enumeración ENUM_ORDER_TYPE_TIME y las clases CSymbolInfo y CAccountInfo también son hijas de CObject. La clase CTrade también utiliza instancias de la clase CSymbolInfo . Vamos a hacer cambios en el diagrama. Ahora, nuestro diagrama tiene la siguiente forma, Fig. 14.

Fig. 14. El diagrama Expert, la vista inicial

Fig. 14. El diagrama Expert, la vista inicial

De nuevo, el diagrama está incompleto. Por ejemplo, si miramos en el archivo de la librería estándar Trade.mqh, veremos que CTrade utiliza diferentes estructuras y enumeraciones y la clase CSymbolInfo . Si todas estuvieran cargadas en un diagrama, este quedaría demasiado sobrecargado. Y esto lo haría difícil de comprender.

Para solucionar este inconveniente he usado un paquete para el diagrama. Este encapsula las clases, enumeraciones y otros paquetes relacionados. He conectado el paquete con los elementos del diagrama a través de la interfaz. Por ejemplo, el diagrama para el paquete CTrade puede representarse de la siguiente forma - Fig. 15.

ig. 15. Diagrama de la clase para el paquete CTrade

Fig. 15. Diagrama de la clase para el paquete CTrade

El diagrama del paquete CTrade muestra las relaciones de dependencia de la clase CTrade con las enumeraciones y la estructura.

Relaciones con la clase básica CObject y la clase CSymbolInfo usada se implementa a través de una interfaz.

Cerca de las interfaces hay un icono de relación con el diagrama de la clase que contiene el paquete CTrade como un único elemento. Al hacer clic en cualquiera de las interfaces vamos automáticamente al diagrama original (Fig. 16).

Fig. 16. Diagrama del experto con interfaces

Figura 16. Diagrama del experto con interfaces

Las relaciones de la interfaz son de color naranja. El icono del diagrama de la clase junto al paquete CTrade indica la posibilidad de desplazarnos a este diagrama. De esta forma, al usar la encapsulación podemos mejor de forma significativa la legibilidad del diagrama de la clase.

Así que vamos con ello. La clase CObject utiliza punteros e instancias de la misma clase en su cuerpo. Por tanto, podemos establecer la relación de dependencia para el bloque CObject con el estereotipo "use" relativo a sí mismo.

Veamos el bloque del modelo de clase CExpertBase. En base a las primeras líneas del archivo de cabecera ExpertBase.mqh podemos decir que esta clase utiliza múltiples instancias de varias clases y enumeraciones. Por tanto, para el modelo de clase y sus relaciones es razonable crear el paquete CExpertBase.

Por ello, vamos primero a definir el modelo de clase CExpertBase en el diagrama del paquete. A través de la interfaz mostramos la relación con la clase básica CObject, y la relación de uso con las clases CSymbolInfo y CAccountInfo. A continuación, usando los bloques de clases y relaciones de dependencia especificamos que la clase CExpertBase utiliza las siguientes clases: CiOpen, CiHigh, CiLow, CiSpread, CiTime, CiTickVolume, CiRealVolume.

Las primeras cuatro clases derivan de CPriceSeries, y las últimas cuatro de CSeries. Además, la clase CSeries tiene una hija CPriceSeries que es, a su vez, hija de CArrayObj. Las relaciones de herencia ya se han usado con anterioridad, como recordamos. Las denominamos como una relación de generalización en el diagrama.

No olvide que la clase CExpertBase utiliza en su cuerpo enumeraciones como: ENUM_TYPE_TREND, ENUM_USED_SERIES, ENUM_INIT_PHASE, ENUM_TIMEFRAMES. La última enumeración también es utilizada por las hijas de la clase CPriceSeries y la clase CSeries. Para no perder las relaciones y hacer el diagrama más claro, vamos a ajustar el estilo de cada uno de los elementos del diagrama. Como resultado obtenemos el siguiente diagrama (Fig. 17):

Fig. 17. Diagrama de la clase para el paquete CExpertBase

Fig. 17. Diagrama de la clase para el paquete CExpertBase

Aún no está completo y tendremos que trabajar algo más en él. Resulta que las cuatro clases que heredan la clase CPriceSeries también utilizan la clase CDoubleBuffer . Además, cada una de las cuatro clases usa su clase de buffer que deriva de CDoubleBuffer. Por tanto, COpen usa COpenBuffer etc.. CDoubleBuffer tiene una clase básica (CArrayDouble) y usa ENUM_TIMEFRAMES.

CArrayDouble hereda CArray, usa punteros a las instancias de la misma clase y la enumeración ENUM_DATATYPE . La clase COpenBuffer y otras clases de buffer de las series de precio (CHighBuffer, CLowBuffer, CCloseBuffer) usan la enumeración ENUM_TIMEFRAMES .

Las cuatro clases que heredan la clase CSeries solo usan sus propias clases de buffer (CSpreadBuffer, CTimeBuffer, CTickVolumeBuffer, CRealVolumeBuffer). El primero de los buffers de la clase CSpreadBuffer hereda CArrayInt, otros heredan CArrayLong. Las últimas dos clases utilizan punteros a las instancias de su propia clase, la enumeración ENUM_DATATYPE y derivan de CArray, que, a su vez, es hija de la clase CObject.

La clase CPriceSeries y sus hijas usan la clase CDoubleBuffer y la enumeración ENUM_TIMEFRAMES .

CSeries usa las enumeraciones ENUM_SERIES_INFO_INTEGER, ENUM_TIMEFRAMES. Y hereda CArrayObj. La última hereda CArray, usa los punteros ENUM_POINTER_TYPE, a las instancias de su propia clase y la clase CObject . Como resultado, obtenemos el gráfico mostrado en la Figura 18.

Fig. 18. Diagrama de la clase extendido para el paquete CExpertBase

Fig. 18. Diagrama de la clase extendido para el paquete CExpertBase

Y el diagrama original Expert para las clases y paquetes CExpert, CExpertBase, CSymbolInfo, CAccountInfo y CObject con interfaces tiene es el siguiente (Fig.19).

Fig. 19. Diagrama del experto con interfaces

Fig. 19. Diagrama del experto con interfaces

También he añadido la enumeración ENUM_ORDER_TYPE usada por CExpertTrade. Para facilitar la legibilidad he marcado el grupo de relaciones con diferentes colores.

Continuamos con nuestro trabajo. Espero que comprenda la lógica. El modelo de una clase en el diagrama puede tener muchas relaciones con otras clases y entidades. Por ello solo sustituyo algunos grupos con un paquete en el diagrama base.

Vamos a estudiar CSymbolInfo. Si miramos el código de SymbolInfo.mqh, veremos que la clase base CSymbolInfo usa algunas enumeraciones y estructuras MQL5. Está bien usar un paquete y sus relaciones para ello (Fig. 20).

Fig. 20. Diagrama del paquete CSymbolInfo

Fig. 20. Diagrama del paquete CSymbolInfo

Puede usarse algo de espacio libre en el diagrama para los comentarios. También he marcado la relación de la interfaz con la clase padre CObject. El diagrama original Expert de paquetes y clases será ligeramente modificado . Daré su versión actualizada más tarde, cuando todas las clases y paquetes se muestren en el diagrama.

Así que vamos con ello. Veamos el código MQLen AccountInfo.mqh. Como resultado, CAccountInfo también utiliza algunas enumeraciones. Las reflejamos en el diagrama del paquete que vamos a crear para esta clase y sus relaciones con otras entidades (Fig. 21).

Fig. 21. Diagrama del paquete CAccountlInfo

Fig. 21. Diagrama del paquete CAccountlInfo

Ahora vamos a trabajar con la clase CExpert . Para esta clase también creamos un paquete CExpert, que aparecerá como se indica en la Fig. 22. Seguimos mejorando la legibilidad de nuestro diagrama principal. La clase CExpert está conectada con algunas otras clases como indican las líneas naranjas de la interfaz con una flecha.

Fig. 22. Diagrama del paquete CExpert

Fig. 22. Diagrama del paquete CExpert


Vamos a explorar otras clases. Crearemos más paquetes para ellas.

CExpertSignal deriva de CExpertBase. Esta relación ya ha sido mostrada en el diagrama original Expert. Además, la clase CExpertSignal usa CArrayObj, COrderInfo, CIndicators e instancias de su propia clase (Fig .23). En particular, la interfaz de la relación con la clase CArrayObj nos llevará al diagrama del paquete CExpertBase que muestra la relación de la clase CArrayObj con otras entidades.

Fig. 23. Diagrama del paquete CExpertSignal

Fig. 23. Diagrama del paquete CExpertSignal

No estoy mostrando ahora todos los diagramas, ya que todos se encuentran disponibles en el archivo Expert.simp. Vamos a ver ahora nuestro diagrama de paquetes y clases actualizado Expert (Fig. 24).

Como puede ver, casi todas las clases principales en el diagrama se han encapsulado en paquetes para facilitar la comprensión del diagrama. He cambiado el color de la línea de generalización a marrón, para distinguirla de la línea de la relación de dependencia.

Fig. 24. El diagrama de paquetes y clases Expert

Fig. 24. El diagrama de paquetes y clases Expert

Por tanto, hemos reflejado todo lo que puede obtenerse del código disponible en la librería estándar para crear diagramas. Solo necesitamos añadir algunos bloques más que especifiquen las operaciones de trading del asesor experto.

El primer bloque esCmyExpert que hereda las "habilidades" de trading de la clase CExpert . Este es el bloque por el que hemos dedicado tanto tiempo a trabajar en la ingeniería inversa. Implementará una estrategia de trading específica. También necesitamos especificar las funciones virtuales de las clases básicas del asesor experto.

Para esta finalidad creamos el bloque de clases CmyExpertSignal, CmyExpertMoney, CmyExpertTrailing e indicamos que tienen la procedencia adecuada (Fig. 25).

Fig. 25. El diagrama ampliado de paquetes y clases Expert

Fig. 25. El diagrama ampliado de paquetes y clases Expert


Las funciones y datos que cada una de estas clases deben incluir es una decisión a tomar por el desarrollador. Aquí estoy intentando mostrar el esquema más general, no una implementación específica de una clase derivada. Por tanto, para cada una de las clases derivadas podemos crear un diagrama independiente con una lista detallada de métodos y propiedades incluidas, tal y como se ha hecho, por ejemplo, en la Fig. 8.

Ahora vamos a ver cómo podemos usar el diagrama de la serie en nuestro trabajo. Permítanme que les recuerde que este muestra cómo nuestro asesor experto opera con respecto a la línea cronológica.

Escribimos la información del trabajo del asesor experto en orden cronológico (Fig. 26).

Fig. 26. Secuencia del diagrama del asesor experto

Fig. 26. Secuencia del diagrama del asesor experto

El terminal sirve como un actor. A nivel global crea el objeto myTrader, una instancia de CmyExpert (paso 1.1). El verde hace referencia a los eventos predefinidos del terminal de cliente (Init, Deinit, NewTick, Trade.) La lógica del diagrama de la secuencia ha sido descrita antes. Aquí me gustaría destacar algunos puntos específicos. Cuando crece el cuerpo del asesor experto y hay cada vez más código, se hace más difícil mostrarlo en un diagrama.

Para resolver este problema usamos el enfoque del bloque. Se visualiza un conjunto de funciones habituales en forma de bloque. Por regla general es otro diagrama de secuencia. Se dice que es un uso de interacción.

Por tanto, en este caso, he creado un diagrama de secuencia llamado OnInit para reflejar la lógica de gestionar el evento del terminal Init en un diagrama separado. Sintácticamente se define como una frontera con la palabra clave ref (referencia) y se usa cuando la señal de control pase de OnInit (paso 2.1) a la línea cronológica del objeto Init .

Además, he establecido un desplazamiento de la interfaz hacia este diagrama de secuencia para OnInit. Es decir, si hacemos clic dos veces en el borde, podemos realmente abrir un diagrama de secuencia detallado de OnInit (Fig. 27).

Fig. 27. El diagrama de secuencia de OnInit

Fig. 27. El diagrama de secuencia de OnInit

Los desplazamientos a otros diagramas de secuencia son muy adecuados cuando hay que repetir las mismas acciones.

Por ejemplo, el diagrama OnInit contiene acciones conectadas con la deinicialización del asesor experto cuyo procesamiento se hace en myTrader_Deinit (Fig. 28).

Fig. 28. El diagrama de secuencia de myTrader_Deinit

Fig. 28. El diagrama de secuencia de myTrader_Deinit

En general, en esta etapa del diseño del asesor experto tengo cuatro diagramas de secuencia. Naturalmente, en un desarrollo más serio puede que necesitemos diagramas adicionales. Por ejemplo, no he controlado otros eventos del terminal de cliente (NewTick, Trade).


Conclusiones

En este artículo he recomendado tener en cuenta la naturaleza multidimensional del proceso de desarrollo de un asesor experto usando el lenguaje gráfico UML, que se utiliza para el modelado visual de los sistemas de software orientados a objeto. La principal ventaja de este enfoque es la visualización del diseñador.

Al igual que ocurre con cualquier fenómeno complejo, UML tiene sus propias desventajas que el desarrollador debe tener en cuenta (redundancia, semántica imprecisa, etc.).

Espero que la metodología descrita del desarrollo del asesor experto les resulte interesante. Estaré agradecido de recibir cualquier comentario y crítica constructiva.


Ubicación de los archivos:

#
          Archivo                
            Ruta               
Descripción
 1  TradeExpert.mqh
  %MetaTrader%\MQL5\Include  Clase del asesor experto
 2  Test_TradeExpert.mq5
  %MetaTrader%\MQL5\Experts  Asesor experto
 3  Expert.simp  %Documents%\UML projects  Proyecto de diagramas de UML
 4   SoftwareIdeasModeler.4.103.zip  %Program Files%\SoftwareIdeasModeler
  Archivo de distribución del modelador de ideas de software


Bibliografía:

  1. Free UML courses. The Internet University of Information Technology
  2. Jim Arlow, Ila Neutstadt. UML2 and the Unified Process Practical: Object-Oriented Analysis and Design
  3. Leonenkov A. Object-Oriented Analysis and Design Using UML and IBM Rational Rose.
  4. Martin Fowler UML Distilled: A Brief Guide to the Standard Object Modeling Language. - 192 стр.
  5. Paul Kimmel. UML Demystified. - 272 стр.
  6. F. A. Novikov, D. Y. Ivanov. Modeling in UML
  7. Mark Priestly. Practical Object-Oriented Design With Uml, Mcgraw Hill Higher Education; 2nd edition, 2007.

Traducción del ruso hecha por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/ru/articles/304

Archivos adjuntos |
expert.zip (82.35 KB)
tradeexpert.mqh (3.5 KB)
Cómo añadir nuevos idiomas de interfaz de usuario a la plataforma de Meta Trader 5 Cómo añadir nuevos idiomas de interfaz de usuario a la plataforma de Meta Trader 5
La interfaz de usuario de la plataforma de Meta Trader 5 está traducida a varios idiomas. No se preocupe si su idioma no se encuentra entre los soportados. Puede fácilmente completar la traducción usando la utilidad especial del paquete multilenguaje de Meta Trader 5, puesta a disposición de todos los usuarios de manera gratuita por MetaQuotes Software Corp. En este artículo mostraremos algunos ejemplos sobre cómo añadir nuevos idiomas de interfaz de usuario a la plataforma de Meta Trader 5.
Aplicar la transformada de Fisher y su transformada inversa al análisis de mercado en Meta Trader 5 Aplicar la transformada de Fisher y su transformada inversa al análisis de mercado en Meta Trader 5
Ahora sabemos que la función densidad de probabilidad (PDF) de un ciclo de mercado no recuerda a una gausiana sino más bien a una PDF de una onda senoidal y la mayoría de indicadores asumen que la PDF del ciclo del mercado es gausiana, por lo que necesitamos conocer una forma de "corregir" eso. La solución es usar la transformada de Fisher. La transformada de Fisher cambia una PDF de cualquier forma de onda en otra aproximadamente gausiana. Este artículo describe las matemáticas que hay tras la transformada de Fisher y la transformada inversa de Fisher y su aplicación al trading. Se presenta y evalúa un módulo de señal de trading propio basado en la transformada de Fisher inversa.
MQL5-RPC. Llamadas a procedimientos remotos desde MQL5: acceso al servicio web y analizador XML-RPC ATC para divertirse y conseguir beneficios MQL5-RPC. Llamadas a procedimientos remotos desde MQL5: acceso al servicio web y analizador XML-RPC ATC para divertirse y conseguir beneficios
Este artículo describe el esquema conceptual de MQL5-RPC que permite las llamadas a procedimientos remotos desde MQL5. Comienza con los fundamentos de XML-RPC, la implementación de MQL5 y continúa con dos ejemplos de uso real. El primer ejemplo es el uso de un servicio web externo y el segundo es un cliente del servicio del analizador XML-RPC ATC 2011 simple. Si está interesado en conocer cómo se implementan y analizan las distintas estadísticas de ATC 2011 en tiempo real, este es su artículo.
Usar WinInet en MQL5. Parte 2: solicitudes y archivos POST Usar WinInet en MQL5. Parte 2: solicitudes y archivos POST
En este artículo seguimos estudiando los principios del trabajo con internet usando solicitudes HTTP e intercambiando información con el servidor. El artículo describe nuevas funciones de la clase CMqlNet, métodos para enviar información desde formularios y envío de archivos usando solicitudes POST así como autorización en sitios web bajo un registro de usuario usando cookies.