Files
MQL5Data/Classes/x-saherelm.x121.setup.xea.mq5
T

2805 lines
67 KiB
Plaintext

///////////////////////////////////////////////////////
//
// SaherElm IT Center MQL5 Class Library
// ----------------------------------------------
// Name: XSCX121SetupCycle
// Description: provides implementation of X121
// Setup on Specified Market Cycle ...
//
//
// 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.xea.class.mq5"
#include "../Classes/x-saherelm.x121.setup.cycle.class.mq5"
//
// Definitions ...
//
struct XSignalInfo
{
//
ulong ticket; // Position Ticket
string symbol; // Trading Symbol
string provider; // Signaller
int pushers; // Signal Pushers
ENUM_TIMEFRAMES period; // Trading Timeframe
datetime time; // Issue Time (Open Position)
//
double profit; // Profit on Close
double commission; // Commission
double swap; // Swap
double volume; // Volume
datetime endTime; // End Time
string message; // Close Reason
//
double bullishScore; // Bullish Score On Signal Time
double bearishScore; // Bearish Score On Signal Time
//
XSignal signal; // Generated Signal
X121SetupConditions conditions; // Generated Conditions
//
// Constructor ...
void XSignalInfo()
{
Clean();
}
//
// Tools ...
//
// Cleanup ...
void Clean()
{
//
ticket = 0;
symbol = NULL;
period = NULL;
provider = NULL;
pushers = 0;
time = NULL;
profit = 0;
commission = 0;
swap = 0;
volume = 0;
endTime = NULL;
message = NULL;
bullishScore = 0;
bearishScore = 0;
signal.Clean();
conditions.Clean();
}
//
bool Fill(
int _pushers,
XSignal &_signal,
double _bullishScore,
double _bearishScore,
X121SetupConditions &_conditions //
)
{
//
bool result = false;
//
result =
//
IsValid(_signal.symbol) &&
IsValid(_signal.period) &&
IsValid(_signal.provider)
//
;
//
if (!result)
{
return result;
}
//
pushers = _pushers;
symbol = _signal.symbol;
period = _signal.period;
volume = _signal.volume;
provider = _signal.provider;
//
signal = _signal;
conditions = _conditions;
//
bullishScore = _bullishScore;
bearishScore = _bearishScore;
//
return result;
}
//
bool IsOwn(
ulong _ticket //
)
{
//
bool result = false;
//
result = _ticket == ticket;
//
return result;
}
//
bool IsOwn(
string _symbol,
string _provider,
ENUM_TIMEFRAMES _period //
)
{
//
bool result = false;
//
result =
//
IsValid(_symbol) &&
IsValid(_provider) &&
IsValid(_period) &&
//
symbol == _symbol &&
provider == _provider &&
period == _period
//
;
//
return result;
}
//
// Data Collector ...
//
bool IsValid()
{
//
bool result = false;
//
result =
//
ticket > 0 &&
IsValid(time) &&
IsValid(symbol) &&
IsValid(period)
//
;
//
return result;
}
//
int GetAge()
{
//
int result = -1;
//
if (!IsValid(symbol) ||
!IsValid(time) ||
!IsValid(endTime) ||
!IsValid(period))
{
return result;
}
//
int startIndex = iBarShift(
symbol,
period,
time,
false //
);
//
int endIndex = iBarShift(
symbol,
period,
endTime,
false //
);
//
result = MathAbs(startIndex - endIndex);
//
return result;
}
//
string GetFileName()
{
//
string result = NULL;
//
if (!IsValid())
{
return result;
}
//
result =
//
symbol + "\\" +
ToString(signal.type) + "\\" +
(profit >= 0
? "Profit"
: "Loss") +
"\\" +
provider + "_" +
ToString(ticket) + "_" +
ToString(period) + "_" +
ToFormatString(time)
//
;
//
return result;
}
//
string ToString()
{
//
string result = NULL;
//
string conditionsStr = conditions
.GenerateSummary(
false, // Only Commons ...
true, // Only Conditions ...
false, // Include Score ...
false // Include False Conditions ...
);
//
int age = GetAge();
//
result =
//
ToString("Ticket", ticket) +
ToString("Symbol", symbol) +
ToString("Period", period) +
ToString("Pushers", pushers) +
ToString("Provider", provider) +
ToString("Time", time) +
ToString("BullishScore", bullishScore) +
ToString("BearishScore", bearishScore) +
ToString("Volume", volume) +
ToString("Profit", profit) +
ToString("Commission", commission) +
ToString("Swap", swap) +
ToString("End Time", endTime) +
ToString("Age", age) +
ToString("Message", message) +
"-------------" + "\n" +
ToString("Signal", "\n" + signal.ToString()) +
"-------------" + "\n" +
ToString("Conditions", "\n" + conditionsStr) +
//
""
//
;
//
return result;
}
//
};
//
class XSignalInfoCollector
{
//
// Public ...
public:
//
// Props ...
//
// Constructor(s) ...
void XSignalInfoCollector(
string _path = NULL // Base Path
)
{
//
mAccount = new XSCAccount();
//
if (IsValid(_path))
{
mPath = _path;
}
else
{
mPath = "XSignalInfo" + "\\" + mAccount.GetCompany();
}
}
//
// Deconstructor ...
void ~XSignalInfoCollector() {}
//
bool IsExists(XSignalInfo &item)
{
//
bool result = false;
//
int mHandler = GetFileHandlerForRead(item);
result = mHandler != INVALID_HANDLE;
FileClose(mHandler);
//
return result;
}
//
bool Save(XSignalInfo &item)
{
//
bool result = false;
//
// Check info is Valid ...
result = item.IsValid();
if (!result)
{
return result;
}
//
string content = item.ToString();
result = IsValid(content);
if (!result)
{
return result;
}
//
int mHandler = GetFileHandlerForWrite(item);
result = mHandler != INVALID_HANDLE;
if (!result)
{
return result;
}
//
FileWrite(mHandler, content);
FileFlush(mHandler);
FileClose(mHandler);
//
return result;
}
//
// Protected ...
protected:
//
// Private ...
private:
//
// Props ...
//
string mPath; // Base Path ...
//
XSCAccount *mAccount;
//
string GetFilePath(XSignalInfo &item)
{
//
string fileName = item.GetFileName();
//
return GetFilePath(fileName);
}
string GetFilePath(string fileName)
{
//
string result = "";
//
result =
//
mPath + "\\" + fileName + ".x121.log"
//
;
//
return result;
}
//
int GetFileHandlerForRead(XSignalInfo &item)
{
//
int result = INVALID_HANDLE;
//
string filePath = GetFilePath(item);
if (!IsValid(filePath))
{
return result;
}
//
result = FileOpen(
filePath,
FILE_READ | FILE_TXT //
);
//
return result;
}
int GetFileHandlerForWrite(XSignalInfo &item)
{
//
int result = INVALID_HANDLE;
//
string filePath = GetFilePath(item);
if (!IsValid(filePath))
{
return result;
}
//
result = FileOpen(
filePath,
FILE_READ | FILE_WRITE | FILE_TXT //
);
//
return result;
}
};
//
// Class ...
class XSCX121SetupEA : public XSCBaseEA
{
//
// Public ...
public:
//
// Props ...
//
// Constructors ...
XSCX121SetupEA(
//
// XTrade Class Requirements ...
int slippage, // Specify Slippage
ulong magicNumber, // Specify Magic Number
//
// XSCTrade Event Handlers ...
TOnSignal onSignal = NULL, // On Signal Recieved Event Handler
TOnModify onModifyPosition = NULL, // On Modify Position Event Handler
TOnStopLoss onStopLossTriggered = NULL, // On StopLoass Triggered Event Handler
TOnTakeProfit onTakeProfitTriggered = NULL, // On TakeProfit Triggered Event Handler
TOnForceClose onForceClosePosition = NULL, // On Force Close Position Event Handler
TOnPartialClose onPartialClosePosition = NULL, // On Partial Close Position Event Handler
TOnDealsChanged onDealsChangedHandler = NULL, // On Deals Changed Event Handler
TOnOrdersChanged onOrdersChangedHandler = NULL, // On Orders Changed Event Handler
TOnPositionsChanged onPositionsChangedHandler = NULL, // On Positions Changed Event Handler
TOnTradeStateChanged onTradeStateChangedHandler = NULL // On Trade State Changed Event Handler
) : XSCBaseEA(slippage,
magicNumber,
onSignal,
onModifyPosition,
onStopLossTriggered,
onTakeProfitTriggered,
onForceClosePosition,
onPartialClosePosition,
onDealsChangedHandler,
onOrdersChangedHandler,
onPositionsChangedHandler,
onTradeStateChangedHandler //
)
{
//
Clean(mSignalInfos);
//
// Disbale Using Signal Collector ...
UseSignalCollector(false);
mSignalCollector = new XSignalInfoCollector();
}
//
// Deconstructor ...
~XSCX121SetupEA()
{
//
delete mSignalCollector;
//
Clean(mSetups);
}
//
bool AddSetup(XSCX121SetupCycles *setup)
{
//
bool result = false;
//
result = setup != NULL;
if (!result)
{
return result;
}
//
Add(
setup,
mSetups //
);
//
return result;
}
//
// Getter(s) / Setter(s) ...
//
bool AllowLong()
{
return mAllowLong;
}
//
void AllowLong(bool value)
{
mAllowLong = value;
}
//
bool AllowShort()
{
return mAllowShort;
}
//
void AllowShort(bool value)
{
mAllowShort = value;
}
//
double Volume()
{
return mVolume;
}
//
void Volume(double value)
{
//
if (value < 0.01)
{
value = 0.01;
}
//
mVolume = value;
}
//
double TPPoint()
{
return mTPPoint;
}
//
void TPPoint(double value)
{
//
if (value < 0)
{
value = 0;
}
//
mTPPoint = value;
}
//
double SLPoint()
{
return mSLPoint;
}
//
void SLPoint(double value)
{
//
if (value < 0)
{
value = 0;
}
//
mSLPoint = value;
}
//
bool IgnoreTP()
{
return mIgnoreTP;
}
//
void IgnoreTP(bool value)
{
mIgnoreTP = value;
}
//
bool IgnoreSL()
{
return mIgnoreSL;
}
//
void IgnoreSL(bool value)
{
mIgnoreSL = value;
}
//
bool CloseOnOpposit()
{
return mCloseOnOpposit;
}
//
void CloseOnOpposit(bool value)
{
mCloseOnOpposit = value;
}
//
int ReuiredSignalVerifications()
{
return mReuiredSignalVerifications;
}
//
void ReuiredSignalVerifications(int value)
{
//
if (value < 1)
{
value = 1;
}
//
mReuiredSignalVerifications = value;
}
//
bool GetVerificationFromOtherTimeFrames()
{
return mGetVerificationFromOtherTimeFrames;
}
//
void GetVerificationFromOtherTimeFrames(bool value)
{
mGetVerificationFromOtherTimeFrames = value;
}
//
int MaxAllowedTrades()
{
return mMaxAllowedTrades;
}
//
void MaxAllowedTrades(int value)
{
//
if (value < 0)
{
value = 0;
}
//
mMaxAllowedTrades = value;
mTrader.SetMaxAllowedPositions(value);
}
//
int CloseOnSpecificTime()
{
return mCloseOnSpecificTime;
}
//
void CloseOnSpecificTime(int value)
{
//
if (value < 0)
{
value = -1;
}
//
if (value > 23)
{
value = 23;
}
//
mCloseOnSpecificTime = value;
}
//
bool UseSupport()
{
return mUseSupport;
}
//
void UseSupport(bool value)
{
mUseSupport = value;
}
//
bool UseGrid()
{
return mUseGrid;
}
//
void UseGrid(bool value)
{
mUseGrid = value;
}
//
double GridDistance()
{
return mGridDistance;
}
//
void GridDistance(double value)
{
//
if (value < 0)
{
value = 0;
}
//
mGridDistance = value;
}
//
double GridVolumeMultiplier()
{
return mGridVolumeMultiplier;
}
//
void GridVolumeMultiplier(double value)
{
//
if (value < 0)
{
value = 0;
}
//
mGridVolumeMultiplier = value;
}
//
bool UseSignalCollector()
{
return mUseSignalCollector;
}
//
void UseSignalCollector(bool value)
{
mUseSignalCollector = value;
}
//
// Overrides ...
//
// Customize Token ...
string
GetToken() override
{
return GetSpecificToken(this);
}
//
string GetTag() override
{
return this.GetToken();
}
//
// Check Provider for any Guards ...
bool CheckForGuard(XGuard &guards[]) override
{
//
bool result = false;
//
return result;
}
//
// Request Provider to Collect all
// Potentially Signals and then
// filters theme here and passed them
// for Executing ...
int RequestForSignal(
XSignal &signals[] // Holds Signals ...
) override
{
//
bool result = 0;
//
Clean(signals);
//
if (!IsEnable())
{
return result;
}
//
// IMPLEMENT ...
int count = CountSetups();
result = IsValidSize(count);
if (!result)
{
return result;
}
//
string separator = "\n";
//
// Current ...
XSignal cSignal;
int cPusher = 0;
bool cHasSignal = false;
string cProvider = NULL;
X121SetupConditions cConditions;
//
// Short ...
XSignal sSignal;
int sPusher = 0;
bool sHasSignal = false;
string sProvider = NULL;
X121SetupConditions sConditions;
//
// Medium ...
XSignal mSignal;
int mPusher = 0;
bool mHasSignal = false;
string mProvider = NULL;
X121SetupConditions mConditions;
//
// Long ...
XSignal lSignal;
int lPusher = 0;
bool lHasSignal = false;
string lProvider = NULL;
X121SetupConditions lConditions;
//
// Hind ...
XSignal hSignal;
int hPusher = 0;
bool hHasSignal = false;
string hProvider = NULL;
X121SetupConditions hConditions;
//
X121SignalGenerator signalGenerator;
//
for (int i = 0; i < count; i++)
{
//
cPusher = 0;
sPusher = 0;
mPusher = 0;
lPusher = 0;
hPusher = 0;
//
cProvider = NULL;
sProvider = NULL;
mProvider = NULL;
lProvider = NULL;
hProvider = NULL;
//
cSignal.Clean();
sSignal.Clean();
mSignal.Clean();
lSignal.Clean();
hSignal.Clean();
//
cHasSignal = false;
sHasSignal = false;
mHasSignal = false;
lHasSignal = false;
hHasSignal = false;
//
cConditions.Clean();
sConditions.Clean();
mConditions.Clean();
lConditions.Clean();
hConditions.Clean();
//
// Current ...
bool canProcess = mSetups[i]
.CanProcessBar(
X_MARKET_CYCLE_UNKNOWN //
);
if (canProcess)
{
//
bool iHasConditions = mSetups[i].GetConditions(
cConditions,
X_MARKET_CYCLE_UNKNOWN, // Current Market ...
0, // Bar Index ...
5 // Loop Back ...
);
//
if (!iHasConditions)
{
continue;
}
//
mVolumeOSC = 0;
mBullishSigns = 0;
mBullishScore = 0;
mBearishSigns = 0;
mBearishScore = 0;
//
// Retrieve Scores ...
double bullishScore = 0;
double bearishScore = 0;
cConditions.GenerateScore(
bullishScore,
bearishScore //
);
mBullishScore += bullishScore;
mBearishScore += bearishScore;
//
mVolumeOSC += cConditions.vlmConditions.volume[1];
//
// Parse Conditions for Signal ...
cHasSignal = signalGenerator.HasSignal(
cConditions,
cSignal,
cPusher,
cProvider,
mUseSupport,
mAllowLong,
mAllowShort,
mVolume,
mSLPoint,
mIgnoreSL,
mTPPoint,
mIgnoreTP //
);
//
if (cHasSignal)
{
//
mSetups[i].WaitsUntilNextBar(
X_MARKET_CYCLE_UNKNOWN //
);
}
}
//
// Short ...
canProcess = mSetups[i]
.CanProcessBar(
X_MARKET_CYCLE_SHORT //
);
if (canProcess)
{
//
bool iHasConditions = mSetups[i].GetConditions(
sConditions,
X_MARKET_CYCLE_SHORT, // Current Market ...
0, // Bar Index ...
5 // Loop Back ...
);
//
if (!iHasConditions)
{
continue;
}
//
// Retrieve Scores ...
double bullishScore = 0;
double bearishScore = 0;
sConditions.GenerateScore(
bullishScore,
bearishScore //
);
mBullishScore += bullishScore;
mBearishScore += bearishScore;
//
mVolumeOSC += sConditions.vlmConditions.volume[1];
//
// Parse Conditions for Signal ...
sHasSignal = signalGenerator.HasSignal(
sConditions,
sSignal,
sPusher,
sProvider,
mAllowLong,
mAllowShort,
mVolume,
mSLPoint,
mIgnoreSL,
mTPPoint,
mIgnoreTP //
);
//
if (sHasSignal)
{
//
mSetups[i].WaitsUntilNextBar(
X_MARKET_CYCLE_SHORT //
);
}
}
//
// Medium ...
canProcess = mSetups[i]
.CanProcessBar(
X_MARKET_CYCLE_MEDIUM //
);
if (canProcess)
{
//
bool iHasConditions = mSetups[i].GetConditions(
mConditions,
X_MARKET_CYCLE_MEDIUM, // Current Market ...
0, // Bar Index ...
5 // Loop Back ...
);
//
if (!iHasConditions)
{
continue;
}
//
// Retrieve Scores ...
double bullishScore = 0;
double bearishScore = 0;
mConditions.GenerateScore(
bullishScore,
bearishScore //
);
mBullishScore += bullishScore;
mBearishScore += bearishScore;
//
mVolumeOSC += mConditions.vlmConditions.volume[1];
//
// Parse Conditions for Signal ...
mHasSignal = signalGenerator.HasSignal(
mConditions,
mSignal,
mPusher,
mProvider,
mUseSupport,
mAllowLong,
mAllowShort,
mVolume,
mSLPoint,
mIgnoreSL,
mTPPoint,
mIgnoreTP //
);
//
if (mHasSignal)
{
//
mSetups[i].WaitsUntilNextBar(
X_MARKET_CYCLE_MEDIUM //
);
}
}
//
// Long ...
canProcess = mSetups[i]
.CanProcessBar(
X_MARKET_CYCLE_LONG //
);
if (canProcess)
{
//
bool iHasConditions = mSetups[i].GetConditions(
lConditions,
X_MARKET_CYCLE_LONG, // Current Market ...
0, // Bar Index ...
5 // Loop Back ...
);
//
if (!iHasConditions)
{
continue;
}
//
// Retrieve Scores ...
double bullishScore = 0;
double bearishScore = 0;
lConditions.GenerateScore(
bullishScore,
bearishScore //
);
mBullishScore += bullishScore;
mBearishScore += bearishScore;
//
mVolumeOSC += lConditions.vlmConditions.volume[1];
//
// Parse Conditions for Signal ...
lHasSignal = signalGenerator.HasSignal(
lConditions,
lSignal,
lPusher,
lProvider,
mUseSupport,
mAllowLong,
mAllowShort,
mVolume,
mSLPoint,
mIgnoreSL,
mTPPoint,
mIgnoreTP //
);
//
if (lHasSignal)
{
//
mSetups[i].WaitsUntilNextBar(
X_MARKET_CYCLE_LONG //
);
}
}
//
// Hind ...
canProcess = mSetups[i]
.CanProcessBar(
X_MARKET_CYCLE_HIND //
);
if (canProcess)
{
//
bool iHasConditions = mSetups[i].GetConditions(
hConditions,
X_MARKET_CYCLE_HIND, // Current Market ...
0, // Bar Index ...
5 // Loop Back ...
);
//
if (!iHasConditions)
{
continue;
}
//
// Retrieve Scores ...
double bullishScore = 0;
double bearishScore = 0;
hConditions.GenerateScore(
bullishScore,
bearishScore //
);
mBullishScore += bullishScore;
mBearishScore += bearishScore;
//
mVolumeOSC += hConditions.vlmConditions.volume[1];
//
// Parse Conditions for Signal ...
hHasSignal = signalGenerator.HasSignal(
hConditions,
hSignal,
hPusher,
hProvider,
mUseSupport,
mAllowLong,
mAllowShort,
mVolume,
mSLPoint,
mIgnoreSL,
mTPPoint,
mIgnoreTP //
);
//
if (hHasSignal)
{
//
mSetups[i].WaitsUntilNextBar(
X_MARKET_CYCLE_HIND //
);
}
}
//
// Parse Signals and Add them for Executing ...
//
// Current Signals ...
if (cSignal.IsValid())
{
//
bool isLong = IsLong(cSignal.type);
if (isLong)
{
mBullishSigns += cPusher;
}
else
{
mBearishSigns += cPusher;
}
//
if (cPusher >= mReuiredSignalVerifications)
{
//
X121SetupConditions otherConditions[];
AddRef(
sConditions,
otherConditions //
);
AddRef(
mConditions,
otherConditions //
);
AddRef(
lConditions,
otherConditions //
);
AddRef(
hConditions,
otherConditions //
);
//
// Check Final Validations ...
bool isValid =
//
(
//
sHasSignal
//
||
//
mHasSignal
//
||
//
lHasSignal
//
||
//
hHasSignal
//
)
//
||
//
(
//
!mGetVerificationFromOtherTimeFrames
? true
: isLong
? signalGenerator.HasLongVerifications(otherConditions)
: signalGenerator.HasShortVerifications(otherConditions)
//
)
//
;
//
if (isValid)
{
//
AddRef(
cSignal,
signals //
);
//
if (UseSignalCollector())
{
//
AddNewSignal(
cPusher,
cSignal,
mBullishScore,
mBearishScore,
cConditions //
);
}
}
}
}
//
// Short Signals ...
if (sSignal.IsValid())
{
//
bool isLong = IsLong(sSignal.type);
if (isLong)
{
mBullishSigns += sPusher;
}
else
{
mBearishSigns += sPusher;
}
//
if (sPusher >= mReuiredSignalVerifications)
{
//
X121SetupConditions otherConditions[];
AddRef(
cConditions,
otherConditions //
);
AddRef(
mConditions,
otherConditions //
);
AddRef(
lConditions,
otherConditions //
);
AddRef(
hConditions,
otherConditions //
);
//
// Check Final Validations ...
bool isValid =
//
(
//
cHasSignal
//
||
//
mHasSignal
//
||
//
lHasSignal
//
||
//
hHasSignal
//
)
//
||
//
(
//
!mGetVerificationFromOtherTimeFrames
? true
: isLong
? signalGenerator.HasLongVerifications(otherConditions)
: signalGenerator.HasShortVerifications(otherConditions)
//
)
//
;
//
if (isValid)
{
//
AddRef(
sSignal,
signals //
);
//
if (UseSignalCollector())
{
//
AddNewSignal(
sPusher,
sSignal,
mBullishScore,
mBearishScore,
sConditions //
);
}
}
}
}
//
// Medium Signals ...
if (mSignal.IsValid())
{
//
bool isLong = IsLong(mSignal.type);
if (isLong)
{
mBullishSigns += mPusher;
}
else
{
mBearishSigns += mPusher;
}
//
if (mPusher >= mReuiredSignalVerifications)
{
//
X121SetupConditions otherConditions[];
AddRef(
cConditions,
otherConditions //
);
AddRef(
sConditions,
otherConditions //
);
AddRef(
lConditions,
otherConditions //
);
AddRef(
hConditions,
otherConditions //
);
//
// Check Final Validations ...
bool isValid =
//
(
//
cHasSignal
//
||
//
sHasSignal
//
||
//
lHasSignal
//
||
//
hHasSignal
//
)
//
||
//
(
//
!mGetVerificationFromOtherTimeFrames
? true
: isLong
? signalGenerator.HasLongVerifications(otherConditions)
: signalGenerator.HasShortVerifications(otherConditions)
//
)
//
;
//
if (isValid)
{
//
AddRef(
mSignal,
signals //
);
//
if (UseSignalCollector())
{
//
AddNewSignal(
mPusher,
mSignal,
mBullishScore,
mBearishScore,
mConditions //
);
}
}
}
}
//
// Long Signals ...
if (lSignal.IsValid())
{
//
bool isLong = IsLong(lSignal.type);
if (isLong)
{
mBullishSigns += lPusher;
}
else
{
mBearishSigns += lPusher;
}
//
if (lPusher >= mReuiredSignalVerifications)
{
//
X121SetupConditions otherConditions[];
AddRef(
cConditions,
otherConditions //
);
AddRef(
sConditions,
otherConditions //
);
AddRef(
mConditions,
otherConditions //
);
AddRef(
hConditions,
otherConditions //
);
//
// Check Final Validations ...
bool isValid =
//
(
//
cHasSignal
//
||
//
sHasSignal
//
||
//
mHasSignal
//
||
//
hHasSignal
//
)
//
||
//
(
//
!mGetVerificationFromOtherTimeFrames
? true
: isLong
? signalGenerator.HasLongVerifications(otherConditions)
: signalGenerator.HasShortVerifications(otherConditions)
//
)
//
;
//
if (isValid)
{
//
AddRef(
lSignal,
signals //
);
//
if (UseSignalCollector())
{
//
AddNewSignal(
lPusher,
lSignal,
mBullishScore,
mBearishScore,
lConditions //
);
}
}
}
}
//
// Hind Signals ...
if (hSignal.IsValid())
{
//
bool isLong = IsLong(hSignal.type);
if (isLong)
{
mBullishSigns += hPusher;
}
else
{
mBearishSigns += hPusher;
}
//
if (hPusher >= mReuiredSignalVerifications)
{
//
X121SetupConditions otherConditions[];
AddRef(
cConditions,
otherConditions //
);
AddRef(
sConditions,
otherConditions //
);
AddRef(
mConditions,
otherConditions //
);
AddRef(
lConditions,
otherConditions //
);
//
// Check Final Validations ...
bool isValid =
//
(
//
cHasSignal
//
||
//
sHasSignal
//
||
//
mHasSignal
//
||
//
lHasSignal
//
) //
||
//
(
//
!mGetVerificationFromOtherTimeFrames
? true
: isLong
? signalGenerator.HasLongVerifications(otherConditions)
: signalGenerator.HasShortVerifications(otherConditions)
//
)
//
;
//
if (isValid)
{
//
AddRef(
hSignal,
signals //
);
//
if (UseSignalCollector())
{
//
AddNewSignal(
hPusher,
hSignal,
mBullishScore,
mBearishScore,
hConditions //
);
}
}
}
}
//
bool hasSignal = cHasSignal || sHasSignal || mHasSignal || lHasSignal || hHasSignal;
if (hasSignal)
{
Print("Signal Recieved ...");
}
}
//
// Create Score Summary for Commenting on Chart ...
string scoreSummary =
//
"----------" + separator +
"Bullish Score: " + ToString(mBullishScore) + separator +
"Bullish Signs: " + ToString(mBullishSigns) + separator +
"----------" + separator +
"Bearish Score: " + ToString(mBearishScore) + separator +
"Bearish Signs: " + ToString(mBearishSigns) + separator +
"----------" + separator +
"Volume: " + ToString(mVolumeOSC) + separator +
"DrawDown: " + ToString(GetDrawdownPercent()) + "%" +
""
//
;
//
Comment(scoreSummary);
//
result = ArraySize(signals);
//
return result;
}
//
// Here we Manage Signals for Executing ...
// - Check Policies based on their Signaller ...
// - Check Same Time Open Positions ...
// - Check Signal Age for new Trade ...
// and etc ...
int HandleSignalManagement(XSignal &signals[]) override
{
//
int result = 0;
//
int signalsCount = ArraySize(signals);
if (!IsValidSize(signalsCount))
{
return result;
}
//
XSignal tmpSignals[];
Copy(
signals,
tmpSignals //
);
//
Clean(signals);
//
for (int i = 0; i < signalsCount; i++)
{
//
XSignal iSignal = tmpSignals[i];
//
// Handle Close All Positions when Opposit Signal Recieved ...
if (mCloseOnOpposit)
{
//
// Select Signal Opposit Positions ...
ENUM_X_POSITION_TYPE iOpposit = GetOppositXPositionType(iSignal.type);
//
XPosition iPositions[];
int iPositionsCount = mTrader.GetPositions(
iPositions,
iSignal.symbol,
NULL, // All Providers ...
NULL, // All Periods ...
iOpposit // Opposit Positions ...
);
//
if (IsValidSize(iPositionsCount))
{
//
string comment = "Close due Opposit ...";
//
int closeds = Close(
iPositions,
comment //
);
if (IsValidSize(closeds))
{
//
string message = XEQMSupportToken + " Closed " + ToString(iPositionsCount) + " due Opposit Signal ...";
//
Alert(message);
}
}
}
//
AddRef(
iSignal,
signals //
);
}
//
result = ArraySize(signals);
//
return result;
}
//
// Handle State Management ....
// here we can manage current state ...
// - Check for Long Positions for each Signaller to Close ...
// - Handle Hedging Signaller's Positions if it's enabled ...
// - Force Closing Position when Specified Time reached ...
// - Check Start and End time or Trading Dates ...
// - handle Trailing or Risk free Signals based on several conditions ...
// and etc ...
bool HandleStateManagement(XSignal &signals[]) override
{
//
const bool result = false;
//
// Do all State Management here ...
//
DoEQMHedge();
//
// Handle Close All Positions on Specific Time ...
DoEQMCloseOnSpecificTime();
//
// Do EQM Grid if Provided ...
DoEQMGrid();
//
// if Returns true, Signal Execution failed ...
return result;
}
//
// Used for Signal Info States ...
void OnDealsChangedHandler(int count) override
{
//
if (UseSignalCollector())
{
//
XDeal deal;
bool hasDeal = mTrader.GetLastDeal(deal);
if (hasDeal)
{
//
// Update Signal Info State ...
UpdateSignalState(deal);
}
}
}
//
void OnPositionClosed(
const ulong ticket,
const XPosition &position,
const string comment //
) override
{
//
if (UseSignalCollector())
{
UpdateSignalState(ticket, position, comment);
}
}
//
// Protected ...
protected:
//
// Tools ...
//
bool IsEnable()
{
return mAllowLong || mAllowShort;
}
//
bool CanCloseOnTime()
{
//
bool result = false;
//
result = mCloseOnSpecificTime >= 0 && mCloseOnSpecificTime <= 23;
if (!result)
{
return result;
}
//
MqlDateTime timeStruct;
result = TimeCurrent(timeStruct);
if (!result)
{
return result;
}
//
result = timeStruct.hour == mCloseOnSpecificTime;
//
return result;
}
//
// Private ...
private:
//
// Props ...
//
bool mAllowLong; // Allow Long
bool mAllowShort; // Allow Short
double mVolume; // Volume
double mTPPoint; // TP Point
double mSLPoint; // SL Point
bool mIgnoreTP; // Ignore Calculated TP
bool mIgnoreSL; // Ignore Calculated SL
int mMaxAllowedTrades; // Max Alloed Positions
bool mCloseOnOpposit; // Close all Positions on Opposit
int mCloseOnSpecificTime; // Close All Trades in Specific Time
int mReuiredSignalVerifications; // Required Verifications for Validate Signals
bool mGetVerificationFromOtherTimeFrames; // Get Verifications from Other Time Frames
//
bool mUseSupport; // Use Support Signals
bool mUseGrid; // Use Grid Signals
double mGridDistance; // Grid Distance
double mGridVolumeMultiplier; // Grid Volume Multiplier
//
XSignalInfo mSignalInfos[];
XSignalInfoCollector *mSignalCollector;
bool mUseSignalCollector; // Enable or Disable Signal Collector
//
int CountSignalInfos()
{
return ArraySize(mSignalInfos);
}
//
int FindSignalInfoIndex(
ulong positionTicket //
)
{
//
int result = -1;
//
int count = CountSignalInfos();
if (!IsValidSize(count))
{
return result;
}
//
for (int i = 0; i < count; i++)
{
//
XSignalInfo iInfo = mSignalInfos[i];
//
bool isOwn = iInfo.IsOwn(
positionTicket //
);
if (isOwn)
{
//
result = i;
break;
}
}
//
return result;
}
//
int FindSignalInfoIndex(
string symbol,
string provider,
ENUM_TIMEFRAMES period //
)
{
//
int result = -1;
//
int count = CountSignalInfos();
if (!IsValidSize(count))
{
return result;
}
//
for (int i = 0; i < count; i++)
{
//
XSignalInfo iInfo = mSignalInfos[i];
//
bool isOwn = iInfo.IsOwn(
symbol,
provider,
period //
);
if (isOwn)
{
//
result = i;
break;
}
}
//
return result;
}
//
int FindSignalInfoIndex(XDeal &deal)
{
//
int result = -1;
//
if (!deal.IsValid())
{
return result;
}
//
if (IsValid(deal.provider))
{
//
ulong supTicket = ExtractSupportedTicket(deal.comment);
ulong supTicket1 = ExtractEQMSupportedTicket(deal.comment);
//
if (supTicket <= 0 && supTicket1 <= 0)
{
//
result = FindSignalInfoIndex(
deal.symbol,
deal.provider,
deal.period //
);
}
}
else
{
result = FindSignalInfoIndex(deal.positionId);
}
//
return result;
}
//
void AddNewSignal(
int pusher,
XSignal &signal,
double bullishScore,
double bearishScore,
X121SetupConditions &conditions //
)
{
//
if (!UseSignalCollector())
{
return;
}
//
XSignalInfo info;
bool isFilled = info.Fill(
pusher,
signal,
bullishScore,
bearishScore,
conditions //
);
//
if (isFilled)
{
//
AddRef(
info,
mSignalInfos //
);
}
}
//
void UpdateSignalState(XDeal &deal)
{
//
if (!UseSignalCollector())
{
return;
}
//
if (!deal.IsValid())
{
return;
}
//
int infoIDX = FindSignalInfoIndex(deal);
if (!IsValidIndex(infoIDX))
{
return;
}
//
if (deal.entry == DEAL_ENTRY_IN)
{
//
mSignalInfos[infoIDX].time = deal.time;
mSignalInfos[infoIDX].ticket = deal.positionId;
mSignalInfos[infoIDX].commission = deal.commission;
mSignalInfos[infoIDX].signal.positionId = deal.positionId;
}
else if (deal.entry == DEAL_ENTRY_OUT)
{
//
mSignalInfos[infoIDX].swap = deal.swap;
mSignalInfos[infoIDX].endTime = deal.time;
mSignalInfos[infoIDX].profit = deal.profit;
//
string message =
//
deal.reason == DEAL_REASON_TP
? "TP"
: deal.reason == DEAL_REASON_SL
? "SL"
: IsValid(deal.comment)
? deal.comment
: "Force Close ..."
//
;
mSignalInfos[infoIDX].message = message;
//
// Now we can Save Signal Info and Remove it from mSignal Infos ...
bool isSaved = mSignalCollector.Save(mSignalInfos[infoIDX]);
if (isSaved)
{
//
ArrayRemove(
mSignalInfos,
infoIDX,
1 //
);
}
}
}
void UpdateSignalState(
const ulong ticket,
const XPosition &position,
const string message //
)
{
//
if (!UseSignalCollector())
{
return;
}
//
int infoIDX = FindSignalInfoIndex(ticket);
if (!IsValidIndex(infoIDX))
{
return;
}
//
mSignalInfos[infoIDX].message = message;
mSignalInfos[infoIDX].swap = position.swap;
mSignalInfos[infoIDX].endTime = TimeCurrent();
mSignalInfos[infoIDX].profit = position.profit;
//
// Now we can Save Signal Info and Remove it from mSignal Infos ...
bool isSaved = mSignalCollector.Save(mSignalInfos[infoIDX]);
if (isSaved)
{
//
ArrayRemove(
mSignalInfos,
infoIDX,
1 //
);
}
}
//
int mBullishSigns;
double mBullishScore;
//
int mBearishSigns;
double mBearishScore;
//
double mVolumeOSC;
//
XSCX121SetupCycles *mSetups[]; // Number of Setups
//
// Tools ...
int CountSetups()
{
return ArraySize(mSetups);
}
//
int FindSetupIndex(
string symbol,
ENUM_TIMEFRAMES period //
)
{
//
int result = -1;
//
int count = CountSetups();
if (!IsValidSize(count))
{
return result;
}
//
for (int i = 0; i < count; i++)
{
//
XSCX121SetupCycles *iSetup = mSetups[i];
//
X121SetupInputs iInputs = iSetup.GetInputs();
//
if (iInputs.symbol == symbol && iInputs.period == period)
{
//
result = i;
break;
}
}
//
return result;
}
//
// EQM Functions ...
//
// Remove Untriggered EQM Orders ...
void RemoveEQMOrders()
{
//
RemoveDraws("XTRND");
//
XOrder supports[];
int supportsCount = mTrader.GetOrders(
supports,
NULL, // All Symbols ...
XEQMSupportToken, // Only EQM Supports ...
NULL, // All Periods ...
X_POSITION_TYPE_ALL, // All Order Types ...
ORDER_STATE_PLACED, // Untriggered Orders ...
true // Filter by Magic ...
);
if (!IsValidSize(supportsCount))
{
return;
}
//
int cancelled = mTrader.CancelOrders(
supports //
);
//
if (IsValidSize(cancelled))
{
//
string message = XEQMSupportToken + " Cancel " + ToString(cancelled) + " Supports ...";
//
Alert(message);
}
}
//
// Place EQM Orders ...
void PlaceEQMOrders()
{
//
int count = CountSetups();
if (!IsValidSize(count))
{
return;
}
//
XSignal supports[];
//
for (int i = 0; i < count; i++)
{
//
string iSymbol = mSetups[i].GetSymbol();
ENUM_TIMEFRAMES iPeriod = NULL; // All Periods ...
string iProvider = NULL; // All Providers ...
//
XPosition iPositions[];
int iPositionsCount = mTrader.GetPositions(
iPositions,
iSymbol,
iProvider,
iPeriod,
X_POSITION_TYPE_ALL //
);
if (!IsValidSize(iPositionsCount))
{
continue;
}
//
int maxInDIDX = FindMaxDrawdownIndex(
iPositions //
);
if (!IsValidIndex(maxInDIDX))
{
continue;
}
//
XPosition maxInDP = iPositions[maxInDIDX];
bool isLong = IsLong(maxInDP.type);
//
XOHCL iZBar;
bool isInited = iZBar.Init(
iSymbol,
iPeriod,
0 //
);
if (!isInited)
{
continue;
}
//
double iSupport = 0;
double iResistance = 0;
bool isDrawn = DrawTrendState(
ChartID(),
"XTRND",
iZBar,
iSupport,
iResistance //
);
if (isDrawn)
{
//
XSignal iSignal;
//
double iSL = 0;
double iTP = 0;
double iEntry = 0;
ENUM_POSITION_TYPE iType;
ENUM_X_ORDER_MODES iMode;
double iVolume = maxInDP.volume * 3;
//
if (iSupport > 0 && isLong && iSupport > maxInDP.sl && maxInDP.sl > 0)
{
//
// Add Short Support for Long ...
iEntry = iSupport;
iSL = maxInDP.tp;
iTP = maxInDP.sl;
iMode = X_ORDER_MODE_STOP;
iType = POSITION_TYPE_SELL;
//
bool isPrepared = iSignal.Prepare(
iSymbol,
XEQMSupportToken,
iPeriod,
iType,
iMode,
iEntry,
iVolume,
iSL,
iTP //
);
if (isPrepared)
{
//
iSignal.comment = GenerateSupportTag(maxInDP.ticket);
//
AddRef(
iSignal,
supports ///
);
//
iSignal.Clean();
}
}
//
if (iResistance > 0 && !isLong && iResistance < maxInDP.sl && maxInDP.sl > 0)
{
//
// Add Long Support for Short ...
iEntry = iResistance;
iSL = maxInDP.tp;
iTP = maxInDP.sl;
iMode = X_ORDER_MODE_STOP;
iType = POSITION_TYPE_BUY;
//
bool isPrepared = iSignal.Prepare(
iSymbol,
XEQMSupportToken,
iPeriod,
iType,
iMode,
iEntry,
iVolume,
iSL,
iTP //
);
if (isPrepared)
{
//
iSignal.comment = GenerateSupportTag(maxInDP.ticket);
//
AddRef(
iSignal,
supports ///
);
//
iSignal.Clean();
}
}
}
}
//
int supportsCount = ArraySize(supports);
if (!IsValidSize(supportsCount))
{
return;
}
//
ENUM_X_SIGNAL_EXECUTION_RESULT states[];
int executeds = mTrader.ExecuteSignals(
supports,
states,
ORDER_TIME_GTC,
false,
false // Ignore Policies
);
if (IsValidSize(executeds))
{
//
string message = XEQMSupportToken + " Execute " + ToString(executeds) + " Supports ...";
//
Alert(message);
}
}
//
// Do Gridding Mechanism ...
void DoEQMGrid()
{
//
if (!UseGrid())
{
return;
}
// //
// int infosCount = CountSignalInfos();
// if (!IsValidSize(infosCount))
// {
// return;
// }
// //
// for (int i = 0; i < infosCount; i++)
// {
// //
// // Check Signal Executed or not ...
// if (mSignalInfos[i].ticket <= 0)
// {
// continue;
// }
// //
// // Check Specific Position not a Support Position ...
// XPosition position;
// bool hasPosition = mTrader.GetPosition(
// mSignalInfos[i].ticket,
// position //
// );
// if (!hasPosition)
// {
// continue;
// }
// //
// // Check Position not a Support or EQM Support ...
// ulong supParent = 0;
// supParent = ExtractSupportedTicket(position.comment);
// if (supParent > 0)
// {
// continue;
// }
// supParent = ExtractEQMSupportedTicket(position.comment);
// if (supParent > 0)
// {
// continue;
// }
// //
// // Check Grid Data ...
// if (mSignalInfos[i].gEntry <= 0 || mSignalInfos[i].gVolume <= 0)
// {
// continue;
// }
// //
// // Retrieve Type of Position ...
// bool isLong = IsLong(mSignalInfos[i].signal.type);
// //
// // Retrieve Cureent Entry Price based on Signal ...
// double cEntry = GetEntry(
// mSignalInfos[i].symbol,
// mSignalInfos[i].signal.type //
// );
// //
// // Check Price Distance passed or not ...
// bool isPriceDistancePassedForGrid =
// isLong
// ? cEntry <= mSignalInfos[i].gEntry
// : cEntry >= mSignalInfos[i].gEntry;
// if (!isPriceDistancePassedForGrid)
// {
// continue;
// }
// //
// // Prepare Grid Signal ...
// XSignal gSignal;
// bool isPrepared = gSignal.Prepare(
// mSignalInfos[i].signal.symbol,
// mSignalInfos[i].signal.provider,
// mSignalInfos[i].signal.period,
// mSignalInfos[i].signal.type,
// X_ORDER_MODE_MARKET,
// mSignalInfos[i].gEntry,
// mSignalInfos[i].gVolume,
// 0, // SL ...
// 0 // TP ...
// );
// if (!isPrepared)
// {
// continue;
// }
// //
// // Add Support Tag ...
// string comment = GenerateSupportTag(mSignalInfos[i].ticket);
// gSignal.comment = comment;
// //
// // Try to Execute Grid Signal ...
// ENUM_X_SIGNAL_EXECUTION_RESULT gState;
// int isExecuted = mTrader.ExecuteSignal(
// gSignal,
// gState,
// ORDER_TIME_GTC,
// NULL,
// false // Ignore Policies ...
// );
// if (isExecuted)
// {
// //
// // Update Grid State of Signal Info ...
// //
// double gDistancePrice = PointToPrice(
// mGridDistance,
// mSignalInfos[i].signal.symbol //
// );
// //
// mSignalInfos[i].gVolume *= mGridVolumeMultiplier;
// mSignalInfos[i].gEntry = isLong
// ? mSignalInfos[i].gEntry - gDistancePrice
// : mSignalInfos[i].gEntry + gDistancePrice;
// //
// string message = XEQMSupportToken + " Execute Grid ...";
// //
// Alert(message);
// }
// }
}
//
// Handle Close Trades on Specific Time ...
void DoEQMCloseOnSpecificTime()
{
//
bool canClose = CanCloseOnTime();
if (!canClose)
{
return;
}
//
XPosition positions[];
int positionsCount = mTrader.GetPositions(positions);
if (!IsValidSize(positionsCount))
{
return;
}
//
string comment = XEQMSupportToken + " Close On Specific Time ...";
//
int closed = Close(
positions,
comment //
);
if (IsValidSize(closed))
{
//
string message = XEQMSupportToken + " Closed " + ToString(closed) + " Positions on Specified Time ...";
//
Alert(message);
}
}
};
//