English Русский 中文 Deutsch 日本語 Português 한국어 Français Italiano Türkçe
preview
Eventos de Trading en MetaTrader 5

Eventos de Trading en MetaTrader 5

MetaTrader 5Trading | 20 diciembre 2013, 14:39
1 282 0
MetaQuotes
MetaQuotes

Introducción

Todos los comandos para ejecutar operaciones de trading se pasan al servidor de trading desde el terminal de cliente MetaTrader 5 a través de solicitudes de envío. Cada solicitud se debe llenar correctamente de acuerdo con la operación solicitada; de lo contrario, no pasará la validación primaria y no se aceptará por el servidor para su procesamiento.

Las solicitudes aceptadas por el servidor de trading se almacenan en forma de órdenes que pueden ser pendientes o ejecutarse inmediatamente por el precio de mercado. Las órdenes se almacenan en el servidor hasta que se llenan o cancelan. El resultado de la ejecución de una orden es una transacción.

Una transacción cambia la posición de trading por un símbolo determinado; puede abrir, cerrar, incrementar, reducir o invertir la posición. Por tanto, una posición abierta siempre es el resultado de ejecutar una o más transacciones. Puede encontrar más información detallada en el artículo Órdenes, Posiciones, y Transacciones en MetaTrader 5.

Este artículo describe el concepto, términos y procesos que fluyen en el período desde el envío de una solicitud hasta su traslado al historial de trading tras su procesamiento.


Paso de Solicitud del Terminal de Cliente al Servidor de Trading

Para ejecutar una operación de trading, debe enviar una orden al sistema de trading. Siempre se envía una solicitud al servidor de trading cuando se presenta una orden del terminal de cliente. La estructura de una solicitud debe llenarse correctamente, independientemente de cómo lleve a cabo las operaciones de trading - manualmente o usando un programa MQL5.

Para ejecutar una operación de trading manualmente, debe abrir la ventana de diálogo para llenar una solicitud de trading pulsando la tecla F9. Cuando haga trading automáticamente a través de MQL5, las solicitudes se envían usando la función OrderSend(). Puesto que un gran número de solicitudes incorrectas pueden causar una sobrecarga del servidor de trading poco deseable, cada solicitud se debe revisar antes de enviarla usando la función OrderCheck(). El resultado de la revisión de una solicitud se coloca en una variable descrita por la estructura MqlTradeCheckresult.

Importante: La corrección de cada solicitud se revisa en el terminal de cliente antes de enviarla al servidor de trading. Solicitudes deliberadamente incorrectas (para comprar un millón de lotes o con un precio negativo) no pasan del terminal de cliente. Esto se hace para proteger los servidores de una masa de solicitudes incorrectas causadas por un error en un programa MQL5.

Una vez que la solicitud llega al servidor de trading, pasa la revisión primaria, comprobado...

  • ... si tiene liquidez suficiente como para ejecutar la operación de trading;
  • ... si los precios especificados son correctos: precios abiertos, Stop Loss, Take Profit, etc.;
  • ... si el precio específico está presente en el flujo de precios para la ejecución instantánea;
  • ... si los niveles de Stop Loss y el Take Profit están ausentes en el modo de Ejecución de Mercado;
  • ... si el volumen es correcto: volumen mínimo y máximo, paso, volumen máximo de la posición (SYMBOL_VOLUME_MIN, SYMBOL_VOLUME_MAX, SYMBOL_VOLUME_STEP y SYMBOL_VOLUME_LIMIT);
  • ... el estado del símbolo: sesión de cotización o trading, posiblemente de trading por el símbolo, un modo específico de trading (por ejemplo, solo cierre de posiciones), etc.
  • ... el estado de la cuenta de trading: límites diferentes para tipos de cuenta específicos;
  • ... otras revisiones, dependiendo de la operación de trading solicitada.
Una solicitud incorrecta que no pase la revisión primaria en el servidor será rechazada. Siempre se informará al terminal de cliente de los resultados de la revisión de una solicitud, enviando una respuesta. La respuesta del servidor de trading puede tomarse de una variable del tipo MqlTradeResult, que se pasa como segundo parámetro en la función OrderSend() al enviar una solicitud.

Enviar Solicitudes de Trading al Servidor desde el Terminal de Cliente

Si una solicitud pasa la revisión primaria de corrección, se colocará en las solicitudes que aguardan para ser procesadas. Como resultado de procesar una solicitud, se crea una orden (comando para ejecutar una operación de trading) en la base del servidor de trading. No obstante, hay dos tipos de solicitudes que no resultan en la creación de una orden:

  1. una solicitud para cambiar una posición (cambiar su Stop Loss y/o Take Profit);
  2. una solicitud para modificar una orden pendiente (sus niveles de precio y fecha de caducidad).

