From ef6485ad797630a63dc3e9c4b53550da84c76f49 Mon Sep 17 00:00:00 2001 From: EarnForex <48102957+EarnForex@users.noreply.github.com> Date: Wed, 19 Jun 2024 17:36:50 +0200 Subject: [PATCH] 1.11 1. Added an option to switch the hidden equity trailing stop to percentage points. 2. Added a silent mode to avoid outputting the AP's log messages to the Experts tab. 3. Added a special mechanism to avoid cyclical triggering of daily profit/loss conditions. 4. Changed the default log file name to ap_log.txt. 5. Changed how autotrading status is detected and reported. --- .../Account Protector/Account Protector.mq4 | 16 +++- .../Account Protector/Account Protector.mqh | 79 ++++++++++------ MQL4/Experts/Account Protector/Defines.mqh | 2 +- .../Account Protector/Account Protector.mq5 | 16 +++- .../Account Protector/Account Protector.mqh | 94 ++++++++++++------- MQL5/Experts/Account Protector/Defines.mqh | 2 +- 6 files changed, 137 insertions(+), 72 deletions(-) diff --git a/MQL4/Experts/Account Protector/Account Protector.mq4 b/MQL4/Experts/Account Protector/Account Protector.mq4 index d777ef9..e211ea7 100644 --- a/MQL4/Experts/Account Protector/Account Protector.mq4 +++ b/MQL4/Experts/Account Protector/Account Protector.mq4 @@ -1,12 +1,12 @@ //+------------------------------------------------------------------+ //| Account Protector.mq4 | -//| Copyright © 2017-2023, EarnForex.com | +//| Copyright © 2017-2024, EarnForex.com | //| https://www.earnforex.com/ | //+------------------------------------------------------------------+ #property copyright "EarnForex.com" #property link "https://www.earnforex.com/metatrader-expert-advisors/Account-Protector/" -#property version "1.10" -string Version = "1.10"; +#property version "1.11" +string Version = "1.11"; #property strict #property description "Protects account balance by applying given actions when set conditions trigger." @@ -59,14 +59,16 @@ input int DelayOrderClose = 0; // DelayOrderClose: Delay in milliseconds. input bool UseTotalVolume = false; // UseTotalVolume: enable if trading with many small trades and partial position closing. input ENUM_CLOSE_TRADES CloseFirst = ENUM_CLOSE_TRADES_DEFAULT; // CloseFirst: Close which trades first? input bool BreakEvenProfitInCurrencyUnits = false; // BreakEvenProfitInCurrencyUnits: currency instead of points. +input bool EquityTrailingStopInPercentage = false; // EquityTrailingStopInPercentage: % instead of $. input string ____Miscellaneous = ""; input bool AlertOnEquityTS = false; // AlertOnEquityTS: Alert when equity trailing stop triggers? input double AdditionalFunds = 0; // AdditionalFunds: Added to balance, equity, and free margin. input string Instruments = ""; // Instruments: Default list of trading instruments for order filtering. input bool GlobalSnapshots = false; // GlobalSnapshots: AP instances share equity & margin snapshots. input int Slippage = 2; // Slippage -input string LogFileName = "log.txt"; // Log file name +input string LogFileName = "ap_log.txt"; // Log file name input string SettingsFileName = ""; // Settings file: Load custom panel settings from \Files\ folder. +input bool Silent = false; // Silent: No log output to the Experts tab. CAccountProtector ExtDialog; @@ -253,7 +255,11 @@ int OnInit() if ((!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) || (!MQLInfoInteger(MQL_TRADE_ALLOWED))) { - Alert("AutoTrading is disabled! EA will be not able to perform trading operations!"); + string where = ""; + if ((!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) && (!MQLInfoInteger(MQL_TRADE_ALLOWED))) where = "in both EA's and platform's settings"; // Both. + else if (!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) where = "in the platform's settings"; // Platform level. + else if (!MQLInfoInteger(MQL_TRADE_ALLOWED)) where = "in the EA's settings"; // EA level. + Alert("AutoTrading is disabled " + where + "! EA will be not able to perform trading operations!"); sets.ClosePos = false; sets.DeletePend = false; sets.DisAuto = false; diff --git a/MQL4/Experts/Account Protector/Account Protector.mqh b/MQL4/Experts/Account Protector/Account Protector.mqh index 85b3734..12e99b9 100644 --- a/MQL4/Experts/Account Protector/Account Protector.mqh +++ b/MQL4/Experts/Account Protector/Account Protector.mqh @@ -1,6 +1,6 @@ //+------------------------------------------------------------------+ //| Account Protector.mqh | -//| Copyright © 2017-2023, EarnForex.com | +//| Copyright © 2017-2024, EarnForex.com | //| https://www.earnforex.com/ | //+------------------------------------------------------------------+ #include "Defines.mqh" @@ -11,9 +11,6 @@ int GetAncestor(int, int); #import -//+------------------------------------------------------------------+ -//| | -//+------------------------------------------------------------------+ class CAccountProtector : public CAppDialog { private: @@ -634,7 +631,10 @@ bool CAccountProtector::CreateObjects() if (!CheckBoxCreate(m_ChkBreakEvenExtra, first_column_start, y, panel_end, y + element_height, "m_ChkBreakEvenExtra", "Breakeven extra profit value (points):")) return false; if (!EditCreate(m_EdtBreakEvenExtra, last_input_start, y, last_input_end, y + element_height, "m_EdtBreakEvenExtra", "0")) return false; y += element_height + v_spacing; - if (!CheckBoxCreate(m_ChkEquityTrailingStop, first_column_start, y, panel_end, y + element_height, "m_ChkEquityTrailingStop", "Equity trailing stop (hidden), USD:")) return false; + string ets = "Equity trailing stop (hidden), "; + if (EquityTrailingStopInPercentage) ets += "%:"; + else ets += "USD:"; + if (!CheckBoxCreate(m_ChkEquityTrailingStop, first_column_start, y, panel_end, y + element_height, "m_ChkEquityTrailingStop", ets)) return false; if (!EditCreate(m_EdtEquityTrailingStop, last_input_start, y, last_input_end, y + element_height, "m_EdtEquityTrailingStop", "0")) return false; y += element_height + v_spacing; if (!LabelCreate(m_LblCurrentEquityStopLoss, first_column_start, y, first_column_start + normal_label_width, y + element_height, "m_LblCurrentEquityStopLoss", "Current equity stop-loss, USD: ")) return false; @@ -1160,11 +1160,12 @@ bool CAccountProtector::RefreshValues() string account_currency = AccountCurrency(); if (account_currency != "") { - m_ChkEquityTrailingStop.Text("Equity trailing stop (hidden), " + account_currency + ":"); + if (!EquityTrailingStopInPercentage) m_ChkEquityTrailingStop.Text("Equity trailing stop (hidden), " + account_currency + ":"); if (BreakEvenProfitInCurrencyUnits) { m_ChkBreakEven.Text("Profit value (" + account_currency + ") to set SL to breakeven:"); } + if ((sets.boolEquityTrailingStop) && (sets.doubleEquityTrailingStop > 0)) m_LblCurrentEquityStopLoss.Text("Current equity stop-loss: " + DoubleToString(sets.doubleCurrentEquityStopLoss, 2) + " " + account_currency + "."); } if (IsANeedToContinueClosingOrders) Close_All_Positions(); if (IsANeedToContinueDeletingPendingOrders) Delete_All_Pending_Orders(); @@ -3743,9 +3744,14 @@ void CAccountProtector::HideShowMaximize(bool max = true) void CAccountProtector::Check_Status() { if (sets.Triggered) return; - if ((!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) || (!MQLInfoInteger(MQL_TRADE_ALLOWED))) + if (!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) + { + m_LblStatus.Text("Status: Autotrading is disabled (platform)."); + return; + } + else if (!MQLInfoInteger(MQL_TRADE_ALLOWED)) { - m_LblStatus.Text("Status: Autotrading is disabled."); + m_LblStatus.Text("Status: Autotrading is disabled (EA)."); return; } else if ((!MQLInfoInteger(MQL_DLLS_ALLOWED)) && ((sets.DisAuto) || (sets.EnableAuto))) @@ -4462,10 +4468,12 @@ void CAccountProtector::EquityTrailing() MoveAndResize(); } // If equity stop-loss should be trailed - update the stop-loss. - else if ((AE - sets.doubleEquityTrailingStop > sets.doubleCurrentEquityStopLoss) || (sets.doubleCurrentEquityStopLoss == 0)) + if (((!EquityTrailingStopInPercentage) && ((AE - sets.doubleEquityTrailingStop > sets.doubleCurrentEquityStopLoss) || (sets.doubleCurrentEquityStopLoss == 0))) || // Currency equity trailing stop should be moved. + ((EquityTrailingStopInPercentage) && ((AE * (1 - sets.doubleEquityTrailingStop / 100.0) > sets.doubleCurrentEquityStopLoss) || (sets.doubleCurrentEquityStopLoss == 0)))) // Percentage equity trailing stop should be moved. { double old_value = sets.doubleCurrentEquityStopLoss; - sets.doubleCurrentEquityStopLoss = AE - sets.doubleEquityTrailingStop; + if (!EquityTrailingStopInPercentage) sets.doubleCurrentEquityStopLoss = AE - sets.doubleEquityTrailingStop; // $ + else sets.doubleCurrentEquityStopLoss = AE * (1 - sets.doubleEquityTrailingStop / 100.0); // % SaveSettingsOnDisk(); string account_currency = AccountCurrency(); if (account_currency != "") m_LblCurrentEquityStopLoss.Text("Current equity stop-loss: " + DoubleToString(sets.doubleCurrentEquityStopLoss, 2) + " " + account_currency + "."); @@ -4958,29 +4966,44 @@ void CAccountProtector::CheckAllConditions() if ((!DisableSpreadLE) && (SymbolInfoInteger(Symbol(), SYMBOL_SPREAD) <= sets.intSpreadLE)) CheckOneCondition(sets.intSpreadLE, sets.boolSpreadLE, "Spread less or equal to " + IntegerToString(sets.intSpreadLE)); -// Daily profit/loss greater or equal to currency units. - if ((!DisableDailyProfitLossUnitsGE) && (daily_profit_loss_units >= sets.doubleDailyProfitLossUnitsGE)) - CheckOneCondition(sets.doubleDailyProfitLossUnitsGE, sets.boolDailyProfitLossUnitsGE, "Daily profit/loss greater or equal to " + DoubleToString(sets.doubleDailyProfitLossUnitsGE, 2) + " " + AccountInfoString(ACCOUNT_CURRENCY)); + bool CheckDailyConditions = true; + if ((DoNotDisableConditions) && (DoNotDisableActions)) // Two main circumstances that could lead to infinite attempts to do something. + { + if (((!sets.ClosePos) || ((sets.ClosePos) && (market == 0))) && // Close all, but there is nothing to close. + ((!sets.DeletePend) || ((sets.DeletePend) && (pending == 0))) && // Delete all pending, but there is nothing to delete. + ((!sets.DisAuto) || ((sets.DisAuto) && (!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)))) && // Disable AT, but it's already disabled. + (!sets.ClosePlatform) && (!sets.EnableAuto) && (!sets.CloseAllOtherCharts) && (!sets.RecaptureSnapshots)) // All other actions (except notifications should be disabled). + { + CheckDailyConditions = false; // No need to check daily conditions. + } + } + if (CheckDailyConditions) + { +// Daily profit/loss greater or equal to currency units. + if ((!DisableDailyProfitLossUnitsGE) && (daily_profit_loss_units >= sets.doubleDailyProfitLossUnitsGE)) + CheckOneCondition(sets.doubleDailyProfitLossUnitsGE, sets.boolDailyProfitLossUnitsGE, "Daily profit/loss greater or equal to " + DoubleToString(sets.doubleDailyProfitLossUnitsGE, 2) + " " + AccountInfoString(ACCOUNT_CURRENCY)); + // Daily profit/loss less or equal to currency units. - if ((!DisableDailyProfitLossUnitsLE) && (daily_profit_loss_units <= sets.doubleDailyProfitLossUnitsLE)) - CheckOneCondition(sets.doubleDailyProfitLossUnitsLE, sets.boolDailyProfitLossUnitsLE, "Daily profit/loss less or equal to " + DoubleToString(sets.doubleDailyProfitLossUnitsLE, 2) + " " + AccountInfoString(ACCOUNT_CURRENCY)); - + if ((!DisableDailyProfitLossUnitsLE) && (daily_profit_loss_units <= sets.doubleDailyProfitLossUnitsLE)) + CheckOneCondition(sets.doubleDailyProfitLossUnitsLE, sets.boolDailyProfitLossUnitsLE, "Daily profit/loss less or equal to " + DoubleToString(sets.doubleDailyProfitLossUnitsLE, 2) + " " + AccountInfoString(ACCOUNT_CURRENCY)); + // Daily profit/loss greater or equal to points. - if ((!DisableDailyProfitLossPointsGE) && (daily_profit_loss_points >= sets.intDailyProfitLossPointsGE)) - CheckOneCondition(sets.intDailyProfitLossPointsGE, sets.boolDailyProfitLossPointsGE, "Daily profit/loss greater or equal to " + IntegerToString(sets.intDailyProfitLossPointsGE)); - + if ((!DisableDailyProfitLossPointsGE) && (daily_profit_loss_points >= sets.intDailyProfitLossPointsGE)) + CheckOneCondition(sets.intDailyProfitLossPointsGE, sets.boolDailyProfitLossPointsGE, "Daily profit/loss greater or equal to " + IntegerToString(sets.intDailyProfitLossPointsGE)); + // Daily profit/loss less or equal to points. - if ((!DisableDailyProfitLossPointsLE) && (daily_profit_loss_points <= sets.intDailyProfitLossPointsLE)) - CheckOneCondition(sets.intDailyProfitLossPointsLE, sets.boolDailyProfitLossPointsLE, "Daily profit/loss less or equal to " + IntegerToString(sets.intDailyProfitLossPointsLE)); - + if ((!DisableDailyProfitLossPointsLE) && (daily_profit_loss_points <= sets.intDailyProfitLossPointsLE)) + CheckOneCondition(sets.intDailyProfitLossPointsLE, sets.boolDailyProfitLossPointsLE, "Daily profit/loss less or equal to " + IntegerToString(sets.intDailyProfitLossPointsLE)); + // Daily profit/loss greater or equal to %. - if ((!DisableDailyProfitLossPercGE) && (daily_profit_loss_perc >= sets.doubleDailyProfitLossPercGE)) - CheckOneCondition(sets.doubleDailyProfitLossPercGE, sets.boolDailyProfitLossPercGE, "Daily profit/loss greater or equal to " + DoubleToString(sets.doubleDailyProfitLossPercGE, 2) + "% of balance"); - + if ((!DisableDailyProfitLossPercGE) && (daily_profit_loss_perc >= sets.doubleDailyProfitLossPercGE)) + CheckOneCondition(sets.doubleDailyProfitLossPercGE, sets.boolDailyProfitLossPercGE, "Daily profit/loss greater or equal to " + DoubleToString(sets.doubleDailyProfitLossPercGE, 2) + "% of balance"); + // Daily profit/loss less or equal to %. - if ((!DisableDailyProfitLossPercLE) && (daily_profit_loss_perc <= sets.doubleDailyProfitLossPercLE)) - CheckOneCondition(sets.doubleDailyProfitLossPercLE, sets.boolDailyProfitLossPercLE, "Daily profit/loss less or equal to " + DoubleToString(sets.doubleDailyProfitLossPercLE, 2) + "% of balance"); + if ((!DisableDailyProfitLossPercLE) && (daily_profit_loss_perc <= sets.doubleDailyProfitLossPercLE)) + CheckOneCondition(sets.doubleDailyProfitLossPercLE, sets.boolDailyProfitLossPercLE, "Daily profit/loss less or equal to " + DoubleToString(sets.doubleDailyProfitLossPercLE, 2) + "% of balance"); + } // Number of positions is greater or equal to . if ((!DisableNumberOfPositionsGE) && (market >= sets.intNumberOfPositionsGE)) @@ -5153,7 +5176,7 @@ void CAccountProtector::Logging(string message) } else Alert("Unexpected error accessing file: ", filename, "."); } - if (!SilentLogging) Print(message); + if ((!Silent) && (!SilentLogging)) Print(message); } // Creates array of Magic numbers and updates its counter. diff --git a/MQL4/Experts/Account Protector/Defines.mqh b/MQL4/Experts/Account Protector/Defines.mqh index 2066642..2ef7b4d 100644 --- a/MQL4/Experts/Account Protector/Defines.mqh +++ b/MQL4/Experts/Account Protector/Defines.mqh @@ -1,6 +1,6 @@ //+------------------------------------------------------------------+ //| Defines.mqh | -//| Copyright © 2017-2023, EarnForex.com | +//| Copyright © 2017-2024, EarnForex.com | //| https://www.earnforex.com/ | //+------------------------------------------------------------------+ #include diff --git a/MQL5/Experts/Account Protector/Account Protector.mq5 b/MQL5/Experts/Account Protector/Account Protector.mq5 index 60b575c..0a15665 100644 --- a/MQL5/Experts/Account Protector/Account Protector.mq5 +++ b/MQL5/Experts/Account Protector/Account Protector.mq5 @@ -1,12 +1,12 @@ //+------------------------------------------------------------------+ //| Account Protector.mq5 | -//| Copyright © 2017-2023, EarnForex.com | +//| Copyright © 2017-2024, EarnForex.com | //| https://www.earnforex.com/ | //+------------------------------------------------------------------+ #property copyright "EarnForex.com" #property link "https://www.earnforex.com/metatrader-expert-advisors/Account-Protector/" -#property version "1.10" -string Version = "1.10"; +#property version "1.11" +string Version = "1.11"; #property strict #property description "Protects account balance by applying given actions when set conditions trigger." @@ -59,14 +59,16 @@ input int DelayOrderClose = 0; // DelayOrderClose: Delay in milliseconds. input bool UseTotalVolume = false; // UseTotalVolume: enable if trading with many small trades and partial position closing. input ENUM_CLOSE_TRADES CloseFirst = ENUM_CLOSE_TRADES_DEFAULT; // CloseFirst: Close which trades first? input bool BreakEvenProfitInCurrencyUnits = false; // BreakEvenProfitInCurrencyUnits: currency instead of points. +input bool EquityTrailingStopInPercentage = false; // EquityTrailingStopInPercentage: % instead of $. input group "Miscellaneous" input bool AlertOnEquityTS = false; // AlertOnEquityTS: Alert when equity trailing stop triggers? input double AdditionalFunds = 0; // AdditionalFunds: Added to balance, equity, and free margin. input string Instruments = ""; // Instruments: Default list of trading instruments for order filtering. input bool GlobalSnapshots = false; // GlobalSnapshots: AP instances share equity & margin snapshots. input int Slippage = 2; // Slippage -input string LogFileName = "log.txt"; // Log file name +input string LogFileName = "ap_log.txt"; // Log file name input string SettingsFileName = ""; // Settings file: Load custom panel settings from \Files\ folder. +input bool Silent = false; // Silent: No log output to the Experts tab. CAccountProtector ExtDialog; @@ -255,7 +257,11 @@ int OnInit() if ((!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) || (!MQLInfoInteger(MQL_TRADE_ALLOWED))) { - Alert("AutoTrading is disabled! EA will be not able to perform trading operations!"); + string where = ""; + if ((!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) && (!MQLInfoInteger(MQL_TRADE_ALLOWED))) where = "in both EA's and platform's settings"; // Both. + else if (!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) where = "in the platform's settings"; // Platform level. + else if (!MQLInfoInteger(MQL_TRADE_ALLOWED)) where = "in the EA's settings"; // EA level. + Alert("AutoTrading is disabled " + where + "! EA will be not able to perform trading operations!"); sets.ClosePos = false; sets.DeletePend = false; sets.DisAuto = false; diff --git a/MQL5/Experts/Account Protector/Account Protector.mqh b/MQL5/Experts/Account Protector/Account Protector.mqh index 2d75bbd..fc27268 100644 --- a/MQL5/Experts/Account Protector/Account Protector.mqh +++ b/MQL5/Experts/Account Protector/Account Protector.mqh @@ -1,6 +1,6 @@ //+------------------------------------------------------------------+ //| Account Protector.mqh | -//| Copyright © 2017-2023, EarnForex.com | +//| Copyright © 2017-2024, EarnForex.com | //| https://www.earnforex.com/ | //+------------------------------------------------------------------+ #include "Defines.mqh" @@ -643,7 +643,10 @@ bool CAccountProtector::CreateObjects() if (!CheckBoxCreate(m_ChkBreakEvenExtra, first_column_start, y, panel_end, y + element_height, "m_ChkBreakEvenExtra", "Breakeven extra profit value (points):")) return false; if (!EditCreate(m_EdtBreakEvenExtra, last_input_start, y, last_input_end, y + element_height, "m_EdtBreakEvenExtra", "0")) return false; y += element_height + v_spacing; - if (!CheckBoxCreate(m_ChkEquityTrailingStop, first_column_start, y, panel_end, y + element_height, "m_ChkEquityTrailingStop", "Equity trailing stop (hidden), USD:")) return false; + string ets = "Equity trailing stop (hidden), "; + if (EquityTrailingStopInPercentage) ets += "%:"; + else ets += "USD:"; + if (!CheckBoxCreate(m_ChkEquityTrailingStop, first_column_start, y, panel_end, y + element_height, "m_ChkEquityTrailingStop", ets)) return false; if (!EditCreate(m_EdtEquityTrailingStop, timer_label_start, y, last_input_end, y + element_height, "m_EdtEquityTrailingStop", "0")) return false; y += element_height + v_spacing; if (!LabelCreate(m_LblCurrentEquityStopLoss, first_column_start, y, first_column_start + normal_label_width, y + element_height, "m_LblCurrentEquityStopLoss", "Current equity stop-loss, USD: ")) return false; @@ -1171,11 +1174,12 @@ bool CAccountProtector::RefreshValues() string account_currency = AccountInfoString(ACCOUNT_CURRENCY); if (account_currency != "") { - m_ChkEquityTrailingStop.Text("Equity trailing stop (hidden), " + account_currency + ":"); + if (!EquityTrailingStopInPercentage) m_ChkEquityTrailingStop.Text("Equity trailing stop (hidden), " + account_currency + ":"); if (BreakEvenProfitInCurrencyUnits) { m_ChkBreakEven.Text("Profit value (" + account_currency + ") to set SL to breakeven:"); } + if ((sets.boolEquityTrailingStop) && (sets.doubleEquityTrailingStop > 0)) m_LblCurrentEquityStopLoss.Text("Current equity stop-loss: " + DoubleToString(sets.doubleCurrentEquityStopLoss, AccountCurrencyDigits) + " " + account_currency + "."); } if (IsANeedToContinueClosingPositions) Close_All_Positions(); @@ -1233,7 +1237,9 @@ void CAccountProtector::RefreshPanelControls() RefreshConditions(sets.boolBreakEvenExtra, sets.intBreakEvenExtra, m_ChkBreakEvenExtra, m_EdtBreakEvenExtra, 0); // Refresh equity trailing stop fields. - RefreshConditions(sets.boolEquityTrailingStop, sets.doubleEquityTrailingStop, m_ChkEquityTrailingStop, m_EdtEquityTrailingStop, AccountCurrencyDigits); + int decimal_places = AccountCurrencyDigits; // $ + if (EquityTrailingStopInPercentage) decimal_places = 2; // % + RefreshConditions(sets.boolEquityTrailingStop, sets.doubleEquityTrailingStop, m_ChkEquityTrailingStop, m_EdtEquityTrailingStop, decimal_places); string AdditionalFunds_Asterisk = ""; if (AdditionalFunds != 0) AdditionalFunds_Asterisk = "*"; @@ -2901,7 +2907,9 @@ void CAccountProtector::OnEndEditEquityTrailingStop() { sets.doubleEquityTrailingStop = ValueFromEdit; SaveSettingsOnDisk(); - m_EdtEquityTrailingStop.Text(DoubleToString(ValueFromEdit, AccountCurrencyDigits)); + int decimal_places = AccountCurrencyDigits; // $ + if (EquityTrailingStopInPercentage) decimal_places = 2; // % + m_EdtEquityTrailingStop.Text(DoubleToString(ValueFromEdit, decimal_places)); } } @@ -3787,9 +3795,14 @@ void CAccountProtector::HideShowMaximize(bool max = true) void CAccountProtector::Check_Status() { if (sets.Triggered) return; - if ((!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) || (!MQLInfoInteger(MQL_TRADE_ALLOWED))) + if (!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) { - m_LblStatus.Text("Status: Autotrading is disabled."); + m_LblStatus.Text("Status: Autotrading is disabled (platform)."); + return; + } + else if (!MQLInfoInteger(MQL_TRADE_ALLOWED)) + { + m_LblStatus.Text("Status: Autotrading is disabled (EA)."); return; } else if ((!MQLInfoInteger(MQL_DLLS_ALLOWED)) && ((sets.DisAuto) || (sets.EnableAuto))) @@ -4563,10 +4576,12 @@ void CAccountProtector::EquityTrailing() MoveAndResize(); } // If equity stop-loss should be trailed - update the stop-loss. - else if ((AE - sets.doubleEquityTrailingStop > sets.doubleCurrentEquityStopLoss) || (sets.doubleCurrentEquityStopLoss == 0)) + if (((!EquityTrailingStopInPercentage) && ((AE - sets.doubleEquityTrailingStop > sets.doubleCurrentEquityStopLoss) || (sets.doubleCurrentEquityStopLoss == 0))) || // Currency equity trailing stop should be moved. + ((EquityTrailingStopInPercentage) && ((AE * (1 - sets.doubleEquityTrailingStop / 100.0) > sets.doubleCurrentEquityStopLoss) || (sets.doubleCurrentEquityStopLoss == 0)))) // Percentage equity trailing stop should be moved. { double old_value = sets.doubleCurrentEquityStopLoss; - sets.doubleCurrentEquityStopLoss = AE - sets.doubleEquityTrailingStop; + if (!EquityTrailingStopInPercentage) sets.doubleCurrentEquityStopLoss = AE - sets.doubleEquityTrailingStop; // $ + else sets.doubleCurrentEquityStopLoss = AE * (1 - sets.doubleEquityTrailingStop / 100.0); // % SaveSettingsOnDisk(); string account_currency = AccountInfoString(ACCOUNT_CURRENCY); if (account_currency != "") m_LblCurrentEquityStopLoss.Text("Current equity stop-loss: " + DoubleToString(sets.doubleCurrentEquityStopLoss, AccountCurrencyDigits) + " " + account_currency + "."); @@ -5130,29 +5145,44 @@ void CAccountProtector::CheckAllConditions() if ((!DisableSpreadLE) && (SymbolInfoInteger(Symbol(), SYMBOL_SPREAD) <= sets.intSpreadLE)) CheckOneCondition(sets.intSpreadLE, sets.boolSpreadLE, "Spread less or equal to " + IntegerToString(sets.intSpreadLE)); - // Daily profit/loss greater or equal to currency units. - if ((!DisableDailyProfitLossUnitsGE) && (daily_profit_loss_units >= sets.doubleDailyProfitLossUnitsGE)) - CheckOneCondition(sets.doubleDailyProfitLossUnitsGE, sets.boolDailyProfitLossUnitsGE, "Daily profit/loss greater or equal to " + DoubleToString(sets.doubleDailyProfitLossUnitsGE, 2) + " " + AccountInfoString(ACCOUNT_CURRENCY)); - - // Daily profit/loss less or equal to currency units. - if ((!DisableDailyProfitLossUnitsLE) && (daily_profit_loss_units <= sets.doubleDailyProfitLossUnitsLE)) - CheckOneCondition(sets.doubleDailyProfitLossUnitsLE, sets.boolDailyProfitLossUnitsLE, "Daily profit/loss less or equal to " + DoubleToString(sets.doubleDailyProfitLossUnitsLE, 2) + " " + AccountInfoString(ACCOUNT_CURRENCY)); - - // Daily profit/loss greater or equal to points. - if ((!DisableDailyProfitLossPointsGE) && (daily_profit_loss_points >= sets.intDailyProfitLossPointsGE)) - CheckOneCondition(sets.intDailyProfitLossPointsGE, sets.boolDailyProfitLossPointsGE, "Daily profit/loss greater or equal to " + IntegerToString(sets.intDailyProfitLossPointsGE)); - - // Daily profit/loss less or equal to points. - if ((!DisableDailyProfitLossPointsLE) && (daily_profit_loss_points <= sets.intDailyProfitLossPointsLE)) - CheckOneCondition(sets.intDailyProfitLossPointsLE, sets.boolDailyProfitLossPointsLE, "Daily profit/loss less or equal to " + IntegerToString(sets.intDailyProfitLossPointsLE)); - - // Daily profit/loss greater or equal to %. - if ((!DisableDailyProfitLossPercGE) && (daily_profit_loss_perc >= sets.doubleDailyProfitLossPercGE)) - CheckOneCondition(sets.doubleDailyProfitLossPercGE, sets.boolDailyProfitLossPercGE, "Daily profit/loss greater or equal to " + DoubleToString(sets.doubleDailyProfitLossPercGE, 2) + "% of balance"); + bool CheckDailyConditions = true; + if ((DoNotDisableConditions) && (DoNotDisableActions)) // Two main circumstances that could lead to infinite attempts to do something. + { + if (((!sets.ClosePos) || ((sets.ClosePos) && (market == 0))) && // Close all, but there is nothing to close. + ((!sets.DeletePend) || ((sets.DeletePend) && (pending == 0))) && // Delete all pending, but there is nothing to delete. + ((!sets.DisAuto) || ((sets.DisAuto) && (!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)))) && // Disable AT, but it's already disabled. + (!sets.ClosePlatform) && (!sets.EnableAuto) && (!sets.CloseAllOtherCharts) && (!sets.RecaptureSnapshots)) // All other actions (except notifications should be disabled). + { + CheckDailyConditions = false; // No need to check daily conditions. + } + } - // Daily profit/loss less or equal to %. - if ((!DisableDailyProfitLossPercLE) && (daily_profit_loss_perc <= sets.doubleDailyProfitLossPercLE)) - CheckOneCondition(sets.doubleDailyProfitLossPercLE, sets.boolDailyProfitLossPercLE, "Daily profit/loss less or equal to " + DoubleToString(sets.doubleDailyProfitLossPercLE, 2) + "% of balance"); + if (CheckDailyConditions) + { + // Daily profit/loss greater or equal to currency units. + if ((!DisableDailyProfitLossUnitsGE) && (daily_profit_loss_units >= sets.doubleDailyProfitLossUnitsGE)) + CheckOneCondition(sets.doubleDailyProfitLossUnitsGE, sets.boolDailyProfitLossUnitsGE, "Daily profit/loss greater or equal to " + DoubleToString(sets.doubleDailyProfitLossUnitsGE, 2) + " " + AccountInfoString(ACCOUNT_CURRENCY)); + + // Daily profit/loss less or equal to currency units. + if ((!DisableDailyProfitLossUnitsLE) && (daily_profit_loss_units <= sets.doubleDailyProfitLossUnitsLE)) + CheckOneCondition(sets.doubleDailyProfitLossUnitsLE, sets.boolDailyProfitLossUnitsLE, "Daily profit/loss less or equal to " + DoubleToString(sets.doubleDailyProfitLossUnitsLE, 2) + " " + AccountInfoString(ACCOUNT_CURRENCY)); + + // Daily profit/loss greater or equal to points. + if ((!DisableDailyProfitLossPointsGE) && (daily_profit_loss_points >= sets.intDailyProfitLossPointsGE)) + CheckOneCondition(sets.intDailyProfitLossPointsGE, sets.boolDailyProfitLossPointsGE, "Daily profit/loss greater or equal to " + IntegerToString(sets.intDailyProfitLossPointsGE)); + + // Daily profit/loss less or equal to points. + if ((!DisableDailyProfitLossPointsLE) && (daily_profit_loss_points <= sets.intDailyProfitLossPointsLE)) + CheckOneCondition(sets.intDailyProfitLossPointsLE, sets.boolDailyProfitLossPointsLE, "Daily profit/loss less or equal to " + IntegerToString(sets.intDailyProfitLossPointsLE)); + + // Daily profit/loss greater or equal to %. + if ((!DisableDailyProfitLossPercGE) && (daily_profit_loss_perc >= sets.doubleDailyProfitLossPercGE)) + CheckOneCondition(sets.doubleDailyProfitLossPercGE, sets.boolDailyProfitLossPercGE, "Daily profit/loss greater or equal to " + DoubleToString(sets.doubleDailyProfitLossPercGE, 2) + "% of balance"); + + // Daily profit/loss less or equal to %. + if ((!DisableDailyProfitLossPercLE) && (daily_profit_loss_perc <= sets.doubleDailyProfitLossPercLE)) + CheckOneCondition(sets.doubleDailyProfitLossPercLE, sets.boolDailyProfitLossPercLE, "Daily profit/loss less or equal to " + DoubleToString(sets.doubleDailyProfitLossPercLE, 2) + "% of balance"); + } // Number of positions is greater or equal to . if ((!DisableNumberOfPositionsGE) && (market >= sets.intNumberOfPositionsGE)) @@ -5326,7 +5356,7 @@ void CAccountProtector::Logging(string message) } else Alert("Unexpected error accessing file: ", filename, "."); } - if (!SilentLogging) Print(message); + if ((!Silent) && (!SilentLogging)) Print(message); } // Creates array of Magic numbers and updates its counter. diff --git a/MQL5/Experts/Account Protector/Defines.mqh b/MQL5/Experts/Account Protector/Defines.mqh index e622f74..1e376f3 100644 --- a/MQL5/Experts/Account Protector/Defines.mqh +++ b/MQL5/Experts/Account Protector/Defines.mqh @@ -1,6 +1,6 @@ //+------------------------------------------------------------------+ //| Defines.mqh | -//| Copyright © 2017-2023, EarnForex.com | +//| Copyright © 2017-2024, EarnForex.com | //| https://www.earnforex.com/ | //+------------------------------------------------------------------+ #include