Files
MQL5Data/Classes/x-saherelm.xea.class.mq5
T
2024-05-25 08:43:32 +03:30

1838 lines
41 KiB
Plaintext

///////////////////////////////////////////////////////
//
// SaherElm IT Center MQL5 Class Library
// ----------------------------------------------
// Name: XSCBaseEA
// Description: provides all Base EA requirements ...
//
//
// Maintainer:
// ------------
// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com)
//
//////////////////////////////////////////////////////
//
// Global Properties ...
#property library
#property copyright "Copyright 2023, SaherElm IT Center"
#property link "https://www.saherelm.ir"
#property version "1.00"
#property strict
//
// Imports ...
#include "../Classes/x-saherelm.base.class.mq5"
#include "../Classes/x-saherelm.xalert.class.mq5"
#include "../Classes/x-saherelm.xtrade.class.mq5"
//
// Define On Signal Event Handler Type ...
typedef void (*TOnSignal)(XSignal &signals[]);
//
enum ENUM_X_PROFIT_TRACK_FIELDS
{
X_PROFIT_TRACK_PROFIT,
X_PROFIT_TRACK_LONGS_PROFIT,
X_PROFIT_TRACK_SHORTS_PROFIT,
};
//
// Model Account Profits ...
struct XProfitTrack
{
//
int longs; // Number of Long ...
int shorts; // Number of Short ...
//
double profit; // Profit of All ...
double longsProfit; // Profits of Longs ...
double shortsProfit; // Profits of Shorts ...
//
double profitFrom; // Profit of All ...
double longsProfitFrom; // Profits of Longs ...
double shortsProfitFrom; // Profits of Shorts ...
//
double volume; // Volume ...
double longsVolume; // Volume of Longs ...
double shortsVolume; // Volume of Shorts ...
//
datetime time; // Check Time ...
//
XProfitTrack()
{
Clean();
}
//
// Tools ...
//
// Initialization ...
bool Init(XSCTrade *mTrader)
{
//
bool result = false;
//
XPosition positions[];
int positionsCount = mTrader.GetPositions(positions);
result = positionsCount > 0;
if (!result)
{
return result;
}
//
for (int i = 0; i < positionsCount; i++)
{
//
XPosition iPosition = positions[i];
//
bool isLong = IsLong(iPosition.type);
//
if (isLong)
{
//
longs++;
longsVolume += iPosition.volume;
longsProfit += iPosition.profit;
}
else
{
//
shorts++;
shortsVolume += iPosition.volume;
shortsProfit += iPosition.profit;
}
//
profit += iPosition.profit;
volume += iPosition.volume;
}
//
result = IsValid();
if (result)
{
time = TimeCurrent();
}
//
return result;
}
//
double SelectField(ENUM_X_PROFIT_TRACK_FIELDS field)
{
//
double result = profit;
//
switch (field)
{
//
case X_PROFIT_TRACK_LONGS_PROFIT:
result = longsProfit;
break;
//
case X_PROFIT_TRACK_SHORTS_PROFIT:
result = shortsProfit;
break;
//
default:
case X_PROFIT_TRACK_PROFIT:
result = profit;
break;
}
//
return result;
}
//
// Cleanup ...
void Clean()
{
//
longs = 0;
shorts = 0;
profit = 0;
volume = 0;
profitFrom = 0;
longsVolume = 0;
longsProfit = 0;
shortsVolume = 0;
shortsProfit = 0;
longsProfitFrom = 0;
shortsProfitFrom = 0;
//
time = NULL;
}
//
// Validate ...
bool IsValid()
{
//
bool result = false;
//
result =
//
(longs > 0 || shorts > 0)
//
&&
//
volume > 0
//
;
//
return result;
}
//
};
//
// Class Definition ...
class XSCBaseEA : public XSCBase
{
//
// Public ...
public:
//
// Props ...
//
// Constructor ...
XSCBaseEA(
//
// XTrade Class Requirements ...
int slippage, // Specify Slippage
ulong magicNumber, // Specify Magic Number
int manageInterval, // Manager Check Intervals Seconds
double maxAllowedSpread, // Max Allowed Spred for Opening Trades
int maxAllowedPositions, // Max Allowed Positions
double maxAllowedDrawdownFactor, // Max Allowed Drawdown Factor
//
// Position Management ...
bool allowLong = true, // Allow Long Trades
bool allowShort = true, // Allow Short Trades
double minProfitPerTrade = 0, // Min Profit Per Trade based On Volume Factor (Hedge)
double minProfitPerVolumeFactor = 0, // Min Volume Factor for Calculating Profit (Hedge)
//
// Event Handlers ...
TOnStopLoss onStopLossTriggered = NULL, // On StopLoass Triggered Event Handler
TOnTakeProfit onTakeProfitTriggered = NULL, // On TakeProfit Triggered Event Handler
TOnDealsChanged onDealsChangedHandler = NULL, // On Deals Changed Event Handler
TOnOrdersChanged onOrdersChangedHandler = NULL, // On Orders Changed Event Handler
TOnPositionsChanged onPositionsChangedHandler = NULL, // On Positions Changed Event Handler
TOnTradeStateChanged onTradeStateChangedHandler = NULL, // On Trade State Changed Event Handler
//
// Log Handler ...
bool enableAlerts = true, // Enable Alerts
bool logAlerts = true, // Log Alerts
bool terminalAlerts = false, // Terminal Alerts
bool mailAlerts = false, // Mail Alerts
bool pushAlerts = false // Push Alerts
)
{
//
// Instance XSCTrade Class ...
mTrader = new XSCTrade(
slippage,
magicNumber,
manageInterval,
maxAllowedSpread,
maxAllowedPositions,
maxAllowedDrawdownFactor
//
);
//
mIsInTestMode = IsRunningOnTestMode();
//
// Position Management ...
mAllowLong = allowLong;
mAllowShort = allowShort;
mMinProfitPerTrade = minProfitPerTrade;
mMinProfitPerVolumeFactor = minProfitPerVolumeFactor;
//
// Set Event Handlers ...
mOnStopLossTriggered = onStopLossTriggered;
mOnTakeProfitTriggered = onTakeProfitTriggered;
mOnDealsChangedHandler = onDealsChangedHandler;
mOnOrdersChangedHandler = onOrdersChangedHandler;
mOnPositionsChangedHandler = onPositionsChangedHandler;
mOnTradeStateChangedHandler = onTradeStateChangedHandler;
//
// Add Event Listeners to XTrade Class if they Provided ...
if (mOnStopLossTriggered != NULL)
{
mTrader.AddOnStopLossEventHandler(mOnStopLossTriggered);
}
//
if (mOnTakeProfitTriggered != NULL)
{
mTrader.AddOnTakeProfitEventHandler(mOnTakeProfitTriggered);
}
//
if (mOnDealsChangedHandler != NULL)
{
mTrader.AddOnDealsChangedEventHandler(mOnDealsChangedHandler);
}
//
if (mOnOrdersChangedHandler != NULL)
{
mTrader.AddOnOrdersChangedEventHandler(mOnOrdersChangedHandler);
}
//
if (mOnPositionsChangedHandler != NULL)
{
mTrader.AddOnPositionsChangedEventHandler(mOnPositionsChangedHandler);
}
//
if (mOnTradeStateChangedHandler != NULL)
{
mTrader.AddOnTradeStateChangedEventHandler(mOnTradeStateChangedHandler);
}
//
// Instantiate Alert Class ...
mAlert = new XSCAlert(
GetTag(),
enableAlerts,
logAlerts,
terminalAlerts,
mailAlerts,
pushAlerts
//
);
}
//
// Deconstractor ...
~XSCBaseEA()
{
//
delete mTrader;
delete mAlert;
}
//
// Properties Getter(s) / Setter(s) ...
//
// Retrieve Slippage ...
int GetSlippage()
{
return mTrader.GetSlippage();
}
//
// Retrieve Magic Number ...
ulong GetMagicNumber()
{
return mTrader.GetMagicNumber();
}
//
// Retrieve Max Allowed Spread for Trading ...
double GetMaxAllowedSpread()
{
return mTrader.GetMaxAllowedSpread();
}
//
// Retrieve Max Allowed Same Time Positions Count ...
int GetMaxAllowedPositions()
{
return mTrader.GetMaxAllowedPositions();
}
//
// Retrieve Max Allowed Drawdown for Opening new Trades ...
double GetMaxAllowedDrawdownFactor()
{
return mTrader.GetMaxAllowedDrawdownFactor();
}
//
bool GetAllowLong()
{
return mAllowLong;
}
//
void SetAllowLong(bool value)
{
mAllowLong = value;
}
//
bool GetAllowShort()
{
return mAllowShort;
}
//
void SetAllowShort(bool value)
{
mAllowShort = value;
}
//
double GetMinProfitPerTrade()
{
return mMinProfitPerTrade;
}
//
void SetMinProfitPerTrade(double value)
{
//
if (value <= 0)
{
value = 0;
}
//
if (value == mMinProfitPerTrade)
{
return;
}
//
mMinProfitPerTrade = value;
}
//
double GetMinProfitPerVolumeFactor()
{
return mMinProfitPerVolumeFactor;
}
//
void SetMinProfitPerVolumeFactor(double value)
{
//
if (value <= 0)
{
value = 0;
}
//
if (value == mMinProfitPerVolumeFactor)
{
return;
}
//
mMinProfitPerVolumeFactor = value;
}
//
// Alert ...
//
bool GetLogAlerts()
{
return mAlert.GetLogAlerts();
}
//
void SetLogAlerts(bool value)
{
mAlert.SetLogAlerts(value);
}
//
bool GetEnableAlerts()
{
return mAlert.GetEnableAlerts();
}
//
void SetEnableAlerts(bool value)
{
mAlert.SetEnableAlerts(value);
}
//
bool GetPushAlerts()
{
return mAlert.GetPushAlerts();
}
//
void SetPushAlerts(bool value)
{
mAlert.SetPushAlerts(value);
}
//
bool GetMailAlerts()
{
return mAlert.GetMailAlerts();
}
//
void SetMailAlerts(bool value)
{
mAlert.SetMailAlerts(value);
}
//
bool GetTerminalAlerts()
{
return mAlert.GetTerminalAlerts();
}
//
void SetTerminalAlerts(bool value)
{
mAlert.SetTerminalAlerts(value);
}
//
// Event Listeners ...
void AddOnSignalEventHandler(TOnSignal listener)
{
//
Add(
listener,
mOnSignalEventHandlers
//
);
}
//
// Overrides ...
//
// Customize Token ...
virtual string GetToken()
{
return GetSpecificToken(this);
}
//
virtual string GetTag()
{
return this.GetToken();
}
//
// Virtual Functions ...
//
// Handle Chart Events ...
virtual void OnChartEvent(
const int id, // event ID
const long &lparam, // long type event parameter
const double &dparam, // double type event parameter
const string &sparam // string type event parameter
)
{
}
//
// OnTick Handler ...
virtual void OnTick()
{
//
// Draw ...
Draw();
//
// Check Trade Events ...
OnTrade();
//
HandleProfitManageMent();
//
// First Check For Any Guard Actions ...
// then Handle Guards if Provided ...
XGuard guards[];
bool hasGuard = CheckForGuard(guards);
if (hasGuard)
{
DoGuards(guards);
}
//
// Second Check for Position Management or Equity Management
// Actions like Supports or etc ...
bool isIgnored = HandleStateManagement();
if (isIgnored)
{
return;
}
//
// Second Check For Signals ...
// then Execute Signals if Provided ...
XSignal signals[];
int signalsCount = RequestForSignal(signals);
if (signalsCount <= 0)
{
return;
}
//
// Execute Signals ...
HandleSignalsExecution(signals);
}
//
// Handle StopLoss Event ...
virtual void OnStopLossTriggered(const XDeal &deal) {}
//
// Handle TakeProfit Event ...
virtual void OnTakeProfitTriggered(const XDeal &deal) {}
//
// Handle Deals Changed Event ...
virtual void OnDealsChangedHandler(int count) {}
//
// Handle Order Changed Event ...
virtual void OnOrdersChangedHandler(int count) {}
//
// Handle Position Changed Event ...
virtual void OnPositionsChangedHandler(int count) {}
//
// Handle Trade State Changed ...
virtual void OnTradeStateChangedHandler(const XOnTradeHandlerState &state) {}
//
// Handle On Trade ...
virtual void OnTrade()
{
//
XOnTradeHandlerState state = mTrader.HandleOnTrade();
//
if (
!state.hasNewDeal &&
!state.hasNewOrder &&
!state.hasNewPosition &&
!state.hasNewHistoryOrder)
{
return;
}
//
// STATE ...
//
// Notfy Trade State Changed Event ...
OnTradeStateChangedHandler(state);
//
// DEALS ...
if (state.hasNewDeal)
{
//
// Notfy Deals Changed Event ...
OnDealsChangedHandler(state.newDeals);
//
// Retrieve Last Deal ...
XDeal deals[];
mTrader.GetDeals(deals);
int dealsCount = ArraySize(deals);
if (dealsCount > 0)
{
//
XDeal lastDeal = deals[0];
//
if (lastDeal.reason == DEAL_REASON_TP)
{
OnTakeProfitTriggered(lastDeal);
}
else if (lastDeal.reason == DEAL_REASON_SL)
{
OnStopLossTriggered(lastDeal);
}
}
}
//
// ORDERS ...
if (state.hasNewOrder || state.hasNewHistoryOrder)
{
//
// Notfy Orders Changed Event ...
OnOrdersChangedHandler(state.newOrders + state.newHistoryOrders);
}
//
// POSITIONS ...
if (state.hasNewPosition)
{
//
// Notfy Positions Changed Event ...
OnPositionsChangedHandler(state.newPositions);
}
}
//
// Retrieve Dept Of Market ...
virtual void OnBookEvent(const string &symbol)
{
//
// TODO: Implement this ...
}
//
// Draw On Chart if anything is required ...
virtual void Draw() {}
//
// Check For any Guard Actions ...
virtual bool CheckForGuard(XGuard &guards[])
{
return false;
}
//
// When a Guard Notified to Do Support Signal ...
// this Method Calls For Retrieve Support Signal ...
// if it's Provided, Execute it ...
virtual bool RequestForSupport(
XSignal &support, // Holds Support Signal, if Provided
string provider, // Positions Provided by Specific Provider
string symbol, // Trading Symbol
ENUM_POSITION_TYPE type, // Trading Type
ENUM_TIMEFRAMES period // Specified Time Frame
)
{
return false;
}
//
// Handle Position(s)/ Order(s) or EQM Supporting Action ...
// if returns false, prevent for process Tick ...
virtual bool HandleStateManagement()
{
return false;
}
//
// Regulary Filtered Signals passed to this
// and here we can do Additional Signal Filtering
// for Signal Management such as (Providers and etc) ...
virtual int HandleSignalManagement(XSignal &signals[])
{
//
int result = ArraySize(signals);
//
return result;
}
//
// Here we Have to Check Market based
// on our Strategy for Trading ...
// and if a Good Entry founded ...
// model it as an XSignal struct and passed it to result ...
virtual int RequestForSignal(
XSignal &signals[] // Holds Signals ...
)
{
return 0;
}
//
// Execute Provided Signals ...
virtual void HandleSignalsExecution(XSignal &signals[])
{
//
int signalsCount = ArraySize(signals);
if (signalsCount <= 0)
{
return;
}
//
// Filter Signals Based on their Types ...
XSignal filteredSignals[];
//
// Try to Filter Signals ...
for (int i = 0; i < signalsCount; i++)
{
//
XSignal iSignal = signals[i];
//
bool isLong = IsLong(iSignal.type);
//
if ((isLong && !GetAllowLong()) || (!isLong && !GetAllowShort()))
{
continue;
}
//
AddRef(
iSignal,
filteredSignals //
);
}
//
int filteredSignalsCount = ArraySize(filteredSignals);
if (filteredSignalsCount <= 0)
{
return;
}
//
int managedSignalsCount = HandleSignalManagement(filteredSignals);
if (managedSignalsCount <= 0)
{
return;
}
//
// Try to Execute Signals ...
ENUM_X_SIGNAL_EXECUTION_RESULT reasons[];
int executedSignalsCount = mTrader.ExecuteSignals(
filteredSignals,
reasons
//
);
//
string message = NULL;
if (executedSignalsCount == 0)
{
//
message = "(" + ToString(filteredSignalsCount) + ") Signals Execution Failed ...";
//
for (int j = 0; j < ArraySize(reasons); j++)
{
//
string iReason = ToString(reasons[j]);
//
// ToString(GetSpread(filteredSignals[j].symbol)) + ","
message += "\n" + ToString(j) + ": " + iReason;
}
}
else if (executedSignalsCount < filteredSignalsCount)
{
//
int diff = filteredSignalsCount - executedSignalsCount;
//
message = "Failed to Execute (" + ToString(diff) + ") Signals ...";
}
else if (executedSignalsCount == filteredSignalsCount)
{
message = "(" + ToString(executedSignalsCount) + ") Signals Executed Successfully ...";
}
//
if (IsValid(message))
{
mAlert.Alert(message);
}
}
//
virtual void OnGoingToProfit(XProfitTrack &track) {}
virtual void OnLongsGoingToProfit(XProfitTrack &track) {}
virtual void OnShortsGoingToProfit(XProfitTrack &track) {}
//
virtual void OnGoingToDrawdown(XProfitTrack &track) {}
virtual void OnLongsGoingToDrawdown(XProfitTrack &track) {}
virtual void OnShortsGoingToDrawdown(XProfitTrack &track) {}
//
// Protected ...
protected:
//
// Props ...
//
// Trade Class Instance ...
XSCTrade *mTrader;
XSCAlert *mAlert;
//
// Check in Test Mode or not ...
bool mIsInTestMode;
//
// Tools ...
//
// Signal Event Listeners ...
void NotifyOnSignalEventHandlers(XSignal &signals[])
{
//
int listenersCount = ArraySize(mOnSignalEventHandlers);
if (listenersCount <= 0)
{
return;
}
//
for (int i = 0; i < listenersCount; i++)
{
//
TOnSignal iListener = mOnSignalEventHandlers[i];
//
iListener(signals);
}
}
//
// Position Management ...
//
// Calculate Required Profit for Hedging ...
double CalculateRequiredProfitForHedge(
XPosition &positions[] // Source
)
{
//
double result = 0;
//
int positionsCount = ArraySize(positions);
if (positionsCount <= 0)
{
return result;
}
//
bool isHedgingEnable = mMinProfitPerTrade > 0 && mMinProfitPerVolumeFactor > 0;
if (!isHedgingEnable)
{
return result;
}
//
for (int i = 0; i < positionsCount; i++)
{
//
XPosition iPosition = positions[i];
//
if (mMinProfitPerTrade > 0 && mMinProfitPerVolumeFactor > 0)
{
//
result +=
((iPosition.volume / mMinProfitPerVolumeFactor) *
mMinProfitPerTrade) +
(-1 * iPosition.swap);
}
}
//
return result;
}
//
// Calculate Positions Profit Summary ...
double CalculatePositionsProfit(
XPosition &positions[] // Source
)
{
//
double result = 0;
//
int positionsCount = ArraySize(positions);
if (positionsCount <= 0)
{
return result;
}
//
for (int i = 0; i < positionsCount; i++)
{
//
XPosition iPosition = positions[i];
//
result += iPosition.profit;
}
//
return result;
}
//
// Profit Tracker ...
//
XProfitTrack mProfitTracks[];
//
bool GetProfitTrack(
XProfitTrack &track,
int index = 0 //
)
{
//
bool result = false;
//
if (index < 0)
{
index = 0;
}
//
int tracksCount = CountProfitTracks();
result = tracksCount > 0 && index < tracksCount;
if (!result)
{
return result;
}
//
track.Clean();
//
track = mProfitTracks[index];
//
result = track.IsValid();
//
return result;
}
//
int CountProfitTracks()
{
return ArraySize(mProfitTracks);
}
//
void AddProfitTrack()
{
//
XProfitTrack track;
bool isValid = track.Init(mTrader);
if (!isValid)
{
return;
}
//
ArraySetAsSeries(mProfitTracks, false);
//
AddRef(
track,
mProfitTracks //
);
//
ArraySetAsSeries(mProfitTracks, true);
}
//
// Extract Specified Field Vales of XProfit Track Struct ...
int ExtractProfitTrackField(
double &result[],
ENUM_X_PROFIT_TRACK_FIELDS field,
int start = 0,
int count = 10 //
)
{
//
Clean(result);
//
if (start < 0)
{
start = 0;
}
//
int end = start + count;
//
int tracksCount = CountProfitTracks();
if (end > tracksCount)
{
end = tracksCount;
}
//
for (int i = start; i < end; i++)
{
//
XProfitTrack iTrack;
bool isValid = GetProfitTrack(
iTrack,
i //
);
//
if (!isValid)
{
continue;
}
//
double iValue = iTrack.SelectField(field);
Add(
iValue,
result //
);
}
//
int mResult = ArraySize(result);
//
return mResult;
}
//
double AverageProfitTrackField(
ENUM_X_PROFIT_TRACK_FIELDS field,
int start = 0,
int count = 10 //
)
{
//
double result = EMPTY_VALUE;
//
double items[];
int itemsCount = ExtractProfitTrackField(
items,
field,
start,
count //
);
if (itemsCount <= 0)
{
return result;
}
//
result = GetAverage(items);
//
return result;
}
//
bool IsProfitTrackFieldIncreasing(
ENUM_X_PROFIT_TRACK_FIELDS field,
int start = 0,
int count = 10 //
)
{
//
bool result = false;
//
double items[];
int itemsCount = ExtractProfitTrackField(
items,
field,
start,
count //
);
if (itemsCount <= 0)
{
return result;
}
//
int from = itemsCount - 1;
int to = 0;
//
result = IsIncreasing(
from,
to,
items //
);
//
return result;
}
//
bool IsProfitTrackFieldDecreasing(
ENUM_X_PROFIT_TRACK_FIELDS field,
int start = 0,
int count = 10 //
)
{
//
bool result = false;
//
double items[];
int itemsCount = ExtractProfitTrackField(
items,
field,
start,
count //
);
if (itemsCount <= 0)
{
return result;
}
//
int from = itemsCount - 1;
int to = 0;
//
result = IsDecreasing(
from,
to,
items //
);
//
return result;
}
//
void HandleProfitManageMent()
{
//
AddProfitTrack();
//
int profitsCount = CountProfitTracks();
if (profitsCount <= 1)
{
return;
}
//
XProfitTrack cT;
bool isValid = GetProfitTrack(
cT,
0 //
);
if (!isValid)
{
return;
}
//
XProfitTrack pT;
isValid = GetProfitTrack(
pT,
1 //
);
if (!isValid)
{
return;
}
//
cT.profitFrom = pT.profit;
cT.longsProfitFrom = pT.longsProfit;
cT.shortsProfitFrom = pT.shortsProfit;
//
bool isGoningToProfit =
//
cT.profit > 0 &&
pT.profit <= 0
//
;
if (isGoningToProfit)
{
//
OnGoingToProfit(cT);
}
//
bool isLongsGoningToProfit =
//
cT.longsProfit > 0 &&
pT.longsProfit <= 0
//
;
if (isLongsGoningToProfit)
{
OnLongsGoingToProfit(cT);
}
//
bool isShortsGoningToProfit =
//
cT.shortsProfit > 0 &&
pT.shortsProfit <= 0
//
;
if (isShortsGoningToProfit)
{
OnShortsGoingToProfit(cT);
}
//
bool isGoningToDrawdown =
//
cT.profit < 0 &&
pT.profit >= 0
//
;
if (isGoningToDrawdown)
{
OnGoingToDrawdown(cT);
}
bool isLongsGoningToDrawdown =
//
cT.longsProfit < 0 &&
pT.longsProfit >= 0
//
;
if (isLongsGoningToDrawdown)
{
OnLongsGoingToDrawdown(cT);
}
bool isShortsGoningToDrawdown =
//
cT.shortsProfit < 0 &&
pT.shortsProfit >= 0
//
;
if (isShortsGoningToDrawdown)
{
OnShortsGoingToDrawdown(cT);
}
}
//
// Guards ...
//
// Do All Provided Guards ...
void DoGuards(XGuard &guards[])
{
//
int guardsCount = ArraySize(guards);
if (guardsCount <= 0)
{
return;
}
//
for (int i = 0; i < guardsCount; i++)
{
//
XGuard iGuard = guards[i];
//
switch (iGuard.action)
{
//
// Hedge In Profit Specified Positions ...
case X_GUARD_ACTION_HEDGE:
HandleGuardHedgeAction(
iGuard.provider,
iGuard.symbol,
iGuard.type,
iGuard.period);
break;
//
// Trail Stop Loss in Specified Positions ...
case X_GUARD_ACTION_TRAIL_STOP:
HandleGuardTrailingStopAction(
iGuard.provider,
iGuard.symbol,
iGuard.type,
iGuard.period,
iGuard.dblPayLoad);
break;
//
// Force Close Specified Positions ...
case X_GUARD_ACTION_FORCE_CLOSE:
HandleGuardForceCloseAction(
iGuard.provider,
iGuard.symbol,
iGuard.type,
iGuard.period);
break;
//
// Generate and Place Support Signals ...
case X_GUARD_ACTION_ADD_SUPPORT_SIGNAL:
HandleGuardAddSupportPositionAction(
iGuard.provider,
iGuard.symbol,
iGuard.type,
iGuard.period);
break;
//
// Delete All Placed Pending Orders ...
case X_GUARD_ACTION_CANCEL_PENDING_ORDERS:
HandleGuardCancelPendingOrdersAction(
iGuard.provider,
iGuard.symbol,
iGuard.type,
iGuard.period);
break;
}
}
}
//
// Close All Specified Provider's Positions in Profit Summary ...
void HandleGuardHedgeAction(
string provider, // Positions Provided by Specific Provider
string symbol, // Trading Symbol
ENUM_POSITION_TYPE type, // Trading Type
ENUM_TIMEFRAMES period, // Specified Time Frame
double minProfitForHedging = 1 // Specified Profit for Hedge
)
{
//
XPosition positions[];
int positionsCount = mTrader
.GetPositions(
positions,
symbol,
provider,
period,
type
//
);
if (positionsCount <= 1)
{
return;
}
//
double profit = CalculatePositionsProfit(positions);
double requiredProfit = CalculateRequiredProfitForHedge(positions);
//
bool isReadyForHedge = profit >= requiredProfit;
if (!isReadyForHedge)
{
return;
}
//
string comment = "Guard Hedge " + provider;
int closed = mTrader.Close(
positions,
comment
//
);
if (closed > 0)
{
//
string message = "Guard Hedge " + provider + "'s Positions on Profit: " + ToString(profit);
//
mAlert.Alert(message);
}
}
//
// Close Max In Profit Trade Guard Action ...
void HandleGuardCloseInProfitAction(
string provider, // Positions Provided by Specific Provider
string symbol, // Trading Symbol
ENUM_POSITION_TYPE type, // Trading Type
ENUM_TIMEFRAMES period, // Specified Time Frame
ENUM_X_POSITION_SELECT_METHODS method = NULL // Select Method
)
{
//
XPosition positions[];
int positionsCount = mTrader
.GetInProfitPositions(
positions,
symbol,
provider,
period,
type,
method
//
);
if (positionsCount <= 0)
{
return;
}
//
string comment = "Close InProfit ...";
mTrader.Close(
positions,
comment
//
);
//
string message = "Guard Close (" + ToString(positionsCount) + ") Postion(s) In Profit ...";
//
mAlert.Alert(message);
}
//
// Close Max In Drawdown Trade Guard Action ...
void HandleGuardCloseInDrawdownAction(
string provider, // Positions Provided by Specific Provider
string symbol, // Trading Symbol
ENUM_POSITION_TYPE type, // Trading Type
ENUM_TIMEFRAMES period, // Specified Time Frame
ENUM_X_POSITION_SELECT_METHODS method = NULL // Select Method
)
{
//
XPosition positions[];
int positionsCount = mTrader
.GetInDrawdownPositions(
positions,
symbol,
provider,
period,
type,
method
//
);
if (positionsCount <= 0)
{
return;
}
//
string comment = "Close InDrawdown ...";
mTrader.Close(
positions,
comment
//
);
//
string message = "Guard Close (" + ToString(positionsCount) + ") Position(s) In Drawdown ...";
//
mAlert.Alert(message);
}
//
// Force Close Specified Set Of Position ...
void HandleGuardForceCloseAction(
string provider, // Positions Provided by Specific Provider
string symbol, // Trading Symbol
ENUM_POSITION_TYPE type, // Trading Type
ENUM_TIMEFRAMES period, // Specified Time Frame
ulong ticket = 0 // Specific Ticket
)
{
//
string comment = "";
//
// Close All Positions ...
if (ticket == 0)
{
//
XPosition positions[];
int positionsCount = mTrader.GetPositions(
positions,
symbol,
provider,
period,
type
//
);
if (positionsCount <= 0)
{
return;
}
//
comment = provider + " Force Close Guard ...";
//
mTrader.Close(
positions,
comment
//
);
}
//
// Close Specific Position ...
else
{
//
XPosition position;
bool hasPosition = mTrader
.GetPosition(
ticket,
position
//
);
//
if (hasPosition)
{
//
comment = provider + "(" + ToString(ticket) + ")" + " Force Close Guard ...";
//
mTrader.Close(
ticket,
comment
//
);
}
}
//
if (IsValid(comment))
{
mAlert.Alert(comment);
}
}
//
// Trailing Specified Set Of Positions Stop Losses ...
void HandleGuardTrailingStopAction(
string provider, // Positions Provided by Specific Provider
string symbol, // Trading Symbol
ENUM_POSITION_TYPE type, // Trading Type
ENUM_TIMEFRAMES period, // Specified Time Frame
double sl // Desired SL Value ...
)
{
//
if (sl <= 0)
{
return;
}
//
NormalizePrice(
sl,
symbol
//
);
//
XPosition positions[];
int positionsCount = mTrader
.GetPositions(
positions,
symbol,
provider,
period,
type
//
);
if (positionsCount <= 0)
{
return;
}
//
int modified = 0;
for (int i = 0; i < positionsCount; i++)
{
//
XPosition iPosition = positions[i];
//
string comment = PrepareSLTrailTag(iPosition.comment);
//
if (iPosition.sl == sl)
{
continue;
}
//
bool isModified = mTrader.Modify(
iPosition.ticket,
sl,
iPosition.tp,
comment);
if (isModified)
{
modified++;
}
}
//
if (modified > 0)
{
//
string message = "(" + ToString(modified) + ") Position's Stop Trailed Successfully ...";
//
mAlert.Alert(message);
}
}
//
// Add Support Signal for Specified Positions ...
void HandleGuardAddSupportPositionAction(
string provider, // Positions Provided by Specific Provider
string symbol, // Trading Symbol
ENUM_POSITION_TYPE type, // Trading Type
ENUM_TIMEFRAMES period // Specified Time Frame
)
{
//
XSignal support;
bool hasSupport = RequestForSupport(
support,
provider,
symbol,
type,
period
//
);
//
if (!hasSupport || !support.IsValid())
{
return;
}
//
// TODO: May be need to add Support Tag to comments ...
//
ENUM_X_SIGNAL_EXECUTION_RESULT reason = NULL;
bool isExecuted = mTrader.ExecuteSignal(
support,
reason);
//
string comment = NULL;
if (!isExecuted)
{
comment = "Support Execution Failed doue " + ToString(reason);
}
else
{
comment = "Guard Support Signal Executed Successfully ...";
}
//
if (IsValid(comment))
{
mAlert.Alert(comment);
}
}
//
// Cancel all Placed Orders ...
void HandleGuardCancelPendingOrdersAction(
string provider, // Positions Provided by Specific Provider
string symbol, // Trading Symbol
ENUM_POSITION_TYPE type, // Trading Type
ENUM_TIMEFRAMES period // Specified Time Frame
)
{
//
XOrder orders[];
int ordersCount = mTrader.GetOrders(
orders,
symbol,
provider,
period,
ToOrderType(type),
ORDER_STATE_PLACED,
true // Filter by Magic ...
//
);
if (ordersCount <= 0)
{
return;
}
//
int canceledOrdersCount = mTrader.CancelOrders(orders);
//
if (canceledOrdersCount > 0)
{
//
string message = "Guard Cancel (" + ToString(canceledOrdersCount) + ") Pending Orders ...";
//
mAlert.Alert(message);
}
}
//
// Private ...
private:
//
// Props ...
//
// Signal Event Listeners ...
TOnSignal mOnSignalEventHandlers[];
//
// Position Management ...
bool mAllowLong; // Allow Long Trades
bool mAllowShort; // Allow Short Trades
double mMinProfitPerTrade; // Min Profit Per Trade based On Volume Factor (Hedge)
double mMinProfitPerVolumeFactor; // Min Volume Factor for Calculating Profit (Hedge)
//
// Event Handlers ...
TOnStopLoss mOnStopLossTriggered;
TOnTakeProfit mOnTakeProfitTriggered;
TOnDealsChanged mOnDealsChangedHandler;
TOnOrdersChanged mOnOrdersChangedHandler;
TOnPositionsChanged mOnPositionsChangedHandler;
TOnTradeStateChanged mOnTradeStateChangedHandler;
};
//