El terminal de cliente recibe el mensaje de que la solicitud ha sido aceptada y colocada en el subsistema de trading de la plataforma MetaTrader 5. El servidor coloca la solicitud aceptada en la cola de solicitudes para su futuro procesamiento, que puede resultar en...

  • ... la realización de una orden pendiente;
  • ... la ejecución de una orden instantánea por el precio de mercado;
  • ... la modificación de una orden o posición.

La duración de estancia de una solicitud en la cola del servidor tiene un límite de tres minutos. Una vez que el este período se ha excedido, la solicitud se quita de la cola de solicitudes.


Enviar Eventos de Trading del Servidor al Terminal de Cliente

El modelo de evento y las funciones de gestión de eventos se implementan en el lenguaje MQL5. Esto significa que en respuesta a cualquier evento predefinido, la ejecución del entorno MQL5 llama a la función apropiada: el controlador de eventos. Para el procesamiento de eventos de trading está la función predefinida OnTrade(). Dentro de ella se debe colocar el código para trabajar con órdenes, posiciones y transacciones. Esta función se llama solo para Asesores Expertos, no se usará en indicadores y scripts aún cuando usted añada en ellos una función con el mismo nombre y tipo.

Los eventos de trading se generan por el servidor en caso de...

  • ... cambio de órdenes activas,
  • ... cambio de posiciones,
  • ... cambio de transacciones,
  • ... cambio de historial de trading.

Note que una operación puede provocar varios eventos. Por ejemplo, la activación de una orden pendiente lleva al desarrollo de dos eventos:

  1. la aparición de una transacción que se escribe en el historial de trading;
  2. el traslado de la orden pendiente de la lista de órdenes activas a la lista de órdenes del historial (la orden se ha trasladado al historial).

Otro ejemplo de eventos múltiples es la ejecución de varias transacciones en la base de una sola orden, en caso de que el volumen requerido no se pueda obtener de una sola oferta opuesta. El servidor de trading crea y envía los mensajes sobre cada evento al terminal de cliente. Por eso, la función OnTrade() se puede llamar varias veces para un evento aparentemente individual. Este es un ejemplo sencillo del procedimiento de una orden en el subsistema de trading de la plataforma MetaTrader 5.

Ejemplo: mientras una orden pendiente para la compra de 10 lotes de EURUSD aguarda su ejecución, aparecen ofertas contrarias para la venta de 1, 4 y 5 lotes. Esas tres solicitudes juntas suponen el volumen requerido de 10 lotes, de modo que se ejecutan una a una, si la política de ejecución permite la realización de operaciones de trading por partes.

Como resultado de la ejecución de 4 órdenes, el servidor realizará 3 transacciones de 1, 4 y 5 lotes en la base de ofertas contrarias existentes. ¿Cuántos eventos de trading se generarán en este caso? La primera solicitud opuesta para la venta de un lote llevará a la ejecución de la transacción de 1 lote. Este sería el primer evento de trading (transacción de 1 lote). Pero la orden pendiente para comprar 10 lotes también ha cambiado; ahora es la orden para comprar 9 lotes de EURUSD. El cambio de volumen de la orden pendiente sería el segundo evento de trading (cambio de volumen de una orden pendiente).

Generación de Eventos de Trading

Para la segunda transacción de 4 lotes, se generarán los otros dos evento de trading, y se enviará un mensaje sobre cada uno de ellos al terminal de cliente que inició la orden pendiente inicial para la compra de 10 lotes EURUSD.

La última transacción de 5 lotes generará tres eventos de trading:

  1. la transacción de 5 lotes;
  2. el cambio de volumen;
  3. el traslado de la orden al historial de órdenes.

Como resultado de la ejecución de la transacción, el terminal de cliente recibirá 7 eventos de trading uno tras otro (suponiendo que la conexión entre el terminal de cliente y el servidor de trading sea estable y no se pierdan mensajes). Esos mensajes se deben procesar en un Asesor Experto usando la función OnTrade().

Importante: Cada mensaje sobre un evento de trading puede aparecer como resultado de una o más solicitudes. Cada solicitud puede llevar a la generación de varios eventos de trading. No puede depender de la declaración "una solicitud - un evento de trading", puesto que el procesamiento de eventos puede desarrollarse en varias etapas, y cada operación podría cambiar el estado de órdenes, posiciones y el historial de trading.


Procesamiento de Órdenes con el Servidor de Trading

