Obtener la lista de posiciones

En muchos ejemplos de Asesores Expertos hemos utilizado ya las funciones de la API de MQL5 diseñadas para analizar las posiciones de trading abiertas. En esta sección se presenta su descripción formal.

Es importante tener en cuenta que las funciones de este grupo no permiten crear, modificar o eliminar posiciones. Como hemos visto antes, todas estas acciones se realizan indirectamente mediante el envío de órdenes. Si se ejecutan con éxito, se realizan transacciones, como resultado de las cuales se forman posiciones.

Otra característica es que las funciones sólo son aplicables a las posiciones en línea. Para restablecer el historial de posiciones, es necesario analizar el historial de operaciones.

La función PositionsTotal permite averiguar el número total de posiciones abiertas en la cuenta (para todos los instrumentos financieros).

int PositionsTotal()

Con la contabilidad de compensación de posiciones (ACCOUNT_MARGIN_MODE_RETAIL_NETTING y ACCOUNT_MARGIN_MODE_EXCHANGE) sólo puede haber una posición para cada símbolo en cualquier momento. Esta posición puede ser el resultado de una o varias transacciones.

Con la representación independiente de las posiciones (ACCOUNT_MARGIN_MODE_RETAIL_HEDGING) se pueden abrir varias posiciones simultáneamente para cada símbolo, incluidas las multidireccionales. Cada operación de entrada en el mercado crea una posición independiente, por lo que la ejecución parcial paso a paso de una orden puede generar varias posiciones.

La función PositionGetSymbol devuelve el símbolo de una posición por su número.

string PositionGetSymbol(int index)

El índice debe estar comprendido entre 0 y N-1, donde N es el valor recibido por la llamada previa de PositionsTotal. El orden de las posiciones no está regulado.

Si no se encuentra la posición, se devolverá una cadena vacía y el código de error estará disponible en _LastError.

Se han ofrecido ejemplos de uso de estas dos funciones en varios Asesores Expertos de prueba (TrailingStop.mq5, TradeCloseBy.mq5, etc.) en funciones con nombres GetMyPosition/GetMyPositions.

Una posición abierta se caracteriza por un ticket único que es el número que la distingue de otras posiciones, pero puede cambiar durante su vida en algunos casos, como una inversión de posición en el modo de compensación por una operación, o como resultado de operaciones de servicio en el servidor (reapertura para cobro de swap, compensación).

Para obtener un ticket de posición por su número, utilizamos la función PositionGetTicket.

ulong PositionGetTicket(int index)

Además, la función resalta una posición en el entorno de trading del terminal, lo que permite leer sus propiedades mediante un grupo de funciones PositionGetespeciales. En otras palabras: por analogía con las órdenes, el terminal mantiene una caché interna para cada programa MQL a fin de almacenar las propiedades de una posición. Para resaltar una posición, además de PositionGetTicket, existen dos funciones: PositionSelect y PositionSelectByTicket, que analizaremos a continuación.

En caso de error, la función PositionGetTicket devolverá 0.

El ticket no debe confundirse con el identificador que se asigna a cada posición y que nunca cambia. Son los identificadores que se utilizan para vincular posiciones con órdenes y operaciones. Hablaremos de ello un poco más adelante.
 
Los tickets son necesarios para satisfacer las solicitudes que implican posiciones: los tickets se especifican en los campos position y position_by de la estructura MqlTradeRequest. Además, al guardar el ticket en una variable, el programa puede seleccionar posteriormente una posición concreta mediante la función PositionSelectByTicket (véase más adelante) y trabajar con ella sin recurrir a la enumeración repetida de posiciones en el bucle.

Cuando se invierte una posición en una cuenta de compensación, POSITION_TICKET se cambia por el ticket de la orden que inició esta operación. Sin embargo, una posición de este tipo puede rastrearse utilizando un ID. La inversión de posiciones no se admite en el modo de cobertura.

bool PositionSelect(const string symbol)

La función selecciona una posición abierta por el nombre del instrumento financiero.

Con la representación independiente de las posiciones (ACCOUNT_MARGIN_MODE_RETAIL_HEDGING) puede haber varias posiciones abiertas para cada símbolo al mismo tiempo. En este caso, PositionSelect seleccionará la posición con el ticket más pequeño.

El resultado devuelto indica una ejecución correcta (true) o incorrecta (false) de la función.

El hecho de que las propiedades de la posición seleccionada se almacenen en caché significa que la posición en sí puede dejar de existir, o puede cambiar si el programa lee sus propiedades al cabo de algún tiempo. Se recomienda llamar a la función PositionSelect justo antes de acceder a los datos.

bool PositionSelectByTicket(ulong ticket)

La función selecciona una posición abierta para seguir trabajando en el ticket especificado.

Veremos ejemplos de uso de funciones más adelante, cuando estudiemos las propiedades y funciones PositionGet relacionadas.

Al construir algoritmos que utilicen las funciones PositionsTotal, OrdersTotal y similares, deben tenerse en cuenta los principios asíncronos del funcionamiento de los terminales. Ya hemos tocado este tema al escribir las clases MqlTradeSync.mqh e implementar la espera de los resultados de ejecución de las solicitudes de operaciones. Sin embargo, esta espera no siempre es posible en el lado del cliente. En concreto, si colocamos una orden pendiente, su transformación en una orden de mercado y su posterior ejecución tendrán lugar en el servidor. En este momento, la orden puede dejar de figurar entre las activas (OrdersTotal devolverá 0), pero la posición aún no se muestra (PositionsTotal también es igual a 0). Por lo tanto, un programa MQL que tiene una condición para colocar una orden en ausencia de una posición puede iniciar erróneamente una nueva orden, como resultado de lo cual la posición al final se duplicará.

Para resolver este problema, un programa MQL debe analizar el entorno de trading más profundamente que simplemente comprobar el número de órdenes y posiciones a la vez. Por ejemplo, puede mantener una instantánea del último estado correcto del entorno de trading y no permitir que desaparezca ninguna entidad sin algún tipo de confirmación. Sólo entonces podrá formarse una nueva conversión. Así, una orden sólo puede borrarse junto con un cambio de posición (creación, cierre) o trasladarse al historial con un estado de cancelación. Una de las posibles soluciones se propone en forma de clase TradeGuard en el archivo TradeGuard.mqh. El libro también incluye el script de demostración TradeGuardExample.mq5 que puede estudiar de forma adicional.