Discusión sobre el artículo "Experto comercial universal: Modelo de eventos y prototipo de estrategia comercial (Parte 2)"

 

Artículo publicado Experto comercial universal: Modelo de eventos y prototipo de estrategia comercial (Parte 2):

Este artículo continúa con la serie de comentarios dedicados al modelo universal de expertos. En esta parte se describe un modelo original de eventos basado en el procesamiento centralizado de datos, y también se estudia la estructura de la clase básica del motor CStrategy.

Este artículo continúa la presentación a los lectores del motor comercial universal CStrategy. En el primer artículo Experto comercial universal: Los modos comerciales de las estrategias (Parte 1) se analizaron con detalle los modos comerciales y las funciones que los organizan. Se propuso un esquema universal de expertos, que consta de cuatro métodos, dos de los cuales abren nuevas posiciones, mientras que los otros dos las cierran. Una combinación diversa en la llamada de estos métodos determina la presencia de uno u otro modo comercial, por ejemplo, para un experto así se puede establecer un modo solo de compras o solo de ventas, el acompañamiento de las posiciones abiertas con anterioridad o el modo espera. Gracias a estos modos, el experto adquiere la posibilidad de ajustar de manera flexible su funcionamiento, dependiendo de la hora comercial o incluso del día de la semana.

Sin embargo, los modos comerciales no son, ni mucho menos, lo único que puede necesitar un experto comercial. En esta segunda parte de la serie de artículos, hablaremos sobre el modelo de eventos del motor comercial CStrategy, basado en el procesamiento centralizado de eventos. El esquema de procesamiento propuesto se distingue de los eventos de sistema precisamente en que todos los eventos se reúnen en un sitio. Hablaremos más abajo de las ventajas que proporciona tal organización.

Asimismo, en esta artículo se describen las dos clases más importantes de todo el motor comercial: son las clases CStrategy y CPosition. La primera de ellas constituye el núcleo de la lógica comercial del experto, ya que une los eventos y los modos en una única carcasa flexible, que heredará directamente el experto del usuario. La segunda clase es la base de la operaciones comerciales universales. En él se ubican las acciones con las posiciones abiertas (por ejemplo, el cierre de posición o el cambio de su nivel de Stop Loss o Take Profit). Gracias a esto, todas las acciones comerciales se convierten en acciones de un solo tipo e independientes de la plataforma.

Acceso a los eventos sucedidos en otros instrumentos, estructura MarketEvent

Al proyectar un sistema comercial que analiza a la vez varios instrumentos, normalmente es necesario un mecanismo que realice el seguimiento del cambio de los precios en varios instrumentos. Sin embargo, la función estándar OnTick se llama solo en el momento de llegada de un nuevo tick en el instrumento en el que ha sido iniciado el experto. Por otra parte, a la disposición de los manejadores de los sistemas comerciales se encuentra la función OnBookEvent. A diferencia de OnTick, la función OnBookEvent se invoca al cambiar la profundidad de mercado del instrumento al que se realizó la suscripción con la ayuda de la función MarketBookAdd.

El cambio de la profundidad de mercado es un evento muy frecuente, y por eso el seguimiento de semejante evento es un procedimiento que exige el gasto de muchos recursos. Normalmente, al experto le basta con realizar un seguimiento de los cambios del flujo de ticks en otros instrumentos. Por otra parte, el evento de cambio en la profundidad de mercado incluye también la llegada de un nuevo tick. Aparte de OnBookEvent, se puede ajustar con cierta periodicidad la llamada OnTimer y ya analizar en esta función los precios cambiados de varios instrumentos.

De esta forma, en las funciones de sistema que reaccionan a los eventos NewTick, BookEvent y Timer, se puede ubicar la llamada de un cierto módulo intermedio (lo llamaremos de forma convencional EventProcessor), que a su vez analizaría el cambio de los precios en varios instrumentos simultáneamente y generaría este u otro evento. Cada evento tendría una descripción unificada en forma de estructura y se enviaría a los métodos de gestión de la estrategia. La estrategia, tras recibir el evento correspondiente en forma de estructura, reaccionaría a él o lo dejaría pasar. En este caso, además, la función de sistema, que sería prácticamente la iniciadora de este evento para el experto final, permanecería desconocida.