Todas las órdenes que aguardan su ejecución se trasladarán al historial al final, ya sea porque la condición para su ejecución se cumplió, o porque fueron canceladas. Hay muchas variantes de una cancelación de orden:

  • ejecución de una transacción en la base de la orden;
  • rechazo de la orden por un comprador;
  • cancelación de la orden a petición del trader (solicitud manual o automática de un programa MQL5);
  • caducidad de la orden, que se determina bien por el trader al enviar la solicitud, o bien por las condiciones de trading del sistema determinado;
  • falta de liquidez en la cuenta de trading para ejecutar la transacción en el momento en el que se cumplieron las condiciones de su ejecución;
  • la orden se canceló a causa de la política de ejecución (una orden parcialmente ejecutada se cancela).

Independientemente de la razón por la que una orden activa pasa al historial, el mensaje sobre el cambio se envía al terminal de cliente. Los mensajes sobre el evento de trading no van a todos los terminales de cliente, sino a los que están conectados con la cuenta correspondiente.



Importante: El hecho de aceptar una solicitud por el servidor de trading no siempre lleva a la ejecución de la operación solicitada. Significa que la solicitud ha pasado la validación después de que fuera al servidor.

Por eso, la documentación de la función OrderSend() dice:

Valor de devolución

Si la revisión de una solicitud con la función OrderSend() devuelva "true", esto no es un símbolo de ejecución exitosa de una operación de trading. Para una descripción más detallada del resultado de ejecución de funciones, analice los campos de la estructura MqlTradeResult.


Actualización del Historial de Trading en el Terminal de Cliente

Los mensajes sobre los eventos de trading y cambios en el historial de trading vienen a través de canales separados. Al enviar una solicitud de compra usando la función OrderSend(), puede obtener el ticket de la orden, que se crea como resultado de la validación exitosa de la solicitud. Al mismo tiempo, puede que la orden no aparezca en el terminal de cliente, y que fallen los intentos de seleccionarla usando la función OrderSelect()


Todos los mensajes del servidor de trading llegan al terminal de cliente independientemente.

En la figura de arriba puede ver cómo el servidor de trading le comunica el ticket de la orden al programa MQL5, pero el mensaje sobre el evento de trading (la aparición de una nueva orden) no ha llegado todavía. El mensaje sobre el cambio de la lista de órdenes activas no ha llegado todavía.

Puede darse una situación en la que el mensaje sobre la aparición de una nueva orden llegue al programa cuando se realiza una transacción en su base, por tanto la orden ya no está en la lista de órdenes activas y ha pasado al historial. Esta es una situación real, puesto que la velocidad de procesamiento de solicitudes es mucho más rápida que la velocidad actual de entrega de mensajes a través de una red.


Gestión de Eventos de Trading

Todas las operaciones en el servidor y el envío de mensajes sobre eventos de trading se realizan asimétricamente. Solo hay un método seguro para descubrir qué es lo que ha cambiado exactamente en la cuenta de trading. Este método es la memorización del estado e historial de trading, y después la comparación con el nuevo estado.

El algoritmo para rastrear los eventos de trading en los Asesores Expertos es como se muestra a continuación:

  1. declarar los contadores de órdenes, posiciones y transacciones en el panorama global;
  2. determinar la profundidad del historial de trading que se solicitará para la caché del programa MQL5. Cuanto más historial carguemos en la caché, más recursos del terminal y del ordenador consumiremos;
  3. inicializar los contadores de órdenes, posiciones y transacciones en la función OnInit();
  4. determinar el controlador de funciones en las que se pedirá el historial de trading de la caché;
  5. Tras cargar el historial de trading, veremos también que le pasó a la cuenta de trading, comparando el estado memorizado con el actual.

Este es el algoritmo más sencillo, y permite descubrir si el número de posiciones abiertas (órdenes, transacciones) ha cambiado, y cuál fue la dirección del cambio. Si hay cambios, entonces podemos obtener más información detallada. Si el número de órdenes no ha cambiado pero las órdenes mismas han sido modificadas, necesita un enfoque diferente - una variante que no se trata en este artículo.

Los cambios del contador se pueden ver en las funciones OnTrade() y OnTick() de un Asesor Experto. 

Escribamos un programa de ejemplo paso a paso.

1. El contador de órdenes, transacciones y posiciones en el panorama global.

int          orders;            // number of active orders
int          positions;         // number of open positions
int          deals;             // number of deals in the trade history cache
int          history_orders;    // number of orders in the trade history cache
bool         started=false;     // flag of initialization of the counters


