Files
MQL5Data/Classes/x-saherelm.x-guard.class.mq5
T
saherelm e46cac2ab1 - Create a Data Collector Class;
- Add Support for Save Logs in Alert Class;
- Add Propper inputs for Handle Saving Logs in EA and Expert Class;
- remove x-trade.manager Class Data Collector and use General Developed Data Collector;
- Add Support for Reading Fles in Data Collector Class for Support Configuration Parsing;
- Remove XCBaseAlert class and add Support for get XCAlert instance reference pointer as Dependency Injection in all used classed and Refactor all Changes;
- Apply Fix some UnImplemented Event Handlers on Ea Expert Class of XCATBEA and also change Event Handler Binding to Collection Based Model;
- Test all Functionalities ...
- Apply Some Fixes on Prevent Double Saing Same Log Messages ...
2025-06-05 05:35:47 +03:30

2009 lines
38 KiB
Plaintext

///////////////////////////////////////////////////////
//
// SaherElm IT Center MQL5 Class
// -------------------------------------------------
// Name: XCXGuard ...
// Description: Guard Provider Class ...
//
//
// Maintainer:
// ------------
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
//
//////////////////////////////////////////////////////
//
// Global Properties ...
#property library
#property copyright "Copyright 2023, SaherElm IT Center"
#property link "https://saherelm.ir"
#property version "1.00"
#property description "SaherElm Guard Provider Class"
#property strict
//
// Imports ...
#include "../Classes/x-saherelm.x-alert.class.mq5"
#include "../Classes/x-saherelm.x-trade.class.mq5"
//
// Enumeration ...
//
// Guard Actions ...
enum ENUM_X_GUARD_ACTIONS
{
X_GUARD_ACTION_NONE, // Nothing to Do
X_GUARD_ACTION_CLOSE, // Close Specified Position
X_GUARD_ACTION_CLOSE_ALL, // Close All Positions
X_GUARD_ACTION_CLOSE_LONGS, // Close All Long Positions
X_GUARD_ACTION_CLOSE_SHORTS, // Close All Short Position
X_GUARD_ACTION_CLOSE_IN_LOSTS, // Close All In Lost Position
X_GUARD_ACTION_CLOSE_IN_PROFITS, // Close All In Profit Position
X_GUARD_ACTION_CLOSE_IN_LOST_LONGS, // Close All In Lost Long Position
X_GUARD_ACTION_CLOSE_IN_PROFIT_LONGS, // Close All In Profit Long Position
X_GUARD_ACTION_CLOSE_IN_LOST_SHORTS, // Close All In Lost Short Position
X_GUARD_ACTION_CLOSE_IN_PROFITS_SHORT, // Close All In Profit Short Position
X_GUARD_ACTION_PARTIAL_CLOSE, // Partial Close Specified Position
X_GUARD_ACTION_TRAIL_STOP, // Trail Stop of Specified Position
X_GUARD_ACTION_TRAIL_TARGET, // Trail Target of Specified Position
X_GUARD_ACTION_HEDGE, // Hedge Specified Positions
};
//
// Definitions ...
//
// Model a Guard Action ...
struct XGuard
{
//
// Props ...
ENUM_X_GUARD_ACTIONS action;
datetime time;
//
string symbol;
string provider;
ENUM_TIMEFRAMES period;
//
// Specified Position ...
ulong ticket;
//
// Partial Close ...
double volumeMultiplier;
//
// SL Trial ...
double sl;
//
// TP Trial ...
double tp;
//
bool force;
//
// Constructor ...
XGuard()
{
Clean();
}
//
// Tools ...
/**
* Cleanup ...
*/
void Clean()
{
//
time = NULL;
action = X_GUARD_ACTION_NONE;
//
symbol = NULL;
period = NULL;
provider = NULL;
//
ticket = 0;
//
volumeMultiplier = 0;
//
sl = 0;
tp = 0;
//
force = false;
//
ZeroMemory(this);
}
/**
* Validate ...
*
* @return ( bool )
*/
bool IsValid()
{
//
bool result = false;
//
result =
//
IsValid(time) &&
IsValid(symbol) &&
IsValid(period) &&
IsValid(action) &&
IsValid(provider)
//
;
if (!result)
{
return result;
}
//
// Validate Model Based On Specified Guard Actions ...
//
return result;
}
};
//
// Extensions ...
//
bool IsValid(ENUM_X_GUARD_ACTIONS item)
{
//
bool result = false;
//
result = item != X_GUARD_ACTION_NONE;
//
return result;
}
/**
* Add Guard to Collection ...
*
* @param guard: XGuard instance ...
* @param guards: XGuard instance Collection ...
*
* @return ( int )
*/
int AddGuard(
XGuard &guard,
XGuard &guards[] //
)
{
//
int result = 0;
//
if (!guard.IsValid())
{
return result;
}
//
AddRef(
guard,
guards //
);
//
result = ArraySize(guards);
//
return result;
}
//
// Implementation ...
class XCGuard : public XCBase
{
//
// public ...
public:
//
// Props ...
double minVolumeFactorForHedge; // Minimum Volume Factor for Hedge Profit Calculation ...
double minProfitPerVolumeFactorForHedge; // Minimum Required Profit per Volume Factor for Hedg ...
//
// Constructor(s) ...
XCGuard(
XCAlert *_alert,
XCTrade *_trader //
)
{
//
alert = _alert;
trader = _trader;
//
minVolumeFactorForHedge = 0.01;
minProfitPerVolumeFactorForHedge = 0.5;
}
//
// Deconstructor(s) ...
~XCGuard()
{
//
ZeroMemory(alert);
ZeroMemory(trader);
}
//
// Tools ...
void DoGuards(XGuard &guards[])
{
//
bool has = HasChild(guards);
if (!has)
{
return;
}
//
XGuard tmp[];
Copy(
guards,
tmp //
);
while (HasChild(tmp))
{
//
XGuard iGuard = tmp[0];
ArrayRemove(
tmp,
0,
1 //
);
//
// Do Guard Action ...
DoGuard(iGuard);
}
//
Clean(tmp);
}
//
void DoGuard(XGuard &guard)
{
//
bool has = false;
//
// Validate and Do Guard ...
has = guard.IsValid();
if (!has)
{
return;
}
//
// Switch Based on Guard Action ...
switch (guard.action)
{
//
// Close ...
case X_GUARD_ACTION_CLOSE:
DoClose(guard);
break;
//
// Close All ...
case X_GUARD_ACTION_CLOSE_ALL:
DoCloseAll(guard);
break;
//
// Close All Long Positions ...
case X_GUARD_ACTION_CLOSE_LONGS:
DoCloseLongs(guard);
break;
//
// Close All Short Positions ...
case X_GUARD_ACTION_CLOSE_SHORTS:
DoCloseShorts(guard);
break;
//
// Close In Losts ...
case X_GUARD_ACTION_CLOSE_IN_LOSTS:
DoCloseInLosts(guard);
break;
//
// Close In Profits ...
case X_GUARD_ACTION_CLOSE_IN_PROFITS:
DoCloseInProfits(guard);
break;
//
// Close In Lost Longs ...
case X_GUARD_ACTION_CLOSE_IN_LOST_LONGS:
DoCloseInLostLongs(guard);
break;
//
// Close In Profit Longs ...
case X_GUARD_ACTION_CLOSE_IN_PROFIT_LONGS:
DoCloseInProfitLongs(guard);
break;
//
// Close In Lost Shorts ...
case X_GUARD_ACTION_CLOSE_IN_LOST_SHORTS:
DoCloseInLostShorts(guard);
break;
//
// Close In Profit Shorts ...
case X_GUARD_ACTION_CLOSE_IN_PROFITS_SHORT:
DoCloseInProfitShorts(guard);
break;
//
// Partial Close ...
case X_GUARD_ACTION_PARTIAL_CLOSE:
DoPartialClose(guard);
break;
//
// Trail Stop ...
case X_GUARD_ACTION_TRAIL_STOP:
DoTrailStop(guard);
break;
//
// Trail Target ...
case X_GUARD_ACTION_TRAIL_TARGET:
DoTrailTarget(guard);
break;
//
// Hedge Positions ...
case X_GUARD_ACTION_HEDGE:
DoHedge(guard);
break;
//
}
}
//
// protected ...
protected:
//
//
bool GetPosition(
XPosition &position,
XGuard &guard //
)
{
//
bool result = false;
//
position.Clean();
//
result =
guard.IsValid() &&
guard.ticket > 0;
if (!result)
{
return result;
}
//
// Get Position ...
result = trader.GetPosition(
guard.ticket,
position //
);
if (!result)
{
//
position.Clean();
//
return result;
}
//
// Validate Position ...
result =
position.IsValid() &&
position.symbol == guard.symbol &&
position.provider == guard.provider &&
position.period == guard.period;
if (!result)
{
//
position.Clean();
//
return result;
}
//
return result;
}
//
int GetPositions(
XPosition &positions[],
XGuard &guard //
)
{
//
int result = 0;
//
Clean(positions);
//
bool has = guard.IsValid();
if (!has)
{
return result;
}
//
result = trader.GetPositions(
positions,
guard.symbol,
guard.provider,
guard.period,
NULL, // All Types ...
true, // Filter By Magc ...
true // Force Clean ...
);
//
result = ArraySize(positions);
//
return result;
}
//
int GetLongPositions(
XPosition &positions[],
XGuard &guard //
)
{
//
int result = 0;
//
Clean(positions);
//
bool has = guard.IsValid();
if (!has)
{
return result;
}
//
result = trader.GetPositions(
positions,
guard.symbol,
guard.provider,
guard.period,
X_POSITION_TYPE_LONG, // Specified Types ...
true, // Filter By Magc ...
true // Force Clean ...
);
//
result = ArraySize(positions);
//
return result;
}
//
int GetShortPositions(
XPosition &positions[],
XGuard &guard //
)
{
//
int result = 0;
//
Clean(positions);
//
bool has = guard.IsValid();
if (!has)
{
return result;
}
//
result = trader.GetPositions(
positions,
guard.symbol,
guard.provider,
guard.period,
X_POSITION_TYPE_SHORT, // Specified Types ...
true, // Filter By Magc ...
true // Force Clean ...
);
//
result = ArraySize(positions);
//
return result;
}
//
int GetInProfitPositions(
XPosition &positions[],
XGuard &guard //
)
{
//
int result = 0;
//
Clean(positions);
//
bool has = guard.IsValid();
if (!has)
{
return result;
}
//
XPosition allPositions[];
int allPositionsCount = GetPositions(
allPositions,
guard //
);
has = IsValidSize(allPositionsCount);
if (!has)
{
return result;
}
//
while (HasChild(allPositions))
{
//
XPosition iPosition = allPositions[0];
ArrayRemove(
allPositions,
0,
1 //
);
//
if (iPosition.profit > 0)
{
//
AddRef(
iPosition,
positions //
);
}
//
iPosition.Clean();
}
Clean(allPositions);
//
result = ArraySize(positions);
//
return result;
}
//
int GetInLostPositions(
XPosition &positions[],
XGuard &guard //
)
{
//
int result = 0;
//
Clean(positions);
//
bool has = guard.IsValid();
if (!has)
{
return result;
}
//
XPosition allPositions[];
int allPositionsCount = GetPositions(
allPositions,
guard //
);
has = IsValidSize(allPositionsCount);
if (!has)
{
return result;
}
//
while (HasChild(allPositions))
{
//
XPosition iPosition = allPositions[0];
ArrayRemove(
allPositions,
0,
1 //
);
//
if (iPosition.profit < 0)
{
//
AddRef(
iPosition,
positions //
);
}
//
iPosition.Clean();
}
Clean(allPositions);
//
result = ArraySize(positions);
//
return result;
}
//
int GetInProfitLongPositions(
XPosition &positions[],
XGuard &guard //
)
{
//
int result = 0;
//
Clean(positions);
//
bool has = guard.IsValid();
if (!has)
{
return result;
}
//
XPosition allPositions[];
int allPositionsCount = GetLongPositions(
allPositions,
guard //
);
has = IsValidSize(allPositionsCount);
if (!has)
{
return result;
}
//
while (HasChild(allPositions))
{
//
XPosition iPosition = allPositions[0];
ArrayRemove(
allPositions,
0,
1 //
);
//
if (iPosition.profit > 0)
{
//
AddRef(
iPosition,
positions //
);
}
//
iPosition.Clean();
}
Clean(allPositions);
//
result = ArraySize(positions);
//
return result;
}
//
int GetInLostLongPositions(
XPosition &positions[],
XGuard &guard //
)
{
//
int result = 0;
//
Clean(positions);
//
bool has = guard.IsValid();
if (!has)
{
return result;
}
//
XPosition allPositions[];
int allPositionsCount = GetLongPositions(
allPositions,
guard //
);
has = IsValidSize(allPositionsCount);
if (!has)
{
return result;
}
//
while (HasChild(allPositions))
{
//
XPosition iPosition = allPositions[0];
ArrayRemove(
allPositions,
0,
1 //
);
//
if (iPosition.profit < 0)
{
//
AddRef(
iPosition,
positions //
);
}
//
iPosition.Clean();
}
Clean(allPositions);
//
result = ArraySize(positions);
//
return result;
}
//
int GetInProfitShortPositions(
XPosition &positions[],
XGuard &guard //
)
{
//
int result = 0;
//
Clean(positions);
//
bool has = guard.IsValid();
if (!has)
{
return result;
}
//
XPosition allPositions[];
int allPositionsCount = GetShortPositions(
allPositions,
guard //
);
has = IsValidSize(allPositionsCount);
if (!has)
{
return result;
}
//
while (HasChild(allPositions))
{
//
XPosition iPosition = allPositions[0];
ArrayRemove(
allPositions,
0,
1 //
);
//
if (iPosition.profit > 0)
{
//
AddRef(
iPosition,
positions //
);
}
//
iPosition.Clean();
}
Clean(allPositions);
//
result = ArraySize(positions);
//
return result;
}
//
int GetInLostShortPositions(
XPosition &positions[],
XGuard &guard //
)
{
//
int result = 0;
//
Clean(positions);
//
bool has = guard.IsValid();
if (!has)
{
return result;
}
//
XPosition allPositions[];
int allPositionsCount = GetShortPositions(
allPositions,
guard //
);
has = IsValidSize(allPositionsCount);
if (!has)
{
return result;
}
//
while (HasChild(allPositions))
{
//
XPosition iPosition = allPositions[0];
ArrayRemove(
allPositions,
0,
1 //
);
//
if (iPosition.profit < 0)
{
//
AddRef(
iPosition,
positions //
);
}
//
iPosition.Clean();
}
Clean(allPositions);
//
result = ArraySize(positions);
//
return result;
}
//
// Guard Handlers ...
//
void DoClose(XGuard &guard)
{
//
bool has = false;
//
has = guard.IsValid();
if (!has)
{
return;
}
//
// Do What we want ...
//
// Validate Action and Requirements ...
has =
NotEmpty(guard.ticket) &&
guard.action == X_GUARD_ACTION_CLOSE;
if (!has)
{
return;
}
//
// Retrieve Position ...
XPosition position;
has = GetPosition(
position,
guard //
);
if (!has)
{
//
position.Clean();
//
return;
}
//
string comment = "Guard Close ...";
//
has = trader.Close(
position.ticket,
comment //
);
if (has)
{
//
string message =
"Guard Closed " +
ToString(position.type) +
" Position (" + ToString(position.ticket) + ") Successfully ...";
//
alert.SendAlert(message);
}
//
// Cleanup Resources ...
//
position.Clean();
}
//
void DoCloseAll(XGuard &guard)
{
//
bool has = false;
//
has = guard.IsValid();
if (!has)
{
return;
}
//
// Do What we want ...
has = guard.action == X_GUARD_ACTION_CLOSE_ALL;
if (!has)
{
return;
}
//
// Retrieve Positions ...
XPosition positions[];
int count = GetPositions(
positions,
guard //
);
has = IsValidSize(count);
if (!has)
{
//
Clean(positions);
//
return;
}
//
string comment = "Guard Close All ...";
//
has = trader.Close(
positions,
comment //
);
if (has)
{
//
string message =
"Guard Closed " +
ToString(count) +
" Positions Successfully ...";
//
alert.SendAlert(message);
}
//
// Cleanup Resources ...
//
Clean(positions);
}
//
void DoCloseInLosts(XGuard &guard)
{
//
bool has = false;
//
has = guard.IsValid();
if (!has)
{
return;
}
//
// Do What we want ...
has = guard.action == X_GUARD_ACTION_CLOSE_IN_LOSTS;
if (!has)
{
return;
}
//
// Retrieve Positions ...
XPosition positions[];
int count = GetInLostPositions(
positions,
guard //
);
has = IsValidSize(count);
if (!has)
{
//
Clean(positions);
//
return;
}
//
string comment = "Guard Close All In Losts ...";
//
has = trader.Close(
positions,
comment //
);
if (has)
{
//
string message =
"Guard Closed " +
ToString(count) +
" In Lost Positions Successfully ...";
//
alert.SendAlert(message);
}
//
// Cleanup Resources ...
//
Clean(positions);
}
//
void DoCloseInProfits(XGuard &guard)
{
//
bool has = false;
//
has = guard.IsValid();
if (!has)
{
return;
}
//
// Do What we want ...
has = guard.action == X_GUARD_ACTION_CLOSE_IN_PROFITS;
if (!has)
{
return;
}
//
// Retrieve Positions ...
XPosition positions[];
int count = GetInProfitPositions(
positions,
guard //
);
has = IsValidSize(count);
if (!has)
{
//
Clean(positions);
//
return;
}
//
string comment = "Guard Close All In Profits ...";
//
has = trader.Close(
positions,
comment //
);
if (has)
{
//
string message =
"Guard Closed " +
ToString(count) +
" In Profit Positions Successfully ...";
//
alert.SendAlert(message);
}
//
// Cleanup Resources ...
//
Clean(positions);
}
//
void DoCloseLongs(XGuard &guard)
{
//
bool has = false;
//
has = guard.IsValid();
if (!has)
{
return;
}
//
// Do What we want ...
has = guard.action == X_GUARD_ACTION_CLOSE_LONGS;
if (!has)
{
return;
}
//
// Retrieve Positions ...
XPosition positions[];
int count = GetLongPositions(
positions,
guard //
);
has = IsValidSize(count);
if (!has)
{
//
Clean(positions);
//
return;
}
//
string comment = "Guard Close Longs ...";
//
has = trader.Close(
positions,
comment //
);
if (has)
{
//
string message =
"Guard Closed " +
ToString(count) +
" Long Positions Successfully ...";
//
alert.SendAlert(message);
}
//
// Cleanup Resources ...
//
Clean(positions);
}
//
void DoCloseInLostLongs(XGuard &guard)
{
//
bool has = false;
//
has = guard.IsValid();
if (!has)
{
return;
}
//
// Do What we want ...
has = guard.action == X_GUARD_ACTION_CLOSE_IN_LOST_LONGS;
if (!has)
{
return;
}
//
// Retrieve Positions ...
XPosition positions[];
int count = GetInLostLongPositions(
positions,
guard //
);
has = IsValidSize(count);
if (!has)
{
//
Clean(positions);
//
return;
}
//
string comment = "Guard Close All In Lost Longs ...";
//
has = trader.Close(
positions,
comment //
);
if (has)
{
//
string message =
"Guard Closed " +
ToString(count) +
" In Lost Longs Positions Successfully ...";
//
alert.SendAlert(message);
}
//
// Cleanup Resources ...
//
Clean(positions);
}
//
void DoCloseInProfitLongs(XGuard &guard)
{
//
bool has = false;
//
has = guard.IsValid();
if (!has)
{
return;
}
//
// Do What we want ...
has = guard.action == X_GUARD_ACTION_CLOSE_IN_PROFIT_LONGS;
if (!has)
{
return;
}
//
// Retrieve Positions ...
XPosition positions[];
int count = GetInProfitLongPositions(
positions,
guard //
);
has = IsValidSize(count);
if (!has)
{
//
Clean(positions);
//
return;
}
//
string comment = "Guard Close All In Profit Longs ...";
//
has = trader.Close(
positions,
comment //
);
if (has)
{
//
string message =
"Guard Closed " +
ToString(count) +
" In Profit Longs Positions Successfully ...";
//
alert.SendAlert(message);
}
//
// Cleanup Resources ...
//
Clean(positions);
}
//
void DoCloseShorts(XGuard &guard)
{
//
bool has = false;
//
has = guard.IsValid();
if (!has)
{
return;
}
//
// Do What we want ...
}
//
void DoCloseInLostShorts(XGuard &guard)
{
//
bool has = false;
//
has = guard.IsValid();
if (!has)
{
return;
}
//
// Do What we want ...
has = guard.action == X_GUARD_ACTION_CLOSE_IN_LOST_SHORTS;
if (!has)
{
return;
}
//
// Retrieve Positions ...
XPosition positions[];
int count = GetInLostShortPositions(
positions,
guard //
);
has = IsValidSize(count);
if (!has)
{
//
Clean(positions);
//
return;
}
//
string comment = "Guard Close All In Lost Shorts ...";
//
has = trader.Close(
positions,
comment //
);
if (has)
{
//
string message =
"Guard Closed " +
ToString(count) +
" In Lost Shorts Positions Successfully ...";
//
alert.SendAlert(message);
}
//
// Cleanup Resources ...
//
Clean(positions);
}
//
void DoCloseInProfitShorts(XGuard &guard)
{
//
bool has = false;
//
has = guard.IsValid();
if (!has)
{
return;
}
//
// Do What we want ...
has = guard.action == X_GUARD_ACTION_CLOSE_IN_PROFITS_SHORT;
if (!has)
{
return;
}
//
// Retrieve Positions ...
XPosition positions[];
int count = GetInProfitShortPositions(
positions,
guard //
);
has = IsValidSize(count);
if (!has)
{
//
Clean(positions);
//
return;
}
//
string comment = "Guard Close All In Profit Shorts ...";
//
has = trader.Close(
positions,
comment //
);
if (has)
{
//
string message =
"Guard Closed " +
ToString(count) +
" In Profit Shorts Positions Successfully ...";
//
alert.SendAlert(message);
}
//
// Cleanup Resources ...
//
Clean(positions);
}
//
void DoPartialClose(XGuard &guard)
{
//
bool has = false;
//
has = guard.IsValid();
if (!has)
{
return;
}
//
// Do What we want ...
//
// Validate Action and Requirements ...
has =
NotEmpty(guard.ticket) &&
guard.volumeMultiplier > 0 &&
guard.action == X_GUARD_ACTION_PARTIAL_CLOSE;
if (!has)
{
return;
}
//
// Retrieve Position ...
XPosition position;
has = GetPosition(
position,
guard //
);
if (!has)
{
//
position.Clean();
//
return;
}
//
// Normalize Volume Multiplier ...
double vMult = guard.volumeMultiplier;
if (vMult > 0.5)
{
vMult = 0.5;
}
if (vMult < 0)
{
vMult = 0.5;
}
//
// Calculate and Normalize Volume ...
double volume = position.volume * vMult;
volume = NormalizeVolume(
volume,
position.symbol //
);
//
string comment = "Guard Partially Closed: " + ToString(volume) + " ...";
//
has = trader.ClosePartial(
position.ticket,
volume,
comment //
);
if (has)
{
//
string message =
"Guard Closed Partially " +
ToString(volume) + " of " +
ToString(position.type) +
" Position (" + ToString(position.ticket) + ") Successfully ...";
//
alert.SendAlert(message);
}
//
// Cleanup Resources ...
//
position.Clean();
}
//
void DoTrailStop(XGuard &guard)
{
//
bool has = false;
//
has = guard.IsValid();
if (!has)
{
return;
}
//
// Do What we want ...
//
// Validate Action and Requirements ...
has =
guard.sl > 0 &&
NotEmpty(guard.ticket) &&
guard.action == X_GUARD_ACTION_TRAIL_STOP;
if (!has)
{
return;
}
//
// Retrieve Position ...
XPosition position;
has = GetPosition(
position,
guard //
);
if (!has)
{
//
position.Clean();
//
return;
}
//
bool isLong = IsLong(position.type);
//
// Check Can Trail Stop or not ...
has =
//
// Position Exists ...
has &&
//
// Positions in Profit for Trailling Stop ...
position.profit > 0 &&
//
// Validate SL based on Position Type ...
(isLong
? position.price > guard.sl &&
(position.sl == 0 ||
position.sl < guard.sl)
: position.price < guard.sl &&
(position.sl == 0 ||
position.sl > guard.sl));
if (!has)
{
//
position.Clean();
//
return;
}
//
string comment = "Guard Trail Stop ...";
//
has = trader.Modify(
position.ticket,
guard.sl,
position.tp,
comment //
);
if (has)
{
//
double before = NormalizePrice(position.sl, position.symbol);
double after = NormalizePrice(guard.sl, position.symbol);
//
string message =
"Guard Trail Stop " +
ToString(position.type) +
" Position (" + ToString(position.ticket) + ")" +
" From: " + ToString(before) +
"To: " + ToString(after) +
" Successfully ...";
//
alert.SendAlert(message);
}
//
// Cleanup Resources ...
//
position.Clean();
}
//
void DoTrailTarget(XGuard &guard)
{
//
bool has = false;
//
has = guard.IsValid();
if (!has)
{
return;
}
//
// Do What we want ...
//
// Validate Action and Requirements ...
has =
guard.tp > 0 &&
NotEmpty(guard.ticket) &&
guard.action == X_GUARD_ACTION_TRAIL_TARGET;
if (!has)
{
return;
}
//
// Retrieve Position ...
XPosition position;
has = GetPosition(
position,
guard //
);
if (!has)
{
//
position.Clean();
//
return;
}
//
bool isLong = IsLong(position.type);
//
// Check Can Trail Stop or not ...
has =
//
// Position Exists ...
has &&
//
// Check TP is not Same ...
guard.tp != position.tp &&
//
// Validate TP based on Current Price ...
(isLong
? guard.tp > position.price
: guard.tp < position.price);
if (!has)
{
//
position.Clean();
//
return;
}
//
string comment = "Guard Trail Target ...";
//
has = trader.Modify(
position.ticket,
position.sl,
guard.tp,
comment //
);
if (has)
{
//
double before = NormalizePrice(position.tp, position.symbol);
double after = NormalizePrice(guard.tp, position.symbol);
//
string message =
"Guard Trail Target " +
ToString(position.type) +
" Position (" + ToString(position.ticket) + ")" +
" From: " + ToString(before) +
"To: " + ToString(after) +
" Successfully ...";
//
alert.SendAlert(message);
}
//
// Cleanup Resources ...
//
position.Clean();
}
//
void DoHedge(XGuard &guard)
{
//
bool has = false;
//
has = guard.IsValid();
if (!has)
{
return;
}
//
// Do What we want ...
//
// Validate Action and Requirements ...
has =
(guard.force
? true
: (minVolumeFactorForHedge > 0 &&
minProfitPerVolumeFactorForHedge > 0)) &&
guard.action == X_GUARD_ACTION_HEDGE;
if (!has)
{
return;
}
//
// Retrieve Positions ...
XPosition positions[];
int count = GetPositions(
positions,
guard //
);
has = HasChild(positions);
if (!has)
{
//
Clean(positions);
//
return;
}
//
// Calculate Positions Profits and Volumes ...
double swaps = 0;
double profits = 0;
double volumes = 0;
double commissions = 0;
for (int i = 0; i < count; i++)
{
//
swaps += positions[i].swap;
profits += positions[i].profit;
volumes += positions[i].volume;
commissions += positions[i].commission;
}
//
// Check Profits and Volumes for Hedging ...
double hedgeValue = profits + (-1 * swaps) + commissions;
//
// Check Force Hedging ...
if (!guard.force)
{
//
// Calculate Minimum Required Profit for Hedging ...
double minRequiredProfit =
(volumes / minVolumeFactorForHedge) * minProfitPerVolumeFactorForHedge;
//
has = hedgeValue >= minRequiredProfit;
}
else
{
has = hedgeValue > 0;
}
//
if (!has)
{
//
Clean(positions);
//
return;
}
//
string comment = "Guard Hedge ...";
//
// Loop through Positions and Close them One by One ...
// this is because of Trade Manager to Handle Close Trades ...
int closedCount = 0;
for (int i = 0; i < count; i++)
{
//
has = trader.Close(
positions[i].ticket,
comment //
);
if (has)
{
closedCount++;
}
}
//
has = IsValidSize(closedCount);
if (has)
{
//
string message =
"Guard Hedge " +
ToString(closedCount) +
" Positions by: " +
ToString(hedgeValue) +
" Successfully ...";
//
alert.SendAlert(message);
}
//
// Cleanup Resources ...
//
Clean(positions);
}
//
// private ...
private:
//
XCTrade *trader;
XCAlert *alert;
//
};
//