From 448b5ece939abb1a04040f7c363e2592183c439d Mon Sep 17 00:00:00 2001 From: EarnForex <48102957+EarnForex@users.noreply.github.com> Date: Wed, 26 Jul 2023 17:46:02 +0200 Subject: [PATCH] 1.00 --- MQL4/Files/EF-Icon-64x64px.ico | Bin 0 -> 2686 bytes MQL4/Scripts/Breakeven.mq4 | 113 +++++++++++++++++++++++++++++++ MQL5/Files/EF-Icon-64x64px.ico | Bin 0 -> 2686 bytes MQL5/Scripts/Breakeven.mq5 | 120 +++++++++++++++++++++++++++++++++ 4 files changed, 233 insertions(+) create mode 100644 MQL4/Files/EF-Icon-64x64px.ico create mode 100644 MQL4/Scripts/Breakeven.mq4 create mode 100644 MQL5/Files/EF-Icon-64x64px.ico create mode 100644 MQL5/Scripts/Breakeven.mq5 diff --git a/MQL4/Files/EF-Icon-64x64px.ico b/MQL4/Files/EF-Icon-64x64px.ico new file mode 100644 index 0000000000000000000000000000000000000000..30c9d729d1b7cafcb9c1b272402220fd54da61d1 GIT binary patch literal 2686 zcmZQzU<5)32LT|-!jQqmz#zuJz@P!d4nW)h#2|58pstI9;pjzwT+*ZB!zBa+u>-jG zuuBV$%0okd*5LyWXfOkA8>%pzH!2Se0eFa@GDr^}xDHeX+*nj$IB!%Q8UpYTL1j=a ieBcIw8E{Kbh2gwWd1wg0Lj;vU>+nIfZIm}`LjVArAv>u6 literal 0 HcmV?d00001 diff --git a/MQL4/Scripts/Breakeven.mq4 b/MQL4/Scripts/Breakeven.mq4 new file mode 100644 index 0000000..b681b9e --- /dev/null +++ b/MQL4/Scripts/Breakeven.mq4 @@ -0,0 +1,113 @@ +#property link "https://www.earnforex.com/metatrader-scripts/breakeven/" +#property version "1.00" +#property strict +#property copyright "EarnForex.com - 2023" +#property description "This script will set breakeven on all trades filtered according to your preferences." +#property description "" +#property description "WARNING: Use this software at your own risk." +#property description "The creator of this script cannot be held responsible for any damage or loss." +#property description "" +#property description "Find More on EarnForex.com" +#property icon "\\Files\\EF-Icon-64x64px.ico" +#property show_inputs + +enum ENUM_ORDER_TYPES +{ + ALL_ORDERS = 1, // ALL ORDERS + ONLY_BUY = 2, // BUY ONLY + ONLY_SELL = 3 // SELL ONLY +}; + +input bool OnlyCurrentSymbol = false; // Only current chart's symbol +input ENUM_ORDER_TYPES OrderTypeFilter = ALL_ORDERS; // Type of orders to move SL to BE +input int MinimumProfit = 0; // Minimum current profit in points to apply BE +input int AdditionalProfit = 0; // Additional profit in points to add to BE +input bool OnlyMagicNumber = false; // Only orders matching the magic number +input int MagicNumber = 0; // Matching magic number +input bool OnlyWithComment = false; // Only orders with the following comment +input string MatchingComment = ""; // Matching comment + +void OnStart() +{ + if (!TerminalInfoInteger(TERMINAL_CONNECTED)) + { + Print("Not connected to the trading server. Exiting."); + return; + } + + if ((!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) || (!MQLInfoInteger(MQL_TRADE_ALLOWED))) + { + Print("Autotrading is disable. Please enable. Exiting."); + return; + } + + int orders_total = OrdersTotal(); + for (int i = orders_total - 1; i >= 0; i--) // Going backwards in case one or more orders are closed during the cycle. + { + if (!OrderSelect(i, SELECT_BY_POS)) + { + Print("ERROR - Unable to select the order - ", GetLastError()); + continue; + } + if (OrderProfit() <= 0) continue; // Unprofitable orders are always skipped. + // Check if the order matches the filter and if not, skip the order and move to the next one. + if ((OrderTypeFilter == ONLY_SELL) && (OrderType() == OP_BUY)) continue; + if ((OrderTypeFilter == ONLY_BUY) && (OrderType() == OP_SELL)) continue; + if ((OnlyCurrentSymbol) && (OrderSymbol() != Symbol())) continue; + if ((OnlyMagicNumber) && (OrderMagicNumber() != MagicNumber)) continue; + if ((OnlyWithComment) && (StringCompare(OrderComment(), MatchingComment) != 0)) continue; + + double point = SymbolInfoDouble(OrderSymbol(), SYMBOL_POINT); + // Compare doubles by calculating difference. If this difference is greater than Point / 2, the order's profit is below the MinimumProfit parameter. + if ((MinimumProfit > 0) && ((double)MinimumProfit - MathAbs(OrderOpenPrice() - OrderClosePrice()) / point > point / 2)) continue; + + if (SymbolInfoInteger(OrderSymbol(), SYMBOL_TRADE_MODE) == SYMBOL_TRADE_MODE_DISABLED) + { + Print("Trading is disabled for ", OrderSymbol(), ". Skipping."); + continue; + } + + double extra_be_distance = AdditionalProfit * point; + int digits = (int)SymbolInfoInteger(OrderSymbol(), SYMBOL_DIGITS); + double tick_size = MarketInfo(OrderSymbol(), MODE_TICKSIZE); + if (tick_size > 0) + { + // Adjust for tick size granularity. + extra_be_distance = NormalizeDouble(MathRound(extra_be_distance / tick_size) * tick_size, digits); + } + else + { + Print("Zero tick size for ", OrderSymbol(), ". Skipping."); + continue; + } + + if (OrderType() == OP_BUY) + { + double BE_price = NormalizeDouble(OrderOpenPrice() + extra_be_distance, digits); + if ((SymbolInfoDouble(OrderSymbol(), SYMBOL_BID) >= BE_price) && (BE_price > OrderStopLoss())) // Only move to BE if the price is above the calculated BE price, and the current stop-loss is lower. + { + double prev_sl = OrderStopLoss(); // Remember old SL for reporting. + // Write BE price to the SL field. + if (!OrderModify(OrderTicket(), OrderOpenPrice(), BE_price, OrderTakeProfit(), OrderExpiration())) + Print("OrderModify Buy BE failed ", GetLastError(), " for ", OrderSymbol()); + else + Print("Breakeven was applied to position - " + OrderSymbol() + " BUY-order #" + IntegerToString(OrderTicket()) + " Lotsize = ", OrderLots(), ", OpenPrice = " + DoubleToString(OrderOpenPrice(), digits) + ", Stop-Loss was moved from " + DoubleToString(prev_sl, digits) + "."); + } + } + else if (OrderType() == OP_SELL) + { + double BE_price = NormalizeDouble(OrderOpenPrice() - extra_be_distance, digits); + if ((SymbolInfoDouble(OrderSymbol(), SYMBOL_ASK) <= BE_price) && ((BE_price < OrderStopLoss()) || (OrderStopLoss() == 0))) // Only move to BE if the price below the calculated BE price, and the current stop-loss is higher (or zero). + { + double prev_sl = OrderStopLoss(); // Remember old SL for reporting. + // Write BE price to the SL field. + if (!OrderModify(OrderTicket(), OrderOpenPrice(), BE_price, OrderTakeProfit(), OrderExpiration())) + Print("OrderModify Buy BE failed ", GetLastError(), " for ", OrderSymbol()); + else + Print("Breakeven was applied to position - " + OrderSymbol() + " SELL-order #" + IntegerToString(OrderTicket()) + " Lotsize = ", OrderLots(), ", OpenPrice = " + DoubleToString(OrderOpenPrice(), digits) + ", Stop-Loss was moved from " + DoubleToString(prev_sl, digits) + "."); + } + } + } + return; +} +//+------------------------------------------------------------------+ \ No newline at end of file diff --git a/MQL5/Files/EF-Icon-64x64px.ico b/MQL5/Files/EF-Icon-64x64px.ico new file mode 100644 index 0000000000000000000000000000000000000000..30c9d729d1b7cafcb9c1b272402220fd54da61d1 GIT binary patch literal 2686 zcmZQzU<5)32LT|-!jQqmz#zuJz@P!d4nW)h#2|58pstI9;pjzwT+*ZB!zBa+u>-jG zuuBV$%0okd*5LyWXfOkA8>%pzH!2Se0eFa@GDr^}xDHeX+*nj$IB!%Q8UpYTL1j=a ieBcIw8E{Kbh2gwWd1wg0Lj;vU>+nIfZIm}`LjVArAv>u6 literal 0 HcmV?d00001 diff --git a/MQL5/Scripts/Breakeven.mq5 b/MQL5/Scripts/Breakeven.mq5 new file mode 100644 index 0000000..4da8c28 --- /dev/null +++ b/MQL5/Scripts/Breakeven.mq5 @@ -0,0 +1,120 @@ +#property link "https://www.earnforex.com/metatrader-scripts/breakeven/" +#property version "1.00" +#property copyright "EarnForex.com - 2023" +#property description "This script will set breakeven on all trades filtered according to your preferences." +#property description "" +#property description "WARNING: Use this software at your own risk." +#property description "The creator of this script cannot be held responsible for any damage or loss." +#property description "" +#property description "Find More on EarnForex.com" +#property icon "\\Files\\EF-Icon-64x64px.ico" +#property script_show_inputs + +#include + +enum ENUM_ORDER_TYPES +{ + ALL_ORDERS = 1, // ALL ORDERS + ONLY_BUY = 2, // BUY ONLY + ONLY_SELL = 3 // SELL ONLY +}; + +input bool OnlyCurrentSymbol = false; // Only current chart's symbol +input ENUM_ORDER_TYPES OrderTypeFilter = ALL_ORDERS; // Type of orders to move SL to BE +input int MinimumProfit = 0; // Minimum current profit in points to apply BE +input int AdditionalProfit = 0; // Additional profit in points to add to BE +input bool OnlyMagicNumber = false; // Only orders matching the magic number +input int MagicNumber = 0; // Matching magic number +input bool OnlyWithComment = false; // Only orders with the following comment +input string MatchingComment = ""; // Matching comment + +void OnStart() +{ + if (!TerminalInfoInteger(TERMINAL_CONNECTED)) + { + Print("Not connected to the trading server. Exiting."); + return; + } + + if ((!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) || (!MQLInfoInteger(MQL_TRADE_ALLOWED))) + { + Print("Autotrading is disable. Please enable. Exiting."); + return; + } + + CTrade *Trade; + Trade = new CTrade; + + int positions_total = PositionsTotal(); + for (int i = positions_total - 1; i >= 0; i--) // Going backwards in case one or more positions are closed during the cycle. + { + ulong ticket = PositionGetTicket(i); + if (ticket <= 0) + { + Print("ERROR - Unable to select the position - ", GetLastError()); + continue; + } + + if (PositionGetDouble(POSITION_PROFIT) <= 0) continue; // Unprofitable positions are always skipped. + // Check if the position matches the filter and if not, skip the position and move to the next one. + if ((OrderTypeFilter == ONLY_SELL) && (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)) continue; + if ((OrderTypeFilter == ONLY_BUY) && (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)) continue; + if ((OnlyCurrentSymbol) && (PositionGetString(POSITION_SYMBOL) != Symbol())) continue; + if ((OnlyMagicNumber) && (PositionGetInteger(POSITION_MAGIC) != MagicNumber)) continue; + if ((OnlyWithComment) && (StringCompare(PositionGetString(POSITION_COMMENT), MatchingComment) != 0)) continue; + + double point = SymbolInfoDouble(PositionGetString(POSITION_SYMBOL), SYMBOL_POINT); + // Compare doubles by calculating difference. If this difference is greater than Point / 2, the position's profit is below the MinimumProfit parameter. + if ((MinimumProfit > 0) && ((double)MinimumProfit - MathAbs(PositionGetDouble(POSITION_PRICE_OPEN) - PositionGetDouble(POSITION_PRICE_CURRENT)) / point > point / 2)) continue; + + if (SymbolInfoInteger(PositionGetString(POSITION_SYMBOL), SYMBOL_TRADE_MODE) == SYMBOL_TRADE_MODE_DISABLED) + { + Print("Trading is disabled for ", PositionGetString(POSITION_SYMBOL), ". Skipping."); + continue; + } + + double extra_be_distance = AdditionalProfit * point; + int digits = (int)SymbolInfoInteger(PositionGetString(POSITION_SYMBOL), SYMBOL_DIGITS); + double tick_size = SymbolInfoDouble(PositionGetString(POSITION_SYMBOL), SYMBOL_TRADE_TICK_SIZE); + if (tick_size > 0) + { + // Adjust for tick size granularity. + extra_be_distance = NormalizeDouble(MathRound(extra_be_distance / tick_size) * tick_size, digits); + } + else + { + Print("Zero tick size for ", PositionGetString(POSITION_SYMBOL), ". Skipping."); + continue; + } + + if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) + { + double BE_price = NormalizeDouble(PositionGetDouble(POSITION_PRICE_OPEN) + extra_be_distance, digits); + if ((SymbolInfoDouble(PositionGetString(POSITION_SYMBOL), SYMBOL_BID) >= BE_price) && (BE_price > PositionGetDouble(POSITION_SL))) // Only move to BE if the price is above the calculated BE price, and the current stop-loss is lower. + { + double prev_sl = PositionGetDouble(POSITION_SL); // Remember old SL for reporting. + // Write BE price to the SL field. + if (!Trade.PositionModify(ticket, BE_price, PositionGetDouble(POSITION_TP))) + Print("PositionModify Buy BE failed ", GetLastError(), " for ", PositionGetString(POSITION_SYMBOL)); + else + Print("Breakeven was applied to position - " + PositionGetString(POSITION_SYMBOL) + " BUY #" + IntegerToString(ticket) + " Lotsize = ", PositionGetDouble(POSITION_VOLUME), ", OpenPrice = " + DoubleToString(PositionGetDouble(POSITION_PRICE_OPEN), digits) + ", Stop-Loss was moved from " + DoubleToString(prev_sl, digits) + "."); + } + } + else if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) + { + double BE_price = NormalizeDouble(PositionGetDouble(POSITION_PRICE_OPEN) - extra_be_distance, digits); + if ((SymbolInfoDouble(PositionGetString(POSITION_SYMBOL), SYMBOL_ASK) <= BE_price) && ((BE_price < PositionGetDouble(POSITION_SL)) || (PositionGetDouble(POSITION_SL) == 0))) // Only move to BE if the price below the calculated BE price, and the current stop-loss is higher (or zero). + { + double prev_sl = PositionGetDouble(POSITION_SL); // Remember old SL for reporting. + // Write BE price to the SL field. + if (!Trade.PositionModify(ticket, BE_price, PositionGetDouble(POSITION_TP))) + Print("PositionModify Buy BE failed ", GetLastError(), " for ", PositionGetString(POSITION_SYMBOL)); + else + Print("Breakeven was applied to position - " + PositionGetString(POSITION_SYMBOL) + " SELL #" + IntegerToString(ticket) + " Lotsize = ", PositionGetDouble(POSITION_VOLUME), ", OpenPrice = " + DoubleToString(PositionGetDouble(POSITION_PRICE_OPEN), digits) + ", Stop-Loss was moved from " + DoubleToString(prev_sl, digits) + "."); + } + } + } + delete Trade; + return; +} +//+------------------------------------------------------------------+ \ No newline at end of file