English Русский Deutsch 日本語
preview
Kit de herramientas de negociación MQL5 (Parte 3): Desarrollo de una biblioteca EX5 para la gestión de órdenes pendientes

Kit de herramientas de negociación MQL5 (Parte 3): Desarrollo de una biblioteca EX5 para la gestión de órdenes pendientes

MetaTrader 5Ejemplos |
236 0
Wanateki Solutions LTD
Kelvin Muturi Muigua

Introducción

En el primer y segundo artículo, se le presentó el desarrollo y la programación de bibliotecas EX5 desde cero, cómo crear documentación detallada para ayudar a los usuarios finales a implementarlas en sus proyectos MQL5, y recibió una demostración práctica paso a paso sobre cómo importarlas e implementarlas en diversas aplicaciones MQL5.

En este artículo, desarrollaremos una biblioteca integral de gestión de órdenes pendientes EX5 y crearemos un panel de interfaz gráfica de usuario (GUI) para demostrar cómo importar e implementar la biblioteca como un ejemplo práctico. Esta biblioteca de gestión de órdenes pendientes utilizará únicamente funciones estándar MQL5 para abrir, modificar y eliminar diferentes tipos de órdenes pendientes. Servirá como un valioso recurso de aprendizaje para los nuevos programadores MQL5 que buscan aprender a codificar módulos de gestión de órdenes pendientes desde simples hasta avanzados. También aprenderá a filtrar y ordenar pedidos pendientes según diferentes categorías.

Las funciones que creamos a continuación se exportarán y compilarán en la biblioteca EX5, lo que la convierte en un activo valioso que reducirá drásticamente el tiempo de desarrollo de futuros proyectos MQL5. Con solo importar la biblioteca Pending Orders Management EX5, puede implementar estas funciones, acortando significativamente tanto la base de código como el proceso general de desarrollo y codificación.


Crear un nuevo archivo de código fuente de la biblioteca EX5 (.mq5)

Para empezar, abra su MetaEditor IDE e inicie el asistente MQL utilizando el botón del menú «Nuevo». Necesitarás crear un nuevo archivo de código fuente de tipo Biblioteca, al que llamaremos PendingOrdersManager.mq5. Este archivo contendrá las funciones principales para gestionar órdenes pendientes. Guárdelo en la carpeta Libraries\Toolkit que configuramos en el primer artículo. Este es el mismo directorio donde guardamos anteriormente la biblioteca Positions Manager EX5, lo que nos permite mantener nuestro proyecto organizado y coherente.

PendingOrdersManager.mql5 Directorio guardado

Si necesita un repaso sobre cómo crear una biblioteca EX5 en MQL5, le recomiendo volver al primer artículo. Allí cubrimos el proceso paso a paso de configurar la estructura de carpetas y crear bibliotecas en detalle. Seguir ese enfoque no sólo ayudará a agilizar el desarrollo, sino que también facilitará el mantenimiento y la reutilización de sus bibliotecas en futuros proyectos MQL5.


Importaciones de bibliotecas EX5 del administrador de directivas de preprocesador, variables globales y posiciones

En nuestro archivo de código fuente de biblioteca PendingOrdersManager.mq5 recién creado, comenzaremos definiendo todas las directivas del preprocesador, las variables globales, las importaciones de bibliotecas y las estructuras de operaciones. Esto garantiza que estén disponibles en toda nuestra biblioteca de gestión de pedidos pendientes y que puedan reutilizarse en diversas funciones según sea necesario.

Comenzaremos definiendo una macro del preprocesador utilizando #define para crear una constante que represente una cadena en blanco. Esta constante, denominada ALL_SYMBOLS, actuará como marcador de posición en las funciones de gestión de órdenes pendientes que requieren una cadena de símbolos como parámetro de entrada. Al pasar esta cadena vacía, las funciones la interpretarán como un comando para aplicar la acción especificada a todos los símbolos disponibles, en lugar de solo a uno.

Este enfoque es simple pero muy efectivo, especialmente cuando se gestionan múltiples instrumentos, ya que agiliza el proceso de manejo de órdenes pendientes en diferentes símbolos. Para implementar esto, defina la constante ALL_SYMBOLS y colóquela directamente debajo de las directivas #property en su código.

#define ALL_SYMBOLS "" //-- Used as a function parameter to select all symbols

También necesitamos crear dos constantes adicionales: una para definir el número máximo de veces que podemos volver a intentar enviar una orden al servidor comercial si falla, y otra para establecer la duración del retraso entre los intentos de reintento. Esto ayuda a evitar saturar el servidor comercial con solicitudes rápidas y consecutivas. Nombraremos la primera constante MAX_ORDER_RETRIES y estableceremos su valor en 600. La segunda constante será ORDER_RETRY_DELAY, con un valor de 500 (milisegundos).

Esto significa que si no ocurre ningún error crítico, podemos intentar abrir, modificar o eliminar una orden hasta 600 veces. Después de cada intento, la función se detendrá durante medio segundo (500 milisegundos) antes de volver a intentarlo. Este retraso garantiza que no sobrecarguemos el servidor y que los recursos se utilicen de manera eficiente. También permite resolver cualquier retraso, como la inactividad del mercado o la falta de disponibilidad de datos de cotización, antes de agotar todos los intentos de reintento, lo que aumenta la probabilidad de que la ejecución de la orden se realice con éxito.

#define MAX_ORDER_RETRIES 600 //-- Sets the order sending retry limit
#define ORDER_RETRY_DELAYS 500//-- Sets the duration to pause before re-sending a failed order request in milliseconds

A continuación, añada las estructuras de datos MQL5 MqlTradeRequest y MqlTradeResult . Estas estructuras son importantes, ya que se encargarán de toda la comunicación con el servidor comercial cuando abramos, modifiquemos y eliminemos diferentes órdenes pendientes. La estructura tradeRequest se encargará de almacenar los detalles de la operación que vamos a ejecutar, incluyendo parámetros de la orden como el precio, el stop loss y el take profit. Mientras tanto, la estructura tradeResult capturará y guardará el resultado de la operación comercial, proporcionándonos información del servidor sobre si nuestra solicitud se ha realizado correctamente o si se ha producido un error.

//-- Trade operations request and result data structures global variables
MqlTradeRequest tradeRequest;
MqlTradeResult  tradeResult;

Para rastrear y almacenar el estado de varios pedidos pendientes, necesitamos crear varios tipos de variables que contendrán esta información de estado. Estas variables de estado de pedido se declararán como variables globales para garantizar que sean accesibles desde cualquier ámbito dentro de nuestra biblioteca, lo que permitirá que cualquier función haga referencia a ellas y las actualice según sea necesario. Inicializaremos estas variables con valores predeterminados cuando las declaremos y luego las actualizaremos con datos precisos en tiempo real dentro de la función GetPendingOrdersData(...), que desarrollaremos más adelante en este artículo. Esto garantizará que el estado de todas las órdenes pendientes se mantenga consistente y actualizado con precisión durante la ejecución de las funciones de llamada.

//-- Pending orders status global variables
//-------------------------------------------------------------------------------------------------------------------
int accountBuyStopOrdersTotal = 0, accountSellStopOrdersTotal = 0,
    accountBuyLimitOrdersTotal = 0, accountSellLimitOrdersTotal = 0,

    symbolPendingOrdersTotal = 0,
    symbolBuyStopOrdersTotal = 0, symbolSellStopOrdersTotal = 0,
    symbolBuyLimitOrdersTotal = 0, symbolSellLimitOrdersTotal = 0,

    magicPendingOrdersTotal = 0,
    magicBuyStopOrdersTotal = 0, magicSellStopOrdersTotal = 0,
    magicBuyLimitOrdersTotal = 0, magicSellLimitOrdersTotal = 0;

double accountPendingOrdersVolumeTotal = 0.0,
       accountBuyStopOrdersVolumeTotal = 0.0, accountSellStopOrdersVolumeTotal = 0.0,
       accountBuyLimitOrdersVolumeTotal = 0.0, accountSellLimitOrdersVolumeTotal = 0.0,

       symbolPendingOrdersVolumeTotal = 0.0,
       symbolBuyStopOrdersVolumeTotal = 0.0, symbolSellStopOrdersVolumeTotal = 0.0,
       symbolBuyLimitOrdersVolumeTotal = 0.0, symbolSellLimitOrdersVolumeTotal = 0.0,

       magicPendingOrdersVolumeTotal = 0.0,
       magicBuyStopOrdersVolumeTotal = 0.0, magicSellStopOrdersVolumeTotal = 0.0,
       magicBuyLimitOrdersVolumeTotal = 0.0, magicSellLimitOrdersVolumeTotal = 0.0;

Es común encontrar varios tipos de errores al abrir, modificar o eliminar pedidos. Para gestionar y resolver estos errores de manera eficiente, necesitaremos una función dedicada diseñada para gestionarlos. Además, necesitamos una función para verificar permisos comerciales críticos, como si nuestro Asesor Experto está autorizado para operar, si el comercio algorítmico está habilitado en la terminal o si nuestro corredor ha permitido el comercio algorítmico para la cuenta.

Afortunadamente, ya hemos desarrollado funciones similares en la biblioteca PositionsManager.ex5 de los artículos anteriores. En lugar de recrear estas funciones, simplemente importaremos esta biblioteca, lo que hará que estas funciones de gestión de errores y comprobación de permisos estén disponibles para su uso en nuestra biblioteca Pending Orders Manager. Importe las funciones ErrorAdvisor(...) y TradingIsAllowed().

//+----------------------------------------------------------------------------+
//| PositionsManager.ex5 imports                                               |
//+----------------------------------------------------------------------------+
#import "Toolkit/PositionsManager.ex5" //-- Opening import directive
//-- Function descriptions for the imported function prototypes

//-- Error Handling and Permission Status Functions
bool   ErrorAdvisor(string callingFunc, string symbol, int tradeServerErrorCode);
bool   TradingIsAllowed();

#import //--- Closing import directive


Función de impresión de detalles del pedido

La función PrintOrderDetails(...) registra información detallada sobre una solicitud de operación y la respuesta del servidor en el registro del Asesor Experto dentro de MetaTrader 5. Requiere dos parámetros de cadena: header, que contiene un mensaje personalizado, y symbol, que representa el símbolo o instrumento bursátil que se está procesando. La función genera un informe completo que incluye detalles esenciales de la orden, tales como el símbolo, el tipo de orden, el volumen, el precio, el stop loss, el take profit, el comentario, el número mágico y cualquier desviación. Además, registra información importante sobre el resultado de la operación, incluida la respuesta del servidor y cualquier error de tiempo de ejecución. El objetivo principal de esta función es ayudar en la depuración y supervisión de las operaciones comerciales, proporcionando una visión general clara y formateada de los parámetros y el estado de cada orden.

void PrintOrderDetails(string header, string symbol)
  {
   string orderDescription;
   int symbolDigits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS);
//-- Print the order details
   orderDescription += "_______________________________________________________________________________________\r\n";
   orderDescription += "--> "  + tradeRequest.symbol + " " + EnumToString(tradeRequest.type) + " " + header +
                       " <--\r\n";
   orderDescription += "Volume: " + StringFormat("%d", tradeRequest.volume) + "\r\n";
   orderDescription += "Price: " + DoubleToString(tradeRequest.price, symbolDigits) + "\r\n";
   orderDescription += "Stop Loss: " + DoubleToString(tradeRequest.sl, symbolDigits) + "\r\n";
   orderDescription += "Take Profit: " + DoubleToString(tradeRequest.tp, symbolDigits) + "\r\n";
   orderDescription += "Comment: " + tradeRequest.comment + "\r\n";
   orderDescription += "Magic Number: " + StringFormat("%d", tradeRequest.magic) + "\r\n";
   orderDescription += "Order filling: " + EnumToString(tradeRequest.type_filling)+ "\r\n";
   orderDescription += "Deviation points: " + StringFormat("%G", tradeRequest.deviation) + "\r\n";
   orderDescription += "RETCODE: " + (string)(tradeResult.retcode) + "\r\n";
   orderDescription += "Runtime Code: " + (string)(GetLastError()) + "\r\n";
   orderDescription += "---";
   Print(orderDescription);
  }


Función de apertura de Buy Limit

La función OpenBuyLimit(...) se encargará de colocar nuevas órdenes pendientes de compra limitada en la terminal de operaciones MetaTrader 5. Esta función garantiza que se cumplan todas las condiciones necesarias antes de enviar la solicitud de pedido, con un sistema integrado de gestión de errores para gestionar posibles problemas. Verifica que todos los parámetros sean válidos y cumplan con los requisitos del broker. Además, implementa un bucle de reintento, lo que aumenta la probabilidad de colocación exitosa de pedidos, lo que lo convierte en una herramienta confiable y eficiente para administrar pedidos pendientes. Las completas funciones de gestión de errores y registro de la función ayudan aún más a identificar y resolver los problemas que puedan surgir durante el proceso de realización de pedidos. La función devolverá un valor booleano de verdadero si abre correctamente una orden de compra limitada, y falso si la solicitud de la orden no se realiza correctamente.

¿Qué es una orden de compra limitada?


Una orden de compra limitada es una solicitud para comprar a un precio de venta igual o inferior al precio de entrada de la orden especificado. El precio de entrada del límite de compra es válido solo cuando el precio de mercado actual es mayor que el precio de entrada de la orden. Este tipo de orden es útil cuando usted anticipa que el precio del símbolo caerá hasta el nivel de entrada deseado y luego subirá, permitiéndole beneficiarse del movimiento ascendente.

Orden de límite de compra

Comencemos definiendo la función, que aceptará siete parámetros, cada uno con un rol específico en el proceso de colocación de una orden de compra limitada. La función será exportable, lo que permitirá acceder a ella externamente en la biblioteca EX5. Estos parámetros son:

  1. magicNumber (unsigned long): Un identificador único para la operación, utilizado para distinguir las órdenes realizadas por nuestro Asesor Experto de otras.
  2. symbol (string): El instrumento o símbolo de negociación (como EURUSD) para el que se colocará la orden.
  3. entryPrice (double): El nivel de precio al que se activará la orden de compra limitada. Este es el precio objetivo al que desea comprar el activo.
  4. lotSize (double): El volumen o tamaño de la orden que se va a realizar, que representa cuántos lotes del activo se negociarán.
  5. sl (int): El valor del stop loss, medido en pips. Esto define la pérdida máxima que puede sufrir la operación antes de cerrarse automáticamente.
  6. tp (int): El valor de take profit, también medido en pips. Esto define el nivel de precio en el que las ganancias se asegurarán automáticamente al cerrar la orden.
  7. orderComment (string): Un comentario o nota adjunta al pedido con fines de identificación o seguimiento.
bool OpenBuyLimit(ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment) export
  {

Después de definir la función y sus parámetros, el primer paso de la función es comprobar si el trading algorítmico o con asesores expertos está habilitado en MetaTrader 5. Si está deshabilitada, saldremos de la función inmediatamente, impidiendo que se realice el pedido.

if(!TradingIsAllowed())
     {
      return(false); //--- algo trading is disabled, exit function
     }

A continuación, creamos las variables tpPrice y slPrice para guardar los valores de los precios de take profit y stop loss, y luego recuperamos información clave sobre el símbolo de negociación, como el número de decimales (dígitos), el nivel mínimo de stop y el spread. Estos detalles nos ayudarán a garantizar que el precio de entrada y los parámetros de la orden estén correctamente configurados para el símbolo elegido.

double tpPrice = 0.0, slPrice = 0.0;

//-- Get some information about the orders symbol
   int symbolDigits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS);
   int symbolStopLevel = (int)SymbolInfoInteger(symbol, SYMBOL_TRADE_STOPS_LEVEL);
   double symbolPoint = SymbolInfoDouble(symbol, SYMBOL_POINT);
   int spread = (int)SymbolInfoInteger(symbol, SYMBOL_SPREAD);

//-- Save the order type enumeration
   ENUM_ORDER_TYPE orderType = ORDER_TYPE_BUY_LIMIT;

Antes de enviar la orden, debemos comprobar si el precio de entrada es válido, asegurándonos de que no esté demasiado cerca del precio de mercado ni por debajo del nivel de stop del bróker. Si el precio no es válido, registraremos un error y saldremos de la función.

//-- check if the entry price is valid
   if(
      SymbolInfoDouble(symbol, SYMBOL_ASK) - (symbolStopLevel * symbolPoint) <
      entryPrice + (spread * symbolPoint)
   )
     {
      Print(
         "\r\n", __FUNCTION__, ": Can't open a new ", EnumToString(orderType),
         ". (Reason --> INVALID ENTRY PRICE: ", DoubleToString(entryPrice, symbolDigits), ")\r\n"
      );
      return(false); //-- Invalid entry price, log the error, exit the function and return false
     }

Asegurémonos de que los valores de stop loss (SL) y take profit (TP) cumplan con los requisitos mínimos del bróker. Si es necesario, ajustaremos el SL y el TP para cumplir con estas reglas antes de continuar.

//-- Check the validity of the sl and tp
   if(sl > 0 && sl < symbolStopLevel)
     {
      sl = symbolStopLevel;
     }
   if(tp > 0 && tp < symbolStopLevel)
     {
      tp = symbolStopLevel;
     }

   slPrice = (sl > 0) ? NormalizeDouble(entryPrice - sl * symbolPoint, symbolDigits) : 0;
   tpPrice = (tp > 0) ? NormalizeDouble(entryPrice + tp * symbolPoint, symbolDigits) : 0;

Una vez que hayamos validado el precio y otros parámetros, prepararemos la estructura tradeRequest con detalles como el tipo de orden, el símbolo, el precio, el volumen, el stop loss, el take profit y un comentario. También nos aseguraremos de que el tamaño del lote esté dentro de los límites permitidos por el corredor y restableceremos cualquier resultado o error comercial anterior.

//-- reset the the tradeRequest and tradeResult values by zeroing them
   ZeroMemory(tradeRequest);
   ZeroMemory(tradeResult);

//-- initialize the parameters to open a buy limit order
   tradeRequest.type = orderType;
   tradeRequest.action = TRADE_ACTION_PENDING;
   tradeRequest.magic = magicNumber;
   tradeRequest.symbol = symbol;
   tradeRequest.price = NormalizeDouble(entryPrice, symbolDigits);
   tradeRequest.tp = tpPrice;
   tradeRequest.sl = slPrice;
   tradeRequest.comment = orderComment;
   tradeRequest.deviation = SymbolInfoInteger(symbol, SYMBOL_SPREAD) * 2;

//-- Set and moderate the lot size or volume
//-- Verify that volume is not less than allowed minimum
   lotSize = MathMax(lotSize, SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN));

//-- Verify that volume is not more than allowed maximum
   lotSize = MathMin(lotSize, SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX));

//-- Round down to nearest volume step
   lotSize = MathFloor(lotSize / SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP)) * SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP);
   tradeRequest.volume = lotSize;

//--- Reset error cache so that we get an accurate runtime error code in the ErrorAdvisor function
   ResetLastError();

Si la solicitud de orden es válida, intentaremos enviarla al servidor comercial del bróker. Si el envío del pedido falla, volveremos a intentar reenviar la solicitud de pedido hasta 600 veces, con una pausa de medio segundo (500 milisegundos) entre cada intento, para garantizar que el pedido se realice correctamente. Este mecanismo de reintento aumenta en gran medida las posibilidades de abrir exitosamente el pedido, especialmente en casos de problemas temporales de red o servidor.

Si el pedido se realiza correctamente, registraremos los detalles del pedido y confirmaremos que el servidor comercial lo ha procesado. Si el pedido falla incluso después de varios intentos, utilizaremos la función ErrorAdvisor(..) que hemos importado de la biblioteca PositionsManager.ex5 para diagnosticar el problema y devolveremos false para indicar que el pedido no se ha realizado.

for(int loop = 0; loop <= MAX_ORDER_RETRIES; loop++) //-- try opening the order until it is successful
     {
      //--- send order to the trade server
      if(OrderSend(tradeRequest, tradeResult))
        {
         //-- Print the order details
         PrintOrderDetails("Sent OK", symbol);

         //-- Confirm order execution
         if(tradeResult.retcode == 10008 || tradeResult.retcode == 10009)
           {
            Print(
               __FUNCTION__, ": CONFIRMED: Successfully openend a ", symbol,
               " ", EnumToString(orderType), " #", tradeResult.order, ", Price: ", tradeResult.price
            );
            PrintFormat("retcode=%u  deal=%I64u  order=%I64u", tradeResult.retcode, tradeResult.deal, tradeResult.order);
            Print("_______________________________________________________________________________________");
            return(true); //-- exit the function
            //break; //--- success - order placed ok. exit the for loop
           }
        }
      else //-- Order request failed
        {
         //-- Print the order details
         PrintOrderDetails("Sending Failed", symbol);

         //-- order not sent or critical error found
         if(!ErrorAdvisor(__FUNCTION__, symbol, tradeResult.retcode) || IsStopped())
           {
            Print(
               __FUNCTION__, ": ", symbol, " ERROR opening a ", EnumToString(orderType),
               " at: ", tradeRequest.price, ", Lot\\Vol: ", tradeRequest.volume
            );
            Print("_______________________________________________________________________________________");
            return(false); //-- exit the function
            //break; //-- exit the for loop

            Sleep(ORDER_RETRY_DELAYS);//-- Small pause before retrying to avoid overwhelming the trade server
           }
        }
     }

Aquí está la función completa con todos los segmentos de código en la secuencia correcta. Asegúrese de que su función OpenBuyLimit(...) contenga el siguiente código completo.

bool OpenBuyLimit(ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment) export
  {
//-- first check if the EA is allowed to trade
   if(!TradingIsAllowed())
     {
      return(false); //--- algo trading is disabled, exit function
     }

   double tpPrice = 0.0, slPrice = 0.0;

//-- Get some information about the orders symbol
   int symbolDigits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS);
   int symbolStopLevel = (int)SymbolInfoInteger(symbol, SYMBOL_TRADE_STOPS_LEVEL);
   double symbolPoint = SymbolInfoDouble(symbol, SYMBOL_POINT);
   int spread = (int)SymbolInfoInteger(symbol, SYMBOL_SPREAD);

//-- Save the order type enumeration
   ENUM_ORDER_TYPE orderType = ORDER_TYPE_BUY_LIMIT;

//-- check if the entry price is valid
   if(
      SymbolInfoDouble(symbol, SYMBOL_ASK) - (symbolStopLevel * symbolPoint) <
      entryPrice + (spread * symbolPoint)
   )
     {
      Print(
         "\r\n", __FUNCTION__, ": Can't open a new ", EnumToString(orderType),
         ". (Reason --> INVALID ENTRY PRICE: ", DoubleToString(entryPrice, symbolDigits), ")\r\n"
      );
      return(false); //-- Invalid entry price, log the error, exit the function and return false
     }

//-- Check the validity of the sl and tp
   if(sl > 0 && sl < symbolStopLevel)
     {
      sl = symbolStopLevel;
     }
   if(tp > 0 && tp < symbolStopLevel)
     {
      tp = symbolStopLevel;
     }

   slPrice = (sl > 0) ? NormalizeDouble(entryPrice - sl * symbolPoint, symbolDigits) : 0;
   tpPrice = (tp > 0) ? NormalizeDouble(entryPrice + tp * symbolPoint, symbolDigits) : 0;

//-- reset the the tradeRequest and tradeResult values by zeroing them
   ZeroMemory(tradeRequest);
   ZeroMemory(tradeResult);

//-- initialize the parameters to open a buy limit order
   tradeRequest.type = orderType;
   tradeRequest.action = TRADE_ACTION_PENDING;
   tradeRequest.magic = magicNumber;
   tradeRequest.symbol = symbol;
   tradeRequest.price = NormalizeDouble(entryPrice, symbolDigits);
   tradeRequest.tp = tpPrice;
   tradeRequest.sl = slPrice;
   tradeRequest.comment = orderComment;
   tradeRequest.deviation = SymbolInfoInteger(symbol, SYMBOL_SPREAD) * 2;

//-- Set and moderate the lot size or volume
//-- Verify that volume is not less than allowed minimum
   lotSize = MathMax(lotSize, SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN));

//-- Verify that volume is not more than allowed maximum
   lotSize = MathMin(lotSize, SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX));

//-- Round down to nearest volume step
   lotSize = MathFloor(lotSize / SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP)) * SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP);
   tradeRequest.volume = lotSize;

//--- Reset error cache so that we get an accurate runtime error code in the ErrorAdvisor function
   ResetLastError();

   for(int loop = 0; loop <= MAX_ORDER_RETRIES; loop++) //-- try opening the order until it is successful
     {
      //--- send order to the trade server
      if(OrderSend(tradeRequest, tradeResult))
        {
         //-- Print the order details
         PrintOrderDetails("Sent OK", symbol);

         //-- Confirm order execution
         if(tradeResult.retcode == 10008 || tradeResult.retcode == 10009)
           {
            Print(
               __FUNCTION__, ": CONFIRMED: Successfully openend a ", symbol,
               " ", EnumToString(orderType), " #", tradeResult.order, ", Price: ", tradeResult.price
            );
            PrintFormat("retcode=%u  deal=%I64u  order=%I64u", tradeResult.retcode, tradeResult.deal, tradeResult.order);
            Print("_______________________________________________________________________________________");
            return(true); //-- exit the function
            //break; //--- success - order placed ok. exit the for loop
           }
        }
      else //-- Order request failed
        {
         //-- Print the order details
         PrintOrderDetails("Sending Failed", symbol);

         //-- order not sent or critical error found
         if(!ErrorAdvisor(__FUNCTION__, symbol, tradeResult.retcode) || IsStopped())
           {
            Print(
               __FUNCTION__, ": ", symbol, " ERROR opening a ", EnumToString(orderType),
               " at: ", tradeRequest.price, ", Lot\\Vol: ", tradeRequest.volume
            );
            Print("_______________________________________________________________________________________");
            return(false); //-- exit the function
            //break; //-- exit the for loop

            Sleep(ORDER_RETRY_DELAYS);//-- Small pause before retrying to avoid overwhelming the trade server
           }
        }
     }
   return(false);
  }


Función de apertura Buy Stop

La función OpenBuyStop(...) se encarga de colocar nuevas órdenes pendientes Buy Stop. Sigue un enfoque similar al de la función OpenBuyLimit(...) descrita anteriormente. La función devolverá true si coloca correctamente una orden de compra stop, y false si la solicitud de la orden falla.

¿Qué es una orden Buy Stop?


Una orden de compra stop es una solicitud de compra a un precio Ask igual o superior al precio de entrada de la orden especificado. El precio de entrada de la orden de compra stop solo es válido cuando el precio actual del mercado es inferior al precio de entrada de la orden. Este tipo de orden es útil cuando anticipas que el precio del símbolo aumentará hasta el nivel de entrada especificado y luego continuará moviéndose hacia arriba, lo que te permitirá sacar provecho de la tendencia alcista.

Orden de stop de compra

A continuación se muestra la función OpenBuyStop(...), con comentarios explicativos añadidos para ayudarle a comprender rápidamente cómo funciona cada parte del código.

bool OpenBuyStop(ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment) export
  {
//-- first check if the EA is allowed to trade
   if(!TradingIsAllowed())
     {
      return(false); //--- algo trading is disabled, exit function
     }

   double tpPrice = 0.0, slPrice = 0.0;

//-- Get some information about the orders symbol
   int symbolDigits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS);
   int symbolStopLevel = (int)SymbolInfoInteger(symbol, SYMBOL_TRADE_STOPS_LEVEL);
   double symbolPoint = SymbolInfoDouble(symbol, SYMBOL_POINT);
   int spread = (int)SymbolInfoInteger(symbol, SYMBOL_SPREAD);

