Skip to content

Commit dbde5d7

Browse files
author
EarnForex
authored
1.04
1. Added an option to close trades in the asynchronous mode in MT5. 2. Added input parameters to filter trades by magic numbers. 3. Changed the messages about disabled auto-trading to specify whether it is disabled in the platform or in the EA. 4. Changed how the EA works when Always enforce schedule is off and the WaitForNoPositions input parameter is set to true. It will now proceed to toggle auto-trading with a schedule period if it finds that there are no more positions after the period starts. 5. Fixed a crashing error that could occur when unticking the Always enforce schedule checkbox with an empty schedule.
1 parent c5a07da commit dbde5d7

File tree

4 files changed

+254
-34
lines changed

4 files changed

+254
-34
lines changed

MQL4/Experts/AutoTrading Scheduler/AutoTrading Scheduler.mq4

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#property copyright "EarnForex.com"
22
#property link "https://www.earnforex.com/metatrader-expert-advisors/AutoTrading-Scheduler/"
3-
#property version "1.03"
4-
string Version = "1.03";
3+
#property version "1.04"
4+
string Version = "1.04";
55
#property strict
66

77
#property description "Creates a weekly schedule when AutoTrading is enabled."
@@ -34,10 +34,13 @@ input int Slippage = 2; // Slippage
3434
input string ScheduleFile = ""; // ScheduleFile (optional)
3535
input bool WaitForNoPositions = false; // Switch A/T off only when there are no open positions?
3636
input bool WaitForNoOrders = false; // Switch A/T off only when there are no pending orders?
37+
input string MagicNumbersFilter = ""; // Magic numbers filter
38+
input bool IgnoreMagicNumbers = false; // Ignore trades with above-listed magic numbers
3739

3840
CScheduler Panel;
3941

4042
int DeinitializationReason = -1;
43+
long MagicNumbers_array[];
4144

4245
//+------------------------------------------------------------------+
4346
//| Initialization function |
@@ -77,6 +80,8 @@ int OnInit()
7780
Panel.RefreshValues();
7881
}
7982

83+
ProcessMagicNumbers();
84+
8085
EventSetTimer(1);
8186

8287
return INIT_SUCCEEDED;
@@ -162,4 +167,54 @@ void OnTimer()
162167
Panel.CheckTimer();
163168
ChartRedraw();
164169
}
170+
171+
void ProcessMagicNumbers()
172+
{
173+
if (MagicNumbersFilter == "")
174+
{
175+
ArrayFree(MagicNumbers_array);
176+
return;
177+
}
178+
179+
string magic = MagicNumbersFilter;
180+
int length = StringLen(magic);
181+
182+
// Only allowed characters are digits, commas, spaces, and semicolons. At least one digit should be present.
183+
for (int i = 0; i < length; i++)
184+
{
185+
if (((magic[i] < '0') || (magic[i] > '9')) && (magic[i] != ' ') && (magic[i] != ',') && (magic[i] != ';'))
186+
{
187+
// Wrong character found.
188+
int replaced_characters = StringReplace(magic, CharToString((uchar)magic[i]), "");
189+
length -= replaced_characters;
190+
i--;
191+
}
192+
}
193+
194+
if (magic == "") return;
195+
196+
// Split string with Magic numbers using all separators, getting an array with clean Magic numbers.
197+
string result[];
198+
int n = StringSplit(magic, StringGetCharacter(",", 0), result);
199+
for (int i = 0; i < n; i++)
200+
{
201+
string second_result[];
202+
int m = StringSplit(result[i], StringGetCharacter(";", 0), second_result);
203+
for (int j = 0; j < m; j++)
204+
{
205+
string third_result[];
206+
// Third result, at this point, holds all the magic numbers (strings) even if there was only one.
207+
// The problem is that it will vanish on next cycle iteration.
208+
int l = StringSplit(second_result[j], StringGetCharacter(" ", 0), third_result);
209+
210+
// Fill MagicNumbers_array.
211+
for (int k = 0; k < l; k++)
212+
{
213+
if (third_result[k] == "") continue;
214+
ArrayResize(MagicNumbers_array, ArraySize(MagicNumbers_array) + 1, 10);
215+
MagicNumbers_array[ArraySize(MagicNumbers_array) - 1] = StringToInteger(third_result[k]);
216+
}
217+
}
218+
}
219+
}
165220
//+------------------------------------------------------------------+

MQL4/Experts/AutoTrading Scheduler/AutoTrading Scheduler.mqh

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ private:
6767
void Notify(const int count, const bool enable_or_disable);
6868
bool ExistsPosition();
6969
bool ExistsOrder();
70+
bool CheckFilterMagic(const long magic);
7071

7172
// Event handlers
7273
void OnChangeChkClosePos();
@@ -562,7 +563,7 @@ void CScheduler::ProcessWeeklySchedule()
562563
Schedule.Sort(0); // Sort schedule by time in ascending mode.
563564

