add supports for Symbol Restrictions ...

This commit is contained in:
2025-05-09 03:43:56 +03:30
parent c7f14e90a1
commit 87c6321dcb
2 changed files with 506 additions and 72 deletions
+13 -20
View File
@@ -56,8 +56,10 @@ input group "Management";
input bool eaAllowTrade = true; // Allow Trade on Signals input bool eaAllowTrade = true; // Allow Trade on Signals
input bool eaAllowLongs = true; // Allow Long Trades input bool eaAllowLongs = true; // Allow Long Trades
input bool eaAllowShorts = true; // Allow Short Trades input bool eaAllowShorts = true; // Allow Short Trades
input int eaMaxAllowedTradesPerDay = 3; // Max Allowed Trades per Day input ENUM_XCAEA_TRADE_RESTRICTION_PERIOD eaRestrictionsPeriod = XCAEA_TRADE_RESTRICATION_DAILY; // Trade Restrictions Period
input int eaMaxAllowedSLsPerDay = 2; // Max Allowed SL(s) per Day input int eaMaxAllowedTPs = 2; // Max Allowed TP(s) per Day
input int eaMaxAllowedSLs = 2; // Max Allowed SL(s) per Day
input int eaMaxAllowedTrades = 3; // Max Allowed Trades per Day
input string eaSessionStartTime = ""; // Trade Start Time input string eaSessionStartTime = ""; // Trade Start Time
input string eaSessionEndTime = ""; // Trade End Time input string eaSessionEndTime = ""; // Trade End Time
input int eaMaxAllowedPositions = 5; // Max Allowed Same Time Trades input int eaMaxAllowedPositions = 5; // Max Allowed Same Time Trades
@@ -662,13 +664,13 @@ void InitRequirements()
); );
// //
// // Setting Trade Restrictions ...
// eaTradeManager.SetTradeRestrictions(
// eaRestrictionsPeriod,
// eaMaxAllowedTradesPerDay eaMaxAllowedTPs,
// eaMaxAllowedSLsPerDay eaMaxAllowedSLs,
// eaSessionStartTime eaMaxAllowedTrades //
// eaSessionEndTime );
// //
// EA Signaller ... // EA Signaller ...
@@ -711,16 +713,8 @@ void HandleTimeReport()
// //
// Daily Report .... // Daily Report ....
bool isNewDay = eaTimeTracker.IsNewDay(); if (eaReportNewDays &&
if (isNewDay) eaTimeTracker.IsNewDay())
{
//
// Handle New Day on Trade Manager ...
eaTradeManager.HandleNewDay();
//
// Reporting New Day if Reuired ...
if (eaReportNewDays)
{ {
// //
string msg = "New Day ..."; string msg = "New Day ...";
@@ -728,7 +722,6 @@ void HandleTimeReport()
// //
eaAlert.Alert(msg); eaAlert.Alert(msg);
} }
}
// //
// Hourly Report .... // Hourly Report ....
+482 -41
View File
@@ -30,6 +30,29 @@
// //
// Definitions ... // Definitions ...
//
enum ENUM_XCAEA_TRADE_RESTRICTION_PERIOD
{
XCAEA_TRADE_RESTRICATION_NONE, // None
XCAEA_TRADE_RESTRICATION_HOURLY, // Per Hour
XCAEA_TRADE_RESTRICATION_DAILY, // Per Day
XCAEA_TRADE_RESTRICATION_WEEKLY, // Per Week
XCAEA_TRADE_RESTRICATION_MONTHLY, // Per Month
};
//
string ToString(ENUM_XCAEA_TRADE_RESTRICTION_PERIOD value)
{
//
string result = NULL;
//
result = EnumToString(value);
//
return result;
}
// //
enum ENUM_XCAEA_TRADE_FINALIZATION enum ENUM_XCAEA_TRADE_FINALIZATION
{ {
@@ -52,6 +75,95 @@ string ToString(ENUM_XCAEA_TRADE_FINALIZATION value)
return result; return result;
} }
//
struct XCAEASymbolInfo
{
//
string symbol;
//
int longs;
int shorts;
//
int trades;
//
int losses;
int profits;
//
int managedSLs;
int managedTPs;
int managedTrades;
//
// Constructor ...
XCAEASymbolInfo()
{
Clean();
}
//
// Tools ...
//
// Cleanup ...
void Clean()
{
//
symbol = NULL;
//
longs = 0;
shorts = 0;
//
trades = 0;
//
losses = 0;
profits = 0;
//
managedSLs = 0;
managedTPs = 0;
managedTrades = 0;
//
ZeroMemory(this);
}
//
// Validate ...
bool IsValid()
{
//
bool result = false;
//
result = IsValid(symbol);
//
return result;
}
//
bool IsSameAs(XCAEASymbolInfo &item)
{
//
bool result = false;
//
result = IsValid() &&
item.IsValid() &&
symbol == item.symbol;
//
return result;
}
};
// //
struct XCAEATrade struct XCAEATrade
{ {
@@ -305,6 +417,7 @@ class XCXCAEATradeManager : public XCBaseAlert
XCTrade *trader; XCTrade *trader;
bool drawSignal; bool drawSignal;
XCPOIDrawer *drawer; XCPOIDrawer *drawer;
XTimeTracker timeTracker;
XCXCAEADataCollector *collector; XCXCAEADataCollector *collector;
// //
@@ -324,6 +437,12 @@ class XCXCAEATradeManager : public XCBaseAlert
allowLongs = true; allowLongs = true;
allowShorts = true; allowShorts = true;
//
maxAllowedTPs = 0;
maxAllowedSLs = 0;
maxAllowedTrades = 0;
restrictionsPeriod = XCAEA_TRADE_RESTRICATION_NONE;
// //
reportTrades = true; reportTrades = true;
reportSignals = true; reportSignals = true;
@@ -352,6 +471,9 @@ class XCXCAEATradeManager : public XCBaseAlert
// //
Clean(trades); Clean(trades);
//
timeTracker.Clean();
// //
ZeroMemory(trader); ZeroMemory(trader);
ZeroMemory(drawer); ZeroMemory(drawer);
@@ -419,6 +541,27 @@ class XCXCAEATradeManager : public XCBaseAlert
allowShorts = _allowShorts; allowShorts = _allowShorts;
} }
//
void SetTradeRestrictions(
ENUM_XCAEA_TRADE_RESTRICTION_PERIOD _period,
int _maxAllowedTPs,
int _maxAllowedSLs,
int _maxAllowedTrades //
)
{
//
// Normalizing Args ...
_maxAllowedTPs = NormalizeInt(_maxAllowedTPs, 0);
_maxAllowedSLs = NormalizeInt(_maxAllowedSLs, 0);
_maxAllowedTrades = NormalizeInt(_maxAllowedTrades, 0);
//
restrictionsPeriod = _period;
maxAllowedTPs = _maxAllowedTPs;
maxAllowedSLs = _maxAllowedSLs;
maxAllowedTrades = _maxAllowedTrades;
}
// //
// Tools ... // Tools ...
@@ -428,6 +571,11 @@ class XCXCAEATradeManager : public XCBaseAlert
void Manage() void Manage()
{ {
// //
// Handle Restrictions ...
HandleRestrictions();
//
// Check Contains Trades for Managing ...
bool has = HasChild(trades); bool has = HasChild(trades);
if (!has) if (!has)
{ {
@@ -435,6 +583,7 @@ class XCXCAEATradeManager : public XCBaseAlert
} }
// //
// Update Required Infos of Trades ...
int count = ArraySize(trades); int count = ArraySize(trades);
for (int i = 0; i < count; i++) for (int i = 0; i < count; i++)
{ {
@@ -464,7 +613,7 @@ class XCXCAEATradeManager : public XCBaseAlert
} }
// //
// After Update All Trades we can Do Protection ... // Do Trade Protection ...
Protect(); Protect();
} }
@@ -823,13 +972,56 @@ class XCXCAEATradeManager : public XCBaseAlert
return result; return result;
} }
//
// Check Symbol Info Exists or not ...
int symbolIDX = -1;
bool isSymbolExists = FindSymbolIndex(
symbolIDX,
signal.symbol //
);
// //
// TODO: Complete this ... // TODO: Complete this ...
// Implementing Trade Session Validating ... // Implementing Trade Session Validating ...
// //
// TODO: Complete this ...
// Implementing Trade Permissions Based on SL(s) Count ... // Implementing Trade Permissions Based on SL(s) Count ...
bool hasRestrictions = restrictionsPeriod != XCAEA_TRADE_RESTRICATION_NONE;
if (hasRestrictions)
{
//
// Only Can Check Restrictions when
// Symbol Info Exists ...
if (isSymbolExists)
{
//
bool isTPAllowed = maxAllowedTPs == 0
? true
: symbols[symbolIDX].managedTPs < maxAllowedTPs;
bool isSLAllowed = maxAllowedSLs == 0
? true
: symbols[symbolIDX].managedSLs < maxAllowedSLs;
bool isTradeAllowed = maxAllowedTrades == 0
? true
: symbols[symbolIDX].managedTrades < maxAllowedTrades;
//
result = isTPAllowed &&
isSLAllowed &&
isTradeAllowed;
}
//
// Report Error ...
if (!result)
{
//
executionResult = X_SIGNAL_EXECUTION_FAILED_MAX_REACHED;
//
return result;
}
}
// //
return result; return result;
@@ -914,6 +1106,7 @@ class XCXCAEATradeManager : public XCBaseAlert
if (result) if (result)
{ {
// //
// Draw Signal ...
if (drawSignal) if (drawSignal)
{ {
// //
@@ -933,6 +1126,30 @@ class XCXCAEATradeManager : public XCBaseAlert
} }
// //
// Create Symbol Info Struct ...
XCAEASymbolInfo iSymbolInfo;
//
iSymbolInfo.trades = 1;
iSymbolInfo.managedTrades = 1;
iSymbolInfo.symbol = signal.symbol;
//
bool isLong = IsLong(signal.type);
if (isLong)
{
iSymbolInfo.longs = 1;
}
else
{
iSymbolInfo.shorts = 1;
}
//
AddOrUpdateSymbolInfo(iSymbolInfo);
//
// Create Trade Struct ...
XCAEATrade iTrade; XCAEATrade iTrade;
// //
@@ -984,10 +1201,6 @@ class XCXCAEATradeManager : public XCBaseAlert
trades[idx].finalizedAt = TimeCurrent(); trades[idx].finalizedAt = TimeCurrent();
trades[idx].finalize = XCAEA_TRADE_FINAL_TP; trades[idx].finalize = XCAEA_TRADE_FINAL_TP;
//
tpCount++;
managedTPCount++;
// //
// Save Trade ... // Save Trade ...
Save(trades[idx]); Save(trades[idx]);
@@ -997,6 +1210,20 @@ class XCXCAEATradeManager : public XCBaseAlert
string prefix = "TP: " + ToString(trades[idx].profit); string prefix = "TP: " + ToString(trades[idx].profit);
HandleReportBalance(prefix); HandleReportBalance(prefix);
//
// Handle Symbol Info ...
//
XCAEASymbolInfo iSymbolInfo;
//
iSymbolInfo.profits = 1;
iSymbolInfo.managedTPs = 1;
iSymbolInfo.symbol = trades[idx].signal.symbol;
//
AddOrUpdateSymbolInfo(iSymbolInfo);
// //
RemoveTrade(idx); RemoveTrade(idx);
} }
@@ -1027,10 +1254,6 @@ class XCXCAEATradeManager : public XCBaseAlert
trades[idx].finalizedAt = TimeCurrent(); trades[idx].finalizedAt = TimeCurrent();
trades[idx].finalize = XCAEA_TRADE_FINAL_SL; trades[idx].finalize = XCAEA_TRADE_FINAL_SL;
//
slCount++;
managedSLCount++;
// //
// Save Trade ... // Save Trade ...
Save(trades[idx]); Save(trades[idx]);
@@ -1040,6 +1263,33 @@ class XCXCAEATradeManager : public XCBaseAlert
string prefix = "SL: " + ToString(trades[idx].profit); string prefix = "SL: " + ToString(trades[idx].profit);
HandleReportBalance(prefix); HandleReportBalance(prefix);
//
// Handle Symbol Info ...
//
bool isInProfit = trades[idx].profit > 0;
//
XCAEASymbolInfo iSymbolInfo;
//
if (isInProfit)
{
//
iSymbolInfo.profits = 1;
iSymbolInfo.managedTPs = 1;
}
else
{
//
iSymbolInfo.losses = 1;
iSymbolInfo.managedSLs = 1;
}
iSymbolInfo.symbol = trades[idx].signal.symbol;
//
AddOrUpdateSymbolInfo(iSymbolInfo);
// //
RemoveTrade(idx); RemoveTrade(idx);
} }
@@ -1076,20 +1326,6 @@ class XCXCAEATradeManager : public XCBaseAlert
? XCAEA_TRADE_FINAL_CLOSE_IN_PROFIT ? XCAEA_TRADE_FINAL_CLOSE_IN_PROFIT
: XCAEA_TRADE_FINAL_CLOSE_IN_LOSE; : XCAEA_TRADE_FINAL_CLOSE_IN_LOSE;
//
if (isInProfit)
{
//
tpCount++;
managedTPCount++;
}
else
{
//
slCount++;
managedSLCount++;
}
// //
// Save Trade ... // Save Trade ...
Save(trades[idx]); Save(trades[idx]);
@@ -1104,6 +1340,30 @@ class XCXCAEATradeManager : public XCBaseAlert
ToString(trades[idx].profit); ToString(trades[idx].profit);
HandleReportBalance(prefix); HandleReportBalance(prefix);
//
// Handle Symbol Info ...
//
XCAEASymbolInfo iSymbolInfo;
//
if (isInProfit)
{
//
iSymbolInfo.profits = 1;
iSymbolInfo.managedTPs = 1;
}
else
{
//
iSymbolInfo.losses = 1;
iSymbolInfo.managedSLs = 1;
}
iSymbolInfo.symbol = trades[idx].signal.symbol;
//
AddOrUpdateSymbolInfo(iSymbolInfo);
// //
RemoveTrade(idx); RemoveTrade(idx);
} }
@@ -1114,15 +1374,6 @@ class XCXCAEATradeManager : public XCBaseAlert
{ {
} }
/**
* Handle New Day ...
*/
void HandleNewDay()
{
//
// Clean Managed SL(s) and TP(s) and Positions ...
}
/** /**
* Find Executed Trade by Providing Position Ticket ... * Find Executed Trade by Providing Position Ticket ...
* *
@@ -1381,6 +1632,197 @@ class XCXCAEATradeManager : public XCBaseAlert
return result; return result;
} }
//
// Symbol Info ...
//
bool FindSymbolIndex(
int &index,
XCAEASymbolInfo &item //
)
{
//
bool result = false;
//
index = -1;
//
result = item.IsValid();
if (!result)
{
return result;
}
//
result = HasChild(symbols);
if (!result)
{
return result;
}
//
index = FindIndex(
item,
symbols //
);
//
result = IsValidIndex(index);
//
return result;
}
//
bool FindSymbolIndex(
int &index,
string symbol //
)
{
//
bool result = false;
//
index = -1;
//
result = IsValid(symbol) &&
HasChild(symbols);
if (!result)
{
return result;
}
//
int count = ArraySize(symbols);
for (int i = 0; i < count; i++)
{
//
result = symbols[i].symbol == symbol;
if (result)
{
//
index = i;
break;
}
}
//
result = IsValidIndex(index);
//
return result;
}
//
void AddOrUpdateSymbolInfo(XCAEASymbolInfo &item)
{
//
bool has = item.IsValid();
if (!has)
{
return;
}
//
int index = -1;
bool isExists = FindSymbolIndex(
index,
item //
);
if (!isExists)
{
//
AddRef(
item,
symbols //
);
}
else
{
//
symbols[index].longs += item.longs;
symbols[index].shorts += item.shorts;
symbols[index].trades += item.trades;
symbols[index].losses += item.losses;
symbols[index].profits += item.profits;
symbols[index].managedSLs += item.managedSLs;
symbols[index].managedTPs += item.managedTPs;
symbols[index].managedTrades += item.managedTrades;
}
}
//
void ResetSymbolsRestrictions()
{
//
bool has = HasChild(symbols);
if (has)
{
//
string prefix = "Protector: ";
//
int count = ArraySize(symbols);
for (int i = 0; i < count; i++)
{
//
symbols[i].managedSLs = 0;
symbols[i].managedTPs = 0;
symbols[i].managedTrades = 0;
}
//
string message = prefix + "Reset Symbols Restrictions";
HandleReportProtector(message);
}
}
//
void HandleRestrictions()
{
//
bool isNewDay = timeTracker.IsNewDay();
bool isNewHour = timeTracker.IsNewHour();
bool isNewWeek = timeTracker.IsNewWeek();
bool isNewMonth = timeTracker.IsNewMonth();
//
bool canResetRestrictions =
(
//
// Hourly ...
(isNewHour &&
restrictionsPeriod == XCAEA_TRADE_RESTRICATION_HOURLY)
//
||
//
// Daily ...
(isNewDay &&
restrictionsPeriod == XCAEA_TRADE_RESTRICATION_DAILY)
//
||
//
// Weekly ...
(isNewWeek &&
restrictionsPeriod == XCAEA_TRADE_RESTRICATION_WEEKLY)
//
||
//
// Monthly ...
(isNewMonth &&
restrictionsPeriod == XCAEA_TRADE_RESTRICATION_MONTHLY)
//
)
//
;
if (canResetRestrictions)
{
ResetSymbolsRestrictions();
}
}
// //
// Private ... // Private ...
private: private:
@@ -1392,17 +1834,15 @@ class XCXCAEATradeManager : public XCBaseAlert
bool allowLongs; bool allowLongs;
bool allowShorts; bool allowShorts;
//
int maxAllowedTPs;
int maxAllowedSLs;
int maxAllowedTrades;
ENUM_XCAEA_TRADE_RESTRICTION_PERIOD restrictionsPeriod;
// //
bool mSaveTrades; bool mSaveTrades;
//
int slCount;
int tpCount;
//
int managedSLCount;
int managedTPCount;
// //
bool reportTrades; bool reportTrades;
bool reportSignals; bool reportSignals;
@@ -1414,6 +1854,7 @@ class XCXCAEATradeManager : public XCBaseAlert
// //
XCAEATrade trades[]; XCAEATrade trades[];
XCAEASymbolInfo symbols[];
}; };
// //