En realidad, si el experto ha recibido una notificación sobre la llegada de un nuevo tick, entonces da igual cómo haya sido recibida la información: si a través de OnTick, OnTimer o OnBookEvent. Solo importa que el nuevo tick para el instrumento indicado haya llegado. El manejador de eventos puede ser uno para varias estrategias. Por ejemplo, si cada estrategia la presentamos en forma de clase de usuario, entonces se pueden guardar de golpe varios ejemplares de esta clase en una lista especial de estrategias. Además, cada una de las estrategias de la lista tendría la posibilidad de recibir un nuevo evento, generado por el módulo EventProcessor. Presentamos de forma esquemática el modelo de creación y distribución de eventos en el siguiente gráfico:

Fig. 1. Esquema del modelo de creación y distribución de eventos

Autor: Vasiliy Sokolov

 
Gracias al autor. El material del artículo es extremadamente útil y además está excelentemente presentado. Hace tiempo que quería poner en orden mis planteamientos sobre la escritura experta, y aquí el autor del artículo ya ha pasado por todos los dolores de la creatividad y ofrece una solución lista para usar. ¡Estupendo! Espero con impaciencia la continuación.


¡Vamos a golpear la falta de camino de la automatización de los sistemas de comercio, las torturas de la creatividad y la dejadez de los desarrolladores con el "motor de comercio "!

 

Gracias al autor por el artículo informativo, pero tengo algunas dudas sobre la fiabilidad de la implementación del software.

En el código que propones, todas las funciones manejadoras de eventos hacen referencia a la variable común event_type o a la estructura m_event en una instancia común de CStrategy.

Pero esto puede ser peligroso, porque los eventos se producen de forma asíncrona y los hilos de sus manejadores pueden solaparse en el tiempo, modificando caóticamente los datos comunes o provocando fallos al acceder a las mismas zonas de memoria.

Normalmente, la sincronización de hilos se realiza mediante semáforos, mutexes, funciones de espera, secciones de código crítico, etc., pero MQL no dispone de estos medios, por lo que es obvio que en las funciones-manejadoras de eventos asíncronos es necesario minimizar las referencias a instancias globales de objetos y variables, procurando utilizar las locales.

Sobre esta base, la combinación de manejador de eventos y bloque de datos propuesta en el artículo, en mi humilde opinión, no es una buena idea.

 
Eugene Myzrov:
Gracias al autor. El material del artículo es extremadamente útil y además está excelentemente presentado. Hace tiempo que quería poner en orden mis planteamientos sobre la escritura experta, y aquí el autor del artículo ya ha pasado por todos los dolores de la creatividad y ofrece una solución lista para usar. ¡Estupendo! Espero con impaciencia la continuación.


¡Vamos a golpear la falta de camino de la automatización de los sistemas de comercio, la agonía de la creatividad y la dejadez de los desarrolladores con el "motor de comercio"!

Gracias.

Ivan Negreshniy:

Gracias al autor por el artículo informativo, pero tengo algunas dudas sobre la fiabilidad de la implementación del software.

En el código propuesto, todas las funciones de control de eventos se refieren a la variable común event_type o a la estructura m_event en una instancia común de CStrategy.

Pero esto puede ser peligroso, porque los eventos ocurren de forma asíncrona y los hilos de sus manejadores pueden solaparse en el tiempo, cambiando caóticamente los datos comunes o causando fallos al acceder a las mismas áreas de memoria.

...

Gracias por el interesante comentario. Efectivamente, los eventos en MetaTrader son asíncronos. Sin embargo, la ejecución de los hilos de usuario es estrictamente secuencial. Esto significa que otros eventos no serán procesados hasta que el Asesor Experto termine de procesar el evento actual. El siguiente código ilustra este punto:

//+------------------------------------------------------------------+
//|TestAsynch.mq5
//|Derechos de autor 2015, Vasiliy Sokolov. |
//|http://www.mql5.com
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, Vasiliy Sokolov."
#property link      "http://www.mql5.com"
#property version   "1.00"
bool need_check = true;
#define  EVENT_CHECK_ASYNCH 1
//+------------------------------------------------------------------+
//| Función tick experto|
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   if(need_check)
   {
      EventChartCustom(ChartID(), EVENT_CHECK_ASYNCH, 0.0, 0.0, "Comprobación de asincronía");
   }
   if(need_check)
      printf("El hilo del usuario se termina primero".);
  }