564565
// Check if the previous week's last switch might be needed. It might be needed to know whether to toggle autotrading when we are inside the first period of the current week in non-enforced mode.
565-
if (sets.Enforce == false) // Only in non-enforced mode.
566+
if ((sets.Enforce == false) && (Schedule.Total() > 0)) // Only in non-enforced mode and if some schedule is given.
566567
{
567568
CTimeStamp* ts = Schedule.GetFirstNode();
568569
datetime current_time;
@@ -1192,16 +1193,16 @@ void CScheduler::CheckTimer()
11921193
if (StartedToggling) return;
11931194
StartedToggling = true;
11941195
sets.LastToggleTime = time;
1195-
if (((WaitForNoPositions) && (ExistsPosition())) || ((WaitForNoOrders) && (ExistsOrder())))
1196-
{
1197-
StartedToggling = false;
1198-
return;
1199-
}
12001196
int n_closed = 0;
12011197
if (sets.ClosePos)
12021198
{
12031199
n_closed = Close_All_Trades();
12041200
}
1201+
if (((WaitForNoPositions) && (ExistsPosition())) || ((WaitForNoOrders) && (ExistsOrder())))
1202+
{
1203+
StartedToggling = false;
1204+
return;
1205+
}
12051206
if (IsANeedToContinueClosingTrades) Print("Not all trades have been closed! Disabling AutoTrading anyway.");
12061207
Toggle_AutoTrading();
12071208
Notify(n_closed, false);
@@ -1308,9 +1309,9 @@ int CScheduler::Close_All_Trades()
13081309

13091310
if ((!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) || (!TerminalInfoInteger(TERMINAL_CONNECTED)) || (!MQLInfoInteger(MQL_TRADE_ALLOWED)))
13101311
{
1311-
if (!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) Print("AutoTrading disabled!");
1312+
if (!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) Print("AutoTrading disabled (platform)!");
13121313
if (!TerminalInfoInteger(TERMINAL_CONNECTED)) Print("No connection!");
1313-
if (!MQLInfoInteger(MQL_TRADE_ALLOWED)) Print("Trade not allowed!");
1314+
if (!MQLInfoInteger(MQL_TRADE_ALLOWED)) Print("AutoTrading disabled (EA)!");
13141315
return 0;
13151316
}
13161317

@@ -1323,8 +1324,11 @@ int CScheduler::Close_All_Trades()
13231324
error = GetLastError();
13241325
Print("AutoTrading Scheduler: OrderSelect failed " + IntegerToString(error) + ".");
13251326
IsANeedToContinueClosingTrades = true;
1327+
continue;
13261328
}
1327-
else if (SymbolInfoInteger(OrderSymbol(), SYMBOL_TRADE_MODE) == SYMBOL_TRADE_MODE_DISABLED)
1329+
if (CheckFilterMagic(OrderMagicNumber())) continue; // Skip if the magic number filter says to.
1330+
1331+
if (SymbolInfoInteger(OrderSymbol(), SYMBOL_TRADE_MODE) == SYMBOL_TRADE_MODE_DISABLED)
13281332
{
13291333
Print("AutoTrading Scheduler: Trading disabled by broker for symbol " + OrderSymbol() + ".");
13301334
IsANeedToContinueClosingTrades = true;
@@ -1351,6 +1355,7 @@ int CScheduler::Close_All_Trades()
13511355
}
13521356
else
13531357
{
1358+
if (CheckFilterMagic(OrderMagicNumber())) continue; // Skip if the magic number filter says to.
13541359
AreAllTradesEliminated = false;
13551360
break;
13561361
}
@@ -1462,6 +1467,7 @@ bool CScheduler::ExistsPosition()
14621467
{
14631468
if (OrderSelect(i, SELECT_BY_POS))
14641469
{
1470+
if (CheckFilterMagic(OrderMagicNumber())) continue; // Skip if the magic number filter says to.
14651471
if ((OrderType() == OP_BUY) || (OrderType() == OP_SELL)) return true;
14661472
}
14671473
}
@@ -1476,6 +1482,7 @@ bool CScheduler::ExistsOrder()
14761482
{
14771483
if (OrderSelect(i, SELECT_BY_POS))
14781484
{
1485+
if (CheckFilterMagic(OrderMagicNumber())) continue; // Skip if the magic number filter says to.
14791486
if ((OrderType() != OP_BUY) && (OrderType() != OP_SELL)) return true;
14801487
}
14811488
}
@@ -1499,6 +1506,24 @@ int CScheduler::AddTimeStamp(CTimeStamp *new_node)
14991506
return Schedule.Total(); // Return the number of nodes after adding the new one to the list.
15001507
}
15011508

