1154 lines
28 KiB
Plaintext
1154 lines
28 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"
|
|
|
|
//
|
|
// 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() {}
|
|
|
|
//
|
|
// 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);
|
|
}
|
|
|
|
//
|
|
// 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()
|
|
{
|
|
//
|
|
// 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 = CheckForSignal(signals);
|
|
if (signalsCount <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Try to Execute Signals ...
|
|
ENUM_X_SIGNAL_EXECUTION_RESULT reasons[];
|
|
int executedSignalsCount = mTrader.ExecuteSignals(
|
|
signals,
|
|
reasons);
|
|
|
|
//
|
|
string message = NULL;
|
|
if (executedSignalsCount == 0)
|
|
{
|
|
message = "(" + ToString(signalsCount) + ") Signals Execution Failed ...";
|
|
}
|
|
else if (executedSignalsCount < signalsCount)
|
|
{
|
|
//
|
|
int diff = signalsCount - executedSignalsCount;
|
|
|
|
//
|
|
message = "Failed to Execute (" + ToString(diff) + ") Signals ...";
|
|
}
|
|
else if (executedSignalsCount == signalsCount)
|
|
{
|
|
message = "(" + ToString(executedSignalsCount) + ") Signals Executed Successfully ...";
|
|
}
|
|
|
|
//
|
|
if (IsValid(message))
|
|
{
|
|
mAlert.Alert(message);
|
|
}
|
|
}
|
|
|
|
//
|
|
// 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 ...
|
|
}
|
|
|
|
//
|
|
// 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 CheckForSupport(
|
|
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;
|
|
}
|
|
|
|
//
|
|
// 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 CheckForSignal(
|
|
XSignal &signals[] // Holds Signals ...
|
|
)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// Protected ...
|
|
protected:
|
|
//
|
|
// Props ...
|
|
|
|
//
|
|
// 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;
|
|
}
|
|
|
|
//
|
|
// 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 = CheckForSupport(
|
|
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 ...
|
|
|
|
//
|
|
// Trade Class Instance ...
|
|
XSCTrade *mTrader;
|
|
XSCAlert *mAlert;
|
|
|
|
//
|
|
// Check in Test Mode or not ...
|
|
bool mIsInTestMode;
|
|
|
|
//
|
|
// 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;
|
|
}
|
|
|
|
// |