2. La profundidad del historial de trading a cargar en la caché se configura en la variable de entrada days ("días", que carga el historial de trading por el número de días especificado en esta variable).

input    int days=7;            // depth of the trade history in days

//--- set the limit of the trade history on the global scope
datetime     start;             // start date of the trade history in cache
datetime     end;               // end date of the trade history in cache


3. Inicialización de los contadores y los límites del historial de trading. Exponga la inicialización de los contadores con la función InitCounters() para una mejor legibilidad del código:

int OnInit()
  {
//---
   end=TimeCurrent();
   start=end-days*PeriodSeconds(PERIOD_D1);
   PrintFormat("Limits of the trade history to be loaded: start - %s, end - %s",
               TimeToString(start),TimeToString(end));
   InitCounters();
//---
   return(0);
  }

La función InitCounters() trata de cargar el historial de trading en la caché, y en caso de éxito, inicializa todos los contadores. Asimismo, si el historial se carga con éxito, el valor de la variable global "started" será "true", lo que indica que los contadores se han inicializado correctamente.

//+------------------------------------------------------------------+
//|  initialization of the counters of positions, orders and deals   |
//+------------------------------------------------------------------+
void InitCounters()
  {
   ResetLastError();
//--- load history
   bool selected=HistorySelect(start,end);
   if(!selected)
     {
      PrintFormat("%s. Failed to load the history from %s to %s to the cache. Error code: %d",
                  __FUNCTION__,TimeToString(start),TimeToString(end),GetLastError());
      return;
     }
//--- get current values
   orders=OrdersTotal();
   positions=PositionsTotal();
   deals=HistoryDealsTotal();
   history_orders=HistoryOrdersTotal();
   started=true;
   Print("The counters of orders, positions and deals are successfully initialized");
  }


4. La revisión de los cambios en la cuenta de trading se ejecuta en los controladores OnTick() y OnTrade(). La variable "started" se revisa primero: si su valor es "true", se llama a la función SimpleTradeProcessor(). De lo contrario, se llama a la función de inicialización de los contadores InitCounters().

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   if(started) SimpleTradeProcessor();
   else InitCounters();
  }
//+------------------------------------------------------------------+
//| called when the Trade event occurs                               |
//+------------------------------------------------------------------+
void OnTrade()
  {
   if(started) SimpleTradeProcessor();
   else InitCounters();
  }

5. La función SimpleTradeProcessor() comprueba si el número de órdenes, transacciones y posiciones ha cambiado. Tras realizar todas las revisiones, llamamos la función CheckStartDateInTradeHistory(), que mueve el valor "start" más cerca al momento presente si es necesario.

//+------------------------------------------------------------------+
//| simple example of processing changes in trade and history        |
//+------------------------------------------------------------------+
void SimpleTradeProcessor()
  {
   end=TimeCurrent();
   ResetLastError();
//--- load history
   bool selected=HistorySelect(start,end);
   if(!selected)
     {
      PrintFormat("%s. Failed to load the history from %s to %s to the cache. Error code: %d",
                  __FUNCTION__,TimeToString(start),TimeToString(end),GetLastError());
      return;
     }

//--- get current values
   int curr_orders=OrdersTotal();
   int curr_positions=PositionsTotal();
   int curr_deals=HistoryDealsTotal();
   int curr_history_orders=HistoryOrdersTotal();

//--- check whether the number of active orders has been changed
   if(curr_orders!=orders)
     {
      //--- number of active orders is changed
      PrintFormat("Number of orders has been changed. Previous number is %d, current number is %d",
                  orders,curr_orders);
     /*
       other actions connected with changes of orders
     */
      //--- update value
      orders=curr_orders;
     }

//--- change in the number of open positions
   if(curr_positions!=positions)
     {
      //--- number of open positions has been changed
      PrintFormat("Number of positions has been changed. Previous number is %d, current number is %d",
                  positions,curr_positions);
      /*
      other actions connected with changes of positions
      */
      //--- update value
      positions=curr_positions;
     }

//--- change in the number of deals in the trade history cache
   if(curr_deals!=deals)
     {
      //--- number of deals in the trade history cache has been changed
      PrintFormat("Number of deals has been changed. Previous number is %d, current number is %d",
                  deals,curr_deals);
      /*
       other actions connected with change of the number of deals
       */
      //--- update value
      deals=curr_deals;
     }

//--- change in the number of history orders in the trade history cache
   if(curr_history_orders!=history_orders)
     {
      //--- the number of history orders in the trade history cache has been changed
      PrintFormat("Number of orders in the history has been changed. Previous number is %d, current number is %d",
                  history_orders,curr_history_orders);
     /*
       other actions connected with change of the number of order in the trade history cache
      */
     //--- update value
     history_orders=curr_history_orders;
     }
//--- check whether it is necessary to change the limits of trade history to be requested in cache
   CheckStartDateInTradeHistory();
  }

