Kit de herramientas de negociación MQL5 (Parte 8): Cómo implementar y utilizar la librería History Manager en sus proyectos
Introducción
En artículos anteriores le he guiado a través del desarrollo de una librería de gestión del historial robusta y completa, diseñada para optimizar la forma en que interactúa con los historiales comerciales en MetaTrader 5. Esta potente librería le permite escanear, recuperar, ordenar, clasificar y filtrar sin esfuerzo todo tipo de historiales comerciales, ya sean posiciones cerradas, órdenes pendientes o historiales de operaciones, directamente desde su cuenta MetaTrader 5. Partiendo de esa base, este artículo da el paso definitivo mostrándole cómo integrar de manera eficiente la librería History Manager en sus proyectos MQL5.
Proporcionaré un desglose detallado de las funciones disponibles en la biblioteca EX5, con explicaciones claras y ejemplos prácticos. Estos casos de uso reales no solo te ayudarán a comprender cómo funciona cada función, sino que también te mostrarán cómo aplicarlas en tus estrategias de trading o herramientas de análisis. Tanto si eres un principiante que desea mejorar sus habilidades de programación como si eres un desarrollador experimentado que busca optimizar su flujo de trabajo, esta guía te proporcionará los conocimientos y las herramientas necesarios para aprovechar todo el potencial de la librería History Manager. Al final de este artículo, podrás implementar esta versátil librería con confianza y empezar a aprovechar sus capacidades para gestionar los historiales comerciales de forma más eficiente que nunca.
Ventajas de utilizar History Manager en MQL5
A continuación se enumeran las principales ventajas de integrar History Manager en sus proyectos MQL5:
- Recuperación de datos sin esfuerzo: La librería proporciona funciones intuitivas para recuperar datos del historial de operaciones, como transacciones, órdenes, posiciones y órdenes pendientes, con un código mínimo. Esto elimina la necesidad de una codificación compleja y repetitiva.
- Interfaz unificada: Se puede acceder a todos los datos del historial comercial a través de una interfaz única y coherente, lo que facilita la gestión y el análisis de diferentes tipos de actividades comerciales.
- Funciones que ahorran tiempo: Con llamadas a funciones de una sola línea, puede acceder rápidamente a datos comerciales críticos, lo que reduce el tiempo de desarrollo y le permite centrarse en la implementación de la estrategia.
- Procesamiento automatizado de datos: La biblioteca automatiza la recuperación, clasificación y filtrado de historiales comerciales, lo que agiliza los flujos de trabajo y mejora la eficiencia general.
- Gestión de datos sin errores: La librería garantiza la recuperación precisa de los datos históricos de operaciones, minimizando el riesgo de errores que pueden producirse con la codificación manual.
- Cobertura completa de datos: Desde posiciones cerradas hasta órdenes pendientes, la librería proporciona acceso a todo tipo de historiales de operaciones, lo que garantiza que no se pase por alto ningún dato.
- Información detallada: Funciones como GetLastClosedPositionData(), GetLastFilledPendingOrderData(), y GetLastClosedProfitablePositionData(), entre muchas otras, proporcionan detalles granulares sobre las operaciones, lo que permite un análisis más profundo y una mejor toma de decisiones.
- Filtros personalizables: Puede filtrar los historiales de operaciones por símbolo, número mágico o periodo temporal para realizar análisis específicos adaptados a sus necesidades concretas.
- Fácil implementación: La librería está diseñada para integrarse perfectamente en los proyectos MQL5 existentes, requiriendo una configuración mínima.
- Escalabilidad: Tanto si está trabajando en un pequeño script como en un sistema de negociación a gran escala, el gestor de historiales se adapta sin esfuerzo a sus necesidades.
- Adaptable a sus necesidades: El diseño modular de la librería le permite utilizar solo las funciones que necesita, lo que la hace muy adaptable a diversos estilos y estrategias de negociación.
- Funcionalidad ampliable: Los desarrolladores pueden basarse en las funciones existentes de la librería para crear soluciones personalizadas que se adapten a requisitos comerciales únicos.
- Soluciones predefinidas: Al aprovechar las funciones predefinidas de la librería, puede reducir significativamente el tiempo y el coste asociados al desarrollo de herramientas personalizadas de gestión del historial comercial.
- Abierto a todos los niveles de conocimiento: Tanto si eres principiante como desarrollador experimentado, el diseño sencillo de la librería la hace accesible a usuarios de todos los niveles.
- Decisiones basadas en datos: El acceso a historiales comerciales completos le permite tomar decisiones informadas a la hora de desarrollar o perfeccionar estrategias comerciales.
- Pruebas retrospectivas históricas: Utilice la librería para recuperar datos históricos de operaciones para realizar pruebas retrospectivas, lo que garantiza que sus estrategias sean sólidas y fiables.
- Código limpio y legible: Las funciones de la librería están diseñadas para producir código limpio y legible, lo que facilita el mantenimiento y la actualización de sus proyectos.
Importación y configuración de la librería History Manager
Antes de poder empezar a utilizar las funciones de la librería History Manager, debe importarla y configurarla correctamente en su proyecto MQL5. Esta sección le guiará paso a paso por el proceso, garantizando una configuración fluida y sin complicaciones.
Para utilizar el archivo de librería HistoryManager.ex5 en sus proyectos MQL5, es necesario descargarlo y colocarlo en el directorio correcto dentro de la carpeta de instalación de MetaTrader 5. Inicie MetaEditor desde su terminal MetaTrader 5 navegando a Herramientas > Editor del lenguaje MetaQuotes o pulsando F4 y siga los pasos que se indican a continuación:
- Paso 1. Cree los directorios necesarios:
Dentro de la carpeta «Libraries» ubicada en el directorio raíz MQL5, cree los siguientes subdirectorios si aún no existen: «\Wanateki\Toolkit\HistoryManager».
The full path in your MQL5 installation folder should look like this: "MQL5\Libraries\Wanateki\Toolkit\HistoryManager".
- Paso 2. Descargar el archivo binario HistoryManager.ex5:
Desplácese hasta la parte inferior o el final de este artículo, localice el archivo adjunto HistoryManager.ex5 y descárguelo. Coloque el archivo en la carpeta HistoryManager que creó en el Paso 1.
La estructura del directorio de la carpeta Libraries debería ser ahora similar a la de la imagen siguiente:

- Paso 3. Crear el archivo de librería de encabezados:
1. En MetaEditor, inicie el Asistente MQL (MQL Wizard) utilizando el botón del elemento de menú Nuevo.
2. Seleccione la opción Incluir (*.mqh) y haga clic en Siguiente.

3. En la ventana Propiedades generales del archivo de inclusión, localice el cuadro de entrada Nombre. Borra todo el texto e introduce la siguiente ruta para especificar el directorio y el nombre del archivo de inclusión: Include\Wanateki\Toolkit\HistoryManager\HistoryManager.mqh