//-- Save the order type enumeration
   ENUM_ORDER_TYPE orderType = ORDER_TYPE_BUY_STOP;

//-- check if the entry price is valid
   if(
      SymbolInfoDouble(symbol, SYMBOL_ASK) + (symbolStopLevel * symbolPoint) >
      entryPrice + (spread * symbolPoint)
   )
     {
      Print(
         "\r\n", __FUNCTION__, ": Can't open a new ", EnumToString(orderType),
         ". (Reason --> INVALID ENTRY PRICE: ", DoubleToString(entryPrice, symbolDigits), ")\r\n"
      );
      return(false); //-- Invalid entry price, log the error, exit the function and return false
     }


//--- Validate Stop Loss (sl) and Take Profit (tp)
   if(sl > 0 && sl < symbolStopLevel)
     {
      sl = symbolStopLevel;
     }
   if(tp > 0 && tp < symbolStopLevel)
     {
      tp = symbolStopLevel;
     }

   slPrice = (sl > 0) ? NormalizeDouble(entryPrice - sl * symbolPoint, symbolDigits) : 0;
   tpPrice = (tp > 0) ? NormalizeDouble(entryPrice + tp * symbolPoint, symbolDigits) : 0;

//-- reset the the tradeRequest and tradeResult values by zeroing them
   ZeroMemory(tradeRequest);
   ZeroMemory(tradeResult);

//-- initialize the parameters to open a buy stop order
   tradeRequest.type = orderType;
   tradeRequest.action = TRADE_ACTION_PENDING;
   tradeRequest.magic = magicNumber;
   tradeRequest.symbol = symbol;
   tradeRequest.price = NormalizeDouble(entryPrice, symbolDigits);
   tradeRequest.tp = tpPrice;
   tradeRequest.sl = slPrice;
   tradeRequest.comment = orderComment;
   tradeRequest.deviation = SymbolInfoInteger(symbol, SYMBOL_SPREAD) * 2;

//-- Set and moderate the lot size or volume
//-- Verify that volume is not less than allowed minimum
   lotSize = MathMax(lotSize, SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN));

//-- Verify that volume is not more than allowed maximum
   lotSize = MathMin(lotSize, SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX));

//-- Round down to nearest volume step
   lotSize = MathFloor(lotSize / SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP)) * SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP);
   tradeRequest.volume = lotSize;

//--- Reset error cache so that we get an accurate runtime error code in the ErrorAdvisor function
   ResetLastError();

   for(int loop = 0; loop <= MAX_ORDER_RETRIES; loop++) //-- try opening the order until it is successful
     {
      //--- send order to the trade server
      if(OrderSend(tradeRequest, tradeResult))
        {
         //-- Print the order details
         PrintOrderDetails("Sent OK", symbol);

         //-- Confirm order execution
         if(tradeResult.retcode == 10008 || tradeResult.retcode == 10009)
           {
            Print(
               __FUNCTION__, ": CONFIRMED: Successfully openend a ", symbol,
               " ", EnumToString(orderType), " #", tradeResult.order, ", Price: ", tradeResult.price
            );
            PrintFormat("retcode=%u  deal=%I64u  order=%I64u", tradeResult.retcode, tradeResult.deal, tradeResult.order);
            Print("_______________________________________________________________________________________");
            return(true); //-- exit the function
            //break; //--- success - order placed ok. exit the for loop
           }
        }
      else //-- Order request failed
        {
         //-- Print the order details
         PrintOrderDetails("Sending Failed", symbol);

         //-- order not sent or critical error found
         if(!ErrorAdvisor(__FUNCTION__, symbol, tradeResult.retcode) || IsStopped())
           {
            Print(
               __FUNCTION__, ": ", symbol, " ERROR opening a ", EnumToString(orderType),
               " at: ", tradeRequest.price, ", Lot\\Vol: ", tradeRequest.volume
            );
            Print("_______________________________________________________________________________________");
            return(false); //-- exit the function
            //break; //-- exit the for loop

            Sleep(ORDER_RETRY_DELAYS);//-- Small pause before retrying to avoid overwhelming the trade server
           }
        }
     }
   return(false);
  }


Función de apertura de Sell Limit

La función OpenSellLimit(...) se encarga de colocar nuevas órdenes pendientes de límite de venta. La función devuelve true cuando se coloca correctamente una orden de venta limitada, y false si la solicitud de la orden no se realiza correctamente.

¿Qué es una orden Sell Limit?


Una orden de venta limitada es una solicitud para vender a un precio Bid igual o superior al precio de entrada de la orden especificado. El precio de entrada del límite de venta es válido solo cuando el precio de mercado actual es inferior al precio de entrada de la orden. Este tipo de orden es útil cuando espera que el precio del símbolo suba hasta el nivel de precio de entrada especificado y luego revierta la dirección, lo que le permite obtener ganancias del movimiento bajista anticipado o la tendencia bajista.

Orden de venta limitada

A continuación se muestra la función OpenSellLimit(...), con comentarios explicativos para ayudarle a comprender mejor cómo funciona cada parte del código.

bool OpenSellLimit(ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment) export
  {
//-- first check if the EA is allowed to trade
   if(!TradingIsAllowed())
     {
      return(false); //--- algo trading is disabled, exit function
     }

   double tpPrice = 0.0, slPrice = 0.0;

//-- Get some information about the orders symbol
   int symbolDigits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS);
   int symbolStopLevel = (int)SymbolInfoInteger(symbol, SYMBOL_TRADE_STOPS_LEVEL);
   double symbolPoint = SymbolInfoDouble(symbol, SYMBOL_POINT);
   int spread = (int)SymbolInfoInteger(symbol, SYMBOL_SPREAD);

//-- Save the order type enumeration
   ENUM_ORDER_TYPE orderType = ORDER_TYPE_SELL_LIMIT;

//-- check if the entry price is valid
   if(
      SymbolInfoDouble(symbol, SYMBOL_BID) + (symbolStopLevel * symbolPoint) >
      entryPrice - (spread * symbolPoint)
   )
     {
      Print(
         "\r\n", __FUNCTION__, ": Can't open a new ", EnumToString(orderType),
         ". (Reason --> INVALID ENTRY PRICE: ", DoubleToString(entryPrice, symbolDigits), ")\r\n"
      );
      return(false); //-- Invalid entry price, log the error, exit the function and return false
     }

//-- Check the validity of the sl and tp
   if(sl > 0 && sl < symbolStopLevel)
     {
      sl = symbolStopLevel;
     }
   if(tp > 0 && tp < symbolStopLevel)
     {
      tp = symbolStopLevel;
     }

   slPrice = (sl > 0) ? NormalizeDouble(entryPrice + sl * symbolPoint, symbolDigits) : 0;
   tpPrice = (tp > 0) ? NormalizeDouble(entryPrice - tp * symbolPoint, symbolDigits) : 0;

//-- reset the the tradeRequest and tradeResult values by zeroing them
   ZeroMemory(tradeRequest);
   ZeroMemory(tradeResult);

//-- initialize the parameters to open a sell limit order
   tradeRequest.type = orderType;
   tradeRequest.action = TRADE_ACTION_PENDING;
   tradeRequest.magic = magicNumber;
   tradeRequest.symbol = symbol;
   tradeRequest.price = NormalizeDouble(entryPrice, symbolDigits);
   tradeRequest.tp = tpPrice;
   tradeRequest.sl = slPrice;
   tradeRequest.comment = orderComment;
   tradeRequest.deviation = SymbolInfoInteger(symbol, SYMBOL_SPREAD) * 2;

//-- Set and moderate the lot size or volume
//-- Verify that volume is not less than allowed minimum
   lotSize = MathMax(lotSize, SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN));

//-- Verify that volume is not more than allowed maximum
   lotSize = MathMin(lotSize, SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX));

//-- Round down to nearest volume step
   lotSize = MathFloor(lotSize / SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP)) * SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP);
   tradeRequest.volume = lotSize;

//--- Reset error cache so that we get an accurate runtime error code in the ErrorAdvisor function
   ResetLastError();

   for(int loop = 0; loop <= MAX_ORDER_RETRIES; loop++) //-- try opening the order until it is successful
     {
      //--- send order to the trade server
      if(OrderSend(tradeRequest, tradeResult))
        {
         //-- Print the order details
         PrintOrderDetails("Sent OK", symbol);

         //-- Confirm order execution
         if(tradeResult.retcode == 10008 || tradeResult.retcode == 10009)
           {
            Print(
               __FUNCTION__, ": CONFIRMED: Successfully openend a ", symbol,
               " ", EnumToString(orderType), " #", tradeResult.order, ", Price: ", tradeResult.price
            );
            PrintFormat("retcode=%u  deal=%I64u  order=%I64u", tradeResult.retcode, tradeResult.deal, tradeResult.order);
            Print("_______________________________________________________________________________________");
            return(true); //-- exit the function
            //break; //--- success - order placed ok. exit the for loop
           }
        }
      else //-- Order request failed
        {
         //-- Print the order details
         PrintOrderDetails("Sending Failed", symbol);

         //-- order not sent or critical error found
         if(!ErrorAdvisor(__FUNCTION__, symbol, tradeResult.retcode) || IsStopped())
           {
            Print(
               __FUNCTION__, ": ", symbol, " ERROR opening a ", EnumToString(orderType),
               " at: ", tradeRequest.price, ", Lot\\Vol: ", tradeRequest.volume
            );
            Print("_______________________________________________________________________________________");
            return(false); //-- exit the function
            //break; //-- exit the for loop

            Sleep(ORDER_RETRY_DELAYS);//-- Small pause before retrying to avoid overwhelming the trade server
           }
        }
     }
   return(false);
  }


Función de apertura Sell Stop

La función OpenSellStop(...) está diseñada para colocar nuevas órdenes pendientes Sell Stop. La función devuelve true cuando se coloca correctamente una orden de venta stop, lo que indica que la solicitud se ha procesado sin problemas. Si el envío del pedido falla por cualquier motivo, devuelve false, lo que indica que el intento no se ha realizado correctamente.

¿Qué es una orden Sell Stop?


Una orden de venta stop es una solicitud para vender a un precio Bid igual o inferior al precio de entrada de la orden especificado. El precio de entrada de stop de venta solo es válido cuando el precio de mercado actual es mayor que el precio de entrada de la orden. Este tipo de orden es útil cuando usted anticipa que el precio de un símbolo caerá al nivel de entrada especificado y luego continuará bajando, lo que le permitirá beneficiarse del movimiento bajista esperado o la tendencia bajista.

Orden de stop de venta

A continuación se proporciona la función OpenSellStop(...), junto con comentarios detallados que le guiarán a través de la funcionalidad de cada parte del código.

bool OpenSellStop(ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment) export
  {
//-- first check if the EA is allowed to trade
   if(!TradingIsAllowed())
     {
      return(false); //--- algo trading is disabled, exit function
     }

   double slPrice = 0.0, tpPrice = 0.0;

//-- Get some information about the orders symbol
   int symbolDigits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS);
   int symbolStopLevel = (int)SymbolInfoInteger(symbol, SYMBOL_TRADE_STOPS_LEVEL);
   double symbolPoint = SymbolInfoDouble(symbol, SYMBOL_POINT);
   int spread = (int)SymbolInfoInteger(symbol, SYMBOL_SPREAD);

//-- Save the order type enumeration
   ENUM_ORDER_TYPE orderType = ORDER_TYPE_SELL_STOP;

//-- check if the entry price is valid
   if(
      SymbolInfoDouble(symbol, SYMBOL_BID) - (symbolStopLevel * symbolPoint) <
      entryPrice - (spread * symbolPoint)
   )
     {
      Print(
         "\r\n", __FUNCTION__, ": Can't open a new ", EnumToString(orderType),
         ". (Reason --> INVALID ENTRY PRICE: ", DoubleToString(entryPrice, symbolDigits), ")\r\n"
      );
      return(false); //-- Invalid entry price, log the error, exit the function and return false
     }

//-- Check the validity of the sl and tp
   if(sl > 0 && sl < symbolStopLevel)
     {
      sl = symbolStopLevel;
     }
   if(tp > 0 && tp < symbolStopLevel)
     {
      tp = symbolStopLevel;
     }

   slPrice = (sl > 0) ? NormalizeDouble(entryPrice + sl * symbolPoint, symbolDigits) : 0;
   tpPrice = (tp > 0) ? NormalizeDouble(entryPrice - tp * symbolPoint, symbolDigits) : 0;

//-- reset the the tradeRequest and tradeResult values by zeroing them
   ZeroMemory(tradeRequest);
   ZeroMemory(tradeResult);

//-- initialize the parameters to open a sell stop order
   tradeRequest.type = orderType;
   tradeRequest.action = TRADE_ACTION_PENDING;
   tradeRequest.magic = magicNumber;
   tradeRequest.symbol = symbol;
   tradeRequest.price = NormalizeDouble(entryPrice, symbolDigits);
   tradeRequest.tp = tpPrice;
   tradeRequest.sl = slPrice;
   tradeRequest.comment = orderComment;
   tradeRequest.deviation = SymbolInfoInteger(symbol, SYMBOL_SPREAD) * 2;

//-- Set and moderate the lot size or volume
//-- Verify that volume is not less than allowed minimum
   lotSize = MathMax(lotSize, SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN));

//-- Verify that volume is not more than allowed maximum
   lotSize = MathMin(lotSize, SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX));

//-- Round down to nearest volume step
   lotSize = MathFloor(lotSize / SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP)) * SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP);
   tradeRequest.volume = lotSize;

//--- Reset error cache so that we get an accurate runtime error code in the ErrorAdvisor function
   ResetLastError();

   for(int loop = 0; loop <= MAX_ORDER_RETRIES; loop++) //-- try opening the order until it is successful
     {
      //--- send order to the trade server
      if(OrderSend(tradeRequest, tradeResult))
        {
         //-- Print the order details
         PrintOrderDetails("Sent OK", symbol);

         //-- Confirm order execution
         if(tradeResult.retcode == 10008 || tradeResult.retcode == 10009)
           {
            Print(
               __FUNCTION__, ": CONFIRMED: Successfully openend a ", symbol,
               " ", EnumToString(orderType), " #", tradeResult.order, ", Price: ", tradeResult.price
            );
            PrintFormat("retcode=%u  deal=%I64u  order=%I64u", tradeResult.retcode, tradeResult.deal, tradeResult.order);
            Print("_______________________________________________________________________________________");
            return(true); //-- exit the function
            //break; //--- success - order placed ok. exit the for loop
           }
        }
      else //-- Order request failed
        {
         //-- Print the order details
         PrintOrderDetails("Sending Failed", symbol);

         //-- order not sent or critical error found
         if(!ErrorAdvisor(__FUNCTION__, symbol, tradeResult.retcode) || IsStopped())
           {
            Print(
               __FUNCTION__, ": ", symbol, " ERROR opening a ", EnumToString(orderType),
               " at: ", tradeRequest.price, ", Lot\\Vol: ", tradeRequest.volume
            );
            Print("_______________________________________________________________________________________");
            return(false); //-- exit the function
            //break; //-- exit the for loop

            Sleep(ORDER_RETRY_DELAYS);//-- Small pause before retrying to avoid overwhelming the trade server
           }
        }
     }
   return(false);
  }


Modificar orden pendiente mediante la función de ticket

La función ModifyPendingOrderByTicket(...) está diseñada para modificar el stop-loss (SL), el take-profit (TP) o el precio de entrada de una orden pendiente activa. Realiza validaciones para garantizar que las modificaciones estén dentro de las reglas del broker, registra el progreso y cualquier error que pueda ocurrir, y utiliza un mecanismo de reintento para intentar la modificación varias veces en caso de falla o condiciones de entrada de órdenes desfavorables.

La función acepta cuatro parámetros:

  1. orderTicket (ulong): El identificador único del pedido. Este número de ticket se utiliza para hacer referencia al pedido específico que desea modificar.
  2. newEntryPrice (double): El nuevo precio de entrada para la orden pendiente. Si el valor se establece en 0, la función conservará el precio de entrada actual.
  3. newSl (int): El nuevo valor de stop-loss (SL), expresado en puntos. Si el valor se establece en 0, el SL se eliminará o permanecerá sin cambios.
  4. newTp (int): El nuevo valor de take-profit (TP), expresado en puntos. Si el valor se establece en 0, el TP se eliminará o permanecerá sin cambios.

Esta función será de tipo bool y se espera que devuelva un valor booleano true si la orden se modifica correctamente o un valor booleano false si la modificación falla, ya sea debido a parámetros no válidos, errores en la selección de la orden o problemas con el servidor. Comencemos codificando la definición de función a continuación.