La función CheckStartDateInTradeHistory() calcula la fecha de inicio de la solicitud del historial de trading para el momento actual (curr_start) y la compara con la variable "start". Si la diferencia entre ellas es mayor de 1 día, entonces "start" se corrige y los contadores de órdenes del historial y transacciones se actualizan.

//+------------------------------------------------------------------+
//|  Changing start date for the request of trade history            |
//+------------------------------------------------------------------+
void CheckStartDateInTradeHistory()
  {
//--- initial interval, as if we started working right now
   datetime curr_start=TimeCurrent()-days*PeriodSeconds(PERIOD_D1);
//--- make sure that the start limit of the trade history period has not gone 
//--- more than 1 day over intended date
   if(curr_start-start>PeriodSeconds(PERIOD_D1))
     {
      //--- we need to correct the date of start of history loaded in the cache
      start=curr_start;
      PrintFormat("New start limit of the trade history to be loaded: start => %s",
                  TimeToString(start));

      //--- now load the trade history for the corrected interval again
      HistorySelect(start,end);

      //--- correct the counters of deals and orders in the history for further comparison
      history_orders=HistoryOrdersTotal();
      deals=HistoryDealsTotal();
     }
  }

El código completo del Asesor Experto DemoTradeEventProcessing.mq5 está adjunto con este artículo.


Conclusión

Todas las operaciones en la plataforma de trading online Meta Trader 5 se ejecutan de forma asíncrona, y los mensajes sobre todos los cambios en una cuenta de trading se envían de forma independiente unos de otros. Por tanto, no tiene sentido tratar de rastrear eventos independientes basándonos en la regla "una solicitud - un evento de trading". Si necesita determinar de forma precisa qué ha cambiado exactamente cuando ocurre un evento de trading, debe analizar todas sus transacciones, posiciones y órdenes en cada llamada del controlador OnTrade(), comparando su estado actual con el anterior.

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

Archivos adjuntos |
Fundamentos de la Simulación en MetaTrader 5 Fundamentos de la Simulación en MetaTrader 5
¿Qué diferencias hay entre los tres modos de simulación en MetaTrader 5, y qué deberíamos buscar particularmente? ¿Como tiene lugar la simulación de un EA haciendo trading en múltiples instrumentos al mismo tiempo? ¿Cuándo y cómo se calculan los valore del indicador durante la simulación, y cómo se gestionan los eventos? ¿Cómo se sincronizan las barras de diferentes instrumentos durante la simulación en un modo de "Solo precios de Apertura"? Este artículo dará respuestas a estas y otras cuestiones.
Órdenes, Posiciones y Transacciones en MetaTrader 5 Órdenes, Posiciones y Transacciones en MetaTrader 5
No se puede crear un robot de trading robusto sin un entendimiento de los mecanismos del sistema de trading del del MetaTrader 5. El terminal de cliente recibe la información sobre las posiciones, órdenes y transacciones del servidor de trading. Para gestionar esta propiedad de datos usando el MQL5 es necesario tener un buen entendimiento de la interacción entre el programa MQL5 y el terminal de cliente.
Trading social en las plataformas comerciales MetaTrader 4 y MetaTrader 5 Trading social en las plataformas comerciales MetaTrader 4 y MetaTrader 5
¿Qué es el trading social? Es el trabajo conjunto y mútuamente beneficioso realizado entre traders e inversores: los traders de éxito ceden su tráfico comercial para la monitorización, y los inversores potenciales, de esta forma, pueden hacer un seguimiento de sus éxitos y copiar las operaciones del trader que más les guste.
Sistemas de Trading Adaptables y su Uso en el Terminal de Cliente MetaTrader 5 Sistemas de Trading Adaptables y su Uso en el Terminal de Cliente MetaTrader 5
Este artículo sugiere una variante de un sistema adaptable que consta de varias estrategias, cada una de las cuales realiza sus propias operaciones de trading "virtuales". El trading real se realiza de acuerdo con las señales de la estrategia más rentable en cada momento. Gracias al uso del enfoque orientado al objeto, las clases para trabajar con datos y las clases de comercio de la Biblioteca estándar, la arquitectura del sistema parece sencilla y manejable; ahora, podrá crear y analizar fácilmente los sistemas adaptables que incluyen cientos de estrategias de comercio.