//+------------------------------------------------------------------+
//| Función ChartEvent|
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
//---
   if(id == CHARTEVENT_CUSTOM+EVENT_CHECK_ASYNCH && need_check)
   {
      printf("Entonces se llama al evento OnChartEvent".);
      need_check = false;
   }
  }
//+------------------------------------------------------------------+

Su ejecución produce líneas en la siguiente secuencia:

2016.01.15 13:51:31.724 TestAsynch (NZDUSD,W1)  Потом вызывается событие OnChartEvent
2016.01.15 13:51:31.722 TestAsynch (NZDUSD,W1)  Сначала завершается пользовательский поток

Así, no hay errores causados por el cambio conjunto de la variable compartida m_event, porque el código se ejecuta secuencialmente. También debo señalar que la propia estructura es privada y sólo es accesible por referencia a métodos especiales. Por lo tanto, su ubicación real dentro de CStrategy no importa, la estructura puede ser fácilmente creada directamente en métodos manejadores de eventos y también pasada a instancias de estrategia.

 
Vasiliy Sokolov:

Muchas gracias.

Gracias por la interesante observación. Efectivamente, los eventos en MetaTrader son asíncronos. Sin embargo, la ejecución de los hilos de usuario es estrictamente secuencial. Esto significa que otros eventos no serán procesados hasta que el Asesor Experto termine de procesar el evento actual. El siguiente código ilustra este punto:

Su ejecución produce líneas en la siguiente secuencia:

Así, no hay errores causados por el cambio conjunto de la variable compartida m_event, porque el código se ejecuta secuencialmente. También debo señalar que la propia estructura es privada y sólo es accesible por referencia a métodos especiales. Por lo tanto, su ubicación real dentro de CStrategy no importa, la estructura puede ser fácilmente creada directamente en métodos manejadores de eventos y también pasada a instancias de estrategia.

Tienes razón, la ejecución estrictamente secuencial de los manejadores de eventos puede eliminar errores, pero esto es esencialmente el modo de un solo hilo, donde es difícil lograr un alto rendimiento.

Al mismo tiempo, hay tareas de tiempo crítico que requieren paralelización, por ejemplo, cálculos con grandes volúmenes de precios y datos históricos realizados con OpenCL o tareas más específicas que son relevantes para mí - entrenamiento de redes neuronales en diferentes símbolos y períodos realizados con la ayuda del motor multihilo descrito en mi artículo.
https://www.mql5.com/es/articles/706

Создание нейросетевых торговых роботов на базе MQL5 Wizard и Hlaiman EA Generator
Создание нейросетевых торговых роботов на базе MQL5 Wizard и Hlaiman EA Generator
  • 2013.08.29
  • Ivan Negreshniy
  • www.mql5.com
В статье рассматривается метод автоматизированного создания нейросетевых торговых роботов на базе MQL5 Wizard и Hlaiman EA Generator. Узнайте, как легко начать работать с нейронными сетями, минуя длительные этапы изучения теоретических материалов и написания собственного кода.
 
Ivan Negreshniy:

Tienes razón, la ejecución estrictamente secuencial de los manejadores de eventos puede eliminar errores, pero se trata esencialmente de un modo monohilo en el que es difícil alcanzar un alto rendimiento.

Al mismo tiempo, hay tareas de tiempo crítico que requieren paralelización, por ejemplo, cálculos con grandes volúmenes de precios y datos históricos realizados con OpenCL o tareas más específicas que son relevantes para mí - entrenamiento de redes neuronales por diferentes símbolos y períodos, realizado con la ayuda del motor multihilo descrito en mi artículo.
https://www.mql5.com/es/articles/706.

Paralelización en MetaTrader se realiza por el probador de estrategia multi-hilo. Por lo tanto, si ejecuta una estrategia escrita con la ayuda del motor descrito en el probador de estrategias, se convertirá automáticamente en multihilo. Dado que no hay dlls de terceros, puede utilizar MQL Networl Cloud en todo su potencial. Lo que escribes se refiere al propio MetaTrader. Sí, el motor, así como cualquier Asesor Experto o script en MetaTrader, es de un solo hilo, pero el optimizador le permite realizar multi-threaded y cloud computing del código presentado.