bool ModifyPendingOrderByTicket(ulong orderTicket, double newEntryPrice, int newSl, int newTp) export
  {

Antes de modificar la orden, debemos asegurarnos de que el entorno comercial permita el comercio algorítmico. Utilizaremos la función TradingIsAllowed() para confirmarlo.

if(!TradingIsAllowed())
     {
      return(false); //--- algo trading is disabled, exit function
     }

Para asegurarnos de que estamos modificando la orden correcta, debemos seleccionar la orden utilizando la función estándar MQL5 OrderSelect() y el parámetro de función orderTicket proporcionado. Si el ticket de pedido no es válido o no se selecciona correctamente, registraremos este error y saldremos de la función, devolviendo un valor booleano de false. Si la selección del ticket del pedido es exitosa, imprimiremos un breve mensaje de registro y procederemos a procesar el pedido.

//--- Confirm and select the order using the provided orderTicket
   ResetLastError(); //--- Reset error cache incase of ticket selection errors
   if(OrderSelect(orderTicket))
     {
      //---Order selected
      Print("\r\n_______________________________________________________________________________________");
      Print(__FUNCTION__, ": Order with ticket:", orderTicket, " selected and ready to set SLTP.");
     }
   else
     {
      Print("\r\n_______________________________________________________________________________________");
      Print(__FUNCTION__, ": Selecting order with ticket:", orderTicket, " failed. ERROR: ", GetLastError());
      return(false); //-- Exit the function
     }

Una vez seleccionada la orden, crearemos algunas variables de tipo double para almacenar nuestro precio de toma de ganancias (TP) y precio de stop loss (SL) y las inicializaremos con valores predeterminados de cero (0.0). A continuación, obtendremos los detalles del pedido (como el símbolo, el volumen, el SL/TP actual, etc.) que serán necesarios para la validación y la modificación.

double newTpPrice = 0.0, newSlPrice = 0.0;

//--- Order ticket selected, save the order properties
   string orderSymbol = OrderGetString(ORDER_SYMBOL);
   double currentEntryPrice = OrderGetDouble(ORDER_PRICE_OPEN);
   double volume = OrderGetDouble(ORDER_VOLUME_INITIAL);
   double currentOrderSlPrice = OrderGetDouble(ORDER_SL);
   double currentOrderTpPrice = OrderGetDouble(ORDER_TP);
   ENUM_ORDER_TYPE orderType = (ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE);
   double orderPriceCurrent = OrderGetDouble(ORDER_PRICE_CURRENT);

//-- Get some information about the orders symbol
   int symbolDigits = (int)SymbolInfoInteger(orderSymbol, SYMBOL_DIGITS); //-- Number of symbol decimal places
   int symbolStopLevel = (int)SymbolInfoInteger(orderSymbol, SYMBOL_TRADE_STOPS_LEVEL);
   double symbolPoint = SymbolInfoDouble(orderSymbol, SYMBOL_POINT);
   int spread = (int)SymbolInfoInteger(orderSymbol, SYMBOL_SPREAD);

A continuación, validamos el nuevo precio de entrada para asegurarnos de que es correcto en función del tipo de orden (por ejemplo, límite de compra, stop de compra, stop de venta y límite de venta). Esto garantizará que detectemos y rechacemos los precios no válidos de forma temprana.

if(newEntryPrice > 0.0)
     {
      if(orderType == ORDER_TYPE_BUY_STOP || orderType == ORDER_TYPE_SELL_LIMIT)
        {
         if(
            SymbolInfoDouble(orderSymbol, SYMBOL_ASK) + (symbolStopLevel * symbolPoint) >
            newEntryPrice - (spread * symbolPoint)
         )
           {
            Print(
               "\r\n", __FUNCTION__, ": Can't MODIFY ", EnumToString(orderType),
               ". (Reason --> INVALID NEW ENTRY PRICE: ", DoubleToString(newEntryPrice, symbolDigits), ")\r\n"
            );
            return(false); //-- Invalid new entry price, log the error, exit the function and return false
           }
        }

      if(orderType == ORDER_TYPE_BUY_LIMIT || orderType == ORDER_TYPE_SELL_STOP)
        {
         if(
            SymbolInfoDouble(orderSymbol, SYMBOL_BID) - (symbolStopLevel * symbolPoint) <
            newEntryPrice + (spread * symbolPoint)
         )
           {
            Print(
               "\r\n", __FUNCTION__, ": Can't MODIFY ", EnumToString(orderType),
               ". (Reason --> INVALID NEW ENTRY PRICE: ", DoubleToString(newEntryPrice, symbolDigits), ")\r\n"
            );
            return(false); //-- Invalid new entry price, log the error, exit the function and return false
           }
        }
     }
   else
     {
      newEntryPrice = currentEntryPrice; //-- Do not modify the entry price
     }

También tendremos que calcular los nuevos precios de stop-loss y take-profit basándonos en los parámetros introducidos y validar estos valores con respecto al nivel de stop del bróker.

if(orderType == ORDER_TYPE_BUY_STOP || orderType == ORDER_TYPE_BUY_LIMIT)
     {
      if(newSl == 0)
        {
         newSlPrice = 0.0; //-- Remove the sl
        }
      else
        {
         newSlPrice = newEntryPrice - (newSl * symbolPoint);
        }
      if(newTp == 0)
        {
         newTpPrice = 0.0; //-- Remove the tp
        }
      else
        {
         newTpPrice = newEntryPrice + (newTp * symbolPoint);
        }

      //-- Check the validity of the newSlPrice
      if(newSlPrice > 0 && newEntryPrice - newSlPrice < symbolStopLevel * symbolPoint)
        {
         Print(
            "\r\n", __FUNCTION__, ": Can't modify ", EnumToString(orderType),
            ". (Reason --> INVALID NEW SL PRICE: ", DoubleToString(newSlPrice, symbolDigits), ")\r\n"
         );
         return(false); //-- Invalid sl price, log the error, exit the function and return false
        }

      //-- Check the validity of the newTpPrice
      if(newTpPrice > 0 && newTpPrice - newEntryPrice < symbolStopLevel * symbolPoint)
        {
         Print(
            "\r\n", __FUNCTION__, ": Can't modify ", EnumToString(orderType),
            ". (Reason --> INVALID NEW TP PRICE: ", DoubleToString(newTpPrice, symbolDigits), ")\r\n"
         );
         return(false); //-- Invalid tp price, log the error, exit the function and return false
        }
     }

   if(orderType == ORDER_TYPE_SELL_STOP || orderType == ORDER_TYPE_SELL_LIMIT)
     {
      if(newSl == 0)
        {
         newSlPrice = 0.0; //-- Remove the sl
        }
      else
        {
         newSlPrice = newEntryPrice + (newSl * symbolPoint);
        }
      if(newTp == 0)
        {
         newTpPrice = 0.0; //-- Remove the tp
        }
      else
        {
         newTpPrice = newEntryPrice - (newTp * symbolPoint);
        }

      //-- Check the validity of the newSlPrice
      if(newSlPrice > 0 && newSlPrice - newEntryPrice < symbolStopLevel * symbolPoint)
        {
         Print(
            "\r\n", __FUNCTION__, ": Can't modify ", EnumToString(orderType),
            ". (Reason --> INVALID NEW SL PRICE: ", DoubleToString(newSlPrice, symbolDigits), ")\r\n"
         );
         return(false); //-- Invalid sl price, log the error, exit the function and return false
        }

      //-- Check the validity of the newTpPrice
      if(newTpPrice > 0 && newEntryPrice - newTpPrice < symbolStopLevel * symbolPoint)
        {
         Print(
            "\r\n", __FUNCTION__, ": Can't modify ", EnumToString(orderType),
            ". (Reason --> INVALID NEW TP PRICE: ", DoubleToString(newTpPrice, symbolDigits), ")\r\n"
         );
         return(false); //-- Invalid tp price, log the error, exit the function and return false
        }
     }

Ahora que hemos validado todos los valores, procederemos a preparar la solicitud de operación para modificar la orden pendiente estableciendo los parámetros adecuados. Primero restableceremos la estructura de datos tradeRequest y luego la inicializaremos con nuestros datos de pedidos verificados y válidos.

   ZeroMemory(tradeRequest);
   ZeroMemory(tradeResult);

//-- initialize the parameters to set the sltp
   tradeRequest.action = TRADE_ACTION_MODIFY; //-- Trade operation type for modifying the pending order
   tradeRequest.order = orderTicket;
   tradeRequest.symbol = orderSymbol;
   tradeRequest.price = newEntryPrice;
   tradeRequest.sl = newSlPrice;
   tradeRequest.tp = newTpPrice;
   tradeRequest.deviation = SymbolInfoInteger(orderSymbol, SYMBOL_SPREAD) * 2;

A continuación, implementamos un mecanismo de reintento para reenviar la solicitud de modificación varias veces si el intento inicial falla, lo que aumenta la probabilidad de modificar correctamente el pedido. En caso de error crítico o si se agotan todos los intentos de reintento, la función devolverá false y se cerrará. Si la orden se modifica correctamente, la función devolverá true y se cerrará. Para evitar sobrecargar el servidor comercial con una serie rápida de solicitudes consecutivas, también introduciremos un retraso entre iteraciones utilizando la función Sleep(...).

ResetLastError(); //--- reset error cache so that we get an accurate runtime error code in the ErrorAdvisor function

   for(int loop = 0; loop <= MAX_ORDER_RETRIES; loop++) //-- try modifying the price open, sl, and tp until the request is successful
     {
      //--- send order to the trade server
      if(OrderSend(tradeRequest, tradeResult))
        {
         //-- Confirm order execution
         if(tradeResult.retcode == 10008 || tradeResult.retcode == 10009)
           {
            PrintFormat("Successfully modified Pending Order: #%I64d %s %s", orderTicket, orderSymbol, EnumToString(orderType));
            PrintFormat("retcode=%u  runtime_code=%u", tradeResult.retcode, GetLastError());
            Print("_______________________________________________________________________________________\r\n\r\n");
            return(true); //-- exit function
            //break; //--- success - order placed ok. exit for loop
           }
        }
      else  //-- Order request failed
        {
         //-- order not sent or critical error found
         if(!ErrorAdvisor(__FUNCTION__, orderSymbol, tradeResult.retcode) || IsStopped())
           {
            PrintFormat("ERROR modifying Pending Order: #%I64d %s %s", orderTicket, orderSymbol, EnumToString(orderType));
            Print("_______________________________________________________________________________________\r\n\r\n");
            return(false); //-- exit function
            //break; //-- exit for loop

            Sleep(ORDER_RETRY_DELAYS);//-- Small pause before retrying to avoid overwhelming the trade server
           }
        }
     }

Aquí está el código completo de la función, incluyendo algunas de las partes que faltaban, con todos los segmentos de código en su orden correcto.

bool ModifyPendingOrderByTicket(ulong orderTicket, double newEntryPrice, int newSl, int newTp) export
  {
//-- first check if the EA is allowed to trade
   if(!TradingIsAllowed())
     {
      return(false); //--- algo trading is disabled, exit function
     }

//--- Confirm and select the order using the provided orderTicket
   ResetLastError(); //--- Reset error cache incase of ticket selection errors
   if(OrderSelect(orderTicket))
     {
      //---Order selected
      Print("\r\n_______________________________________________________________________________________");
      Print(__FUNCTION__, ": Order with ticket:", orderTicket, " selected and ready to set SLTP.");
     }
   else
     {
      Print("\r\n_______________________________________________________________________________________");
      Print(__FUNCTION__, ": Selecting order with ticket:", orderTicket, " failed. ERROR: ", GetLastError());
      return(false); //-- Exit the function
     }

//-- create variables to store the calculated tp and sl prices to send to the trade server
   double newTpPrice = 0.0, newSlPrice = 0.0;

//--- Order ticket selected, save the order properties
   string orderSymbol = OrderGetString(ORDER_SYMBOL);
   double currentEntryPrice = OrderGetDouble(ORDER_PRICE_OPEN);
   double volume = OrderGetDouble(ORDER_VOLUME_INITIAL);
   double currentOrderSlPrice = OrderGetDouble(ORDER_SL);
   double currentOrderTpPrice = OrderGetDouble(ORDER_TP);
   ENUM_ORDER_TYPE orderType = (ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE);
   double orderPriceCurrent = OrderGetDouble(ORDER_PRICE_CURRENT);

//-- Get some information about the orders symbol
   int symbolDigits = (int)SymbolInfoInteger(orderSymbol, SYMBOL_DIGITS); //-- Number of symbol decimal places
   int symbolStopLevel = (int)SymbolInfoInteger(orderSymbol, SYMBOL_TRADE_STOPS_LEVEL);
   double symbolPoint = SymbolInfoDouble(orderSymbol, SYMBOL_POINT);
   int spread = (int)SymbolInfoInteger(orderSymbol, SYMBOL_SPREAD);

//-- Check the validity of the newEntryPrice
   if(newEntryPrice > 0.0)
     {
      if(orderType == ORDER_TYPE_BUY_STOP || orderType == ORDER_TYPE_SELL_LIMIT)
        {
         if(
            SymbolInfoDouble(orderSymbol, SYMBOL_ASK) + (symbolStopLevel * symbolPoint) >
            newEntryPrice - (spread * symbolPoint)
         )
           {
            Print(
               "\r\n", __FUNCTION__, ": Can't MODIFY ", EnumToString(orderType),
               ". (Reason --> INVALID NEW ENTRY PRICE: ", DoubleToString(newEntryPrice, symbolDigits), ")\r\n"
            );
            return(false); //-- Invalid new entry price, log the error, exit the function and return false
           }
        }

      if(orderType == ORDER_TYPE_BUY_LIMIT || orderType == ORDER_TYPE_SELL_STOP)
        {
         if(
            SymbolInfoDouble(orderSymbol, SYMBOL_BID) - (symbolStopLevel * symbolPoint) <
            newEntryPrice + (spread * symbolPoint)
         )
           {
            Print(
               "\r\n", __FUNCTION__, ": Can't MODIFY ", EnumToString(orderType),
               ". (Reason --> INVALID NEW ENTRY PRICE: ", DoubleToString(newEntryPrice, symbolDigits), ")\r\n"
            );
            return(false); //-- Invalid new entry price, log the error, exit the function and return false
           }
        }
     }
   else
     {
      newEntryPrice = currentEntryPrice; //-- Do not modify the entry price
     }

//-- Calculate and store the non-validated sl and tp prices
   if(orderType == ORDER_TYPE_BUY_STOP || orderType == ORDER_TYPE_BUY_LIMIT)
     {
      if(newSl == 0)
        {
         newSlPrice = 0.0; //-- Remove the sl
        }
      else
        {
         newSlPrice = newEntryPrice - (newSl * symbolPoint);
        }
      if(newTp == 0)
        {
         newTpPrice = 0.0; //-- Remove the tp
        }
      else
        {
         newTpPrice = newEntryPrice + (newTp * symbolPoint);
        }

      //-- Check the validity of the newSlPrice
      if(newSlPrice > 0 && newEntryPrice - newSlPrice < symbolStopLevel * symbolPoint)
        {
         Print(
            "\r\n", __FUNCTION__, ": Can't modify ", EnumToString(orderType),
            ". (Reason --> INVALID NEW SL PRICE: ", DoubleToString(newSlPrice, symbolDigits), ")\r\n"
         );
         return(false); //-- Invalid sl price, log the error, exit the function and return false
        }

      //-- Check the validity of the newTpPrice
      if(newTpPrice > 0 && newTpPrice - newEntryPrice < symbolStopLevel * symbolPoint)
        {
         Print(
            "\r\n", __FUNCTION__, ": Can't modify ", EnumToString(orderType),
            ". (Reason --> INVALID NEW TP PRICE: ", DoubleToString(newTpPrice, symbolDigits), ")\r\n"
         );
         return(false); //-- Invalid tp price, log the error, exit the function and return false
        }
     }

   if(orderType == ORDER_TYPE_SELL_STOP || orderType == ORDER_TYPE_SELL_LIMIT)
     {
      if(newSl == 0)
        {
         newSlPrice = 0.0; //-- Remove the sl
        }
      else
        {
         newSlPrice = newEntryPrice + (newSl * symbolPoint);
        }
      if(newTp == 0)
        {
         newTpPrice = 0.0; //-- Remove the tp
        }
      else
        {
         newTpPrice = newEntryPrice - (newTp * symbolPoint);
        }

      //-- Check the validity of the newSlPrice
      if(newSlPrice > 0 && newSlPrice - newEntryPrice < symbolStopLevel * symbolPoint)
        {
         Print(
            "\r\n", __FUNCTION__, ": Can't modify ", EnumToString(orderType),
            ". (Reason --> INVALID NEW SL PRICE: ", DoubleToString(newSlPrice, symbolDigits), ")\r\n"
         );
         return(false); //-- Invalid sl price, log the error, exit the function and return false
        }

      //-- Check the validity of the newTpPrice
      if(newTpPrice > 0 && newEntryPrice - newTpPrice < symbolStopLevel * symbolPoint)
        {
         Print(
            "\r\n", __FUNCTION__, ": Can't modify ", EnumToString(orderType),
            ". (Reason --> INVALID NEW TP PRICE: ", DoubleToString(newTpPrice, symbolDigits), ")\r\n"
         );
         return(false); //-- Invalid tp price, log the error, exit the function and return false
        }
     }

//-- Print order properties before modification
   string orderProperties = "--> "  + orderSymbol + " " + EnumToString(orderType) + " SLTP Modification Details" +
                            " <--\r\n";
   orderProperties += "------------------------------------------------------------\r\n";
   orderProperties += "Ticket: " + (string)orderTicket + "\r\n";
   orderProperties += "Volume: " + DoubleToString(volume, symbolDigits) + "\r\n";
   orderProperties += "Price Open: " + DoubleToString(currentEntryPrice, symbolDigits) +
                      "   -> New Proposed Price Open: " + DoubleToString(newEntryPrice, symbolDigits) + "\r\n";
   orderProperties += "Current SL: " + DoubleToString(currentOrderSlPrice, symbolDigits) +
                      "   -> New Proposed SL: " + DoubleToString(newSlPrice, symbolDigits) + "\r\n";
   orderProperties += "Current TP: " + DoubleToString(currentOrderTpPrice, symbolDigits) +
                      "   -> New Proposed TP: " + DoubleToString(newTpPrice, symbolDigits) + "\r\n";
   orderProperties += "Comment: " + OrderGetString(ORDER_COMMENT) + "\r\n";
   orderProperties += "Magic Number: " + (string)OrderGetInteger(ORDER_MAGIC) + "\r\n";
   orderProperties += "---";

//-- Print verified order properties before modification
   orderProperties += "--> Validated and Confirmed NewEntry, SL, and TP Prices: <--\r\n";
   orderProperties += "Order Price Current: " + DoubleToString(orderPriceCurrent, symbolDigits) + "\r\n";
   orderProperties += "Current Entry Price: " + DoubleToString(currentEntryPrice, symbolDigits) +
                      ", New Entry Price: " + DoubleToString(newEntryPrice, symbolDigits) + "\r\n";
   orderProperties += "Current SL: " + DoubleToString(currentOrderSlPrice, symbolDigits) +
                      "   -> New SL: " + DoubleToString(newSlPrice, symbolDigits) + "\r\n";
   orderProperties += "Current TP: " + DoubleToString(currentOrderTpPrice, symbolDigits) +
                      "   -> New TP: " + DoubleToString(newTpPrice, symbolDigits) + "\r\n";
   Print(orderProperties);

//-- reset the the tradeRequest and tradeResult values by zeroing them
   ZeroMemory(tradeRequest);
   ZeroMemory(tradeResult);

//-- initialize the parameters to set the sltp
   tradeRequest.action = TRADE_ACTION_MODIFY; //-- Trade operation type for modifying the pending order
   tradeRequest.order = orderTicket;
   tradeRequest.symbol = orderSymbol;
   tradeRequest.price = newEntryPrice;
   tradeRequest.sl = newSlPrice;
   tradeRequest.tp = newTpPrice;
   tradeRequest.deviation = SymbolInfoInteger(orderSymbol, SYMBOL_SPREAD) * 2;

   ResetLastError(); //--- reset error cache so that we get an accurate runtime error code in the ErrorAdvisor function

   for(int loop = 0; loop <= MAX_ORDER_RETRIES; loop++) //-- try modifying the price open, sl, and tp until the request is successful
     {
      //--- send order to the trade server
      if(OrderSend(tradeRequest, tradeResult))
        {
         //-- Confirm order execution
         if(tradeResult.retcode == 10008 || tradeResult.retcode == 10009)
           {
            PrintFormat("Successfully modified Pending Order: #%I64d %s %s", orderTicket, orderSymbol, EnumToString(orderType));
            PrintFormat("retcode=%u  runtime_code=%u", tradeResult.retcode, GetLastError());
            Print("_______________________________________________________________________________________\r\n\r\n");
            return(true); //-- exit function
            //break; //--- success - order placed ok. exit for loop
           }
        }
      else  //-- Order request failed
        {
         //-- order not sent or critical error found
         if(!ErrorAdvisor(__FUNCTION__, orderSymbol, tradeResult.retcode) || IsStopped())
           {
            PrintFormat("ERROR modifying Pending Order: #%I64d %s %s", orderTicket, orderSymbol, EnumToString(orderType));
            Print("_______________________________________________________________________________________\r\n\r\n");
            return(false); //-- exit function
            //break; //-- exit for loop

            Sleep(ORDER_RETRY_DELAYS);//-- Small pause before retrying to avoid overwhelming the trade server
           }
        }
     }
   return(false);
  }


Eliminar pedido pendiente por función de ticket

La función DeletePendingOrderByTicket(...) se encarga de eliminar un pedido pendiente utilizando su número de ticket único. Primero verifica si el comercio algorítmico está habilitado, selecciona la orden y luego intenta eliminarla del servidor comercial. Durante todo el proceso, la función registra detalles importantes sobre el pedido en diferentes etapas y emplea un mecanismo de reintento para maximizar las posibilidades de una eliminación exitosa, reintentándolo varias veces si es necesario.

La función acepta un parámetro de tipo ulong, que es el orderTicket que representa el número de ticket único del pedido que se va a eliminar. Devuelve un valor bool, donde true indica que la orden pendiente se ha eliminado correctamente y false indica que la eliminación ha fallado o que se ha producido un error crítico.

A continuación se muestra el código completo de la función, con comentarios detallados para facilitar su comprensión.

bool DeletePendingOrderByTicket(ulong orderTicket) export
  {
//-- first check if the EA is allowed to trade
   if(!TradingIsAllowed())
     {
      return(false); //--- algo trading is disabled, exit function
     }

//--- Confirm and select the order using the provided orderTicket
   ResetLastError(); //--- Reset error cache incase of ticket selection errors
   if(OrderSelect(orderTicket))
     {
      //---Order selected
      Print("...........................................................................................");
      Print(__FUNCTION__, ": Order with ticket:", orderTicket, " selected and ready to be deleted.");
     }
   else
     {
      Print("...........................................................................................");
      Print(__FUNCTION__, ": Selecting order with ticket:", orderTicket, " failed. ERROR: ", GetLastError());
      return(false); //-- Exit the function
     }

//--- Order ticket selected, save the order properties
   string orderSymbol = OrderGetString(ORDER_SYMBOL);
   double orderVolume = OrderGetDouble(ORDER_VOLUME_CURRENT);
   int symbolDigits = (int)SymbolInfoInteger(orderSymbol, SYMBOL_DIGITS);
   ENUM_ORDER_TYPE orderType = (ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE);

//-- Print order properties before deleting it
   string orderProperties;
   orderProperties += "-- "  + orderSymbol + " " + EnumToString(orderType) + " Details" +
   " -------------------------------------------------------------\r\n";
   orderProperties += "Ticket: " + (string)orderTicket + "\r\n";
   orderProperties += "Volume: " + DoubleToString(orderVolume) + "\r\n";
   orderProperties += "Price Open: " + DoubleToString(OrderGetDouble(ORDER_PRICE_OPEN), symbolDigits) + "\r\n";
   orderProperties += "SL: " + DoubleToString(OrderGetDouble(ORDER_SL), symbolDigits) + "\r\n";
   orderProperties += "TP: " + DoubleToString(OrderGetDouble(ORDER_TP), symbolDigits) + "\r\n";
   orderProperties += "Comment: " + OrderGetString(ORDER_COMMENT) + "\r\n";
   orderProperties += "Magic Number: " + (string)OrderGetInteger(ORDER_MAGIC) + "\r\n";
   orderProperties += "_______________________________________________________________________________________";
   Print(orderProperties);

//-- reset the the tradeRequest and tradeResult values by zeroing them
   ZeroMemory(tradeRequest);
   ZeroMemory(tradeResult);

//-- initialize the trade reqiest parameters to delete the order
   tradeRequest.action = TRADE_ACTION_REMOVE; //-- Trade operation type for deleting an order
   tradeRequest.order = orderTicket;

   ResetLastError(); //--- reset error cache so that we get an accurate runtime error code in the ErrorAdvisor function

   for(int loop = 0; loop <= MAX_ORDER_RETRIES; loop++) //-- try deleting the order until the request is successful
     {
      //--- send order to the trade server
      if(OrderSend(tradeRequest, tradeResult))
        {
         //-- Confirm order execution
         if(tradeResult.retcode == 10008 || tradeResult.retcode == 10009)
           {
            Print(__FUNCTION__, "_________________________________________________________________________");
            PrintFormat("Successfully deleted order #%I64d %s %s", orderTicket, orderSymbol, EnumToString(orderType));
            PrintFormat("retcode=%u  runtime_code=%u", tradeResult.retcode, GetLastError());
            Print("_______________________________________________________________________________________");
            return(true); //-- exit function
            //break; //--- success - order placed ok. exit for loop
           }
        }
      else  //-- order deleting request failed
        {
         //-- order not sent or critical error found
         if(!ErrorAdvisor(__FUNCTION__, orderSymbol, tradeResult.retcode) || IsStopped())
           {
            Print(__FUNCTION__, "_________________________________________________________________________");
            PrintFormat("ERROR deleting order #%I64d %s %s", orderTicket, orderSymbol, EnumToString(orderType));
            Print("_______________________________________________________________________________________");
            return(false); //-- exit function
            //break; //-- exit for loop

            Sleep(ORDER_RETRY_DELAYS);//-- Small pause before retrying to avoid overwhelming the trade server
           }
        }
     }
   return(false);
  }


Función para eliminar todos los pedidos pendientes

La función DeleteAllPendingOrders(...) está diseñada para eliminar todas las órdenes pendientes para un determinado símbolo y número mágico. Primero se asegura de que el trading algorítmico esté habilitado antes de continuar. La función recorrerá todas las órdenes abiertas, comprobará si coinciden con el símbolo y el número mágico especificados, e intentará eliminarlas una por una. En los casos en que algunos pedidos no se pueden eliminar inmediatamente, la función utiliza un mecanismo de devolución de llamada y reintento para intentar la eliminación continuamente hasta que se eliminen todos los pedidos seleccionados. Durante todo el proceso, registra errores y comprueba problemas críticos para evitar posibles bloqueos en un bucle infinito.

La función acepta dos parámetros opcionales:

  1. symbol (string): Un parámetro string que representa el símbolo bursátil. El valor predeterminado es ALL_SYMBOLS, lo que significa que se aplicará a las órdenes de todos los símbolos a menos que se especifique un símbolo concreto.
  2. magicNumber (ulong): Un parámetro entero largo sin signo que representa el número mágico único de los pedidos. El valor predeterminado es 0, lo que significa que la función se aplicará a todos los pedidos independientemente de su número mágico, a menos que se especifique un valor concreto.

La función devuelve un valor booleano (bool), donde true indica que todas las órdenes pendientes seleccionadas se han eliminado correctamente, y false indica que se ha producido un error al eliminar algunas o todas las órdenes, o que se ha producido un error crítico.

A continuación se muestra el código completo de la función, con comentarios añadidos para facilitar su comprensión:

bool DeleteAllPendingOrders(string symbol = ALL_SYMBOLS, ulong magicNumber = 0) export
  {
//-- first check if the EA is allowed to trade
   if(!TradingIsAllowed())
     {
      return(false); //--- algo trading is disabled, exit function
     }

   bool returnThis = false;

//-- Scan for symbol and magic number for the specified orders and close them
   int totalOpenOrders = OrdersTotal();
   for(int x = 0; x < totalOpenOrders; x++)
     {
      //--- Get order properties
      ulong orderTicket = OrderGetTicket(x); //-- Get ticket to select the order
      string selectedSymbol = OrderGetString(ORDER_SYMBOL);
      ulong orderMagicNo = OrderGetInteger(ORDER_MAGIC);

      //-- Filter orders by symbol and magic number
      if(
         (symbol != ALL_SYMBOLS && symbol != selectedSymbol) ||
         (magicNumber != 0 && orderMagicNo != magicNumber)
      )
        {
         continue;
        }

      //-- Delete the order
      DeletePendingOrderByTicket(orderTicket);
     }

//-- Confirm that we have closed all the orders being targeted
   int breakerBreaker = 0; //-- Variable that safeguards and makes sure we are not locked in an infinite loop
   while(SymbolOrdersTotal(symbol, magicNumber) > 0)
     {
      breakerBreaker++;
      DeleteAllPendingOrders(symbol, magicNumber); //-- We still have some open orders, do a function callback
      Sleep(ORDER_RETRY_DELAYS); //-- Micro sleep to pace the execution and give some time to the trade server

      //-- Check for critical errors so that we exit the loop if we run into trouble
      if(!ErrorAdvisor(__FUNCTION__, symbol, GetLastError()) || IsStopped() || breakerBreaker > MAX_ORDER_RETRIES)
        {
         break;
        }
     }

//-- Final confirmations that all targeted orders have been closed
   if(SymbolOrdersTotal(symbol, magicNumber) == 0)
     {
      returnThis = true; //-- Save this status for the function return value
     }

   return(returnThis);
  }

Para que borrar todos los pedidos pendientes sea más rápido y menos tedioso, vamos a sobrecargar la función DeleteAllPendingOrders(...) con una segunda versión que no toma ningún argumento. Cuando se llame a esta función, se eliminarán todos los pedidos pendientes de la cuenta. A continuación se muestra la función sobrecargada DeleteAllPendingOrders():

bool DeleteAllPendingOrders() export
  {
   return(DeleteAllPendingOrders(ALL_SYMBOLS, 0));
  }


Función para eliminar todas las órdenes Buy Stop

La función DeleteAllBuyStops(...) se encarga de eliminar todas las órdenes de compra stop pendientes para un determinado símbolo y número mágico. Al igual que otras funciones de eliminación, primero comprueba si el trading algorítmico está habilitado. A continuación, la función analiza todas las órdenes abiertas, identifica aquellas que coinciden con el símbolo, número mágico y el tipo de orden (Buy Stop) e intenta eliminarlas. Si no se elimina algún pedido durante el paso inicial, la función utiliza un mecanismo de devolución de llamada y reintento para intentar la eliminación continuamente. Asegura que no se produzcan bucles infinitos estableciendo protecciones y controles de errores. Durante todo el proceso, la función registra información relevante y gestiona errores críticos.

La función acepta dos parámetros opcionales:

  1. symbol (string): Un string que representa el símbolo bursátil. El valor predeterminado es ALL_SYMBOLS, lo que significa que se aplicará a las órdenes Buy Stop en todos los símbolos, a menos que se especifique un símbolo concreto.
  2. magicNumber (ulong): Un entero largo sin signo que representa el número mágico único asignado a los pedidos. El valor predeterminado es 0, lo que significa que la función se dirigirá a todas las órdenes de compra stop, independientemente de su número mágico, a menos que se especifique un número mágico concreto.

La función devuelve un valor booleano (bool), donde true indica que todas las órdenes de compra stop seleccionadas se han eliminado correctamente, y false indica que la función no ha podido eliminar algunas o todas las órdenes o ha encontrado un problema crítico.

A continuación se muestra el código de función completo con comentarios útiles para facilitar su comprensión:

bool DeleteAllBuyStops(string symbol = ALL_SYMBOLS, ulong magicNumber = 0) export
  {
//-- first check if the EA is allowed to trade
   if(!TradingIsAllowed())
     {
      return(false); //--- algo trading is disabled, exit function
     }

   bool returnThis = false;

//-- Scan for symbol and magic number specific buy stop orders and close them
   int totalOpenOrders = OrdersTotal();
   for(int x = 0; x < totalOpenOrders; x++)
     {
      //--- Get order properties
      ulong orderTicket = OrderGetTicket(x); //-- Get ticket to select the order
      string selectedSymbol = OrderGetString(ORDER_SYMBOL);
      ulong orderMagicNo = OrderGetInteger(ORDER_MAGIC);
      ulong orderType = OrderGetInteger(ORDER_TYPE);

      //-- Filter order by symbol, type and magic number
      if(
         (symbol != ALL_SYMBOLS && symbol != selectedSymbol) || (orderType != ORDER_TYPE_BUY_STOP) ||
         (magicNumber != 0 && orderMagicNo != magicNumber)
      )
        {
         continue;
        }

      //-- Close the order
      DeletePendingOrderByTicket(orderTicket);
     }

//-- Confirm that we have closed all the buy stop orders being targeted
   int breakerBreaker = 0; //-- Variable that safeguards and makes sure we are not locked in an infinite loop
   while(SymbolBuyStopOrdersTotal(symbol, magicNumber) > 0)
     {
      breakerBreaker++;
      DeleteAllBuyStops(symbol, magicNumber); //-- We still have some open buy stop orders, do a function callback
      Sleep(ORDER_RETRY_DELAYS); //-- Micro sleep to pace the execution and give some time to the trade server

      //-- Check for critical errors so that we exit the loop if we run into trouble
      if(!ErrorAdvisor(__FUNCTION__, symbol, GetLastError()) || IsStopped() || breakerBreaker > MAX_ORDER_RETRIES)
        {
         break;
        }
     }

   if(SymbolBuyStopOrdersTotal(symbol, magicNumber) == 0)
     {
      returnThis = true;
     }
   return(returnThis);
  }


Función para eliminar todas las órdenes Buy Limit

La función DeleteAllBuyLimits(...) se encarga de eliminar todas las órdenes de compra con límite pendientes para un determinado símbolo y número mágico. La función devuelve un valor booleano (bool), donde true indica que todas las órdenes de compra limitadas seleccionadas se han eliminado correctamente, y false indica que la función no ha podido eliminar algunas o todas las órdenes o ha encontrado un problema crítico.

bool DeleteAllBuyLimits(string symbol = ALL_SYMBOLS, ulong magicNumber = 0) export
  {
//-- first check if the EA is allowed to trade
   if(!TradingIsAllowed())
     {
      return(false); //--- algo trading is disabled, exit function
     }

   bool returnThis = false;

//-- Scan for symbol and magic number specific buy limit orders and close them
   int totalOpenOrders = OrdersTotal();
   for(int x = 0; x < totalOpenOrders; x++)
     {
      //--- Get order properties
      ulong orderTicket = OrderGetTicket(x); //-- Get ticket to select the order
      string selectedSymbol = OrderGetString(ORDER_SYMBOL);
      ulong orderMagicNo = OrderGetInteger(ORDER_MAGIC);
      ulong orderType = OrderGetInteger(ORDER_TYPE);

      //-- Filter order by symbol, type and magic number
      if(
         (symbol != ALL_SYMBOLS && symbol != selectedSymbol) || (orderType != ORDER_TYPE_BUY_LIMIT) ||
         (magicNumber != 0 && orderMagicNo != magicNumber)
      )
        {
         continue;
        }

      //-- Close the order
      DeletePendingOrderByTicket(orderTicket);
     }

//-- Confirm that we have closed all the buy limit orders being targeted
   int breakerBreaker = 0; //-- Variable that safeguards and makes sure we are not locked in an infinite loop
   while(SymbolBuyLimitOrdersTotal(symbol, magicNumber) > 0)
     {
      breakerBreaker++;
      DeleteAllBuyLimits(symbol, magicNumber); //-- We still have some open buy limit orders, do a function callback
      Sleep(ORDER_RETRY_DELAYS); //-- Micro sleep to pace the execution and give some time to the trade server

      //-- Check for critical errors so that we exit the loop if we run into trouble
      if(!ErrorAdvisor(__FUNCTION__, symbol, GetLastError()) || IsStopped() || breakerBreaker > MAX_ORDER_RETRIES)
        {
         break;
        }
     }

   if(SymbolBuyLimitOrdersTotal(symbol, magicNumber) == 0)
     {
      returnThis = true;
     }
   return(returnThis);
  }


Función para eliminar todas las órdenes Sell Stop

La función DeleteAllSellStops(...) se encarga de eliminar todas las órdenes Sell Stop pendientes asociadas a un símbolo y un número mágico específicos. Devuelve un valor booleano (bool), donde true significa que todas las órdenes Sell Stop seleccionadas se han eliminado correctamente, y false indica que la función no ha podido eliminar algunas o todas las órdenes, o que se ha producido un error crítico.

bool DeleteAllSellStops(string symbol = ALL_SYMBOLS, ulong magicNumber = 0) export
  {
//-- first check if the EA is allowed to trade
   if(!TradingIsAllowed())
     {
      return(false); //--- algo trading is disabled, exit function
     }

   bool returnThis = false;

//-- Scan for symbol and magic number specific sell stop orders and close them
   int totalOpenOrders = OrdersTotal();
   for(int x = 0; x < totalOpenOrders; x++)
     {
      //--- Get order properties
      ulong orderTicket = OrderGetTicket(x); //-- Get ticket to select the order
      string selectedSymbol = OrderGetString(ORDER_SYMBOL);
      ulong orderMagicNo = OrderGetInteger(ORDER_MAGIC);
      ulong orderType = OrderGetInteger(ORDER_TYPE);

      //-- Filter order by symbol, type and magic number
      if(
         (symbol != ALL_SYMBOLS && symbol != selectedSymbol) || (orderType != ORDER_TYPE_SELL_STOP) ||
         (magicNumber != 0 && orderMagicNo != magicNumber)
      )
        {
         continue;
        }

      //-- Close the order
      DeletePendingOrderByTicket(orderTicket);
     }

//-- Confirm that we have closed all the sell stop orders being targeted
   int breakerBreaker = 0; //-- Variable that safeguards and makes sure we are not locked in an infinite loop
   while(SymbolSellStopOrdersTotal(symbol, magicNumber) > 0)
     {
      breakerBreaker++;
      DeleteAllSellStops(symbol, magicNumber); //-- We still have some open sell stop orders, do a function callback
      Sleep(ORDER_RETRY_DELAYS); //-- Micro sleep to pace the execution and give some time to the trade server

      //-- Check for critical errors so that we exit the loop if we run into trouble
      if(!ErrorAdvisor(__FUNCTION__, symbol, GetLastError()) || IsStopped() || breakerBreaker > MAX_ORDER_RETRIES)
        {
         break;
        }
     }

   if(SymbolSellStopOrdersTotal(symbol, magicNumber) == 0)
     {
      returnThis = true;
     }
   return(returnThis);
  }


Función para eliminar todas las órdenes Sell Limit

La función DeleteAllSellLimits(...) se encarga de eliminar todas las órdenes Sell Limit pendientes vinculadas a un símbolo y un número mágico concretos. Devuelve un valor booleano (bool) de true si todas las órdenes Sell Limit especificadas se eliminaron correctamente, y false si la función no pudo eliminar algunas o todas las órdenes o se produjo un error crítico.

bool DeleteAllSellLimits(string symbol = ALL_SYMBOLS, ulong magicNumber = 0) export
  {
//-- first check if the EA is allowed to trade
   if(!TradingIsAllowed())
     {
      return(false); //--- algo trading is disabled, exit function
     }

   bool returnThis = false;

//-- Scan for symbol and magic number specific sell limit orders and close them
   int totalOpenOrders = OrdersTotal();
   for(int x = 0; x < totalOpenOrders; x++)
     {
      //--- Get order properties
      ulong orderTicket = OrderGetTicket(x); //-- Get ticket to select the order
      string selectedSymbol = OrderGetString(ORDER_SYMBOL);
      ulong orderMagicNo = OrderGetInteger(ORDER_MAGIC);
      ulong orderType = OrderGetInteger(ORDER_TYPE);

      //-- Filter order by symbol, type and magic number
      if(
         (symbol != ALL_SYMBOLS && symbol != selectedSymbol) || (orderType != ORDER_TYPE_SELL_LIMIT) ||
         (magicNumber != 0 && orderMagicNo != magicNumber)
      )
        {
         continue;
        }

      //-- Close the order
      DeletePendingOrderByTicket(orderTicket);
     }

//-- Confirm that we have closed all the sell limit orders being targeted
   int breakerBreaker = 0; //-- Variable that safeguards and makes sure we are not locked in an infinite loop
   while(SymbolSellLimitOrdersTotal(symbol, magicNumber) > 0)
     {
      breakerBreaker++;
      DeleteAllSellLimits(symbol, magicNumber); //-- We still have some open sell limit orders, do a function callback
      Sleep(ORDER_RETRY_DELAYS); //-- Micro sleep to pace the execution and give some time to the trade server

      //-- Check for critical errors so that we exit the loop if we run into trouble
      if(!ErrorAdvisor(__FUNCTION__, symbol, GetLastError()) || IsStopped() || breakerBreaker > MAX_ORDER_RETRIES)
        {
         break;
        }
     }

   if(SymbolSellLimitOrdersTotal(symbol, magicNumber) == 0)
     {
      returnThis = true;
     }
   return(returnThis);
  }


Función para eliminar todas las órdenes por Magic Number

La función DeleteAllMagicOrders(...) se encarga de eliminar todas las órdenes pendientes asociadas a un número mágico específico. Devuelve un valor booleano (bool), donde true indica que todas las órdenes mágicas relevantes se han eliminado correctamente, y false indica que la función no ha podido eliminar algunas o todas las órdenes, o que se ha producido un error crítico.

bool DeleteAllMagicOrders(ulong magicNumber) export
  {
//-- first check if the EA is allowed to trade
   if(!TradingIsAllowed())
     {
      return(false); //--- algo trading is disabled, exit function
     }

   bool returnThis = false;

//-- Variables to store the selected orders data
   ulong orderTicket, orderMagicNo;
   string orderSymbol;

//-- Scan for magic number specific orders and delete them
   int totalOpenOrders = OrdersTotal();
   for(int x = 0; x < totalOpenOrders; x++)
     {
      //--- Get order properties
      orderTicket = OrderGetTicket(x); //-- Get ticket to select the order
      orderMagicNo = OrderGetInteger(ORDER_MAGIC);
      orderSymbol = OrderGetString(ORDER_SYMBOL);

      //-- Filter orders by magic number
      if(magicNumber == orderMagicNo)
        {
         //-- Delete the order
         DeletePendingOrderByTicket(orderTicket);
        }
     }

//-- Confirm that we have deleted all the orders being targeted
   int breakerBreaker = 0; //-- Variable that safeguards and makes sure we are not locked in an infinite loop
   while(MagicOrdersTotal(magicNumber) > 0)
     {
      breakerBreaker++;
      DeleteAllMagicOrders(magicNumber); //-- We still have some open orders, do a function callback
      Sleep(ORDER_RETRY_DELAYS); //-- Micro sleep to pace the execution and give some time to the trade server

      //-- Check for critical errors so that we exit the loop if we run into trouble
      if(!ErrorAdvisor(__FUNCTION__, orderSymbol, GetLastError()) || IsStopped() || breakerBreaker > MAX_ORDER_RETRIES)
        {
         break;
        }
     }

   if(MagicOrdersTotal(magicNumber) == 0)
     {
      returnThis = true;
     }
   return(returnThis);
  }


Obtener datos de órdenes pendientes

Para que cualquier sistema de trading algorítmico autónomo o Asesor Experto sea fiable y rentable de forma constante a largo plazo, debe conocer todas las posiciones y el estado de las órdenes de la cuenta. En el segundo artículo, desarrollamos una función para supervisar las posiciones que recopilan datos sobre todas las posiciones abiertas. Dado que este artículo se centra en los pedidos pendientes, crearemos una función para escanear y almacenar datos de todos los pedidos pendientes, haciéndolos disponibles en toda la biblioteca para que los utilicen otras funciones. Lograremos esto utilizando las variables globales establecidas al principio de este artículo.

Como estas variables globales no se pueden exportar ni acceder fuera del archivo de código fuente de la biblioteca o del archivo binario .EX5, las pasaremos a varias funciones de estado de pedidos pendientes exportables, lo que permitirá que sean accesibles en la biblioteca .EX5 final. Comenzaremos creando una función para recuperar todos los datos de los pedidos pendientes, a la que llamaremos GetPendingOrdersData(...).

La función GetPendingOrdersData(...) recuperará y guardará los detalles del estado de las órdenes pendientes abiertas en relación con la cuenta, los símbolos de negociación específicos y el número mágico del Asesor Experto. Comenzará por restablecer varias variables globales que almacenan los totales y volúmenes de diferentes tipos de órdenes pendientes, incluyendo órdenes stop de compra, órdenes límite de compra, órdenes stop de venta y órdenes límite de venta. Después de este reinicio, la función comprobará si hay órdenes pendientes abiertas y las revisará para recopilar los datos relevantes. A continuación, filtrará las órdenes en función del símbolo symbol y el número mágico magic number proporcionados, acumulando los totales y los volúmenes de las órdenes pendientes coincidentes. Este enfoque integral garantizará que la función capture datos en tiempo real sobre el estado de las órdenes pendientes, que podrán ser utilizados por otras funciones del Asesor Experto.

La función aceptará dos parámetros:

  1. symbol (string): Un string que representa el símbolo de negociación para el que se recuperarán los datos de la orden pendiente. El valor predeterminado será ALL_SYMBOLS, lo que indica que recopilará datos de todos los símbolos, a menos que se proporcione un símbolo específico.
  2. magicNumber (ulong): Un entero largo sin signo que representa el número mágico único asignado a las órdenes pendientes del Asesor Experto. Este parámetro tendrá un valor predeterminado de 0, lo que permitirá a la función recuperar datos de todas las órdenes pendientes, independientemente de su número mágico, a menos que se especifique un número mágico concreto.

La función no devolverá ningún valor (void), ya que su objetivo principal es rellenar y actualizar las variables de estado globales con los detalles de los pedidos pendientes. Otras partes de la biblioteca luego accederán a estas variables para fundamentar la toma de decisiones y las estrategias comerciales.

A continuación se muestra el código de función completo con comentarios detallados para mejorar la comprensión:

void GetPendingOrdersData(string symbol, ulong magicNumber)
  {
//-- Reset the account open pending orders status
   accountBuyStopOrdersTotal = 0;
   accountBuyLimitOrdersTotal = 0;

   accountSellStopOrdersTotal = 0;
   accountSellLimitOrdersTotal = 0;

   accountPendingOrdersVolumeTotal = 0.0;

   accountBuyStopOrdersVolumeTotal = 0.0;
   accountBuyLimitOrdersVolumeTotal = 0.0;

   accountSellStopOrdersVolumeTotal = 0.0;
   accountSellLimitOrdersVolumeTotal = 0.0;

//-- Reset the EA's magic open pending orders status
   magicPendingOrdersTotal = 0;

   magicBuyStopOrdersTotal = 0;
   magicBuyLimitOrdersTotal = 0;

   magicSellStopOrdersTotal = 0;
   magicSellLimitOrdersTotal = 0;

   magicPendingOrdersVolumeTotal = 0.0;

   magicBuyStopOrdersVolumeTotal = 0.0;
   magicBuyLimitOrdersVolumeTotal = 0.0;

   magicSellStopOrdersVolumeTotal = 0.0;
   magicSellLimitOrdersVolumeTotal = 0.0;

//-- Reset the symbol open pending orders status
   symbolPendingOrdersTotal = 0;

   symbolBuyStopOrdersTotal = 0;
   symbolBuyLimitOrdersTotal = 0;

   symbolSellStopOrdersTotal = 0;
   symbolSellLimitOrdersTotal = 0;

   symbolPendingOrdersVolumeTotal = 0.0;

   symbolBuyStopOrdersVolumeTotal = 0.0;
   symbolBuyLimitOrdersVolumeTotal = 0.0;

   symbolSellStopOrdersVolumeTotal = 0.0;
   symbolSellLimitOrdersVolumeTotal = 0.0;

//-- Update and save the open pending orders status with realtime data
   int totalOpenPendingOrders = OrdersTotal();
   if(totalOpenPendingOrders > 0)
     {
      //-- Scan for symbol and magic number specific pending orders and save their status
      for(int x = 0; x < totalOpenPendingOrders; x++)
        {
         //--- Get the pending orders properties
         ulong  orderTicket = OrderGetTicket(x); //-- Get ticket to select the pending order
         string selectedSymbol = OrderGetString(ORDER_SYMBOL);
         ulong orderMagicNo = OrderGetInteger(ORDER_MAGIC);

         //-- Filter pending orders by magic number
         if(magicNumber != 0 && orderMagicNo != magicNumber)
           {
            continue;
           }

         //-- Save the account pending orders status first
         accountPendingOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT);

         if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_STOP)
           {
            //-- Account properties
            ++accountBuyStopOrdersTotal;
            accountBuyStopOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT);
           }
         if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_LIMIT)
           {
            //-- Account properties
            ++accountBuyLimitOrdersTotal;
            accountBuyLimitOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT);
           }
         if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_STOP)
           {
            //-- Account properties
            ++accountSellStopOrdersTotal;
            accountSellStopOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT);
           }
         if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_LIMIT)
           {
            //-- Account properties
            ++accountSellLimitOrdersTotal;
            accountSellLimitOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT);
           }


         //-- Filter pending orders openend by EA and save their status
         if(
            OrderGetInteger(ORDER_REASON) == ORDER_REASON_EXPERT &&
            orderMagicNo == magicNumber
         )
           {
            ++magicPendingOrdersTotal;
            magicPendingOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT);
            if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_STOP)
              {
               //-- Magic properties
               ++magicBuyStopOrdersTotal;
               magicBuyStopOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT);
              }
            if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_LIMIT)
              {
               //-- Magic properties
               ++magicBuyLimitOrdersTotal;
               magicBuyLimitOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT);
              }
            if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_STOP)
              {
               //-- Magic properties
               ++magicSellStopOrdersTotal;
               magicSellStopOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT);
              }
            if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_LIMIT)
              {
               //-- Magic properties
               ++magicSellLimitOrdersTotal;
               magicSellLimitOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT);
              }
           }

         //-- Filter positions by symbol
         if(symbol == ALL_SYMBOLS || selectedSymbol == symbol)
           {
            ++symbolPendingOrdersTotal;
            symbolPendingOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT);
            if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_STOP)
              {
               ++symbolBuyStopOrdersTotal;
               symbolBuyStopOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT);
              }
            if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_LIMIT)
              {
               ++symbolBuyLimitOrdersTotal;
               symbolBuyLimitOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT);
              }
            if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_STOP)
              {
               ++symbolSellStopOrdersTotal;
               symbolSellStopOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT);
              }
            if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_SELL_LIMIT)
              {
               ++symbolSellLimitOrdersTotal;
               symbolSellLimitOrdersVolumeTotal += OrderGetDouble(ORDER_VOLUME_CURRENT);
              }
           }
        }
     }
  }


