2506 lines
61 KiB
Plaintext
2506 lines
61 KiB
Plaintext
///////////////////////////////////////////////////////
|
||
//
|
||
// 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)
|
||
{
|
||
//
|
||
}
|
||
|
||
//
|
||
};
|
||
|
||
// |