Files
MQL5Data/Classes/x-saherelm.xea.class.mq5
T

1806 lines
42 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.xalert.class.mq5"
#include "../Classes/x-saherelm.xtrade.class.mq5"
//
// Define On Signal Event Handler Type ...
typedef void (*TOnSignal)(XSignal &signal);
//
// Class Definition ...
class XSCBaseEA : public XSCBaseAlert
{
//
// Public ...
public:
//
// Props ...
//
// Trade Class Instance ...
XSCTrade *mTrader;
//
// Constructor ...
XSCBaseEA(
//
// XTrade Class Requirements ...
int slippage, // Specify Slippage
ulong magicNumber, // Specify Magic Number
//
// Event Handlers ...
TOnSignal onSignal = NULL, // On Signal Recieved Event Handler
TOnModify onModifyPosition = NULL, // On Modify Position Event Handler
TOnStopLoss onStopLossTriggered = NULL, // On StopLoass Triggered Event Handler
TOnTakeProfit onTakeProfitTriggered = NULL, // On TakeProfit Triggered Event Handler
TOnForceClose onForceClosePosition = NULL, // On Force Close Position Event Handler
TOnPartialClose onPartialClosePosition = NULL, // On Partial Close Position 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
)
{
//
// Instance XSCTrade Class ...
mTrader = new XSCTrade(
slippage,
magicNumber //
);
//
mIsInTestMode = IsRunningOnTestMode();
mStaticBalanceForCalculateDrawdown = 0; // Ignore ...
//
// Set Event Handlers ...
mOnSignal = onSignal;
mOnModifyPosition = onModifyPosition;
mOnStopLossTriggered = onStopLossTriggered;
mOnForceClosePosition = onForceClosePosition;
mOnTakeProfitTriggered = onTakeProfitTriggered;
mOnDealsChangedHandler = onDealsChangedHandler;
mOnPartialClosePosition = onPartialClosePosition;
mOnOrdersChangedHandler = onOrdersChangedHandler;
mOnPositionsChangedHandler = onPositionsChangedHandler;
mOnTradeStateChangedHandler = onTradeStateChangedHandler;
//
if (mOnSignal != NULL)
{
AddOnSignalEventHandler(mOnSignal);
}
//
if (mOnModifyPosition != NULL)
{
mTrader.AddOnModifyPositionEventHandler(mOnModifyPosition);
}
//
if (mOnForceClosePosition != NULL)
{
mTrader.AddOnForceClosePositionEventHandler(mOnForceClosePosition);
}
//
if (mOnPartialClosePosition != NULL)
{
mTrader.AddOnPartialClosePositionEventHandler(mOnPartialClosePosition);
}
//
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);
}
}
//
// Deconstractor ...
~XSCBaseEA()
{
//
delete mTrader;
//
Clean(mOnSignalEventHandlers);
//
mOnSignal = NULL;
mOnModifyPosition = NULL;
mOnStopLossTriggered = NULL;
mOnTakeProfitTriggered = NULL;
mOnForceClosePosition = NULL;
mOnDealsChangedHandler = NULL;
mOnPartialClosePosition = NULL;
mOnOrdersChangedHandler = NULL;
mOnPositionsChangedHandler = NULL;
mOnTradeStateChangedHandler = NULL;
}
//
// Properties Getter(s) / Setter(s) ...
//
// Retrieve Slippage ...
int GetSlippage()
{
return mTrader.GetSlippage();
}
//
// Retrieve Magic Number ...
ulong GetMagicNumber()
{
return mTrader.GetMagicNumber();
}
//
double GetDrawdownPercent()
{
//
CalculateMaxDrawdown();
return mDrawdownPercent;
}
//
void AddOnSignalEventHandler(TOnSignal handler)
{
//
Add(
handler,
mOnSignalEventHandlers //
);
}
//
double MinRequiredProfitPerTrade()
{
return mMinRequiredProfitPerTrade;
}
//
void MinRequiredProfitPerTrade(double value)
{
//
if (value < 0)
{
value = 0;
}
//
mMinRequiredProfitPerTrade = value;
}
//
double MinRequiredProfitPerVolumeFactor()
{
return mMinRequiredProfitPerVolumeFactor;
}
//
void MinRequiredProfitPerVolumeFactor(double value)
{
//
if (value < 0)
{
value = 0;
}
//
if (value > 0 && value < 0.01)
{
value = 0.01;
}
//
mMinRequiredProfitPerVolumeFactor = value;
}
//
int RestingAfterHedge()
{
return mRestingAfterHedge;
}
//
void RestingAfterHedge(int value)
{
//
if (value < 0)
{
value = 0;
}
//
mRestingAfterHedge = value;
}
//
// 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()
{
//
CalculateMaxDrawdown();
//
// Draw ...
Draw();
//
// Check Trade Events ...
OnTrade();
//
SyncSupports();
//
// First Check For Any Guard Actions ...
// then Handle Guards if Provided ...
XGuard guards[];
bool hasGuard = CheckForGuard(guards);
if (hasGuard)
{
DoGuards(guards);
}
//
XSignal signals[];
//
// Second Check for Position Management or Equity Management
// Actions like Supports or etc ...
bool isIgnored = HandleStateManagement(signals);
if (isIgnored)
{
return;
}
//
// Check Sleeping State ...
bool isSlept = IsSlept();
if (isSlept)
{
return;
}
//
// Second Check For Signals ...
// then Execute Signals if Provided ...
int signalsCount = RequestForSignal(signals);
if (signalsCount <= 0)
{
return;
}
//
// Execute Signals ...
HandleSignalsExecution(signals);
//
Clean(guards);
Clean(signals);
}
//
// These are Some Event Handler ...
//
// Calls whenever a signal Executed ...
virtual void OnSignalExecuted(const XSignal &signal) {}
//
// Cals whenever a Signal Execution Failed ...
virtual void OnSignalExecutionFailed(
const XSignal &signal,
const ENUM_X_SIGNAL_EXECUTION_RESULT reason //
)
{
}
//
// Calls when a Position Modified ...
virtual void OnPositionModified(
const XPosition &position,
const string comment //
)
{
}
//
// Calls when a Position Closed ...
virtual void OnPositionClosed(
const XPosition &position,
const string comment //
)
{
}
//
// Calls when a Position Partially Closed ...
virtual void OnPositionPartialyClosed(
const XPosition &position,
const string comment //
)
{
}
//
// 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_X_POSITION_TYPES type, // Trading Type
ENUM_TIMEFRAMES period // Specified Time Frame
)
{
return false;
}
//
// Handle Position(s)/ Order(s) or EQM Supporting Action ...
// if returns true, prevent for process Tick ...
virtual bool HandleStateManagement(XSignal &signals[])
{
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;
}
//
int managedSignalsCount = HandleSignalManagement(signals);
if (managedSignalsCount <= 0)
{
return;
}
//
// Notify Signal Event Handlers for Reciving New Signal ...
for (int i = 0; i < managedSignalsCount; i++)
{
NotifyOnSignalEventHandlers(signals[i]);
}
//
// Try to Execute Signals ...
ENUM_X_SIGNAL_EXECUTION_RESULT reasons[];
int executedSignalsCount = ExecuteSignals(
signals,
reasons //
);
}
//
// Tools ...
//
// Calculate Max Drawdown and it's Percent ...
double CalculateMaxDrawdown()
{
//
int positionsCount = PositionsTotal();
if (IsValidSize(positionsCount))
{
double mEquity = mTrader.mAccount.GetEquity();
if (mEquity > mMaxDrawdown)
{
mMaxDrawdown = mEquity;
}
//
mDrawdownPercent = (mMaxDrawdown - mEquity) / (mStaticBalanceForCalculateDrawdown > 0 ? mStaticBalanceForCalculateDrawdown : mMaxDrawdown) * 100;
mDrawdownPercent = NormalizeDouble(mDrawdownPercent, 3);
}
else
{
//
mMaxDrawdown = 0.0;
mDrawdownPercent = 0.0;
}
//
return mDrawdownPercent;
}
//
// Protected ...
protected:
//
// Props ...
//
// Check in Test Mode or not ...
bool mIsInTestMode;
//
// Save Max Drawdown ...
double mMaxDrawdown;
double mDrawdownPercent;
double mStaticBalanceForCalculateDrawdown;
//
//
// Tools ...
//
// Since we need to Calls Some Event Handlers on
// - Signal Execution;
// - Modified;
// - Closed;
// - Partial Closed;
// events ...
// we have to implement thouse Methods here and use them ...
//
// Execute Stand alone Signal ...
bool ExecuteSignal(
XSignal &signal, // Signal
ENUM_X_SIGNAL_EXECUTION_RESULT &state, // Result
bool checkPolicies = true, // Check Account Policies
ENUM_ORDER_TYPE_TIME lifetime = ORDER_TIME_GTC, // Order LifeTime
datetime expiration = NULL // order expiration time
)
{
//
bool result = false;
//
result = mTrader.ExecuteSignal(
signal,
state,
lifetime,
expiration,
checkPolicies //
);
if (result)
{
//
OnSignalExecuted(signal);
//
string message = "Signal Executed (" + ToString(signal.positionId) + ") Successfully ...";
//
Alert(message);
}
else
{
//
OnSignalExecutionFailed(signal, state);
// //
// string message = "Signal Execution Failed: " + ToString(state) + " ...";
// //
// Alert(message);
}
//
return result;
}
//
// Execute a Collection of Signals ...
int ExecuteSignals(
XSignal &signals[], // Collection of Signal for Execution
ENUM_X_SIGNAL_EXECUTION_RESULT &states[], // Signal Execution Result
bool checkPolicies = true, // Check Account Policies
ENUM_ORDER_TYPE_TIME lifetime = ORDER_TIME_GTC, // Order LifeTime
datetime expiration = NULL // order expiration time
)
{
//
int result = 0;
//
int signalsCount = ArraySize(signals);
if (!IsValidSize(signalsCount))
{
return result;
}
//
Clean(states);
ArrayResize(states, signalsCount, X_SIGNAL_EXECUTION_UNKNOWN);
//
for (int i = 0; i < signalsCount; i++)
{
//
bool isExecuted = ExecuteSignal(
signals[i],
states[i],
checkPolicies,
lifetime,
expiration //
);
if (isExecuted)
{
result++;
}
}
//
return result;
}
//
// Modify ...
bool Modify(
ulong ticket, // position ticket
double sl = 0, // stop loss price
double tp = 0, // take profit
string comment = NULL // comment
)
{
//
bool result = false;
//
result = mTrader.Modify(
ticket,
sl,
tp,
comment //
);
//
if (result)
{
//
XPosition position;
result = mTrader.GetPosition(
ticket,
position //
);
if (result)
{
//
OnPositionModified(
position,
comment //
);
//
string message = "Position " + ToString(ticket) + " Modified Successfully ...";
//
Alert(message);
}
}
//
return result;
}
//
// Close ...
bool Close(
ulong ticket,
string comment //
)
{
//
bool result = false;
//
XPosition position;
result = mTrader.GetPosition(
ticket,
position //
);
//
result = mTrader.Close(
ticket,
comment //
);
//
if (result)
{
//
OnPositionClosed(
position,
comment //
);
//
string message = "Position " + ToString(ticket) + " Closed Successfully ...";
//
Alert(message);
}
//
return result;
}
//
// Close ...
int Close(
XPosition &positions[],
string comment //
)
{
//
int result = 0;
//
int count = ArraySize(positions);
if (!IsValidSize(count))
{
return result;
}
//
for (int i = 0; i < count; i++)
{
//
bool isClosed = Close(
positions[i].ticket,
comment //
);
//
if (isClosed)
{
result++;
}
}
//
return result;
}
//
// Partial Close ...
bool PartialClose(
ulong ticket,
double volume,
string comment //
)
{
//
bool result = false;
//
XPosition position;
result = mTrader.GetPosition(
ticket,
position //
);
if (!result)
{
return result;
}
//
result = mTrader.ClosePartial(
ticket,
volume,
comment //
);
//
if (result)
{
//
OnPositionPartialyClosed(
position,
comment //
);
//
string message = "Position " + ToString(ticket) + " Successfully Closed Parital ...";
//
Alert(message);
}
//
return result;
}
//
// Partial Close ...
int PartialClose(
XPosition &positions[],
double volume,
string comment //
)
{
//
int result = 0;
//
int count = ArraySize(positions);
if (!IsValidSize(count))
{
return result;
}
//
for (int i = 0; i < count; i++)
{
//
bool isClosed = PartialClose(
positions[i].ticket,
volume,
comment //
);
//
if (isClosed)
{
result++;
}
}
//
return result;
}
//
int CancelOrders()
{
//
int result = 0;
//
XOrder supports[];
int supportsCount = mTrader.GetOrders(
supports,
NULL, // All Symbols ...
XEQMSupportToken, // Only EQM Supports ...
NULL, // All Periods ...
X_POSITION_TYPE_ALL, // All Order Types ...
ORDER_STATE_PLACED, // Untriggered Orders ...
true // Filter by Magic ...
);
if (!IsValidSize(supportsCount))
{
return result;
}
//
result = mTrader.CancelOrders(
supports //
);
//
Clean(supports);
//
return result;
}
//
// Search Positions and Remove
// non Exists Positions Support Orders ...
void SyncSupports()
{
//
XOrder orders[];
int ordersCount = mTrader.GetOrders(
orders,
NULL, // All Symbols ...
NULL, // All Providers ...
NULL, // All Periods ...
X_POSITION_TYPE_ALL, // All Types ...
ORDER_STATE_PLACED, // Placed Untriggered Orders ...
true // Filter by Magic ...
);
if (!IsValidSize(ordersCount))
{
return;
}
//
XPosition positions[];
int positionsCount = mTrader.GetPositions(
positions //
);
if (!IsValidSize(positions))
{
//
mTrader.CancelOrders(orders);
return;
}
//
XOrder mustCancel[];
for (int i = 0; i < ordersCount; i++)
{
//
XOrder iOrder = orders[i];
//
// Check Order is Support or not ...
ulong iParentTicket = ExtractSupportedTicket(iOrder.comment);
if (iParentTicket <= 0)
{
continue;
}
//
// We Sure it is support Order ...
XPosition parent;
bool isParentExists = mTrader.GetPosition(
iParentTicket,
parent //
);
if (!isParentExists)
{
//
AddRef(
iOrder,
mustCancel //
);
}
}
//
int mustCancelCount = ArraySize(mustCancel);
if (!IsValidSize(mustCancelCount))
{
return;
}
//
mTrader.CancelOrders(mustCancel);
//
Clean(orders);
Clean(positions);
Clean(mustCancel);
}
//
// Hedging ...
//
// Check Required Properties Setted for Hedge or not ...
bool AllowHedge()
{
//
bool result = false;
//
result =
//
mMinRequiredProfitPerTrade > 0 &&
mMinRequiredProfitPerVolumeFactor > 0
//
;
//
return result;
}
//
// Check Hedge Conditions is Happens or not ...
// if true doing Hedge ...
bool DoHedge()
{
//
bool result = false;
//
result = AllowHedge();
if (!result)
{
return result;
}
//
XPosition positions[];
int positionsCount = mTrader.GetPositions(positions);
result = positionsCount > 1;
if (!result)
{
return result;
}
//
// Check At Least One Support Positions Open For Hedging ...
// XPosition supports[];
// int supportsCount = ExtractSupports(
// positions,
// supports //
// );
// result = IsValidSize(supportsCount);
// if (!result)
// {
// return result;
// }
//
double profits = SpecifiedCalculatePositionsProfit(positions);
double requiredProfit = SpecifiedCalculateRequiredProfitForHedge(
positions,
mMinRequiredProfitPerTrade,
mMinRequiredProfitPerVolumeFactor //
);
//
result =
positionsCount <= 5
? profits >= requiredProfit
: profits >= requiredProfit * 0.6;
if (!result)
{
return result;
}
//
string comment = XEQMSupportToken + " Hedge ...";
//
int closed = Close(
positions,
comment //
);
result = IsValidSize(closed);
if (!result)
{
return result;
}
//
SyncSupports();
//
string message = XEQMSupportToken + " Hedge: " + ToString(profits) + " ...";
//
Alert(message);
//
if (mRestingAfterHedge > 0)
{
Sleeping(mRestingAfterHedge);
}
//
return result;
}
//
// Signal Event Listeners ...
//
void NotifyOnSignalEventHandlers(XSignal &signal)
{
//
int listenersCount = ArraySize(mOnSignalEventHandlers);
if (listenersCount <= 0)
{
return;
}
//
for (int i = 0; i < listenersCount; i++)
{
//
TOnSignal iListener = mOnSignalEventHandlers[i];
//
iListener(signal);
}
}
//
// 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_X_POSITION_TYPES type, // Trading Type
ENUM_TIMEFRAMES period, // Specified Time Frame
double minProfitForHedging = 1, // Specified Profit for Hedge
double minProfitForHedgingVolumeFactor = 0.01 // Specified Volume Factor for Hedge
)
{
//
XPosition positions[];
int positionsCount = mTrader
.GetPositions(
positions,
symbol,
provider,
period,
type
//
);
if (positionsCount <= 1)
{
return;
}
//
double profit = SpecifiedCalculatePositionsProfit(positions);
double requiredProfit = SpecifiedCalculateRequiredProfitForHedge(
positions,
minProfitForHedging,
minProfitForHedgingVolumeFactor //
);
//
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);
//
Alert(message);
}
}
//
// Close Max In Profit Trade Guard Action ...
void HandleGuardCloseInProfitAction(
string provider, // Positions Provided by Specific Provider
string symbol, // Trading Symbol
ENUM_X_POSITION_TYPES 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 ...";
//
Alert(message);
}
//
// Close Max In Drawdown Trade Guard Action ...
void HandleGuardCloseInDrawdownAction(
string provider, // Positions Provided by Specific Provider
string symbol, // Trading Symbol
ENUM_X_POSITION_TYPES 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 ...";
//
Alert(message);
}
//
// Force Close Specified Set Of Position ...
void HandleGuardForceCloseAction(
string provider, // Positions Provided by Specific Provider
string symbol, // Trading Symbol
ENUM_X_POSITION_TYPES 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))
{
Alert(comment);
}
}
//
// Trailing Specified Set Of Positions Stop Losses ...
void HandleGuardTrailingStopAction(
string provider, // Positions Provided by Specific Provider
string symbol, // Trading Symbol
ENUM_X_POSITION_TYPES 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 ...";
//
Alert(message);
}
}
//
// Add Support Signal for Specified Positions ...
void HandleGuardAddSupportPositionAction(
string provider, // Positions Provided by Specific Provider
string symbol, // Trading Symbol
ENUM_X_POSITION_TYPES 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 = 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))
{
Alert(comment);
}
}
//
// Cancel all Placed Orders ...
void HandleGuardCancelPendingOrdersAction(
string provider, // Positions Provided by Specific Provider
string symbol, // Trading Symbol
ENUM_X_POSITION_TYPES type, // Trading Type
ENUM_TIMEFRAMES period // Specified Time Frame
)
{
//
XOrder orders[];
int ordersCount = mTrader.GetOrders(
orders,
symbol,
provider,
period,
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 ...";
//
Alert(message);
}
}
//
// Sleeping Context ...
//
// Sleeping Mode ...
int mSleepingDuration;
datetime mSleepingStartAt;
bool Sleeping(int seconds = -1)
{
//
bool result = false;
//
mSleepingDuration =
seconds > 0
? seconds
: mRestingAfterHedge > 0
? mRestingAfterHedge
: 0;
result = mSleepingDuration > 0;
if (!result)
{
//
ResetSleeping();
return result;
}
//
// Check Doesnt Sleep Before ...
result = mSleepingStartAt == NULL;
if (!result)
{
//
ResetSleeping();
return result;
}
//
datetime cTime = TimeCurrent();
mSleepingStartAt = cTime;
//
return result;
}
bool IsSlept()
{
//
bool result = false;
//
result = mSleepingDuration > 0 &&
mSleepingStartAt != NULL;
if (!result)
{
//
ResetSleeping();
return result;
}
//
datetime cTime = TimeCurrent();
result = (int)cTime < (int)mSleepingStartAt + mSleepingDuration;
if (!result)
{
ResetSleeping();
}
//
return result;
}
void ResetSleeping()
{
//
mSleepingDuration = 0;
mSleepingStartAt = NULL;
}
//
// Private ...
private:
//
// Props ...
//
int mRestingAfterHedge; // Resting Bars After Hedge
double mMinRequiredProfitPerTrade; // Minimum Required Profit for Hedging
double mMinRequiredProfitPerVolumeFactor; // Minimum Required Profit for Hedging Per Velume
//
// Signal Event Listeners ...
TOnSignal mOnSignalEventHandlers[];
//
// Event Handlers ...
TOnSignal mOnSignal;
TOnModify mOnModifyPosition;
TOnStopLoss mOnStopLossTriggered;
TOnTakeProfit mOnTakeProfitTriggered;
TOnForceClose mOnForceClosePosition;
TOnDealsChanged mOnDealsChangedHandler;
TOnPartialClose mOnPartialClosePosition;
TOnOrdersChanged mOnOrdersChangedHandler;
TOnPositionsChanged mOnPositionsChangedHandler;
TOnTradeStateChanged mOnTradeStateChangedHandler;
};
//