Función para contar el total de órdenes Buy Stop

Devuelve un número entero que representa el número total de órdenes stop de compra abiertas en la cuenta.

int BuyStopOrdersTotal() export
  {
   GetPendingOrdersData(ALL_SYMBOLS, 0);
   return(accountBuyStopOrdersTotal);
  }


Función para contar el total de órdenes Buy Limit

Devuelve un número entero que representa el número total de órdenes de compra limitadas abiertas en la cuenta.

int BuyLimitOrdersTotal() export
  {
   GetPendingOrdersData(ALL_SYMBOLS, 0);
   return(accountBuyLimitOrdersTotal);
  }


Función para contar el total de órdenes Sell Stop

Devuelve un número entero que representa el número total de órdenes de venta stop abiertas en la cuenta.

int SellStopOrdersTotal() export
  {
   GetPendingOrdersData(ALL_SYMBOLS, 0);
   return(accountSellStopOrdersTotal);
  }


Función para contar el total de órdenes Sell Limit

Devuelve un número entero que representa el número total de órdenes de venta limitadas abiertas en la cuenta.

int SellLimitOrdersTotal() export
  {
   GetPendingOrdersData(ALL_SYMBOLS, 0);
   return(accountSellLimitOrdersTotal);
  }


Función de volumen total de pedidos

Devuelve un valor doble que representa el volumen/lote/cantidad total de todas las órdenes abiertas en la cuenta.

double OrdersTotalVolume() export
  {
   GetPendingOrdersData(ALL_SYMBOLS, 0);
   return(accountPendingOrdersVolumeTotal);
  }


Función para obtener el volumen total de las órdenes Buy Stop

Devuelve un valor doble que representa el volumen/lote/cantidad total de todas las órdenes de stop de compra abiertas en la cuenta.

double BuyStopOrdersTotalVolume() export
  {
   GetPendingOrdersData(ALL_SYMBOLS, 0);
   return(accountBuyStopOrdersVolumeTotal);
  }


Función para obtener el volumen total de las órdenes Buy Limit

Devuelve un valor doble que representa el volumen/lote/cantidad total de todas las órdenes de compra limitada abiertas en la cuenta.

double BuyLimitOrdersTotalVolume() export
  {
   GetPendingOrdersData(ALL_SYMBOLS, 0);
   return(accountBuyLimitOrdersVolumeTotal);
  }


Función para obtener el volumen total de las órdenes Sell Stop

Devuelve un valor doble que representa el volumen/lote/cantidad total de todas las órdenes de venta stop abiertas en la cuenta.

double SellStopOrdersTotalVolume() export
  {
   GetPendingOrdersData(ALL_SYMBOLS, 0);
   return(accountSellStopOrdersVolumeTotal);
  }


Función para obtener el volumen total de las órdenes Sell Limit

Devuelve un valor doble que representa el volumen/lote/cantidad total de todas las órdenes de venta límite abiertas en la cuenta.

double SellLimitOrdersTotalVolume() export
  {
   GetPendingOrdersData(ALL_SYMBOLS, 0);
   return(accountSellLimitOrdersVolumeTotal);
  }


Función para contar el total de órdenes con Magic Number

Devuelve un valor entero del número total de todas las órdenes pendientes abiertas para el número mágico especificado en la cuenta.

int MagicOrdersTotal(ulong magicNumber) export
  {
   GetPendingOrdersData(ALL_SYMBOLS, magicNumber);
   return(magicPendingOrdersTotal);
  }


Función para contar el total de órdenes Buy Stop con Magic Number

Devuelve un valor entero que representa el número total de órdenes stop de compra abiertas para el número mágico especificado en la cuenta.

int MagicBuyStopOrdersTotal(ulong magicNumber) export
  {
   GetPendingOrdersData(ALL_SYMBOLS, magicNumber);
   return(magicBuyStopOrdersTotal);
  }


Función para contar el total de órdenes Buy Limit con Magic Number

Devuelve un valor entero del número total de todas las órdenes de compra limitadas abiertas para el número mágico especificado en la cuenta.

int MagicBuyLimitOrdersTotal(ulong magicNumber) export
  {
   GetPendingOrdersData(ALL_SYMBOLS, magicNumber);
   return(magicBuyLimitOrdersTotal);
  }


Función para contar el total de órdenes Sell Stop con Magic Number

Devuelve un valor entero del número total de todas las órdenes de venta stop abiertas para el número mágico especificado en la cuenta.

int MagicSellStopOrdersTotal(ulong magicNumber) export
  {
   GetPendingOrdersData(ALL_SYMBOLS, magicNumber);
   return(magicSellStopOrdersTotal);
  }


Función para contar el total de órdenes Sell Limit con Magic Number

Devuelve un valor entero del número total de todas las órdenes de venta límite abiertas para el número mágico especificado en la cuenta.

int MagicSellLimitOrdersTotal(ulong magicNumber) export
  {
   GetPendingOrdersData(ALL_SYMBOLS, magicNumber);
   return(magicSellLimitOrdersTotal);
  }


Función para obtener el volumen total de las órdenes con Magic Number

Devuelve un valor doble que representa el volumen/lote/cantidad total de todas las órdenes pendientes abiertas para el número mágico especificado en la cuenta.

double MagicOrdersTotalVolume(ulong magicNumber) export
  {
   GetPendingOrdersData(ALL_SYMBOLS, magicNumber);
   return(magicPendingOrdersVolumeTotal);
  }


Función para obtener el volumen total de las órdenes Buy Stop con Magic Number

Devuelve un valor doble que representa el volumen/lote/cantidad total de todas las órdenes de compra stop abiertas para el número mágico especificado en la cuenta.

double MagicBuyStopOrdersTotalVolume(ulong magicNumber) export
  {
   GetPendingOrdersData(ALL_SYMBOLS, magicNumber);
   return(magicBuyStopOrdersVolumeTotal);
  }


Función para obtener el volumen total de las órdenes Buy Limit con Magic Number

Devuelve un valor doble que representa el volumen/lote/cantidad total de todas las órdenes de compra límite abiertas para el número mágico especificado en la cuenta.

double MagicBuyLimitOrdersTotalVolume(ulong magicNumber) export
  {
   GetPendingOrdersData(ALL_SYMBOLS, magicNumber);
   return(magicBuyLimitOrdersVolumeTotal);
  }


Función para obtener el volumen total de las órdenes Sell Stop con Magic Number

Devuelve un valor doble que representa el volumen/lote/cantidad total de todas las órdenes de venta stop abiertas para el número mágico especificado en la cuenta.

double MagicSellStopOrdersTotalVolume(ulong magicNumber) export
  {
   GetPendingOrdersData(ALL_SYMBOLS, magicNumber);
   return(magicSellStopOrdersVolumeTotal);
  }


Función para obtener el volumen total de las órdenes Sell Limit con Magic Number

Devuelve un valor doble que representa el volumen/lote/cantidad total de todas las órdenes de venta límite abiertas para el número mágico especificado en la cuenta.

double MagicSellLimitOrdersTotalVolume(ulong magicNumber) export
  {
   GetPendingOrdersData(ALL_SYMBOLS, magicNumber);
   return(magicSellLimitOrdersVolumeTotal);
  }


Función para contar el total de órdenes de un símbolo

Devuelve un valor entero que representa el número total de todas las órdenes pendientes abiertas para un símbolo y un número mágico específicos en la cuenta.

int SymbolOrdersTotal(string symbol, ulong magicNumber) export
  {
   GetPendingOrdersData(symbol, magicNumber);
   return(symbolPendingOrdersTotal);
  }


Función para contar el total de órdenes Buy Stop de un símbolo

Devuelve un valor entero que representa el número total de todas las órdenes de compra stop abiertas para un símbolo y un número mágico específicos en la cuenta.

int SymbolBuyStopOrdersTotal(string symbol, ulong magicNumber) export
  {
   GetPendingOrdersData(symbol, magicNumber);
   return(symbolBuyStopOrdersTotal);
  }


Función para contar el total de órdenes Buy Limit de un símbolo

Devuelve un valor entero que representa el número total de todas las órdenes de compra limitadas abiertas para un símbolo y un número mágico específicos en la cuenta.

int SymbolBuyLimitOrdersTotal(string symbol, ulong magicNumber) export
  {
   GetPendingOrdersData(symbol, magicNumber);
   return(symbolBuyLimitOrdersTotal);
  }


Función para contar el total de órdenes Sell Stop de un símbolo

Devuelve un valor entero que representa el número total de todas las órdenes stop de venta abiertas para un símbolo y un número mágico específicos en la cuenta.

int SymbolSellStopOrdersTotal(string symbol, ulong magicNumber) export
  {
   GetPendingOrdersData(symbol, magicNumber);
   return(symbolSellStopOrdersTotal);
  }


Función para contar el total de órdenes Sell Limit de un símbolo

Devuelve un valor entero que representa el número total de todas las órdenes de venta limitadas abiertas para un símbolo y un número mágico específicos en la cuenta.

int SymbolSellLimitOrdersTotal(string symbol, ulong magicNumber) export
  {
   GetPendingOrdersData(symbol, magicNumber);
   return(symbolSellLimitOrdersTotal);
  }


Función para obtener el volumen total de las órdenes de un símbolo

Devuelve un valor doble que representa el volumen/lote/cantidad total de todas las órdenes pendientes abiertas para el símbolo especificado y el número mágico en la cuenta.

double SymbolOrdersTotalVolume(string symbol, ulong magicNumber) export
  {
   GetPendingOrdersData(symbol, magicNumber);
   return(symbolPendingOrdersVolumeTotal);
  }


Función para obtener el volumen total de las órdenes Buy Stop de un símbolo

Devuelve un valor doble que representa el volumen/lote/cantidad total de todas las órdenes de compra stop abiertas para el símbolo especificado y el número mágico en la cuenta.

double SymbolBuyStopOrdersTotalVolume(string symbol, ulong magicNumber) export
  {
   GetPendingOrdersData(symbol, magicNumber);
   return(symbolBuyStopOrdersVolumeTotal);
  }


Función para obtener el volumen total de las órdenes Buy Limit de un símbolo

Devuelve un valor doble que representa el volumen/lote/cantidad total de todas las órdenes de compra límite abiertas para el símbolo especificado y el número mágico en la cuenta.

double SymbolBuyLimitOrdersTotalVolume(string symbol, ulong magicNumber) export
  {
   GetPendingOrdersData(symbol, magicNumber);
   return(symbolBuyLimitOrdersVolumeTotal);
  }


Función para obtener el volumen total de las órdenes Sell Stop de un símbolo

Devuelve un valor doble que representa el volumen/lote/cantidad total de todas las órdenes de venta stop abiertas para el símbolo especificado y el número mágico en la cuenta.

double SymbolSellStopOrdersTotalVolume(string symbol, ulong magicNumber) export
  {
   GetPendingOrdersData(symbol, magicNumber);
   return(symbolSellStopOrdersVolumeTotal);
  }


Función para obtener el volumen total de las órdenes Sell Limit de un símbolo

Devuelve un valor doble que representa el volumen/lote/cantidad total de todas las órdenes de venta límite abiertas para el símbolo especificado y el número mágico en la cuenta.

double SymbolSellLimitOrdersTotalVolume(string symbol, ulong magicNumber) export
  {
   GetPendingOrdersData(symbol, magicNumber);
   return(symbolSellLimitOrdersVolumeTotal);
  }


Función para obtener el estado de las órdenes de la cuenta

Devuelve una cadena preformateada que contiene el estado de los pedidos de la cuenta, que se puede imprimir en el registro o mostrar en los comentarios del gráfico. La función toma un único parámetro booleano denominado formatForComment. Si formatForComment se establece en true, la función formatea los datos para mostrarlos en la ventana del gráfico; si se establece en false, formatea los datos para la pestaña de registro del Asesor Experto.

string AccountOrdersStatus(bool formatForComment) export
  {
   GetPendingOrdersData(ALL_SYMBOLS, 0); //-- Update the orders status variables before we display their data
   string spacer = "";
   if(formatForComment) //-- Add some formating space for the chart comment string
     {
      spacer = "                                        ";
     }
   string accountOrdersStatus = "\r\n" + spacer + "|---------------------------------------------------------------------------\r\n";
   accountOrdersStatus += spacer + "| " + (string)AccountInfoInteger(ACCOUNT_LOGIN) + " - ACCOUNT ORDERS STATUS \r\n";
   accountOrdersStatus += spacer + "|---------------------------------------------------------------------------\r\n";
   accountOrdersStatus += spacer + "|     Total Open:   " + (string)OrdersTotal() + "\r\n";
   accountOrdersStatus += spacer + "|     Total Volume: " + (string)accountPendingOrdersVolumeTotal + "\r\n";
   accountOrdersStatus += spacer + "|------------------------------------------------------------------\r\n";
   accountOrdersStatus += spacer + "| BUY STOP ORDERS: \r\n";
   accountOrdersStatus += spacer + "|     Total Open:   " + (string)accountBuyStopOrdersTotal + "\r\n";
   accountOrdersStatus += spacer + "|     Total Volume: " + (string)accountBuyStopOrdersVolumeTotal + "\r\n";
   accountOrdersStatus += spacer + "|------------------------------------------------------------------\r\n";
   accountOrdersStatus += spacer + "| BUY LIMIT ORDERS: \r\n";
   accountOrdersStatus += spacer + "|     Total Open:   " + (string)accountBuyLimitOrdersTotal + "\r\n";
   accountOrdersStatus += spacer + "|     Total Volume: " + (string)accountBuyLimitOrdersVolumeTotal + "\r\n";
   accountOrdersStatus += spacer + "|---------------------------------------------------------------------------\r\n";
   accountOrdersStatus += spacer + "| SELL STOP ORDERS: \r\n";
   accountOrdersStatus += spacer + "|     Total Open:   " + (string)accountSellStopOrdersTotal + "\r\n";
   accountOrdersStatus += spacer + "|     Total Volume: " + (string)accountSellStopOrdersVolumeTotal + "\r\n";
   accountOrdersStatus += spacer + "|---------------------------------------------------------------------------\r\n";
   accountOrdersStatus += spacer + "| SELL LIMIT ORDERS: \r\n";
   accountOrdersStatus += spacer + "|     Total Open:   " + (string)accountSellLimitOrdersTotal + "\r\n";
   accountOrdersStatus += spacer + "|     Total Volume: " + (string)accountSellLimitOrdersVolumeTotal + "\r\n";
   accountOrdersStatus += spacer + "|---------------------------------------------------------------------------\r\n";
   accountOrdersStatus += spacer + "\r\n";
   return(accountOrdersStatus);
  }


Función para obtener el estado de las órdenes con Magic Number