1509+
// Returns true if order should be filtered out based on its magic number and filter settings.
1510+
bool CScheduler::CheckFilterMagic(const long magic)
1511+
{
1512+
int total = ArraySize(MagicNumbers_array);
1513+
if (total < 1) return false; // Empty array - don't filter.
1514+
1515+
for (int i = 0; i < total; i++)
1516+
{
1517+
// Skip order if its magic number is in the array, and "Ignore" option is turned on.
1518+
if ((magic == MagicNumbers_array[i]) && (IgnoreMagicNumbers)) return true;
1519+
// Do not skip order if its magic number is in the array, and "Ignore" option is turned off.
1520+
if ((magic == MagicNumbers_array[i]) && (!IgnoreMagicNumbers)) return false;
1521+
}
1522+
1523+
if (IgnoreMagicNumbers) return false; // If not found in the array and should ignore listed magic numbers, then default ruling is - don't filter out this order.
1524+
else return true;
1525+
}
1526+
15021527
// Returns true if weekday is actually a date for a long-term schedule.
15031528
bool IsWeekdayADate(const string wd)
15041529
{

MQL5/Experts/AutoTrading Scheduler/AutoTrading Scheduler.mq5

Lines changed: 58 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#property copyright "EarnForex.com"
22
#property link "https://www.earnforex.com/metatrader-expert-advisors/AutoTrading-Scheduler/"
3-
#property version "1.03"
4-
string Version = "1.03";
3+
#property version "1.04"
4+
string Version = "1.04";
55
#property strict
66

77
#property description "Creates a weekly schedule when AutoTrading is enabled."
@@ -35,10 +35,14 @@ input int Slippage = 2; // Slippage
3535
input string ScheduleFile = ""; // ScheduleFile (optional)
3636
input bool WaitForNoPositions = false; // Switch A/T off only when there are no open positions?
3737
input bool WaitForNoOrders = false; // Switch A/T off only when there are no pending orders?
38+
input string MagicNumbersFilter = ""; // Magic numbers filter
39+
input bool IgnoreMagicNumbers = false; // Ignore trades with above-listed magic numbers
40+
input bool AsyncMode = false; // AsyncMode: If true, trades are closed in async mode
3841

3942
CScheduler Panel;
4043

4144
int DeinitializationReason = -1;
45+
long MagicNumbers_array[];
4246

4347
//+------------------------------------------------------------------+
4448
//| Initialization function |
@@ -78,6 +82,8 @@ int OnInit()
7882
Panel.RefreshValues();
7983
}
8084

85+
ProcessMagicNumbers();
86+
8187
EventSetTimer(1);
8288

8389
return INIT_SUCCEEDED;
@@ -164,4 +170,54 @@ void OnTimer()
164170
Panel.CheckTimer();
165171
ChartRedraw();
166172
}
173+
174+
void ProcessMagicNumbers()
175+
{
176+
if (MagicNumbersFilter == "")
177+
{
178+
ArrayFree(MagicNumbers_array);
179+
return;
180+
}
181+
182+
string magic = MagicNumbersFilter;
183+
int length = StringLen(magic);
184+
185+
// Only allowed characters are digits, commas, spaces, and semicolons. At least one digit should be present.
186+
for (int i = 0; i < length; i++)
187+
{
188+
if (((magic[i] < '0') || (magic[i] > '9')) && (magic[i] != ' ') && (magic[i] != ',') && (magic[i] != ';'))
189+
{
190+
// Wrong character found.
191+
int replaced_characters = StringReplace(magic, CharToString((uchar)magic[i]), "");
192+
length -= replaced_characters;
193+
i--;
194+
}
195+
}
196+
197+
if (magic == "") return;
198+
199+
// Split string with Magic numbers using all separators, getting an array with clean Magic numbers.
200+
string result[];
201+
int n = StringSplit(magic, StringGetCharacter(",", 0), result);
202+
for (int i = 0; i < n; i++)
203+
{
204+
string second_result[];
205+
int m = StringSplit(result[i], StringGetCharacter(";", 0), second_result);
206+
for (int j = 0; j < m; j++)
207+
{
208+
string third_result[];
209+
// Third result, at this point, holds all the magic numbers (strings) even if there was only one.
210+
// The problem is that it will vanish on next cycle iteration.
211+
int l = StringSplit(second_result[j], StringGetCharacter(" ", 0), third_result);
212+
213+
// Fill MagicNumbers_array.
214+
for (int k = 0; k < l; k++)
215+
{
216+
if (third_result[k] == "") continue;
217+
ArrayResize(MagicNumbers_array, ArraySize(MagicNumbers_array) + 1, 10);
218+
MagicNumbers_array[ArraySize(MagicNumbers_array) - 1] = StringToInteger(third_result[k]);
219+
}
220+
}
221+
}
222+
}
167223
//+------------------------------------------------------------------+

0 commit comments

Comments
 (0)