4. Pulse el botón Finalizar para generar el archivo de encabezado de la librería.
Codificación del archivo de encabezado del gestor de historial (HistoryManager.mqh)
Ahora que hemos creado correctamente un archivo include en blanco para el encabezado de la librería HistoryManager.mqh, el siguiente paso es rellenarlo con los componentes necesarios que definirán su funcionalidad. Esto implica añadir estructuras de datos para gestionar y almacenar información de forma eficiente, incorporar directivas macro para simplificar tareas repetitivas y mejorar la legibilidad del código, e importar y declarar las funciones de librería que servirán como interfaces principales para interactuar con la funcionalidad HistoryManager.ex5.
Bajo el enlace #property, comenzaremos declarando las estructuras de datos DealData, OrderData, PositionData y PendingOrderData en el ámbito global. Estas estructuras se encargarán de almacenar diversas propiedades del historial comercial y serán accesibles desde cualquier parte de nuestro código base.
struct DealData { // Add all the DealData members here } struct OrderData { // Add all the OrderData members here } struct PositionData { // Add all the PositionData members here } struct PendingOrderData { // Add all the PendingOrderData members here }
A continuación, definiremos varias constantes o macros para representar períodos de tiempo clave en segundos. Estos incluyen NOW, ONE_DAY, ONE_WEEK, ONE_MONTH, ONE_YEAR, EPOCH, TODAY, THIS_WEEK, THIS_MONTH, y THIS_YEAR , lo que simplificará los cálculos relacionados con el tiempo y mejorará la legibilidad del código.
#define NOW datetime(TimeCurrent()) #define ONE_DAY datetime(TimeCurrent() - PeriodSeconds(PERIOD_D1)) #define ONE_WEEK datetime(TimeCurrent() - PeriodSeconds(PERIOD_W1)) #define ONE_MONTH datetime(TimeCurrent() - PeriodSeconds(PERIOD_MN1)) #define ONE_YEAR datetime(TimeCurrent() - (PeriodSeconds(PERIOD_MN1) * 12)) #define EPOCH 0 // 1st Jan 1970 //-- #define TODAY 12 #define THIS_WEEK 13 #define THIS_MONTH 14 #define THIS_YEAR 15
También crearemos la macro de cadena ALL_SYMBOLS para almacenar una cadena vacía. Esto servirá como señal para indicar que queremos procesar el historial especificado para todos los símbolos. Además, definiremos las macros enteras ALL_POSITIONS, ALL_ORDERS y ALL_DEALS . Esto nos permitirá especificar los tipos de historial de órdenes, operaciones y posiciones que deseamos procesar.
#define ALL_SYMBOLS "" #define ALL_POSITIONS 1110 #define ALL_ORDERS 1111 #define ALL_DEALS 1112
Ahora que hemos creado todas las estructuras de datos necesarias y definido las directivas del preprocesador o macros esenciales, es el momento de importar la biblioteca HistoryManager.ex5. Para ello, utilizaremos la directiva #import seguida de la ruta de la carpeta donde se encuentra la librería EX5.
#import "Wanateki/Toolkit/HistoryManager/HistoryManager.ex5"
Después de la directiva #import, añadiremos las declaraciones de funciones de la librería y concluiremos insertando la directiva de cierre #import como última línea de nuestro archivo de encabezado HistoryManager.mqh.
#import "Wanateki/Toolkit/HistoryManager/HistoryManager.ex5" //-- void PrintDealsHistory(datetime fromDateTime, datetime toDateTime); void PrintOrdersHistory(datetime fromDateTime, datetime toDateTime); void PrintPositionsHistory(datetime fromDateTime, datetime toDateTime); void PrintPendingOrdersHistory(datetime fromDateTime, datetime toDateTime); //-- bool GetDealsData(DealData &dealsData[], datetime fromDateTime, datetime toDateTime, string symbol, ulong magic); bool GetOrdersData(OrderData &ordersData[], datetime fromDateTime, datetime toDateTime, string symbol, ulong magic); bool GetPositionsData(PositionData &positionsData[], datetime fromDateTime, datetime toDateTime, string symbol, ulong magic); bool GetPendingOrdersData(PendingOrderData &pendingOrdersData[], datetime fromDateTime, datetime toDateTime, string symbol, ulong magic); //-- // Add all the other function declarations here... #import
A continuación se muestran los segmentos de código esenciales que forman el archivo de inclusión HistoryManager.mqh. Este archivo de encabezado proporciona todos los recursos necesarios para importar e integrar la librería History Manager EX5 en sus proyectos MQL5. Al incluirlo al principio de tu archivo fuente, obtienes acceso a todas las estructuras de datos y funciones de la librería, lo que las hace fácilmente disponibles para su uso inmediato. El archivo fuente completo HistoryManager.mqh también se adjunta al final de este artículo para que lo descargues.
struct DealData { ulong ticket; ulong magic; ENUM_DEAL_ENTRY entry; ENUM_DEAL_TYPE type; ENUM_DEAL_REASON reason; ulong positionId; ulong order; string symbol; string comment; double volume; double price; datetime time; double tpPrice; double slPrice; double commission; double swap; double profit; }; //-- struct OrderData { datetime timeSetup; datetime timeDone; datetime expirationTime; ulong ticket; ulong magic; ENUM_ORDER_REASON reason; ENUM_ORDER_TYPE type; ENUM_ORDER_TYPE_FILLING typeFilling; ENUM_ORDER_STATE state; ENUM_ORDER_TYPE_TIME typeTime; ulong positionId; ulong positionById; string symbol; string comment; double volumeInitial; double priceOpen; double priceStopLimit; double tpPrice; double slPrice; }; //-- struct PositionData { ENUM_POSITION_TYPE type; ulong ticket; ENUM_ORDER_TYPE initiatingOrderType; ulong positionId; bool initiatedByPendingOrder; ulong openingOrderTicket; ulong openingDealTicket; ulong closingDealTicket; string symbol; double volume; double openPrice; double closePrice; datetime openTime; datetime closeTime; long duration; double commission; double swap; double profit; double tpPrice; double slPrice; int tpPips; int slPips; int pipProfit; double netProfit; ulong magic; string comment; }; //-- struct PendingOrderData { string symbol; ENUM_ORDER_TYPE type; ENUM_ORDER_STATE state; double priceOpen; double tpPrice; double slPrice; int tpPips; int slPips; ulong positionId; ulong ticket; datetime timeSetup; datetime expirationTime; datetime timeDone; ENUM_ORDER_TYPE_TIME typeTime; ulong magic; ENUM_ORDER_REASON reason; ENUM_ORDER_TYPE_FILLING typeFilling; string comment; double volumeInitial; double priceStopLimit; }; //-- #define NOW datetime(TimeCurrent()) #define ONE_DAY datetime(TimeCurrent() - PeriodSeconds(PERIOD_D1)) #define ONE_WEEK datetime(TimeCurrent() - PeriodSeconds(PERIOD_W1)) #define ONE_MONTH datetime(TimeCurrent() - PeriodSeconds(PERIOD_MN1)) #define ONE_YEAR datetime(TimeCurrent() - (PeriodSeconds(PERIOD_MN1) * 12)) #define EPOCH 0 // 1st Jan 1970 //-- #define TODAY 12 #define THIS_WEEK 13 #define THIS_MONTH 14 #define THIS_YEAR 15 //-- #define ALL_SYMBOLS "" #define ALL_POSITIONS 1110 #define ALL_ORDERS 1111 #define ALL_DEALS 1112 //-- #import "Wanateki/Toolkit/HistoryManager/HistoryManager.ex5" //-- void PrintDealsHistory(datetime fromDateTime, datetime toDateTime); void PrintOrdersHistory(datetime fromDateTime, datetime toDateTime); void PrintPositionsHistory(datetime fromDateTime, datetime toDateTime); void PrintPendingOrdersHistory(datetime fromDateTime, datetime toDateTime); //-- bool GetDealsData(DealData &dealsData[], datetime fromDateTime, datetime toDateTime, string symbol, ulong magic); bool GetOrdersData(OrderData &ordersData[], datetime fromDateTime, datetime toDateTime, string symbol, ulong magic); bool GetPositionsData(PositionData &positionsData[], datetime fromDateTime, datetime toDateTime, string symbol, ulong magic); bool GetPendingOrdersData(PendingOrderData &pendingOrdersData[], datetime fromDateTime, datetime toDateTime, string symbol, ulong magic); //-- bool GetDealsData(DealData &dealsData[], datetime fromDateTime, datetime toDateTime); bool GetOrdersData(OrderData &ordersData[], datetime fromDateTime, datetime toDateTime); bool GetPositionsData(PositionData &positionsData[], datetime fromDateTime, datetime toDateTime); bool GetPendingOrdersData(PendingOrderData &pendingOrdersData[], datetime fromDateTime, datetime toDateTime); //-- bool GetAllDealsData(DealData &dealsData[]); bool GetAllOrdersData(OrderData &ordersData[]); bool GetAllPositionsData(PositionData &positionsData[]); bool GetAllPendingOrdersData(PendingOrderData &pendingOrdersData[]); //-- bool GetAllDealsData(DealData &dealsData[], string symbol, ulong magic); bool GetAllOrdersData(OrderData &ordersData[], string symbol, ulong magic); bool GetAllPositionsData(PositionData &positionsData[], string symbol, ulong magic); bool GetAllPendingOrdersData(PendingOrderData &pendingOrdersData[], string symbol, ulong magic); //-- bool GetLastClosedPositionData(PositionData &lastClosedPositionInfo); bool LastClosedPositionType(ENUM_POSITION_TYPE &lastClosedPositionType); bool LastClosedPositionVolume(double &lastClosedPositionVolume); bool LastClosedPositionSymbol(string &lastClosedPositionSymbol); bool LastClosedPositionTicket(ulong &lastClosedPositionTicket); bool LastClosedPositionProfit(double &lastClosedPositionProfit); bool LastClosedPositionNetProfit(double &lastClosedPositionNetProfit); bool LastClosedPositionPipProfit(int &lastClosedPositionPipProfit); bool LastClosedPositionClosePrice(double &lastClosedPositionClosePrice); bool LastClosedPositionOpenPrice(double &lastClosedPositionOpenPrice); bool LastClosedPositionSlPrice(double &lastClosedPositionSlPrice); bool LastClosedPositionTpPrice(double &lastClosedPositionTpPrice); bool LastClosedPositionSlPips(int &lastClosedPositionSlPips); bool LastClosedPositionTpPips(int &lastClosedPositionTpPips); bool LastClosedPositionOpenTime(datetime &lastClosedPositionOpenTime); bool LastClosedPositionCloseTime(datetime &lastClosedPositionCloseTime); bool LastClosedPositionSwap(double &lastClosedPositionSwap); bool LastClosedPositionCommission(double &lastClosedPositionCommission); bool LastClosedPositionInitiatedByPendingOrder(bool &lastClosedPositionInitiatedByPendingOrder); bool LastClosedPositionInitiatingOrderType(ENUM_ORDER_TYPE &lastClosedPositionInitiatingOrderType); bool LastClosedPositionId(ulong &lastClosedPositionId); bool LastClosedPositionOpeningOrderTicket(ulong &lastClosedPositionOpeningOrderTicket); bool LastClosedPositionOpeningDealTicket(ulong &lastClosedPositionOpeningDealTicket); bool LastClosedPositionClosingDealTicket(ulong &lastClosedPositionClosingDealTicket); bool LastClosedPositionMagic(ulong &lastClosedPositionMagic); bool LastClosedPositionComment(string &lastClosedPositionComment); bool LastClosedPositionDuration(long &lastClosedPositionDuration); //-- bool GetLastClosedProfitablePositionData(PositionData &lastClosedProfitablePositionInfo); bool GetLastClosedLossPositionData(PositionData &lastClosedLossPositionData); //-- bool GetLastFilledPendingOrderData(PendingOrderData &getLastFilledPendingOrderData); bool LastFilledPendingOrderType(ENUM_ORDER_TYPE &lastFilledPendingOrderType); bool LastFilledPendingOrderSymbol(string &lastFilledPendingOrderSymbol); bool LastFilledPendingOrderTicket(ulong &lastFilledPendingOrderTicket); bool LastFilledPendingOrderPriceOpen(double &lastFilledPendingOrderPriceOpen); bool LastFilledPendingOrderSlPrice(double &lastFilledPendingOrderSlPrice); bool LastFilledPendingOrderTpPrice(double &lastFilledPendingOrderTpPrice); bool LastFilledPendingOrderSlPips(int &lastFilledPendingOrderSlPips); bool LastFilledPendingOrderTpPips(int &lastFilledPendingOrderTpPips); bool LastFilledPendingOrderTimeSetup(datetime &lastFilledPendingOrderTimeSetup); bool LastFilledPendingOrderTimeDone(datetime &lastFilledPendingOrderTimeDone); bool LastFilledPendingOrderExpirationTime(datetime &lastFilledPendingOrderExpirationTime); bool LastFilledPendingOrderPositionId(ulong &lastFilledPendingOrderPositionId); bool LastFilledPendingOrderMagic(ulong &lastFilledPendingOrderMagic); bool LastFilledPendingOrderReason(ENUM_ORDER_REASON &lastFilledPendingOrderReason); bool LastFilledPendingOrderTypeFilling(ENUM_ORDER_TYPE_FILLING &lastFilledPendingOrderTypeFilling); bool LastFilledPendingOrderTypeTime(datetime &lastFilledPendingOrderTypeTime); bool LastFilledPendingOrderComment(string &lastFilledPendingOrderComment); //-- bool GetLastCanceledPendingOrderData(PendingOrderData &getLastCanceledPendingOrderData); bool LastCanceledPendingOrderType(ENUM_ORDER_TYPE &lastCanceledPendingOrderType); bool LastCanceledPendingOrderSymbol(string &lastCanceledPendingOrderSymbol); bool LastCanceledPendingOrderTicket(ulong &lastCanceledPendingOrderTicket); bool LastCanceledPendingOrderPriceOpen(double &lastCanceledPendingOrderPriceOpen); bool LastCanceledPendingOrderSlPrice(double &lastCanceledPendingOrderSlPrice); bool LastCanceledPendingOrderTpPrice(double &lastCanceledPendingOrderTpPrice); bool LastCanceledPendingOrderSlPips(int &lastCanceledPendingOrderSlPips); bool LastCanceledPendingOrderTpPips(int &lastCanceledPendingOrderTpPips); bool LastCanceledPendingOrderTimeSetup(datetime &lastCanceledPendingOrderTimeSetup); bool LastCanceledPendingOrderTimeDone(datetime &lastCanceledPendingOrderTimeDone); bool LastCanceledPendingOrderExpirationTime(datetime &lastCanceledPendingOrderExpirationTime); bool LastCanceledPendingOrderPositionId(ulong &lastCanceledPendingOrderPositionId); bool LastCanceledPendingOrderMagic(ulong &lastCanceledPendingOrderMagic); bool LastCanceledPendingOrderReason(ENUM_ORDER_REASON &lastCanceledPendingOrderReason); bool LastCanceledPendingOrderTypeFilling(ENUM_ORDER_TYPE_FILLING &lastCanceledPendingOrderTypeFilling); bool LastCanceledPendingOrderTypeTime(datetime &lastCanceledPendingOrderTypeTime); bool LastCanceledPendingOrderComment(string &lastCanceledPendingOrderComment); //* //-- bool GetLastClosedPositionData(PositionData &lastClosedPositionInfo, string symbol, ulong magic); bool LastClosedPositionType(ENUM_POSITION_TYPE &lastClosedPositionType, string symbol, ulong magic); bool LastClosedPositionVolume(double &lastClosedPositionVolume, string symbol, ulong magic); bool LastClosedPositionSymbol(string &lastClosedPositionSymbol, string symbol, ulong magic); bool LastClosedPositionTicket(ulong &lastClosedPositionTicket, string symbol, ulong magic); bool LastClosedPositionProfit(double &lastClosedPositionProfit, string symbol, ulong magic); bool LastClosedPositionNetProfit(double &lastClosedPositionNetProfit, string symbol, ulong magic); bool LastClosedPositionPipProfit(int &lastClosedPositionPipProfit, string symbol, ulong magic); bool LastClosedPositionClosePrice(double &lastClosedPositionClosePrice, string symbol, ulong magic); bool LastClosedPositionOpenPrice(double &lastClosedPositionOpenPrice, string symbol, ulong magic); bool LastClosedPositionSlPrice(double &lastClosedPositionSlPrice, string symbol, ulong magic); bool LastClosedPositionTpPrice(double &lastClosedPositionTpPrice, string symbol, ulong magic); bool LastClosedPositionSlPips(int &lastClosedPositionSlPips, string symbol, ulong magic); bool LastClosedPositionTpPips(int &lastClosedPositionTpPips, string symbol, ulong magic); bool LastClosedPositionOpenTime(datetime &lastClosedPositionOpenTime, string symbol, ulong magic); bool LastClosedPositionCloseTime(datetime &lastClosedPositionCloseTime, string symbol, ulong magic); bool LastClosedPositionSwap(double &lastClosedPositionSwap, string symbol, ulong magic); bool LastClosedPositionCommission(double &lastClosedPositionCommission, string symbol, ulong magic); bool LastClosedPositionInitiatingOrderType(ENUM_ORDER_TYPE &lastClosedPositionInitiatingOrderType, string symbol, ulong magic); bool LastClosedPositionId(ulong &lastClosedPositionId, string symbol, ulong magic); bool LastClosedPositionInitiatedByPendingOrder(bool &lastClosedPositionInitiatedByPendingOrder, string symbol, ulong magic); bool LastClosedPositionOpeningOrderTicket(ulong &lastClosedPositionOpeningOrderTicket, string symbol, ulong magic); bool LastClosedPositionOpeningDealTicket(ulong &lastClosedPositionOpeningDealTicket, string symbol, ulong magic); bool LastClosedPositionClosingDealTicket(ulong &lastClosedPositionClosingDealTicket, string symbol, ulong magic); bool LastClosedPositionMagic(ulong &lastClosedPositionMagic, string symbol, ulong magic); bool LastClosedPositionComment(string &lastClosedPositionComment, string symbol, ulong magic); bool LastClosedPositionDuration(long &lastClosedPositionDuration, string symbol, ulong magic); //-- bool GetLastClosedProfitablePositionData(PositionData &lastClosedProfitablePositionInfo, string symbol, ulong magic); bool GetLastClosedLossPositionData(PositionData &lastClosedLossPositionData, string symbol, ulong magic); //-- bool GetLastFilledPendingOrderData(PendingOrderData &lastFilledPendingOrderData, string symbol, ulong magic); bool LastFilledPendingOrderType(ENUM_ORDER_TYPE &lastFilledPendingOrderType, string symbol, ulong magic); bool LastFilledPendingOrderSymbol(string &lastFilledPendingOrderSymbol, string symbol, ulong magic); bool LastFilledPendingOrderTicket(ulong &lastFilledPendingOrderTicket, string symbol, ulong magic); bool LastFilledPendingOrderPriceOpen(double &lastFilledPendingOrderPriceOpen, string symbol, ulong magic); bool LastFilledPendingOrderSlPrice(double &lastFilledPendingOrderSlPrice, string symbol, ulong magic); bool LastFilledPendingOrderTpPrice(double &lastFilledPendingOrderTpPrice, string symbol, ulong magic); bool LastFilledPendingOrderSlPips(int &lastFilledPendingOrderSlPips, string symbol, ulong magic); bool LastFilledPendingOrderTpPips(int &lastFilledPendingOrderTpPips, string symbol, ulong magic); bool LastFilledPendingOrderTimeSetup(datetime &lastFilledPendingOrderTimeSetup, string symbol, ulong magic); bool LastFilledPendingOrderTimeDone(datetime &lastFilledPendingOrderTimeDone, string symbol, ulong magic); bool LastFilledPendingOrderExpirationTime(datetime &lastFilledPendingOrderExpirationTime, string symbol, ulong magic); bool LastFilledPendingOrderPositionId(ulong &lastFilledPendingOrderPositionId, string symbol, ulong magic); bool LastFilledPendingOrderMagic(ulong &lastFilledPendingOrderMagic, string symbol, ulong magic); bool LastFilledPendingOrderReason(ENUM_ORDER_REASON &lastFilledPendingOrderReason, string symbol, ulong magic); bool LastFilledPendingOrderTypeFilling(ENUM_ORDER_TYPE_FILLING &lastFilledPendingOrderTypeFilling, string symbol, ulong magic); bool LastFilledPendingOrderTypeTime(datetime &lastFilledPendingOrderTypeTime, string symbol, ulong magic); bool LastFilledPendingOrderComment(string &lastFilledPendingOrderComment, string symbol, ulong magic); //-- bool GetLastCanceledPendingOrderData(PendingOrderData &lastCanceledPendingOrderData, string symbol, ulong magic); bool LastCanceledPendingOrderType(ENUM_ORDER_TYPE &lastCanceledPendingOrderType, string symbol, ulong magic); bool LastCanceledPendingOrderSymbol(string &lastCanceledPendingOrderSymbol, string symbol, ulong magic); bool LastCanceledPendingOrderTicket(ulong &lastCanceledPendingOrderTicket, string symbol, ulong magic); bool LastCanceledPendingOrderPriceOpen(double &lastCanceledPendingOrderPriceOpen, string symbol, ulong magic); bool LastCanceledPendingOrderSlPrice(double &lastCanceledPendingOrderSlPrice, string symbol, ulong magic); bool LastCanceledPendingOrderTpPrice(double &lastCanceledPendingOrderTpPrice, string symbol, ulong magic); bool LastCanceledPendingOrderSlPips(int &lastCanceledPendingOrderSlPips, string symbol, ulong magic); bool LastCanceledPendingOrderTpPips(int &lastCanceledPendingOrderTpPips, string symbol, ulong magic); bool LastCanceledPendingOrderTimeSetup(datetime &lastCanceledPendingOrderTimeSetup, string symbol, ulong magic); bool LastCanceledPendingOrderTimeDone(datetime &lastCanceledPendingOrderTimeDone, string symbol, ulong magic); bool LastCanceledPendingOrderExpirationTime(datetime &lastCanceledPendingOrderExpirationTime, string symbol, ulong magic); bool LastCanceledPendingOrderPositionId(ulong &lastCanceledPendingOrderPositionId, string symbol, ulong magic); bool LastCanceledPendingOrderMagic(ulong &lastCanceledPendingOrderMagic, string symbol, ulong magic); bool LastCanceledPendingOrderReason(ENUM_ORDER_REASON &lastCanceledPendingOrderReason, string symbol, ulong magic); bool LastCanceledPendingOrderTypeFilling(ENUM_ORDER_TYPE_FILLING &lastCanceledPendingOrderTypeFilling, string symbol, ulong magic); bool LastCanceledPendingOrderTypeTime(datetime &lastCanceledPendingOrderTypeTime, string symbol, ulong magic); bool LastCanceledPendingOrderComment(string &lastCanceledPendingOrderComment, string symbol, ulong magic); //-- string BoolToString(bool boolVariable); datetime GetPeriodStart(int periodType); #import //+------------------------------------------------------------------+
Implementación práctica y descripción general de la librería History Manager
Ahora examinaremos las funciones de la librería, organizándolas en sus respectivas categorías para mayor claridad y facilidad de uso. A lo largo del camino, describiremos sus funciones y proporcionaremos casos de uso sencillos para demostrar cómo se pueden utilizar para realizar diversas tareas.
1. Imprimir historiales comerciales para un intervalo de tiempo específico
Estas funciones le permiten imprimir los datos del historial comercial directamente en el registro de las terminales MetaTrader 5, lo que resulta muy práctico para consultar rápidamente y depurar errores. Son de tipo void, lo que significa que no devuelven ningún valor, y aceptan dos parámetros de tipo datetime , que se utilizan para especificar el intervalo de tiempo del historial que se va a procesar:
| Definición del prototipo de función | Descripciónption | Ejemplo de caso de uso |
|---|---|---|
void PrintDealsHistory( datetime fromDateTime, datetime toDateTime ); | Imprime los detalles de todas las transacciones dentro de un intervalo de tiempo especificado. | // Print the deals history for the last 24 hours (1 day)
PrintDealsHistory(ONE_DAY, NOW); |
void PrintOrdersHistory( datetime fromDateTime, datetime toDateTime ); | Imprime los detalles de todos los pedidos dentro de un intervalo de tiempo especificado. | // Print the orders history for the last 24 hours (1 day)
PrintOrdersHistory(ONE_DAY, NOW); |
void PrintPositionsHistory( datetime fromDateTime, datetime toDateTime ); | Imprime los detalles de todas las posiciones cerradas dentro de un intervalo de tiempo especificado. | // Print the positions history for the last 24 hours (1 day)
PrintPositionsHistory(ONE_DAY, NOW); |
void PrintPendingOrdersHistory( datetime fromDateTime, datetime toDateTime ); | Imprime los detalles de todos los pedidos pendientes dentro de un intervalo de tiempo especificado. | // Print the pending orders history for the last 24 hours (1 day)
PrintPendingOrdersHistory(ONE_DAY, NOW); |
2. Recuperación de datos históricos comerciales para un intervalo de tiempo específico
Estas funciones le permiten recuperar mediante programación datos del historial de operaciones, filtrados por símbolo y número mágico, para un período específico. Los datos recuperados se almacenan en matrices de estructuras de datos, lo que permite su posterior análisis o procesamiento:
| Definición del prototipo de función | Descripciónption | Ejemplo de caso de uso |
|---|---|---|
bool GetDealsData( DealData &dealsData[], // [out] datetime fromDateTime, datetime toDateTime, string symbol, // Optional parameter ulong magic // Optional parameter ); | Esta función busca y recupera datos de operaciones dentro de un intervalo de tiempo especificado. Además, ofrece la opción de filtrar los datos recuperados por símbolo y número mágico, lo que permite un procesamiento más específico. | // Print the total account net profit for the last 7 days DealData dealsData[]; if( GetDealsData( dealsData, ONE_WEEK, NOW, ALL_SYMBOLS, 0 ) && ArraySize(dealsData) > 0 ) { double totalGrossProfit = 0.0, totalSwap = 0.0, totalCommission = 0.0; int totalDeals = ArraySize(dealsData); for(int k = 0; k < totalDeals; k++) { if(dealsData[k].entry == DEAL_ENTRY_OUT) { totalGrossProfit += dealsData[k].profit; totalSwap += dealsData[k].swap; totalCommission += dealsData[k].commission; } } double totalExpenses = totalSwap + totalCommission; double totalNetProfit = totalGrossProfit - MathAbs(totalExpenses); Print("-------------------------------------------------"); Print( "Account No: ", AccountInfoInteger(ACCOUNT_LOGIN), " [ 7 DAYS NET PROFIT ]" ); Print( "Total Gross Profit: ", DoubleToString(totalGrossProfit, 2), " ", AccountInfoString(ACCOUNT_CURRENCY) ); Print( "Total Swap: ", DoubleToString(totalSwap, 2), " ", AccountInfoString(ACCOUNT_CURRENCY) ); Print( "Total Commission: ", DoubleToString(totalCommission, 2), " ", AccountInfoString(ACCOUNT_CURRENCY) ); Print( "Total Net Profit: ", DoubleToString(totalNetProfit, 2), " ", AccountInfoString(ACCOUNT_CURRENCY) ); } |
bool GetOrdersData( OrderData &ordersData[], // [out] datetime fromDateTime, datetime toDateTime, string symbol, // Optional parameter ulong magic // Optional parameter ); | Esta función consulta y recupera datos de pedidos dentro de un intervalo de tiempo especificado. Además, ofrece la opción de filtrar los datos recuperados por símbolo y número mágico. | // Print the total BUY Orders filled in the last 7 days OrderData ordersData[]; if( GetOrdersData(ordersData, ONE_WEEK, NOW) && ArraySize(ordersData) > 0 ) { int totalBuyOrdersFilled = 0, totalOrders = ArraySize(ordersData); for(int w = 0; w < totalOrders; w++) { if(ordersData[w].type == ORDER_TYPE_BUY) ++totalBuyOrdersFilled; } Print(""); Print("-------------------------------------------------"); Print("Account No: ", AccountInfoInteger(ACCOUNT_LOGIN)); Print(totalBuyOrdersFilled, " BUY Orders Filled in the last 7 days!"); } |
bool GetPositionsData( PositionData &positionsData[], // [out] datetime fromDateTime, datetime toDateTime, string symbol, // Optional parameter ulong magic // Optional parameter ); | Esta función busca y recupera datos históricos de posiciones cerradas dentro de un intervalo de tiempo especificado. Tiene la opción de filtrar los datos recuperados por valores de símbolo y número mágico. | // Print total pips earned in last 24hrs for specified symbol and magic string symbol = _Symbol; long magic = 0; PositionData positionsData[]; if( GetPositionsData(positionsData, ONE_DAY, NOW, symbol, magic) && ArraySize(positionsData) > 0 ) { int totalPipsEarned = 0, totalPositions = ArraySize(positionsData); for(int k = 0; k < totalPositions; k++) { totalPipsEarned += positionsData[k].pipProfit; } Print(""); Print("-------------------------------------------------"); Print("Account No: ", AccountInfoInteger(ACCOUNT_LOGIN)); Print( totalPipsEarned, " pips earned in the last 24hrs for ", symbol, " with magic no. ", magic ); } |
bool GetPendingOrdersData( PendingOrderData &pendingOrdersData[], // [out] datetime fromDateTime, datetime toDateTime, string symbol, // Optional parameter ulong magic // Optional parameter ); | Esta función obtiene el historial de datos de órdenes pendientes dentro de un intervalo de tiempo especificado. También le ofrece la opción de filtrar los datos del historial de órdenes pendientes por símbolo y número mágico. | // Print total number of buy and sell stops filled for symbol and magic // in the last 7 days string symbol = _Symbol; long magic = 0; PendingOrderData pendingOrdersData[]; if( GetPendingOrdersData(pendingOrdersData, ONE_WEEK, NOW, symbol, magic) && ArraySize(pendingOrdersData) > 0 ) { int totalBuyStopsFilled = 0, totalSellStopsFilled = 0, totalPendingOrders = ArraySize(pendingOrdersData); for(int k = 0; k < totalPendingOrders; k++) { if(pendingOrdersData[k].type == ORDER_TYPE_BUY_STOP) ++totalBuyStopsFilled; if(pendingOrdersData[k].type == ORDER_TYPE_SELL_STOP) ++totalSellStopsFilled; } Print(""); Print("-------------------------------------------------"); Print("Account No: ", AccountInfoInteger(ACCOUNT_LOGIN), ", Magic No = ", magic); Print( symbol, " --> Total Filled - (Buy Stops = ", totalBuyStopsFilled, ") (Sell Stops = ", totalSellStopsFilled, ") in the last 7 days." ); } |
3. Recuperación de todo el historial de operaciones
Estas funciones proporcionan una forma completa de obtener todos los datos históricos de operaciones disponibles en la cuenta, con filtros opcionales para símbolo y número mágico, sin necesidad de introducir un intervalo de tiempo específico:
| Definición del prototipo de función | Descripciónption | Ejemplo de caso de uso |
|---|---|---|
bool GetAllDealsData( DealData &dealsData[], // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | La función recupera todos los datos de las operaciones, con la opción de filtrar los datos del historial de operaciones por símbolo y número mágico. | // Find and list total deposited funds in the account DealData dealsData[]; if(GetAllDealsData(dealsData) && ArraySize(dealsData) > 0) { double totalDeposits = 0.0; int totalDeals = ArraySize(dealsData); Print(""); for(int k = 0; k < totalDeals; k++) { if(dealsData[k].type == DEAL_TYPE_BALANCE) { totalDeposits += dealsData[k].profit; Print( dealsData[k].profit, " ", AccountInfoString(ACCOUNT_CURRENCY), " --> Cash deposit on: ", dealsData[k].time ); } } Print("-------------------------------------------------"); Print( "Account No: ", AccountInfoInteger(ACCOUNT_LOGIN), " Total Cash Deposits: ", totalDeposits, " ", AccountInfoString(ACCOUNT_CURRENCY) ); } |
bool GetAllOrdersData( OrderData &ordersData[], // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Esta función recupera todos los datos de los pedidos y ofrece la opción de filtrar el historial de pedidos por símbolo y número mágico. | // Find if the account has ever gotten a Stop Out/Margin Call OrderData ordersData[]; if(GetAllOrdersData(ordersData) && ArraySize(ordersData) > 0) { int totalStopOuts = 0; int totalOrders = ArraySize(ordersData); Print(""); for(int k = 0; k < totalOrders; k++) { if(ordersData[k].reason == ORDER_REASON_SO) { ++totalStopOuts; Print( EnumToString(ordersData[k].type), " --> on: ", ordersData[k].timeDone ); } } Print("-------------------------------------------------"); Print("Account No: ", AccountInfoInteger(ACCOUNT_LOGIN)); Print("Total STOP OUT events: ", totalStopOuts); } |
bool GetAllPositionsData( PositionData &positionsData[], // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | La función obtiene todos los datos del historial de posiciones, con la opción de filtrar los datos de las posiciones cerradas por símbolo y número mágico. | // Find the average trade duration in seconds PositionData positionsData[]; if(GetAllPositionsData(positionsData) && ArraySize(positionsData) > 0) { long totalTradesDuration = 0; int totalPositions = ArraySize(positionsData); Print(""); for(int k = 0; k < totalPositions; k++) { totalTradesDuration += positionsData[k].duration; } long averageTradesDuration = totalTradesDuration / totalPositions; Print("-------------------------------------------------"); Print("Account No: ", AccountInfoInteger(ACCOUNT_LOGIN)); Print("Average trade duration: ", averageTradesDuration, " seconds."); } |
bool GetAllPendingOrdersData( PendingOrderData &pendingOrdersData[], // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Esta función recupera todos los datos de órdenes pendientes, con la opción de filtrar los datos históricos de órdenes pendientes por símbolo y número mágico. | // Find the total expired pending orders in the account PendingOrderData pendingOrdersData[]; if(GetAllPendingOrdersData(pendingOrdersData) && ArraySize(pendingOrdersData) > 0) { int totalExpiredPendingOrders = 0; int totalPendingOrders = ArraySize(pendingOrdersData); Print(""); Print("-- EXPIRED PENDING ORDERS --"); for(int k = 0; k < totalPendingOrders; k++) { if(pendingOrdersData[k].state == ORDER_STATE_EXPIRED) { ++totalExpiredPendingOrders; Print("Symbol = ", pendingOrdersData[k].symbol); Print("Time Setup = ", pendingOrdersData[k].timeSetup); Print("Ticket = ", pendingOrdersData[k].ticket); Print("Price Open = ", pendingOrdersData[k].priceOpen); Print( "SL Price = ", pendingOrdersData[k].slPrice, ", TP Price = ", pendingOrdersData[k].tpPrice ); Print("Expiration Time = ", pendingOrdersData[k].expirationTime); Print(""); } } Print("-------------------------------------------------"); Print("Account No: ", AccountInfoInteger(ACCOUNT_LOGIN)); Print("Total Expired Pending Orders: ", totalExpiredPendingOrders); } |
4. Análisis de las últimas posiciones cerradas
Estas funciones están diseñadas para obtener información detallada sobre las posiciones cerradas más recientemente, proporcionando datos sobre aspectos clave como las ganancias o pérdidas, el volumen de operaciones y el momento en que se cerró cada posición. Cada función tiene un propósito único, lo que garantiza que usted tenga acceso a todos los aspectos críticos de su última operación. Las funciones también le ofrecen la opción de filtrar los datos del historial de posiciones que se van a procesar por símbolo y número mágico :
| Definición del prototipo de función | Descripciónption | Ejemplo de caso de uso |
|---|---|---|
bool GetLastClosedPositionData( PositionData &lastClosedPositionInfo, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | La función obtiene una instantánea completa de la posición final cerrada, incluyendo todos los detalles relevantes. Tienes la opción de filtrar el resultado por símbolo y número mágico. | // Get the last closed position in the account PositionData lastClosedPositionInfo; if( GetLastClosedPositionData(lastClosedPositionInfo) && lastClosedPositionInfo.ticket > 0 ) { // Process the last closed position data Print("---LAST CLOSED POSITION--"); Print("Symbol: ", lastClosedPositionInfo.symbol); Print("Type: ", EnumToString(lastClosedPositionInfo.type)); Print("Open Time: ", lastClosedPositionInfo.openTime); Print("Close Time: ", lastClosedPositionInfo.closeTime); Print("Profit: ", lastClosedPositionInfo.profit); // Place more position properties analysis code.... } //- // Get the last closed position for GBPUSD and magic 0 PositionData lastClosedPositionInfo; string symbol = "GBPUSD"; if( GetLastClosedPositionData(lastClosedPositionInfo, symbol, 0) && lastClosedPositionInfo.ticket > 0 ) { // Process the last closed position data Print("---LAST CLOSED POSITION FOR ", symbol, " --"); Print("Symbol: ", lastClosedPositionInfo.symbol); Print("Type: ", EnumToString(lastClosedPositionInfo.type)); Print("Open Time: ", lastClosedPositionInfo.openTime); Print("Close Time: ", lastClosedPositionInfo.closeTime); Print("Profit: ", lastClosedPositionInfo.profit); // Place more position properties analysis code.... } |
bool LastClosedPositionType( ENUM_POSITION_TYPE &lastClosedPositionType, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Esta función revela si la última posición fue una operación de compra o de venta. Tiene la opción de filtrar los datos por símbolo y número mágico. | // Get the last closed position type in the account ENUM_POSITION_TYPE lastClosedPositionType; LastClosedPositionType(lastClosedPositionType); Print( "Account's last closed position type: ", EnumToString(lastClosedPositionType) ); //-- // Get the last closed position type for EURUSD and magic 0 ENUM_POSITION_TYPE lastClosedPositionType; LastClosedPositionType(lastClosedPositionType, "EURUSD", 0); Print( "EURUSD: last closed position type: ", EnumToString(lastClosedPositionType) ); |
bool LastClosedPositionVolume( double &lastClosedPositionVolume, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Esta función proporciona el volumen de operaciones de la posición cerrada más recientemente. La función también le ofrece la opción de filtrar los datos por símbolo y número mágico. | // Get the last closed position volume in the account double lastClosedPositionVolume; LastClosedPositionVolume(lastClosedPositionVolume); Print( "Account's last closed position volume: ", lastClosedPositionVolume ); //-- // Get the last closed position volume for GBPUSD and magic 0 double lastClosedPositionVolume; LastClosedPositionVolume(lastClosedPositionVolume, "GBPUSD", 0); Print( "GBPUSD: last closed position volume: ", lastClosedPositionVolume ); |
bool LastClosedPositionSymbol( string &lastClosedPositionSymbol, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | La función obtiene el símbolo de la posición cerrada más recientemente. Te ofrece la opción de filtrar el resultado por símbolo y número mágico. | // Get the last closed position's symbol in the account string lastClosedPositionSymbol; LastClosedPositionSymbol(lastClosedPositionSymbol); Print( lastClosedPositionSymbol, " is the last closed position symbol ", "in the account" ); //-- // Get the last closed position's symbol for magic 0 string lastClosedPositionSymbol; LastClosedPositionSymbol(lastClosedPositionSymbol, ALL_SYMBOLS, 0); Print( lastClosedPositionSymbol, " is the last closed position symbol ", "for magic no: 0." ); |
bool LastClosedPositionTicket( ulong &lastClosedPositionTicket, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Esta función recupera el número de ticket de la posición cerrada más recientemente. La función tiene la opción de filtrar el resultado por símbolo y número mágico. | // Get the last closed position's ticket in the account long lastClosedPositionTicket; LastClosedPositionTicket(lastClosedPositionTicket); Print( "Account's last closed position's ticket: ", lastClosedPositionTicket ); //-- // Get the last closed position's ticket for EURUSD and magic 0 long lastClosedPositionTicket; LastClosedPositionTicket(lastClosedPositionTicket, "EURUSD", 0); Print( "EURUSD: last closed position's ticket: ", lastClosedPositionTicket ); |
bool LastClosedPositionProfit( double &lastClosedPositionProfit, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Esta función proporciona el beneficio bruto generado por la última operación. También tienes la opción de filtrar los datos por símbolo y número mágico. | // Get the last closed position's profit in the account double lastClosedPositionProfit; LastClosedPositionProfit(lastClosedPositionProfit); Print( "Account's last closed position's profit: ", lastClosedPositionProfit, " ", AccountInfoString(ACCOUNT_CURRENCY) ); //-- // Get the last closed position's profit for EURUSD and magic 0 //double lastClosedPositionProfit; LastClosedPositionProfit(lastClosedPositionProfit, "EURUSD", 0); Print( "EURUSD: last closed position's profit: ", lastClosedPositionProfit, " ", AccountInfoString(ACCOUNT_CURRENCY) ); |
A continuación se muestran las funciones de librería restantes responsables de recuperar las propiedades de la última posición cerrada. Para obtener detalles sobre la implementación, consulte los ejemplos de código anteriores, incluidas funciones como LastClosedPositionVolume(), LastClosedPositionType() y otras, ya que todas siguen un enfoque similar.
| Definición del prototipo de función | Descripciónption |
|---|---|
bool LastClosedPositionNetProfit( double &lastClosedPositionNetProfit, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Calcula el beneficio neto de la última operación, teniendo en cuenta los swaps y las comisiones. La función tiene la opción de filtrar los datos por símbolo y número mágico. |
bool LastClosedPositionPipProfit( int &lastClosedPositionPipProfit, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Obtiene la ganancia medida en pips para la posición final cerrada. Los datos se pueden filtrar por símbolo y número mágico. |
bool LastClosedPositionClosePrice( double &lastClosedPositionClosePrice, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Recupera el precio al que se cerró la posición. La función ofrece la opción de filtrar el resultado por símbolo y número mágico. |
bool LastClosedPositionOpenPrice( double &lastClosedPositionOpenPrice, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Revela el precio al que se abrió inicialmente la posición. Opcionalmente, puede filtrar los datos por símbolo y número mágico. |
bool LastClosedPositionSlPrice( double &lastClosedPositionSlPrice, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Obtiene el precio de stop-loss establecido para la última posición cerrada. La función le ofrece la opción de filtrar el resultado por símbolo y número mágico. |
bool LastClosedPositionTpPrice( double &lastClosedPositionTpPrice, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Proporciona el precio de toma de ganancias asignado a la última operación cerrada. También se proporciona una opción para filtrar los datos por símbolo y número mágico. |
bool LastClosedPositionSlPips( int &lastClosedPositionSlPips, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Indica la distancia de stop-loss en pips para la última posición cerrada. También se admite el filtrado de datos por símbolo y número mágico. |
bool LastClosedPositionTpPips( int &lastClosedPositionTpPips, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Muestra la distancia de toma de ganancias en pips para la operación cerrada más recientemente. La función también puede filtrar opcionalmente el resultado por símbolo y número mágico. |
bool LastClosedPositionOpenTime( datetime &lastClosedPositionOpenTime, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Recupera la marca de tiempo cuando se abrió la última posición cerrada. También se proporciona filtrado de datos por símbolo y número mágico. |
bool LastClosedPositionCloseTime( datetime &lastClosedPositionCloseTime, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Proporciona la hora exacta en que se cerró la posición más reciente. También puedes filtrar opcionalmente el resultado por símbolo y número mágico. |
bool LastClosedPositionSwap( double &lastClosedPositionSwap, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Revela el valor de swap asociado con la última posición cerrada. La información también se puede filtrar opcionalmente por valores de símbolos y números mágicos. |
bool LastClosedPositionCommission( double &lastClosedPositionCommission, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Obtiene la comisión cobrada por la última operación cerrada. También se admite el filtrado por símbolo y número mágico. |
bool LastClosedPositionInitiatingOrderType( ENUM_ORDER_TYPE &lastClosedPositionInitiatingOrderType, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Identifica el tipo de orden que inició la última posición cerrada. Opcionalmente puede filtrar el resultado por símbolo y número mágico. |
bool LastClosedPositionId( ulong &lastClosedPositionId, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Recupera el identificador único de la posición cerrada más reciente. Los parámetros de símbolo y mágico son opcionales y solo son necesarios cuando necesitas filtrar el resultado. |
bool LastClosedPositionInitiatedByPendingOrder( bool &lastClosedPositionInitiatedByPendingOrder, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Comprueba si la última posición cerrada fue activada o iniciada por una orden pendiente. Opcionalmente, puede filtrar los datos por símbolo y número mágico. |
bool LastClosedPositionOpeningOrderTicket( ulong &lastClosedPositionOpeningOrderTicket, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Proporciona el número de ticket de la orden que abrió la posición. La función también puede filtrar opcionalmente los datos por símbolo y número mágico. |
bool LastClosedPositionOpeningDealTicket( ulong &lastClosedPositionOpeningDealTicket, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Obtiene el número de ticket de la operación que inició la posición. Puede filtrar el resultado por símbolo y número mágico. |
bool LastClosedPositionClosingDealTicket( ulong &lastClosedPositionClosingDealTicket, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Recupera el número de ticket de la operación que cerró la posición. Filtrar los datos por símbolo y magia también es una opción. |
bool LastClosedPositionMagic( ulong &lastClosedPositionMagic, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Revela el número mágico asociado a la última posición cerrada. Puedes filtrar los datos por símbolo y número mágico. |
bool LastClosedPositionComment( string &lastClosedPositionComment, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Recupera cualquier comentario o nota adjunta a la última operación cerrada. También se ofrece la opción de filtrar el resultado por símbolo y número mágico. |
bool LastClosedPositionDuration( long &lastClosedPositionDuration, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Calcula la duración total (en segundos) que la posición permaneció abierta. Puedes filtrar el resultado por símbolo y número mágico. |
5. Análisis de las últimas posiciones cerradas ganadoras y perdedoras
Cuando necesite recuperar las propiedades de la última posición cerrada con ganancias o pérdidas, la librería History Manager proporciona dos funciones específicas para esta tarea. Estas funciones le permiten acceder rápidamente a todos los detalles relevantes con una sola llamada de función, lo que le permite analizar la posición cerrada más reciente en función de su rentabilidad. Al proporcionar datos esenciales, ayudan a evaluar el desempeño comercial y a perfeccionar las estrategias. Además, estas funciones ofrecen la flexibilidad de filtrar los resultados por un símbolo específico y un número mágico, lo que le permite centrarse en operaciones concretas y evaluar el rendimiento de estrategias o activos individuales de forma más eficaz.
| Definición del prototipo de función | Descripciónption | Ejemplo de caso de uso |
|---|---|---|
bool GetLastClosedProfitablePositionData( PositionData &lastClosedProfitablePositionInfo, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Recupera los detalles y las propiedades de la última posición cerrada que se cerró con ganancias. La función también te ofrece la opción de filtrar los resultados por símbolo y número mágico. | // Get the symbol, ticket, and net and pip profit of // the last closed profitable position PositionData lastClosedProfitablePosition; if( GetLastClosedProfitablePositionData(lastClosedProfitablePosition) && lastClosedProfitablePosition.ticket > 0 ) { Print("-------------------------------------------------"); Print( lastClosedProfitablePosition.symbol, " --> LAST CLOSED PROFITABLE POSITION" ); Print("Ticket = ", lastClosedProfitablePosition.ticket); Print( "Net Profit = ", lastClosedProfitablePosition.netProfit, " ", AccountInfoString(ACCOUNT_CURRENCY) ); Print("Pip Profit = ", lastClosedProfitablePosition.pipProfit); } //-- // Get the ticket, and net and pip profit of // the last closed profitable position for EURUSD and magic 0 PositionData lastClosedProfitablePosition; if( GetLastClosedProfitablePositionData( lastClosedProfitablePosition, "EURUSD", 0 ) && lastClosedProfitablePosition.ticket > 0 ) { Print("-------------------------------------------------"); Print("EURUSD --> LAST CLOSED PROFITABLE POSITION"); Print("Ticket = ", lastClosedProfitablePosition.ticket); Print( "Net Profit = ", lastClosedProfitablePosition.netProfit, " ", AccountInfoString(ACCOUNT_CURRENCY) ); Print("Pip Profit = ", lastClosedProfitablePosition.pipProfit); } |
bool GetLastClosedLossPositionData( PositionData &lastClosedLossPositionData, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Recupera los detalles y las propiedades de la última posición cerrada que se cerró o resultó en una pérdida. La función también le permite filtrar opcionalmente los resultados por símbolo y número mágico. | // Get the symbol, ticket, and net and pip profit of // the last closed loss position PositionData lastClosedLossPosition; if( GetLastClosedLossPositionData(lastClosedLossPosition) && lastClosedLossPosition.ticket > 0 ) { Print("-------------------------------------------------"); Print( lastClosedLossPosition.symbol, " --> LAST CLOSED LOSS POSITION" ); Print("Ticket = ", lastClosedLossPosition.ticket); Print( "Net Profit = ", lastClosedLossPosition.netProfit, " ", AccountInfoString(ACCOUNT_CURRENCY) ); Print("Pip Profit = ", lastClosedLossPosition.pipProfit); } //-- // Get the ticket, and net and pip profit of // the last closed loss position for GBPUSD and magic 0 PositionData lastClosedLossPosition; if( GetLastClosedLossPositionData( lastClosedLossPosition, "GBPUSD", 0 ) && lastClosedLossPosition.ticket > 0 ) { Print("-------------------------------------------------"); Print("GBPUSD --> LAST CLOSED LOSS POSITION"); Print("Ticket = ", lastClosedLossPosition.ticket); Print( "Net Profit = ", lastClosedLossPosition.netProfit, " ", AccountInfoString(ACCOUNT_CURRENCY) ); Print("Pip Profit = ", lastClosedLossPosition.pipProfit); } |
6. Análisis de las últimas órdenes completadas y canceladas pendientes
Para recuperar información detallada sobre la última orden pendiente completada o cancelada, la librería History Manager proporciona funciones especializadas para este fin. Estas funciones le permiten obtener todos los detalles relevantes de un pedido con una sola llamada a la función, lo que facilita el análisis de la ejecución o cancelación de pedidos pendientes. Al proporcionar datos clave, ayudan a evaluar la gestión de órdenes, la eficiencia de la ejecución y los ajustes de la estrategia comercial. Además, estas funciones ofrecen la flexibilidad de filtrar los resultados por un símbolo específico y un número mágico, lo que le permite centrarse en órdenes concretas y perfeccionar su enfoque basándose en datos históricos precisos.
Dado que las funciones última orden completada y cancelada pendiente se importan e implementan utilizando el mismo enfoque que las que procesan los datos históricos de la última posición cerrada, solo se proporcionarán sus prototipos de función y breves descripciones. Si necesita un ejemplo de cómo implementar estas funciones, consulte la sección «Análisis de las últimas posiciones cerradas» más arriba.
Para obtener detalles completos de la última orden pendiente ejecutada, la función GetLastFilledPendingOrderData() recupera todas las propiedades relevantes, ofreciendo una visión general de la ejecución de la orden. Si solo necesita atributos específicos, las siguientes funciones dedicadas le permitirán extraer detalles o propiedades individuales:
| Definición del prototipo de función | Descripciónption |
|---|---|
bool GetLastFilledPendingOrderData( PendingOrderData &lastFilledPendingOrderData, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Esta función recupera todos los detalles pertinentes de la última orden pendiente que se ha ejecutado, ofreciendo una visión completa de cómo se ha ejecutado la orden. |
bool LastFilledPendingOrderType( ENUM_ORDER_TYPE &lastFilledPendingOrderType, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Obtiene el tipo de orden, lo que le ayuda a determinar si se trataba de una orden de compra stop, una orden de venta limitada u otra variante de orden pendiente. |
bool LastFilledPendingOrderSymbol( string &lastFilledPendingOrderSymbol, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Identifica el instrumento de negociación, lo que le permite centrarse en las órdenes asociadas a un activo concreto. |
bool LastFilledPendingOrderTicket( ulong &lastFilledPendingOrderTicket, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Proporciona el ticket de orden único, esencial para referenciar o rastrear una orden específica ejecutada. |
bool LastFilledPendingOrderPriceOpen( double &lastFilledPendingOrderPriceOpen, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Recupera el precio al que se activó la orden, lo cual es crucial para analizar las condiciones de entrada. |
bool LastFilledPendingOrderSlPrice( double &lastFilledPendingOrderSlPrice, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); bool LastFilledPendingOrderTpPrice( double &lastFilledPendingOrderTpPrice, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Estas funciones devuelven los niveles de stop-loss y take-profit, respectivamente, lo que le permite evaluar los ajustes de gestión de riesgos. |
bool LastFilledPendingOrderSlPips( int &lastFilledPendingOrderSlPips, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); bool LastFilledPendingOrderTpPips( int &lastFilledPendingOrderTpPips, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Estas funciones expresan las distancias de stop-loss y take-profit en pips, lo que ofrece una visión más clara de la relación riesgo-recompensa de la operación. |
bool LastFilledPendingOrderTimeSetup( datetime &lastFilledPendingOrderTimeSetup, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); bool LastFilledPendingOrderTimeDone( datetime &lastFilledPendingOrderTimeDone, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | LastFilledPendingOrderTimeSetup() registra cuándo se realizó la orden, mientras que LastFilledPendingOrderTimeDone() registra cuándo se ejecutó. Esto ayuda a analizar el tiempo transcurrido entre el momento en que se estableció la orden pendiente y el momento en que se activó o se completó. |
bool LastFilledPendingOrderExpirationTime( datetime &lastFilledPendingOrderExpirationTime, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Comprueba y proporciona la hora de vencimiento, útil para estrategias de negociación en las que el tiempo es un factor importante. |
bool LastFilledPendingOrderPositionId( ulong &lastFilledPendingOrderPositionId, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Recupera el ID de posición, que es fundamental para vincular el pedido a su posición correspondiente, lo que garantiza un seguimiento preciso. |
bool LastFilledPendingOrderMagic( ulong &lastFilledPendingOrderMagic, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Recupera el número mágico, lo que le permite filtrar órdenes según estrategias automatizadas o bots comerciales. |
bool LastFilledPendingOrderReason( ENUM_ORDER_REASON &lastFilledPendingOrderReason, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Captura el motivo de la ejecución, lo que ofrece información sobre el procesamiento de órdenes iniciadas por el sistema o manuales. |
bool LastFilledPendingOrderTypeFilling( ENUM_ORDER_TYPE_FILLING &lastFilledPendingOrderTypeFilling, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); bool LastFilledPendingOrderTypeTime( datetime &lastFilledPendingOrderTypeTime, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | LastFilledPendingOrderTypeFilling() y LastFilledPendingOrderTypeTime() definen el método de ejecución de órdenes y el modelo temporal, respectivamente, lo que facilita el análisis de la ejecución. |
bool LastFilledPendingOrderComment( string &lastFilledPendingOrderComment, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Recupera cualquier comentario asociado a la última orden pendiente completada, lo que puede resultar útil para etiquetar y categorizar las operaciones. |
Del mismo modo, si necesita examinar la última orden pendiente cancelada, la función GetLastCanceledPendingOrderData() recupera todos los detalles en una sola llamada. Como alternativa, puede extraer propiedades individuales utilizando las siguientes funciones especializadas:
| Definición del prototipo de función | Descripciónption |
|---|---|
bool GetLastCanceledPendingOrderData( PendingOrderData &lastCanceledPendingOrderData, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Esta función proporciona un registro completo de la última orden pendiente cancelada, incluyendo todas sus propiedades y atributos. |
bool LastCanceledPendingOrderType( ENUM_ORDER_TYPE &lastCanceledPendingOrderType, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Recupera y especifica el tipo de la última orden pendiente cancelada. |
bool LastCanceledPendingOrderSymbol( string &lastCanceledPendingOrderSymbol, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Obtiene e identifica el símbolo bursátil de la orden pendiente cancelada más recientemente, lo que permite realizar un análisis específico. |
bool LastCanceledPendingOrderTicket( ulong &lastCanceledPendingOrderTicket, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Proporciona el número de ticket único del último pedido pendiente cancelado como referencia. |
bool LastCanceledPendingOrderPriceOpen( double &lastCanceledPendingOrderPriceOpen, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Obtiene y guarda el precio de entrada original previsto de la última orden pendiente cancelada. |
bool LastCanceledPendingOrderSlPrice( double &lastCanceledPendingOrderSlPrice, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); bool LastCanceledPendingOrderTpPrice( double &lastCanceledPendingOrderTpPrice, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | LastCanceledPendingOrderSlPrice() y LastCanceledPendingOrderTpPrice() recuperan los niveles de precios de stop-loss y take-profit de la orden pendiente cancelada más recientemente. |
bool LastCanceledPendingOrderSlPips( int &lastCanceledPendingOrderSlPips, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); bool LastCanceledPendingOrderTpPips( int &lastCanceledPendingOrderTpPips, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | LastCanceledPendingOrderSlPips() y LastCanceledPendingOrderTpPips() expresan las distancias de stop-loss y take-profit de la última orden pendiente cancelada en pips. |
bool LastCanceledPendingOrderTimeSetup( datetime &lastCanceledPendingOrderTimeSetup, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); bool LastCanceledPendingOrderTimeDone( datetime &lastCanceledPendingOrderTimeDone, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | LastCanceledPendingOrderTimeSetup() proporciona la hora en la que se realizó la última orden pendiente cancelada, mientras que LastCanceledPendingOrderTimeDone() registra la hora en la que se eliminó por cancelación. |
bool LastCanceledPendingOrderExpirationTime( datetime &lastCanceledPendingOrderExpirationTime, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Recupera y guarda la hora en la que la orden pendiente cancelada estaba programada para expirar. |
bool LastCanceledPendingOrderMagic( ulong &lastCanceledPendingOrderMagic, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Obtiene y almacena el número mágico asociado con la última orden pendiente cancelada, lo que permite filtrar en función de identificadores de estrategia automatizados. |
bool LastCanceledPendingOrderReason( ENUM_ORDER_REASON &lastCanceledPendingOrderReason, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Recupera el motivo de la última orden pendiente cancelada y nos permite identificar desde qué plataforma se inició la orden. |
bool LastCanceledPendingOrderTypeFilling( ENUM_ORDER_TYPE_FILLING &lastCanceledPendingOrderTypeFilling, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); bool LastCanceledPendingOrderTypeTime( datetime &lastCanceledPendingOrderTypeTime, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | LastCanceledPendingOrderTypeFilling() y LastCanceledPendingOrderTypeTime() recuperan y guardan la configuración del tipo de ejecución y la hora de la última orden pendiente cancelada. |
bool LastCanceledPendingOrderComment( string &lastCanceledPendingOrderComment, // [Out] string symbol, // Optional parameter ulong magic // Optional parameter ); | Recupera cualquier comentario definido por el usuario que se haya guardado al abrir la última orden pendiente cancelada con fines de seguimiento. |
| Definición del prototipo de función | Descripciónption |
|---|---|
string BoolToString(bool boolVariable); | La función de utilidad convierte un valor booleano en una cadena («TRUE» o «FALSE») para facilitar la lectura y el registro. |
datetime GetPeriodStart(int periodType); | Esta función de utilidad devuelve el valor datetime para el inicio del año, mes, semana (comenzando el domingo) o día, dependiendo del tipo de entrada. Acepta como entrada macros predefinidas del archivo de encabezado, concretamente TODAY, THIS_WEEK, THIS_MONTH y THIS_YEAR. Esta función simplifica el proceso de obtener el valor de fecha y hora para estos períodos, permitiéndole hacerlo con una sola línea de código. |
En la siguiente sección, exploraremos ejemplos prácticos que demuestran cómo se puede utilizar la librería History Management para generar análisis comerciales reveladores. Además, desarrollaremos un Asesor Experto que aproveche la librería para determinar el volumen o lote óptimo y la dirección de la posición para ejecutar nuevas operaciones. Esto pondrá de relieve cómo los datos históricos pueden incorporarse de manera eficaz a los sistemas de negociación automatizados, mejorando tanto la ejecución de estrategias como la toma de decisiones.
Cómo calcular el factor de beneficio, la ganancia/pérdida bruta y la ganancia y pérdida bruta promedio por operación de un asesor experto o símbolo
Al evaluar el rendimiento de un Asesor Experto o una estrategia comercial en MetaTrader 5, una de las métricas más importantes a considerar es el Factor de Beneficio. El factor de beneficio es una relación que mide la ganancia bruta frente a la pérdida bruta durante un período específico. Proporciona una indicación clara de cuán rentable es una estrategia comercial al comparar las ganancias totales con las pérdidas totales.
Un factor de beneficio alto indica que la estrategia está generando más ganancias en relación con sus pérdidas, lo que es una característica deseable para cualquier sistema de trading. Por el contrario, un factor de beneficio bajo sugiere que la estrategia puede no ser tan efectiva y podría necesitar una mayor optimización.
El factor de beneficio se calcula utilizando la siguiente fórmula:Factor de beneficio = beneficio bruto / pérdida bruta
Donde:
- Beneficio bruto es la cantidad total de dinero obtenida de todas las operaciones rentables.
- Pérdida bruta es la cantidad total de dinero perdido en todas las operaciones con pérdidas.
Un factor de beneficio superior a 1 indica que la estrategia es rentable, ya que el beneficio bruto supera la pérdida bruta. Un factor de beneficio de 1 significa que el beneficio bruto y la pérdida bruta son iguales, lo que sugiere un escenario de equilibrio. Un factor de beneficio inferior a 1 indica que la estrategia está perdiendo dinero, ya que la pérdida bruta supera al beneficio bruto.
Comprender y calcular el factor de beneficio es fundamental para que los operadores y desarrolladores tomen decisiones informadas sobre la viabilidad y el rendimiento de sus estrategias de negociación.
En este ejemplo, utilizaré la librería HistoryManager.ex5 para demostrar lo fácil que es implementar este cálculo en su código MQL5.
Comience por crear un nuevo Asesor Experto y asígnele el nombre GetProfitFactor.mq5. Guárdelo en la siguiente ruta de carpeta: Experts\Wanateki\HistoryManager\GetProfitFactor.mq5. Tenga en cuenta que el directorio en el que guarda el Asesor Experto es importante, ya que influirá en la ruta utilizada para incluir el archivo de encabezado que contiene las definiciones de los prototipos de funciones de la librería.
El Asesor Experto GetProfitFactor.mq5 le ayudará a analizar el rendimiento de sus estrategias de trading calculando métricas clave como el beneficio bruto, la pérdida bruta y el propio factor de beneficio.
En primer lugar, debemos incluir la librería HistoryManager.ex5 y definir una enumeración que utilizaremos para introducir el valor de cadena symbol en nuestro Asesor Experto. La enumeración symbolName nos permitirá especificar si queremos analizar el símbolo del gráfico actual o todos los símbolos de la cuenta. Esta enumeración, junto con la entrada del número mágico, nos permitirá filtrar los resultados para que se ajusten a nuestros símbolos y asesores expertos específicos.
#include <Wanateki/Toolkit/HistoryManager/HistoryManager.mqh> //-- enum symbolName { CURRENT_CHART_SYMBOL, ALL_ACCOUNT_SYMBOLS, };
A continuación, definimos los parámetros de entrada que utilizará el usuario del Asesor Experto para filtrar la salida.
//--- input parameters input ulong magicNo = 0; //Magic Number (0 to disable) input symbolName getSymbolName = ALL_ACCOUNT_SYMBOLS;
Inicializamos las variables que se utilizarán para almacenar nuestros cálculos y mostrar los resultados.
string currency = " " + AccountInfoString(ACCOUNT_CURRENCY); double totalGrossProfit = 0.0, totalGrossLoss = 0.0, averageGrossProfit = 0.0, averageGrossLoss = 0.0, averageProfitOrLossPerTrade = 0.0, profitFactor = 0.0; int totalTrades = 0, totalLossPositions = 0, totalProfitPositions = 0; string symbol, printedSymbol, profitFactorSummery, commentString;
En la función OnInit(), utilizaremos una instrucción switch para determinar el símbolo que se va a analizar. Una vez identificado el símbolo, llamaremos a la función CalcProfitFactor(), que se encarga de calcular el factor de beneficio. As the first task when the Expert Advisor loads, we will then display all the results on the chart using the Comment() function.
int OnInit() { //--- switch(getSymbolName) { case CURRENT_CHART_SYMBOL: symbol = _Symbol; break; case ALL_ACCOUNT_SYMBOLS: symbol = ALL_SYMBOLS; break; default: symbol = ALL_SYMBOLS; } printedSymbol = symbol; if(symbol == "") printedSymbol = "ALL_SYMBOLS"; //-- CalcProfitFactor(); Comment(commentString); //--- return(INIT_SUCCEEDED); }
Antes de continuar, codifiquemos la función CalcProfitFactor(), ya que contiene la mayor parte del código que ejecuta el Asesor Experto GetProfitFactor .
Comenzaremos la función CalcProfitFactor() codificando la firma de la función y, a continuación, restableceremos todas las variables a sus valores iniciales. Esto garantiza que cualquier cálculo anterior no interfiera con el análisis actual.
totalGrossProfit = 0.0; totalGrossLoss = 0.0; averageProfitOrLossPerTrade = 0.0; averageGrossProfit = 0.0; averageGrossLoss = 0.0; profitFactor = 0.0; totalTrades = 0; totalLossPositions = 0; totalProfitPositions = 0;
A continuación, utilizamos la función GetAllPositionsData() para recuperar datos históricos de operaciones. Esta función rellena la matriz positionsData con todas las posiciones comerciales basadas en el símbolo y el número mágico especificados. Del mismo modo, comprobamos si la función devuelve true y si el tamaño de la matriz es superior a cero para asegurarnos de que tenemos datos válidos para procesar. Este paso es esencial para acceder a la información comercial necesaria para realizar nuestros cálculos.
if(GetAllPositionsData(positionsData, symbol, magicNo) && ArraySize(positionsData) > 0) { //-- }
A continuación, recorremos cada operación de la matriz positionsData para calcular el beneficio y pérdida brutos totales. Para cada operación, comprobamos si la ganancia supera cero para determinar si es una operación rentable. Si es así, incrementamos el contador totalProfitPositions y añadimos el beneficio a totalGrossProfit. Si la ganancia es menor o igual a cero, incrementamos el contador totalLossPositions y sumamos el valor absoluto de la ganancia a totalGrossLoss. Este bucle nos ayuda a acumular las ganancias y pérdidas totales de todas las operaciones.
totalTrades = ArraySize(positionsData); for(int r = 0; r < totalTrades; r++) { if(positionsData[r].profit > 0) // profitable trade { ++totalProfitPositions; totalGrossProfit += positionsData[r].profit; } else // loss trade { ++totalLossPositions; totalGrossLoss += MathAbs(positionsData[r].profit); } } // Calculate the profit factor and other data if(totalGrossProfit > 0 || totalGrossLoss > 0) averageProfitOrLossPerTrade = NormalizeDouble( (totalGrossProfit + totalGrossLoss) / totalTrades, 2 ); if(totalGrossProfit > 0) averageGrossProfit = NormalizeDouble( (totalGrossProfit / totalProfitPositions), 2 ); if(totalGrossLoss > 0) averageGrossLoss = NormalizeDouble( (totalGrossLoss / totalLossPositions), 2 ); //-- if(totalGrossLoss == 0.0) profitFactor = 0.0; // Avoid division by zero, indicating no losses profitFactor = totalGrossProfit / totalGrossLoss; }
Tras acumular el total de ganancias y pérdidas brutas, procedemos a calcular diversas métricas. Primero, calculamos la ganancia o pérdida promedio por operación dividiendo la suma de la ganancia y pérdida bruta total por el número total de operaciones. Además, calculamos la ganancia bruta promedio dividiendo la ganancia bruta total por el número de operaciones rentables. De manera similar, calculamos la pérdida bruta promedio dividiendo la pérdida bruta total por el número de operaciones con pérdidas. Finalmente, calculamos el factor de beneficio dividiendo la ganancia bruta total por la pérdida bruta total. Estas métricas proporcionan una visión integral del rendimiento de la estrategia comercial.
profitFactorSummery = "Profit Factor = " + DoubleToString(profitFactor, 2); if(profitFactor > 2.0) { profitFactorSummery = profitFactorSummery + "\nThe trading strategy is HIGHLY PROFITABLE and efficient."; } else if(profitFactor > 1.5) { profitFactorSummery = profitFactorSummery + "\nThe trading strategy is profitable and well-balanced."; } else if(profitFactor > 1.0) { profitFactorSummery = profitFactorSummery + "\nThe trading strategy is slightly profitable but may need improvement."; } else if(profitFactor == 1.0) { profitFactorSummery = profitFactorSummery + "\nThe strategy is break-even with no net gain or loss."; } else { profitFactorSummery = profitFactorSummery + "\nThe trading strategy is unprofitable and needs optimization."; }
Analizamos el factor de beneficio para generar una cadena de resumen que describe el rendimiento de la estrategia comercial. Así es como interpretamos el factor beneficio:
- Factor de beneficio > 2.0: La estrategia es altamente rentable y eficiente.
- Factor de beneficio entre 1,0 y 1,5: La estrategia es ligeramente rentable pero puede necesitar mejoras.
- Factor de beneficio = 1,0: La estrategia alcanza el punto de equilibrio, sin ganancias ni pérdidas netas.
- Factor de beneficio < 1,0: La estrategia no es rentable y requiere optimización.
Este análisis del factor de beneficio proporciona una comprensión rápida de la eficacia general de la estrategia comercial.
Por último, generamos una cadena detallada de comentarios que incluye todas las métricas calculadas y el resumen del factor de beneficio. Esta cadena está formateada para mostrar el símbolo que se está analizando, el número mágico, el número total de operaciones, el número de operaciones rentables y con pérdidas, el beneficio y la pérdida brutos totales, el beneficio o la pérdida medios por operación, el beneficio y la pérdida brutos medios, y el resumen del factor de beneficio.
Aquí está la función completa CalcProfitFactor() con todos los segmentos de código en su lugar.
void CalcProfitFactor() { totalGrossProfit = 0.0; totalGrossLoss = 0.0; averageProfitOrLossPerTrade = 0.0; averageGrossProfit = 0.0; averageGrossLoss = 0.0; profitFactor = 0.0; totalTrades = 0; totalLossPositions = 0; totalProfitPositions = 0; //-- PositionData positionsData[]; if(GetAllPositionsData(positionsData, symbol, magicNo) && ArraySize(positionsData) > 0) { totalTrades = ArraySize(positionsData); for(int r = 0; r < totalTrades; r++) { if(positionsData[r].profit > 0) // profitable trade { ++totalProfitPositions; totalGrossProfit += positionsData[r].profit; } else // loss trade { ++totalLossPositions; totalGrossLoss += MathAbs(positionsData[r].profit); } } // Calculate the profit factor and other data if(totalGrossProfit > 0 || totalGrossLoss > 0) averageProfitOrLossPerTrade = NormalizeDouble( (totalGrossProfit + totalGrossLoss) / totalTrades, 2 ); if(totalGrossProfit > 0) averageGrossProfit = NormalizeDouble( (totalGrossProfit / totalProfitPositions), 2 ); if(totalGrossLoss > 0) averageGrossLoss = NormalizeDouble( (totalGrossLoss / totalLossPositions), 2 ); //-- if(totalGrossLoss == 0.0) profitFactor = 0.0; // Avoid division by zero, indicating no losses profitFactor = totalGrossProfit / totalGrossLoss; } // Analyze the Profit Factor result profitFactorSummery = "Profit Factor = " + DoubleToString(profitFactor, 2); if(profitFactor > 2.0) { profitFactorSummery = profitFactorSummery + "\nThe trading strategy is HIGHLY PROFITABLE and efficient."; } else if(profitFactor > 1.5) { profitFactorSummery = profitFactorSummery + "\nThe trading strategy is profitable and well-balanced."; } else if(profitFactor > 1.0) { profitFactorSummery = profitFactorSummery + "\nThe trading strategy is slightly profitable but may need improvement."; } else if(profitFactor == 1.0) { profitFactorSummery = profitFactorSummery + "\nThe strategy is break-even with no net gain or loss."; } else { profitFactorSummery = profitFactorSummery + "\nThe trading strategy is unprofitable and needs optimization."; } commentString = "\n\n-----------------------------------------------------------------------------------------------------" + "\n HistoryManager.ex5 --- PROFIT FACTOR ANALYTICS ---" + "\n-----------------------------------------------------------------------------------------------------" + "\n -> Symbol = " + printedSymbol + "\n -> Magic No = " + IntegerToString(magicNo) + "\n-----------------------------------------------------------------------------------------------------" + "\n-----------------------------------------------------------------------------------------------------" + "\n" + profitFactorSummery + "\n-----------------------------------------------------------------------------------------------------" + "\n-----------------------------------------------------------------------------------------------------" + "\n -> Total Trades Analysed = " + IntegerToString(totalTrades) + "\n -> Total Profitable Trades = " + IntegerToString(totalProfitPositions) + "\n -> Total Loss Trades = " + IntegerToString(totalLossPositions) + "\n --------------------------------------------------------" + "\n -> Total Gross Profit = " + DoubleToString(totalGrossProfit, 2) + currency + "\n -> Total Gross Loss = -" + DoubleToString(totalGrossLoss, 2) + currency + "\n ----------------------------------" + "\n -> Total Gross (Profit - Loss) = " + DoubleToString(totalGrossProfit - totalGrossLoss, 2) + currency + "\n --------------------------------------------------------" + "\n -> Average Profit or Loss Per Trade = (-/+)" + DoubleToString(averageProfitOrLossPerTrade, 2) + currency + "\n --------------------------------------------------------" + "\n -> Average Gross Profit = " + DoubleToString(averageGrossProfit, 2) + currency + "\n -> Average Gross Loss = -" + DoubleToString(averageGrossLoss, 2) + currency + "\n --------------------------------------------------------" + "\n-----------------------------------------------------------------------------------------------------"; //-- }
También colocamos la función dentro de la función estándar OnTrade() para ejecutarla y volver a calcular el factor de beneficio después de cada operación comercial.
void OnTrade() { //--- CalcProfitFactor(); }
Para asegurarnos de que estamos imprimiendo datos actualizados en el gráfico, utilizaremos la función Comment() para imprimir la commentString que contiene toda la información sobre el factor de beneficio actualizado y la imprimiremos después de cada nuevo tick entrante en la función estándar OnTick().
void OnTick() { //--- Comment(commentString); }
Aquí está el resultado del Asesor Experto GetProfitFactor en la ventana del gráfico de MetaTrader 5.

El archivo fuente GetProfitFactor.mq5 se adjunta al final de este artículo para su comodidad.
Cómo calcular el beneficio bruto y neto monetario de la semana actual para un asesor experto o símbolo específico
En este ejemplo, vamos a crear un script MQL5 que proporcionará una visión general completa del rendimiento financiero de la semana actual, incluyendo el beneficio bruto, los swaps, las comisiones y el beneficio neto. Esto le ayudará a demostrar cómo puede utilizar la librería History Manager para evaluar rápidamente el rendimiento semanal de toda la cuenta, un símbolo específico o el número mágico de un Asesor Experto directamente en el terminal MetaTrader 5.
Empezamos creando un nuevo script llamado GetNetProfitThisWeek.mq5 y lo guardamos en esta carpeta: (Scripts\Wanateki\HistoryManager\GetNetProfitThisWeek.mq5). En el nuevo archivo de script, comience incluyendo la librería HistoryManager.mqh, que nos proporcionará acceso a todas las funciones de la librería.
#include <Wanateki/Toolkit/HistoryManager/HistoryManager.mqh> A continuación, colocaremos todo nuestro código dentro de la función OnStart() para que todo resulte más sencillo y claro. El primer segmento del script consistirá en inicializar una variable de cadena para almacenar la moneda de la cuenta. Esto se utilizará para dar formato a los resultados de las métricas financieras.
string currency = " " + AccountInfoString(ACCOUNT_CURRENCY);
Antes de comenzar cualquier cálculo, primero debemos calcular la hora de inicio de la semana actual. Esto se ha simplificado, ya que la biblioteca HistoryManager.ex5 contiene la función de utilidad GetPeriodStart(), que utilizaremos para obtener el valor datetime del inicio de la semana actual. Para obtener este valor, solo tenemos que invocar la función GetPeriodStart() con el parámetro THIS_WEEK como entrada. Esto nos ayudará a filtrar las transacciones que se han producido durante la semana actual.
datetime thisWeekStartTime = GetPeriodStart(THIS_WEEK); Declaramos una matriz para almacenar los datos de las transacciones y utilizamos la función GetDealsData() para rellenarla con las transacciones que se han producido entre el inicio de la semana actual y el momento actual (NOW). Del mismo modo, filtramos las operaciones para todos los símbolos con un número mágico de 0.
if( GetDealsData( dealsData, thisWeekStartTime, NOW, ALL_SYMBOLS, 0 ) && ArraySize(dealsData) > 0 )
Inicializamos las variables para almacenar el total de ganancia bruta, el total de intercambio, y el total de comisión. Estas variables se utilizarán para acumular los valores respectivos de los datos de la operación.
double totalGrossProfit = 0.0, totalSwap = 0.0, totalCommission = 0.0;
Recorremos cada operación de la matriz dealsData . Para cada operación , comprobamos si se trata de una operación de cierre (DEAL_ENTRY_OUT). Si es así, añadimos beneficio, intercambio y comisión a sus respectivas variables totales.
int totalDeals = ArraySize(dealsData); for(int k = 0; k < totalDeals; k++) { if(dealsData[k].entry == DEAL_ENTRY_OUT) { totalGrossProfit += dealsData[k].profit; totalSwap += dealsData[k].swap; totalCommission += dealsData[k].commission; } }
Calculamos los gastos totales sumando el total de swap y comisión. Además, calculamos el beneficio neto total restando los gastos totales del beneficio bruto total.
double totalExpenses = totalSwap + totalCommission; double totalNetProfit = totalGrossProfit - MathAbs(totalExpenses);
Utilizamos la función Print() para enviar los resultados al registro de MetaTrader 5. Esto incluye el beneficio bruto total, los swaps totales, la comisión total y el beneficio neto total de la semana actual. Además, también utilizamos la función Comment() para mostrar los resultados directamente en la ventana del gráfico. Esto incluye un resumen detallado de las métricas financieras de la semana actual.

Aquí está la función completa OnStart() con todos los segmentos de código en su secuencia correcta y en su totalidad.
void OnStart() { //--- string currency = " " + AccountInfoString(ACCOUNT_CURRENCY); datetime thisWeekStartTime = GetPeriodStart(THIS_WEEK); DealData dealsData[]; if( GetDealsData( dealsData, thisWeekStartTime, NOW, ALL_SYMBOLS, 0 ) && ArraySize(dealsData) > 0 ) { double totalGrossProfit = 0.0, totalSwap = 0.0, totalCommission = 0.0; int totalDeals = ArraySize(dealsData); for(int k = 0; k < totalDeals; k++) { if(dealsData[k].entry == DEAL_ENTRY_OUT) { totalGrossProfit += dealsData[k].profit; totalSwap += dealsData[k].swap; totalCommission += dealsData[k].commission; } } double totalExpenses = totalSwap + totalCommission; double totalNetProfit = totalGrossProfit - MathAbs(totalExpenses); Print("-------------------------------------------------"); Print( "Account No: ", AccountInfoInteger(ACCOUNT_LOGIN), " [ THIS WEEK'S NET PROFIT ]" ); Print( "Total Gross Profit This Week: ", DoubleToString(totalGrossProfit, 2), " ", currency ); Print( "Total Swaps This Week: ", DoubleToString(totalSwap, 2), " ", currency ); Print( "Total Commission This Week: ", DoubleToString(totalCommission, 2), " ", currency ); Print( "Total Net Profit This Week: ", DoubleToString(totalNetProfit, 2), " ", currency ); //-- Comment( "\n\n-----------------------------------------------------------------------------------------------------" + "-------------------------------------------------------------------" + "\n HistoryManager.ex5 --- TOTAL NET PROFIT THIS WEEK ---" + "\n-----------------------------------------------------------------------------------------------------" + "------------------------------------------------------" + "\n DATE = ( From: " + TimeToString(thisWeekStartTime) + ", to: " + TimeToString(NOW) + " )" + "\n Account No = " + IntegerToString(AccountInfoInteger(ACCOUNT_LOGIN)) + "\n------------------------------------------------------" + "\n -> Total Gross Profit = " + DoubleToString(totalGrossProfit, 2) + currency + "\n -> Total Swaps = " + DoubleToString(totalSwap, 2) + currency + "\n -> Total Commission = " + DoubleToString(totalCommission, 2) + currency + "\n-----------------------------------------------------------------------------------------------------" + "------------------------------------------------------" + "\n -> TOTAL NET PROFIT = " + DoubleToString(totalNetProfit, 2) + currency + "\n-----------------------------------------------------------------------------------------------------" + "------------------------------------------------------" + "\n-----------------------------------------------------------------------------------------------------" + "-------------------------------------------------------------------" ); } }
Para obtener el código fuente completo del script, descargue el archivo fuente GetNetProfitThisWeek.mq5 adjunto al final de este artículo.
Cómo calcular la relación entre ganancias y pérdidas en pips para un símbolo o asesor experto específico
En este ejemplo, exploraremos cómo calcular la relación ganancia-pérdida en pips para un símbolo comercial específico o un asesor experto completo utilizando MQL5. Este cálculo es una herramienta crucial para evaluar el rendimiento de una estrategia comercial, ya que proporciona una métrica clara y cuantificable para determinar si la estrategia es rentable, alcanza el punto de equilibrio o no es rentable en función de los pips ganados o perdidos. El código proporcionado está diseñado para analizar datos comerciales históricos, calcular la proporción y presentar los resultados en un formato fácil de usar y de interpretar.
Nombraremos al Asesor Experto GetSymbolPipsProfitToLossRatio.mq5, lo guardaremos en la carpeta correspondiente y comenzaremos incluyendo la librería HistoryManager.mqh como la primera y más importante línea de nuestro archivo fuente. A continuación, crearemos un enum para almacenar el nombre del símbolo y definiremos los parámetros de entrada (símbolo y número mágico ). Estos parámetros permitirán al usuario filtrar los resultados de los datos según sus preferencias: si desea analizar todas las posiciones cerradas para un símbolo específico, posiciones cerradas para un símbolo específico que incluye un número mágico particular, o todas las posiciones con un número mágico específico, independientemente del símbolo.
En la función OnInit(), recuperaremos la divisa de la cuenta y determinaremos el símbolo o símbolos que se analizarán en función de la información introducida por el usuario. Si el usuario selecciona CURRENT_CHART_SYMBOL, nuestro Asesor Experto se centrará en el símbolo del gráfico actual. Si seleccionan ALL_ACCOUNT_SYMBOLS, se analizarán todos los símbolos negociados en la cuenta.
Utilizaremos la función GetAllPositionsData() para obtener datos históricos de operaciones para los símbolos y números mágicos especificados. Estos datos se almacenarán en una matriz de estructuras PositionData . Del mismo modo, iteraremos a través de la matriz para clasificar las operaciones como rentables o deficitarias. Durante este proceso, calcularemos el total de pips ganados en operaciones rentables (totalPipsProfit) y el total de pips perdidos en operaciones con pérdidas (totalPipsLoss).
Para calcular la relación pip beneficio-pérdida, dividiremos el total de pips ganados por el total de pips perdidos. Además, utilizaremos el valor absoluto para garantizar que la relación sea siempre positiva. Si no hay operaciones perdedoras (totalPipsLoss == 0), la ratio será indefinida, y el Asesor Experto mostrará un mensaje indicando que la estrategia no tiene operaciones perdedoras. El Asesor Experto interpretará la relación de la siguiente manera:
- Ratio > 1.0: La estrategia es rentable, ya que gana más pips de los que pierde.
- Relación == 1.0: La estrategia alcanza el punto de equilibrio en términos de pips.
- Ratio < 1.0: La estrategia no es rentable, ya que pierde más pips de los que gana.
Utilizaremos la función Comment() para mostrar los resultados del análisis directamente en el gráfico. El resultado incluirá: los símbolos analizados, el número mágico utilizado (si hay alguno), el número total de operaciones analizadas, el número de operaciones rentables y perdedoras, junto con el total de pips ganados y perdidos, y la relación ganancia-pérdida calculada en pips y su interpretación.

En la función OnDeinit(), realizaremos una limpieza sencilla borrando los comentarios del gráfico cuando se elimine o desinicialice el Asesor Experto, lo que garantizará un espacio de trabajo limpio. Dejaremos la función OnTick() vacía, ya que el análisis solo se realiza una vez durante la inicialización. Sin embargo, puede ampliar esta función para realizar cálculos o actualizaciones en tiempo real si es necesario.
Aquí están todos los segmentos de código presentados en su secuencia correcta:
//-- #include <Wanateki/Toolkit/HistoryManager/HistoryManager.mqh> //-- enum symbolName { CURRENT_CHART_SYMBOL, ALL_ACCOUNT_SYMBOLS, }; //--- input parameters input ulong magicNo = 0; //Magic Number (0 to disable) input symbolName getSymbolName = CURRENT_CHART_SYMBOL;
int OnInit() { //--- string currency = " " + AccountInfoString(ACCOUNT_CURRENCY); string symbol, printedSymbol; switch(getSymbolName) { case CURRENT_CHART_SYMBOL: symbol = _Symbol; break; case ALL_ACCOUNT_SYMBOLS: symbol = ALL_SYMBOLS; break; default: symbol = ALL_SYMBOLS; } printedSymbol = symbol; if(symbol == "") printedSymbol = "ALL_SYMBOLS"; //-- int totalTrades = 0; int totalLossPositions = 0; int totalProfitPositions = 0; double totalPipsProfit = 0; double totalPipsLoss = 0; string interpretation; double pipsProfitToLossRatio = 0; //-- PositionData positionsData[]; if(GetAllPositionsData(positionsData, symbol, magicNo) && ArraySize(positionsData) > 0) { totalTrades = ArraySize(positionsData); for(int r = 0; r < totalTrades; r++) { if(positionsData[r].profit > 0) // profitable trade { ++totalProfitPositions; totalPipsProfit += positionsData[r].pipProfit; } else // loss trade { ++totalLossPositions; totalPipsLoss += positionsData[r].pipProfit; } } // Calculate the pip profit loss ratioInterpretation if(totalPipsLoss == 0) { interpretation = "Pips Profit-to-Loss Ratio: Undefined (Total pips loss is zero)." + "The strategy has no losing trades."; } else { pipsProfitToLossRatio = fabs(totalPipsProfit / totalPipsLoss); switch(pipsProfitToLossRatio > 1.0 ? 1 : pipsProfitToLossRatio == 1.0 ? 0 : -1) { case 1: interpretation = "Pips Profit-to-Loss Ratio: " + DoubleToString(pipsProfitToLossRatio, 2) + ". The strategy is profitable as it gains more pips than it loses."; break; case 0: interpretation = "Pips Profit-to-Loss Ratio: " + DoubleToString(pipsProfitToLossRatio, 2) + ". The strategy breaks even in terms of pips."; break; case -1: interpretation = "Pips Profit-to-Loss Ratio: " + DoubleToString(pipsProfitToLossRatio, 2) + ". The strategy is unprofitable as it loses more pips than it gains."; break; } } Comment( "\n\n-----------------------------------------------------------------------------------------------------" + "---------------------------" + "\n HistoryManager.ex5 --- PIPS PROFIT TO LOSS RATIO ---" + "\n-----------------------------------------------------------------------------------------------------" + "---------------------------" + "\n -> Symbol = " + printedSymbol + "\n -> Magic No = " + IntegerToString(magicNo) + "\n-----------------------------------------------------------------------------------------------------" + "---------------------------" + "\n-----------------------------------------------------------------------------------------------------" + "---------------------------" + "\n" + interpretation + "\n-----------------------------------------------------------------------------------------------------" + "---------------------------" + "\n-----------------------------------------------------------------------------------------------------" + "---------------------------" + "\n -> Total Trades Analysed = " + IntegerToString(totalTrades) + "\n -> Total Profitable Trades = " + IntegerToString(totalProfitPositions) + " ( " + DoubleToString(totalPipsProfit, 0) + " Pips )" + "\n -> Total Loss Trades = " + IntegerToString(totalLossPositions) + " ( " + DoubleToString(totalPipsLoss, 0) + " Pips )" + "\n --------------------------------------------------------------------------" + "\n -> PIPS PROFIT TO LOSS RATIO = " + DoubleToString(pipsProfitToLossRatio, 2) + "\n --------------------------------------------------------------------------" + "\n-----------------------------------------------------------------------------------------------------" + "---------------------------" ); } //--- return(INIT_SUCCEEDED); }
Puede descargar el archivo fuente completo GetSymbolPipsProfitToLossRatio.mq5 al final de este artículo.
Cómo obtener el valor total en efectivo de los depósitos en cuenta
En esta sección, crearemos un sencillo script MQL5 llamado GetTotalDeposits.mq5 que utiliza la función GetAllDealsData() de nuestra biblioteca para recuperar y analizar datos de operaciones, con el fin de ayudarle a obtener una visión general clara del historial de financiación de su cuenta. Esta es una herramienta muy útil que conviene tener en su kit de herramientas para cuando desee realizar un seguimiento algorítmico del total de fondos depositados en su cuenta de operaciones, auditar el historial de financiación de su cuenta con fines contables o fiscales, o simplemente verificar las transacciones de depósito para garantizar su exactitud.
Utilizaremos la función GetAllDealsData() para recuperar todos los datos históricos de transacciones de la cuenta. Estos datos se almacenarán en una matriz de estructuras DealData. A continuación, inicializaremos una variable para almacenar el valor total del depósito y recorreremos los datos de la operación. Identifique las transacciones de depósito comprobando si el tipo de operación es DEAL_TYPE_BALANCE. Sume los valores de beneficio de estas operaciones para calcular el total de los depósitos.
Después de calcular y guardar todos los datos específicos, imprimiremos el valor total del depósito en el terminal y lo mostraremos en el gráfico utilizando la función Comment(). Esto proporciona un resumen fácil de usar del historial de depósitos de la cuenta.
#include <Wanateki/Toolkit/HistoryManager/HistoryManager.mqh> void OnStart() { //--- // Find and list total deposited funds in the account DealData dealsData[]; if(GetAllDealsData(dealsData) && ArraySize(dealsData) > 0) { double totalDeposits = 0.0; int totalDeals = ArraySize(dealsData); Print(""); for(int k = 0; k < totalDeals; k++) { if(dealsData[k].type == DEAL_TYPE_BALANCE) { totalDeposits += dealsData[k].profit; Print( dealsData[k].profit, " ", AccountInfoString(ACCOUNT_CURRENCY), " --> Cash deposit on: ", dealsData[k].time ); } } Print("-------------------------------------------------"); Print( "Account No: ", AccountInfoInteger(ACCOUNT_LOGIN), " Total Cash Deposits: ", totalDeposits, " ", AccountInfoString(ACCOUNT_CURRENCY) ); Comment( "\n\n-----------------------------------------------------------------------------------------------------" + "---------------------------------------------------------" + "\n HistoryManager.ex5 --- TOTAL ACCOUNT DEPOSITS ---" + "\n-----------------------------------------------------------------------------------------------------" + "------------------------------------------------------" + "\n -> Account No = " + IntegerToString(AccountInfoInteger(ACCOUNT_LOGIN)) + "\n -> Total Cash Deposits = " + DoubleToString(totalDeposits, 2) + AccountInfoString(ACCOUNT_CURRENCY) + "\n-----------------------------------------------------------------------------------------------------" + "------------------------------------------------------" ); } }
Puede descargar el archivo fuente completo GetTotalDeposits.mq5 al final de este artículo.
Cómo crear un asesor experto basado en datos de precios con la librería History Manager
Para el último ejemplo de este artículo, crearemos un asesor experto sencillo pero potente basado en datos de precios llamado PriceTrader_EA, impulsado por las bibliotecas PositionsManager.ex5 y HistoryManager.ex5. Este asesor experto tiene un importante potencial de rentabilidad, especialmente cuando se utiliza en una cuenta grande y tras realizar pruebas retrospectivas y optimizaciones exhaustivas. Notará que el código fuente de PriceTrader_EA es conciso y eficiente, gracias al uso de nuestras librerías pre-desarrolladas PositionsManager.ex5 y HistoryManager.ex5. Estas bibliotecas nos permiten minimizar el código sin perder fiabilidad ni coherencia.
PriceTrader_EA está diseñado para tomar decisiones comerciales basadas en datos de precios y el rendimiento histórico de las operaciones. Incorpora las siguientes características clave:
- Tamaño dinámico del lote: El Asesor Experto ajusta el tamaño de los lotes en función del resultado de las operaciones anteriores, duplicando el tamaño del lote después de una operación perdedora para recuperar las pérdidas (dentro de los límites predefinidos).
- Dirección de la operación basada en la acción del precio:PriceTrader_EA abre operaciones en la dirección de la tendencia predominante, según lo determinado por la acción del precio en el marco temporal H1.
- Gestión de riesgos: Los niveles de stop-loss (SL) y take-profit (TP) se calculan dinámicamente en función del spread actual, lo que garantiza la adaptabilidad a las condiciones cambiantes del mercado.
Comenzaremos incluyendo los archivos de encabezado de biblioteca HistoryManager.mqh y PositionsManager.mqh en la sección de encabezado de nuestro archivo fuente.
#include <Wanateki/Toolkit/HistoryManager/HistoryManager.mqh> #include <Wanateki/Toolkit/PositionsManager/PositionsManager.mqh>
A continuación, definiremos los parámetros de entrada para PriceTrader_EA. Estos parámetros nos permiten configurar el número mágico, los multiplicadores de spread para TP y SL, y el aumento máximo del tamaño del lote.
input ulong magicNo = 101010; input int tpSpreadMulti = 70; input int slSpreadMulti = 90; input int maxLotIncrease = 1000;
Inicializaremos las variables clave para almacenar información como el spread actual, el tamaño del lote, y el número de posiciones abiertas. Estas variables se utilizarán en toda la lógica del Asesor Experto.
bool eaJustLoaded = true; double spread; int spreadPips; long minSLTP = SymbolInfoInteger(Symbol(), SYMBOL_TRADE_STOPS_LEVEL); long freezeLevel = SymbolInfoInteger(Symbol(), SYMBOL_TRADE_FREEZE_LEVEL); double lotSize; int sl, tp; int totalOpenPositions, totalBuyPositionsOpen, totalSellPositionsOpen; //-- PositionData lastClosedPositionInfo;
En la función OnInit(), calcularemos el spread actual e inicializaremos los niveles TP y SL basándonos en los multiplicadores de spread. También reproduciremos un sonido para indicar que PriceTrader_EA se ha cargado correctamente.
int OnInit() { //--- spread = SymbolInfoDouble(_Symbol, SYMBOL_ASK) - SymbolInfoDouble(_Symbol, SYMBOL_BID); spread = NormalizeDouble(spread, _Digits); spreadPips = int(spread / _Point); tp = spreadPips * tpSpreadMulti; sl = spreadPips * slSpreadMulti; //-- PlaySound("connect.wav"); //--- return(INIT_SUCCEEDED); }
En la función OnDeinit(), borraremos los comentarios del gráfico y reproduciremos un sonido para indicar que PriceTrader_EA se ha descargado y eliminado del gráfico.
void OnDeinit(const int reason) { //--- Comment(""); PlaySound("disconnect.wav"); }
En la función OnDeinit(), borraremos los comentarios del gráfico y reproduciremos un sonido para indicar que PriceTrader_EA se ha descargado y eliminado del gráfico. Esto es lo que haremos en esta función:
- Recuperar el tamaño actual del lote y el número de posiciones abiertas.
- Comprueba si PriceTrader_EA se acaba de cargar y abre una operación inicial basada en la acción del precio H1.
- Ajuste el tamaño del lote y la dirección de la operación en función del resultado de la última operación cerrada.
- Abre operaciones consecutivas para aprovechar las tendencias rentables o recuperar pérdidas.
void OnTick() { //--- lotSize = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN); //-- totalOpenPositions = SymbolPositionsTotal(_Symbol, magicNo); totalBuyPositionsOpen = SymbolBuyPositionsTotal(_Symbol, magicNo); totalSellPositionsOpen = SymbolSellPositionsTotal(_Symbol, magicNo); if(eaJustLoaded && totalOpenPositions == 0) { //-- GetLastClosedPositionData(lastClosedPositionInfo, _Symbol, magicNo); if(lastClosedPositionInfo.ticket > 0 && lastClosedPositionInfo.profit < 0) { if(lastClosedPositionInfo.volume * 2 < lotSize * maxLotIncrease) lotSize = lastClosedPositionInfo.volume * 2; // double lot size } //-- if(iOpen(_Symbol, PERIOD_H1, 0) < iClose(_Symbol, PERIOD_H1, 0)) { OpenBuyPosition(magicNo, _Symbol, lotSize, sl, tp, "Initial_Position"); } else { OpenSellPosition(magicNo, _Symbol, lotSize, sl, tp, "Initial_Position"); } if(totalOpenPositions > 0) eaJustLoaded = false; } else { eaJustLoaded = false; } if(totalOpenPositions == 0 && !eaJustLoaded) { if(GetLastClosedPositionData(lastClosedPositionInfo, _Symbol, magicNo)) { if(lastClosedPositionInfo.profit > 0) // PROFITABLE TRADE { if(lastClosedPositionInfo.type == POSITION_TYPE_BUY) { OpenBuyPosition(magicNo, _Symbol, lotSize, sl, tp, "Consecutive Profit"); } else // SELL POSITION { OpenSellPosition(magicNo, _Symbol, lotSize, sl, tp, "Consecutive Profit"); } } else // LOSS TRADE { if(lastClosedPositionInfo.volume * 2 < lotSize * maxLotIncrease) lotSize = lastClosedPositionInfo.volume * 2; // double lot size //-- if(lastClosedPositionInfo.type == POSITION_TYPE_BUY) { // Reverse trade direction OpenSellPosition(magicNo, _Symbol, lotSize, sl, tp, "Loss Recovery"); } else // SELL POSITION { OpenBuyPosition(magicNo, _Symbol, lotSize, sl, tp, "Loss Recovery"); } } } }
PriceTrader_EA es ideal para usted si es el tipo de operador que prefiere o necesita una estrategia automatizada sencilla pero eficaz que siga las tendencias y cuente con una gestión dinámica del riesgo. Este EA está diseñado para recuperar pérdidas rápidamente mediante el ajuste adaptativo del tamaño de los lotes, lo que garantiza que su estrategia de trading siga siendo sólida incluso en condiciones de mercado desfavorables. Además, observará que PriceTrader_EA está codificado de forma inteligente para que las pruebas retrospectivas en MetaTrader 5 sean lo más sencillas y eficientes posible. Los datos introducidos por el usuario para el tamaño del lote, el stop loss y el take profit se ajustan automáticamente en función del símbolo cargado, lo que elimina la necesidad de realizar ajustes manuales y garantiza un rendimiento óptimo en diferentes instrumentos.
Encontrará el archivo fuente completo PriceTrader_EA.mq5 al final de este artículo, así como la biblioteca PositionsManager.ex5.
Prueba retrospectiva del asesor experto Price Trader
Realicemos una prueba retrospectiva en el probador de estrategias de MetaTrader 5 para ver cómo ha funcionado esta sencilla estrategia de trading durante los últimos catorce meses.
Estos son los ajustes que aplicaremos en el probador de estrategias:
-
Broker: Deriv
-
Servidor: Deriv-Demo
-
Símbolo: Volatility 50 (1s) Index
-
Marco temporal: Diario
-
Período de prueba (fecha): 1 año y 2 meses (enero de 2024 a febrero de 2025)
-
Modelado: Cada tick basado en ticks reales
-
Depósito: 5000 USD
-
Apalancamiento: 1:1000

Configuración de entradas:

Estos son los resultados de la prueba retrospectiva para PriceTrader_EA:






Al revisar los resultados de nuestras pruebas retrospectivas, PriceTrader_EA obtuvo una impresionante rentabilidad superior al 129 %, al tiempo que mantuvo una baja caída del capital de solo el 29 %. Esta estrategia sencilla pero eficaz demuestra un potencial significativo y puede perfeccionarse y optimizarse aún más para lograr resultados aún mejores. Dado que PriceTrader_EA ajusta dinámicamente sus entradas, como el tamaño del lote, el stop loss, y el take profit en función del símbolo o activo con el que opera, puede probarlo fácilmente en una cuenta demo. Simplemente cárguelo en un gráfico y observe su rendimiento durante un día o más para ver si genera beneficios, tal y como lo hizo durante nuestras evaluaciones con el probador de estrategias. Esta flexibilidad lo convierte en una herramienta excelente tanto para realizar pruebas como para operar en tiempo real.
Conclusión
Como se demuestra en este último artículo de la serie, la librería HistoryManager.ex5 es una herramienta potente y eficaz que simplifica el procesamiento de los historiales de operaciones en MetaTrader 5. Con su amplia gama de funciones, esta librería le permite acceder y gestionar sin esfuerzo datos relacionados con operaciones, órdenes, posiciones y órdenes pendientes, todo ello mediante sencillas llamadas a funciones de una sola línea. Este enfoque simplificado ahorra tiempo y esfuerzo, lo que le permite centrarse en desarrollar y optimizar sus estrategias de negociación.
A lo largo de este artículo, he proporcionado ejemplos prácticos de código para ayudarle a aprovechar todo el potencial de la librería HistoryManager.ex5. Estos ejemplos, junto con los conocimientos compartidos en esta serie, le han proporcionado las herramientas y los recursos necesarios para procesar algorítmicamente cualquier tipo de datos históricos generados a partir de sus actividades de trading en MetaTrader 5 utilizando MQL5. Como regalo de despedida para todos los lectores que me han seguido, he creado PriceTrader_EA, un asesor experto básico pero eficaz que muestra la aplicación práctica de algunos de estos conceptos.
Gracias por acompañarme en este viaje por el desarrollo de MQL5. Tu dedicación al aprendizaje y la exploración de estas herramientas es una prueba de tu compromiso con el dominio del arte del trading algorítmico. Como siempre, le deseo lo mejor en su búsqueda por desentrañar las complejidades de los mercados y alcanzar el éxito a través de sus desarrollos MQL5. ¡Feliz programación, y que tus estrategias siempre prosperen!
Recursos y archivos fuente
Todo el código mencionado en este artículo se proporciona a continuación para su comodidad. La tabla que se incluye aquí describe las librerías EX5 y los archivos de código fuente adjuntos, lo que facilita el acceso, la implementación y la exploración de los ejemplos comentados.
| Nombre del archivo | Descripciónption |
|---|---|
| HistoryManager.ex5 | Librería diseñada para procesar y gestionar historiales comerciales. |
| PositionsManager.ex5 | Librería para gestionar y procesar posiciones y órdenes. |
| HistoryManager.mqh | Archivo de encabezado utilizado para importar estructuras de datos y funciones prototipo desde la librería HistoryManager.ex5 a sus archivos fuente. |
| PositionsManager.mqh | Archivo de encabezado utilizado para importar funciones prototipo desde la librería PositionsManager.ex5 a sus archivos fuente. |
| GetProfitFactor.mq5 | Asesor experto que analiza el rendimiento de sus estrategias de trading calculando métricas clave como el beneficio bruto, la pérdida bruta y el factor de beneficio. |
| GetNetProfitThisWeek.mq5 | Script que calcula el beneficio neto de la semana actual. |
| GetSymbolPipsProfitToLossRatio.mq5 | Asesor experto que calcula la relación entre ganancias y pérdidas en pips para un símbolo de trading específico o para todo un asesor experto. |
| GetTotalDeposits.mq5 | Script que recupera y analiza datos de transacciones para proporcionar una visión general clara del historial de financiación o depósitos en efectivo de su cuenta. |
| PriceTrader_EA.mq5 | Un asesor experto basado en datos de precios que utiliza datos históricos de operaciones para detectar la dirección de los precios y recuperarse de las pérdidas. Desarrollado conjuntamente con las librerías PositionsManager.ex5 e HistoryManager.ex5. |
Traducción del inglés realizada por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/en/articles/17015
Advertencia: todos los derechos de estos materiales pertenecen a MetaQuotes Ltd. Queda totalmente prohibido el copiado total o parcial.
Este artículo ha sido escrito por un usuario del sitio web y refleja su punto de vista personal. MetaQuotes Ltd. no se responsabiliza de la exactitud de la información ofrecida, ni de las posibles consecuencias del uso de las soluciones, estrategias o recomendaciones descritas.
Desarrollo de un kit de herramientas para el análisis de la acción del precio (Parte 15): Introducción a la teoría de los cuartos (I) - Dibujando la teoría de cuartos
Características del Wizard MQL5 que debe conocer (Parte 56): Fractales de Bill Williams
Un nuevo enfoque para los criterios personalizados en las optimizaciones (Parte 1): Ejemplos de funciones de activación
Desarrollamos un asesor experto multidivisas (Parte 24): Añadimos una nueva estrategia (I)
- Aplicaciones de trading gratuitas
- 8 000+ señales para copiar
- Noticias económicas para analizar los mercados financieros
Usted acepta la política del sitio web y las condiciones de uso
Hola hini, gracias por tu interés en el artículo. Es rápido ya que devuelve los resultados consultados en milisegundos incluso trabajando con un gran número de órdenes históricas, pero eso depende de lo rápido que sea tu ordenador.