Devuelve una cadena preformateada que indica el estado de las órdenes mágicas, que se puede imprimir en el registro o mostrar en los comentarios del gráfico. La función acepta dos parámetros: un unsigned long (ulong) llamado magicNumber para especificar el número mágico deseado, y un boolean llamado formatForComment para determinar el tipo de formato. Si formatForComment es verdadero, la función formatea los datos para mostrarlos en la ventana del gráfico; si es falso, formatea los datos para la pestaña de registro del Asesor Experto.

string MagicOrdersStatus(ulong magicNumber, bool formatForComment) export
  {
   GetPendingOrdersData(ALL_SYMBOLS, magicNumber); //-- Update the order status variables before we display their data
   string spacer = "";
   if(formatForComment) //-- Add some formating space for the chart comment string
     {
      spacer = "                                        ";
     }
   string magicOrdersStatus = "\r\n" + spacer + "|---------------------------------------------------------------------------\r\n";
   magicOrdersStatus += spacer + "| " + (string)magicNumber + " - MAGIC ORDERS STATUS \r\n";
   magicOrdersStatus += spacer + "|---------------------------------------------------------------------------\r\n";
   magicOrdersStatus += spacer + "|     Total Open:   " + (string)magicPendingOrdersTotal + "\r\n";
   magicOrdersStatus += spacer + "|     Total Volume: " + (string)magicPendingOrdersVolumeTotal + "\r\n";
   magicOrdersStatus += spacer + "|------------------------------------------------------------------\r\n";
   magicOrdersStatus += spacer + "| BUY STOP ORDERS: \r\n";
   magicOrdersStatus += spacer + "|     Total Open:   " + (string)magicBuyStopOrdersTotal + "\r\n";
   magicOrdersStatus += spacer + "|     Total Volume: " + (string)magicBuyStopOrdersVolumeTotal + "\r\n";
   magicOrdersStatus += spacer + "|------------------------------------------------------------------\r\n";
   magicOrdersStatus += spacer + "| BUY LIMIT ORDERS: \r\n";
   magicOrdersStatus += spacer + "|     Total Open:   " + (string)magicBuyLimitOrdersTotal + "\r\n";
   magicOrdersStatus += spacer + "|     Total Volume: " + (string)magicBuyLimitOrdersVolumeTotal + "\r\n";
   magicOrdersStatus += spacer + "|---------------------------------------------------------------------------\r\n";
   magicOrdersStatus += spacer + "| SELL STOP ORDERS: \r\n";
   magicOrdersStatus += spacer + "|     Total Open:   " + (string)magicSellStopOrdersTotal + "\r\n";
   magicOrdersStatus += spacer + "|     Total Volume: " + (string)magicSellStopOrdersVolumeTotal + "\r\n";
   magicOrdersStatus += spacer + "|------------------------------------------------------------------\r\n";
   magicOrdersStatus += spacer + "| SELL LIMIT ORDERS: \r\n";
   magicOrdersStatus += spacer + "|     Total Open:   " + (string)magicSellLimitOrdersTotal + "\r\n";
   magicOrdersStatus += spacer + "|     Total Volume: " + (string)magicSellLimitOrdersVolumeTotal + "\r\n";
   magicOrdersStatus += spacer + "|---------------------------------------------------------------------------\r\n";
   magicOrdersStatus += spacer + "\r\n";
   return(magicOrdersStatus);
  }


Función para obtener el estado de las órdenes de un símbolo

Devuelve una cadena preformateada que indica el estado de las órdenes de símbolos, que se puede imprimir en el registro o mostrar en los comentarios del gráfico. La función acepta tres parámetros: una cadena (string)denominada symbol, un unsigned long (ulong) denominado magicNumber para especificar el número mágico deseado (un valor de cero (0) desactivará el filtro de número mágico), y un booleano denominado formatForComment para determinar el tipo de formato. Si formatForComment es verdadero, la función formatea los datos para mostrarlos en la ventana del gráfico; si es falso, formatea los datos para la pestaña de registro del Asesor Experto.

string SymbolOrdersStatus(string symbol, ulong magicNumber, bool formatForComment) export
  {
   GetPendingOrdersData(symbol, magicNumber); //-- Update the order status variables before we display their data
   string spacer = "";
   if(formatForComment) //-- Add some formating space for the chart comment string
     {
      spacer = "                                        ";
     }
   string symbolOrdersStatus = "\r\n" + spacer + "|---------------------------------------------------------------------------\r\n";
   symbolOrdersStatus += spacer + "| " + symbol + " - SYMBOL ORDERS STATUS \r\n";
   symbolOrdersStatus += spacer + "|---------------------------------------------------------------------------\r\n";
   symbolOrdersStatus += spacer + "|     Total Open:   " + (string)symbolPendingOrdersTotal + "\r\n";
   symbolOrdersStatus += spacer + "|     Total Volume: " + (string)symbolPendingOrdersVolumeTotal + "\r\n";
   symbolOrdersStatus += spacer + "|------------------------------------------------------------------\r\n";
   symbolOrdersStatus += spacer + "| BUY STOP ORDERS: \r\n";
   symbolOrdersStatus += spacer + "|     Total Open:   " + (string)symbolBuyStopOrdersTotal + "\r\n";
   symbolOrdersStatus += spacer + "|     Total Volume: " + (string)symbolBuyStopOrdersVolumeTotal + "\r\n";
   symbolOrdersStatus += spacer + "|------------------------------------------------------------------\r\n";
   symbolOrdersStatus += spacer + "| BUY LIMIT ORDERS: \r\n";
   symbolOrdersStatus += spacer + "|     Total Open:   " + (string)symbolBuyLimitOrdersTotal + "\r\n";
   symbolOrdersStatus += spacer + "|     Total Volume: " + (string)symbolBuyLimitOrdersVolumeTotal + "\r\n";
   symbolOrdersStatus += spacer + "|---------------------------------------------------------------------------\r\n";
   symbolOrdersStatus += spacer + "| SELL STOP ORDERS: \r\n";
   symbolOrdersStatus += spacer + "|     Total Open:   " + (string)symbolSellStopOrdersTotal + "\r\n";
   symbolOrdersStatus += spacer + "|     Total Volume: " + (string)symbolSellStopOrdersVolumeTotal + "\r\n";
   symbolOrdersStatus += spacer + "|------------------------------------------------------------------\r\n";
   symbolOrdersStatus += spacer + "| SELL LIMIT ORDERS: \r\n";
   symbolOrdersStatus += spacer + "|     Total Open:   " + (string)symbolSellLimitOrdersTotal + "\r\n";
   symbolOrdersStatus += spacer + "|     Total Volume: " + (string)symbolSellLimitOrdersVolumeTotal + "\r\n";
   symbolOrdersStatus += spacer + "|---------------------------------------------------------------------------\r\n";
   symbolOrdersStatus += spacer + "\r\n";
   return(symbolOrdersStatus);
  }

Las amplias funciones de biblioteca que hemos creado anteriormente conforman nuestra biblioteca Pending Orders Management EX5. Al final de este artículo encontrará el archivo de código fuente, PendingOrdersManager.mq5, así como el archivo ejecutable binario compilado, PendingOrdersManager.ex5, que puede importar y utilizar fácilmente en sus proyectos MQL5.


Cómo importar e implementar nuestra biblioteca EX5 de gestión de órdenes pendientes

Hemos desarrollado una sólida biblioteca EX5 de gestión de órdenes pendientes, que incluye funciones esenciales para manejar órdenes pendientes, obtener su estado y mostrar información relevante. Ahora es el momento de documentar y demostrar cómo importar y utilizar correctamente esta biblioteca en cualquier proyecto MQL5.

Para facilitar el proceso de implementación, comenzaremos por describir todas las funciones y módulos de la biblioteca de gestión de órdenes pendientes, junto con ejemplos prácticos de código en la sección de documentación que figura a continuación. Esto proporcionará a los usuarios una comprensión clara de los componentes incluidos en el archivo binario PendingOrdersManager.ex5.


Documentación de la biblioteca EX5 "Pending Orders Manager"

Paso 1: Copie los archivos ejecutables de la biblioteca (PositionsManager.ex5 y PendingOrdersManager.ex5).

Coloque los archivos PositionsManager.ex5 y PendingOrdersManager.ex5 en la carpeta MQL5/Libraries/Toolkit o en la misma carpeta que el archivo de código fuente que importa la biblioteca. Asegúrese de que estos archivos se descarguen y copien en la ubicación especificada si aún no se encuentran allí. Se adjuntan copias de ambos archivos al final de este artículo para su comodidad.

Paso 2: Importar las descripciones de los prototipos de funciones.

En la sección de encabezado de tu código fuente, añade las directivas import para la biblioteca Pending Orders Manager y sus descripciones de prototipos de funciones. Utilice el siguiente segmento de código para importar de manera eficiente todas las funciones o módulos de la biblioteca PendingOrdersManager.ex5. También he creado una plantilla en blanco para el Asesor Experto (PendingOrdersManager_Imports_Template.mq5) que incluye este segmento de código. Puede comentar o eliminar cualquier descripción de función que no necesite para su proyecto. El archivo PendingOrdersManager_Imports_Template.mq5 también se adjunta al final de este artículo.

//+------------------------------------------------------------------------------------------+
//-- Copy and paste the import derictives below to use the Pending Orders Manager EX5 Library
//---
//+-------------------------------------------------------------------------------------+
//| PendingOrdersManager.ex5 imports template                                           |
//+-------------------------------------------------------------------------------------+
#import "Toolkit/PendingOrdersManager.ex5" //-- Opening import directive
//-- Function descriptions for the imported function prototypes

//-- Pending Orders Execution and Modification Functions
bool OpenBuyLimit(ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment);
bool OpenBuyStop(ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment);
bool OpenSellLimit(ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment);
bool OpenSellStop(ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment);
bool ModifyPendingOrderByTicket(ulong orderTicket, double newEntryPrice, int newSl, int newTp);
bool DeletePendingOrderByTicket(ulong orderTicket);
bool DeleteAllPendingOrders(string symbol, ulong magicNumber);
bool DeleteAllPendingOrders();
bool DeleteAllBuyStops(string symbol, ulong magicNumber);
bool DeleteAllBuyLimits(string symbol, ulong magicNumber);
bool DeleteAllSellStops(string symbol, ulong magicNumber);
bool DeleteAllSellLimits(string symbol, ulong magicNumber);
bool DeleteAllMagicOrders(ulong magicNumber);

//-- Pending Orders Status Monitoring Functions
int BuyStopOrdersTotal();
int BuyLimitOrdersTotal();
int SellStopOrdersTotal();
int SellLimitOrdersTotal();
double OrdersTotalVolume();
double BuyStopOrdersTotalVolume();
double BuyLimitOrdersTotalVolume();
double SellStopOrdersTotalVolume();
double SellLimitOrdersTotalVolume();

//-- Pending Orders Filtered By Magic Number Status Monitoring Functions
int MagicOrdersTotal(ulong magicNumber);
int MagicBuyStopOrdersTotal(ulong magicNumber);
int MagicBuyLimitOrdersTotal(ulong magicNumber);
int MagicSellStopOrdersTotal(ulong magicNumber);
int MagicSellLimitOrdersTotal(ulong magicNumber);
double MagicOrdersTotalVolume(ulong magicNumber);
double MagicBuyStopOrdersTotalVolume(ulong magicNumber);
double MagicBuyLimitOrdersTotalVolume(ulong magicNumber);
double MagicSellStopOrdersTotalVolume(ulong magicNumber);
double MagicSellLimitOrdersTotalVolume(ulong magicNumber);

//-- Pending Orders Filtered By Symbol and/or Magic Number Status Monitoring Functions
int SymbolOrdersTotal(string symbol, ulong magicNumber);
int SymbolBuyStopOrdersTotal(string symbol, ulong magicNumber);
int SymbolBuyLimitOrdersTotal(string symbol, ulong magicNumber);
int SymbolSellStopOrdersTotal(string symbol, ulong magicNumber);
int SymbolSellLimitOrdersTotal(string symbol, ulong magicNumber);
double SymbolOrdersTotalVolume(string symbol, ulong magicNumber);
double SymbolBuyStopOrdersTotalVolume(string symbol, ulong magicNumber);
double SymbolBuyLimitOrdersTotalVolume(string symbol, ulong magicNumber);
double SymbolSellStopOrdersTotalVolume(string symbol, ulong magicNumber);
double SymbolSellLimitOrdersTotalVolume(string symbol, ulong magicNumber);

//-- Log and Data Display Functions
string AccountOrdersStatus(bool formatForComment);
string MagicOrdersStatus(ulong magicNumber, bool formatForComment);
string SymbolOrdersStatus(string symbol, ulong magicNumber, bool formatForComment);

#import //--- Closing import directive
//+-------------------------------------------------------------------------------------+

Ahora que las funciones prototipo de la biblioteca .EX5 se han importado a su proyecto MQL5 o código fuente, la tabla siguiente proporciona documentación detallada y ejemplos prácticos sobre cómo implementar y utilizar estas funciones en su código.

Descripción del prototipo de la función Descripción Ejemplo de caso de uso
bool OpenBuyLimit(
   ulong magicNumber,
   string symbol,
   double entryPrice,
   double lotSize,
   int sl,
   int tp,
   string orderComment
);


Abre una nueva orden de compra limitada que coincide con los parámetros especificados.
double symbolPoint = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
int spread = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
//---
ulong magicNo = 123;
string symbol = _Symbol;
double entryPrice = SymbolInfoDouble(
                       _Symbol, SYMBOL_ASK) - ((spread * 20) 
                       * symbolPoint
                    );
double lotSize = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);
int sl = spread * 50;  //-- pips
int tp = spread * 100; //-- pips
string orderComment = "Pending Orders Manager Buy Limit Order";
OpenBuyLimit(
   magicNumber, symbol, entryPrice, 
   lotSize, sl, tp, orderComment
);

bool OpenBuyStop(
   ulong magicNumber,
   string symbol,
   double entryPrice,
   double lotSize,
   int sl,
   int tp,
   string orderComment
);


Abre una nueva orden de compra stop (Buy stop) que coincide con los parámetros especificados.
double symbolPoint = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
int spread = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
//---
ulong magicNo = 123;
string symbol = _Symbol;
double entryPrice = SymbolInfoDouble(
                       _Symbol, SYMBOL_ASK) + ((spread * 20) 
                       * symbolPoint
                    );
double lotSize = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);
int sl = spread * 50;  //-- pips
int tp = spread * 100; //-- pips
string orderComment = "Pending Orders Manager Buy Stop Order";
OpenBuyStop(
   magicNumber, symbol, entryPrice, 
   lotSize, sl, tp, orderComment
);

bool OpenSellLimit(
   ulong magicNumber,
   string symbol,
   double entryPrice,
   double lotSize,
   int sl,
   int tp,
   string orderComment
);


Abre una nueva orden de venta limitada (Sell Limit) que coincide con los parámetros especificados.
double symbolPoint = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
int spread = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
//---
ulong magicNo = 123;
string symbol = _Symbol;
double entryPrice = SymbolInfoDouble(
                       _Symbol, SYMBOL_ASK) + ((spread * 20) 
                       * symbolPoint
                    );
double lotSize = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);
int sl = spread * 50;  //-- pips
int tp = spread * 100; //-- pips
string orderComment = "Pending Orders Manager Sell Limit Order";
OpenSellLimit(
   magicNumber, symbol, entryPrice, 
   lotSize, sl, tp, orderComment
);

bool OpenSellStop(
   ulong magicNumber,
   string symbol,
   double entryPrice,
   double lotSize,
   int sl,
   int tp,
   string orderComment
);


Abre una nueva orden de venta stop (Sell Stop) que coincide con los parámetros especificados.
double symbolPoint = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
int spread = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
//---
ulong magicNo = 123;
string symbol = _Symbol;
double entryPrice = SymbolInfoDouble(
                       _Symbol, SYMBOL_ASK) - ((spread * 20) 
                       * symbolPoint
                    );
double lotSize = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);
int sl = spread * 50;  //-- pips
int tp = spread * 100; //-- pips
string orderComment = "Pending Orders Manager Sell Stop Order";
OpenSellStop(
   magicNumber, symbol, entryPrice, 
   lotSize, sl, tp, orderComment
);

bool ModifyPendingOrderByTicket(
   ulong orderTicket,
   double newEntryPrice,
   int newSl,
   int newTp
);

Modifica una orden pendiente utilizando los parámetros especificados.
double symbolPoint = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
int spread = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
int totalOpenOders = OrdersTotal();
for(int x = 0; x < totalOpenOders; x++)
  {
   ulong orderTicket = OrderGetTicket(x);
   if(orderTicket > 0)
     {
      //-- Modify a buy stop order
      if(OrderGetInteger(ORDER_TYPE) == ORDER_TYPE_BUY_STOP)
        {
         double newEntryPrice = OrderGetDouble(
                                   ORDER_PRICE_OPEN) + 
                                   ((spread * 40) * symbolPoint
                                );
         int newSl = 0; //-- Do not modify the stop loss level
         int newTp = 0; //-- Don not modify the take profit level
         ModifyPendingOrderByTicket(
            orderTicket, newEntryPrice, newSl, newTp
         );
         break;
        }
     }
  }

bool DeletePendingOrderByTicket(
   ulong orderTicket
);

Elimina una orden pendiente basándose en el parámetro del número de ticket proporcionado.
for(int x = 0; x < totalOpenOders; x++)
  {
   ulong orderTicket = OrderGetTicket(x);
   if(orderTicket > 0)
     {
      DeletePendingOrderByTicket(orderTicket);
      break;
     }
  }

bool DeleteAllPendingOrders(
   string symbol = ALL_SYMBOLS,
   ulong magicNumber = 0
);

Elimina todas las órdenes pendientes basadas en los parámetros de nombre de símbolo y número mágico proporcionados.
//Deletes all orders in the account
DeleteAllPendingOrders("", 0);

//Deletes all orders belonging to the symbol
DeleteAllPendingOrders(_Symbol, 0);

//Deletes all orders that have a magic number 101
DeleteAllPendingOrders("", 101);

//Deletes all EURUSD orders that have a magic number 101
DeleteAllPendingOrders("EURUSD", 101);

bool DeleteAllPendingOrders()

Simplemente elimina todas las órdenes pendientes abiertas en la cuenta.
//Deletes all orders in the account
DeleteAllPendingOrders();

bool DeleteAllBuyStops(
   string symbol = ALL_SYMBOLS,
   ulong magicNumber = 0
);

Elimina todas las órdenes de compra stop (Buy Stop) basadas en los parámetros de nombre de símbolo y número mágico proporcionados.
//Deletes all buy stops in the account
DeleteAllBuyStops("", 0);

//Deletes all buy stops belonging to the symbol
DeleteAllBuyStops(_Symbol, 0);

//Deletes all buy stops that have a magic number 101
DeleteAllBuyStops("", 101);

//Deletes all EURUSD buy stops that have a magic number 101
DeleteAllBuyStops("EURUSD", 101);

bool DeleteAllBuyLimits(
   string symbol = ALL_SYMBOLS,
   ulong magicNumber = 0
);

Elimina todas las órdenes de compra con límite (Buy Limit) basadas en los parámetros de nombre de símbolo y número mágico proporcionados.
//Deletes all buy limits in the account
DeleteAllBuyLimits("", 0);

//Deletes all buy limits belonging to the symbol
DeleteAllBuyLimits(_Symbol, 0);

//Deletes all buy limits that have a magic number 101
DeleteAllBuyLimits("", 101);

//Deletes all GBPUSD buy limits that have a magic number 101
DeleteAllBuyLimits("GBPUSD", 101);

bool DeleteAllSellStops(
   string symbol = ALL_SYMBOLS,
   ulong magicNumber = 0
);

Elimina todas las órdenes stop de venta (Sell Stop) basadas en los parámetros de nombre de símbolo y número mágico proporcionados.
//Deletes all sell stops in the account
DeleteAllSellStops("", 0);

//Deletes all sell stops belonging to the symbol
DeleteAllSellStops(_Symbol, 0);

//Deletes all sell stops that have a magic number 101
DeleteAllSellStops("", 101);

//Deletes all JPYUSD sell stops that have a magic number 101
DeleteAllSellStops("JPYUSD", 101);

bool DeleteAllSellLimits(
   string symbol = ALL_SYMBOLS,
   ulong magicNumber = 0
);

Elimina todas las órdenes de venta con límite basadas en los parámetros de nombre de símbolo y número mágico proporcionados.
//Deletes all sell limits in the account
DeleteAllSellLimits("", 0);

//Deletes all sell limits belonging to the symbol
DeleteAllSellLimits(_Symbol, 0);

//Deletes all sell limits that have a magic number 101
DeleteAllSellLimits("", 101);

//Deletes all AUDJPY sell limits that have a magic number 101
DeleteAllSellLimits("AUDJPY", 101);


bool DeleteAllMagicOrders(
   ulong magicNumber
);

Elimina todos los pedidos pendientes según el parámetro de número mágico proporcionado.
//-- Deletes all orders open in the account
DeleteAllMagicOrders("", 0);

//-- Deletes all orders that have a magic number 101
DeleteAllMagicOrders(101);

int BuyStopOrdersTotal();

Devuelve el número total de órdenes de stop de compra (Buy Stop) abiertas.
//Get the total number of open buy stops in the account
BuyStopOrdersTotal();


int BuyLimitOrdersTotal();

Devuelve el número total de órdenes límite de compra (Buy Limit) abiertas.
//Get the total number of open buy limits in the account
BuyLimitOrdersTotal();


int SellStopOrdersTotal();

Devuelve el número total de órdenes de venta stop (Sell Stop) abiertas.
//Get the total number of open sell stops in the account
SellStopOrdersTotal();


int SellLimitOrdersTotal();

Devuelve el número total de órdenes de venta limitadas (Sell Limit) abiertas.
//Get the total number of open sell limits in the account
SellLimitOrdersTotal();


double OrdersTotalVolume();

Devuelve el volumen total de todas las órdenes abiertas.
//Get the total volume/lot of open orders in the account
OrdersTotalVolume();


double BuyStopOrdersTotalVolume();

Devuelve el volumen total de todas las órdenes de compra stop (Buy Stop).
//Get the total volume/lot of open buy stops in the account
BuyStopOrdersTotalVolume();


double BuyLimitOrdersTotalVolume();

Devuelve el volumen total de todas las órdenes de límite de compra (Buy Limit).
//Get the total volume/lot of open buy limits in the account
BuyLimitOrdersTotalVolume();


double SellStopOrdersTotalVolume();

Devuelve el volumen total de todas las órdenes de venta stop (Sell Stop).
//Get the total volume/lot of open sell stops in the account
SellStopOrdersTotalVolume();

double SellLimitOrdersTotalVolume();


Devuelve el volumen total de todas las órdenes de venta límite (Sell Limit).
//Get the total volume/lot of open sell limits in the account
SellLimitOrdersTotalVolume();

int MagicOrdersTotal(
   ulong magicNumber
);


Devuelve el número de órdenes abiertas que coinciden con el número mágico especificado.
//Get the total open pending orders for magic number 101
MagicOrdersTotal(101);


int MagicBuyStopOrdersTotal(
   ulong magicNumber
);


Devuelve el número de órdenes de compra stop (Buy Stop) abiertas que coinciden con el número mágico especificado.
//Get the total open buy stop orders for magic number 101
MagicBuyStopOrdersTotal(101);


int MagicBuyLimitOrdersTotal(
   ulong magicNumber
);


Devuelve la cantidad de órdenes límite de compra (Buy Limit) abiertas que coinciden con el número mágico especificado.
//Get the total open buy limit orders for magic number 101
MagicBuyLimitOrdersTotal(101);


int MagicSellStopOrdersTotal(
   ulong magicNumber
);


Devuelve el número de órdenes de venta stop (Sell Stop) abiertas que coinciden con el número mágico especificado.
//Get the total open sell stop orders for magic number 101
MagicSellStopOrdersTotal(101);


int MagicSellLimitOrdersTotal(
   ulong magicNumber
);

Devuelve la cantidad de órdenes de venta limitada abiertas que coinciden con el número mágico especificado.
//Get the total open sell limit orders for magic number 101
MagicSellLimitOrdersTotal(101);


double MagicOrdersTotalVolume(
   ulong magicNumber
);

Devuelve el volumen total de todas las órdenes abiertas que coinciden con el número mágico especificado.
//Get the total volume/lot of all open orders for magic 101
MagicOrdersTotalVolume(101);

double MagicBuyStopOrdersTotalVolume(
   ulong magicNumber
);


Devuelve el volumen total de todas las órdenes de compra stop (Buy Stop) abiertas que coinciden con el número mágico especificado.
//Get the total volume/lot of all buy stop orders for magic 101
MagicBuyStopOrdersTotalVolume(101);

double MagicBuyLimitOrdersTotalVolume(
   ulong magicNumber
);


Devuelve el volumen total de todas las órdenes de compra limitadas (Buy Limit) abiertas que coinciden con el número mágico especificado.
//Get the total volume/lot of all buy limit orders for magic 101
MagicBuyLimitOrdersTotalVolume(101);

double MagicSellStopOrdersTotalVolume(
   ulong magicNumber
);


Devuelve el volumen total de todas las órdenes de venta stop (Sell Stop) abiertas que coinciden con el número mágico especificado.
//Get the total volume/lot of all sell stop orders for magic 101
MagicSellStopOrdersTotalVolume(101);

double MagicSellLimitOrdersTotalVolume(
   ulong magicNumber
);


Devuelve el volumen total de todas las órdenes de venta limitada (Sell Limit) abiertas que coinciden con el número mágico especificado.
//Get the total volume/lot of all sell limit orders for magic 101
MagicSellLimitOrdersTotalVolume(101);

int SymbolOrdersTotal(
   string symbol,
   ulong magicNumber
);

Devuelve la cantidad de órdenes abiertas que coinciden con el símbolo especificado y el número mágico.
//Get the total open orders for the symbol
SymbolOrdersTotal(_Symbol, 0);

//Get the total open orders for the symbol and magic 101
SymbolOrdersTotal(_Symbol, 101);


int SymbolBuyStopOrdersTotal(
   string symbol,
   ulong magicNumber
);


Devuelve el número de órdenes de compra stop (Buy Stop) abiertas que coinciden con el símbolo especificado y el número mágico.
//Get the total buy stop orders for the symbol
SymbolBuyStopOrdersTotal(_Symbol, 0);

//Get the total buy stop orders for the symbol and magic number 101
SymbolBuyStopOrdersTotal(_Symbol, 101);


int SymbolBuyLimitOrdersTotal(
   string symbol,
   ulong magicNumber
);


Devuelve la cantidad de órdenes de compra limitadas (Buy Limit) abiertas que coinciden con el símbolo especificado y el número mágico.
//Get the total buy limit orders for the symbol
SymbolBuyLimitOrdersTotal(_Symbol, 0);

//Get the total buy limit orders for the symbol and magic number 101
SymbolBuyLimitOrdersTotal(_Symbol, 101);


int SymbolSellStopOrdersTotal(
   string symbol,
   ulong magicNumber
);


Devuelve el número de órdenes de venta stop (Sell Stop) abiertas que coinciden con el símbolo especificado y el número mágico.
//Get the total sell stop orders for the symbol
SymbolSellStopOrdersTotal(_Symbol, 0);

//Get the total sell stop orders for the symbol and magic 101
SymbolSellStopOrdersTotal(_Symbol, 101);


int SymbolSellLimitOrdersTotal(
   string symbol,
   ulong magicNumber
);


Devuelve la cantidad de órdenes de venta limitada abiertas que coinciden con el símbolo especificado y el número mágico.
//Get the total sell limit orders for the symbol
SymbolSellLimitOrdersTotal(_Symbol, 0);

