Files
MQL5Data/X121SMCEA/Experts/x-121.smc.expert.class.mq5
T
2025-02-01 19:59:02 +03:30

2506 lines
61 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
///////////////////////////////////////////////////////
//
// SaherElm IT Center MQL5 Class Library
// --------------------------------------
// Name: XC121SMCExpert
// Description: provides all based classes for use ...
//
//
// 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.x-expert.class.mq5"
#include "../Classes/x-121.smc.x-tradehandler.class.mq5"
#include "../Libraries/x-121.smc.lib.mq5"
#include "../Strategy/x-121.smc.strategy.class.mq5"
//
// Definitions ...
string XC121SMCExpertToken = "XC121SMCEA";
//
// Implementation ...
class XC121SMCExpert : public XCBaseExpert
{
//
public:
//
//
// Signal Event Listener ...
TOnStopLoss OnPositionSLEventListener;
TOnTakeProfit OnPositionTPEventListener;
TOnPartialClose OnPositionPartialCloseEventListener;
TOnModify OnPositionModifiedEventListener;
TOnForceClose OnPositionForceCloseEventListener;
//
TOnDealsChanged OnDealsChangedEventListener;
TOnOrdersChanged OnOrdersChangedEventListener;
TOnPositionsChanged OnPositionsChangedEventListener;
//
TOnX121SMCSignal OnSignalEventListener;
//
// Constructor(s) ...
XC121SMCExpert()
{
}
//
// Deconstructor(s) ...
~XC121SMCExpert()
{
Clean(mStrategies);
}
//
// Getter(s) / Setter(s) ...
//
// Signalling Props ...
/**
* Get Allow Long Signals State ...
*
* @return ( bool )
*/
bool AllowLong()
{
return mAllowLong;
}
/**
* Set Allow Long Signals State ...
*
* @param value: Boolean ...
*/
void AllowLong(bool value)
{
//
mAllowLong = value;
ReConfigure();
}
/**
* Get Allow Short Signals State ...
*
* @return ( bool )
*/
bool AllowShort()
{
return mAllowShort;
}
/**
* Set Allow Short Signals State ...
*
* @param value: Boolean ...
*/
void AllowShort(bool value)
{
//
mAllowShort = value;
ReConfigure();
}
/**
* Get Max Allowed Long Signals ...
* 0 => Unlimited ...
*
* @return ( int )
*/
int MaxAllowedLongs()
{
return mMaxAllowedLongs;
}
/**
* Set Max Allowed Long Signals ...
*
* @param value: Integer ...
* 0 => Unlimited ...
*/
void MaxAllowedLongs(int value)
{
//
if (value < 0)
{
value = 0;
}
//
mMaxAllowedLongs = value;
ReConfigure();
}
/**
* Get Max Allowed Short Signals ...
* 0 => Unlimited ...
*
* @return ( int )
*/
int MaxAllowedShorts()
{
return mMaxAllowedShorts;
}
/**
* Set Max Allowed Short Signals ...
*
* @param value: Integer ...
* 0 => Unlimited ...
*/
void MaxAllowedShorts(int value)
{
//
if (value < 0)
{
value = 0;
}
//
mMaxAllowedShorts = value;
ReConfigure();
}
/**
* Get Use Max Allowed Signal Types Per Symbol State ...
*
* @return ( bool )
*/
bool UseMaxAllowedSignalsPerSymbol()
{
return mUseMaxAllowedSignalsPerSymbol;
}
/**
* Set Use Max Allowed Signal Types Per Symbol State ...
*
* @param value: Boolean ...
*/
void UseMaxAllowedSignalsPerSymbol(bool value)
{
//
mUseMaxAllowedSignalsPerSymbol = false;
ReConfigure();
}
/**
* Get Last Position Profit In Points for Accept new Signal ...
* 0 => Accept All ...
*
* @return ( double )
*/
double LastPositionProfitForAcceptNextInPoint()
{
return mLastPositionProfitForAcceptNextInPoint;
}
/**
* Set Last Position Profit In Points for Accept new Signal ...
*
* @param value: Double ...
* 0 => Accept All ...
*/
void LastPositionProfitForAcceptNextInPoint(double value)
{
//
if (value < 0)
{
value = 0;
}
//
mLastPositionProfitForAcceptNextInPoint = value;
ReConfigure();
}
/**
* Get Delay between two Signals in Bars ...
* 0 => Accept All ...
*
* @return ( int )
*/
int DelaysBetweenTwoSignalsInBar()
{
return mDelaysBetweenTwoSignalsInBar;
}
/**
* Set Delay between two Signals in Bars ...
*
* @param value: Integer ...
* 0 => Accept All ...
*/
void DelaysBetweenTwoSignalsInBar(int value)
{
//
if (value < 0)
{
value = 0;
}
//
mDelaysBetweenTwoSignalsInBar = value;
ReConfigure();
}
/**
* Get Max Allowed Spread for Signalling ...
* 0 => Accept All ...
*
* @return ( double )
*/
double MaxAllowedSpread()
{
return mMaxAllowedSpread;
}
/**
* Set Max Allowed Spread for Signalling ...
*
* @param value: Double ...
* 0 => Accept All ...
*/
void MaxAllowedSpread(double value)
{
//
if (value < 0)
{
value = 0;
}
//
mMaxAllowedSpread = value;
ReConfigure();
}
/**
* Get Minimum Spread Verification for Signalling ...
* 0 => Ignore ...
*
* @return ( int )
*/
int MinRequiredVerificationForSpreadPass()
{
return mMinRequiredVerificationForSpreadPass;
}
/**
* Set Minimum Spread Verification for Signalling ...
*
* @param value: Integer ...
* 0 => Ignore ...
*/
void MinRequiredVerificationForSpreadPass(int value)
{
//
if (value < 0)
{
value = 0;
}
//
mMinRequiredVerificationForSpreadPass = value;
ReConfigure();
}
//
// Trade ...
/**
* Get Allow Open Trade On Signals State ...
*
* @return ( bool )
*/
bool AllowTrade()
{
return mAllowTrade;
}
/**
* Set Allow Open Trade On Signals State ...
*
* @param value: Boolean ...
*/
void AllowTrade(bool value)
{
mAllowTrade = value;
}
/**
* Get Enable Trade on Signals on Time ...
*
* @return ( string )
*/
string StartTradeAt()
{
return mStartTradeAt;
}
/**
* Set Enable Trade on Signals on Time ...
*
* @param value: String ...
*/
void StartTradeAt(string value)
{
mStartTradeAt = value;
}
/**
* Get Enable Trade on Signals on Time ...
*
* @return ( string )
*/
string StopTradeAt()
{
return mStopTradeAt;
}
/**
* Set Enable Trade on Signals on Time ...
*
* @param value: String ...
*/
void StopTradeAt(string value)
{
mStopTradeAt = value;
}
/**
* Get Enable Close All Trades on Signals on Time ...
*
* @return ( string )
*/
string CloseAllTradesAt()
{
return mCloseAllTradesAt;
}
/**
* Set Enable Close All Trades on Signals on Time ...
*
* @param value: String ...
*/
void CloseAllTradesAt(string value)
{
mCloseAllTradesAt = value;
}
//
// Risk Management Props ...
/**
* Get Risk to Reward Ratio ...
*
* @return ( double )
*/
double R2R()
{
return mR2R;
}
/**
* Set Risk to Reward Ratio ...
*
* @param value: Double ...
*/
void R2R(double value)
{
//
if (value < 1)
{
value = 1;
}
//
mR2R = value;
ReConfigure();
}
/**
* Get Static Volume ...
*
* @return ( double )
*/
double Volume()
{
return mVolume;
}
/**
* Set Static Volume ...
*
* @param value: Double ...
*/
void Volume(double value)
{
//
if (value < 0.01)
{
value = 0.01;
}
//
mVolume = value;
ReConfigure();
}
/**
* Get Static Balance for Calculate Trade Volume ...
*
* @return ( double )
*/
double StaticBalance()
{
return mStaticBalance;
}
/**
* Set Static Balance for Calculate Trade Volume ...
*
* @param value: Argument 1
*/
void StaticBalance(double value)
{
//
if (value < 0)
{
value = 0;
}
//
mStaticBalance = value;
}
/**
* Get Balance Used In Each Trade ...
*
* @return ( double )
*/
double BalancePerTrade()
{
return mBalancePerTrade;
}
/**
* Set Balance Used In Each Trade ...
*
* @param value: Argument 1
*/
void BalancePerTrade(double value)
{
//
if (value < 0)
{
value = 0;
}
//
mBalancePerTrade = value;
}
/**
* Get Risk Percent Per Balance in Each Trade ...
*
* @return ( double )
*/
double RiskPercentPerBalance()
{
return mRiskPercentPerBalance;
}
/**
* Set Risk Percent Per Balance in Each Trade ...
*
* @param value: Double
*/
void RiskPercentPerBalance(double value)
{
//
if (value < 0)
{
value = 0;
}
//
mRiskPercentPerBalance = value;
ReConfigure();
}
/**
* Get Dynamic Risk Management State ...
*
* @return ( bool )
*/
bool DynamicRiskManagement()
{
return mDynamicRiskManagement;
}
/**
* Set Dynamic Risk Management State ...
*
* @param value: Boolean ...
*/
void DynamicRiskManagement(bool value)
{
//
mDynamicRiskManagement = value;
ReConfigure();
}
/**
* Get Use Dynamic Volume State ...
*
* @return ( bool )
*/
bool UseDynamicVolume()
{
return mUseDynamicVolume;
}
/**
* Set Use Dynamic Volume State ...
*
* @param value: Boolean ...
*/
void UseDynamicVolume(bool value)
{
//
mUseDynamicVolume = value;
ReConfigure();
}
/**
* Get Increase Volume Step ...
*
* @return ( double )
*/
double DynamicVolumeStep()
{
return mDynamicVolumeStep;
}
/**
* Set Increase Volume Step ...
*
* @param value: Double ...
*/
void DynamicVolumeStep(double value)
{
//
if (value < 0.01)
{
value = 0.01;
}
//
mDynamicVolumeStep = value;
ReConfigure();
}
/**
* Get Balance Factor for Generate Dynamic Volume ...
*
* @return ( double )
*/
double DynamicVolumeBalanceFactor()
{
return mDynamicVolumeBalanceFactor;
}
/**
* Set Balance Factor for Generate Dynamic Volume ...
*
* @param value: Double ...
*/
void DynamicVolumeBalanceFactor(double value)
{
//
if (value < 0)
{
value = 0;
}
//
mDynamicVolumeBalanceFactor = value;
ReConfigure();
}
/**
* Get Max Allowed Drawdown Percent for Open Trades ...
* 0 => Ignore ...
* min => 0 ...
* max => 100 ...
*
* @return ( double )
*/
double MaxAllowedDrawdownToOpenTrades()
{
return mMaxAllowedDrawdownToOpenTrades;
}
/**
* Set Max Allowed Drawdown Percent for Open Trades ...
*
* @param value: Double ...
* 0 => Ignore ...
* min => 0 ...
* max => 100 ...
*/
void MaxAllowedDrawdownToOpenTrades(double value)
{
//
if (value < 0)
{
value = 0;
}
//
if (value > 50)
{
value = 50;
}
//
mMaxAllowedDrawdownToOpenTrades = value;
ReConfigure();
}
/**
* Get Max Allowed SL for Pause Signalling Per Symbol ...
* 0 => Unlimited ...
*
* @return ( int )
*/
int MaxAllowedSLToPauseSignallingPerSymbol()
{
return mMaxAllowedSLToPauseSignallingPerSymbol;
}
/**
* Set Max Allowed SL for Pause Signalling Per Symbol ...
*
* @param value: Integer ...
* 0 => Unlimited ...
*/
void MaxAllowedSLToPauseSignallingPerSymbol(int value)
{
//
if (value < 0)
{
value = 0;
}
//
mMaxAllowedSLToPauseSignallingPerSymbol = value;
ReConfigure();
}
/**
* Get Pause Signalling Per Symbol afte Max Allowed SL Reached In Seconds ...
* 0 => Ignore ...
*
* @return ( int )
*/
int PauseSignallingAfterReachesMaxAllowedSLInSecconds()
{
return mPauseSignallingAfterReachesMaxAllowedSLInSecconds;
}
/**
* Set Pause Signalling Per Symbol afte Max Allowed SL Reached In Seconds ...
*
* @param value: Integer ...
* 0 => Ignore ...
*/
void PauseSignallingAfterReachesMaxAllowedSLInSecconds(int value)
{
//
if (value < 0)
{
value = 0;
}
//
mPauseSignallingAfterReachesMaxAllowedSLInSecconds = value;
ReConfigure();
}
//
// Protection Props ...
/**
* Get Allow Hedge Positions State ...
*
* @return ( bool )
*/
bool AllowHedging()
{
return mAllowHedging;
}
/**
* Set Allow Hedge Positions State ...
*
* @param value: Boolean ...
*/
void AllowHedging(bool value)
{
//
mAllowHedging = value;
ReConfigure();
}
/**
* Get Minimum Open Positions for Hedging ...
* 0 => Ignore ...
*
* @return ( int )
*/
int MinOpenTradesFroHedging()
{
return mMinOpenTradesFroHedging;
}
/**
* Set Minimum Open Positions for Hedging ...
*
* @param value: Integer ...
* 0 => Ignore ...
*/
void MinOpenTradesFroHedging(int value)
{
//
if (value < 0)
{
value = 0;
}
//
mMinOpenTradesFroHedging = value;
ReConfigure();
}
/**
* Get Minimum Volume Step for Hedging ...
* 0 => Ignore ...
*
* @return ( double )
*/
double HedgingMinVolumeStep()
{
return mHedgingMinVolumeStep;
}
/**
* Set Minimum Volume Step for Hedging ...
*
* @param value: Double ...
* 0 => Ignore ...
*/
void HedgingMinVolumeStep(double value)
{
//
if (value < 0)
{
value = 0;
}
//
if (value > 0 && value < 0.01)
{
value = 0.01;
}
//
if (value > 0 && value > 0.1)
{
value = 0.1;
}
//
mHedgingMinVolumeStep = value;
ReConfigure();
}
/**
* Get Minimum Required Profit Per Volume Step for Hedging ...
* 0 => Ignore ...
*
* @return ( double )
*/
double HedgeingMinRequiredProfitPerVolumeStep()
{
return mHedgeingMinRequiredProfitPerVolumeStep;
}
/**
* Set Minimum Required Profit Per Volume Step for Hedging ...
*
* @param value: Double ...
* 0 => Ignore ...
*/
void HedgeingMinRequiredProfitPerVolumeStep(double value)
{
//
if (value < 0)
{
value = 0;
}
//
mHedgeingMinRequiredProfitPerVolumeStep = value;
ReConfigure();
}
//
// Actions ...
/**
* Handle OnSignalRecieved Event ...
*
* @param signal: XSignal instance ...
* @param conditions: X121SMCStrategyConditions instance ...
*/
void HandleOnSignalRecieved(
XSignal &signal,
X121SMCStrategyConditions &conditions //
)
{
//
// Check Signal and Conditions Validations ...
//
if (!signal.IsValid())
{
return;
}
//
if (!conditions.IsValid())
{
return;
}
//
bool isLong = IsLong(signal.type);
//
// Notify When a Raw (Unfiltered) Signal Recieved
// if it's Provided ...
bool mAlertRawSignals = false;
if (mAlertRawSignals)
{
//
string msg = "Raw " + (IsLong(signal.type) ? "Long" : "Short") +
" Signal Recieved: (" + signal.provider + "," +
signal.symbol + "," +
ToString(signal.period) +
") ...";
//
Alert(msg);
}
//
// Apply Volume On Signal ...
ApplyVolumeOnSignal(signal);
//
// Chekc Signalling Enable or not ...
bool canContinue =
isLong
? AllowLong()
: AllowShort();
if (!canContinue)
{
return;
}
//
// TODO: Apply Filtering On Signal ...
bool isFiltered = false;
if (isFiltered)
{
//
mTradeHandler.Remove(signal);
return;
}
//
// Attach Conditions Summary to Signal ...
string conditionsSummary = conditions.GenerateSummary(
false,
false,
true,
false //
);
//
// TODO: Retrieve Conditions Summary based on Filter ...
signal.conditions = conditionsSummary;
//
datetime currentTime = TimeCurrent();
//
// Chack Allow Trades ...
bool allowTrade = AllowTrade();
if (allowTrade)
{
//
string startTime = StartTradeAt();
string endTime = StopTradeAt();
bool isTimePassed = IsTimeInRange(
TimeCurrent(),
startTime,
endTime //
);
//
if (isTimePassed)
{
//
// Execute Signal Using Trade Handler ...
ENUM_X_SIGNAL_EXECUTION_RESULT state;
bool isExecuted = mTradeHandler.ExecuteSignal(
signal,
conditions,
state,
false // ignore Policies ...
);
}
}
else
{
//
// Only Alert Signals ...
string msg = (IsLong(signal.type)
? "Long"
: "Short") +
" Signal Recieved: (" +
signal.provider + "," +
signal.symbol + "," +
ToString(signal.period) +
") ...";
//
Alert(msg);
//
// Draw Signals and Conditions ...
if (eaDrawer != NULL)
{
//
XCBaseObject *objects[];
XCSignalObject *signalObject;
bool isCreated = eaDrawer.DrawSignal(
signal,
signalObject //
);
// DrawX121SMCStrategyConditions(
// conditions,
// objects,
// eaDrawer,
// true, // draw Market Structure ...
// true, // Draw Price Zones ...
// true // Draw Decision Zones ...
// );
//
Add(
(XCBaseObject *)signalObject,
objects //
);
//
Clean(objects);
}
}
//
signal.Clean();
conditions.Clean();
}
//
// Override Actions ...
/**
* Apply Default Configurations ...
*/
void DefaultConfigure() override
{
//
// Commons ...
Slippage(10);
TagPrefix("");
MagicNumber(1694056);
//
// Symbol ...
SetSymbol(_Symbol);
SetPeriod(_Period);
MultiSymbol(false);
Symbols("EURUSDb,GBPUSDb,USDJPYb,USDCHFb,DowJones30,XAUUSDb");
//
// Signalling ...
Disabled(false);
AllowLong(true);
AllowShort(true);
//
string tag = GetTag();
//
// Alert ...
SetAlertPrefix(tag);
SetAlertLogAlerts(true);
SetAlertPushAlerts(true);
SetAlertMailAlerts(false);
SetAlertEnableAlerts(true);
SetAlertTerminalAlerts(false);
//
// Reports ...
ReportNewDays(true);
ReportNewWeeks(false);
ReportNewHours(false);
ReportNewMonths(false);
//
R2R(1);
//
// Volume Default Configurations ...
Volume(0.01);
UseDynamicVolume(false);
DynamicVolumeStep(0.01);
DynamicVolumeBalanceFactor(200);
//
RiskPercentPerBalance(0);
DynamicRiskManagement(false);
}
/**
* Vaslidate Inputs ...
*
* @return ( bool )
*/
bool ValidateInputs() override
{
//
bool result = false;
//
string errMessage = "";
//
bool isCommonValid = (
//
Slippage() > 0 &&
MagicNumber() > 0
//
);
if (!isCommonValid)
{
//
errMessage += "common configurations error;" + "\n";
}
//
// Checking Volume ...
bool isVolumeValid = true;
if (UseDynamicVolume())
{
//
isVolumeValid =
DynamicVolumeStep() > 0 &&
DynamicVolumeBalanceFactor() > 0;
if (!isVolumeValid)
{
errMessage += "Dynamic Volume configurations error;" + "\n";
}
}
isVolumeValid = isVolumeValid &&
Volume() > 0;
if (!isVolumeValid)
{
errMessage += "Static Volume configurations error;" + "\n";
}
//
result =
//
// Common ...
isCommonValid &&
//
// Volume Coniguration ...
isVolumeValid &&
//
// Otere ...
true
//
;
//
if (!result)
{
//
// Since here Logger not Initiallized, we Use Raw Print Command ...
errMessage = " Errors: \n" + errMessage;
Alert(errMessage);
}
//
return result;
}
//
// Initializers and DeInitializers ...
/**
* Initial EA Requirements ...
*
* @return ( bool )
*/
bool InitEA() override
{
//
bool result = false;
//
// Initialize Indicator Helpers ...
//
// Bar Timer ...
XCTInputs ctInputs;
ctInputs.Default(); // Default Configurations ...
mCTHelper = new XCXCTHelper();
result = mCTHelper.Init(
GetSymbol(),
GetPeriod(),
ctInputs //
);
if (!result)
{
return result;
}
//
// Bar Styles ...
XCCInputs ccInputs;
ccInputs.Default(); // Default Configurations ...
mCCHelper = new XCXCCHelper();
result = mCCHelper.Init(
GetSymbol(),
GetPeriod(),
ccInputs //
);
if (!result)
{
return result;
}
//
// Configure Alerts ...
SetAlertPrefix(GetTag());
SetAlertEnableAlerts(GetAlertEnableAlerts());
SetAlertLogAlerts(GetAlertLogAlerts());
SetAlertMailAlerts(GetAlertMailAlerts());
SetAlertPushAlerts(GetAlertPushAlerts());
SetAlertTerminalAlerts(GetAlertTerminalAlerts());
//
// Create Trader Instance and Configure it ...
mTrader = new XCTrade(
Slippage(),
MagicNumber() //
);
mTrader.AddOnStopLossEventHandler(OnPositionSLEventListener);
mTrader.AddOnTakeProfitEventHandler(OnPositionTPEventListener);
mTrader.AddOnDealsChangedEventHandler(OnDealsChangedEventListener);
mTrader.AddOnOrdersChangedEventHandler(OnOrdersChangedEventListener);
mTrader.AddOnModifyPositionEventHandler(OnPositionModifiedEventListener);
mTrader.AddOnPositionsChangedEventHandler(OnPositionsChangedEventListener);
mTrader.AddOnForceClosePositionEventHandler(OnPositionForceCloseEventListener);
mTrader.AddOnPartialClosePositionEventHandler(OnPositionPartialCloseEventListener);
//
// Initialize Trade Handler ...
mTradeHandler = new XC121SMCTradeHandler(mTrader);
mTradeHandler.SaveTrades(false);
mTradeHandler.SaveSignals(false);
mTradeHandler.SaveConditions(false);
//
ReConfigureTradeHandler();
//
// Parsers ...
XSymbolParser _symbolParser;
eaDrawer = NULL;
//
// Single Symbol ...
if (!MultiSymbol())
{
//
// Register Strategy ...
//
// Create Class Instance ...
XCX121SMCBaseStrategy *iX121SMCStrategy;
iX121SMCStrategy = new XCX121SMCStrategy(
_Symbol,
_Period //
);
//
if (eaDrawer == NULL)
{
//
eaDrawer = iX121SMCStrategy
.GetDrawer();
}
//
iX121SMCStrategy.AddXSignalEventHandler(OnSignalEventListener);
//
ConfigureStrategy(iX121SMCStrategy);
RegisterStrategy(iX121SMCStrategy);
}
//
// Multi Symbol ...
else
{
//
// Parse Symbols ...
string symbols[];
int symbolsCount = SplitContent(
symbols,
Symbols() //
);
result = IsValidSize(symbolsCount);
if (!result)
{
return result;
}
//
for (int i = 0; i < symbolsCount; i++)
{
//
// Select Symbol ...
string iSymbol = symbols[i];
//
// Register Strategy Based On Symbol ...
//
// Parse Symbol ...
bool isEURUSD = _symbolParser.IsEURUSD(_Symbol);
bool isGBPUSD = _symbolParser.IsGBPUSD(_Symbol);
bool isEURGBP = _symbolParser.IsEURGBP(_Symbol);
bool isUSDCHF = _symbolParser.IsUSDCHF(_Symbol);
bool isEURCHF = _symbolParser.IsEURCHF(_Symbol);
bool isUSDJPY = _symbolParser.IsUSDJPY(_Symbol);
bool isEURJPY = _symbolParser.IsEURJPY(_Symbol);
bool isUSDCAD = _symbolParser.IsUSDCAD(_Symbol);
bool isEURCAD = _symbolParser.IsEURCAD(_Symbol);
bool isAUDUSD = _symbolParser.IsAUDUSD(_Symbol);
bool isEURAUD = _symbolParser.IsEURAUD(_Symbol);
bool isNZDUSD = _symbolParser.IsNZDUSD(_Symbol);
bool isEURNZD = _symbolParser.IsEURNZD(_Symbol);
//
// Check Symbol Can Register or not ...
bool canRegisterStrategy = true;
//
if (canRegisterStrategy)
{
//
// Create Class Instance ...
XCX121SMCBaseStrategy *iX121SMCStrategy;
iX121SMCStrategy = new XCX121SMCStrategy(
iSymbol,
_Period //
);
//
if (eaDrawer == NULL)
{
//
eaDrawer = iX121SMCStrategy
.GetDrawer();
}
//
iX121SMCStrategy.AddXSignalEventHandler(OnSignalEventListener);
//
// Register Strategy ...
ConfigureStrategy(iX121SMCStrategy);
RegisterStrategy(iX121SMCStrategy);
}
}
//
Clean(symbols);
}
//
if (eaDrawer != NULL)
{
mTradeHandler.SetDrawer(eaDrawer);
}
//
return result;
}
/**
* Destroy all Initialized EA Requirements ...
*/
void DestroyEA() override
{
//
ZeroMemory(mCTHelper);
ZeroMemory(mCCHelper);
ZeroMemory(mTradeHandler);
//
delete mCTHelper;
delete mCCHelper;
delete mTradeHandler;
//
Clean(mStrategies);
}
/**
* Call all Registered Strategies On Tick ...
*/
void HandleStrategiesOnTick() override
{
//
// Check Force Close ...
string forceCloseTimeStr = CloseAllTradesAt();
if (IsValid(forceCloseTimeStr))
{
//
datetime forceCloseTime = ParseDateTimeFromTimeString(forceCloseTimeStr);
bool canForceClose = IsTimeInRange(
TimeCurrent(),
forceCloseTime //
) &&
!mIsForceCloseAtTime;
if (canForceClose)
{
mIsForceCloseAtTime = mTradeHandler.ForceClose();
}
}
//
// Update Positions Data ...
mTradeHandler.UpdateData();
//
// Protect Positions ...
mTradeHandler.HandleProtection();
//
int count = ArraySize(mStrategies);
if (!IsValidSize(count))
{
return;
}
//
for (int i = 0; i < count; i++)
{
//
// Call Tick Handler Function ...
mStrategies[i].HandleTick();
}
}
/**
* Handle Strategies Guards ...
*/
void HandleStrategiesGuard() override
{
//
int count = ArraySize(mStrategies);
if (!IsValidSize(count))
{
return;
}
//
XPosition positions[];
int positionsCount = mTrader.GetPositions(
positions, // Result ...
NULL, // Symbol ...
NULL, // Provider ...
NULL, // Period ...
X_POSITION_TYPE_ALL // All Types ...
);
if (!IsValidSize(positionsCount))
{
return;
}
//
for (int i = 0; i < count; i++)
{
//
// Call Tick Handler Function ...
X121SMCGuard iGuards[];
bool hasGuards = mStrategies[i].HandleGuard(
iGuards,
positions //
);
if (hasGuards)
{
HandleGuards(iGuards);
}
}
//
Clean(positions);
}
//
// Event Handlers ...
/**
* Calls When a Deals Changed Triggered ...
*
* @param count: Integer, Number of Changes ...
*/
void HandleOnDealsChanged(int count) override
{
}
/**
* Calls When a Order Changed Triggered ...
*
* @param count: Integer, Number of Changes ...
*/
void HandleOnOrdersChanged(int count) override
{
}
/**
* Calls When a Positions Changed Triggered ...
*
* @param count: Integer, Number of Changes ...
*/
void HandleOnPositionsChanged(int count) override
{
//
if (IsValidSize(count))
{
mTradeHandler.HandleNewPosition();
}
}
/**
* Calls When a Position's SL Triggered ...
*
* @param deal: XDeal instance ...
*/
void HandleOnStopLossTriggered(const XDeal &deal) override
{
//
// Finish ...
mTradeHandler.Finish(deal);
//
HandleReportBalance();
}
/**
* Calls When a Position's TP Triggered ...
*
* @param deal: XDeal instance ...
*/
void HandleOnTakeProfitTriggered(const XDeal &deal) override
{
//
// Finish ...
mTradeHandler.Finish(deal);
//
bool useDynamicRiskManagement = DynamicRiskManagement();
if (useDynamicRiskManagement)
{
mTradeHandler.ResetSymbolInfo(deal.symbol);
}
//
HandleReportBalance();
}
/**
* Handle Force Close a Position ...
*
* @param ticket: Position Ticket ...
* @param position: XPosition ...
* @param comment: Closing Comment ...
*/
void HandleOnPositionForceClosed(
const ulong ticket,
const XPosition &position,
const string comment //
) override
{
//
// Finish ...
mTradeHandler.Finish(
ticket,
position,
comment //
);
//
HandleReportBalance();
}
/**
* Reset All Paused Symbols on Each New Days ...
*/
void HandleOnNewDay() override
{
//
mIsForceCloseAtTime = false;
mTradeHandler.ResumePausedSymbols();
}
/**
* Re Configure Materials on Properties Changed ...
*/
void ReConfigure() override
{
//
ReConfigureTradeHandler();
ReConfigureAllStrategies();
}
/**
* Generate Identifier Tag ...
*
* @return ( string )
*/
string GetTag() override
{
//
string result = NULL;
//
string tagPrefix = TagPrefix();
if (IsValid(tagPrefix))
{
result = tagPrefix;
}
else
{
result = "";
}
//
result =
XC121SMCExpertToken + result;
//
return result;
}
//
protected:
//
//
// Props ...
//
XC121SMCTradeHandler *mTradeHandler; // Trade Handler ...
XCX121SMCBaseStrategy *mStrategies[]; // Registere Strategies in EA ...
//
// Actions ...
/**
* Apply Volume Based On Configurations on Signal ...
*
* @param signal: XSignal instance
*/
void ApplyVolumeOnSignal(XSignal &signal)
{
//
double staticVolume = Volume();
double fVolume = staticVolume > 0
? staticVolume
: 0.01;
//
double staticBalance = StaticBalance();
double accountBalance = mTrader.mAccount.GetBalance();
double balance = staticBalance > 0
? staticBalance
: accountBalance;
//
bool useDynamicVolume = UseDynamicVolume();
double balancePerTrade = BalancePerTrade();
double dynamicVolumeStep = DynamicVolumeStep();
double riskPercentPerBalance = RiskPercentPerBalance();
bool allowDynamicRiskManagement = DynamicRiskManagement();
double dynamicVolumeBalanceFactor = DynamicVolumeBalanceFactor();
//
// Apply Static Volume ...
bool allowStaticVolume = staticVolume > 0;
//
// Apply Dynamic Volume ...
bool aloowApplyDynamicVolume = useDynamicVolume &&
dynamicVolumeStep &&
dynamicVolumeBalanceFactor;
//
// Apply Risk Per Trade Volume ...
bool allowApplyRiskPerTradeVolume =
!aloowApplyDynamicVolume &&
riskPercentPerBalance > 0;
//
// Apply Balance Per Trade Volume ...
bool allowApplyBalacePerTradeVolume =
!aloowApplyDynamicVolume &&
!allowApplyRiskPerTradeVolume &&
balancePerTrade > 0;
//
// First Check Dynamic Volume ...
if (aloowApplyDynamicVolume)
{
//
// Dynamic Volume ...
double dVolume = mTrader.GetDynamicVolume(
signal.symbol,
dynamicVolumeBalanceFactor,
dynamicVolumeStep //
);
if (dVolume < fVolume)
{
dVolume = fVolume;
}
//
signal.volume = dVolume;
}
else if (allowApplyRiskPerTradeVolume)
{
//
double riskAmountPerBalance = (riskPercentPerBalance * balance) / 100;
//
double risk = signal.GetRisk();
double points = GetPoints(signal.symbol);
double riskInPoints = risk / points;
//
double volume = mTrader.mAccount.CalculateVolume(
signal.symbol,
riskAmountPerBalance,
riskInPoints //
);
if (volume <= 0)
{
volume = fVolume;
}
//
// Check Dynamic Risk Management ...
bool allowDynamicRiskManagement = DynamicRiskManagement();
if (allowDynamicRiskManagement)
{
//
// Calculate Dynamic Additional Risk Management Volume Multiplier ...
double mAdditionalRiskMultiplier = CalculateAdditionalVolumeMultiplier(signal);
if (mAdditionalRiskMultiplier < 1)
{
mAdditionalRiskMultiplier = 1;
}
//
volume *= mAdditionalRiskMultiplier;
}
//
signal.volume = volume;
}
else if (allowApplyBalacePerTradeVolume)
{
//
double risk = signal.GetRisk();
double points = GetPoints(signal.symbol);
double riskInPoints = risk / points;
//
double volume = mTrader.mAccount.CalculateVolume(
signal.symbol,
balancePerTrade,
riskInPoints //
);
if (volume <= 0)
{
volume = fVolume;
}
//
signal.volume = volume;
}
else if (allowStaticVolume)
{
signal.volume = staticVolume;
}
else
{
signal.volume = fVolume;
}
//
// Normalize Signal Volume ...
signal.volume = NormalizeVolume(
signal.volume,
signal.symbol //
);
}
/**
* Configure Startegy ...
*/
void ConfigureStrategy(XCX121SMCBaseStrategy *&strategy)
{
//
if (strategy == NULL)
{
return;
}
//
// Configure Alerts ...
strategy.SetAlertPrefix(GetTag());
strategy.SetAlertLogAlerts(GetAlertLogAlerts());
strategy.SetAlertMailAlerts(GetAlertMailAlerts());
strategy.SetAlertPushAlerts(GetAlertPushAlerts());
strategy.SetAlertEnableAlerts(GetAlertEnableAlerts());
strategy.SetAlertTerminalAlerts(GetAlertTerminalAlerts());
//
// Confiugre Signalling ...
//
strategy.R2R(R2R());
strategy.AllowLong(AllowLong());
strategy.AllowShort(AllowShort());
strategy.MaxAllowedSpread(20);
strategy.MaxAllowedSaveTicks(150);
strategy.MinRequiredTicksForSpreadPass(100);
//
if (Disabled())
{
strategy.Disable();
}
else
{
strategy.Enable();
}
//
}
/**
* Register an Strategy in EA ...
*
* @param strategy: XCX121SMCBaseStrategy instance ...
*/
void RegisterStrategy(XCX121SMCBaseStrategy *strategy)
{
//
if (strategy == NULL)
{
return;
}
//
ArrayResize(
mStrategies,
ArraySize(mStrategies) + 1 //
);
//
mStrategies[ArraySize(mStrategies) - 1] = strategy;
}
/**
* Re Configure All Registered Strategies ...
*/
void ReConfigureAllStrategies()
{
//
int count = ArraySize(mStrategies);
if (!IsValidSize(count))
{
return;
}
//
for (int i = 0; i < count; i++)
{
//
ConfigureStrategy(mStrategies[i]);
}
}
/**
* Re Configure Trade Handler ...
*/
void ReConfigureTradeHandler()
{
//
if (mTradeHandler == NULL)
{
return;
}
//
// Configure Alerts ...
mTradeHandler.SetAlertPrefix(GetTag());
mTradeHandler.SetAlertEnableAlerts(GetAlertEnableAlerts());
mTradeHandler.SetAlertLogAlerts(GetAlertLogAlerts());
mTradeHandler.SetAlertMailAlerts(GetAlertMailAlerts());
mTradeHandler.SetAlertPushAlerts(GetAlertPushAlerts());
mTradeHandler.SetAlertTerminalAlerts(GetAlertTerminalAlerts());
//
mTradeHandler.AllowLong(AllowLong());
mTradeHandler.AllowShort(AllowShort());
mTradeHandler.MaxAllowedLongs(MaxAllowedLongs());
mTradeHandler.MaxAllowedShorts(MaxAllowedShorts());
mTradeHandler.UseMaxAllowedSignalsPerSymbol(UseMaxAllowedSignalsPerSymbol());
mTradeHandler.LastPositionProfitForAcceptNextInPoint(LastPositionProfitForAcceptNextInPoint());
mTradeHandler.DelaysBetweenTwoSignalsInBar(DelaysBetweenTwoSignalsInBar());
mTradeHandler.MaxAllowedSpread(MaxAllowedSpread());
mTradeHandler.MaxAllowedDrawdownToOpenTrades(MaxAllowedDrawdownToOpenTrades());
mTradeHandler.MaxAllowedSLToPauseSignallingPerSymbol(MaxAllowedSLToPauseSignallingPerSymbol());
mTradeHandler.PauseSignallingAfterReachesMaxAllowedSLInSecconds(PauseSignallingAfterReachesMaxAllowedSLInSecconds());
mTradeHandler.AllowHedging(AllowHedging());
mTradeHandler.MinOpenTradesFroHedging(MinOpenTradesFroHedging());
mTradeHandler.HedgingMinVolumeStep(HedgingMinVolumeStep());
mTradeHandler.HedgeingMinRequiredProfitPerVolumeStep(HedgeingMinRequiredProfitPerVolumeStep());
}
//
private:
//
//
// Props ...
//
// Signalling Props ...
bool mAllowLong; // Allow Long Signals ...
bool mAllowShort; // Allow Short Signals ...
int mMaxAllowedLongs; // Max Allowed Long Signals ...
int mMaxAllowedShorts; // Max Allowed Short Signals ...
bool mUseMaxAllowedSignalsPerSymbol; // Use Max Allowed Signal Types Per Symbol ...
double mLastPositionProfitForAcceptNextInPoint; // Last Position Profit In Points for Accept new Signal ...
int mDelaysBetweenTwoSignalsInBar; // Delay between two Signals in Bars ...
double mMaxAllowedSpread; // Max Allowed Spread for Signalling ...
int mMinRequiredVerificationForSpreadPass; // Minimum Spread Verification for Signalling ...
//
// Trade ...
bool mAllowTrade; // Allow Open Trade On Signals ...
string mStartTradeAt; // Enable Trade on Signals on Time ...
string mStopTradeAt; // Enable Trade on Signals on Time ...
string mCloseAllTradesAt; // Enable Close All Trades on Signals on Time ...
//
bool mIsForceCloseAtTime;
//
// Risk Management Props ...
double mR2R; // Signallers Risk to Reward Ratio ...
double mVolume; // Static Volume ...
double mStaticBalance; // Static Balance for Calculate Trade Volume ...
double mBalancePerTrade; // Balance Used in Each Trade ...
double mRiskPercentPerBalance; // Risk Percent Per Balance in Each Trade ...
bool mDynamicRiskManagement; // Dynamic Risk Management ...
bool mUseDynamicVolume; // Use Dynamic Volume ...
double mDynamicVolumeStep; // Increase Volume Step ...
double mDynamicVolumeBalanceFactor; // Balance Factor for Generate Dynamic Volume ...
double mMaxAllowedDrawdownToOpenTrades; // Max Allowed Drawdown for Open Trades ...
int mMaxAllowedSLToPauseSignallingPerSymbol; // Max Allowed SL for Pause Signalling Per Symbol ...
int mPauseSignallingAfterReachesMaxAllowedSLInSecconds; // Pause Signalling Per Symbol afte Max Allowed SL Reached In Seconds ...
//
// Protection Props ...
bool mAllowHedging; // Allow Hedge Positions ...
int mMinOpenTradesFroHedging; // Minimum Open Positions for Hedging ...
double mHedgingMinVolumeStep; // Minimum Volume Step for Hedging ...
double mHedgeingMinRequiredProfitPerVolumeStep; // Minimum Required Profit Per Volume Step for Hedging ...
//
XCPOIDrawer *eaDrawer; // EA Drawer ...
//
double CalculateAdditionalVolumeMultiplier(XSignal &signal)
{
//
double result = 0;
//
if (!signal.IsValid())
{
return result;
}
//
X121SMCSymbolPositionInfo info;
bool hasInfo = mTradeHandler.GetSymbolInfo(
signal.symbol,
info //
);
if (!hasInfo)
{
return result;
}
//
if (info.countedSLs >= 2)
{
result = (info.countedSLs / 2) + 1;
}
//
return result;
}
/**
* Handle Guard Actions ...
*
* @param guards: X121SMCGuard instance Collection ...
*/
void HandleGuards(X121SMCGuard &guards[])
{
//
int count = ArraySize(guards);
if (!IsValidSize(guards))
{
return;
}
//
for (int i = 0; i < count; i++)
{
//
X121SMCGuard iGuard = guards[i];
//
if (!iGuard.IsValid())
{
continue;
}
//
// Here we Have to Handle Guard Actions ...
//
// Close ...
bool canClose =
NotEmpty(iGuard.ticket) &&
iGuard.action == X_121_SMC_GUARD_ACTION_CLOSE;
//
// Close All ...
bool canCloseAll = iGuard.action == X_121_SMC_GUARD_ACTION_CLOSE_ALL;
//
// Close Longs ...
bool canCloseLongs = iGuard.action == X_121_SMC_GUARD_ACTION_CLOSE_LONGS;
//
// Close Shorts ...
bool canCloseShorts = iGuard.action == X_121_SMC_GUARD_ACTION_CLOSE_SHORTS;
//
// Partial Close ...
bool canPartialClose =
NotEmpty(iGuard.ticket) &&
iGuard.volumeMultiplier > 0 &&
iGuard.action == X_121_SMC_GUARD_ACTION_PARTIAL_CLOSE;
//
// Trail Stop ...
bool canTrailStop =
iGuard.sl > 0 &&
NotEmpty(iGuard.ticket) &&
iGuard.action == X_121_SMC_GUARD_ACTION_TRAIL_STOP;
//
// Trail Target ...
bool canTrailTarget =
iGuard.tp > 0 &&
NotEmpty(iGuard.ticket) &&
iGuard.action == X_121_SMC_GUARD_ACTION_TRAIL_TARGET;
//
// Hedge ...
bool canHedge = iGuard.action == X_121_SMC_GUARD_ACTION_HEDGE;
//
// Check is Guard Valid ...
bool isValidGuardAction =
canHedge ||
canClose ||
canCloseAll ||
canTrailStop ||
canCloseLongs ||
canTrailTarget ||
canCloseShorts ||
canPartialClose;
if (!isValidGuardAction)
{
continue;
}
//
// Now we Sure to Have a Valid Guard ...
// Start to o Guard Actions ...
//
// Close All ...
if (canCloseAll)
{
//
XPosition positions[];
int positionsCount =
mTrader
.GetPositions(
positions, // Result ...
iGuard.symbol,
iGuard.provider,
NULL, // Period ...
X_POSITION_TYPE_ALL, // All Types ...
true // Filter by Magic ...
);
if (IsValidSize(positionsCount))
{
//
string comment = "Guard Close All ...";
string message = "Guard Close All (" + ToString(positionsCount) + ") Positions Successfully ...";
int forceClosed = mTradeHandler.ForceClose(
positions,
comment,
message //
);
//
if (forceClosed)
{
RestEA(120 * 60);
}
}
}
//
// Close Longs ...
if (canCloseLongs)
{
//
XPosition longPositions[];
XPosition shortPositions[];
mTrader
.GetPositions(
longPositions, // Result ...
shortPositions, // Result ...
iGuard.symbol,
iGuard.provider,
NULL, // Period ...
true // Filter by Magic ...
);
//
int longPositionsCount = ArraySize(longPositions);
bool hasLongPositions = IsValidSize(longPositionsCount);
//
int shortPositionsCount = ArraySize(shortPositions);
bool hasShortPositions = IsValidSize(shortPositionsCount);
//
if (hasLongPositions)
{
//
string comment = "Guard Close Longs ...";
string message = "Guard Close (" + ToString(longPositionsCount) + ") Long Positions Successfully ...";
bool isClosed = mTradeHandler.ForceClose(
longPositions,
comment,
message //
);
//
if (isClosed)
{
RestEA(120 * 60);
}
}
}
//
// Close Shorts ...
if (canCloseShorts)
{
//
XPosition longPositions[];
XPosition shortPositions[];
mTrader
.GetPositions(
longPositions, // Result ...
shortPositions, // Result ...
iGuard.symbol,
iGuard.provider,
NULL, // Period ...
true // Filter by Magic ...
);
//
int longPositionsCount = ArraySize(longPositions);
bool hasLongPositions = IsValidSize(longPositionsCount);
//
int shortPositionsCount = ArraySize(shortPositions);
bool hasShortPositions = IsValidSize(shortPositionsCount);
//
if (hasShortPositions)
{
//
string comment = "Guard Close Shorts ...";
string message = "Guard Close (" + ToString(shortPositionsCount) + ") Short Positions Successfully ...";
bool isClosed = mTradeHandler.ForceClose(
shortPositions,
comment,
message //
);
//
if (isClosed)
{
RestEA(120 * 60);
}
}
}
//
// Close ...
if (canClose)
{
//
XPosition iPosition;
bool hasPosition = mTrader.GetPosition(
iGuard.ticket,
iPosition //
);
//
bool isLong = IsLong(iPosition.type);
//
if (hasPosition)
{
//
XPosition positions[];
AddRef(
iPosition,
positions //
);
//
string comment = "Guard Close ...";
string message = "Guard Close " + (isLong ? "Long" : "Short") + " Position: (" + ToString(iGuard.ticket) + ") Successfully ...";
bool isClosed = mTradeHandler.ForceClose(
positions,
comment,
message //
);
//
if (isClosed)
{
RestEA(120 * 60);
}
}
}
//
// Partial Close ...
if (canPartialClose)
{
//
XPosition iPosition;
bool hasPosition = mTrader.GetPosition(
iGuard.ticket,
iPosition //
);
//
bool isLong = IsLong(iPosition.type);
//
if (hasPosition)
{
//
// Normalize Volume Multiplier ...
double vMult = iGuard.volumeMultiplier;
if (vMult > 0.5)
{
vMult = 0.5;
}
if (vMult < 0)
{
vMult = 0.5;
}
//
// Calculate and Normalize Volume ...
double volume = iPosition.volume * iGuard.volumeMultiplier;
volume = NormalizeVolume(
volume,
iPosition.symbol //
);
//
string comment = "Guard Partially Closed: " + ToString(volume) + " ...";
string message = "Guard Partially Closed " + (isLong ? "Long" : "Short") + ": " + ToString(volume) + " Successfully ...";
bool isModified = mTrader.ClosePartial(
iPosition.ticket,
volume,
comment //
);
if (isModified)
{
//
mTradeHandler.Alert(message);
//
if (volume == iPosition.volume)
{
//
mTradeHandler.Finish(
iPosition.ticket,
iPosition,
comment //
);
//
RestEA(120 * 60);
}
}
}
}
//
// Hedge ...
if (canHedge)
{
//
XPosition positions[];
int positionsCount =
mTrader
.GetPositions(
positions, // Result ...
iGuard.symbol,
iGuard.provider,
NULL, // Period ...
X_POSITION_TYPE_ALL, // All Types ...
true // Filter by Magic ...
);
if (IsValidSize(positionsCount))
{
//
int longs = 0;
double longProfits = 0;
double longVolumes = 0;
//
int shorts = 0;
double shortProfits = 0;
double shortVolumes = 0;
CountPositions(
positions,
longs,
longProfits,
longVolumes,
shorts,
shortProfits,
shortVolumes //
);
//
int count = longs + shorts;
double profits = longProfits + shortProfits;
double volumes = longVolumes + shortVolumes;
//
bool canDoHedge =
count > 0 &&
profits > 0 &&
volumes > 0;
if (canDoHedge)
{
//
string comment = "Guard Hedge ...";
string message = "Guard Hedge (" + ToString(count) + ") Positions by: (" + ToString(profits) + ") Successfully ...";
bool isClosed = mTradeHandler.ForceClose(
positions,
comment,
message //
);
//
if (isClosed)
{
RestEA(120 * 60);
}
}
}
}
//
// Trail Stop ...
if (canTrailStop)
{
//
XPosition iPosition;
bool hasPosition = mTrader.GetPosition(
iGuard.ticket,
iPosition //
);
//
bool isLong = IsLong(iPosition.type);
//
bool canDoTrail =
hasPosition &&
iPosition.profit > 0 &&
isLong
? iPosition.price > iGuard.sl &&
(iPosition.sl == 0 ||
iPosition.sl < iGuard.sl)
: iPosition.price < iGuard.sl &&
(iPosition.sl == 0 ||
iPosition.sl > iGuard.sl);
if (canDoTrail)
{
//
string comment = "Guard Trail Stop ...";
string message = "Guard Trail " + (isLong ? "Long" : "Short") + " Position: (" + ToString(iGuard.ticket) + ") Stop Successfully ...";
bool isModified = mTrader.Modify(
iPosition.ticket,
iGuard.sl,
iPosition.tp,
comment //
);
if (isModified)
{
mTradeHandler.Alert(message);
}
}
}
//
// Trail Target ...
if (canTrailTarget)
{
//
XPosition iPosition;
bool hasPosition = mTrader.GetPosition(
iGuard.ticket,
iPosition //
);
//
bool isLong = IsLong(iPosition.type);
//
bool canDoTrail =
hasPosition &&
iGuard.tp != iPosition.tp &&
isLong
? iGuard.tp > iPosition.price
: iGuard.tp < iPosition.price;
if (canDoTrail)
{
//
string comment = "Guard Trail Target ...";
string message = "Guard Trail " + (isLong ? "Long" : "Short") + " Position: (" + ToString(iGuard.ticket) + ") Target Successfully ...";
bool isModified = mTrader.Modify(
iPosition.ticket,
iPosition.sl,
iGuard.tp,
comment //
);
if (isModified)
{
mTradeHandler.Alert(message);
}
}
}
}
//
Clean(guards);
Clean(guards);
}
//
void RestEA(int seconds)
{
//
}
//
};
//