En cuanto al rendimiento del motor en sí, todo está bien aquí. Usted puede asegurarse de ello mediante la realización de perfiles. Los costes de infraestructura y entrega de eventos son mínimos. El tiempo de ejecución principal se concentra en las llamadas de funciones del sistema y métodos personalizados BuyInit, SellInit, BuySupport, SellSupport. Basado en cálculos de perfil, el motor es capaz de manejar muchas docenas de eventos por segundo, redirigiéndolos sin esfuerzo a múltiples estrategias simultáneamente.

Lo que se ofrece con el artículo, pido disculpas, no es señalar con el dedo. Es una solución verificada y probada durante varios años. Todas las llamadas y procedimientos internos son óptimos e importantes. Los algoritmos se prueban en el perfilador. No hay restricciones en la organización interna del código de usuario. En general, hay de todo para la felicidad completa. Tómelo y úselo.

 
Muchas gracias a Vasiliy Sokolov por sus esfuerzos para promover el buen estilo de programación en general y la programación orientada a objetos en particular.
El artículo está claramente expuesto y es muy útil, al menos para los principiantes en MQL, que soy yo. :)
Por favor, responda a la siguiente pregunta:
En mis algoritmos de negociación, las posiciones
por órdenes de mercado de tipo Compra/Ventase abren en situaciones especiales - si el precio ya ha superado el nivel correspondiente o antes del final de la sesión de negociación.
Generalmente las posiciones se abren/cierran en la ruptura del nivel alcista/bajista (para Long) mediante la colocación de órdenes stop BuyStop/SelStop, que se recalculan al comienzo de una nueva barra.
¿Podría sugerirme cómo sería posible introducir la colocación y el cambio de órdenes stop en las clases descritas?
 
Mike:
Muchas gracias a Vasiliy Sokolov por sus esfuerzos para promover el buen estilo de programación en general y la programación orientada a objetos en particular.
El artículo está claramente expuesto y es muy útil, al menos para los principiantes en MQL, que soy yo. :)
Por favor, responda a la siguiente pregunta:
En mis algoritmos de negociación, las posiciones
por órdenes de mercado de tipo Compra/Ventase abren en situaciones especiales - si el precio ya ha superado el nivel correspondiente o antes del final de la sesión de negociación.
Por lo general, las posiciones se abren/cierran en la ruptura del nivel alcista/bajista (para Long) mediante la colocación de órdenes stop BuyStop/SelStop, que se vuelven a calcular al comienzo de una nueva barra.
¿Podría sugerirme cómo podría introducir la colocación y el cambio de órdenes stop en las clases descritas?

Saludos. En estos momentos se están elaborando algoritmos para gestionar las órdenes pendientes, pero todavía no hay una implementación concreta en la versión actual del motor. Lo único que puedo sugerir por el momento es colocar el código para colocar órdenes pendientes en los métodos BuyInit y SellInit. También es necesario enumerar allí las órdenes pendientes y todas aquellas acciones que normalmente tienen que hacerse en los Asesores Expertos normales.

En el futuro se planea añadir al motor métodos para procesar órdenes pendientes y hacer su correspondiente descripción. Funcionarán de forma similar a los métodos de gestión de posiciones.

 
Vasiliy Sokolov:

Saludos. En estos momentos se está trabajando en algoritmos para la gestión de órdenes pendientes, pero no hay una implementación concreta en la versión actual del motor. Lo único que puedo sugerir por el momento es colocar el código para colocar las órdenes pendientes en los métodos BuyInit y SellInit. También es necesario enumerar allí las órdenes pendientes y todas aquellas acciones que normalmente se tienen que hacer en los Asesores Expertos normales.

En el futuro se planea añadir al motor métodos para procesar órdenes pendientes y hacer su correspondiente descripción. Funcionarán de forma similar a los métodos de gestión de posiciones.

Gracias, Vasily, estaremos esperando. :)
 
Vasily, ¡muchas gracias por los artículos! ¡Simplemente genial y muy útil para un principiante!
 

gracias

*****