//Get the total sell limit orders for the symbol and magic 101
SymbolSellLimitOrdersTotal(_Symbol, 101);


double SymbolOrdersTotalVolume(
   string symbol,
   ulong magicNumber
);


Devuelve el volumen total de todas las órdenes abiertas que coinciden con el símbolo especificado y el número mágico.
//Get the total orders volume/lot for the symbol
SymbolOrdersTotalVolume(_Symbol, 0);

//Get the total orders volume/lot for the symbol and magic 101
SymbolOrdersTotalVolume(_Symbol, 101);


double SymbolBuyStopOrdersTotalVolume(
   string symbol,
   ulong magicNumber
);

Devuelve el volumen total de todas las órdenes de compra stop (Buy Stop) abiertas que coinciden con el símbolo especificado y el número mágico.
//Get the total buy stops volume/lot for the symbol
SymbolBuyStopOrdersTotalVolume(_Symbol, 0);

//Get the total buy stops volume/lot for the symbol and magic 101
SymbolBuyStopOrdersTotalVolume(_Symbol, 101);

double SymbolBuyLimitOrdersTotalVolume(
   string symbol,
   ulong magicNumber
);


Devuelve el volumen total de todas las órdenes de compra limitadas (Buy Limit) abiertas que coinciden con el símbolo especificado y el número mágico.
//Get the total buy limits volume/lot for the symbol
SymbolBuyLimitOrdersTotalVolume(_Symbol, 0);

//Get the total buy limits volume/lot for symbol and magic 101
SymbolBuyLimitOrdersTotalVolume(_Symbol, 101);

double SymbolSellStopOrdersTotalVolume(
   string symbol,
   ulong magicNumber
);


Devuelve el volumen total de todas las órdenes de venta stop (Sell Stop) abiertas que coinciden con el símbolo especificado y el número mágico.
//Get the total sell stops volume/lot for symbol
SymbolSellStopOrdersTotalVolume(_Symbol, 0);

//Get the total sell stops volume/lot for symbol and magic 101
SymbolSellStopOrdersTotalVolume(_Symbol, 101);

double SymbolSellLimitOrdersTotalVolume(
   string symbol,
   ulong magicNumber
);


Devuelve el volumen total de todas las órdenes de venta limitada (Sell Limit) abiertas que coinciden con el símbolo y el número mágico especificados.
//Get the total sell limits volume/lot for symbol
SymbolSellLimitOrdersTotalVolume(_Symbol, 0);

//Get the total sell limits volume/lot for symbol and magic 101
SymbolSellLimitOrdersTotalVolume(_Symbol, 101);

string AccountOrdersStatus(
   bool formatForComment
);


Imprime un estado con formato de cadena de todas las órdenes abiertas en el gráfico de símbolos o en la pestaña Expertos en MetaTrader 5.
//Print the status of all open orders 
//formatted for the chart comments
Comment(AccountOrdersStatus(true));

//Print the status of all open orders 
//formatted for the Experts tab
Print(AccountOrdersStatus(false));

//Activate an alert with the status of all 
//open orders formatted for printing
Print(AccountOrdersStatus(false));


string MagicOrdersStatus(
   ulong magicNumber,
   bool formatForComment
);


Imprime un estado con formato de cadena de todas las órdenes abiertas que coinciden con el número mágico especificado en el gráfico de símbolos o en la pestaña Expertos en MetaTrader 5.
//Print the status of all open orders matching 
//magic number 101 formatted for the chart comments
Comment(MagicOrdersStatus(101, true));

//Print the status of all open orders matching
//magic number 101 formatted for the Experts tab
Print(MagicOrdersStatus(101, false));

//Activate an alert with the status of all open orders
//matching magic number 101 formatted for printing
Print(MagicOrdersStatus(101, false));


 
string SymbolOrdersStatus(
   string symbol,
   ulong magicNumber,
   bool formatForComment
);

Imprime un estado con formato de cadena de todas las órdenes abiertas que coinciden con el símbolo especificado y el número mágico en el gráfico de símbolos o en la pestaña Expertos en MetaTrader 5.  
//Print the status of all open orders matching
//the symbol and magic number 101 formatted for the chart comments
Comment(SymbolOrdersStatus(_Symbol, 101, true));

//Print the status of all open orders matching
//the symbol and magic number 101 formatted for the Experts tab
Print(SymbolOrdersStatus(_Symbol, 101, false));

//Activate an alert with the status of all open orders
//matching the symbol and magic number 101 formatted for printing
Print(SymbolOrdersStatus(_Symbol, 101, false));

Una vez importada la biblioteca, ahora puede fácilmente abrir, modificar, eliminar o recuperar datos del estado de los pedidos pendientes mediante simples llamadas a funciones. Para demostrarlo, en la siguiente sección crearemos un panel de negociación con interfaz gráfica de usuario (GUI) práctico para gestionar las órdenes pendientes.


Cómo desarrollar un panel de órdenes pendientes (GUI) con la biblioteca Pending Orders Manager EX5

En esta sección, desarrollaremos una interfaz gráfica de usuario (GUI) para un Asesor Experto Pending Orders Panel, que utiliza la biblioteca Pending Orders Manager EX5 para abrir, eliminar y monitorear todas las órdenes asociadas a un número mágico específico vinculado al panel. Este ejemplo proporciona una demostración práctica de cómo importar e implementar la biblioteca EX5 que acabamos de crear en una aplicación MQL5 del mundo real.

El panel de órdenes pendientes aprovechará la biblioteca estándar MQL5 para paneles y cuadros de diálogo, lo que nos permitirá mantener la base de código mínima y eficiente. A continuación se muestra una imagen de la GUI final del panel de órdenes pendientes.

Panel de órdenes pendientes MQL5 (GUI)

Para empezar a crear la interfaz gráfica de usuario, cree un nuevo Asesor Experto utilizando el Asistente MQL del IDE MetaEditor y asígnele el nombre PendingOrdersPanel.mq5. Dado que nuestro Asesor Experto del Panel de Órdenes Pendiente integrará la biblioteca PendingOrdersManager.ex5, el primer paso es importar e incluir las descripciones de los prototipos de funciones de la biblioteca, tal y como se ha descrito anteriormente. Coloca el código de importación de la biblioteca justo debajo de las directivas #property. Dado que la biblioteca contiene numerosas funciones, solo importaremos los prototipos de funciones específicos necesarios, que se enumeran en el código siguiente.

#import "Toolkit/PendingOrdersManager.ex5" //-- Opening import directive
//-- Function descriptions for the imported function prototypes

//-- Pending Orders Execution and Modification Functions
bool OpenBuyLimit(ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment);
bool OpenBuyStop(ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment);
bool OpenSellLimit(ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment);
bool OpenSellStop(ulong magicNumber, string symbol, double entryPrice, double lotSize, int sl, int tp, string orderComment);
//--
int MagicOrdersTotal(ulong magicNumber);
int MagicBuyStopOrdersTotal(ulong magicNumber);
int MagicBuyLimitOrdersTotal(ulong magicNumber);
int MagicSellStopOrdersTotal(ulong magicNumber);
int MagicSellLimitOrdersTotal(ulong magicNumber);
//--
bool DeleteAllBuyStops(string symbol, ulong magicNumber);
bool DeleteAllBuyLimits(string symbol, ulong magicNumber);
bool DeleteAllSellStops(string symbol, ulong magicNumber);
bool DeleteAllSellLimits(string symbol, ulong magicNumber);
bool DeleteAllMagicOrders(ulong magicNumber);

#import //--- Closing import directive

Crea las variables globales que utilizaremos para almacenar las propiedades del pedido.

//-- Global variables
//-----------------------
ulong magicNo = 10101010;
double symbolPoint = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
long symbolDigits = SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
int spread = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
double volumeLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
int sl = (int)spread * 50;
int tp = (int)spread * 100;

A continuación, debemos definir algunas constantes para almacenar todas las propiedades de los objetos gráficos. Esto nos facilitará la tarea de actualizar o modificar sus valores en un lugar centralizado en caso de que queramos realizar algún cambio en la apariencia de los paneles de pedidos.

//-- Define some values for the main panel
#define MAIN_PANEL_NAME string("Orders Panel - Trading: " + _Symbol + " - Magic No: " + IntegerToString(magicNo))
#define MAIN_PANEL_SUBWINDOW 0
#define MAIN_PANEL_X1 350
#define MAIN_PANEL_Y1 10
#define MAIN_PANEL_WIDTH int(800 + MAIN_PANEL_X1)
#define MAIN_PANEL_X2 MAIN_PANEL_WIDTH

//-- Define the GUI objects general properties
#define GUI_OBJECTS_MARGIN 5
#define GUI_OBJECTS_HEIGHT 40//40
#define GUI_OBJECTS_WIDTH int((MAIN_PANEL_WIDTH) / 7)
#define GUI_OBJECTS_FONT_SIZE 9//10
#define GUI_OBJECTS_HEADER_FONT_SIZE GUI_OBJECTS_FONT_SIZE
//-----
#define MAIN_PANEL_HEIGHT int(((GUI_OBJECTS_HEIGHT + (GUI_OBJECTS_MARGIN * 2)) * 10) + MAIN_PANEL_Y1)
#define MAIN_PANEL_Y2 MAIN_PANEL_HEIGHT

//-- Define the GUI objects colors
#define GUI_OBJECTS_HEADING_COLOR clrNavy

#define GUI_OBJECTS_BUY_BTN_COLOR clrWhite
#define GUI_OBJECTS_BUY_BTN_BG_COLOR clrBlue
#define GUI_OBJECTS_BUY_EDIT_COLOR clrBlue
#define GUI_OBJECTS_BUY_EDIT_BG_COLOR clrAliceBlue

#define GUI_OBJECTS_SELL_BTN_COLOR clrWhite
#define GUI_OBJECTS_SELL_BTN_BG_COLOR clrCrimson
#define GUI_OBJECTS_SELL_EDIT_COLOR clrMaroon
#define GUI_OBJECTS_SELL_EDIT_BG_COLOR clrMistyRose

/*------------------------------------------------------
* Define GUI components for the heading labels ****
*-----------------------------------------------------*/
//-- Define values for the lotVolHeaderLabel
#define VOLUME_LOT_LABEL_NAME "Volume Lot Header Label"
#define VOLUME_LOT_LABEL_SUBWINDOW 0
#define VOLUME_LOT_LABEL_X1 int(GUI_OBJECTS_MARGIN + GUI_OBJECTS_WIDTH)
#define VOLUME_LOT_LABEL_Y1 int(GUI_OBJECTS_MARGIN * 2)
#define VOLUME_LOT_LABEL_TEXT "VOLUME/LOT"


//-- Define values for the openPriceHeaderLabel
#define OPEN_PRICE_LABEL_NAME "Open Price Header Label"
#define OPEN_PRICE_LABEL_SUBWINDOW 0
#define OPEN_PRICE_LABEL_X1 (int(GUI_OBJECTS_WIDTH) * 2)
#define OPEN_PRICE_LABEL_Y1 int(GUI_OBJECTS_MARGIN * 2)
#define OPEN_PRICE_LABEL_TEXT "OPENING PRICE"

//-- Define values for the slHeaderLabel
#define SL_LABEL_NAME "Sl Header Label"
#define SL_LABEL_SUBWINDOW 0
#define SL_LABEL_X1 (int(GUI_OBJECTS_WIDTH) * 3)
#define SL_LABEL_Y1 int(GUI_OBJECTS_MARGIN * 2)
#define SL_LABEL_TEXT "SL (Pips)"

//-- Define values for the tpHeaderLabel
#define TP_LABEL_NAME "Tp Header Label"
#define TP_LABEL_SUBWINDOW 0
#define TP_LABEL_X1 (int(GUI_OBJECTS_WIDTH) * 3.75)
#define TP_LABEL_Y1 int(GUI_OBJECTS_MARGIN * 2)
#define TP_LABEL_TEXT "TP (Pips)"

/*------------------------------------------------------
* Define Buy Stop Order GUI components ****
*-----------------------------------------------------*/
//-- Define values for the buyStopBtn
#define BUY_STOP_BTN_NAME "Buy Stop Button"
#define BUY_STOP_BTN_SUBWINDOW 0
#define BUY_STOP_BTN_X1 GUI_OBJECTS_MARGIN
#define BUY_STOP_BTN_Y1 int(GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT)
#define BUY_STOP_BTN_TEXT "BUY STOP"

//-- Define values for the buyStopVolumeLotEdit
#define BUY_STOP_VOLUME_LOT_EDIT_NAME "Buy Stop Volume Lot Edit"
#define BUY_STOP_VOLUME_LOT_EDIT_SUBWINDOW 0
#define BUY_STOP_VOLUME_LOT_EDIT_X1 int(GUI_OBJECTS_MARGIN + GUI_OBJECTS_WIDTH)
#define BUY_STOP_VOLUME_LOT_EDIT_Y1 int(GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT)

//-- Define values for the buyStopOpenPriceEdit
#define BUY_STOP_OPEN_PRICE_EDIT_NAME "Buy Stop Open Price Edit"
#define BUY_STOP_OPEN_PRICE_EDIT_SUBWINDOW 0
#define BUY_STOP_OPEN_PRICE_EDIT_X1 int((GUI_OBJECTS_WIDTH) * 2)
#define BUY_STOP_OPEN_PRICE_EDIT_Y1 int(GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT)

//-- Define values for the buyStopSlEdit
#define BUY_STOP_SL_EDIT_NAME "Buy Stop SL Edit"
#define BUY_STOP_SL_EDIT_SUBWINDOW 0
#define BUY_STOP_SL_EDIT_X1 int(GUI_OBJECTS_WIDTH * 3)
#define BUY_STOP_SL_EDIT_Y1 int(GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT)

//-- Define values for the buyStopTpEdit
#define BUY_STOP_TP_EDIT_NAME "Buy Stop TP Edit"
#define BUY_STOP_TP_EDIT_SUBWINDOW 0
#define BUY_STOP_TP_EDIT_X1 int(GUI_OBJECTS_WIDTH * 3.7)
#define BUY_STOP_TP_EDIT_Y1 int(GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT)

/*------------------------------------------------------
* Define Sell Stop Order GUI components ****
*-----------------------------------------------------*/
//-- Define values for the sellStopBtn
#define SELL_STOP_BTN_NAME "Sell Stop Button"
#define SELL_STOP_BTN_SUBWINDOW 0
#define SELL_STOP_BTN_X1 GUI_OBJECTS_MARGIN
#define SELL_STOP_BTN_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 2)
#define SELL_STOP_BTN_TEXT "SELL STOP"

//-- Define values for the sellStopVolumeLotEdit
#define SELL_STOP_VOLUME_LOT_EDIT_NAME "Sell Stop Volume Lot Edit"
#define SELL_STOP_VOLUME_LOT_EDIT_SUBWINDOW 0
#define SELL_STOP_VOLUME_LOT_EDIT_X1 int(GUI_OBJECTS_MARGIN + GUI_OBJECTS_WIDTH)
#define SELL_STOP_VOLUME_LOT_EDIT_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 2)

//-- Define values for the sellStopOpenPriceEdit
#define SELL_STOP_OPEN_PRICE_EDIT_NAME "Sell Stop Open Price Edit"
#define SELL_STOP_OPEN_PRICE_EDIT_SUBWINDOW 0
#define SELL_STOP_OPEN_PRICE_EDIT_X1 int((GUI_OBJECTS_WIDTH) * 2)
#define SELL_STOP_OPEN_PRICE_EDIT_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 2)

//-- Define values for the sellStopSlEdit
#define SELL_STOP_SL_EDIT_NAME "Sell Stop SL Edit"
#define SELL_STOP_SL_EDIT_SUBWINDOW 0
#define SELL_STOP_SL_EDIT_X1 int(GUI_OBJECTS_WIDTH * 3)
#define SELL_STOP_SL_EDIT_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 2)

//-- Define values for the sellStopTpEdit
#define SELL_STOP_TP_EDIT_NAME "Sell Stop TP Edit"
#define SELL_STOP_TP_EDIT_SUBWINDOW 0
#define SELL_STOP_TP_EDIT_X1 int(GUI_OBJECTS_WIDTH * 3.7)
#define SELL_STOP_TP_EDIT_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 2)

/*------------------------------------------------------
* Define Buy Limit Order GUI components ****
*-----------------------------------------------------*/
//-- Define values for the buyLimitBtn
#define BUY_LIMIT_BTN_NAME "Buy Limit Button"
#define BUY_LIMIT_BTN_SUBWINDOW 0
#define BUY_LIMIT_BTN_X1 GUI_OBJECTS_MARGIN
#define BUY_LIMIT_BTN_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 3)
#define BUY_LIMIT_BTN_TEXT "BUY LIMIT"

//-- Define values for the buyLimitVolumeLotEdit
#define BUY_LIMIT_VOLUME_LOT_EDIT_NAME "Buy Limit Volume Lot Edit"
#define BUY_LIMIT_VOLUME_LOT_EDIT_SUBWINDOW 0
#define BUY_LIMIT_VOLUME_LOT_EDIT_X1 int(GUI_OBJECTS_MARGIN + GUI_OBJECTS_WIDTH)
#define BUY_LIMIT_VOLUME_LOT_EDIT_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 3)

//-- Define values for the buySLimitOpenPriceEdit
#define BUY_LIMIT_OPEN_PRICE_EDIT_NAME "Buy Limit Open Price Edit"
#define BUY_LIMIT_OPEN_PRICE_EDIT_SUBWINDOW 0
#define BUY_LIMIT_OPEN_PRICE_EDIT_X1 int((GUI_OBJECTS_WIDTH) * 2)
#define BUY_LIMIT_OPEN_PRICE_EDIT_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 3)

//-- Define values for the buyLimitSlEdit
#define BUY_LIMIT_SL_EDIT_NAME "Buy Limit SL Edit"
#define BUY_LIMIT_SL_EDIT_SUBWINDOW 0
#define BUY_LIMIT_SL_EDIT_X1 int(GUI_OBJECTS_WIDTH * 3)
#define BUY_LIMIT_SL_EDIT_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 3)

//-- Define values for the buyLimitTpEdit
#define BUY_LIMIT_TP_EDIT_NAME "Buy Limit TP Edit"
#define BUY_LIMIT_TP_EDIT_SUBWINDOW 0
#define BUY_LIMIT_TP_EDIT_X1 int(GUI_OBJECTS_WIDTH * 3.7)
#define BUY_LIMIT_TP_EDIT_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 3)

/*------------------------------------------------------
* Define Sell Limit Order GUI components ****
*-----------------------------------------------------*/
//-- Define values for the sellLimitBtn
#define SELL_LIMIT_BTN_NAME "Sell Limit Button"
#define SELL_LIMIT_BTN_SUBWINDOW 0
#define SELL_LIMIT_BTN_X1 GUI_OBJECTS_MARGIN
#define SELL_LIMIT_BTN_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 4)
#define SELL_LIMIT_BTN_TEXT "SELL LIMIT"

//-- Define values for the sellLimitVolumeLotEdit
#define SELL_LIMIT_VOLUME_LOT_EDIT_NAME "Sell Limit Volume Lot Edit"
#define SELL_LIMIT_VOLUME_LOT_EDIT_SUBWINDOW 0
#define SELL_LIMIT_VOLUME_LOT_EDIT_X1 int(GUI_OBJECTS_MARGIN + GUI_OBJECTS_WIDTH)
#define SELL_LIMIT_VOLUME_LOT_EDIT_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 4)

//-- Define values for the sellLimitOpenPriceEdit
#define SELL_LIMIT_OPEN_PRICE_EDIT_NAME "Sell Limit Open Price Edit"
#define SELL_LIMIT_OPEN_PRICE_EDIT_SUBWINDOW 0
#define SELL_LIMIT_OPEN_PRICE_EDIT_X1 int((GUI_OBJECTS_WIDTH) * 2)
#define SELL_LIMIT_OPEN_PRICE_EDIT_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 4)

//-- Define values for the sellLimitSlEdit
#define SELL_LIMIT_SL_EDIT_NAME "Sell Limit SL Edit"
#define SELL_LIMIT_SL_EDIT_SUBWINDOW 0
#define SELL_LIMIT_SL_EDIT_X1 int(GUI_OBJECTS_WIDTH * 3)
#define SELL_LIMIT_SL_EDIT_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 4)

//-- Define values for the sellLimitTpEdit
#define SELL_LIMIT_TP_EDIT_NAME "Sell Limit TP Edit"
#define SELL_LIMIT_TP_EDIT_SUBWINDOW 0
#define SELL_LIMIT_TP_EDIT_X1 int(GUI_OBJECTS_WIDTH * 3.7)
#define SELL_LIMIT_TP_EDIT_Y1 int((GUI_OBJECTS_MARGIN + GUI_OBJECTS_HEIGHT) * 4)

/*------------------------------------------------------
* Define Order Status GUI components ****
*-----------------------------------------------------*/
//-- Define values for the orders status
#define STATUS_HEADER_FONT_SIZE int(GUI_OBJECTS_FONT_SIZE)// / 1.1)
#define STATUS_EDIT_FONT_SIZE int(GUI_OBJECTS_FONT_SIZE)// / 1.1)
#define STATUS_EDIT_WIDTH int((MAIN_PANEL_WIDTH / 1.485) - (GUI_OBJECTS_MARGIN * 2))
#define STATUS_EDIT_COLOR clrBlack
#define STATUS_EDIT_BG_COLOR clrLemonChiffon
#define STATUS_EDIT_BORDER_COLOR clrMidnightBlue
#define DELETE_ORDERS_BTN_COLOR clrLightYellow
#define DELETE_BUY_ORDERS_BTN_BG_COLOR clrRoyalBlue
#define DELETE_SELL_ORDERS_BTN_BG_COLOR clrCrimson
#define DELETE_ALL_ORDERS_BTN_BG_COLOR clrMediumVioletRed
#define DELETE_ORDERS_BTN_BORDER_COLOR clrBlack
#define DELETE_ORDERS_BTN_WIDTH int((STATUS_EDIT_WIDTH / 1.93) - (GUI_OBJECTS_MARGIN * 3))
#define DELETE_ORDERS_BTN_FONT_SIZE int((GUI_OBJECTS_FONT_SIZE))// / 1.05)

//-- Define values for the magicOrderStatusLabel
#define MAGIC_ORDER_STATUS_LABEL_NAME "Magic Order Status Label"
#define MAGIC_ORDER_STATUS_LABEL_SUBWINDOW 0
#define MAGIC_ORDER_STATUS_LABEL_X1 int(GUI_OBJECTS_MARGIN * 3)
#define MAGIC_ORDER_STATUS_LABEL_Y1 int((GUI_OBJECTS_HEIGHT * 6) + (GUI_OBJECTS_MARGIN * 2))
#define MAGIC_ORDER_STATUS_LABEL_TEXT string("MAGIC No: " + IntegerToString(magicNo) + " - TOTAL OPEN ORDERS: ")

//-- Define values for the magicOrdersStatusEdit
#define MAGIC_ORDER_STATUS_EDIT_NAME "Magic Order Status Edit"
#define MAGIC_ORDER_STATUS_EDIT_SUBWINDOW 0
#define MAGIC_ORDER_STATUS_EDIT_X1 int(GUI_OBJECTS_MARGIN * 2)
#define MAGIC_ORDER_STATUS_EDIT_Y1 int((MAGIC_ORDER_STATUS_LABEL_Y1) + (GUI_OBJECTS_HEIGHT / 1.7))

//-- Define values for the deleteAllMagicBuyStopsBtn
#define DELETE_ALL_MAGIC_BUY_STOPS_BTN_NAME "Delete All Magic Buy Stops Btn"
#define DELETE_ALL_MAGIC_BUY_STOPS_BTN_SUBWINDOW 0
#define DELETE_ALL_MAGIC_BUY_STOPS_BTN_X1 int(GUI_OBJECTS_MARGIN * 2)
#define DELETE_ALL_MAGIC_BUY_STOPS_BTN_Y1 int((MAGIC_ORDER_STATUS_EDIT_Y1) + (GUI_OBJECTS_HEIGHT + GUI_OBJECTS_MARGIN))
#define DELETE_ALL_MAGIC_BUY_STOPS_BTN_TEXT "DELETE ALL MAGIC BUY STOPS"

//-- Define values for the deleteAllMagicSellStopsBtn
#define DELETE_ALL_MAGIC_SELL_STOPS_BTN_NAME "Delete All Magic Sell Stops Btn"
#define DELETE_ALL_MAGIC_SELL_STOPS_BTN_SUBWINDOW 0
#define DELETE_ALL_MAGIC_SELL_STOPS_BTN_X1 int((GUI_OBJECTS_MARGIN * 3) + DELETE_ORDERS_BTN_WIDTH)
#define DELETE_ALL_MAGIC_SELL_STOPS_BTN_Y1 int((MAGIC_ORDER_STATUS_EDIT_Y1) + (GUI_OBJECTS_HEIGHT + GUI_OBJECTS_MARGIN))
#define DELETE_ALL_MAGIC_SELL_STOPS_BTN_TEXT "DELETE ALL MAGIC SELL STOPS"

//-- Define values for the deleteAllMagicBuyLimitsBtn
#define DELETE_ALL_MAGIC_BUY_LIMITS_BTN_NAME "Delete All Magic Buy Limits Btn"
#define DELETE_ALL_MAGIC_BUY_LIMITS_BTN_SUBWINDOW 0
#define DELETE_ALL_MAGIC_BUY_LIMITS_BTN_X1 int(GUI_OBJECTS_MARGIN * 2)
#define DELETE_ALL_MAGIC_BUY_LIMITS_BTN_Y1 int((DELETE_ALL_MAGIC_BUY_STOPS_BTN_Y1) + (GUI_OBJECTS_HEIGHT + GUI_OBJECTS_MARGIN))
#define DELETE_ALL_MAGIC_BUY_LIMITS_BTN_TEXT "DELETE ALL MAGIC BUY LIMITS"

//-- Define values for the deleteAllMagicSellLimitsBtn
#define DELETE_ALL_MAGIC_SELL_LIMITS_BTN_NAME "Delete All Magic Sell Limits Btn"
#define DELETE_ALL_MAGIC_SELL_LIMITS_BTN_SUBWINDOW 0
#define DELETE_ALL_MAGIC_SELL_LIMITS_BTN_X1 int((GUI_OBJECTS_MARGIN * 3) + DELETE_ORDERS_BTN_WIDTH)
#define DELETE_ALL_MAGIC_SELL_LIMITS_BTN_Y1 DELETE_ALL_MAGIC_BUY_LIMITS_BTN_Y1//int((MAGIC_ORDER_STATUS_EDIT_Y1) + (GUI_OBJECTS_HEIGHT + GUI_OBJECTS_MARGIN))
#define DELETE_ALL_MAGIC_SELL_LIMITS_BTN_TEXT "DELETE ALL MAGIC SELL LIMITS"

//-- Define values for the deleteAllMagicOrdersBtn
#define DELETE_ALL_MAGIC_ORDERS_BTN_NAME "Delete All Magic Orders Btn"
#define DELETE_ALL_MAGIC_ORDERS_BTN_SUBWINDOW 0
#define DELETE_ALL_MAGIC_ORDERS_BTN_X1 int(GUI_OBJECTS_MARGIN * 2)
#define DELETE_ALL_MAGIC_ORDERS_BTN_Y1 int((DELETE_ALL_MAGIC_BUY_LIMITS_BTN_Y1) + (GUI_OBJECTS_HEIGHT + GUI_OBJECTS_MARGIN))
#define DELETE_ALL_MAGIC_ORDERS_BTN_TEXT "DELETE ALL MAGIC PENDING ORDERS"

