- Evento principal de Asesores Expertos: OnTick
- Principios y conceptos básicos: orden, transacción y posición
- Tipos de operaciones de trading
- Tipos de órdenes
- Modos de ejecución de órdenes por precio y volumen
- Fechas de vencimiento de órdenes pendientes
- Cálculo del margen para una orden futura: OrderCalcMargin
- Estimación del beneficio de una operación de trading: OrderCalcProfit
- Estructura MqlTradeRequest
- Estructura MqlTradeCheckResult
- Solicitar validación: OrderCheck
- Solicitar resultado del envío: estructura MqlTradeResult
- Enviar una solicitud de trading: OrderSend y OrderSendAsync
- Operaciones de compraventa
- Modificar los niveles de Stop Loss y/o Take Profit de una posición
- Trailing stop
- Cierre de una posición: total y parcial
- Cierre de posiciones opuestas: total y parcial
- Colocar una orden pendiente
- Modificar una orden pendiente
- Borrar una orden pendiente
- Obtener una lista de órdenes activas
- Propiedades de una orden (activas e históricas)
- Funciones para leer las propiedades de órdenes activas
- Seleccionar órdenes por propiedades
- Obtener la lista de posiciones
- Propiedades de posiciones
- Funciones de lectura de propiedades de posición
- Propiedades de transacción
- Seleccionar órdenes y transacciones del historial
- Funciones para leer propiedades de órdenes del historial
- Funciones para leer propiedades de transacciones del historial
- Tipos de transacciones de trading
- Evento OnTradeTransaction
- Peticiones síncronas y asíncronas
- Evento OnTrade
- Seguimiento de los cambios en el entorno de trading
- Crear Asesores Expertos multisímbolo
- Limitaciones y ventajas de los Asesores Expertos
- Crear Asesores Expertos en el Asistente MQL
Funciones de lectura de propiedades de posición
Un programa MQL puede obtener propiedades de posición utilizando varias funciones PositionGet dependiendo del tipo de propiedades. En todas las funciones, la propiedad específica que se solicita se define en el primer parámetro, que toma el ID de una de las enumeraciones ENUM_POSITION_PROPERTY comentadas en la sección anterior.
Para cada tipo de propiedad, existe una forma corta y una forma larga de la función: la primera devuelve directamente el valor de la propiedad, y la segunda lo escribe en el segundo parámetro, pasado por referencia.
Las propiedades de enteros y las propiedades de tipos compatibles (datetime, enumeraciones) pueden obtenerse mediante la función PositionGetInteger.
long PositionGetInteger(ENUM_POSITION_PROPERTY_INTEGER property)
bool PositionGetInteger(ENUM_POSITION_PROPERTY_INTEGER property, long &value)
Si falla, la función devuelve 0 o false.
La función PositionGetDouble se utiliza para obtener propiedades reales.
double PositionGetDouble(ENUM_POSITION_PROPERTY_DOUBLE property)
bool PositionGetDouble(ENUM_POSITION_PROPERTY_DOUBLE property, double &value)
Por último, la función PositionGetString devuelve las propiedades de las cadenas.
string PositionGetString(ENUM_POSITION_PROPERTY_STRING property)
bool PositionGetString(ENUM_POSITION_PROPERTY_STRING property, string &value)
En caso de fallo, la primera forma de la función devuelve una cadena vacía.
Para leer las propiedades de posición, tenemos ya lista una interfaz abstracta MonitorInterface (TradeBaseMonitor.mqh) que utilizamos para escribir un monitor de órdenes. Ahora será fácil implantar un monitor similar para las posiciones. El resultado se adjunta en el archivo PositionMonitor.mqh.
La clase PositionMonitorInterface se hereda de MonitorInterface con asignación a los tipos de plantilla I, D y S de las enumeraciones consideradas ENUM_POSITION_PROPERTY, y anula un par de métodos de stringify teniendo en cuenta las particularidades de las propiedades de posición.
class PositionMonitorInterface:
|
La clase específica del monitor, preparada para ver posiciones, es la siguiente en la cadena de herencia y se basa en las funciones de PositionGet. La selección de una posición por ticket se realiza en el constructor.
class PositionMonitor: public PositionMonitorInterface
|
Un sencillo script le permitirá registrar todas las características de la primera posición (si hay al menos una disponible).
void OnStart()
|
En el registro, deberíamos obtener algo como esto:
MonitorInterface<ENUM_POSITION_PROPERTY_INTEGER, »
|
Si no hay posiciones abiertas en ese momento, veremos un mensaje de error.
Error: PositionSelectByTicket(0) failed: TRADE_POSITION_NOT_FOUND |
No obstante, el monitor es útil no sólo y no tanto por la salida de las propiedades en el registro. Basándonos en PositionMonitor, creamos una clase para seleccionar posiciones por condiciones, similar a lo que hicimos para las órdenes (OrderFilter). El objetivo final es mejorar nuestro Asesor Experto de cuadrícula.
Gracias a la programación orientada a objetos (POO), la creación de una nueva clase de filtro no requiere prácticamente ningún esfuerzo. A continuación se muestra el código fuente completo (archivo PositionFilter.mqh).
class PositionFilter: public TradeFilter<PositionMonitor,
|
Ahora podemos escribir un script de este tipo para recibir beneficios específicos en posiciones con el número mágico dado, por ejemplo.
input ulong Magic;
|
En este caso hemos tenido que llamar al método select dos veces, porque los tipos de propiedades que nos interesan son diferentes: beneficio real y lote, pero el nombre de cadena del instrumento. En una de las secciones al principio del capítulo, cuando estábamos desarrollando la clase de filtro para símbolos, describimos el concepto de tuplas. En MQL5 podemos implementarlo como plantillas de estructura con campos de tipos arbitrarios. Estas tuplas serían muy útiles para finalizar la jerarquía de clases de filtros, ya que entonces sería posible describir el método select que rellena un array de tuplas con campos de cualquier tipo.
Las tuplas se describen en el archivo Tuples.mqh. Todas sus estructuras tienen un nombre TupleN<T1,...>, donde N es un número de 2 a 8, y corresponde al número de parámetros de la plantilla (tipos Ti). Por ejemplo, Tuple2:
template<typename T1,typename T2>
|
En la clase TradeFilter (TradeFilter.mqh) vamos a añadir una versión de la función select con tuplas.
template<typename T,typename I,typename D,typename S>
|
Un array de tuplas puede ordenarse opcionalmente por el primer campo _1, por lo que puede estudiar adicionalmente el método de ayuda sortTuple.
Con las tuplas puede consultar un objeto de filtro para propiedades de tres tipos diferentes en una sola llamada a select.
A continuación se muestran posiciones con algún número de Magic, ordenadas por beneficio; para cada una se obtiene adicionalmente un símbolo y un ticket.
input ulong Magic;
|
Por supuesto, los tipos de parámetros de la descripción del array de tuplas (en este caso, Tuple3<double,string,ulong>) deben coincidir con los tipos de enumeración de propiedades solicitados (POSITION_PROFIT, POSITION_SYMBOL, POSITION_TICKET).
Ahora podemos simplificar ligeramente el Asesor Experto de cuadrícula (lo que significa no sólo un código más corto, sino también más comprensible). La nueva versión se llama PendingOrderGrid2.mq5. Los cambios afectarán a todas las funciones relacionadas con la gestión de posiciones.
La función GetMyPositions rellena el array de tuplas types4tickets pasadas por referencia. Se supone que en cada tupla Tuple2 se almacena el tipo y el ticket de la posición. En este caso concreto, podríamos arreglárnoslas simplemente con un array bidimensional ulong en lugar de tuplas porque ambas propiedades son del mismo tipo base. Sin embargo, utilizamos tuplas para demostrar cómo trabajar con ellas en el código de llamada.
#include <MQL5Book/Tuples.mqh>
|
Observe que el último y tercer parámetro del método select es igual a true, que ordena el array por el primer campo, es decir, el tipo de posiciones. Así, tendremos compras al principio y ventas al final. Esto será necesario para el cierre del contador.
La reencarnación del método CompactPositions es la siguiente:
uint CompactPositions(const bool cleanup = false)
|
La función CloseAllPositions es prácticamente la misma:
uint CloseAllPositions(const Tuple2<ulong,ulong> &types4tickets[],
|
Puede comparar el trabajo de los Asesores Expertos PendingOrderGrid1.mq5 y PendingOrderGrid2.mq5 en el probador.
Los informes serán ligeramente diferentes, porque si hay varias posiciones, se cierran en combinaciones opuestas, debido a lo cual el cierre de otras posiciones no emparejadas se produce con respecto a sus diferenciales individuales.