
Kit de herramientas de negociación MQL5 (Parte 2): Ampliación e implantación de la biblioteca EX5 de gestión de posiciones
Introducción
En el primer artículo, analizamos en detalle las bibliotecas de código MQL5. Hemos tratado los diferentes tipos de bibliotecas, sus ventajas, la creación de bibliotecas EX5 y los componentes de un archivo de código fuente de biblioteca EX5 (.mq5). Esto le proporcionó una base sólida en las bibliotecas EX5 y su proceso de creación. A continuación, creamos un ejemplo práctico de una biblioteca de gestión de posiciones EX5, demostrando cómo codificar funciones exportables con MQL5.
En este artículo, seguiremos construyendo sobre esa base. Ampliaremos la biblioteca EX5 de gestión de posiciones y crearemos dos Asesores Expertos básicos. Uno de estos Asesores Expertos de ejemplo utilizará un panel gráfico de operaciones e información, demostrando cómo importar e implementar en la práctica la biblioteca EX5 de gestión de posiciones. Esto servirá como un ejemplo real de cómo crear e integrar una biblioteca EX5 en su código MQL5. Para empezar, desglosemos primero el proceso de importación y uso de una biblioteca binaria .ex5 ya desarrollada y compilada.
Cómo importar e implementar una biblioteca EX5
Para importar y utilizar una librería .EX5 en su código MQL5 (Asesores Expertos, Indicadores Personalizados, Scripts o Servicios), necesita insertar las directivas #import justo debajo de las directivas #property en la cabecera o sección superior de su archivo de código fuente. Para incluir la biblioteca binaria compilada, comience especificando la directiva #import seguida de la ruta del archivo donde se almacena la biblioteca. Por defecto, MQL5 busca bibliotecas en dos ubicaciones para ahorrarte tiempo referenciándolas directamente en tu código. La primera ubicación es la carpeta «MQL5/Libraries», que es la ubicación predefinida por defecto para almacenar las librerías. Si la biblioteca no se encuentra allí, MQL5 buscará entonces en la carpeta donde se encuentra el propio programa MQL. Si su librería EX5 está almacenada directamente en la carpeta «MQL5/Libraries/» o en la misma carpeta que su código fuente, simplemente especifique el nombre de la librería entre comillas dobles después de la directiva #import sin especificar la ruta de la carpeta.
Tras especificar la ruta de la carpeta de la biblioteca, indique el nombre de la biblioteca seguido de la extensión .ex5. En la siguiente línea nueva, añada las definiciones o descripciones de todos los prototipos de función exportados que se importarán en su código. Por último, termina el segmento de código de importación con otra directiva #import para cerrarlo.
#import "FilePath/LibraryName.ex5" //-- Opening .EX5 Library import directive //-- Function definitions/descriptions prototypes int FunctionPrototype1(); void FunctionPrototype2(bool y); bool FunctionPrototype3(double x); #import //--- Closing .EX5 Library import directive
Es necesario especificar y proporcionar la extensión .ex5 después del nombre de la biblioteca al declarar la directiva de importación. La omisión de la extensión indicará que está importando una biblioteca .DLL por defecto.
También puedes importar e implementar múltiples bibliotecas .ex5 en un único archivo MQL5. La estructura del código para importar varias bibliotecas .ex5 es similar a la de importar una sola biblioteca, con la única diferencia de la colocación de las directivas de cierre #import. Para múltiples importaciones de bibliotecas, la directiva de cierre #import de la primera biblioteca debe ir seguida del nombre de la siguiente biblioteca .ex5 que se importa. Esto cerrará la primera directiva de importación mientras inicia la siguiente directiva de importación, y así sucesivamente. Al cerrar la última directiva de importación de la última biblioteca, asegúrese de que termina sin nombre de biblioteca.
#import "FilePath/LibraryName.ex5" //-- Opening .EX5 Library import directive //-- Function definitions/descriptions prototypes for the first library here int FunctionPrototype1(); void FunctionPrototype2(bool y); #import "FilePath/SecondLibraryName.ex5" //-- Function definitions/descriptions prototypes for the second library here bool FunctionPrototype(); string FunctionPrototype2(bool z); #import //--- Closing .EX5 Library import directive
Cuando se trabaja con múltiples bibliotecas en MQL5, es necesario dar a cada uno un nombre único. No importa si todas estas bibliotecas están almacenadas en carpetas diferentes, tener nombres distintos es un requisito para no encontrar errores.
Cada biblioteca crea su propio entorno aislado o «espacio de nombres». Esto significa que las funciones dentro de una biblioteca se asocian con el nombre de esa biblioteca. Puede nombrar libremente las funciones dentro de una biblioteca sin preocuparse por los conflictos, incluso si coinciden con nombres de funciones incorporadas. Sin embargo, por lo general se recomienda evitar este tipo de denominaciones en aras de la claridad.
Si por casualidad tiene funciones con el mismo nombre en bibliotecas diferentes, el sistema dará prioridad a la función basándose en reglas específicas. Esto evita confusiones al llamar a funciones con nombres idénticos. Una vez que haya importado correctamente los prototipos de función de la biblioteca, podrá integrarlos sin problemas en su código y tratarlos como cualquier otra función local que haya definido usted mismo.
Más adelante en el artículo, ofrezco una explicación detallada de cómo incorporar y utilizar las bibliotecas EX5 en un entorno práctico. Encontrará dos demostraciones en profundidad: una en la que codificamos un Asesor Experto basado en la estrategia de trading VIDyA, y otra en la que utilizamos una interfaz gráfica de usuario (GUI). Estos Asesores Expertos integrarán y aprovecharán nuestra biblioteca personalizada Positions Management EX5. Estos ejemplos prácticos ofrecerán información valiosa sobre la implementación de las bibliotecas EX5 en Expert Advisors del mundo real.
Errores comunes de ejecución de la biblioteca EX5
La depuración de las bibliotecas EX5 puede ser un reto, ya que la mayoría de los errores comunes relacionados con las funciones prototipo importadas se producen durante el tiempo de ejecución al cargar la aplicación MQL5 final compilada en el terminal de operaciones. Estos errores suelen producirse al codificar la sección de directivas de biblioteca de importación del encabezado con valores incorrectos como las rutas o los nombres de los archivos de biblioteca, las descripciones de los prototipos de funciones, los tipos, los nombres, la lista completa de parámetros y los valores de retorno durante las declaraciones de importación. No se espera que el compilador detecte estos errores de declaración de importación en tiempo de compilación, ni se le encomienda esta tarea, porque no puede acceder al código fuente de la biblioteca importada, ya que está encapsulada y ya compilada en un módulo de formato binario ejecutable (.ex5).
Cualquier archivo de código fuente que contenga estos errores se compilará correctamente, pero cuando intentes cargar la aplicación MQL5 compilada en el terminal de trading, fallará y generará errores de ejecución. Estos errores se muestran en la pestaña Expertos o en la pestaña Diario del Terminal MetaTrader 5. Estos son los errores más comunes que puede encontrar:
Llamada a función de importación no resuelta: (no se encuentra <nombre_función> en <nombre_biblioteca.ex5>).
- Descripción: Este error de ejecución se produce al intentar cargar la aplicación MQL5 en un gráfico de MetaTrader 5 y se muestra en la pestaña Expertos. Está causado por definiciones o descripciones incorrectas de prototipos de funciones, como tipo, nombre o parámetros, proporcionadas en la sección de directivas de importación de la biblioteca.
- Resolución: Asegúrese de que el segmento de código de importación de la biblioteca está codificado correctamente con las definiciones de prototipo de función correctas según sea necesario y vuelva a compilar su código.
No se puede abrir el archivo 'Nombre_Biblioteca.ex5': (la carga de Nombre_del_asesor_experto (GBPJPY,M15) falló [0]).
- Descripción: Este error de ejecución se produce al intentar cargar la aplicación MQL5 en un gráfico de MetaTrader 5 y se muestra en la pestaña Diario. Se produce cuando no se puede localizar y cargar el archivo de biblioteca EX5 importado.
- Resolución: Asegúrese de que se especifica la ruta de archivo correcta a la biblioteca en el segmento de código de importación de la biblioteca y vuelva a compilar el código.
Mientras que otros errores pueden surgir cuando se trabaja con las bibliotecas importadas en MQL5, los errores en tiempo de ejecución anteriores son los más comunes y problemáticos para los desarrolladores principiantes. Estos errores son especialmente difíciles porque se pasan por alto con facilidad y no están diseñados para que el compilador los detecte durante la compilación.
Cómo actualizar y reimplementar bibliotecas EX5
Es importante seguir la secuencia correcta a la hora de redesplegar tus librerías EX5 después de cada actualización para asegurar que los nuevos cambios se integran correctamente en los proyectos MQL5 que utilizan la librería. La secuencia de compilación es el paso más crucial en la actualización y redistribución de las bibliotecas en MQL5. Para garantizar que todos los nuevos cambios y actualizaciones se utilicen en todos los proyectos que importen la biblioteca, siga estos pasos:
- Compilar el nuevo archivo EX5: Comience compilando el archivo de código fuente actualizado de la biblioteca .mq5 para crear el nuevo archivo binario ejecutable .ex5.
- Actualizar prototipos de función importados: En todos los proyectos MQL5 que utilicen la librería EX5, actualice cualquier definición de importación de prototipos de función si han cambiado en la nueva actualización de la librería .ex5.
- Compilar los proyectos: Recompila todos los proyectos MQL5 que implementen la librería EX5.
Función Trailing Stop Loss
Antes de poner en marcha nuestra biblioteca de gestión de puestos, vamos a ampliarla añadiendo algunas funciones vitales. Empezaremos añadiendo un módulo o función de gestión de trailing stop loss, ya que nuestra biblioteca no estará completa sin esta característica esencial. Un trailing stop loss es una parte importante de cualquier estrategia de negociación, ya que cuando se aplica correctamente, tiene el potencial de aumentar los márgenes de beneficio de un sistema y la tasa de éxito global.
La función trailing stop loss se llamará SetTrailingStopLoss() y se encargará de establecer el trailing SL de una posición abierta existente utilizando la entrada de la posición como mecanismo de filtrado. Tomará el número de ticket de una posición y el trailing stop loss deseado en pips (puntos) como argumentos o parámetros e intentará actualizar el trailing stop loss de la posición en el servidor de negociación cuando se cumplan ciertas condiciones. Esta función debe ser llamada continuamente en cada tick para modificar el trailing stop loss en tiempo real, ya que el estado de las posiciones objetivo cambia constantemente.
Primero comprobará si la negociación está permitida y si el trailing stop loss en pips (puntos) es válido. A continuación, seleccionará la posición, recuperará y guardará toda la información necesaria sobre el símbolo y calculará el precio de arrastre de pérdidas. Si el precio calculado es válido, enviará una orden al servidor de operaciones para fijar el stop loss. Si la orden se ejecuta correctamente, la función devolverá true; en caso contrario, devolverá false.
En primer lugar, empezaremos por crear la definición de la función. Nuestra función trailing stop loss será de tipo bool y tomará dos parámetros:
- ulong positionTicket: Se trata de un identificador único para la posición que vamos a modificar.
- int trailingStopLoss: Es el nivel de Stop Loss deseado en pips (puntos) desde el precio actual de la posición.
La palabra clave export indica que esta función de biblioteca se puede llamar desde cualquier archivo de código fuente MQL5 o proyecto que la importe.
bool SetTrailingStopLoss(ulong positionTicket, int trailingStopLoss) export { //-- place the function body here }
Tenemos que comprobar si se permite la negociación y si el parámetro trailingStopLoss es mayor que cero. Si no se cumple alguna de las dos condiciones, salimos de la función y devolvemos false para terminar la operación.
if(!TradingIsAllowed() || trailingStopLoss == 0) { return(false); //--- algo trading is disabled or trailing stop loss is invalid, exit function }
A continuación, confirmamos y seleccionamos la posición utilizando el positionTicket proporcionado. Si la selección de posición falla, imprimimos un mensaje de error y salimos de la función.
//--- Confirm and select the position using the provided positionTicket ResetLastError(); //--- Reset error cache incase of ticket selection errors if(!PositionSelectByTicket(positionTicket)) { //---Position selection failed Print("\r\n_______________________________________________________________________________________"); Print(__FUNCTION__, ": Selecting position with ticket:", positionTicket, " failed. ERROR: ", GetLastError()); return(false); //-- Exit the function }
A continuación, creamos algunas variables para ayudarnos a almacenar y validar el trailing stop loss. Comenzamos creando la variable slPrice para almacenar el precio calculado del trailing stop loss y, a continuación, guardamos las propiedades de la posición, como el símbolo, el precio de entrada, el volumen, el precio actual del stop loss, el precio actual del take profit y el tipo de posición.
//-- create variable to store the calculated trailing sl prices to send to the trade server double slPrice = 0.0; //--- Position ticket selected, save the position properties string positionSymbol = PositionGetString(POSITION_SYMBOL); double entryPrice = PositionGetDouble(POSITION_PRICE_OPEN); double volume = PositionGetDouble(POSITION_VOLUME); double currentPositionSlPrice = PositionGetDouble(POSITION_SL); double currentPositionTpPrice = PositionGetDouble(POSITION_TP); ENUM_POSITION_TYPE positionType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
Asimismo, seguimos guardando las distintas propiedades del símbolo asociadas a la posición seleccionada. Estas propiedades también se utilizarán más adelante para validar y calcular el trailing stop loss.
//-- Get some information about the positions symbol int symbolDigits = (int)SymbolInfoInteger(positionSymbol, SYMBOL_DIGITS); //-- Number of symbol decimal places int symbolStopLevel = (int)SymbolInfoInteger(positionSymbol, SYMBOL_TRADE_STOPS_LEVEL); double symbolPoint = SymbolInfoDouble(positionSymbol, SYMBOL_POINT); double positionPriceCurrent = PositionGetDouble(POSITION_PRICE_CURRENT); int spread = (int)SymbolInfoInteger(positionSymbol, SYMBOL_SPREAD);
Comprobamos si el valor de trailing stop loss proporcionado es inferior al nivel de stop de la operación del símbolo. Si lo es, ajustamos el trailing stop loss para que sea igual al nivel de stop del símbolo.
//-- Check if the trailing stop loss is less than the symbol trade stop levels if(trailingStopLoss < symbolStopLevel) { //-- Trailing stop loss is less than the allowed level for the current symbol trailingStopLoss = symbolStopLevel; //-- Set it to the symbol stop level by default }
El siguiente paso consiste en calcular el precio de arrastre de pérdidas en función de si la posición es de compra o de venta. Para las posiciones de compra, el precio de stop loss se fija por debajo del precio actual, mientras que para las posiciones de venta, se fija por encima del precio actual. También validamos que el precio de stop loss calculado está dentro de los límites válidos.
//-- Calculate and store the trailing stop loss price if(positionType == POSITION_TYPE_BUY) { slPrice = positionPriceCurrent - (trailingStopLoss * symbolPoint); //-- Check if the proposed slPrice for the trailing stop loss is valid if(slPrice < entryPrice || slPrice < currentPositionSlPrice) { return(false); //-- Exit the function, proposed trailing stop loss price is invalid } } else //-- SELL POSITION { slPrice = positionPriceCurrent + (trailingStopLoss * symbolPoint); //-- Check if the proposed slPrice for the trailing stop loss is valid if(slPrice > entryPrice || slPrice > currentPositionSlPrice) { return(false); //-- Exit the function, proposed trailing stop loss price is invalid } }
Antes de establecer el trailing stop loss, imprimamos los detalles de la posición en el registro de MetaTrader 5. Esto incluye el símbolo, el tipo de posición, el volumen, el precio de entrada, los precios actuales de stop loss y take profit, y otra información relevante.
//-- Print position properties before setting the trailing stop loss string positionProperties = "--> " + positionSymbol + " " + EnumToString(positionType) + " Trailing Stop Loss Modification Details" + " <--\r\n"; positionProperties += "------------------------------------------------------------\r\n"; positionProperties += "Ticket: " + (string)positionTicket + "\r\n"; positionProperties += "Volume: " + StringFormat("%G", volume) + "\r\n"; positionProperties += "Price Open: " + StringFormat("%G", entryPrice) + "\r\n"; positionProperties += "Current SL: " + StringFormat("%G", currentPositionSlPrice) + " -> New Trailing SL: " + (string)slPrice + "\r\n"; positionProperties += "Current TP: " + StringFormat("%G", currentPositionTpPrice) + "\r\n"; positionProperties += "Comment: " + PositionGetString(POSITION_COMMENT) + "\r\n"; positionProperties += "Magic Number: " + (string)PositionGetInteger(POSITION_MAGIC) + "\r\n"; positionProperties += "---"; Print(positionProperties);
Reseteamos las estructuras tradeRequest y tradeResult a cero. A continuación, inicializamos los parámetros necesarios para establecer el stop loss y el take profit.
//-- 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_SLTP; //-- Trade operation type for setting sl and tp tradeRequest.position = positionTicket; tradeRequest.symbol = positionSymbol; tradeRequest.sl = slPrice; tradeRequest.tp = currentPositionTpPrice;
Por último, restablecemos la caché de errores y enviamos la orden al servidor de operaciones hasta que tenga éxito o hasta 101 reintentos. Si la orden se ejecuta correctamente, imprimimos un mensaje de éxito, devolvemos true y salimos de la función. Si la solicitud de pedido falla, gestionamos el error, devolvemos false y salimos de la función.
ResetLastError(); //--- reset error cache so that we get an accurate runtime error code in the ErrorAdvisor function for(int loop = 0; loop <= 100; loop++) //-- try modifying the sl and tp 101 times untill 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 set the Trailing SL for #%I64d %s %s", positionTicket, positionSymbol, EnumToString(positionType)); 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__, positionSymbol, tradeResult.retcode) || IsStopped()) { PrintFormat("ERROR setting the Trailing SL for #%I64d %s %s", positionTicket, positionSymbol, EnumToString(positionType)); Print("_______________________________________________________________________________________\r\n\r\n"); return(false); //-- exit function break; //-- exit for loop } } } return(false); }
Asegúrese de que todos los segmentos de código de la función SetTrailingStopLoss() estén completos en la secuencia siguiente:
bool SetTrailingStopLoss(ulong positionTicket, int trailingStopLoss) export { //-- first check if the EA is allowed to trade and the trailing stop loss parameter is more than zero if(!TradingIsAllowed() || trailingStopLoss == 0) { return(false); //--- algo trading is disabled or trailing stop loss is invalid, exit function } //--- Confirm and select the position using the provided positionTicket ResetLastError(); //--- Reset error cache incase of ticket selection errors if(!PositionSelectByTicket(positionTicket)) { //---Position selection failed Print("\r\n_______________________________________________________________________________________"); Print(__FUNCTION__, ": Selecting position with ticket:", positionTicket, " failed. ERROR: ", GetLastError()); return(false); //-- Exit the function } //-- create variable to store the calculated trailing sl prices to send to the trade server double slPrice = 0.0; //--- Position ticket selected, save the position properties string positionSymbol = PositionGetString(POSITION_SYMBOL); double entryPrice = PositionGetDouble(POSITION_PRICE_OPEN); double volume = PositionGetDouble(POSITION_VOLUME); double currentPositionSlPrice = PositionGetDouble(POSITION_SL); double currentPositionTpPrice = PositionGetDouble(POSITION_TP); ENUM_POSITION_TYPE positionType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); //-- Get some information about the positions symbol int symbolDigits = (int)SymbolInfoInteger(positionSymbol, SYMBOL_DIGITS); //-- Number of symbol decimal places int symbolStopLevel = (int)SymbolInfoInteger(positionSymbol, SYMBOL_TRADE_STOPS_LEVEL); double symbolPoint = SymbolInfoDouble(positionSymbol, SYMBOL_POINT); double positionPriceCurrent = PositionGetDouble(POSITION_PRICE_CURRENT); int spread = (int)SymbolInfoInteger(positionSymbol, SYMBOL_SPREAD); //-- Check if the trailing stop loss is less than the symbol trade stop levels if(trailingStopLoss < symbolStopLevel) { //-- Trailing stop loss is less than the allowed level for the current symbol trailingStopLoss = symbolStopLevel; //-- Set it to the symbol stop level by default } //-- Calculate and store the trailing stop loss price if(positionType == POSITION_TYPE_BUY) { slPrice = positionPriceCurrent - (trailingStopLoss * symbolPoint); //-- Check if the proposed slPrice for the trailing stop loss is valid if(slPrice < entryPrice || slPrice < currentPositionSlPrice) { return(false); //-- Exit the function, proposed trailing stop loss price is invalid } } else //-- SELL POSITION { slPrice = positionPriceCurrent + (trailingStopLoss * symbolPoint); //-- Check if the proposed slPrice for the trailing stop loss is valid if(slPrice > entryPrice || slPrice > currentPositionSlPrice) { return(false); //-- Exit the function, proposed trailing stop loss price is invalid } } //-- Print position properties before setting the trailing stop loss string positionProperties = "--> " + positionSymbol + " " + EnumToString(positionType) + " Trailing Stop Loss Modification Details" + " <--\r\n"; positionProperties += "------------------------------------------------------------\r\n"; positionProperties += "Ticket: " + (string)positionTicket + "\r\n"; positionProperties += "Volume: " + StringFormat("%G", volume) + "\r\n"; positionProperties += "Price Open: " + StringFormat("%G", entryPrice) + "\r\n"; positionProperties += "Current SL: " + StringFormat("%G", currentPositionSlPrice) + " -> New Trailing SL: " + (string)slPrice + "\r\n"; positionProperties += "Current TP: " + StringFormat("%G", currentPositionTpPrice) + "\r\n"; positionProperties += "Comment: " + PositionGetString(POSITION_COMMENT) + "\r\n"; positionProperties += "Magic Number: " + (string)PositionGetInteger(POSITION_MAGIC) + "\r\n"; positionProperties += "---"; Print(positionProperties); //-- 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_SLTP; //-- Trade operation type for setting sl and tp tradeRequest.position = positionTicket; tradeRequest.symbol = positionSymbol; tradeRequest.sl = slPrice; tradeRequest.tp = currentPositionTpPrice; ResetLastError(); //--- reset error cache so that we get an accurate runtime error code in the ErrorAdvisor function for(int loop = 0; loop <= 100; loop++) //-- try modifying the sl and tp 101 times untill 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 set the Trailing SL for #%I64d %s %s", positionTicket, positionSymbol, EnumToString(positionType)); 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__, positionSymbol, tradeResult.retcode) || IsStopped()) { PrintFormat("ERROR setting the Trailing SL for #%I64d %s %s", positionTicket, positionSymbol, EnumToString(positionType)); Print("_______________________________________________________________________________________\r\n\r\n"); return(false); //-- exit function break; //-- exit for loop } } } return(false); }
Cerrar todas las posiciones
Esta función está diseñada para ser muy flexible y se encargará de cerrar todas las posiciones abiertas en función de los parámetros especificados. Llamaremos a la función CloseAllPositions(). Buscará posiciones abiertas que coincidan con los argumentos o parámetros proporcionados de símbolo y número mágico e intentará cerrarlas todas. Si no se permite la negociación, la función dejará de ejecutarse y saldrá inmediatamente. La función recorrerá todas las posiciones abiertas, las filtrará en función de los criterios especificados y cerrará todas las posiciones coincidentes.
Cuando termine de intentar cerrar todas las posiciones, entrará en un bucle para confirmar que se han cerrado todas las posiciones objetivo, gestionar cualquier error y asegurarse de que no entramos en un bucle infinito. Cuando nuestra función cierre con éxito todas las posiciones, saldrá, devolviendo true; en caso contrario, devolverá false.
Empecemos por definir la función CloseAllPositions(). Devolverá un bool y aceptará dos parámetros con valores por defecto:
- string symbol: Por defecto es ALL_SYMBOLS.
- ulong magicNumber: Este valor por defecto es 0.
bool CloseAllPositions(string symbol = ALL_SYMBOLS, ulong magicNumber = 0) export { //-- Functions body goes here }
Tenemos que comprobar si se permite el comercio. Si no se permite la negociación, salimos de la función y devolvemos false.
if(!TradingIsAllowed()) { return(false); //--- algo trading is disabled, exit function }
Crea una nueva variable de tipo bool returnThis para almacenar el valor de retorno de la función y dale un valor por defecto de false.
bool returnThis = false;
Recuperar y guardar el número total de posiciones abiertas y utilizar este valor en un bucle for que nos permitirá acceder y procesar todas las posiciones abiertas. En cada iteración, guardaremos las propiedades de posición seleccionadas y utilizaremos estos datos para filtrar las posiciones en función del símbolo y el número mágico proporcionados. Si la posición no coincide con los criterios, se pasa a la posición siguiente. Si la posición coincide con los criterios, cerramos la posición utilizando la función ClosePositionByTicket().
int totalOpenPositions = PositionsTotal(); for(int x = 0; x < totalOpenPositions; x++) { //--- Get position properties ulong positionTicket = PositionGetTicket(x); //-- Get ticket to select the position string selectedSymbol = PositionGetString(POSITION_SYMBOL); ulong positionMagicNo = PositionGetInteger(POSITION_MAGIC); //-- Filter positions by symbol and magic number if( (symbol != ALL_SYMBOLS && symbol != selectedSymbol) || (magicNumber != 0 && positionMagicNo != magicNumber) ) { continue; } //-- Close the position ClosePositionByTicket(positionTicket); }
Ahora hemos iterado sobre todas las posiciones abiertas especificadas y enviado solicitudes de terminación al servidor de operaciones para cerrarlas. Antes de concluir la función, debemos confirmar que todas las posiciones objetivo se han cerrado realmente. Para ello, utilizaremos un bucle que llame repetidamente a la función CloseAllPositions() de forma recursiva hasta que se cierren todas las posiciones que coincidan con nuestros criterios. En cada iteración, intentaremos cerrar las posiciones restantes, pausar el envío de la orden durante un breve periodo de tiempo para acelerar la ejecución y evitar saturar el servidor de operaciones e incrementar un contador de interrupciones para evitar bucles infinitos. También comprobaremos los errores críticos y otras condiciones de salida (como que el script se detenga o exceda el número máximo de bucles). Si se cumple alguna de estas condiciones, saldremos del bucle.
int breakerBreaker = 0; //-- Variable that safeguards and makes sure we are not locked in an infinite loop while(SymbolPositionsTotal(symbol, magicNumber) > 0) { breakerBreaker++; CloseAllPositions(symbol, magicNumber); //-- We still have some open positions, do a function callback Sleep(100); //-- 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 > 101) { break; } }
Vuelva a comprobar que se han cerrado todas las posiciones objetivo y guarde este estado en la variable de retorno antes de concluir y salir de la función.
if(SymbolPositionsTotal(symbol, magicNumber) == 0) { returnThis = true; //-- Save this status for the function return value } return(returnThis);
Confirme que todos los segmentos de código de la función CloseAllPositions() están completos en la secuencia siguiente:
bool CloseAllPositions(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 positions and close them int totalOpenPositions = PositionsTotal(); for(int x = 0; x < totalOpenPositions; x++) { //--- Get position properties ulong positionTicket = PositionGetTicket(x); //-- Get ticket to select the position string selectedSymbol = PositionGetString(POSITION_SYMBOL); ulong positionMagicNo = PositionGetInteger(POSITION_MAGIC); //-- Filter positions by symbol and magic number if( (symbol != ALL_SYMBOLS && symbol != selectedSymbol) || (magicNumber != 0 && positionMagicNo != magicNumber) ) { continue; } //-- Close the position ClosePositionByTicket(positionTicket); } //-- Confirm that we have closed all the positions being targeted int breakerBreaker = 0; //-- Variable that safeguards and makes sure we are not locked in an infinite loop while(SymbolPositionsTotal(symbol, magicNumber) > 0) { breakerBreaker++; CloseAllPositions(symbol, magicNumber); //-- We still have some open positions, do a function callback Sleep(100); //-- 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 > 101) { break; } } //-- Final confirmations that all targeted positions have been closed if(SymbolPositionsTotal(symbol, magicNumber) == 0) { returnThis = true; //-- Save this status for the function return value } return(returnThis); }
Cerrar todas las posiciones y función de sobrecarga
Por comodidad, sobrecargaremos la función CloseAllPositions() con una segunda versión que no acepta parámetros y cierra todas las posiciones abiertas en la cuenta cuando se llama. Esta función también podrá exportarse y utilizarse en la biblioteca EX5 'Positions Manager'.
//+------------------------------------------------------------------+ //| CloseAllPositions(): Closes all positions in the account | //+------------------------------------------------------------------+ bool CloseAllPositions() export { return(CloseAllPositions(ALL_SYMBOLS, 0)); }
Clasificación y filtrado de funciones de cierre de posiciones
Si navega por los foros de desarrolladores de MQL5, a menudo encontrará preguntas de desarrolladores principiantes de MQL5 que buscan ayuda con la codificación de algoritmos para filtrar, ordenar y gestionar diversas operaciones de posición, como el cierre o la modificación de posiciones específicas en función de criterios como el número mágico, el estado de ganancias o pérdidas, etc. La siguiente biblioteca de funciones pretende dar respuesta a esta necesidad, facilitando y agilizando la aplicación eficaz de estas operaciones.
Las funciones de ordenación y filtrado de cierre de posiciones que aparecen a continuación implementan un enfoque similar al de la función CloseAllPositions(), pero presentan diferencias notables propias de cada una. Utilizan una estrategia de programación recursiva para garantizar que se cierran todas las posiciones especificadas e incluyen registros de seguimiento para imprimir y registrar cualquier error encontrado en el registro de Asesores Expertos para el diagnóstico del usuario final. Una ventaja añadida de estas funciones es su elevada tasa de éxito en el cumplimiento de los objetivos especificados, ya que buscan recursivamente errores recuperables y envían las solicitudes de operaciones especificadas varias veces para garantizar que las órdenes tengan éxito. Para una comprensión más profunda de cómo funciona cada función, he incluido comentarios de código detallados para explicar la estructura y organización de cada componente de código dentro de las funciones.
Cerrar todas las posiciones de compra
La función CloseAllBuyPositions() se encarga de cerrar todas las posiciones de compra abiertas que coincidan con los parámetros o argumentos de la función proporcionados de nombre de símbolo y número mágico. Devuelve un bool, indicando true si cierra con éxito todas las posiciones especificadas y false en caso contrario.
bool CloseAllBuyPositions(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 positions and close them int totalOpenPositions = PositionsTotal(); for(int x = 0; x < totalOpenPositions; x++) { //--- Get position properties ulong positionTicket = PositionGetTicket(x); //-- Get ticket to select the position string selectedSymbol = PositionGetString(POSITION_SYMBOL); ulong positionMagicNo = PositionGetInteger(POSITION_MAGIC); ulong positionType = PositionGetInteger(POSITION_TYPE); //-- Filter positions by symbol, type and magic number if( (symbol != ALL_SYMBOLS && symbol != selectedSymbol) || (positionType != POSITION_TYPE_BUY) || (magicNumber != 0 && positionMagicNo != magicNumber) ) { continue; } //-- Close the position ClosePositionByTicket(positionTicket); } //-- Confirm that we have closed all the buy positions being targeted int breakerBreaker = 0; //-- Variable that safeguards and makes sure we are not locked in an infinite loop while(SymbolBuyPositionsTotal(symbol, magicNumber) > 0) { breakerBreaker++; CloseAllBuyPositions(symbol, magicNumber); //-- We still have some open buy positions, do a function callback Sleep(100); //-- 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 > 101) { break; } } if(SymbolBuyPositionsTotal(symbol, magicNumber) == 0) { returnThis = true; } return(returnThis); }
Cerrar todas las posiciones de venta
La función CloseAllSellPositions() se encarga de cerrar todas las posiciones de venta abiertas que coincidan con los parámetros o argumentos de la función proporcionados de nombre de símbolo y número mágico. Devuelve un bool, indicando true si cierra con éxito todas las posiciones especificadas y false en caso contrario.
bool CloseAllSellPositions(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 positions and close them int totalOpenPositions = PositionsTotal(); for(int x = 0; x < totalOpenPositions; x++) { //--- Get position properties ulong positionTicket = PositionGetTicket(x); //-- Get ticket to select the position string selectedSymbol = PositionGetString(POSITION_SYMBOL); ulong positionMagicNo = PositionGetInteger(POSITION_MAGIC); ulong positionType = PositionGetInteger(POSITION_TYPE); //-- Filter positions by symbol, type and magic number if( (symbol != ALL_SYMBOLS && symbol != selectedSymbol) || (positionType != POSITION_TYPE_SELL) || (magicNumber != 0 && positionMagicNo != magicNumber) ) { continue; } //-- Close the position ClosePositionByTicket(positionTicket); } //-- Confirm that we have closed all the sell positions being targeted int breakerBreaker = 0; //-- Variable that safeguards and makes sure we are not locked in an infinite loop while(SymbolSellPositionsTotal(symbol, magicNumber) > 0) { breakerBreaker++; CloseAllSellPositions(symbol, magicNumber); //-- We still have some open sell positions, do a function callback Sleep(100); //-- 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 > 101) { break; } } if(SymbolSellPositionsTotal(symbol, magicNumber) == 0) { returnThis = true; } return(returnThis); }
Cerrar todas las posiciones "mágicas"
La función CloseAllMagicPositions() se encarga de cerrar todas las posiciones abiertas que coincidan con el parámetro o argumento de función de número mágico proporcionado. Devuelve un bool, indicando true si cierra con éxito todas las posiciones especificadas y false en caso contrario.
bool CloseAllMagicPositions(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 positions data ulong positionTicket, positionMagicNo; string positionSymbol; //-- Scan for magic number specific positions and close them int totalOpenPositions = PositionsTotal(); for(int x = 0; x < totalOpenPositions; x++) { //--- Get position properties positionTicket = PositionGetTicket(x); //-- Get ticket to select the position positionMagicNo = PositionGetInteger(POSITION_MAGIC); positionSymbol = PositionGetString(POSITION_SYMBOL); //-- Filter positions by magic number if(magicNumber == positionMagicNo) { //-- Close the position ClosePositionByTicket(positionTicket); } } //-- Confirm that we have closed all the positions being targeted int breakerBreaker = 0; //-- Variable that safeguards and makes sure we are not locked in an infinite loop while(MagicPositionsTotal(magicNumber) > 0) { breakerBreaker++; CloseAllMagicPositions(magicNumber); //-- We still have some open positions, do a function callback Sleep(100); //-- 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__, positionSymbol, GetLastError()) || IsStopped() || breakerBreaker > 101) { break; } } if(MagicPositionsTotal(magicNumber) == 0) { returnThis = true; } return(returnThis); }
Cerrar todas las posiciones rentables
La función CloseAllProfitablePositions() cierra todas las posiciones abiertas rentables que coincidan con los parámetros o argumentos de la función de nombre de símbolo y número mágico proporcionados. Devuelve un bool, indicando true si cierra con éxito todas las posiciones especificadas y false en caso contrario.
bool CloseAllProfitablePositions(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 } //-- Scan for profitable positions that match the specified symbol and magic number to close them int totalOpenPositions = PositionsTotal(); for(int x = 0; x < totalOpenPositions; x++) { //--- Get position properties ulong positionTicket = PositionGetTicket(x); //-- Get ticket to select the position string selectedSymbol = PositionGetString(POSITION_SYMBOL); ulong positionMagicNo = PositionGetInteger(POSITION_MAGIC); double positionProfit = PositionGetDouble(POSITION_PROFIT); //-- Filter positions by symbol, magic number and profit if( ((symbol != ALL_SYMBOLS && symbol != selectedSymbol) || (magicNumber != 0 && positionMagicNo != magicNumber)) || positionProfit <= 0 ) { continue; } //-- Close the position ClosePositionByTicket(positionTicket); } return(true); }
___
Cerrar todas las posiciones de compra rentables
La función CloseAllProfitableBuyPositions() cierra todas las posiciones de compra abiertas rentables que coincidan con los parámetros o argumentos de la función proporcionados de nombre de símbolo y número mágico. Devuelve un bool, indicando true si cierra con éxito todas las posiciones especificadas y false en caso contrario.
bool CloseAllProfitableBuyPositions(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 } //-- Scan for profitable positions that match the specified symbol and magic number to close them int totalOpenPositions = PositionsTotal(); for(int x = 0; x < totalOpenPositions; x++) { //--- Get position properties ulong positionTicket = PositionGetTicket(x); //-- Get ticket to select the position string selectedSymbol = PositionGetString(POSITION_SYMBOL); ulong positionMagicNo = PositionGetInteger(POSITION_MAGIC); double positionProfit = PositionGetDouble(POSITION_PROFIT); //-- Filter positions by symbol, magic number, profit and type if( ((symbol != ALL_SYMBOLS && symbol != selectedSymbol) || (magicNumber != 0 && positionMagicNo != magicNumber)) || positionProfit <= 0 || PositionGetInteger(POSITION_TYPE) != POSITION_TYPE_BUY ) { continue; } //-- Close the position ClosePositionByTicket(positionTicket); } return(true); }
Cerrar todas las posiciones de venta rentables
La función CloseAllProfitableSellPositions() cierra todas las posiciones de venta abiertas rentables que coincidan con los parámetros o argumentos de la función proporcionados de nombre de símbolo y número mágico. Devuelve un bool, indicando true si cierra con éxito todas las posiciones especificadas y false en caso contrario.
bool CloseAllProfitableSellPositions(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 } //-- Scan for profitable positions that match the specified symbol and magic number to close them int totalOpenPositions = PositionsTotal(); for(int x = 0; x < totalOpenPositions; x++) { //--- Get position properties ulong positionTicket = PositionGetTicket(x); //-- Get ticket to select the position string selectedSymbol = PositionGetString(POSITION_SYMBOL); ulong positionMagicNo = PositionGetInteger(POSITION_MAGIC); double positionProfit = PositionGetDouble(POSITION_PROFIT); //-- Filter positions by symbol, magic number, profit and type if( ((symbol != ALL_SYMBOLS && symbol != selectedSymbol) || (magicNumber != 0 && positionMagicNo != magicNumber)) || positionProfit <= 0 || PositionGetInteger(POSITION_TYPE) != POSITION_TYPE_SELL ) { continue; } //-- Close the position ClosePositionByTicket(positionTicket); } return(true); }
Cerrar todas las posiciones con pérdidas
La función CloseAllLossPositions() cierra todas las posiciones abiertas perdedoras que coincidan con los parámetros o argumentos de la función de nombre de símbolo y número mágico proporcionados. Devuelve un bool, indicando true si cierra con éxito todas las posiciones especificadas y false si no lo hace.
bool CloseAllLossPositions(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 } //-- Scan for loss positions that match the specified symbol and magic number and close them int totalOpenPositions = PositionsTotal(); for(int x = 0; x < totalOpenPositions; x++) { //--- Get position properties ulong positionTicket = PositionGetTicket(x); //-- Get ticket to select the position string selectedSymbol = PositionGetString(POSITION_SYMBOL); ulong positionMagicNo = PositionGetInteger(POSITION_MAGIC); double positionProfit = PositionGetDouble(POSITION_PROFIT); //-- Filter positions by symbol, magic number and profit if( ((symbol != ALL_SYMBOLS && symbol != selectedSymbol) || (magicNumber != 0 && positionMagicNo != magicNumber)) || positionProfit > 0 ) { continue; } //-- Close the position ClosePositionByTicket(positionTicket); } return(true); }
Cerrar todas las posiciones de compra con pérdidas
La función CloseAllLossBuyPositions() cierra todas las posiciones de compra abiertas perdedoras que coincidan con los parámetros o argumentos de la función proporcionados de nombre de símbolo y número mágico. Devuelve un bool, indicando true si cierra con éxito todas las posiciones especificadas y false si no lo hace.
bool CloseAllLossBuyPositions(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 } //-- Scan for loss positions that match the specified symbol and magic number and close them int totalOpenPositions = PositionsTotal(); for(int x = 0; x < totalOpenPositions; x++) { //--- Get position properties ulong positionTicket = PositionGetTicket(x); //-- Get ticket to select the position string selectedSymbol = PositionGetString(POSITION_SYMBOL); ulong positionMagicNo = PositionGetInteger(POSITION_MAGIC); double positionProfit = PositionGetDouble(POSITION_PROFIT); //-- Filter positions by symbol, magic number, profit and type if( ((symbol != ALL_SYMBOLS && symbol != selectedSymbol) || (magicNumber != 0 && positionMagicNo != magicNumber)) || positionProfit > 0 || PositionGetInteger(POSITION_TYPE) != POSITION_TYPE_BUY ) { continue; } //-- Close the position ClosePositionByTicket(positionTicket); } return(true); }
Cerrar todas las posiciones de venta con pérdidas
La función CloseAllLossSellPositions() cierra todas las posiciones de venta abiertas perdedoras que coincidan con los parámetros o argumentos de la función proporcionados de nombre de símbolo y número mágico. Devuelve un bool, indicando true si cierra con éxito todas las posiciones especificadas y false si no lo hace.
bool CloseAllLossSellPositions(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 } //-- Scan for loss positions that match the specified symbol and magic number and close them int totalOpenPositions = PositionsTotal(); for(int x = 0; x < totalOpenPositions; x++) { //--- Get position properties ulong positionTicket = PositionGetTicket(x); //-- Get ticket to select the position string selectedSymbol = PositionGetString(POSITION_SYMBOL); ulong positionMagicNo = PositionGetInteger(POSITION_MAGIC); double positionProfit = PositionGetDouble(POSITION_PROFIT); //-- Filter positions by symbol, magic number, profit and type if( ((symbol != ALL_SYMBOLS && symbol != selectedSymbol) || (magicNumber != 0 && positionMagicNo != magicNumber)) || positionProfit > 0 || PositionGetInteger(POSITION_TYPE) != POSITION_TYPE_SELL ) { continue; } //-- Close the position ClosePositionByTicket(positionTicket); } return(true); }
Funciones de estado de la posición
Al desarrollar un sistema de negociación, es importante realizar un seguimiento del estado de la cuenta utilizando datos en tiempo real sobre las distintas posiciones. Tanto si está desarrollando una estrategia basada en cuadrículas como una estrategia conservadora de acción de precios, tener una visión clara y directa de todas las posiciones abiertas es fundamental para el éxito de su sistema de negociación. Sin embargo, no existen funciones estándar del lenguaje que proporcionen esta información. Esta biblioteca EX5 pretende simplificar la recopilación de información de posición con llamadas a funciones de una sola línea. Las funciones exportables que se indican a continuación le proporcionarán la ventaja que necesita para supervisar las posiciones y decidir si cerrarlas o ampliarlas, constituyendo uno de los pilares fundamentales de su sistema de negociación.
Obtener datos de posiciones
La función GetPositionsData() desempeña un papel crucial en la recopilación y almacenamiento de toda la información necesaria sobre el estado de las posiciones. Guarda estos datos en variables globales que son fácilmente accesibles dentro de toda la biblioteca. Estas variables se actualizan continuamente con cada tick, lo que garantiza su precisión y fiabilidad.
Coloque las siguientes declaraciones de variables globales en la parte superior de nuestra biblioteca debajo de las declaraciones de variables globales de las estructuras de datos de solicitud y resultado de las operaciones comerciales.
string accountCurrency = AccountInfoString(ACCOUNT_CURRENCY); //-- Position status global variables //------------------------------------------------------------------------------------------------------------------- int accountBuyPositionsTotal = 0, accountSellPositionsTotal = 0, symbolPositionsTotal = 0, symbolBuyPositionsTotal = 0, symbolSellPositionsTotal = 0, magicPositionsTotal = 0, magicBuyPositionsTotal = 0, magicSellPositionsTotal = 0; double accountPositionsVolumeTotal = 0.0, accountBuyPositionsVolumeTotal = 0.0, accountSellPositionsVolumeTotal = 0.0, accountBuyPositionsProfit = 0.0, accountSellPositionsProfit = 0.0, symbolPositionsVolumeTotal = 0.0, symbolBuyPositionsVolumeTotal = 0.0, symbolSellPositionsVolumeTotal = 0.0, symbolPositionsProfit = 0.0, symbolBuyPositionsProfit = 0.0, symbolSellPositionsProfit = 0.0, magicPositionsVolumeTotal = 0.0, magicBuyPositionsVolumeTotal = 0.0, magicSellPositionsVolumeTotal = 0.0, magicPositionsProfit = 0.0, magicBuyPositionsProfit = 0.0, magicSellPositionsProfit = 0.0;
Actualice y guarde los datos de estado de posición en la función GetPositionsData() a continuación.
void GetPositionsData(string symbol, ulong magicNumber) { //-- Reset the acount open positions status accountBuyPositionsTotal = 0; accountSellPositionsTotal = 0; accountPositionsVolumeTotal = 0.0; accountBuyPositionsVolumeTotal = 0.0; accountSellPositionsVolumeTotal = 0.0; accountBuyPositionsProfit = 0.0; accountSellPositionsProfit = 0.0; //-- Reset the EA's magic open positions status magicPositionsTotal = 0; magicBuyPositionsTotal = 0; magicSellPositionsTotal = 0; magicPositionsVolumeTotal = 0.0; magicBuyPositionsVolumeTotal = 0.0; magicSellPositionsVolumeTotal = 0.0; magicPositionsProfit = 0.0; magicBuyPositionsProfit = 0.0; magicSellPositionsProfit = 0.0; //-- Reset the symbol open positions status symbolPositionsTotal = 0; symbolBuyPositionsTotal = 0; symbolSellPositionsTotal = 0; symbolPositionsVolumeTotal = 0.0; symbolBuyPositionsVolumeTotal = 0.0; symbolSellPositionsVolumeTotal = 0.0; symbolPositionsProfit = 0.0; symbolBuyPositionsProfit = 0.0; symbolSellPositionsProfit = 0.0; //-- Update and save the open positions status with realtime data int totalOpenPositions = PositionsTotal(); if(totalOpenPositions > 0) { //-- Scan for symbol and magic number specific positions and save their status for(int x = 0; x < totalOpenPositions; x++) { //--- Get position properties ulong positionTicket = PositionGetTicket(x); //-- Get ticket to select the position string selectedSymbol = PositionGetString(POSITION_SYMBOL); ulong positionMagicNo = PositionGetInteger(POSITION_MAGIC); //-- Filter positions by magic number if(magicNumber != 0 && positionMagicNo != magicNumber) { continue; } //-- Save the account positions status first accountPositionsVolumeTotal += PositionGetDouble(POSITION_VOLUME); if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) { //-- Account properties ++accountBuyPositionsTotal; accountBuyPositionsVolumeTotal += PositionGetDouble(POSITION_VOLUME); accountBuyPositionsProfit += PositionGetDouble(POSITION_PROFIT); } else //-- POSITION_TYPE_SELL { //-- Account properties ++accountSellPositionsTotal; accountSellPositionsVolumeTotal += PositionGetDouble(POSITION_VOLUME); accountSellPositionsProfit += PositionGetDouble(POSITION_PROFIT); } //-- Filter positions openend by EA and save their status if( PositionGetInteger(POSITION_REASON) == POSITION_REASON_EXPERT && positionMagicNo == magicNumber ) { ++magicPositionsTotal; magicPositionsProfit += PositionGetDouble(POSITION_PROFIT); magicPositionsVolumeTotal += PositionGetDouble(POSITION_VOLUME); if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) { //-- Magic properties ++magicBuyPositionsTotal; magicBuyPositionsProfit += PositionGetDouble(POSITION_PROFIT); magicBuyPositionsVolumeTotal += PositionGetDouble(POSITION_VOLUME); } else //-- POSITION_TYPE_SELL { //-- Magic properties ++magicSellPositionsTotal; magicSellPositionsProfit += PositionGetDouble(POSITION_PROFIT); magicSellPositionsVolumeTotal += PositionGetDouble(POSITION_VOLUME); } } //-- Filter positions by symbol if(symbol == ALL_SYMBOLS || selectedSymbol == symbol) { ++symbolPositionsTotal; symbolPositionsVolumeTotal += PositionGetDouble(POSITION_VOLUME); symbolPositionsProfit += PositionGetDouble(POSITION_PROFIT); if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) { ++symbolBuyPositionsTotal; symbolBuyPositionsVolumeTotal += PositionGetDouble(POSITION_VOLUME); symbolBuyPositionsProfit += PositionGetDouble(POSITION_PROFIT); } else //-- POSITION_TYPE_SELL { ++symbolSellPositionsTotal; symbolSellPositionsVolumeTotal += PositionGetDouble(POSITION_VOLUME); symbolSellPositionsProfit += PositionGetDouble(POSITION_PROFIT); } } } } }
Para acceder a las diferentes propiedades de estado de posición que hemos capturado y guardado en las variables globales anteriores, necesitamos crear funciones exportables simples que puedan ser accesibles externamente desde una base de código externa. Para ello, codificaremos las funciones que se indican a continuación.
Posiciones de compra totales
Devuelve un valor entero del número total de todas las posiciones de compra abiertas en la cuenta.
int BuyPositionsTotal() export { GetPositionsData(ALL_SYMBOLS, 0); return(accountBuyPositionsTotal); }
Posiciones de venta totales
Devuelve un valor entero del número total de todas las posiciones de venta abiertas en la cuenta.
int SellPositionsTotal() export { GetPositionsData(ALL_SYMBOLS, 0); return(accountSellPositionsTotal); }
Volumen total de posiciones
Devuelve un valor doble del volumen/lote/cantidad total de todas las posiciones abiertas en la cuenta.
double PositionsTotalVolume() export { GetPositionsData(ALL_SYMBOLS, 0); return(accountPositionsVolumeTotal); }
Volumen total de posiciones de compra
Devuelve un valor doble del volumen/lote/cantidad total de todas las posiciones de compra abiertas en la cuenta.
double BuyPositionsTotalVolume() export { GetPositionsData(ALL_SYMBOLS, 0); return(accountBuyPositionsVolumeTotal); }
Volumen total de posiciones de venta
Devuelve un valor doble del volumen/lote/cantidad total de todas las posiciones de venta abiertas en la cuenta.
double SellPositionsTotalVolume() export { GetPositionsData(ALL_SYMBOLS, 0); return(accountSellPositionsVolumeTotal); }
Posiciones de compra con ganancias
Devuelve un valor doble del beneficio total de todas las posiciones de compra abiertas en la cuenta.
double BuyPositionsProfit() export { GetPositionsData(ALL_SYMBOLS, 0); return(accountBuyPositionsProfit); }
Posiciones de venta con ganancias
Devuelve un valor doble del beneficio total de todas las posiciones de venta abiertas en la cuenta.
double SellPositionsProfit() export { GetPositionsData(ALL_SYMBOLS, 0); return(accountSellPositionsProfit); }
Total de posiciones "mágicas"
Devuelve un valor entero del número total de todas las posiciones abiertas para el número mágico especificado en la cuenta.
int MagicPositionsTotal(ulong magicNumber) export { GetPositionsData(ALL_SYMBOLS, magicNumber); return(magicPositionsTotal); }
Total de posiciones de compra "mágicas"
Devuelve un valor entero del número total de todas las posiciones de compra abiertas para el número mágico especificado en la cuenta.
int MagicBuyPositionsTotal(ulong magicNumber) export { GetPositionsData(ALL_SYMBOLS, magicNumber); return(magicBuyPositionsTotal); }
Posiciones de venta "mágicas" totales
Devuelve un valor entero del número total de todas las posiciones de venta abiertas para el número mágico especificado en la cuenta.
int MagicSellPositionsTotal(ulong magicNumber) export { GetPositionsData(ALL_SYMBOLS, magicNumber); return(magicSellPositionsTotal); }
Volumen total de posiciones "mágicas"
Devuelve un valor doble del volumen/lote/cantidad total de todas las posiciones abiertas para el número mágico especificado en la cuenta.
double MagicPositionsTotalVolume(ulong magicNumber) export { GetPositionsData(ALL_SYMBOLS, magicNumber); return(magicPositionsVolumeTotal); }
Volumen total de posiciones de compra "mágicas"
Devuelve un valor doble del volumen/lote/cantidad total de todas las posiciones de compra abiertas para el número mágico especificado en la cuenta.
double MagicBuyPositionsTotalVolume(ulong magicNumber) export { GetPositionsData(ALL_SYMBOLS, magicNumber); return(magicBuyPositionsVolumeTotal); }
Volumen total de posiciones de venta "mágicas"
Devuelve un valor doble del volumen/lote/cantidad total de todas las posiciones de venta abiertas para el número mágico especificado en la cuenta.
double MagicSellPositionsTotalVolume(ulong magicNumber) export { GetPositionsData(ALL_SYMBOLS, magicNumber); return(magicSellPositionsVolumeTotal); }
Posiciones "mágicas" de ganancias
Devuelve un valor doble de la ganancia total de todas las posiciones abiertas para el número mágico especificado en la cuenta.
double MagicPositionsProfit(ulong magicNumber) export { GetPositionsData(ALL_SYMBOLS, magicNumber); return(magicPositionsProfit); }
Posiciones de compra "mágicas" con ganancias
Devuelve un valor doble de la ganancia total de todas las posiciones de compra abiertas para el número mágico especificado en la cuenta.
double MagicBuyPositionsProfit(ulong magicNumber) export { GetPositionsData(ALL_SYMBOLS, magicNumber); return(magicBuyPositionsProfit); }
Posiciones de venta "mágicas" con beneficios
Devuelve un valor doble de la ganancia total de todas las posiciones de venta abiertas para el número mágico especificado en la cuenta.
double MagicSellPositionsProfit(ulong magicNumber) export { GetPositionsData(ALL_SYMBOLS, magicNumber); return(magicSellPositionsProfit); }
Posiciones totales del símbolo
Devuelve un valor entero del número total de todas las posiciones abiertas para un símbolo específico en la cuenta.
int SymbolPositionsTotal(string symbol, ulong magicNumber) export { GetPositionsData(symbol, magicNumber); return(symbolPositionsTotal); }
Posiciones totales de compra del símbolo
Devuelve un valor entero del número total de todas las posiciones de compra abiertas para un símbolo específico en la cuenta.
int SymbolBuyPositionsTotal(string symbol, ulong magicNumber) export { GetPositionsData(symbol, magicNumber); return(symbolBuyPositionsTotal); }
Posiciones totales de venta del símbolo
Devuelve un valor entero del número total de todas las posiciones de venta abiertas para un símbolo específico en la cuenta.
int SymbolSellPositionsTotal(string symbol, ulong magicNumber) export { GetPositionsData(symbol, magicNumber); return(symbolSellPositionsTotal); }
Volumen total de las posiciones del símbolo
Devuelve un valor doble del volumen/lote/cantidad total de todas las posiciones abiertas para un símbolo especificado en la cuenta.
double SymbolPositionsTotalVolume(string symbol, ulong magicNumber) export { GetPositionsData(symbol, magicNumber); return(symbolPositionsVolumeTotal); }
Volumen total de las posiciones de compra del símbolo
Devuelve un valor doble del volumen/lote/cantidad total de todas las posiciones de compra abiertas para un símbolo específico en la cuenta.
double SymbolBuyPositionsTotalVolume(string symbol, ulong magicNumber) export { GetPositionsData(symbol, magicNumber); return(symbolBuyPositionsVolumeTotal); }
Volumen total de las posiciones de venta del símbolo
Devuelve un valor doble del volumen/lote/cantidad total de todas las posiciones de venta abiertas para un símbolo especificado en la cuenta.
double SymbolSellPositionsTotalVolume(string symbol, ulong magicNumber) export { GetPositionsData(symbol, magicNumber); return(symbolSellPositionsVolumeTotal); }
Beneficio de las posiciones del símbolo
Devuelve un valor doble del beneficio total de todas las posiciones abiertas para un símbolo especificado en la cuenta.
double SymbolPositionsProfit(string symbol, ulong magicNumber) export { GetPositionsData(symbol, magicNumber); return(NormalizeDouble(symbolPositionsProfit, 2)); }
Beneficio total de posiciones de compra del símbolo
Devuelve un valor doble del beneficio total de todas las posiciones de compra abiertas para un símbolo especificado en la cuenta.
double SymbolBuyPositionsProfit(string symbol, ulong magicNumber) export { GetPositionsData(symbol, magicNumber); return(NormalizeDouble(symbolBuyPositionsProfit, 2)); }
Beneficio total de posiciones de venta del símbolo
Devuelve un valor doble de la ganancia total de todas las posiciones de venta abiertas para un símbolo específico en la cuenta.
double SymbolSellPositionsProfit(string symbol, ulong magicNumber) export { GetPositionsData(symbol, magicNumber); return(NormalizeDouble(symbolSellPositionsProfit, 2)); }
Estado de las posiciones de la cuenta
Devuelve una cadena preformateada con el estado de las posiciones de la cuenta, que puede imprimirse en el registro o mostrarse en los comentarios del gráfico. La función acepta un único parámetro booleano llamado formatForComment. Si formatForComment es true, la función formatea los datos para mostrarlos en la ventana del gráfico. Si es false, los datos se formatean para su visualización en la pestaña de registros del Asesor Experto.
string AccountPositionsStatus(bool formatForComment) export { GetPositionsData(ALL_SYMBOLS, 0); //-- Update the position status variables before we display their data string spacer = ""; if(formatForComment) //-- Add some formating space for the chart comment string { spacer = " "; } string accountPositionsStatus = "\r\n" + spacer + "|---------------------------------------------------------------------------\r\n"; accountPositionsStatus += spacer + "| " + (string)AccountInfoInteger(ACCOUNT_LOGIN) + " - ACCOUNT POSTIONS STATUS \r\n"; accountPositionsStatus += spacer + "|---------------------------------------------------------------------------\r\n"; accountPositionsStatus += spacer + "| Total Open: " + (string)PositionsTotal() + "\r\n"; accountPositionsStatus += spacer + "| Total Volume: " + (string)accountPositionsVolumeTotal + "\r\n"; accountPositionsStatus += spacer + "| Total Profit: " + (string)(NormalizeDouble(AccountInfoDouble(ACCOUNT_PROFIT), 2)) + accountCurrency + "\r\n"; accountPositionsStatus += spacer + "|------------------------------------------------------------------\r\n"; accountPositionsStatus += spacer + "| BUY POSITIONS: \r\n"; accountPositionsStatus += spacer + "| Total Open: " + (string)accountBuyPositionsTotal + "\r\n"; accountPositionsStatus += spacer + "| Total Volume: " + (string)accountBuyPositionsVolumeTotal + "\r\n"; accountPositionsStatus += spacer + "| Total Profit: " + (string)(NormalizeDouble(accountBuyPositionsProfit, 2)) + accountCurrency + "\r\n"; accountPositionsStatus += spacer + "|------------------------------------------------------------------\r\n"; accountPositionsStatus += spacer + "| SELL POSITIONS: \r\n"; accountPositionsStatus += spacer + "| Total Open: " + (string)accountSellPositionsTotal + "\r\n"; accountPositionsStatus += spacer + "| Total Volume: " + (string)accountSellPositionsVolumeTotal + "\r\n"; accountPositionsStatus += spacer + "| Total Profit: " + (string)(NormalizeDouble(accountSellPositionsProfit, 2)) + accountCurrency + "\r\n"; accountPositionsStatus += spacer + "|---------------------------------------------------------------------------\r\n"; accountPositionsStatus += spacer + "\r\n"; return(accountPositionsStatus); }
Estado de las posiciones mágicas
Devuelve una cadena preformateada que contiene el estado de las posiciones mágicas de la cuenta, que puede imprimirse en el registro o mostrarse en los comentarios del gráfico. La función acepta dos argumentos o parámetros. Un long magicNumber y un booleano formatForComment. Si formatForComment es true, la función formatea los datos para mostrarlos en la ventana del gráfico. Si es false, los datos se formatean para su visualización en la pestaña de registros del Asesor Experto.
string MagicPositionsStatus(ulong magicNumber, bool formatForComment) export { GetPositionsData(ALL_SYMBOLS, magicNumber); //-- Update the position status variables before we display their data string spacer = ""; if(formatForComment) //-- Add some formating space for the chart comment string { spacer = " "; } string magicPositionsStatus = "\r\n" + spacer + "|---------------------------------------------------------------------------\r\n"; magicPositionsStatus += spacer + "| " + (string)magicNumber + " - MAGIC POSTIONS STATUS \r\n"; magicPositionsStatus += spacer + "|---------------------------------------------------------------------------\r\n"; magicPositionsStatus += spacer + "| Total Open: " + (string)magicPositionsTotal + "\r\n"; magicPositionsStatus += spacer + "| Total Volume: " + (string)magicPositionsVolumeTotal + "\r\n"; magicPositionsStatus += spacer + "| Total Profit: " + (string)(NormalizeDouble(magicPositionsProfit, 2)) + accountCurrency + "\r\n"; magicPositionsStatus += spacer + "|------------------------------------------------------------------\r\n"; magicPositionsStatus += spacer + "| BUY POSITIONS: \r\n"; magicPositionsStatus += spacer + "| Total Open: " + (string)magicBuyPositionsTotal + "\r\n"; magicPositionsStatus += spacer + "| Total Volume: " + (string)magicBuyPositionsVolumeTotal + "\r\n"; magicPositionsStatus += spacer + "| Total Profit: " + (string)(NormalizeDouble(magicBuyPositionsProfit, 2)) + accountCurrency + "\r\n"; magicPositionsStatus += spacer + "|------------------------------------------------------------------\r\n"; magicPositionsStatus += spacer + "| SELL POSITIONS: \r\n"; magicPositionsStatus += spacer + "| Total Open: " + (string)magicSellPositionsTotal + "\r\n"; magicPositionsStatus += spacer + "| Total Volume: " + (string)magicSellPositionsVolumeTotal + "\r\n"; magicPositionsStatus += spacer + "| Total Profit: " + (string)(NormalizeDouble(magicSellPositionsProfit, 2)) + accountCurrency + "\r\n"; magicPositionsStatus += spacer + "|---------------------------------------------------------------------------\r\n"; magicPositionsStatus += spacer + "\r\n"; return(magicPositionsStatus); }
Estado de las posiciones del símbolo
Devuelve una cadena preformateada con el estado de las posiciones del símbolo de la cuenta, que puede imprimirse en el registro o mostrarse en los comentarios del gráfico. La función acepta tres argumentos o parámetros. Un string para el símbolo, un long sin signo para el número mágico, y un bool para formatForComment. Si el valor formatForComment booleano es true, la función formatea los datos para mostrarlos en la ventana del gráfico. Si es false, los datos se formatean para su visualización en la pestaña de registros del Asesor Experto.
string SymbolPositionsStatus(string symbol, ulong magicNumber, bool formatForComment) export { GetPositionsData(symbol, magicNumber); //-- Update the position status variables before we display their data string spacer = ""; if(formatForComment) //-- Add some formating space for the chart comment string { spacer = " "; } string symbolPositionsStatus = "\r\n" + spacer + "|---------------------------------------------------------------------------\r\n"; symbolPositionsStatus += spacer + "| " + symbol + " - SYMBOL POSTIONS STATUS \r\n"; symbolPositionsStatus += spacer + "|---------------------------------------------------------------------------\r\n"; symbolPositionsStatus += spacer + "| Total Open: " + (string)symbolPositionsTotal + "\r\n"; symbolPositionsStatus += spacer + "| Total Volume: " + (string)symbolPositionsVolumeTotal + "\r\n"; symbolPositionsStatus += spacer + "| Total Profit: " + (string)(NormalizeDouble(symbolPositionsProfit, 2)) + accountCurrency + "\r\n"; symbolPositionsStatus += spacer + "|------------------------------------------------------------------\r\n"; symbolPositionsStatus += spacer + "| BUY POSITIONS: \r\n"; symbolPositionsStatus += spacer + "| Total Open: " + (string)symbolBuyPositionsTotal + "\r\n"; symbolPositionsStatus += spacer + "| Total Volume: " + (string)symbolBuyPositionsVolumeTotal + "\r\n"; symbolPositionsStatus += spacer + "| Total Profit: " + (string)(NormalizeDouble(symbolBuyPositionsProfit, 2)) + accountCurrency + "\r\n"; symbolPositionsStatus += spacer + "|------------------------------------------------------------------\r\n"; symbolPositionsStatus += spacer + "| SELL POSITIONS: \r\n"; symbolPositionsStatus += spacer + "| Total Open: " + (string)symbolSellPositionsTotal + "\r\n"; symbolPositionsStatus += spacer + "| Total Volume: " + (string)symbolSellPositionsVolumeTotal + "\r\n"; symbolPositionsStatus += spacer + "| Total Profit: " + (string)(NormalizeDouble(symbolSellPositionsProfit, 2)) + accountCurrency + "\r\n"; symbolPositionsStatus += spacer + "|---------------------------------------------------------------------------\r\n"; symbolPositionsStatus += spacer + "\r\n"; return(symbolPositionsStatus); }
Cómo importar e implementar nuestra biblioteca EX5 de gestión de posiciones
Hemos desarrollado una completa biblioteca de gestión de posiciones EX5, que contiene todas las funciones esenciales para las operaciones de posición, la extracción de estados y los módulos de visualización. Ahora es el momento de documentar y explicar cómo importar y utilizar eficazmente esta biblioteca en cualquier proyecto MQL5.
Para agilizar el proceso de implementación, comencemos por esbozar todas las funciones o módulos dentro de la biblioteca de gestión de posiciones, junto con algunos casos de uso de ejemplos de código del mundo real. Esto proporcionará a los usuarios de la biblioteca una rápida visión general de los componentes incluidos en el archivo binario PositionsManager.ex5.
Documentación de la biblioteca EX5 para la gestión de posiciones
Descripción del prototipo de la función | Descripción | Ejemplo de uso |
---|---|---|
bool ErrorAdvisor( string callingFunc, string symbol, int tradeServerErrorCode ); | Gestiona el servidor de operaciones y los errores de ejecución al gestionar posiciones y órdenes. Devuelve true si el error es recuperable y se puede volver a enviar la solicitud de operación, false si el error es crítico y se debe detener el envío de la solicitud. | ResetLastError(); //-- Reset and clear the last error //-------------------------------------------------------------- //-- Insert code to send the order request to the trade server //-------------------------------------------------------------- string symbol = _Symbol; //Symbol being traded int retcode = tradeResult.retcode;//Trade Request Structure (MqlTradeRequest) if(!ErrorAdvisor(__FUNCTION__, symbol, retcode) { //Critical error found //Order can not be executed. Exit function or log this error } |
bool TradingIsAllowed(); | Verifica si el usuario, el servidor de operaciones y el corredor han dado permiso al asesor experto para ejecutar operaciones. | if(!TradingIsAllowed()) { //--- algo trading is disabled, exit function return(false); } |
bool OpenBuyPosition( ulong magicNumber, string symbol, double lotSize, int sl, int tp, string positionComment ); | Abre una nueva posición de compra que coincide con los parámetros especificados. | ulong magicNo = 123; string symbol = _Symbol; double lotSize = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN); int sl = 500; //-- pips int tp = 1000; //-- pips string comment = "Buy position"; OpenBuyPosition(magicNo, symbol, lotSize, sl, tp, comment); |
bool OpenSellPosition( ulong magicNumber, string symbol, double lotSize, int sl, int tp, string positionComment ); | Abre una nueva posición de venta que coincide con los parámetros especificados. | ulong magicNo = 123; string symbol = _Symbol; double lotSize = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN); int sl = 500; //-- pips int tp = 1000; //-- pips string comment = "Sell position"; OpenSellPosition(magicNo, symbol, lotSize, sl, tp, comment); |
bool SetSlTpByTicket( ulong positionTicket, int sl, int tp ); | Establece el stop loss para una posición que coincida con la entrada especificada. | int sl = 500, int tp = 1000; //-- pips int totalOpenPostions = PositionsTotal(); for(int x = 0; x < totalOpenPostions; x++) { ulong positionTicket = PositionGetTicket(x); if(positionTicket > 0) { SetSlTpByTicket(positionTicket, sl, tp); } } |
bool ClosePositionByTicket( ulong positionTicket ); | Cierra una posición que coincide con el ticket especificado. | //-- Example to close all open positions for(int x = 0; x < totalOpenPostions; x++) { ulong positionTicket = PositionGetTicket(x); if(positionTicket > 0) { ClosePositionByTicket(positionTicket); } } |
bool SetTrailingStopLoss( ulong positionTicket, int trailingStopLoss ); | Establece un trailing stop loss para una posición que coincida con la entrada especificada. Esta función debe ejecutarse en cada tick en la función OnTick() para actualizar el trailing stop loss en tiempo real. | //-- Execute this on every tick //-- Example to set 500 pips trailing stop loss for all positions int trailingStopLoss = 500; //-- 500 pips trailing stop loss for(int x = 0; x < totalOpenPostions; x++) { ulong positionTicket = PositionGetTicket(x); if(positionTicket > 0) { SetTrailingStopLoss(positionTicket, trailingStopLoss); } } |
bool CloseAllPositions( string symbol, ulong magicNumber ); | Función versátil que cierra todas las posiciones abiertas que coincidan con los parámetros especificados. | //Close all positions CloseAllPositions("", 0); //Only close all positions matching a magic number value of 1 CloseAllPositions("", 1); //Only close all current symbol positions CloseAllPositions(_Symbol, 0); |
bool CloseAllPositions(); | Cierra todas las posiciones abiertas. | //Close all open positions in the account
CloseAllPositions(); |
bool CloseAllBuyPositions( string symbol, ulong magicNumber ); | Cierra todas las posiciones de compra que coincidan con los parámetros especificados. | //Close all buy positions for the current symbol CloseAllBuyPositions(_Symbol, 0); //Close all buy positions matching magic number 1 for all symbols CloseAllBuyPositions("", 1); //Close all buy positions in the account CloseAllBuyPositions("", 0); |
bool CloseAllSellPositions( string symbol, ulong magicNumber ); | Cierra todas las posiciones de venta que coincidan con los parámetros especificados. | //Close all sell positions for the current symbol CloseAllSellPositions(_Symbol, 0); //Close all sell positions matching magic number 1 for all symbols CloseAllSellPositions("", 1); //Close all sell positions in the account CloseAllSellPositions("", 0); |
bool CloseAllMagicPositions( ulong magicNumber ); | Cierra todas las posiciones que coincidan con el número mágico especificado. | //Close all positions matching magic number 1 CloseAllMagicPositions(1); //Close all positions in the account CloseAllMagicPositions(0); |
bool CloseAllProfitablePositions( string symbol, ulong magicNumber ); | Cierra todas las posiciones rentables que coincidan con los parámetros especificados. | //Close all profitable positions for the current symbol CloseAllProfitablePositions(_Symbol, 0); //Close all profitable positions matching magic number 1 for all symbols CloseAllProfitablePositions("", 1); //Close all profitable positions in the account CloseAllProfitablePositions("", 0); |
bool CloseAllProfitableBuyPositions( string symbol, ulong magicNumber ); | Cierra todas las posiciones de compra rentables que coincidan con los parámetros especificados. | //Close all profitable buy positions for the current symbol CloseAllProfitableBuyPositions(_Symbol, 0); //Close all profitable buy positions matching magic number 1 for all symbols CloseAllProfitableBuyPositions("", 1); //Close all profitable buy positions in the account CloseAllProfitableBuyPositions("", 0); |
bool CloseAllProfitableSellPositions( string symbol, ulong magicNumber ); | Cierra todas las posiciones de venta rentables que coincidan con los parámetros especificados. | //Close all profitable sell positions for the current symbol CloseAllProfitableSellPositions(_Symbol, 0); //Close all profitable sell positions matching magic number 1 for all symbols CloseAllProfitableSellPositions("", 1); //Close all profitable sell positions in the account CloseAllProfitableSellPositions("", 0); |
bool CloseAllLossPositions( string symbol, ulong magicNumber ); | Cierra todas las posiciones de pérdidas que coincidan con los parámetros especificados. | //Close all loss positions for the current symbol CloseAllLossPositions(_Symbol, 0); //Close all loss positions matching magic number 1 for all symbols CloseAllLossPositions("", 1); //Close all loss positions in the account CloseAllLossPositions("", 0); |
bool CloseAllLossBuyPositions( string symbol, ulong magicNumber ); | Cierra todas las posiciones de compra con pérdidas que coincidan con los parámetros especificados. | //Close all loss buy positions for the current symbol CloseAllLossBuyPositions(_Symbol, 0); //Close all loss buy positions matching magic number 1 for all symbols CloseAllLossBuyPositions("", 1); //Close all loss buy positions in the account CloseAllLossBuyPositions("", 0); |
bool CloseAllLossSellPositions( string symbol, ulong magicNumber ); | Cierra todas las posiciones de venta con pérdidas que coincidan con los parámetros especificados. | //Close all loss sell positions for the current symbol CloseAllLossSellPositions(_Symbol, 0); //Close all loss sell positions matching magic number 1 for all symbols CloseAllLossSellPositions("", 1); //Close all loss sell positions in the account CloseAllLossSellPositions("", 0); |
int BuyPositionsTotal(); | Devuelve el número de posiciones de compra abiertas. | //Get the total number of open buy positions in the account
BuyPositionsTotal(); |
int SellPositionsTotal();
| Devuelve el número de posiciones de venta abiertas. | //Get the total number of open sell positions in the account
SellPositionsTotal(); |
double PositionsTotalVolume();
| Devuelve el volumen total de todas las posiciones abiertas. | //Get the total volume of all open positions in the account
PositionsTotalVolume(); |
double BuyPositionsTotalVolume(); | Devuelve el volumen total de todas las posiciones abiertas de compra. | //Get the total volume of all open buy positions in the account
BuyPositionsTotalVolume(); |
double SellPositionsTotalVolume(); | Devuelve el volumen total de todas las posiciones abiertas de venta. | //Get the total volume of all open sell positions in the account
SellPositionsTotalVolume(); |
double BuyPositionsProfit(); | Devuelve el beneficio total de todas las posiciones abiertas de compra. | //Get the total profit of all open buy positions in the account
BuyPositionsProfit(); |
double SellPositionsProfit(); | Devuelve el beneficio total de todas las posiciones abiertas de venta. | //Get the total profit of all open sell positions in the account
SellPositionsProfit(); |
int MagicPositionsTotal( ulong magicNumber ); | Devuelve el número de posiciones abiertas que coinciden con el número mágico especificado. | //Get the total number of open positions matching magic number 1 MagicPositionsTotal(1); |
int MagicBuyPositionsTotal( ulong magicNumber ); | Devuelve el número de posiciones de compra abiertas que coinciden con el número mágico especificado. | //Get the total number of open buy positions matching magic number 1 MagicBuyPositionsTotal(1); |
int MagicSellPositionsTotal( ulong magicNumber ); | Devuelve el número de posiciones de venta abiertas que coinciden con el número mágico especificado. | //Get the total number of open sell positions matching magic number 1 MagicSellPositionsTotal(1); |
double MagicPositionsTotalVolume( ulong magicNumber ); | Devuelve el volumen total de todas las posiciones abiertas que coinciden con el número mágico especificado. | //Get the total volume of open positions matching magic number 1 MagicPositionsTotalVolume(1); |
double MagicBuyPositionsTotalVolume( ulong magicNumber ); | Devuelve el volumen total de todas las posiciones de compra abiertas que coinciden con el número mágico especificado. | //Get the total volume of open buy positions matching magic number 1 MagicBuyPositionsTotalVolume(1); |
double MagicSellPositionsTotalVolume( ulong magicNumber ); | Devuelve el volumen total de todas las posiciones de venta abiertas que coinciden con el número mágico especificado. | //Get the total volume of open sell positions matching magic number 1 MagicSellPositionsTotalVolume(1); |
double MagicPositionsProfit( ulong magicNumber ); | Devuelve la ganancia total de todas las posiciones abiertas que coinciden con el número mágico especificado. | //Get the total profit of open positions matching magic number 1 MagicPositionsProfit(1); |
double MagicBuyPositionsProfit( ulong magicNumber ); | Devuelve la ganancia total de todas las posiciones de compra abiertas que coinciden con el número mágico especificado. | //Get the total profit of open buy positions matching magic number 1 MagicBuyPositionsProfit(1); |
double MagicSellPositionsProfit( ulong magicNumber ); | Devuelve la ganancia total de todas las posiciones de venta abiertas que coinciden con el número mágico especificado. | //Get total profit of sell positions matching magic number 1 MagicSellPositionsProfit(1); |
int SymbolPositionsTotal( string symbol, ulong magicNumber ); | Devuelve el número total de todas las posiciones abiertas que coinciden con el símbolo y el número mágico especificados. | //Get total number of positions matching symbol and magic number 1 MagicPositionsTotal(_Symbol, 1); |
int SymbolBuyPositionsTotal( string symbol, ulong magicNumber ); | Devuelve el número total de todas las posiciones de compra abiertas que coinciden con el símbolo especificado y el número mágico. | //Get total number of buy positions matching symbol and magic number 1 SymbolBuyPositionsTotal(_Symbol, 1); |
int SymbolSellPositionsTotal( string symbol, ulong magicNumber ); | Devuelve el número total de todas las posiciones de venta abiertas que coinciden con el símbolo y el número mágico especificados. | //Get total number of sell positions matching symbol and magic number 1 SymbolSellPositionsTotal(_Symbol, 1); |
double SymbolPositionsTotalVolume( string symbol, ulong magicNumber ); | Devuelve el volumen total de todas las posiciones abiertas que coinciden con el símbolo y el número mágico especificados. | //Get the volume of positions matching symbol and magic number 1 SymbolPositionsTotalVolume(_Symbol, 1); |
double SymbolBuyPositionsTotalVolume( string symbol, ulong magicNumber ); | Devuelve el volumen total de todas las posiciones de compra abiertas que coinciden con el símbolo y el número mágico especificados. | //Get the volume of buy positions matching symbol and magic number 1 SymbolBuyPositionsTotalVolume(_Symbol, 1); |
double SymbolSellPositionsTotalVolume( string symbol, ulong magicNumber ); | Devuelve el volumen total de todas las posiciones de venta abiertas que coinciden con el símbolo y el número mágico especificados. | //Get the volume of sell positions matching symbol and magic number 1 SymbolSellPositionsTotalVolume(_Symbol, 1); |
double SymbolPositionsProfit( string symbol, ulong magicNumber ); | Devuelve la ganancia total de todas las posiciones abiertas que coinciden con el símbolo especificado y el número mágico. | //Get the profit of all positions matching symbol and magic number 1 SymbolPositionsProfit(_Symbol, 1); |
double SymbolBuyPositionsProfit( string symbol, ulong magicNumber ); | Devuelve la ganancia total de todas las posiciones de compra abiertas que coinciden con el símbolo especificado y el número mágico. | //Get the profit of all buy positions matching symbol and magic number 1 SymbolBuyPositionsProfit(_Symbol, 1); |
double SymbolSellPositionsProfit( string symbol, ulong magicNumber ); | Devuelve la ganancia total de todas las posiciones de venta abiertas que coinciden con el símbolo y el número mágico especificados. | //Get the profit of all sell positions matching symbol and magic number 1 SymbolSellPositionsProfit(_Symbol, 1); |
string AccountPositionsStatus( bool formatForComment ); | Imprime un estado con formato de cadena de todas las posiciones abiertas en el gráfico de símbolos o en la pestaña Expertos en MetaTrader 5. | //Print the status of all open positions formatted for the chart comments AccountPositionsStatus(true); //Print the status of all open positions formatted for the Experts tab AccountPositionsStatus(false); |
string MagicPositionsStatus( ulong magicNumber, bool formatForComment ); | Imprime un estado con formato de cadena de todas las posiciones 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 positions matching //the magic number 1 formatted for the chart comments MagicPositionsStatus(1, true); //Print the status of all open positions matching //the magic number 1 formatted for the Experts tab MagicPositionsStatus(1, false); |
string SymbolPositionsStatus( string symbol, ulong magicNumber, bool formatForComment ); | Imprime un estado con formato de cadena de todas las posiciones 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 positions matching //the symbol and magic number 1 formatted for the chart comments SymbolPositionsStatus(_Symbol, 1, true); //Print the status of all open positions matching //the symbol and magic number 1 formatted for the Experts tab SymbolPositionsStatus(_Symbol, 1, false); |
Integrar la biblioteca en sus proyectos MQL5 es sencillo. Siga estos dos pasos para importarPositionsManager.ex5 en su código MQL5:
- Paso 1: Copie el archivo ejecutable de la biblioteca (PositionsManager.ex5)
Coloque el archivo PositionsManager.ex5 en la carpeta MQL5/Libraries/Toolkit. Asegúrese de haber descargado y copiado este archivo en la ubicación especificada si aún no está presente. Una copia de PositionsManager.ex5 se adjunta al final de este artículo para su conveniencia.
- Paso 2: Importar las descripciones de los prototipos de funciones
Añade las directivas de importación de la librería Positions Manager, y sus descripciones de prototipos de funciones en la sección de cabecera de tu fichero de código fuente. Utilice el siguiente segmento de código para importar eficientemente todas las funciones o módulos de la biblioteca PositionsManager.ex5. También he creado una plantilla en blanco de un Asesor Experto (PositionsManager_Imports_Template.mq5) que incluye el segmento de código a continuación. Puede comentar o eliminar las descripciones de funciones que no necesite para su proyecto. El archivo PositionsManager_Imports_Template.mq5 también se adjunta al final de este artículo.
//+-------------------------------------------------------------------------------------+ //| PositionsManager.ex5 imports template | //+-------------------------------------------------------------------------------------+ #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(); //-- Position Execution and Modification Functions bool OpenBuyPosition(ulong magicNumber, string symbol, double lotSize, int sl, int tp, string positionComment); bool OpenSellPosition(ulong magicNumber, string symbol, double lotSize, int sl, int tp, string positionComment); bool SetSlTpByTicket(ulong positionTicket, int sl, int tp); bool ClosePositionByTicket(ulong positionTicket); bool SetTrailingStopLoss(ulong positionTicket, int trailingStopLoss); bool CloseAllPositions(string symbol, ulong magicNumber); bool CloseAllPositions(); bool CloseAllBuyPositions(string symbol, ulong magicNumber); bool CloseAllSellPositions(string symbol, ulong magicNumber); bool CloseAllMagicPositions(ulong magicNumber); bool CloseAllProfitablePositions(string symbol, ulong magicNumber); bool CloseAllProfitableBuyPositions(string symbol, ulong magicNumber); bool CloseAllProfitableSellPositions(string symbol, ulong magicNumber); bool CloseAllLossPositions(string symbol, ulong magicNumber); bool CloseAllLossBuyPositions(string symbol, ulong magicNumber); bool CloseAllLossSellPositions(string symbol, ulong magicNumber); //-- Position Status Monitoring Functions int BuyPositionsTotal(); int SellPositionsTotal(); double PositionsTotalVolume(); double BuyPositionsTotalVolume(); double SellPositionsTotalVolume(); double BuyPositionsProfit(); double SellPositionsProfit(); //-- Positions Filtered By Magic Number Status Monitoring Functions int MagicPositionsTotal(ulong magicNumber); int MagicBuyPositionsTotal(ulong magicNumber); int MagicSellPositionsTotal(ulong magicNumber); double MagicPositionsTotalVolume(ulong magicNumber); double MagicBuyPositionsTotalVolume(ulong magicNumber); double MagicSellPositionsTotalVolume(ulong magicNumber); double MagicPositionsProfit(ulong magicNumber); double MagicBuyPositionsProfit(ulong magicNumber); double MagicSellPositionsProfit(ulong magicNumber); //-- Positions Filtered By Symbol and/or Magic Number Status Monitoring Functions int SymbolPositionsTotal(string symbol, ulong magicNumber); int SymbolBuyPositionsTotal(string symbol, ulong magicNumber); int SymbolSellPositionsTotal(string symbol, ulong magicNumber); double SymbolPositionsTotalVolume(string symbol, ulong magicNumber); double SymbolBuyPositionsTotalVolume(string symbol, ulong magicNumber); double SymbolSellPositionsTotalVolume(string symbol, ulong magicNumber); double SymbolPositionsProfit(string symbol, ulong magicNumber); double SymbolBuyPositionsProfit(string symbol, ulong magicNumber); double SymbolSellPositionsProfit(string symbol, ulong magicNumber); //-- Log and Data Display Functions string AccountPositionsStatus(bool formatForComment); string MagicPositionsStatus(ulong magicNumber, bool formatForComment); string SymbolPositionsStatus(string symbol, ulong magicNumber, bool formatForComment); #import //--- Closing import directive
Con la biblioteca importada, ahora puede abrir, cerrar, modificar o recuperar datos de estado de posición sin esfuerzo mediante sencillas llamadas a funciones. Para ilustrar esto, vamos a crear tres Asesores Expertos básicos en las siguientes secciones.
Desarrollo de un asesor experto dual VIDyA con trailing stop potenciado por la biblioteca EX5 'Positions Manager'
En esta sección, desarrollaremos un asesor experto con trailing stop basado en el indicador técnico de Promedio Dinámico de Índice Variable (Variable Index Dynamic Average, VIDyA) como un ejemplo práctico de implementación de la librería Positions Manager en una aplicación de trading en el mundo real.
La estrategia VIDyA con trailing stop utilizará un par de Indicadores Técnicos de Media Dinámica de Índice Variable para generar señales de compra y venta. Dado que el indicador VIDyA se muestra como una línea en el gráfico, utilizaremos una estrategia de cruce de líneas para señalar la entrada de una nueva operación. Para una estrategia de cruce, los pares de indicadores deben tener configuraciones diferentes. El primer indicador VIDyA, con valores de entrada más bajos, se denominará «fast VIDyA», ya que reaccionará y generará señales más rápidamente. El segundo, con valores de entrada más altos, se llamará «slow VIDyA», ya que responde a las variaciones de precios más lentamente. Para una entrada de compra, la línea «fast VIDyA» debe estar por encima de la línea «slow VIDyA», y para una entrada de venta, la línea «fast VIDyA» debe estar por debajo de la línea «slow VIDyA».
Cree un nuevo Asesor Experto utilizando MetaEditor IDE y cree un nuevo archivo en MQL Wizard y llámelo «DualVidyaTrader.mq5». Dado que nuestro Asesor Experto utilizará la biblioteca PositionsManager.ex5, el primer paso es importar e insertar las descripciones de los prototipos de las funciones de la biblioteca como se ha descrito anteriormente. Coloque el segmento de código de importación de la biblioteca debajo de las directivas #property. Dado que la biblioteca contiene muchas funciones, no las importaremos ni utilizaremos todas; sólo importaremos los prototipos de función que se indican en el código siguiente.
//--- Import the PositionsManager EX5 Library #import "Toolkit/PositionsManager.ex5" //-- Open the ex5 import directive //-- Prototype function descriptions of the EX5 PositionsManager library bool OpenBuyPosition(ulong magicNumber, string symbol, double lotSize, int sl, int tp, string positionComment); bool OpenSellPosition(ulong magicNumber, string symbol, double lotSize, int sl, int tp, string positionComment); bool SetTrailingStopLoss(ulong positionTicket, int trailingStopLoss); int MagicPositionsTotal(ulong magicNumber); int MagicBuyPositionsTotal(ulong magicNumber); int MagicSellPositionsTotal(ulong magicNumber); bool CloseAllProfitableBuyPositions(string symbol, ulong magicNumber); bool CloseAllProfitableSellPositions(string symbol, ulong magicNumber); string MagicPositionsStatus(ulong magicNumber, bool formatForComment); #import //-- Close the ex5 import directive
Después del segmento de código de importación de la biblioteca PositionsManager.ex5, inserte las variables globales de entrada de usuario como se muestra.
input group "" input ulong magicNo = 1234; input ENUM_TIMEFRAMES timeframe = PERIOD_H1; input ENUM_APPLIED_PRICE appliedPrice = PRICE_CLOSE; // Applied VIDyA Price //-- Fast Vidya user inputs input group "-- FAST VIDyA INPUTS" input int fast_cmoPeriod = 5; // Fast Chande Momentum Period input int fast_maPeriod = 10; // Fast MA Smoothing Period input int fast_emaShift = 0; // Fast Horizontal Shift //-- Slow Vidya user inputs input group "-- SLOW VIDyA INPUTS" input int slow_cmoPeriod = 9; // Slow Chande Momentum Period input int slow_maPeriod = 12; // Slow MA Smoothing Period input int slow_emaShift = 0; // Slow Horizontal Shift input group "-- PROFIT MANAGEMENT" input bool liquidateProfitOnCrossover = false; // Liquidate Profit On VIDyA Signal input bool enableTrailingStops = true; // Use Trailing Stop Losses
Creemos más variables globales para almacenar los valores de stop loss, take profit, trailing stop loss y lote o volumen.
//-- Get and save the SL, trailingSL and TP values from the spread int spreadMultiForSl = 1000; int spreadMultiForTrailingSl = 300; int spreadMultiForTp = 1000; int sl = int(SymbolInfoInteger(_Symbol, SYMBOL_SPREAD)) * spreadMultiForSl; int trailingSl = int(SymbolInfoInteger(_Symbol, SYMBOL_SPREAD)) * spreadMultiForTrailingSl; int tp = int(SymbolInfoInteger(_Symbol, SYMBOL_SPREAD)) * spreadMultiForTp; //-- Set the lot or volume to the symbol allowed min value double lotSize = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
Crear las variables del indicador técnico VIDyA en el ámbito global para asegurar que también son accesibles desde cualquier parte de nuestro código de asesor experto.
//-- Vidya indicator variables double fastVidya[], slowVidya[]; int fastVidyaHandle, slowVidyaHandle; bool buyOk, sellOk, vidyaBuy, vidyaSell; string vidyaTrend;
Después de la sección de variables globales, cree la función de inicialización del Asesor Experto que se llamará desde la función estándar de manejo de eventos MQL5 OnInit(), que se ejecuta por primera vez durante la puesta en marcha o inicialización del Asesor Experto. Nombre esta función GetInit(). Realizaremos todas nuestras inicializaciones de datos en esta función, incluyendo las inicializaciones del indicador VIDyA y manejando el procesamiento de arranque.
int GetInit() { int returnVal = 1; //-- Helps to regulate and prevent openning multiple trades on a single signal trigger buyOk = true; sellOk = true; //-- Create the fast iVIDyA indicator handle fastVidyaHandle = iVIDyA(_Symbol, timeframe, fast_cmoPeriod, fast_maPeriod, fast_emaShift, appliedPrice); if(fastVidyaHandle < 0) { Print("Error creating fastVidyaHandle = ", INVALID_HANDLE); Print("Handle creation: Runtime error = ", GetLastError()); //-- Close the EA if the handle is not properly loaded return(-1); } ArraySetAsSeries(fastVidya, true); //-- set the vidya array to series access //-- Create the slow iVIDyA indicator handle slowVidyaHandle = iVIDyA(_Symbol, timeframe, slow_cmoPeriod, slow_maPeriod, slow_emaShift, appliedPrice); if(slowVidyaHandle < 0) { Print("Error creating vidyaHandle = ", INVALID_HANDLE); Print("Handle creation: Runtime error = ", GetLastError()); //-- Close the EA if the handle is not properly loaded return(-1); } ArraySetAsSeries(slowVidya, true); //-- set the vidya array to series access return(returnVal); }
Después de la función de inicialización, crea la función de desinicialización y llámala GetDeinit(). Esta función será llamada dentro de la función estándar de manejo de eventos MQL5 OnDeinit() para realizar una limpieza en todo el sistema de todos los recursos utilizados por nuestro Asesor Experto. Esto incluye la liberación del indicador VIDyA, la liberación de todos los recursos vinculados a las matrices de control del indicador y la eliminación de cualquier comentario u objeto del gráfico.
void GetDeinit() //-- De-initialize the robot on shutdown and clean everything up { //-- Delete the vidya handles and de-allocate the memory spaces occupied IndicatorRelease(fastVidyaHandle); ArrayFree(fastVidya); IndicatorRelease(slowVidyaHandle); ArrayFree(slowVidya); //-- Delete and clear all chart displayed messages Comment(""); }
A continuación, necesitamos crear una función personalizada para detectar y recuperar las señales de operación generadas por nuestro par de indicadores VIDyA. Esta función se llamará GetVidya(). Se ejecutará y actualizará cada vez que haya un nuevo tick entrante para garantizar que la generación de señales sea precisa y en tiempo real.
void GetVidya() { //-- Get vidya line directions if(CopyBuffer(fastVidyaHandle, 0, 0, 100, fastVidya) <= 0 || CopyBuffer(slowVidyaHandle, 0, 0, 100, slowVidya) <= 0) { return; } //-- Reset vidya status variables vidyaBuy = false; vidyaSell = false; vidyaTrend = "FLAT"; //-- Scan for vidya crossover buy signal if(fastVidya[1] > slowVidya[1]) { //-- Save the vidya signal vidyaTrend = "BUY/LONG"; vidyaBuy = true; vidyaSell = false; } //-- Scan for vidya crossover sell signal if(fastVidya[1] < slowVidya[1]) { //-- Save the vidya signal vidyaTrend = "SELL/SHORT"; vidyaSell = true; vidyaBuy = false; } }
Ahora que hemos creado la función para obtener y actualizar la señal VIDyA, vamos a crear otra función personalizada que se ejecutará en cada nuevo tick para escanear y abrir nuevas posiciones basadas en la señal VIDyA actual. Esta función se llamará ScanForTradeOpportunities(). En esta función llamaremos y ejecutaremos las funciones prototipo de apertura y estado de posición importadas de nuestra librería PositionsManager.ex5.
void ScanForTradeOpportunities() { //-- Get the VIDyA signal GetVidya(); if(MagicPositionsTotal(magicNo) == 0) { buyOk = true; sellOk = true; } //-- Check for a buy entry when a VIDyA buy signal is found if(buyOk && vidyaBuy) //-- Open a new buy position { if(OpenBuyPosition(magicNo, _Symbol, lotSize, sl, tp, "Vidya_BUY: " + IntegerToString(MagicBuyPositionsTotal(magicNo) + 1))) { buyOk = false; sellOk = true; } //-- Market has a strong buy trend, close all profitable sell positions if(liquidateProfitOnCrossover) { CloseAllProfitableSellPositions(_Symbol, magicNo); } } //-- Check for a sell entry when a VIDyA sell signal is found if(sellOk && vidyaSell) //-- Open a new sell position { if(OpenSellPosition(magicNo, _Symbol, lotSize, sl, tp, "Vidya_SELL: " + IntegerToString(MagicSellPositionsTotal(magicNo) + 1))) { sellOk = false; buyOk = true; } //-- Market has a strong sell trend, close all profitable buy positions if(liquidateProfitOnCrossover) { CloseAllProfitableBuyPositions(_Symbol, magicNo); } } }
También tenemos que comprobar y establecer trailing stops en todas las posiciones abiertas. Esto será sencillo ya que nuestra biblioteca PositionsManager.ex5 contiene una función prototipo de trailing stop loss para ayudarnos a conseguirlo. Creemos una nueva función llamada CheckAndSetTrailingSl() para escanear todas las posiciones abiertas y recuperar sus tickets para utilizarlos como parámetros en la función prototipo importada SetTrailingStopLoss().
void CheckAndSetTrailingSl() { int totalOpenPostions = PositionsTotal(); for(int x = 0; x < totalOpenPostions; x++) { //--- Get position properties ulong positionTicket = PositionGetTicket(x); //-- Get ticket to select the position string selectedSymbol = PositionGetString(POSITION_SYMBOL); ulong positionMagicNo = PositionGetInteger(POSITION_MAGIC); int positionType = int(PositionGetInteger(POSITION_TYPE)); //-- modify only the positions we have opened with this EA (magic number) if(selectedSymbol != _Symbol && positionMagicNo != magicNo) { continue; } //-- Only set the trailing stop loss when the market trend is in the opposing direction of the position type if((positionType == POSITION_TYPE_BUY && vidyaBuy) || (positionType == POSITION_TYPE_SELL && vidyaSell)) { continue; } //--- set the trailing stop loss SetTrailingStopLoss(positionTicket, trailingSl); //-- call the imported function from our ex5 library } }
Ahora que hemos creado todos los módulos importantes para nuestro Asesor Experto, vamos a reunirlos en la función de manejo de eventos MQL5 OnTick() que se ejecuta en cada nuevo tick. Colóquelos en el orden especificado a continuación para garantizar que ejecutan sistemáticamente nuestro sistema de negociación en la secuencia correcta.
void OnTick() { //-- Scan and open new positions based on the vidya signal ScanForTradeOpportunities(); //-- Check and set the trailing stop if(enableTrailingStops) { CheckAndSetTrailingSl(); } //-- Display the vidya trend and positions status for the EA's magicNo Comment( "\nvidyaTrend: ", vidyaTrend, MagicPositionsStatus(magicNo, true) ); }
Finalmente, no olvides colocar las funciones de inicialización y desinicialización en sus respectivas funciones estándar de manejo de eventos MQL5.
//+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- if(GetInit() <= 0) { return(INIT_FAILED); } return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- GetDeinit(); }
Puede acceder y descargar el archivo de código fuente de DualVidyaTrader.mq5 al final de este artículo. He adjuntado el archivo de código fuente completo para asegurar que usted tiene todos los componentes necesarios para implementar y personalizar la estrategia de negociación según sea necesario.
Cuando compile y cargue nuestro nuevo DualVidyaTrader en MetaTrader 5, observará que en la pestaña «Dependencias» aparecen listados todos los prototipos de funciones de la biblioteca importados de PositionsManager.ex5, junto con la ruta completa del archivo donde se guarda la biblioteca EX5. Esto asegura que todas las dependencias requeridas están correctamente referenciadas antes de que el Asesor Experto se cargue en el gráfico. Si se encuentra algún error de referencia a bibliotecas, como los comentados anteriormente en el artículo, se registrará en las pestañas Expertos o Diario de la ventana Caja de herramientas de MetaTrader 5.
Panel de operaciones de Positions Manager desarrollado con la biblioteca EX5 Positions Manager
En este segundo ejemplo, crearemos un panel de operaciones básico de interfaz gráfica de usuario (GUI) de Asesor Experto que también funciona con nuestra biblioteca PositionsManager.ex5.
Cree un nuevo Asesor Experto utilizando el MetaEditor IDE y cree un nuevo archivo MQL Wizard y llámelo PositionsManagerPanel.mq5. Bajo el segmento de código #property, importa la librería PositionsManager.ex5. En la sección de descripciones de funciones de importación, importe únicamente los siguientes prototipos de funciones.
//+------------------------------------------------------------------+ //| EX5 PositionsManager imports | //+------------------------------------------------------------------+ #import "Toolkit/PositionsManager.ex5" //-- Open import directive //-- Function descriptions for the imported function prototypes //--Position Execution and Modification Functions bool OpenBuyPosition(ulong magicNumber, string symbol, double lotSize, int sl, int tp, string positionComment); bool OpenSellPosition(ulong magicNumber, string symbol, double lotSize, int sl, int tp, string positionComment); bool SetSlTpByTicket(ulong positionTicket, int sl, int tp); bool ClosePositionByTicket(ulong positionTicket); bool SetTrailingStopLoss(ulong positionTicket, int trailingStopLoss); bool CloseAllPositions(string symbol, ulong magicNumber); bool CloseAllBuyPositions(string symbol, ulong magicNumber); bool CloseAllSellPositions(string symbol, ulong magicNumber); bool CloseAllMagicPositions(ulong magicNumber); bool CloseAllProfitablePositions(string symbol, ulong magicNumber); bool CloseAllLossPositions(string symbol, ulong magicNumber); //--Position Status Monitoring Functions int BuyPositionsTotal(); int SellPositionsTotal(); double PositionsTotalVolume(); double BuyPositionsTotalVolume(); double SellPositionsTotalVolume(); double BuyPositionsProfit(); double SellPositionsProfit(); int MagicPositionsTotal(ulong magicNumber); int MagicBuyPositionsTotal(ulong magicNumber); int MagicSellPositionsTotal(ulong magicNumber); double MagicPositionsTotalVolume(ulong magicNumber); double MagicBuyPositionsTotalVolume(ulong magicNumber); double MagicSellPositionsTotalVolume(ulong magicNumber); double MagicPositionsProfit(ulong magicNumber); double MagicBuyPositionsProfit(ulong magicNumber); double MagicSellPositionsProfit(ulong magicNumber); int SymbolPositionsTotal(string symbol, ulong magicNumber); int SymbolBuyPositionsTotal(string symbol, ulong magicNumber); int SymbolSellPositionsTotal(string symbol, ulong magicNumber); double SymbolPositionsTotalVolume(string symbol, ulong magicNumber); double SymbolBuyPositionsTotalVolume(string symbol, ulong magicNumber); double SymbolSellPositionsTotalVolume(string symbol, ulong magicNumber); double SymbolPositionsProfit(string symbol, ulong magicNumber); double SymbolBuyPositionsProfit(string symbol, ulong magicNumber); double SymbolSellPositionsProfit(string symbol, ulong magicNumber); string AccountPositionsStatus(bool formatForComment); string MagicPositionsStatus(ulong magicNumber, bool formatForComment); string SymbolPositionsStatus(string symbol, ulong magicNumber, bool formatForComment); #import //--- Close import directive
El PositionsManagerPanel.mq5 sólo contendrá una entrada de usuario (número mágico).
//--User input variables input ulong magicNo = 101010;
A continuación, creamos las variables globales para almacenar el volumeLot, sl y tp.
//-- Global variables //----------------------- //-- Get the current symbol spread and multiply it by a significant number //-- to simulate user-input SL and TP values double volumeLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN); int sl = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD) * 50; int tp = (int)SymbolInfoInteger(_Symbol, SYMBOL_SPREAD) * 100;
Vamos a crear nuestro primer objeto gráfico, que servirá de fondo para nuestra interfaz gráfica de usuario. Para ello utilizaremos una etiqueta rectangular. Para ello, crearemos una función personalizada llamada CreateRectangleLabel().
//+-----------------------------------------------------------------------+ //| CreateRectangleLabel(): Creates a rectangle label on the chart window | //+-----------------------------------------------------------------------+ void CreateRectangleLabel() { //--- Detect if we have an object named the same as our rectangle label if(ObjectFind(0, "mainRectangleLabel") >= 0) { //--- Delete the specified object if it is not a rectangle label if(ObjectGetInteger(0, "mainRectangleLabel", OBJPROP_TYPE) != OBJ_RECTANGLE_LABEL) { ObjectDelete(0, "mainRectangleLabel"); } } else { //-- Create the mainRectangleLabel ObjectCreate(0, "mainRectangleLabel", OBJ_RECTANGLE_LABEL, 0, 0, 0); } //--- Set up the new rectangle label properties ObjectSetInteger(0, "mainRectangleLabel", OBJPROP_CORNER, CORNER_LEFT_UPPER); ObjectSetInteger(0, "mainRectangleLabel", OBJPROP_XDISTANCE, 240); ObjectSetInteger(0, "mainRectangleLabel", OBJPROP_YDISTANCE, 2); ObjectSetInteger(0, "mainRectangleLabel", OBJPROP_XSIZE, 460); ObjectSetInteger(0, "mainRectangleLabel", OBJPROP_YSIZE, 520); ObjectSetInteger(0, "mainRectangleLabel", OBJPROP_BGCOLOR, clrMintCream); ObjectSetInteger(0, "mainRectangleLabel", OBJPROP_BACK, false); ObjectSetInteger(0, "mainRectangleLabel", OBJPROP_HIDDEN, true); }
También necesitamos etiquetas para mostrar texto en nuestro panel comercial. Crearemos otra función personalizada llamada CreateLabel() para manejar esta tarea.
//+---------------------------------------------------------+ //| CreateLabel(): Creates a text label on the chart window | //+---------------------------------------------------------+ void CreateLabel( string labelName, int xDistance, int yDistance, int xSize, int ySize, string labelText, color textColor, string fontType, int fontSize ) { //--- Detect if we have an object with the same name as our label if(ObjectFind(0, labelName) >= 0) { //--- Delete the specified object if it is not a label if(ObjectGetInteger(0, labelName, OBJPROP_TYPE) != OBJ_LABEL) { ObjectDelete(0, labelName); } } else { //-- Create the label ObjectCreate(0, labelName, OBJ_LABEL, 0, 0, 0); } //--- Set up the new rectangle label properties ObjectSetInteger(0, labelName, OBJPROP_CORNER, CORNER_LEFT_UPPER); ObjectSetInteger(0, labelName, OBJPROP_XDISTANCE, xDistance); ObjectSetInteger(0, labelName, OBJPROP_YDISTANCE, yDistance); ObjectSetInteger(0, labelName, OBJPROP_XSIZE, xSize); ObjectSetInteger(0, labelName, OBJPROP_YSIZE, ySize); ObjectSetString(0, labelName, OBJPROP_TEXT, labelText); ObjectSetInteger(0, labelName, OBJPROP_COLOR, textColor); ObjectSetString(0, labelName, OBJPROP_FONT, fontType); ObjectSetInteger(0, labelName, OBJPROP_FONTSIZE, fontSize); ObjectSetInteger(0, labelName, OBJPROP_BACK, false); ObjectSetInteger(0, labelName, OBJPROP_HIDDEN, true); ObjectSetInteger(0, labelName, OBJPROP_SELECTABLE, false); ObjectSetInteger(0, labelName, OBJPROP_SELECTED, false); }
Los botones clicables o sensibles son necesarios para que nuestro panel de operaciones realice diferentes operaciones comerciales. Por lo tanto, debemos crear una función personalizada para manejar la creación de botones. Llamemos a esta función CreateButton().
//+------------------------------------------------------+ //| CreateButton(): Creates buttons on the chart window | //+------------------------------------------------------+ void CreateButton( string btnName, int xDistance, int yDistance, int xSize, int ySize, string btnText, string tooltip, color textColor, string fontType, int fontSize, color bgColor ) { //--- Detect if we have an object named the same as our button if(ObjectFind(0, btnName) >= 0) { //--- Delete the specified object if it is not a button if(ObjectGetInteger(0, btnName, OBJPROP_TYPE) != OBJ_BUTTON) { ObjectDelete(0, btnName); } } else { //-- Create the button ObjectCreate(0, btnName, OBJ_BUTTON, 0, 0, 0); } //--- Set up the new button properties ObjectSetInteger(0, btnName, OBJPROP_CORNER, CORNER_LEFT_UPPER); ObjectSetInteger(0, btnName, OBJPROP_XDISTANCE, xDistance); ObjectSetInteger(0, btnName, OBJPROP_YDISTANCE, yDistance); ObjectSetInteger(0, btnName, OBJPROP_XSIZE, xSize); ObjectSetInteger(0, btnName, OBJPROP_YSIZE, ySize); ObjectSetString(0, btnName, OBJPROP_TEXT, btnText); ObjectSetString(0, btnName, OBJPROP_TOOLTIP, tooltip); ObjectSetInteger(0, btnName, OBJPROP_COLOR, textColor); ObjectSetString(0, btnName, OBJPROP_FONT, fontType); ObjectSetInteger(0, btnName, OBJPROP_FONTSIZE, fontSize); ObjectSetInteger(0, btnName, OBJPROP_BGCOLOR, bgColor); }
Ahora necesitamos otra función personalizada para cargar todos los diferentes objetos gráficos y componentes gráficos de entrada de usuario creados con las funciones que hemos escrito anteriormente. Llamemos a esta función LoadChartObjects().
//+--------------------------------------------------------------------+ //| LoadChartObjects(): Create and load the buttons and chart objects | //| for demonstrating how the imported library functions work | //+--------------------------------------------------------------------+ void LoadChartObjects() { //-- Create the rectangle label first CreateRectangleLabel(); //-- Create the heading label CreateLabel( "headingLabel", 250, 10, 440, 60, "PositionsManager ex5 Library Demo Trade Panel", clrMidnightBlue, "Calibri", 10 ); //-- Create the second heading label CreateLabel( "headingLabel2", 250, 30, 440, 60, ("Trading " + _Symbol + " with Magic Number: " + (string)magicNo), clrBlack, "Consolas", 11 ); //-- "BUY": Button to call the imported ex5 OpenBuyPosition() function CreateButton( "OpenBuyPositionBtn", 250, 50, 215, 35, "BUY", "OpenBuyPosition() Function", clrMintCream, "Arial Black", 10, clrDodgerBlue ); //-- "SELL": Button to call the imported ex5 OpenSellPosition() function CreateButton( "OpenSellPositionBtn", 475, 50, 215, 35, "SELL", "OpenSellPosition() Function", clrMintCream, "Arial Black", 10, clrCrimson ); //-- "SetSlTpByTicket": Button to call the imported ex5 SetSlTpByTicket() function CreateButton( "SetSlTpBtn", 250, 90, 215, 35, "SetSlTpByTicket", "SetSlTpByTicket() Function", clrMintCream, "Arial Black", 10, clrDarkSlateGray ); //-- "SetTrailingStopLoss": Button to call the imported ex5 SetTrailingStopLoss() function when clicked CreateButton( "SetTrailingStopLossBtn", 475, 90, 215, 35, "SetTrailingStopLoss", "SetTrailingStopLoss Function", clrMintCream, "Arial Black", 10, clrDarkSlateGray ); //-- "ClosePositionsByTicket": Button to call the imported ex5 ClosePositionByTicket() function CreateButton( "ClosePositionsBtn", 250, 130, 215, 35, "ClosePositionsByTicket", "ClosePositionByTicket() Function", clrMintCream, "Arial Black", 10, clrMaroon ); //-- "CloseAllSymbolPositions": Button to call the imported ex5 CloseAllSymbolPositions() function CreateButton( "CloseAllPositionsBtn", 475, 130, 215, 35, "CloseAllPositions", "CloseAllPositions() Function", clrMintCream, "Arial Black", 10, clrMaroon ); //-- "CloseAllBuySymbolPositions": Button to call the imported ex5 CloseAllBuySymbolPositions() function CreateButton( "CloseAllBuyPositionsBtn", 250, 170, 215, 35, "CloseAllBuyPositions", "CloseAllBuyPositions() Function", clrMintCream, "Arial Black", 10, clrBrown ); //-- "CloseAllSellSymbolPositions": Button to call the imported ex5 CloseAllSellSymbolPositions() function CreateButton( "CloseAllSellPositionsBtn", 475, 170, 215, 35, "CloseAllSellPositions", "CloseAllSellPositions() Function", clrMintCream, "Arial Black", 10, clrBrown ); //-- "CloseAllMagicPositions": Button to call the imported ex5 CloseAllMagicPositions() function CreateButton( "CloseAllMagicPositionsBtn", 250, 210, 440, 35, "CloseAllMagicPositions", "CloseAllMagicPositions() Function", clrMintCream, "Arial Black", 10, C'203,18,55' ); //-- "CloseAllProfitablePositions": Button to call the imported ex5 CloseAllMagicPositions() function CreateButton( "CloseAllProfitablePositionsBtn", 250, 250, 215, 35, "CloseAllProfitablePositions", "CloseAllProfitablePositions() Function", clrMintCream, "Arial Black", 10, clrSeaGreen ); //-- "CloseAllLossPositions": Button to call the imported ex5 CloseAllLossPositions() function CreateButton( "CloseAllLossPositionsBtn", 475, 250, 215, 35, "CloseAllLossPositions", "CloseAllLossPositions() Function", clrMintCream, "Arial Black", 10, C'179,45,0' ); //-- Create the bottomHeadingLabel CreateLabel( "bottomHeadingLabel", 250, 310, 440, 60, (_Symbol + " - (Magic Number: " + (string)magicNo + ") Positions Status"), clrBlack, "Calibri", 12 ); //-- Create totalOpenPositionsLabel CreateLabel( "totalOpenPositionsLabel", 250, 340, 440, 60, (" Total Open: " + (string)MagicPositionsTotal(magicNo)), clrNavy, "Consolas", 11 ); //-- Create totalPositionsVolumeLabel CreateLabel( "totalPositionsVolumeLabel", 250, 360, 440, 60, (" Total Volume: " + (string)NormalizeDouble(MagicPositionsTotalVolume(magicNo), 2)), clrNavy, "Consolas", 11 ); //-- Create the totalPositionsProfitLabel CreateLabel( "totalPositionsProfitLabel", 250, 380, 100, 60, ( " Total Profit: " + (string)(NormalizeDouble(MagicPositionsProfit(magicNo), 2)) + " " + AccountInfoString(ACCOUNT_CURRENCY) ), clrNavy, "Consolas", 11 ); //-- Create the buyPositionsHeadingLabel CreateLabel( "buyPositionsHeadingLabel", 250, 410, 440, 60, ("BUY POSITIONS:"), clrBlack, "Calibri", 12 ); //-- Create the totalBuyPositionsLabel CreateLabel( "totalBuyPositionsLabel", 250, 430, 440, 60, (" Total Open: " + (string)MagicBuyPositionsTotal(magicNo)), clrNavy, "Consolas", 11 ); //-- Create the totalBuyPositionsVolumeLabel CreateLabel( "totalBuyPositionsVolumeLabel", 250, 450, 440, 60, (" Total Volume: " + (string)NormalizeDouble(MagicBuyPositionsTotalVolume(magicNo), 2)), clrNavy, "Consolas", 11 ); //-- Create the totalBuyPositionsProfitLabel CreateLabel( "totalBuyPositionsProfitLabel", 250, 470, 440, 60, ( " Total Profit: " + (string)(NormalizeDouble(MagicBuyPositionsProfit(magicNo), 2)) + " " + AccountInfoString(ACCOUNT_CURRENCY) ), clrNavy, "Consolas", 11 ); //-- Create the sellPositionsHeadingLabel CreateLabel( "sellPositionsHeadingLabel", 475, 410, 440, 60, ("SELL POSITIONS:"), clrBlack, "Calibri", 12 ); //-- Create the totalSellPositionsLabel CreateLabel( "totalSellPositionsLabel", 475, 430, 440, 60, (" Total Open: " + (string)MagicSellPositionsTotal(magicNo)), clrNavy, "Consolas", 11 ); //-- Create the totalSellPositionsVolumeLabel CreateLabel( "totalSellPositionsVolumeLabel", 475, 450, 440, 60, (" Total Volume: " + (string)NormalizeDouble(MagicSellPositionsTotalVolume(magicNo), 2)), clrNavy, "Consolas", 11 ); //-- Create the totalSellPositionsProfitLabel CreateLabel( "totalSellPositionsProfitLabel", 475, 470, 100, 60, ( " Total Profit: " + (string)(NormalizeDouble(MagicSellPositionsProfit(magicNo), 2)) + " " + AccountInfoString(ACCOUNT_CURRENCY) ), clrNavy, "Consolas", 11 ); //--- Redraw the chart to refresh it so that it loads our new chart objects ChartRedraw(); //--- }
La siguiente función personalizada se encargará de limpiar y borrar todos los objetos y datos del gráfico cuando el Asesor Experto finalice o se desinicialice. Llamémosla DeleteChartObjects(). Se colocará y ejecutará en la función OnDeinit() MQL5 de manejo de eventos estándar.
//+------------------------------------------------------------------------------+ //| DeleteChartObjects(): Delete all the chart objects when the EA is terminated | //| on De-initialization | //+------------------------------------------------------------------------------+ void DeleteChartObjects() { //--- //--- Clean up and delete all the buttons or graphical objects ObjectDelete(0, "OpenBuyPositionBtn"); ObjectDelete(0, "OpenSellPositionBtn"); ObjectDelete(0, "SetSlTpBtn"); ObjectDelete(0, "SetTrailingStopLossBtn"); ObjectDelete(0, "ClosePositionsBtn"); ObjectDelete(0, "CloseAllPositionsBtn"); ObjectDelete(0, "CloseAllBuyPositionsBtn"); ObjectDelete(0, "CloseAllSellPositionsBtn"); ObjectDelete(0, "CloseAllMagicPositionsBtn"); ObjectDelete(0, "CloseAllProfitablePositionsBtn"); ObjectDelete(0, "CloseAllLossPositionsBtn"); ObjectDelete(0, "mainRectangleLabel"); ObjectDelete(0, "headingLabel"); ObjectDelete(0, "headingLabel2"); ObjectDelete(0, "bottomHeadingLabel"); ObjectDelete(0, "totalOpenPositionsLabel"); ObjectDelete(0, "totalPositionsVolumeLabel"); ObjectDelete(0, "totalPositionsProfitLabel"); ObjectDelete(0, "buyPositionsHeadingLabel"); ObjectDelete(0, "totalBuyPositionsLabel"); ObjectDelete(0, "totalBuyPositionsVolumeLabel"); ObjectDelete(0, "totalBuyPositionsProfitLabel"); ObjectDelete(0, "sellPositionsHeadingLabel"); ObjectDelete(0, "totalSellPositionsLabel"); ObjectDelete(0, "totalSellPositionsVolumeLabel"); ObjectDelete(0, "totalSellPositionsProfitLabel"); }
Ahora que hemos terminado de crear y gestionar los objetos gráficos, vamos a crear las funciones personalizadas que implementarán algunas de las funciones importadas de la librería PositionsManager.ex5. La primera función de este grupo, que llamaremos ModifySlTp(), se encargará de modificar el stop loss (sl) y el take profit (tp) de todas las posiciones abiertas por este Asesor Experto que coincidan con el número mágico introducido por el usuario. Esta función se ejecutará cada vez que se pulse el botón setSLTP del gráfico.
//+-------------------------------------------------------------------------+ // ModifySlTp(): This function demonstrates how to use the imported ex5 | // bool SetSlTpByTicket(ulong positionTicket, int sl, int tp); | // It runs this function when the setSLTP button on the chart is clicked. | //+-------------------------------------------------------------------------+ void ModifySlTp() { //-- Get positions that we have openend with the chart buy and sell buttons to test the imported function with int totalOpenPostions = PositionsTotal(); //--- Scan open positions for(int x = 0; x < totalOpenPostions; x++) { //--- Get position properties ulong positionTicket = PositionGetTicket(x); //-- Get ticket to select the position string selectedSymbol = PositionGetString(POSITION_SYMBOL); ulong positionMagicNo = PositionGetInteger(POSITION_MAGIC); //-- modify only the positions we have opened with this EA (magic number) using the BUY and SELL buttons on the chart if(selectedSymbol != _Symbol && positionMagicNo != magicNo) { continue; } //--- modify the sl and tp of the position SetSlTpByTicket(positionTicket, sl, tp);//-- call the imported function from our ex5 library } }
La siguiente función, SetTrailingSl(), se encargará de actualizar el trailing stop loss. Se ejecutará tanto cuando se haga clic en el botón SetTrailingStopLoss del gráfico como en cada nuevo tick entrante en la función de gestión de eventos OnTick().
//+-----------------------------------------------------------------------------------+ // SetTrailingSl(): This function demonstrates how to use the imported ex5 | // bool SetTrailingStopLoss(ulong positionTicket, int trailingStopLoss); | // It runs this function when the SetTrailingStopLoss button on the chart is clicked. | //+-----------------------------------------------------------------------------------+ void SetTrailingSl() { int trailingSl = sl; //-- Get positions that we have openend with the chart buy and sell buttons to test the imported function with int totalOpenPostions = PositionsTotal(); //--- Scan open positions for(int x = 0; x < totalOpenPostions; x++) { //--- Get position properties ulong positionTicket = PositionGetTicket(x); //-- Get ticket to select the position string selectedSymbol = PositionGetString(POSITION_SYMBOL); ulong positionMagicNo = PositionGetInteger(POSITION_MAGIC); //-- modify only the positions we have opened with this EA (magic number) using the BUY and SELL buttons on the chart if(selectedSymbol != _Symbol && positionMagicNo != magicNo) { continue; } //--- set the trailing stop loss SetTrailingStopLoss(positionTicket, trailingSl); //-- call the imported function from our ex5 library } }
La función ClosePositionWithTicket() se encargará de cerrar todas las posiciones abiertas y se ejecutará cuando se pulse el botón ClosePositions del gráfico.
//+-----------------------------------------------------------------------------------+ // ClosePositionWithTicket(): This function demonstrates how to use the imported ex5 | // bool ClosePositionByTicket(ulong positionTicket) | // It runs this function when the ClosePositions button on the chart is clicked. | //+-----------------------------------------------------------------------------------+ void ClosePositionWithTicket() { //-- Get positions that we have openend with the chart buy and sell buttons to test the imported function with int totalOpenPostions = PositionsTotal(); //--- Scan open positions for(int x = 0; x < totalOpenPostions; x++) { //--- Get position properties ulong positionTicket = PositionGetTicket(x); //-- Get ticket to select the position string selectedSymbol = PositionGetString(POSITION_SYMBOL); ulong positionMagicNo = PositionGetInteger(POSITION_MAGIC); //-- close only the positions we have opened with this EA (magic number) using the BUY and SELL buttons on the chart if(selectedSymbol != _Symbol && positionMagicNo != magicNo) { continue; } //--- Close the position ClosePositionByTicket(positionTicket);//-- call the imported function from our ex5 library } }
La última función es la función estándar OnChartEvent() MQL5, que detectará cuando se pulsan nuestros distintos botones y realizará las acciones correspondientes. Casi todas las funciones importadas de gestión de posiciones de la librería PositionsManager.ex5 serán llamadas y ejecutadas desde esta función.
//+------------------------------------------------------------------+ //| ChartEvent function to detect when the buttons are clicked | //+------------------------------------------------------------------+ void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { //--- //--- Detected a CHARTEVENT_CLICK event if(id == CHARTEVENT_OBJECT_CLICK) { Print(__FUNCTION__, ": ", sparam); //--- Buy when OpenBuyPositionBtn button (BUY) is pressed or clicked if(sparam == "OpenBuyPositionBtn") { //-- Call our imported function from the Toolkit/PositionsManager ex5 library OpenBuyPosition(magicNo, _Symbol, volumeLot, sl, tp, "ex5 PositionsManager"); //--- Release and unpress the button ObjectSetInteger(0, "OpenBuyPositionBtn", OBJPROP_STATE, false); } //--- Sell when OpenSellPositionBtn button (SELL) is pressed if(sparam == "OpenSellPositionBtn") { //-- Call our imported function from the Toolkit/PositionsManager ex5 library OpenSellPosition(magicNo, _Symbol, volumeLot, sl, tp, "ex5 PositionsManager"); //OpenSellPosition(magicNo, "NON-EXISTENT-Symbol-Name"/*_Symbol*/, volumeLot, sl, tp, "ex5 PositionsManager"); //--- Release and unpress the button ObjectSetInteger(0, "OpenSellPositionBtn", OBJPROP_STATE, false); } //--- Modify specified positions SL and TP when SetSlTpBtn button (setSLTP) is pressed if(sparam == "SetSlTpBtn") { ModifySlTp();//-- Modify the SL and TP of the positions generated by the BUY and SELL buttons //--- Release and unpress the button ObjectSetInteger(0, "SetSlTpBtn", OBJPROP_STATE, false); } //--- Set the Trailing Stop Loss when SetSlTpBtn button (SetTrailingStopLossBtn) is pressed if(sparam == "SetTrailingStopLossBtn") { SetTrailingSl();//-- Set the Trailing Stop Loss for the positions generated by the BUY and SELL buttons //--- Release and unpress the button ObjectSetInteger(0, "SetTrailingStopLossBtn", OBJPROP_STATE, false); } //--- Close specified positions when SetSlTpBtn button (setSLTP) is pressed if(sparam == "ClosePositionsBtn") { ClosePositionWithTicket();//-- Close all the positions generated by the BUY and SELL buttons //--- Release and unpress the button ObjectSetInteger(0, "ClosePositionsBtn", OBJPROP_STATE, false); } //--- Close all positions for the current symbol when the CloseAllPositionsBtn button is pressed if(sparam == "CloseAllPositionsBtn") { CloseAllPositions(_Symbol, 0);//-- Close all the open symbol positions //--- Release and unpress the button ObjectSetInteger(0, "CloseAllPositionsBtn", OBJPROP_STATE, false); } //--- Close all buy positions for the current symbol when the CloseAllBuyPositionsBtn button is pressed if(sparam == "CloseAllBuyPositionsBtn") { CloseAllBuyPositions(_Symbol, magicNo);//-- Close all the open symbol buy positions //--- Release and unpress the button ObjectSetInteger(0, "CloseAllBuyPositionsBtn", OBJPROP_STATE, false); } //--- Close all sell positions for the current symbol when the CloseAllSellPositionsBtn button is pressed if(sparam == "CloseAllSellPositionsBtn") { CloseAllSellPositions(_Symbol, magicNo);//-- Close all the open symbol sell positions //--- Release and unpress the button ObjectSetInteger(0, "CloseAllSellPositionsBtn", OBJPROP_STATE, false); } //--- Close all positions with the specified magic number when the CloseAllMagicPositionsBtn button is pressed if(sparam == "CloseAllMagicPositionsBtn") { CloseAllMagicPositions(magicNo);//-- Close all the open positions with the specified magic number //--- Release and unpress the button ObjectSetInteger(0, "CloseAllMagicPositionsBtn", OBJPROP_STATE, false); } //--- Close all profitable positions with the specified symbol and magic number when the CloseAllProfitablePositionsBtn button is pressed if(sparam == "CloseAllProfitablePositionsBtn") { CloseAllProfitablePositions(_Symbol, magicNo);//-- Close all the open profitable positions with the specified symbol and magic number //--- Release and unpress the button ObjectSetInteger(0, "CloseAllProfitablePositionsBtn", OBJPROP_STATE, false); } //--- Close all loss positions with the specified symbol and magic number when the CloseAllLossPositionsBtn button is pressed if(sparam == "CloseAllLossPositionsBtn") { CloseAllLossPositions(_Symbol, magicNo);//-- Close all the open loss positions with the specified symbol and magic number //--- Release and unpress the button ObjectSetInteger(0, "CloseAllLossPositionsBtn", OBJPROP_STATE, false); } //--- Redraw the chart to refresh it ChartRedraw(); } //--- }
Antes de ejecutar PositionsTradePanel.mq5, necesitamos incorporar todos los componentes necesarios en las funciones de manejo de eventos OnInit(), OnDeinit(), y OnTick(). Comience cargando todos los objetos gráficos durante la inicialización del Experto con la función LoadChartObjects() en la función OnInit().
//+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- //create buttons to demonstrate how the different ex5 library functions work LoadChartObjects(); //--- return(INIT_SUCCEEDED); }
Llama y ejecuta las siguientes funciones en la función OnTick().
//+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //-- Check for profitable positions and set the trailing stop loss on every new tick SetTrailingSl(); //-- Calls the ex5 library function responsible for setting Trailing stops LoadChartObjects(); //--- Update chart objects }
Añada la función de desinicialización al manejador de eventos OnDeinit() para eliminar todos los objetos gráficos y de gráfico cuando se cierre o finalice el Asesor Experto.
//+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- //-- Clean up the chart DeleteChartObjects(); //-- Clear any chart comments Comment(""); }
Encontrará el archivo de código fuente completo de PositionsManagerPanel.mq5 adjunto al final de este artículo para un examen más detallado.
Guarde, compile y cargue PositionsManagerPanel.mq5 en cualquier gráfico de MetaTrader 5. En la pestaña Dependencias, verás todos los prototipos de funciones de la biblioteca importados de PositionsManager.ex5, junto con la ruta completa del archivo donde se guarda la biblioteca EX5. Una vez cargado en el gráfico, pruébelo abriendo algunas posiciones y comprobando en el registro de la pestaña Expertos del panel Caja de herramientas del terminal de negociación los datos de registro impresos de las funciones prototipo de PositionsManager.ex5.
Conclusión
Ahora ya conoce en profundidad las bibliotecas EX5 de MQL5. Hemos cubierto su creación, integración e implementación en proyectos MQL5 externos, incluyendo cómo depurar varios errores de las librerías EX5, y cómo actualizarlas y redistribuirlas. Además, hemos creado una biblioteca de gestión de posiciones EX5 potente y repleta de funciones, con documentación detallada y ejemplos prácticos de casos de uso. También he demostrado cómo importar e implementar esta biblioteca en dos diferentes asesores expertos MQL5 prácticos, proporcionando ejemplos del mundo real sobre la implementación efectiva de las bibliotecas EX5. En el próximo artículo, seguiremos un enfoque similar para desarrollar una completa librería EX5 de gestión de órdenes pendientes, diseñada para simplificar las tareas de procesamiento de órdenes pendientes en tus aplicaciones MQL5. Gracias por seguirme y te deseo mucho éxito en tu viaje por el trading y la programación.
Traducción del inglés realizada por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/en/articles/15224





- Aplicaciones de trading gratuitas
- 8 000+ señales para copiar
- Noticias económicas para analizar los mercados financieros
Usted acepta la política del sitio web y las condiciones de uso