Añadir o incluir las clases estándar MQL5 para paneles y cuadros de diálogo a nuestro código.

//-- Include the MQL5 standard library for panels and dialogs
#include <Controls\Dialog.mqh>
#include <Controls\Button.mqh>
#include <Controls\Label.mqh>
#include <Controls\Edit.mqh>

Ahora que las clases del panel y del cuadro de diálogo están incluidas y disponibles en nuestro archivo, podemos proceder a crear sus objetos para ampliar su funcionalidad dentro de nuestro código.

//-- Create objects for the included standard classes
CAppDialog mainPanelWindow;

//-- Create the header label components
CLabel lotVolHeaderLabel;
CLabel openPriceHeaderLabel;
CLabel slHeaderLabel;
CLabel tpHeaderLabel;

//-- Create the buy stop GUI components
//--BuyStopBtn
CButton buyStopBtn;
//--BuyStopEdits
CEdit buyStopVolumeLotEdit;
CEdit buyStopOpenPriceEdit;
CEdit buyStopSlEdit;
CEdit buyStopTpEdit;

//-- Create the sell stop GUI components
//--SellStopBtn
CButton sellStopBtn;
//--sellStopEdits
CEdit sellStopVolumeLotEdit;
CEdit sellStopOpenPriceEdit;
CEdit sellStopSlEdit;
CEdit sellStopTpEdit;

//-- Create the buy limit GUI components
//--BuyLimitBtn
CButton buyLimitBtn;
//--BuyLimitEdits
CEdit buyLimitVolumeLotEdit;
CEdit buyLimitOpenPriceEdit;
CEdit buyLimitSlEdit;
CEdit buyLimitTpEdit;

//-- Create the sell limit GUI components
//--sellLimitBtn
CButton sellLimitBtn;
//--sellLimitEdits
CEdit sellLimitVolumeLotEdit;
CEdit sellLimitOpenPriceEdit;
CEdit sellLimitSlEdit;
CEdit sellLimitTpEdit;

//-- Create the order status GUI components
//--magic order status
CLabel magicOrderStatusLabel;
CEdit magicOrdersStatusEdit;
//--Magic orders delete buttons
CButton deleteAllMagicBuyStopsBtn;
CButton deleteAllMagicSellStopsBtn;
CButton deleteAllMagicBuyLimitsBtn;
CButton deleteAllMagicSellLimitsBtn;
CButton deleteAllMagicOrdersBtn;

Cree las variables que se encargarán de almacenar los precios de entrada de las órdenes y una cadena para almacenar el estado de todas las órdenes abiertas por nuestro Asesor Experto.

//-- Default starting entry prices for different pending orders
double buyStopEntryPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK) + ((spread * 20) * symbolPoint);
double buyLimitEntryPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK) - ((spread * 20) * symbolPoint);
double sellStopEntryPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK) - ((spread * 20) * symbolPoint);
double sellLimitEntryPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK) + ((spread * 20) * symbolPoint);

//-- String values for the orders status
string magicOrderStatus;

Una vez completada la sección principal de nuestro código, el siguiente paso es crear la función responsable de generar y cargar la interfaz gráfica de usuario durante la inicialización del Asesor Experto. Llamaremos a esta función CreateGui().

void CreateGui()
  {
//-- Create the orders panel
   mainPanelWindow.Create(
      0, MAIN_PANEL_NAME, MAIN_PANEL_SUBWINDOW,
      MAIN_PANEL_X1, MAIN_PANEL_Y1, MAIN_PANEL_X2, MAIN_PANEL_Y2
   );
   /*------------------------------------------------------
   * Header Labels GUI components creation ****
   *-----------------------------------------------------*/
//--Create the lot volume header label
   lotVolHeaderLabel.Create(
      0, VOLUME_LOT_LABEL_NAME, VOLUME_LOT_LABEL_SUBWINDOW,
      VOLUME_LOT_LABEL_X1,
      VOLUME_LOT_LABEL_Y1,
      GUI_OBJECTS_WIDTH,
      GUI_OBJECTS_HEIGHT
   );
   lotVolHeaderLabel.Text(VOLUME_LOT_LABEL_TEXT);
   lotVolHeaderLabel.Color(GUI_OBJECTS_HEADING_COLOR);
   lotVolHeaderLabel.FontSize(GUI_OBJECTS_HEADER_FONT_SIZE);
   mainPanelWindow.Add(lotVolHeaderLabel);

//--Create the open price header label
   openPriceHeaderLabel.Create(
      0, OPEN_PRICE_LABEL_NAME, OPEN_PRICE_LABEL_SUBWINDOW,
      OPEN_PRICE_LABEL_X1, OPEN_PRICE_LABEL_Y1,
      GUI_OBJECTS_WIDTH, GUI_OBJECTS_HEIGHT
   );
   openPriceHeaderLabel.Text(OPEN_PRICE_LABEL_TEXT);
   openPriceHeaderLabel.Color(GUI_OBJECTS_HEADING_COLOR);
   openPriceHeaderLabel.FontSize(GUI_OBJECTS_HEADER_FONT_SIZE);
   mainPanelWindow.Add(openPriceHeaderLabel);

//--Create the sl header label
   slHeaderLabel.Create(
      0, SL_LABEL_NAME, SL_LABEL_SUBWINDOW,
      SL_LABEL_X1, SL_LABEL_Y1,
      int(GUI_OBJECTS_WIDTH / 1.4), GUI_OBJECTS_HEIGHT
   );
   slHeaderLabel.Text(SL_LABEL_TEXT);
   slHeaderLabel.Color(GUI_OBJECTS_HEADING_COLOR);
   slHeaderLabel.FontSize(GUI_OBJECTS_HEADER_FONT_SIZE);
   mainPanelWindow.Add(slHeaderLabel);

//--Create the tp header label
   tpHeaderLabel.Create(
      0, TP_LABEL_NAME, TP_LABEL_SUBWINDOW,
      TP_LABEL_X1, TP_LABEL_Y1,
      int(GUI_OBJECTS_WIDTH / 1.4), GUI_OBJECTS_HEIGHT
   );
   tpHeaderLabel.Text(TP_LABEL_TEXT);
   tpHeaderLabel.Color(GUI_OBJECTS_HEADING_COLOR);
   tpHeaderLabel.FontSize(GUI_OBJECTS_HEADER_FONT_SIZE);
   mainPanelWindow.Add(tpHeaderLabel);

   /*------------------------------------------------------
   * Buy Stop Order GUI components creation ****
   *-----------------------------------------------------*/
//--Create the open buy stop button
   buyStopBtn.Create(
      0, BUY_STOP_BTN_NAME, BUY_STOP_BTN_SUBWINDOW,
      BUY_STOP_BTN_X1, BUY_STOP_BTN_Y1,
      0, 0
   );
   buyStopBtn.Text(BUY_STOP_BTN_TEXT);
   buyStopBtn.Width(GUI_OBJECTS_WIDTH);
   buyStopBtn.Height(GUI_OBJECTS_HEIGHT);
   buyStopBtn.Color(GUI_OBJECTS_BUY_BTN_COLOR);
   buyStopBtn.ColorBackground(GUI_OBJECTS_BUY_BTN_BG_COLOR);
   buyStopBtn.FontSize(GUI_OBJECTS_FONT_SIZE);
   mainPanelWindow.Add(buyStopBtn);

//--Create the buy stop volume lot edit to get the buy stop volume/lot user input
   buyStopVolumeLotEdit.Create(
      0, BUY_STOP_VOLUME_LOT_EDIT_NAME, BUY_STOP_VOLUME_LOT_EDIT_SUBWINDOW,
      BUY_STOP_VOLUME_LOT_EDIT_X1, BUY_STOP_VOLUME_LOT_EDIT_Y1,
      0, 0
   );
   buyStopVolumeLotEdit.Text(DoubleToString(volumeLot));
   buyStopVolumeLotEdit.Width(GUI_OBJECTS_WIDTH);
   buyStopVolumeLotEdit.Height(GUI_OBJECTS_HEIGHT);
   buyStopVolumeLotEdit.Color(GUI_OBJECTS_BUY_EDIT_COLOR);
   buyStopVolumeLotEdit.ColorBackground(GUI_OBJECTS_BUY_EDIT_BG_COLOR);
   buyStopVolumeLotEdit.FontSize(GUI_OBJECTS_FONT_SIZE);
   buyStopVolumeLotEdit.ColorBorder(GUI_OBJECTS_BUY_BTN_BG_COLOR);
   mainPanelWindow.Add(buyStopVolumeLotEdit);

//--Create the buy stop price edit to get the buy stop opening price user input
   buyStopOpenPriceEdit.Create(
      0, BUY_STOP_OPEN_PRICE_EDIT_NAME, BUY_STOP_OPEN_PRICE_EDIT_SUBWINDOW,
      BUY_STOP_OPEN_PRICE_EDIT_X1, BUY_STOP_OPEN_PRICE_EDIT_Y1,
      0, 0
   );
   buyStopOpenPriceEdit.Text(DoubleToString(buyStopEntryPrice, int(symbolDigits)));
   buyStopOpenPriceEdit.Width(GUI_OBJECTS_WIDTH);
   buyStopOpenPriceEdit.Height(GUI_OBJECTS_HEIGHT);
   buyStopOpenPriceEdit.Color(GUI_OBJECTS_BUY_EDIT_COLOR);
   buyStopOpenPriceEdit.ColorBackground(GUI_OBJECTS_BUY_EDIT_BG_COLOR);
   buyStopOpenPriceEdit.FontSize(GUI_OBJECTS_FONT_SIZE);
   buyStopOpenPriceEdit.ColorBorder(GUI_OBJECTS_BUY_BTN_BG_COLOR);
   mainPanelWindow.Add(buyStopOpenPriceEdit);

//--Create the buy stop sl edit to get the buy stop sl user input
   buyStopSlEdit.Create(
      0, BUY_STOP_SL_EDIT_NAME, BUY_STOP_SL_EDIT_SUBWINDOW,
      BUY_STOP_SL_EDIT_X1, BUY_STOP_SL_EDIT_Y1,
      0, 0
   );
   buyStopSlEdit.Text(IntegerToString(sl));
   buyStopSlEdit.Width(int(GUI_OBJECTS_WIDTH / 1.4));
   buyStopSlEdit.Height(GUI_OBJECTS_HEIGHT);
   buyStopSlEdit.Color(GUI_OBJECTS_BUY_EDIT_COLOR);
   buyStopSlEdit.ColorBackground(GUI_OBJECTS_BUY_EDIT_BG_COLOR);
   buyStopSlEdit.FontSize(GUI_OBJECTS_FONT_SIZE);
   buyStopSlEdit.ColorBorder(GUI_OBJECTS_BUY_BTN_BG_COLOR);
   mainPanelWindow.Add(buyStopSlEdit);

//--Create the buy stop tp edit to get the buy stop tp user input
   buyStopTpEdit.Create(
      0, BUY_STOP_TP_EDIT_NAME, BUY_STOP_TP_EDIT_SUBWINDOW,
      BUY_STOP_TP_EDIT_X1, BUY_STOP_TP_EDIT_Y1,
      0, 0
   );
   buyStopTpEdit.Text(IntegerToString(tp));
   buyStopTpEdit.Width(GUI_OBJECTS_WIDTH);
   buyStopTpEdit.Height(GUI_OBJECTS_HEIGHT);
   buyStopTpEdit.Color(GUI_OBJECTS_BUY_EDIT_COLOR);
   buyStopTpEdit.ColorBackground(GUI_OBJECTS_BUY_EDIT_BG_COLOR);
   buyStopTpEdit.FontSize(GUI_OBJECTS_FONT_SIZE);
   buyStopTpEdit.ColorBorder(GUI_OBJECTS_BUY_BTN_BG_COLOR);
   mainPanelWindow.Add(buyStopTpEdit);

   /*------------------------------------------------------
   * Sell Stop Order GUI components creation ****
   *-----------------------------------------------------*/
//--Create the open sell stop button
   sellStopBtn.Create(
      0, SELL_STOP_BTN_NAME, SELL_STOP_BTN_SUBWINDOW,
      SELL_STOP_BTN_X1, SELL_STOP_BTN_Y1,
      0, 0
   );
   sellStopBtn.Text(SELL_STOP_BTN_TEXT);
   sellStopBtn.Width(GUI_OBJECTS_WIDTH);
   sellStopBtn.Height(GUI_OBJECTS_HEIGHT);
   sellStopBtn.Color(GUI_OBJECTS_SELL_BTN_COLOR);
   sellStopBtn.ColorBackground(GUI_OBJECTS_SELL_BTN_BG_COLOR);
   sellStopBtn.FontSize(GUI_OBJECTS_FONT_SIZE);
   mainPanelWindow.Add(sellStopBtn);

//--Create the sell stop volume lot edit to get the sell stop volume/lot user input
   sellStopVolumeLotEdit.Create(
      0, SELL_STOP_VOLUME_LOT_EDIT_NAME, SELL_STOP_VOLUME_LOT_EDIT_SUBWINDOW,
      SELL_STOP_VOLUME_LOT_EDIT_X1, SELL_STOP_VOLUME_LOT_EDIT_Y1,
      0, 0
   );
   sellStopVolumeLotEdit.Text(DoubleToString(volumeLot));
   sellStopVolumeLotEdit.Width(GUI_OBJECTS_WIDTH);
   sellStopVolumeLotEdit.Height(GUI_OBJECTS_HEIGHT);
   sellStopVolumeLotEdit.Color(GUI_OBJECTS_SELL_EDIT_COLOR);
   sellStopVolumeLotEdit.ColorBackground(GUI_OBJECTS_SELL_EDIT_BG_COLOR);
   sellStopVolumeLotEdit.FontSize(GUI_OBJECTS_FONT_SIZE);
   sellStopVolumeLotEdit.ColorBorder(GUI_OBJECTS_SELL_BTN_BG_COLOR);
   mainPanelWindow.Add(sellStopVolumeLotEdit);

//--Create the sell stop price edit to get the sell stop opening price user input
   sellStopOpenPriceEdit.Create(
      0, SELL_STOP_OPEN_PRICE_EDIT_NAME, SELL_STOP_OPEN_PRICE_EDIT_SUBWINDOW,
      SELL_STOP_OPEN_PRICE_EDIT_X1, SELL_STOP_OPEN_PRICE_EDIT_Y1,
      0, 0
   );
   sellStopOpenPriceEdit.Text(DoubleToString(sellStopEntryPrice, int(symbolDigits)));
   sellStopOpenPriceEdit.Width(GUI_OBJECTS_WIDTH);
   sellStopOpenPriceEdit.Height(GUI_OBJECTS_HEIGHT);
   sellStopOpenPriceEdit.Color(GUI_OBJECTS_SELL_EDIT_COLOR);
   sellStopOpenPriceEdit.ColorBackground(GUI_OBJECTS_SELL_EDIT_BG_COLOR);
   sellStopOpenPriceEdit.FontSize(GUI_OBJECTS_FONT_SIZE);
   sellStopOpenPriceEdit.ColorBorder(GUI_OBJECTS_SELL_BTN_BG_COLOR);
   mainPanelWindow.Add(sellStopOpenPriceEdit);

//--Create the sell stop sl edit to get the sell stop sl user input
   sellStopSlEdit.Create(
      0, SELL_STOP_SL_EDIT_NAME, SELL_STOP_SL_EDIT_SUBWINDOW,
      SELL_STOP_SL_EDIT_X1, SELL_STOP_SL_EDIT_Y1,
      0, 0
   );
   sellStopSlEdit.Text(IntegerToString(sl));
   sellStopSlEdit.Width(int(GUI_OBJECTS_WIDTH / 1.4));
   sellStopSlEdit.Height(GUI_OBJECTS_HEIGHT);
   sellStopSlEdit.Color(GUI_OBJECTS_SELL_EDIT_COLOR);
   sellStopSlEdit.ColorBackground(GUI_OBJECTS_SELL_EDIT_BG_COLOR);
   sellStopSlEdit.FontSize(GUI_OBJECTS_FONT_SIZE);
   sellStopSlEdit.ColorBorder(GUI_OBJECTS_SELL_BTN_BG_COLOR);
   mainPanelWindow.Add(sellStopSlEdit);

//--Create the sell stop tp edit to get the sell stop tp user input
   sellStopTpEdit.Create(
      0, SELL_STOP_TP_EDIT_NAME, SELL_STOP_TP_EDIT_SUBWINDOW,
      SELL_STOP_TP_EDIT_X1, SELL_STOP_TP_EDIT_Y1,
      0, 0
   );
   sellStopTpEdit.Text(IntegerToString(tp));
   sellStopTpEdit.Width(GUI_OBJECTS_WIDTH);
   sellStopTpEdit.Height(GUI_OBJECTS_HEIGHT);
   sellStopTpEdit.Color(GUI_OBJECTS_SELL_EDIT_COLOR);
   sellStopTpEdit.ColorBackground(GUI_OBJECTS_SELL_EDIT_BG_COLOR);
   sellStopTpEdit.FontSize(GUI_OBJECTS_FONT_SIZE);
   sellStopTpEdit.ColorBorder(GUI_OBJECTS_SELL_BTN_BG_COLOR);
   mainPanelWindow.Add(sellStopTpEdit);

   /*------------------------------------------------------
   * Buy Limit Order GUI components creation ****
   *-----------------------------------------------------*/
//--Create the open buy limit button
   buyLimitBtn.Create(
      0, BUY_LIMIT_BTN_NAME, BUY_LIMIT_BTN_SUBWINDOW,
      BUY_LIMIT_BTN_X1, BUY_LIMIT_BTN_Y1,
      0, 0
   );
   buyLimitBtn.Text(BUY_LIMIT_BTN_TEXT);
   buyLimitBtn.Width(GUI_OBJECTS_WIDTH);
   buyLimitBtn.Height(GUI_OBJECTS_HEIGHT);
   buyLimitBtn.Color(GUI_OBJECTS_BUY_BTN_COLOR);
   buyLimitBtn.ColorBackground(GUI_OBJECTS_BUY_BTN_BG_COLOR);
   buyLimitBtn.FontSize(GUI_OBJECTS_FONT_SIZE);
   mainPanelWindow.Add(buyLimitBtn);

//--Create the buy limit volume lot edit to get the buy limit volume/lot user input
   buyLimitVolumeLotEdit.Create(
      0, BUY_LIMIT_VOLUME_LOT_EDIT_NAME, BUY_LIMIT_VOLUME_LOT_EDIT_SUBWINDOW,
      BUY_LIMIT_VOLUME_LOT_EDIT_X1, BUY_LIMIT_VOLUME_LOT_EDIT_Y1,
      0, 0
   );
   buyLimitVolumeLotEdit.Text(DoubleToString(volumeLot));
   buyLimitVolumeLotEdit.Width(GUI_OBJECTS_WIDTH);
   buyLimitVolumeLotEdit.Height(GUI_OBJECTS_HEIGHT);
   buyLimitVolumeLotEdit.Color(GUI_OBJECTS_BUY_EDIT_COLOR);
   buyLimitVolumeLotEdit.ColorBackground(GUI_OBJECTS_BUY_EDIT_BG_COLOR);
   buyLimitVolumeLotEdit.FontSize(GUI_OBJECTS_FONT_SIZE);
   buyLimitVolumeLotEdit.ColorBorder(GUI_OBJECTS_BUY_BTN_BG_COLOR);
   mainPanelWindow.Add(buyLimitVolumeLotEdit);

//--Create the buy limit price edit to get the buy limit opening price user input
   buyLimitOpenPriceEdit.Create(
      0, BUY_LIMIT_OPEN_PRICE_EDIT_NAME, BUY_LIMIT_OPEN_PRICE_EDIT_SUBWINDOW,
      BUY_LIMIT_OPEN_PRICE_EDIT_X1, BUY_LIMIT_OPEN_PRICE_EDIT_Y1,
      0, 0
   );
   buyLimitOpenPriceEdit.Text(DoubleToString(buyLimitEntryPrice, int(symbolDigits)));
   buyLimitOpenPriceEdit.Width(GUI_OBJECTS_WIDTH);
   buyLimitOpenPriceEdit.Height(GUI_OBJECTS_HEIGHT);
   buyLimitOpenPriceEdit.Color(GUI_OBJECTS_BUY_EDIT_COLOR);
   buyLimitOpenPriceEdit.ColorBackground(GUI_OBJECTS_BUY_EDIT_BG_COLOR);
   buyLimitOpenPriceEdit.FontSize(GUI_OBJECTS_FONT_SIZE);
   buyLimitOpenPriceEdit.ColorBorder(GUI_OBJECTS_BUY_BTN_BG_COLOR);
   mainPanelWindow.Add(buyLimitOpenPriceEdit);

//--Create the buy limit sl edit to get the buy limit sl user input
   buyLimitSlEdit.Create(
      0, BUY_LIMIT_SL_EDIT_NAME, BUY_LIMIT_SL_EDIT_SUBWINDOW,
      BUY_LIMIT_SL_EDIT_X1, BUY_LIMIT_SL_EDIT_Y1,
      0, 0
   );
   buyLimitSlEdit.Text(IntegerToString(sl));
   buyLimitSlEdit.Width(int(GUI_OBJECTS_WIDTH / 1.4));
   buyLimitSlEdit.Height(GUI_OBJECTS_HEIGHT);
   buyLimitSlEdit.Color(GUI_OBJECTS_BUY_EDIT_COLOR);
   buyLimitSlEdit.ColorBackground(GUI_OBJECTS_BUY_EDIT_BG_COLOR);
   buyLimitSlEdit.FontSize(GUI_OBJECTS_FONT_SIZE);
   buyLimitSlEdit.ColorBorder(GUI_OBJECTS_BUY_BTN_BG_COLOR);
   mainPanelWindow.Add(buyLimitSlEdit);

//--Create the buy limit tp edit to get the buy limit tp user input
   buyLimitTpEdit.Create(
      0, BUY_LIMIT_TP_EDIT_NAME, BUY_LIMIT_TP_EDIT_SUBWINDOW,
      BUY_LIMIT_TP_EDIT_X1, BUY_LIMIT_TP_EDIT_Y1,
      0, 0
   );
   buyLimitTpEdit.Text(IntegerToString(tp));
   buyLimitTpEdit.Width(GUI_OBJECTS_WIDTH);
   buyLimitTpEdit.Height(GUI_OBJECTS_HEIGHT);
   buyLimitTpEdit.Color(GUI_OBJECTS_BUY_EDIT_COLOR);
   buyLimitTpEdit.ColorBackground(GUI_OBJECTS_BUY_EDIT_BG_COLOR);
   buyLimitTpEdit.FontSize(GUI_OBJECTS_FONT_SIZE);
   buyLimitTpEdit.ColorBorder(GUI_OBJECTS_BUY_BTN_BG_COLOR);
   mainPanelWindow.Add(buyLimitTpEdit);

   /*------------------------------------------------------
   * Sell Limit Order GUI components creation ****
   *-----------------------------------------------------*/
//--Create the open sell limit button
   sellLimitBtn.Create(
      0, SELL_LIMIT_BTN_NAME, SELL_LIMIT_BTN_SUBWINDOW,
      SELL_LIMIT_BTN_X1, SELL_LIMIT_BTN_Y1,
      0, 0
   );
   sellLimitBtn.Text(SELL_LIMIT_BTN_TEXT);
   sellLimitBtn.Width(GUI_OBJECTS_WIDTH);
   sellLimitBtn.Height(GUI_OBJECTS_HEIGHT);
   sellLimitBtn.Color(GUI_OBJECTS_SELL_BTN_COLOR);
   sellLimitBtn.ColorBackground(GUI_OBJECTS_SELL_BTN_BG_COLOR);
   sellLimitBtn.FontSize(GUI_OBJECTS_FONT_SIZE);
   mainPanelWindow.Add(sellLimitBtn);

//--Create the sell limit volume lot edit to get the sell limit volume/lot user input
   sellLimitVolumeLotEdit.Create(
      0, SELL_LIMIT_VOLUME_LOT_EDIT_NAME, SELL_LIMIT_VOLUME_LOT_EDIT_SUBWINDOW,
      SELL_LIMIT_VOLUME_LOT_EDIT_X1, SELL_LIMIT_VOLUME_LOT_EDIT_Y1,
      0, 0
   );
   sellLimitVolumeLotEdit.Text(DoubleToString(volumeLot));
   sellLimitVolumeLotEdit.Width(GUI_OBJECTS_WIDTH);
   sellLimitVolumeLotEdit.Height(GUI_OBJECTS_HEIGHT);
   sellLimitVolumeLotEdit.Color(GUI_OBJECTS_SELL_EDIT_COLOR);
   sellLimitVolumeLotEdit.ColorBackground(GUI_OBJECTS_SELL_EDIT_BG_COLOR);
   sellLimitVolumeLotEdit.FontSize(GUI_OBJECTS_FONT_SIZE);
   sellLimitVolumeLotEdit.ColorBorder(GUI_OBJECTS_SELL_BTN_BG_COLOR);
   mainPanelWindow.Add(sellLimitVolumeLotEdit);

//--Create the sell limit price edit to get the sell limit opening price user input
   sellLimitOpenPriceEdit.Create(
      0, SELL_LIMIT_OPEN_PRICE_EDIT_NAME, SELL_LIMIT_OPEN_PRICE_EDIT_SUBWINDOW,
      SELL_LIMIT_OPEN_PRICE_EDIT_X1, SELL_LIMIT_OPEN_PRICE_EDIT_Y1,
      0, 0
   );
   sellLimitOpenPriceEdit.Text(DoubleToString(sellLimitEntryPrice, int(symbolDigits)));
   sellLimitOpenPriceEdit.Width(GUI_OBJECTS_WIDTH);
   sellLimitOpenPriceEdit.Height(GUI_OBJECTS_HEIGHT);
   sellLimitOpenPriceEdit.Color(GUI_OBJECTS_SELL_EDIT_COLOR);
   sellLimitOpenPriceEdit.ColorBackground(GUI_OBJECTS_SELL_EDIT_BG_COLOR);
   sellLimitOpenPriceEdit.FontSize(GUI_OBJECTS_FONT_SIZE);
   sellLimitOpenPriceEdit.ColorBorder(GUI_OBJECTS_SELL_BTN_BG_COLOR);
   mainPanelWindow.Add(sellLimitOpenPriceEdit);

//--Create the sell limit sl edit to get the sell limit sl user input
   sellLimitSlEdit.Create(
      0, SELL_LIMIT_SL_EDIT_NAME, SELL_LIMIT_SL_EDIT_SUBWINDOW,
      SELL_LIMIT_SL_EDIT_X1, SELL_LIMIT_SL_EDIT_Y1,
      0, 0
   );
   sellLimitSlEdit.Text(IntegerToString(sl));
   sellLimitSlEdit.Width(int(GUI_OBJECTS_WIDTH / 1.4));
   sellLimitSlEdit.Height(GUI_OBJECTS_HEIGHT);
   sellLimitSlEdit.Color(GUI_OBJECTS_SELL_EDIT_COLOR);
   sellLimitSlEdit.ColorBackground(GUI_OBJECTS_SELL_EDIT_BG_COLOR);
   sellLimitSlEdit.FontSize(GUI_OBJECTS_FONT_SIZE);
   sellLimitSlEdit.ColorBorder(GUI_OBJECTS_SELL_BTN_BG_COLOR);
   mainPanelWindow.Add(sellLimitSlEdit);

//--Create the sell limit tp edit to get the sell limit tp user input
   sellLimitTpEdit.Create(
      0, SELL_LIMIT_TP_EDIT_NAME, SELL_LIMIT_TP_EDIT_SUBWINDOW,
      SELL_LIMIT_TP_EDIT_X1, SELL_LIMIT_TP_EDIT_Y1,
      0, 0
   );
   sellLimitTpEdit.Text(IntegerToString(tp));
   sellLimitTpEdit.Width(GUI_OBJECTS_WIDTH);
   sellLimitTpEdit.Height(GUI_OBJECTS_HEIGHT);
   sellLimitTpEdit.Color(GUI_OBJECTS_SELL_EDIT_COLOR);
   sellLimitTpEdit.ColorBackground(GUI_OBJECTS_SELL_EDIT_BG_COLOR);
   sellLimitTpEdit.FontSize(GUI_OBJECTS_FONT_SIZE);
   sellLimitTpEdit.ColorBorder(GUI_OBJECTS_SELL_BTN_BG_COLOR);
   mainPanelWindow.Add(sellLimitTpEdit);

   /*-------------------------------------------------------------
   * Status Labels and readonly edits GUI components creation ****
   *------------------------------------------------------------*/
//--Create the order magic status label
   magicOrderStatusLabel.Create(
      0, MAGIC_ORDER_STATUS_LABEL_NAME, MAGIC_ORDER_STATUS_LABEL_SUBWINDOW,
      MAGIC_ORDER_STATUS_LABEL_X1,
      MAGIC_ORDER_STATUS_LABEL_Y1,
      GUI_OBJECTS_WIDTH,
      GUI_OBJECTS_HEIGHT
   );
   magicOrderStatusLabel.Text(MAGIC_ORDER_STATUS_LABEL_TEXT + " - (Total Open Orders: " + (string(MagicOrdersTotal(magicNo))) + ")");
   magicOrderStatusLabel.Color(STATUS_EDIT_COLOR);
   magicOrderStatusLabel.FontSize(STATUS_HEADER_FONT_SIZE);
   mainPanelWindow.Add(magicOrderStatusLabel);

//--Create the magic order status edit to display the magic orders status
   magicOrdersStatusEdit.Create(
      0, MAGIC_ORDER_STATUS_EDIT_NAME, MAGIC_ORDER_STATUS_EDIT_SUBWINDOW,
      MAGIC_ORDER_STATUS_EDIT_X1, MAGIC_ORDER_STATUS_EDIT_Y1,
      0, 0
   );
   magicOrdersStatusEdit.ReadOnly(true);
   magicOrdersStatusEdit.Text(magicOrderStatus);
   magicOrdersStatusEdit.Width(STATUS_EDIT_WIDTH);
   magicOrdersStatusEdit.Height(GUI_OBJECTS_HEIGHT);
   magicOrdersStatusEdit.Color(STATUS_EDIT_COLOR);
   magicOrdersStatusEdit.ColorBackground(STATUS_EDIT_BG_COLOR);
   magicOrdersStatusEdit.FontSize(STATUS_EDIT_FONT_SIZE);
   magicOrdersStatusEdit.ColorBorder(STATUS_EDIT_BORDER_COLOR);
   mainPanelWindow.Add(magicOrdersStatusEdit);

//--Create the delete all magic buy stops button
   deleteAllMagicBuyStopsBtn.Create(
      0, DELETE_ALL_MAGIC_BUY_STOPS_BTN_NAME, DELETE_ALL_MAGIC_BUY_STOPS_BTN_SUBWINDOW,
      DELETE_ALL_MAGIC_BUY_STOPS_BTN_X1, DELETE_ALL_MAGIC_BUY_STOPS_BTN_Y1,
      0, 0
   );
   deleteAllMagicBuyStopsBtn.Text(DELETE_ALL_MAGIC_BUY_STOPS_BTN_TEXT);
   deleteAllMagicBuyStopsBtn.Width(DELETE_ORDERS_BTN_WIDTH);
   deleteAllMagicBuyStopsBtn.Height(GUI_OBJECTS_HEIGHT);
   deleteAllMagicBuyStopsBtn.Color(DELETE_ORDERS_BTN_COLOR);
   deleteAllMagicBuyStopsBtn.ColorBackground(DELETE_BUY_ORDERS_BTN_BG_COLOR);
   deleteAllMagicBuyStopsBtn.ColorBorder(DELETE_ORDERS_BTN_BORDER_COLOR);
   deleteAllMagicBuyStopsBtn.FontSize(DELETE_ORDERS_BTN_FONT_SIZE);
   mainPanelWindow.Add(deleteAllMagicBuyStopsBtn);

//--Create the delete all magic sell stops button
   deleteAllMagicSellStopsBtn.Create(
      0, DELETE_ALL_MAGIC_SELL_STOPS_BTN_NAME, DELETE_ALL_MAGIC_SELL_STOPS_BTN_SUBWINDOW,
      DELETE_ALL_MAGIC_SELL_STOPS_BTN_X1, DELETE_ALL_MAGIC_SELL_STOPS_BTN_Y1,
      0, 0
   );
   deleteAllMagicSellStopsBtn.Text(DELETE_ALL_MAGIC_SELL_STOPS_BTN_TEXT);
   deleteAllMagicSellStopsBtn.Width(DELETE_ORDERS_BTN_WIDTH);
   deleteAllMagicSellStopsBtn.Height(GUI_OBJECTS_HEIGHT);
   deleteAllMagicSellStopsBtn.Color(DELETE_ORDERS_BTN_COLOR);
   deleteAllMagicSellStopsBtn.ColorBackground(DELETE_SELL_ORDERS_BTN_BG_COLOR);
   deleteAllMagicSellStopsBtn.ColorBorder(DELETE_ORDERS_BTN_BORDER_COLOR);
   deleteAllMagicSellStopsBtn.FontSize(DELETE_ORDERS_BTN_FONT_SIZE);
   mainPanelWindow.Add(deleteAllMagicSellStopsBtn);

//--Create the delete all magic buy limits button
   deleteAllMagicBuyLimitsBtn.Create(
      0, DELETE_ALL_MAGIC_BUY_LIMITS_BTN_NAME, DELETE_ALL_MAGIC_BUY_LIMITS_BTN_SUBWINDOW,
      DELETE_ALL_MAGIC_BUY_LIMITS_BTN_X1, DELETE_ALL_MAGIC_BUY_LIMITS_BTN_Y1,
      0, 0
   );
   deleteAllMagicBuyLimitsBtn.Text(DELETE_ALL_MAGIC_BUY_LIMITS_BTN_TEXT);
   deleteAllMagicBuyLimitsBtn.Width(DELETE_ORDERS_BTN_WIDTH);
   deleteAllMagicBuyLimitsBtn.Height(GUI_OBJECTS_HEIGHT);
   deleteAllMagicBuyLimitsBtn.Color(DELETE_ORDERS_BTN_COLOR);
   deleteAllMagicBuyLimitsBtn.ColorBackground(DELETE_BUY_ORDERS_BTN_BG_COLOR);
   deleteAllMagicBuyLimitsBtn.ColorBorder(DELETE_ORDERS_BTN_BORDER_COLOR);
   deleteAllMagicBuyLimitsBtn.FontSize(DELETE_ORDERS_BTN_FONT_SIZE);
   mainPanelWindow.Add(deleteAllMagicBuyLimitsBtn);

//--Create the delete all magic sell limits button
   deleteAllMagicSellLimitsBtn.Create(
      0, DELETE_ALL_MAGIC_SELL_LIMITS_BTN_NAME, DELETE_ALL_MAGIC_SELL_LIMITS_BTN_SUBWINDOW,
      DELETE_ALL_MAGIC_SELL_LIMITS_BTN_X1, DELETE_ALL_MAGIC_SELL_LIMITS_BTN_Y1,
      0, 0
   );
   deleteAllMagicSellLimitsBtn.Text(DELETE_ALL_MAGIC_SELL_LIMITS_BTN_TEXT);
   deleteAllMagicSellLimitsBtn.Width(DELETE_ORDERS_BTN_WIDTH);
   deleteAllMagicSellLimitsBtn.Height(GUI_OBJECTS_HEIGHT);
   deleteAllMagicSellLimitsBtn.Color(DELETE_ORDERS_BTN_COLOR);
   deleteAllMagicSellLimitsBtn.ColorBackground(DELETE_SELL_ORDERS_BTN_BG_COLOR);
   deleteAllMagicSellLimitsBtn.ColorBorder(DELETE_ORDERS_BTN_BORDER_COLOR);
   deleteAllMagicSellLimitsBtn.FontSize(DELETE_ORDERS_BTN_FONT_SIZE);
   mainPanelWindow.Add(deleteAllMagicSellLimitsBtn);

//--Create the delete all magic orders button
   deleteAllMagicOrdersBtn.Create(
      0, DELETE_ALL_MAGIC_ORDERS_BTN_NAME, DELETE_ALL_MAGIC_ORDERS_BTN_SUBWINDOW,
      DELETE_ALL_MAGIC_ORDERS_BTN_X1, DELETE_ALL_MAGIC_ORDERS_BTN_Y1,
      0, 0
   );
   deleteAllMagicOrdersBtn.Text(DELETE_ALL_MAGIC_ORDERS_BTN_TEXT);
   deleteAllMagicOrdersBtn.Width(STATUS_EDIT_WIDTH);
   deleteAllMagicOrdersBtn.Height(GUI_OBJECTS_HEIGHT);
   deleteAllMagicOrdersBtn.Color(DELETE_ORDERS_BTN_COLOR);
   deleteAllMagicOrdersBtn.ColorBackground(DELETE_ALL_ORDERS_BTN_BG_COLOR);
   deleteAllMagicOrdersBtn.ColorBorder(DELETE_ORDERS_BTN_BORDER_COLOR);
   deleteAllMagicOrdersBtn.FontSize(DELETE_ORDERS_BTN_FONT_SIZE);
   mainPanelWindow.Add(deleteAllMagicOrdersBtn);

//--Call the Run() method to load the main panel window
   mainPanelWindow.Run();
  }

