2811 lines
67 KiB
Plaintext
2811 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();
|
|
|
|
//
|
|
ResetGrid();
|
|
}
|
|
|
|
//
|
|
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;
|
|
}
|
|
|
|
//
|
|
// Grid ...
|
|
|
|
//
|
|
double gVolume; // Next Grid Volume
|
|
double gEntry; // Next Grid Entry
|
|
|
|
//
|
|
void ResetGrid()
|
|
{
|
|
//
|
|
gEntry = 0;
|
|
gVolume = 0;
|
|
}
|
|
|
|
//
|
|
};
|
|
|
|
//
|
|
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);
|
|
mSignalCollector = new XSignalInfoCollector();
|
|
}
|
|
|
|
//
|
|
// Deconstructor ...
|
|
~XSCX121SetupEA()
|
|
{
|
|
//
|
|
int count = CountSignalInfos();
|
|
if (IsValidSize(count))
|
|
{
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
mSignalCollector.Save(mSignalInfos[i]);
|
|
}
|
|
|
|
//
|
|
Clean(mSignalInfos);
|
|
}
|
|
|
|
//
|
|
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;
|
|
}
|
|
|
|
//
|
|
// 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 //
|
|
);
|
|
|
|
//
|
|
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 //
|
|
);
|
|
|
|
//
|
|
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 //
|
|
);
|
|
|
|
//
|
|
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 //
|
|
);
|
|
|
|
//
|
|
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 //
|
|
);
|
|
|
|
//
|
|
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
|
|
{
|
|
//
|
|
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
|
|
{
|
|
//
|
|
UpdateSignalState(ticket, position, comment);
|
|
}
|
|
|
|
//
|
|
void OnGoingToProfit(XProfitTrack &track) override
|
|
{
|
|
// RemoveEQMOrders();
|
|
}
|
|
|
|
//
|
|
void OnGoingToDrawdown(XProfitTrack &track) override
|
|
{
|
|
// PlaceEQMOrders();
|
|
}
|
|
|
|
//
|
|
// 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;
|
|
|
|
//
|
|
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 //
|
|
)
|
|
{
|
|
//
|
|
XSignalInfo info;
|
|
bool isFilled = info.Fill(
|
|
pusher,
|
|
signal,
|
|
bullishScore,
|
|
bearishScore,
|
|
conditions //
|
|
);
|
|
|
|
//
|
|
if (isFilled)
|
|
{
|
|
//
|
|
AddRef(
|
|
info,
|
|
mSignalInfos //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
void UpdateSignalState(XDeal &deal)
|
|
{
|
|
//
|
|
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;
|
|
|
|
//
|
|
bool isLong = IsLong(mSignalInfos[infoIDX].signal.type);
|
|
double sEntry = mSignalInfos[infoIDX].signal.entry;
|
|
|
|
//
|
|
// Setting Grid Data ...
|
|
if (mUseGrid)
|
|
{
|
|
//
|
|
mSignalInfos[infoIDX].ResetGrid();
|
|
|
|
//
|
|
double gDistancePrice = PointToPrice(
|
|
mGridDistance,
|
|
mSignalInfos[infoIDX].signal.symbol //
|
|
);
|
|
|
|
//
|
|
mSignalInfos[infoIDX].gVolume = mSignalInfos[infoIDX].volume * mGridVolumeMultiplier;
|
|
mSignalInfos[infoIDX].gEntry = isLong
|
|
? sEntry - gDistancePrice
|
|
: sEntry + gDistancePrice;
|
|
}
|
|
}
|
|
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 //
|
|
)
|
|
{
|
|
//
|
|
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 (!mUseGrid)
|
|
{
|
|
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);
|
|
}
|
|
}
|
|
};
|
|
|
|
//
|