Ahora necesitamos detectar cualquier pulsación o activación de botones rellenando la función OnChartEvent(...). Esta función servirá como controlador de eventos para todas las interacciones del usuario, lo que la convierte en el componente central de la capacidad de respuesta de nuestro panel. En esta sección, llamaremos a las funciones prototipo importadas desde la biblioteca PendingOrdersManager.ex5, lo que nos permitirá gestionar y manipular los pedidos pendientes en función de la información introducida por el usuario. Por ejemplo, si un usuario hace clic en un botón para realizar una nueva orden pendiente, se activará la función de biblioteca correspondiente para ejecutar la operación.

Para mejorar aún más la experiencia del usuario con el panel de órdenes pendientes, también integraremos comentarios auditivos. Se reproducirán diferentes sonidos para indicar el resultado de una acción, como si un pedido se ha realizado correctamente o si ha fallado debido a algún error. Esto proporciona información en tiempo real y añade un nivel adicional de interactividad, lo que hace que el panel sea más intuitivo y fácil de usar. La combinación de señales visuales y auditivas garantizará que los usuarios puedan seguir fácilmente el estado de sus acciones y responder en consecuencia.

void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
//--Detect any clicks or events performed to the orders panel window and make it moveable
   mainPanelWindow.ChartEvent(id, lparam, dparam, sparam);

//--Detect any click events on the chart
   if(id == CHARTEVENT_OBJECT_CLICK)
     {
      //--Detect when the buyStopBtn is clicked and open a new buy stop order
      if(sparam == buyStopBtn.Name())
        {
         Print(__FUNCTION__, " CHARTEVEN_OBJECT_CLICK: ", sparam);
         Print("Opening a new Buy Stop Order with the details below: ");
         Print("Volume: ", buyStopVolumeLotEdit.Text());
         Print("Open Price: ", buyStopOpenPriceEdit.Text());
         Print("Sl (Pips): ", buyStopSlEdit.Text());
         Print("Tp (Pips): ", buyStopTpEdit.Text());
         if(
            OpenBuyStop(
               magicNo, _Symbol, StringToDouble(buyStopOpenPriceEdit.Text()),
               StringToDouble(buyStopVolumeLotEdit.Text()), (uint)StringToInteger(buyStopSlEdit.Text()),
               (uint)StringToInteger(buyStopTpEdit.Text()), "EX5 PendingOrdersManager Panel"
            )
         )
           {
            PlaySound("ok.wav");//-- Order placed ok
           }
         else
           {
            PlaySound("alert2.wav");//-- Order failed
           }
        }

      //--Detect when the sellStopBtn is clicked and open a new sell stop order
      if(sparam == sellStopBtn.Name())
        {
         Print(__FUNCTION__, " CHARTEVEN_OBJECT_CLICK: ", sparam);
         Print("Opening a new Sell Stop Order with the details below: ");
         Print("Volume: ", sellStopVolumeLotEdit.Text());
         Print("Open Price: ", sellStopOpenPriceEdit.Text());
         Print("Sl (Pips): ", sellStopSlEdit.Text());
         Print("Tp (Pips): ", sellStopTpEdit.Text());
         if(
            OpenSellStop(
               magicNo, _Symbol, StringToDouble(sellStopOpenPriceEdit.Text()),
               StringToDouble(sellStopVolumeLotEdit.Text()), (uint)StringToInteger(sellStopSlEdit.Text()),
               (uint)StringToInteger(sellStopTpEdit.Text()), "EX5 PendingOrdersManager Panel"
            )
         )
           {
            PlaySound("ok.wav");//-- Order placed ok
           }
         else
           {
            PlaySound("alert2.wav");//-- Order failed
           }
        }

      //--Detect when the buyLimitBtn is clicked and open a new buy limit order
      if(sparam == buyLimitBtn.Name())
        {
         Print(__FUNCTION__, " CHARTEVEN_OBJECT_CLICK: ", sparam);
         Print("Opening a new Buy Limit Order with the details below: ");
         Print("Volume: ", buyLimitVolumeLotEdit.Text());
         Print("Open Price: ", buyLimitOpenPriceEdit.Text());
         Print("Sl (Pips): ", buyLimitSlEdit.Text());
         Print("Tp (Pips): ", buyLimitTpEdit.Text());
         if(
            OpenBuyLimit(
               magicNo, _Symbol, StringToDouble(buyLimitOpenPriceEdit.Text()),
               StringToDouble(buyLimitVolumeLotEdit.Text()), (uint)StringToInteger(buyLimitSlEdit.Text()),
               (uint)StringToInteger(buyLimitTpEdit.Text()), "EX5 PendingOrdersManager Panel"
            )
         )
           {
            PlaySound("ok.wav");//-- Order placed ok
           }
         else
           {
            PlaySound("alert2.wav");//-- Order failed
           }
        }

      //--Detect when the sellLimitBtn is clicked and open a new sell limit order
      if(sparam == sellLimitBtn.Name())
        {
         Print(__FUNCTION__, " CHARTEVEN_OBJECT_CLICK: ", sparam);
         Print("Opening a new Sell Limit Order with the details below: ");
         Print("Volume: ", sellLimitVolumeLotEdit.Text());
         Print("Open Price: ", sellLimitOpenPriceEdit.Text());
         Print("Sl (Pips): ", sellLimitSlEdit.Text());
         Print("Tp (Pips): ", sellLimitTpEdit.Text());

         if(
            OpenSellLimit(
               magicNo, _Symbol, StringToDouble(sellLimitOpenPriceEdit.Text()),
               StringToDouble(sellLimitVolumeLotEdit.Text()), (uint)StringToInteger(sellLimitSlEdit.Text()),
               (uint)StringToInteger(sellLimitTpEdit.Text()), "EX5 PendingOrdersManager Panel"
            )
         )
           {
            PlaySound("ok.wav");//-- Order placed ok
           }
         else
           {
            PlaySound("alert2.wav");//-- Order failed
           }
        }

      //--Detect when the deleteAllMagicBuyStopsBtn is clicked and delete all the specified orders
      if(sparam == deleteAllMagicBuyStopsBtn.Name() && MagicBuyStopOrdersTotal(magicNo) > 0)
        {
         Print(__FUNCTION__, " CHARTEVEN_OBJECT_CLICK: ", sparam);
         Print("Deleting all the buy stop orders with magic number: ", magicNo);
         if(DeleteAllBuyStops("", magicNo))
           {
            PlaySound("ok.wav");//-- Orders deleted ok
           }
         else
           {
            PlaySound("alert2.wav");//-- Order deleting failed
           }
        }

      //--Detect when the deleteAllMagicSellStopsBtn is clicked and delete all the specified orders
      if(sparam == deleteAllMagicSellStopsBtn.Name() && MagicSellStopOrdersTotal(magicNo) > 0)
        {
         Print(__FUNCTION__, " CHARTEVEN_OBJECT_CLICK: ", sparam);
         Print("Deleting all the sell stop orders with magic number: ", magicNo);
         if(DeleteAllSellStops("", magicNo))
           {
            PlaySound("ok.wav");//-- Orders deleted ok
           }
         else
           {
            PlaySound("alert2.wav");//-- Order deleting failed
           }
        }

      //--Detect when the deleteAllMagicBuyLimitsBtn is clicked and delete all the specified orders
      if(sparam == deleteAllMagicBuyLimitsBtn.Name() && MagicBuyLimitOrdersTotal(magicNo) > 0)
        {
         Print(__FUNCTION__, " CHARTEVEN_OBJECT_CLICK: ", sparam);
         Print("Deleting all the buy limit orders with magic number: ", magicNo);
         if(DeleteAllBuyLimits("", magicNo))
           {
            PlaySound("ok.wav");//-- Orders deleted ok
           }
         else
           {
            PlaySound("alert2.wav");//-- Order deleting failed
           }
        }

      //--Detect when the deleteAllMagicSellLimitsBtn is clicked and delete all the specified orders
      if(sparam == deleteAllMagicSellLimitsBtn.Name() && MagicSellLimitOrdersTotal(magicNo) > 0)
        {
         Print(__FUNCTION__, " CHARTEVEN_OBJECT_CLICK: ", sparam);
         Print("Deleting all the sell limit orders with magic number: ", magicNo);
         if(DeleteAllSellLimits("", magicNo))
           {
            PlaySound("ok.wav");//-- Orders deleted ok
           }
         else
           {
            PlaySound("alert2.wav");//-- Order deleting failed
           }
        }

      //--Detect when the deleteAllMagicOrdersBtn is clicked and delete all the specified orders
      if(sparam == deleteAllMagicOrdersBtn.Name() && MagicOrdersTotal(magicNo) > 0)
        {
         Print(__FUNCTION__, " CHARTEVEN_OBJECT_CLICK: ", sparam);
         Print("Deleting all the open peding orders with magic number: ", magicNo);
         if(DeleteAllMagicOrders(magicNo))
           {
            PlaySound("ok.wav");//-- Orders deleted ok
           }
         else
           {
            PlaySound("alert2.wav");//-- Order deleting failed
           }
        }
     }
  }

Notará que, tan pronto como se carga el Asesor Experto, este rellena automáticamente los campos de volumen/lote de la orden, precios de entrada, stop loss (SL) y take profit (TP) con valores predefinidos basados en el spread actual. Estos valores proporcionan al usuario un punto de partida para la realización de pedidos, agilizando el proceso de negociación y minimizando la introducción manual de datos. Además, los botones para eliminar órdenes, situados debajo de los estados de las órdenes mágicas, aparecen inicialmente en gris y desactivados si no se detectan órdenes pendientes o activas que coincidan con el número mágico asignado al Asesor Experto. Una vez que el Asesor Experto identifica las órdenes coincidentes, los botones se activarán y cambiarán de color, lo que indica que ahora están operativos y listos para ejecutar comandos de eliminación.

Botones de eliminación de órdenes deshabilitados en el Panel de Órdenes

Cuando el Asesor Experto detecta que se abren órdenes que coinciden con el número mágico asignado, se activan los botones de eliminación de órdenes, que cambian de color para indicar que están habilitados y pueden utilizarse.

Dos botones habilitados para eliminar órdenes en el Panel de Órdenes

Todos los botones habilitados para eliminar órdenes en el Panel de Órdenes

Para implementar esta función, debemos añadir el siguiente código en la función OnTick(). Esto nos permitirá utilizar las funciones de la biblioteca EX5 importadas para supervisar y actualizar continuamente la interfaz gráfica de usuario en tiempo real, garantizando que se mantenga sincronizada con el estado de las órdenes en cada tick entrante.

void OnTick()
  {
//---
   magicOrderStatus = " Buy Stops: " + (string(MagicBuyStopOrdersTotal(magicNo))) +
                      ", Sell Stops: " + (string(MagicSellStopOrdersTotal(magicNo))) +
                      ", Buy Limits: " + (string(MagicBuyLimitOrdersTotal(magicNo))) +
                      ", Sell Limits: " + (string(MagicSellLimitOrdersTotal(magicNo))) +
                      " ";
   magicOrderStatusLabel.Text(MAGIC_ORDER_STATUS_LABEL_TEXT + (string(MagicOrdersTotal(magicNo))));
   magicOrdersStatusEdit.Text(magicOrderStatus);

//-- Disable and change the background color of the deleteAllMagicBuyStopsBtn depending on the open orders status
   if(MagicBuyStopOrdersTotal(magicNo) == 0)
     {
      deleteAllMagicBuyStopsBtn.Disable();
      deleteAllMagicBuyStopsBtn.ColorBackground(clrLightSlateGray);
     }
   else
     {
      deleteAllMagicBuyStopsBtn.Enable();
      deleteAllMagicBuyStopsBtn.ColorBackground(DELETE_BUY_ORDERS_BTN_BG_COLOR);
     }

//-- Disable and change the background color of the deleteAllMagicSellStopsBtn depending on the open orders status
   if(MagicSellStopOrdersTotal(magicNo) == 0)
     {
      deleteAllMagicSellStopsBtn.Disable();
      deleteAllMagicSellStopsBtn.ColorBackground(clrLightSlateGray);
     }
   else
     {
      deleteAllMagicSellStopsBtn.Enable();
      deleteAllMagicSellStopsBtn.ColorBackground(DELETE_SELL_ORDERS_BTN_BG_COLOR);
     }

//-- Disable and change the background color of the deleteAllMagicBuyLimitsBtn depending on the open orders status
   if(MagicBuyLimitOrdersTotal(magicNo) == 0)
     {
      deleteAllMagicBuyLimitsBtn.Disable();
      deleteAllMagicBuyLimitsBtn.ColorBackground(clrLightSlateGray);
     }
   else
     {
      deleteAllMagicBuyLimitsBtn.Enable();
      deleteAllMagicBuyLimitsBtn.ColorBackground(DELETE_BUY_ORDERS_BTN_BG_COLOR);
     }

//-- Disable and change the background color of the deleteAllMagicSellLimitsBtn depending on the open orders status
   if(MagicSellLimitOrdersTotal(magicNo) == 0)
     {
      deleteAllMagicSellLimitsBtn.Disable();
      deleteAllMagicSellLimitsBtn.ColorBackground(clrLightSlateGray);
     }
   else
     {
      deleteAllMagicSellLimitsBtn.Enable();
      deleteAllMagicSellLimitsBtn.ColorBackground(DELETE_SELL_ORDERS_BTN_BG_COLOR);
     }

//-- Disable and change the background color of the deleteAllMagicOrdersBtn depending on the open orders status
   if(MagicOrdersTotal(magicNo) == 0)
     {
      deleteAllMagicOrdersBtn.Disable();
      deleteAllMagicOrdersBtn.ColorBackground(clrLightSlateGray);
     }
   else
     {
      deleteAllMagicOrdersBtn.Enable();
      deleteAllMagicOrdersBtn.ColorBackground(DELETE_ALL_ORDERS_BTN_BG_COLOR);
     }
  }

Por último, debemos asegurarnos de que todos los recursos se liberen y limpien correctamente cuando finalice el Asesor Experto. Para ello, añada el siguiente código a la función OnDeinit(...).

void OnDeinit(const int reason)
  {
//---
   //-- Delete and garbage collect the graphical user interface and other graphical objects
   mainPanelWindow.Destroy();

//-- Clear any chart comments
   Comment("");
  }

El archivo PendingOrdersPanel.mq5 se adjunta al final de este artículo.


Conclusión

Hemos creado una biblioteca completa Pending Orders Management EX5 que muestra cómo se pueden abrir, modificar, eliminar, ordenar y filtrar diferentes tipos de órdenes pendientes. Esta biblioteca es un recurso útil para cualquier desarrollador de MQL5 que necesite una herramienta flexible y fácil de usar para gestionar órdenes pendientes, ya que les permite obtener rápidamente el estado de las órdenes o realizar acciones sobre ellas con solo una simple llamada a la función.

La biblioteca está repleta de funciones e incluye documentación clara y ejemplos reales. En el próximo artículo, aplicaremos un método similar para crear una biblioteca EX5 de gestión del historial, lo que facilitará enormemente el manejo de las operaciones y el historial de órdenes en MQL5.

¡Gracias por seguirnos y mucha suerte en tus operaciones y en la programación MQL5!

Traducción del inglés realizada por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/en/articles/15888

Creación de un Panel de administración de operaciones en MQL5 (Parte IV): Capa de seguridad de inicio de sesión Creación de un Panel de administración de operaciones en MQL5 (Parte IV): Capa de seguridad de inicio de sesión
Imagine un actor malicioso infiltrándose en la sala del administrador comercial y obteniendo acceso a las computadoras y al panel de administración que se utilizan para comunicar información valiosa a millones de comerciantes en todo el mundo. Una intrusión de este tipo podría tener consecuencias desastrosas, como el envío no autorizado de mensajes engañosos o clics aleatorios en botones que desencadenan acciones no deseadas. En esta discusión, exploraremos las medidas de seguridad en MQL5 y las nuevas características de seguridad que hemos implementado en nuestro Panel de administración para protegernos contra estas amenazas. Al mejorar nuestros protocolos de seguridad, nuestro objetivo es proteger nuestros canales de comunicación y mantener la confianza de nuestra comunidad comercial global. Encuentre más información en la discusión de este artículo.
Integración de MQL5 con paquetes de procesamiento de datos (Parte 3): Visualización mejorada de datos Integración de MQL5 con paquetes de procesamiento de datos (Parte 3): Visualización mejorada de datos
En este artículo, realizaremos una visualización de datos mejorada que va más allá de los gráficos básicos, incorporando características como interactividad, datos en capas y elementos dinámicos, lo que permite a los operadores explorar tendencias, patrones y correlaciones de manera más eficaz.
Integración de Smart Money Concepts (SMC), Order Blocks (OB) y Fibonacci para entradas óptimas Integración de Smart Money Concepts (SMC), Order Blocks (OB) y Fibonacci para entradas óptimas
Los bloques de órdenes (Order Blocks, OB) son áreas clave donde los operadores institucionales inician compras o ventas significativas. Después de un movimiento de precio significativo, Fibonacci ayuda a identificar un retroceso potencial desde un máximo reciente hasta un mínimo para identificar la entrada comercial óptima.
Cómo crear un panel interactivo MQL5 utilizando la clase Controls (Parte 1): Configuración del panel Cómo crear un panel interactivo MQL5 utilizando la clase Controls (Parte 1): Configuración del panel
En este artículo, creamos un panel de control interactivo para operaciones bursátiles utilizando la clase Controls en MQL5, diseñada para optimizar las operaciones bursátiles. El panel incluye un título, botones de navegación para Operar, Cerrar e Información, y botones de acción especializados para ejecutar operaciones y gestionar posiciones. Al final del artículo, tendrás un panel base listo para futuras mejoras en futuras entregas.