Files
xMQL5/BKPS/14030412/Classes/x-saherelm.x121.setup.xea.mq5
T
2024-07-02 17:37:21 +03:30

5772 lines
127 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.x121.setup.cycle.class.mq5"
#include "../Classes/x-saherelm.xea.class.mq5"
//
// Definitions ...
//
// Model all Trades Data as this Structure ...
struct XTradeInfo
{
//
int pushers; // Signal Pushers
datetime time; // Issue Time (Open Position)
string symbol; // Trading Symbol
double entry; // Entry Price
double volume; // Volume
string provider; // Signaller
ENUM_TIMEFRAMES period; // Trading Timeframe
ENUM_X_POSITION_TYPES type; // Position Type
//
ulong ticket; // Position Ticket
double profit; // Profit on Close
double commission; // Commission
double swap; // Swap
string message; // Close Reason
datetime endTime; // End Time
//
X121SetupConditions cConditions; // Generated Current Conditions
X121SetupConditions sConditions; // Generated Short Conditions
X121SetupConditions mConditions; // Generated Medium Conditions
X121SetupConditions lConditions; // Generated Long Conditions
X121SetupConditions hConditions; // Generated Hind Conditions
//
// Constructor ...
void XTradeInfo()
{
Clean();
}
//
// Tools ...
//
// Cleanup ...
void Clean()
{
//
time = NULL;
type = NULL;
symbol = NULL;
period = NULL;
endTime = NULL;
message = NULL;
provider = NULL;
//
swap = 0;
entry = 0;
ticket = 0;
profit = 0;
volume = 0;
pushers = 0;
commission = 0;
//
cConditions.Clean();
sConditions.Clean();
mConditions.Clean();
lConditions.Clean();
hConditions.Clean();
//
ResetGrid();
ResetSupport();
ResetRecovery();
}
//
bool Fill(
const XSignal &_signal,
int _pushers,
bool _allowGrid,
bool _allowRecover,
bool _allowSupport,
X121SetupConditions &_cConditions,
X121SetupConditions &_sConditions,
X121SetupConditions &_mConditions,
X121SetupConditions &_lConditions,
X121SetupConditions &_hConditions //
)
{
//
bool result = false;
//
result =
//
IsValid(_signal.symbol) &&
IsValid(_signal.period) &&
IsValid(_signal.provider)
//
;
//
if (!result)
{
return result;
}
//
pushers = _pushers;
time = _signal.time;
entry = _signal.entry;
symbol = _signal.symbol;
period = _signal.period;
volume = _signal.volume;
provider = _signal.provider;
type = ToPositionType(_signal.type);
//
cConditions = _cConditions;
sConditions = _sConditions;
mConditions = _mConditions;
lConditions = _lConditions;
hConditions = _hConditions;
//
allowGrid = _allowGrid;
allowRecover = _allowRecover;
allowSupport = _allowSupport;
//
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(type) + "\\" +
(profit >= 0 ? "Profit" : "Loss") +
"\\" +
provider + "_" +
ToString(ticket) + "_" +
ToString(period) + "_" +
ToFormatString(time)
//
;
//
return result;
}
//
string GetSignalFileName()
{
//
string result = NULL;
//
result =
//
symbol + "\\" +
ToString(type) + "\\" +
provider + "_" +
ToFormatString(time)
//
;
//
return result;
}
//
string ToString(
bool onlySignals = false //
)
{
//
string result = NULL;
//
string cConditionsStr = cConditions
.GenerateSummary(
false, // Only Commons ...
true, // Only Conditions ...
false, // Include Score ...
false // Include False Conditions ...
);
double cBullishScore = 0;
double cBearishScore = 0;
cConditions.GenerateScore(
cBullishScore,
cBearishScore //
);
//
string sConditionsStr = sConditions
.GenerateSummary(
false, // Only Commons ...
true, // Only Conditions ...
false, // Include Score ...
false // Include False Conditions ...
);
double sBullishScore = 0;
double sBearishScore = 0;
sConditions.GenerateScore(
sBullishScore,
sBearishScore //
);
//
string mConditionsStr = mConditions
.GenerateSummary(
false, // Only Commons ...
true, // Only Conditions ...
false, // Include Score ...
false // Include False Conditions ...
);
double mBullishScore = 0;
double mBearishScore = 0;
mConditions.GenerateScore(
mBullishScore,
mBearishScore //
);
//
string lConditionsStr = lConditions
.GenerateSummary(
false, // Only Commons ...
true, // Only Conditions ...
false, // Include Score ...
false // Include False Conditions ...
);
double lBullishScore = 0;
double lBearishScore = 0;
lConditions.GenerateScore(
lBullishScore,
lBearishScore //
);
//
string hConditionsStr = hConditions
.GenerateSummary(
false, // Only Commons ...
true, // Only Conditions ...
false, // Include Score ...
false // Include False Conditions ...
);
double hBullishScore = 0;
double hBearishScore = 0;
hConditions.GenerateScore(
hBullishScore,
hBearishScore //
);
//
//
int age = GetAge();
//
result =
//
(onlySignals ? "" : ToString("Ticket", ticket)) +
ToString("Symbol", symbol) +
ToString("Period", period) +
ToString("Entry", entry) +
ToString("Provider", provider) +
ToString("Type", ToString(type)) +
ToString("Time", time) +
ToString("Pushers", pushers) +
(onlySignals
? ""
:
//
"-------------" + "\n" +
ToString("Volume", volume) +
ToString("Profit", profit) +
ToString("Commission", commission) +
ToString("Swap", swap) +
ToString("End Time", endTime) +
ToString("Age", age) +
ToString("Message", message)
//
) +
"-------------" + "\n" +
"Conditions" + "\n" +
"-------------" + "\n" +
"-------------" + "\n" +
"CURRENT [" + ToString(cConditions.period) + "]" + "\n" + "\n" +
"Bullish: " + ToString(cBullishScore) + "\n" +
"Bearish: " + ToString(cBearishScore) + "\n" +
"-------------" + "\n" +
cConditionsStr + "\n" +
"-------------" + "\n" +
"SHORT [" + ToString(sConditions.period) + "]" + "\n" + "\n" +
"Bullish: " + ToString(sBullishScore) + "\n" +
"Bearish: " + ToString(sBearishScore) + "\n" +
"-------------" + "\n" +
sConditionsStr + "\n" +
"-------------" + "\n" +
"MEDIUM [" + ToString(mConditions.period) + "]" + "\n" + "\n" +
"Bullish: " + ToString(mBullishScore) + "\n" +
"Bearish: " + ToString(mBearishScore) + "\n" +
"-------------" + "\n" +
mConditionsStr + "\n" +
"-------------" + "\n" +
"LONG [" + ToString(lConditions.period) + "]" + "\n" + "\n" +
"Bullish: " + ToString(lBullishScore) + "\n" +
"Bearish: " + ToString(lBearishScore) + "\n" +
"-------------" + "\n" +
lConditionsStr + "\n" +
"-------------" + "\n" +
"HIND [" + ToString(hConditions.period) + "]" + "\n" + "\n" +
"Bullish: " + ToString(hBullishScore) + "\n" +
"Bearish: " + ToString(hBearishScore) + "\n" +
"-------------" + "\n" +
hConditionsStr + "\n" +
//
""
//
;
//
return result;
}
//
// These are Some Helpers for Trading Controls and do not relate to Main
// purpose of Trade Handler ...
//
// Supporting ...
//
bool allowSupport; // Allow Support
//
void ResetSupport()
{
allowSupport = false;
}
//
// Retrieve Support Signal ...
bool HasSupport(
XSignal &support //
)
{
//
bool result = false;
//
return result;
}
//
// Grid System Calculations ...
//
int gLevel; // Number of Grids
bool allowGrid; // Allow Grid
double gEntry; // Represents Next Grid Signal's Entry
double gVolume; // Represent Next Grid Signal's Volume
//
void ResetGrid()
{
//
gEntry = 0;
gLevel = 0;
gVolume = 0;
//
allowGrid = false;
}
//
void SetGrid(
double nextEntry,
double nextVolume //
)
{
//
gEntry = nextEntry;
gVolume = nextVolume;
}
//
// Prepare Data For Next Grid ...
void PrepareNextGrid(
double distance,
double volumeMultiplier //
)
{
//
bool isValid =
//
IsValid() &&
entry > 0 &&
volume > 0 &&
distance > 0 &&
volumeMultiplier > 0
//
;
bool isLong = IsLong(type);
//
double distancePrice = PointToPrice(
distance,
symbol //
);
//
double selectedEntry =
gEntry <= 0
? entry
: gEntry;
double selectedVolume =
gVolume <= 0
? volume
: gVolume;
//
double nextEntry =
isLong
? selectedEntry - distancePrice
: selectedEntry + distancePrice;
double nextVolume = selectedVolume * volumeMultiplier;
//
SetGrid(
nextEntry,
nextVolume //
);
}
//
// Check if a Grid Signal Exists Prepared and
// Provide it ...
bool HasGrid(
XSignal &signal, // Result Signal
double distance,
double volumeMultiplier //
)
{
//
bool result = false;
//
signal.Clean();
//
result = IsValid() &&
distance > 0 &&
volumeMultiplier > 0;
if (!result)
{
return result;
}
//
bool isLong = IsLong(type);
//
ENUM_POSITION_TYPE gType =
isLong ? POSITION_TYPE_BUY : POSITION_TYPE_SELL;
//
double cEntry = GetEntry(
symbol,
gType //
);
//
result =
isLong
? cEntry <= gEntry
: cEntry >= gEntry;
if (!result)
{
return result;
}
//
result = signal.Prepare(
symbol,
provider,
period,
gType,
X_ORDER_MODE_MARKET,
cEntry,
gVolume,
0, // SL ...
0 // TP ...
);
//
if (result)
{
//
// set Support Token ...
string comment = GenerateSupportTag(ticket);
signal.comment = comment;
//
PrepareNextGrid(
distance,
volumeMultiplier //
);
//
gLevel++;
}
//
return result;
}
//
// Recovery Zone System ...
//
bool allowRecover; // Allow Recover
ENUM_POSITION_TYPE rLastRecoveryType; // Last Executed Recovery Signal's Type
double rLongEntry; // Represent Next Recovery Long Signal's Entry
double rShortEntry; // Represent Next Recovery Short Signal's Entry
double rVolume; // Represent Next Recovery Signal's Volume
double rZoneUpper; // Zone Recovery Upper Bound
double rZoneLower; // Zone Recovery Lower Bound
int rLevel; // Number of Recoveries
//
void ResetRecovery()
{
//
rLevel = 0;
rVolume = 0;
rLongEntry = 0;
rZoneUpper = 0;
rZoneLower = 0;
rShortEntry = 0;
//
allowRecover = false;
}
//
void SetRecovery(
double nextLongEntry,
double nextShortEntry,
double zoneUpper,
double zoneLower,
double nextVolume //
)
{
//
rVolume = nextVolume;
rZoneUpper = zoneUpper;
rZoneLower = zoneLower;
rLongEntry = nextLongEntry;
rShortEntry = nextShortEntry;
}
//
void PrepareNextRecovery(
double distance, // Define Target Based On Zones
double volumeMultiplier, // Volume Multiplier
ENUM_POSITION_TYPE lastType // Last Type
)
{
//
bool isValid =
//
IsValid() &&
entry > 0 &&
volume > 0 &&
distance > 0 &&
volumeMultiplier > 0
//
;
//
bool isLong = IsLong(lastType);
//
double distancePrice = PointToPrice(
distance,
symbol //
);
//
double selectedEntry =
isLong
? rLongEntry <= 0
? entry
: rLongEntry
: rShortEntry <= 0
? entry
: rShortEntry;
double selectedVolume =
rVolume <= 0
? volume
: rVolume;
//
double nextLongEntry =
isLong
? selectedEntry
: selectedEntry + distancePrice;
double nextShortEntry =
isLong
? selectedEntry - distancePrice
: selectedEntry;
//
double nextVolume = selectedVolume * volumeMultiplier;
// rLevel % 2 == 1
// ? volume
// : volume * volumeMultiplier;
//
double zoneUpper =
rZoneUpper > 0
? rZoneUpper
: isLong
? entry + distancePrice
: entry + (distancePrice * 2);
double zoneLower =
rZoneLower > 0
? rZoneLower
: isLong
? entry + (distancePrice * 2)
: entry - distancePrice;
//
SetRecovery(
nextLongEntry,
nextShortEntry,
zoneUpper,
zoneLower,
nextVolume //
);
//
rLastRecoveryType = lastType;
}
//
// Check if a Recovery Signal Exists Prepared and
// Provide it ...
bool HasRecovery(
XSignal &signal, // Result Signal ...
double distance,
double volumeMultiplier //
)
{
//
bool result = false;
//
signal.Clean();
//
result =
//
IsValid() &&
entry > 0 &&
volume > 0 &&
distance > 0 &&
volumeMultiplier > 0
//
;
if (!result)
{
return result;
}
//
double distancePrice = PointToPrice(
distance,
symbol //
);
//
bool isLong = IsLong(type);
bool isLastLong = IsLong(rLastRecoveryType);
//
// Check For Long Recovery ...
double cLongEntry = GetEntry(
symbol,
POSITION_TYPE_BUY //
);
bool hasLongRecovery =
!isLastLong &&
rLongEntry > 0 && cLongEntry >= rLongEntry;
//
// Check For Short Recovery ...
double cShortEntry = GetEntry(
symbol,
POSITION_TYPE_SELL //
);
bool hasShortRecovery =
isLastLong &&
rShortEntry > 0 &&
cShortEntry <= rShortEntry;
//
result = hasLongRecovery || hasShortRecovery;
if (!result)
{
return result;
}
//
ENUM_POSITION_TYPE rType =
hasLongRecovery
? POSITION_TYPE_BUY
: POSITION_TYPE_SELL;
//
double rEntry =
hasLongRecovery
? cLongEntry
: cShortEntry;
//
double rTP =
hasLongRecovery
? rZoneUpper
: rZoneLower;
//
double rSL =
hasLongRecovery
? rZoneLower
: rZoneUpper;
//
result = signal.Prepare(
symbol,
provider,
period,
rType,
X_ORDER_MODE_MARKET,
rEntry,
rVolume,
0, // rSL, // SL ...
0 // rTP // TP ...
);
if (result)
{
//
// set Support Token ...
string comment = GenerateSupportTag(ticket);
signal.comment = comment;
//
rLevel++;
//
PrepareNextRecovery(
distance,
volumeMultiplier,
rType //
);
}
//
return result;
}
};
//
// a Class For Read and Write Trade Info Data in Files ...
class XTradeInfoCollector
{
//
// Public ...
public:
//
// Props ...
//
// Constructor(s) ...
void XTradeInfoCollector(
string _path = NULL // Base Path
)
{
//
mAccount = new XSCAccount();
//
if (IsValid(_path))
{
mPath = _path;
}
else
{
mPath = "XTradeInfo" + "\\" + mAccount.GetCompany();
}
}
//
// Deconstructor ...
void ~XTradeInfoCollector() {}
//
bool IsExists(XTradeInfo &item)
{
//
bool result = false;
//
int mHandler = GetFileHandlerForRead(item);
result = mHandler != INVALID_HANDLE;
FileClose(mHandler);
//
return result;
}
//
bool Save(XTradeInfo &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;
}
//
bool SaveSignal(XTradeInfo &item)
{
//
bool result = false;
//
string content = item.ToString(true);
result = IsValid(content);
if (!result)
{
return result;
}
//
int mHandler = GetSignalFileHandlerForWrite(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(XTradeInfo &item)
{
//
string fileName = item.GetFileName();
//
return GetFilePath(fileName);
}
string GetFilePath(string fileName)
{
//
string result = "";
//
result =
//
mPath + "\\" + "Trades" + "\\" + fileName + ".x121.log"
//
;
//
return result;
}
//
string GetSignalFilePath(XTradeInfo &item)
{
//
string fileName = item.GetSignalFileName();
//
return GetSignalFilePath(fileName);
}
string GetSignalFilePath(string fileName)
{
//
string result = "";
//
result =
//
mPath + "\\" + "Signals" + "\\" + fileName + ".x121.log"
//
;
//
return result;
}
//
int GetFileHandlerForRead(XTradeInfo &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(XTradeInfo &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;
}
//
int GetSignalFileHandlerForRead(XTradeInfo &item)
{
//
int result = INVALID_HANDLE;
//
string filePath = GetSignalFilePath(item);
if (!IsValid(filePath))
{
return result;
}
//
result = FileOpen(
filePath,
FILE_READ | FILE_TXT //
);
//
return result;
}
int GetSignalFileHandlerForWrite(XTradeInfo &item)
{
//
int result = INVALID_HANDLE;
//
string filePath = GetSignalFilePath(item);
if (!IsValid(filePath))
{
return result;
}
//
result = FileOpen(
filePath,
FILE_READ | FILE_WRITE | FILE_TXT //
);
//
return result;
}
};
//
// a Class for Holding all required data for Specified Trade
// such as:
// - Signal;
// - Position;
// - Conditions;
// - Scores;
// - etc ...
class XTradeHandler
{
//
public:
//
// Props ...
//
// Constructor ...
void XTradeHandler(
XSCTrade *trade // an Instance of Trader Class
)
{
//
Clean(data);
SetSave(false);
mTrader = trade;
collector = new XTradeInfoCollector();
}
//
// Getter(s) / Setter(s) ...
//
// Others ...
//
bool GetSave()
{
return mSave;
}
//
void SetSave(bool value)
{
mSave = value;
}
//
bool GetSaveSignalsOnly()
{
return mSaveSignalsOnly;
}
//
void SetSaveSignalsOnly(bool value)
{
mSaveSignalsOnly = value;
}
//
// Hedging ...
//
double MinProfitPerTrade()
{
return mMinProfitPerTrade;
}
//
void MinProfitPerTrade(double value)
{
//
if (value < 0)
{
value = 0;
}
//
mMinProfitPerTrade = value;
}
//
double MinProfitPerVolumeFactor()
{
return mMinProfitPerVolumeFactor;
}
//
void MinProfitPerVolumeFactor(double value)
{
//
if (value < 0)
{
value = 0;
}
//
if (value > 0 && value < 0.01)
{
value = 0.01;
}
//
mMinProfitPerVolumeFactor = value;
}
//
// Trailling Stop ...
//
bool AllowTrailStop()
{
return mAllowTrailStop;
}
//
void AllowTrailStop(bool value)
{
mAllowTrailStop = value;
}
//
bool DisableTrailingWhenOpposit()
{
return mDisableTrailingWhenOpposit;
}
//
void DisableTrailingWhenOpposit(bool value)
{
mDisableTrailingWhenOpposit = value;
}
//
double NextTrailPoint()
{
return mNextTrailPoint;
}
//
void NextTrailPoint(double value)
{
//
if (value < 0)
{
value = 0;
}
//
mNextTrailPoint = value;
}
//
double FirstTrailPoint()
{
return mFirstTrailPoint;
}
//
void FirstTrailPoint(double value)
{
//
if (value < 0)
{
value = 0;
}
//
mFirstTrailPoint = value;
}
//
double NextTrailDistance()
{
return mNextTrailDistance;
}
//
void NextTrailDistance(double value)
{
//
if (value < 0)
{
value = 0;
}
//
mNextTrailDistance = value;
}
//
double FirstTrailDistance()
{
return mFirstTrailDistance;
}
//
void FirstTrailDistance(double value)
{
//
if (value < 0)
{
value = 0;
}
//
mFirstTrailDistance = value;
}
//
bool EnableTrailling()
{
//
bool result = false;
//
result =
//
AllowTrailStop() &&
NextTrailPoint() > 0 &&
FirstTrailPoint() > 0 &&
NextTrailDistance() > 0 &&
FirstTrailDistance() > 0
//
;
//
return result;
}
//
// Supporting ...
//
bool AllowSupport()
{
return mAllowSupport;
}
//
void AllowSupport(bool value)
{
mAllowSupport = value;
}
//
bool SupportOnlyForces()
{
return mSupportOnlyForces;
}
//
void SupportOnlyForces(bool value)
{
mSupportOnlyForces = value;
}
//
double SupportDistance()
{
return mSupportDistance;
}
//
void SupportDistance(double value)
{
//
if (value < 0)
{
value = 0;
}
//
mSupportDistance = value;
}
//
int MaxNumberOfSupports()
{
return mMaxNumberOfSupports;
}
//
void MaxNumberOfSupports(int value)
{
//
if (value < 0)
{
value = 0;
}
//
mMaxNumberOfSupports = value;
}
//
double SupportVolumeMultiplier()
{
return mSupportVolumeMultiplier;
}
//
void SupportVolumeMultiplier(double value)
{
//
if (value < 1)
{
value = 1;
}
//
mSupportVolumeMultiplier = value;
}
//
double MaxAllowedSupportVolume()
{
return mMaxAllowedSupportVolume;
}
//
void MaxAllowedSupportVolume(double value)
{
//
if (value < 0.01)
{
value = 0.01;
}
//
mMaxAllowedSupportVolume = value;
}
//
bool EnableSupport()
{
//
bool result = false;
//
result =
//
AllowSupport() &&
SupportDistance() > 0 &&
MaxNumberOfSupports() >= 0 &&
SupportVolumeMultiplier() > 0
//
;
//
return result;
}
//
// Grid ...
//
bool AllowGrid()
{
return mAllowGrid;
}
//
void AllowGrid(bool value)
{
mAllowGrid = value;
}
//
bool GridOnlyForces()
{
return mGridOnlyForces;
}
//
void GridOnlyForces(bool value)
{
mGridOnlyForces = value;
}
//
int MaxNumberOfGrids()
{
return mMaxNumberOfGrids;
}
//
void MaxNumberOfGrids(int value)
{
//
if (value < 0)
{
value = 0;
}
//
mMaxNumberOfGrids = 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 < 1)
{
value = 1;
}
//
mGridVolumeMultiplier = value;
}
//
double MaxAllowedGridVolume()
{
return mMaxAllowedGridVolume;
}
//
void MaxAllowedGridVolume(double value)
{
//
if (value < 0.01)
{
value = 0.01;
}
//
mMaxAllowedGridVolume = value;
}
//
// Check Grid Properties to Validate it's Enable or not ...
bool EnableGrid()
{
//
bool result = false;
//
result =
//
AllowGrid() &&
GridDistance() > 0 &&
MaxNumberOfGrids() >= 0 &&
GridVolumeMultiplier() > 0
//
;
//
return result;
}
//
// Recovery System ...
//
bool AllowRecovery()
{
return mAllowRecovery;
}
//
void AllowRecovery(bool value)
{
mAllowRecovery = value;
}
//
bool RecoverOnlyForces()
{
return mRecoverOnlyForces;
}
//
void RecoverOnlyForces(bool value)
{
mRecoverOnlyForces = value;
}
//
int MaxNumberOfRecoveries()
{
return mMaxNumberOfRecoveries;
}
//
void MaxNumberOfRecoveries(int value)
{
//
if (value < 0)
{
value = 0;
}
//
mMaxNumberOfRecoveries = value;
}
//
double RecoveryDistance()
{
return mRecoveryDistance;
}
//
void RecoveryDistance(double value)
{
//
if (value < 0)
{
value = 0;
}
//
mRecoveryDistance = value;
}
//
double RecoveryVolumeMultiplier()
{
return mRecoveryVolumeMultiplier;
}
//
void RecoveryVolumeMultiplier(double value)
{
//
if (value < 1)
{
value = 1;
}
//
mRecoveryVolumeMultiplier = value;
}
//
double MaxAllowedRecoveryVolume()
{
return mMaxAllowedRecoveryVolume;
}
//
void MaxAllowedRecoveryVolume(double value)
{
//
if (value < 0.01)
{
value = 0.01;
}
//
mMaxAllowedRecoveryVolume = value;
}
//
// Check Recovery Properties to Validate it's Enable or not ...
bool EnableRecovery()
{
//
bool result = false;
//
result =
//
AllowRecovery() &&
RecoveryDistance() > 0 &&
MaxNumberOfRecoveries() >= 0 &&
RecoveryVolumeMultiplier() > 0
//
;
//
return result;
}
//
// Tools ...
//
int Count()
{
return ArraySize(data);
}
//
int FindIndex(ulong ticket)
{
//
int result = -1;
//
int count = Count();
if (!IsValidSize(count))
{
return result;
}
//
for (int i = 0; i < count; i++)
{
//
XTradeInfo iInfo = data[i];
//
bool isOwn = iInfo.IsOwn(
ticket //
);
if (isOwn)
{
//
result = i;
break;
}
}
//
return result;
}
//
int FindIndex(XSignal &signal)
{
//
int result = -1;
//
int count = Count();
if (!IsValidSize(count))
{
return result;
}
//
for (int i = 0; i < count; i++)
{
//
XTradeInfo iInfo = data[i];
//
bool isOWN =
//
iInfo.time == signal.time &&
iInfo.symbol == signal.symbol &&
iInfo.volume == signal.volume &&
iInfo.period == signal.period &&
iInfo.provider == signal.provider &&
iInfo.type == ToPositionType(signal.type)
//
;
//
if (isOWN)
{
//
result = i;
break;
}
}
//
return result;
}
//
void Add(
XSignal &signal,
int pushers,
bool allowGrid,
bool allowRecover,
bool allowSupport,
X121SetupConditions &cConditions,
X121SetupConditions &sConditions,
X121SetupConditions &mConditions,
X121SetupConditions &lConditions,
X121SetupConditions &hConditions //
)
{
//
XTradeInfo info;
bool isFilled = info.Fill(
signal,
pushers,
allowGrid,
allowRecover,
allowSupport,
cConditions,
sConditions,
mConditions,
lConditions,
hConditions //
);
if (!isFilled)
{
return;
}
//
AddRef(
info,
data //
);
//
if (GetSaveSignalsOnly())
{
collector.SaveSignal(info);
}
}
//
void Remove(XSignal &signal)
{
//
int infoIDX = FindIndex(signal);
if (!IsValidIndex(infoIDX))
{
return;
}
//
ArrayRemove(
data,
infoIDX,
1 //
);
}
//
void Update(XSignal &signal)
{
//
if (!signal.IsValid() || !signal.IsExecuted())
{
return;
}
//
int infoIDX = FindIndex(signal);
if (!IsValidIndex(infoIDX))
{
return;
}
//
data[infoIDX].volume = signal.volume;
data[infoIDX].ticket = signal.positionId;
//
// Find Orders for Accessing Commission ...
XDeal deals[];
int dealsCount = mTrader.GetDeals(
deals,
signal.symbol,
signal.provider,
signal.period,
NULL,
DEAL_ENTRY_IN // Position Open Deal ...
);
if (!IsValidSize(dealsCount))
{
return;
}
//
for (int i = 0; i < dealsCount; i++)
{
//
XDeal iDeal = deals[i];
//
if (iDeal.positionId == signal.positionId)
{
data[infoIDX].commission = iDeal.commission;
}
}
//
// Check if Grid System Enable or Not ...
if (EnableGrid())
{
//
// Here we Prepare Handler Structure for
// Next Grid Position ...
if (data[infoIDX].allowGrid)
{
//
data[infoIDX].PrepareNextGrid(
GridDistance(),
GridVolumeMultiplier() //
);
}
}
//
// Check if Recovery System Enable or Not ...
if (EnableRecovery())
{
//
if (data[infoIDX].allowRecover)
{
//
data[infoIDX].PrepareNextRecovery(
GridDistance(),
GridVolumeMultiplier(),
signal.type //
);
}
}
}
//
void Update(XDeal &deal)
{
//
if (!deal.IsValid())
{
return;
}
//
int infoIDX = FindIndex(deal.positionId);
if (!IsValidIndex(infoIDX))
{
return;
}
//
data[infoIDX].swap = deal.swap;
data[infoIDX].endTime = deal.time;
data[infoIDX].profit = deal.profit;
//
string message = deal.reason == DEAL_REASON_TP ? "TP" : "SL";
data[infoIDX].message = message;
//
Finish(infoIDX);
}
//
void Update(XPosition &position)
{
//
if (!position.IsValid())
{
return;
}
//
int infoIDX = FindIndex(position.ticket);
if (!IsValidIndex(infoIDX))
{
return;
}
//
data[infoIDX].swap = position.swap;
data[infoIDX].endTime = TimeCurrent();
data[infoIDX].profit = position.profit;
data[infoIDX].message = position.comment;
//
Finish(infoIDX);
}
//
// Sync ...
void Sync()
{
//
int count = Count();
if (!IsValidSize(count))
{
return;
}
//
int mustRemoved[];
for (int i = 0; i < count; i++)
{
//
XTradeInfo iInfo = data[i];
//
if (iInfo.ticket > 0 && !mTrader.IsOpen(iInfo.ticket))
{
//
AddSpecific(
i,
mustRemoved //
);
}
}
//
int mustRemovedCount = ArraySize(mustRemoved);
if (!IsValidSize(mustRemovedCount))
{
return;
}
//
for (int i = 0; i < mustRemovedCount; i++)
{
//
ArrayRemove(
data,
i,
1 //
);
}
}
//
// Protection Handlers ...
//
// Handle Do All Protecting ...
int DoProtect(
XSignal &signals[], // if PRotecting Generate Some Support Signals, Holds them here
XSCX121SetupCycles *&setups[] // Number of Setups
)
{
//
int result = 0;
//
// Calling Protection Algorithms ...
//
// Trailling ...
if (EnableTrailling())
{
int traillings = HandleTrailling();
}
//
if (AllowSupport())
{
//
XSignal supports[];
int supportsCount = RequestForSupport(
supports,
setups //
);
//
if (IsValidSize(supportsCount))
{
//
Copy(
supports,
signals,
false //
);
}
}
//
// Grid ...
if (EnableGrid())
{
//
XSignal grids[];
int gridsCount = RequestForGrid(grids);
if (IsValidSize(gridsCount))
{
//
Copy(
grids,
signals,
false //
);
}
}
//
// Recovery ...
if (EnableRecovery())
{
//
XSignal recoveries[];
int recoveriesCount = RequestForRecovery(recoveries);
if (IsValidSize(recoveriesCount))
{
//
Copy(
recoveries,
signals,
false //
);
}
}
//
result = ArraySize(signals);
//
return result;
}
//
int GetBreakoutsSignals(XSignal &signals[])
{
//
int result = 0;
//
Clean(signals);
//
int count = Count();
if (!IsValidSize(count))
{
return result;
}
//
for (int i = 0; i < count; i++)
{
//
double iEntry = data[i].entry;
string iSymbol = data[i].symbol;
ENUM_TIMEFRAMES iPeriod = data[i].period;
ENUM_X_POSITION_TYPES iType = data[i].type;
//
bool isLong = IsLong(iType);
ENUM_POSITION_TYPE iPType =
isLong
? POSITION_TYPE_BUY
: POSITION_TYPE_SELL;
//
double cEntry = GetEntry(
iSymbol,
iPType //
);
//
XOHCL cBar;
bool isInited = cBar.Init(
iSymbol,
iPeriod,
1 //
);
if (!isInited)
{
continue;
}
//
bool isBullish = cBar.IsBullish();
bool isBreakUp = cBar.IsBreakUp(iEntry);
//
bool isBearish = cBar.IsBearish();
bool isBreakDown = cBar.IsBreakDown(iEntry);
//
bool isBreaked =
isLong
? isBullish &&
isBreakUp &&
cEntry > iEntry
: isBearish &&
isBreakDown &&
cEntry < iEntry;
//
if (isBreaked)
{
//
// Update Date of TradeInfo ...
data[i].entry = cEntry;
data[i].time = TimeCurrent();
//
// Generate Signal ...
XSignal iSignal;
bool isPrepared = iSignal.Prepare(
data[i].symbol,
data[i].provider,
data[i].period,
iPType,
X_ORDER_MODE_MARKET,
data[i].entry,
data[i].volume,
0,
0 //
);
//
// Add Signal to Result ...
if (isPrepared)
{
//
AddRef(
iSignal,
signals //
);
}
}
// //
// double hotLevels[];
// //
// AddSpecific(
// 0.25,
// hotLevels //
// );
// //
// AddSpecific(
// 0.20,
// hotLevels //
// );
// //
// AddSpecific(
// 0.12,
// hotLevels //
// );
// //
// XSCZonesInput zonesInput;
// zonesInput.length = 71;
// zonesInput.numberOfZones = 10;
// XSCZones *zones = new XSCZones(
// iSymbol,
// _Period //
// );
// //
// zonesInput.AddLevelColor(
// hotLevels[0],
// clrRed //
// );
// zonesInput.AddLevelColor(
// hotLevels[1],
// clrOrange //
// );
// zonesInput.AddLevelColor(
// hotLevels[2],
// clrLightCoral //
// );
// bool canUseZones = zones.Init(zonesInput);
// //
// XSCCFInput cfInputs;
// cfInputs.Default();
// XSCCF *cf = new XSCCF(
// iSymbol,
// _Period //
// );
// bool canUseCF = cf.Init(cfInputs);
// //
// XSCTrendInput tInputs;
// tInputs.Default();
// XSCTrend *trend = new XSCTrend(
// iSymbol,
// _Period //
// );
// bool canUseTrend = trend.Init(tInputs);
// if (canUseCF && canUseTrend && canUseZones)
// {
// //
// // cf.Draw();
// trend.Draw();
// // zones.Draw();
// Print("Use CF ...");
// // cf.Remove();
// // trend.Remove();
// // zones.Remove();
// }
}
//
result = ArraySize(signals);
//
return result;
}
//
// Protected ...
protected:
//
// Props ...
XSCTrade *mTrader;
XTradeInfo data[];
XTradeInfoCollector *collector;
//
bool mSave; // Save Results ...
bool mSaveSignalsOnly; // Save Only Signals and COnditions
//
// Hedging ...
double mMinProfitPerTrade; // Minimum Required Profit for Hedging
double mMinProfitPerVolumeFactor; // Minimum Required Profit for Hedging Per Volume
//
// Trailling ...
bool mAllowTrailStop; // Enable Trailling Stop Losses
bool mDisableTrailingWhenOpposit; // Disable Trailling When has Opposite In Drawdown
double mNextTrailPoint; // Next Trailling Step
double mFirstTrailPoint; // First Stop Trail
double mFirstTrailDistance; // Start Trailling Distance
double mNextTrailDistance; // Next Trailling Distance
//
// Supporting ...
bool mAllowSupport; // Allow Support Signals
bool mSupportOnlyForces; // Support Only Force Signals
double mSupportDistance; // Supporting Distance
int mMaxNumberOfSupports; // Max Number of Support Signals
double mSupportVolumeMultiplier; // Support Signals Volume Multiplier
double mMaxAllowedSupportVolume; // Max Allowed Support Signals Volume
//
// Grid ...
bool mAllowGrid; // Allow Grid Signals
bool mGridOnlyForces; // Grid Only Force Signals
int mMaxNumberOfGrids; // Max Number of Grid Signals
double mGridDistance; // Grid Distance
double mGridVolumeMultiplier; // Grid Volume Multiplier
double mMaxAllowedGridVolume; // Max Allowed Grid Signals Volume
//
// Recovery ...
bool mAllowRecovery; // Allow Recovery Signals
bool mRecoverOnlyForces; // Recover Only Force Signals
int mMaxNumberOfRecoveries; // Max Number of Recovery Signals
double mRecoveryDistance; // Recovery Distance
double mRecoveryVolumeMultiplier; // Recovery Volume Multiplier
double mMaxAllowedRecoveryVolume; // Max Allowed Recovery Signals Volume
//
// Tools ...
//
void Finish(int index)
{
//
XTradeInfo info = data[index];
if (!info.IsValid())
{
return;
}
//
ArrayRemove(
data,
index,
1 //
);
//
if (GetSave())
{
collector.Save(info);
}
}
//
// Protection Methods ...
//
int HandleTrailling()
{
//
int result = 0;
//
// Check Trailling is Enabled or not ...
if (!EnableTrailling())
{
return result;
}
//
// Do Synch Before Start Trailing ...
Sync();
//
// Since Trailing Done based On In Profit Positions ...
// First we Check if ...
XPosition positions[];
XPosition inDPositions[];
XPosition inPPositions[];
int positionsCount = mTrader.GetPositions(positions);
if (!IsValidSize(positionsCount))
{
return result;
}
//
int inDPositionsCount = ExtractInDrawdownPositions(
positions,
inDPositions //
);
int inPPositionsCount = ExtractInProfitPositions(
positions,
inPPositions //
);
if (!IsValidSize(inPPositionsCount))
{
return result;
}
//
for (int i = 0; i < inPPositionsCount; i++)
{
//
XPosition iPosition = inPPositions[i];
//
// ignore Support Positions ...
bool isSupport = IsSupport(iPosition.comment);
if (isSupport)
{
continue;
}
//
// Only Trail Positions which they Hasnt any Support ...
bool hasSupport = mTrader.HasSupport(iPosition.ticket);
result = !hasSupport;
if (!result)
{
return result;
}
//
// Find Positin Info Index ...
int idx = FindIndex(iPosition.ticket);
if (!IsValidIndex(idx))
{
continue;
}
//
bool isLong = IsLong(iPosition.type);
//
// Here we Select Price for SL Trailling ...
double usedPrice = 0;
if (iPosition.sl != 0)
{
//
if (isLong)
{
//
if (iPosition.sl < iPosition.entry)
{
usedPrice = iPosition.entry;
}
else
{
usedPrice = iPosition.sl;
}
}
else
{
//
if (iPosition.sl > iPosition.entry)
{
usedPrice = iPosition.entry;
}
else
{
usedPrice = iPosition.sl;
}
}
}
else
{
usedPrice = iPosition.entry;
}
//
double nextTrailPoint = NextTrailPoint();
double firstTrailPoint = FirstTrailPoint();
double nextTrailDistance = NextTrailDistance();
double firstTrailDistance = FirstTrailDistance();
//
bool isFirstTrail = usedPrice == iPosition.entry;
//
double usedTrailDiff =
isFirstTrail
? MathMax(firstTrailPoint, firstTrailDistance)
: MathMax(nextTrailPoint, nextTrailDistance);
//
double iExit = GetExit(
iPosition.symbol,
iPosition.type //
);
double iPriceDistance = MathAbs(usedPrice - iExit);
double iPriceDistanceInPoint = PriceToPoint(
iPriceDistance,
iPosition.symbol //
);
//
bool canTrail = iPriceDistanceInPoint >= usedTrailDiff;
if (!canTrail)
{
continue;
}
//
// Check Opposit Side Position ...
// if Exists, dont Trail ...
if (DisableTrailingWhenOpposit() && IsValidSize(inDPositionsCount))
{
//
bool canTrail = true;
ENUM_POSITION_TYPE oppositType = GetOpposit(iPosition.type);
for (int j = 0; j < inDPositionsCount; j++)
{
//
XPosition inDPosition = inDPositions[j];
//
bool isOpposit =
inDPosition.symbol == iPosition.symbol &&
inDPosition.type == oppositType;
if (isOpposit)
{
//
canTrail = false;
break;
}
}
//
if (!canTrail)
{
continue;
}
}
//
usedTrailDiff =
isFirstTrail
? MathMin(firstTrailPoint, firstTrailDistance)
: MathMin(nextTrailPoint, nextTrailDistance);
double usedTrailDiffPrice = PointToPrice(
usedTrailDiff,
iPosition.symbol //
);
//
double sl =
isLong
? usedPrice + usedTrailDiffPrice
: usedPrice - usedTrailDiffPrice;
string comment = PrepareSLTrailTag(iPosition.comment);
//
bool isModified = mTrader.Modify(
iPosition.ticket,
sl,
iPosition.tp,
comment //
);
if (isModified)
{
result++;
}
}
//
return result;
}
//
int RequestForSupport(
XSignal &signals[],
XSCX121SetupCycles *&setups[] //
)
{
//
int result = 0;
//
Clean(signals);
//
if (!AllowSupport())
{
return result;
}
//
Sync();
//
int count = Count();
if (!IsValidSize(count))
{
return result;
}
//
for (int i = 0; i < count; i++)
{
//
XSignal iSupport;
double iPivot = -1;
int iPivotIDX = -1;
bool hasSupport = data[i].HasSupport(
iSupport //
);
if (hasSupport)
{
//
AddRef(
iSupport,
signals //
);
}
}
//
result = ArraySize(signals);
//
// TODO: Complete this Later ...
return result;
//
// Validate Setups Count ...
// int setupsCount = ArraySize(setups);
// if (!IsValidSize(setupsCount))
// {
// return result;
// }
// //
// // Implement Supporting Mechanism ...
// //
// // Extracting In Drawdown Positions ...
// XPosition positions[];
// int positionsCount = mTrader.GetInDrawdownPositions(
// positions //
// );
// if (!IsValidSize(positionsCount))
// {
// return result;
// }
// //
// double supportDistance = SupportDistance();
// int maxNUmberOfSupports = MaxNumberOfSupports();
// double maxAllowedVolume = MaxAllowedSupportVolume();
// double volumeMultiplier = SupportVolumeMultiplier();
// //
// X121SignalGenerator signalGenerator;
// //
// for (int i = 0; i < positionsCount; i++)
// {
// //
// XPosition iPosition = positions[i];
// //
// // Check Position is not Support Position ...
// bool isSupport = IsSupport(iPosition.comment);
// if (isSupport)
// {
// continue;
// }
// //
// // Find Related Setp ...
// int idx = FindSetupIndex(
// iPosition.symbol,
// setups //
// );
// if (!IsValidIndex(idx))
// {
// continue;
// }
// //
// int index = FindIndex(iPosition.ticket);
// if (!IsValidIndex(index))
// {
// continue;
// }
// //
// // Check Position must atleast 20 Point in drawdown ...
// //
// double onePointPrice = PointToPrice(
// 1,
// iPosition.symbol //
// );
// //
// double iExitPrice = GetExit(
// iPosition.symbol,
// iPosition.type //
// );
// //
// double priceDiff = MathAbs(iPosition.entry - iExitPrice);
// double priceDiffPoints = priceDiff / onePointPrice;
// //
// bool isFarEnough = priceDiffPoints >= (supportDistance / 2);
// if (!isFarEnough)
// {
// continue;
// }
// //
// // Check Support COunts and etc ...
// // implementing supporting mechanis ...
// //
// }
// //
// result = ArraySize(signals);
//
return result;
}
//
int RequestForGrid(XSignal &signals[])
{
//
int result = 0;
//
Clean(signals);
//
if (!EnableGrid())
{
return result;
}
//
int maxAllowed = MaxNumberOfGrids();
double maxAllowedVolume = MaxAllowedGridVolume();
//
int count = Count();
if (!IsValidSize(count))
{
return result;
}
//
for (int i = 0; i < count; i++)
{
//
// Check Count ...
bool isMaxPassed =
maxAllowed <= 0
? true
: data[i].gLevel < maxAllowed;
if (!isMaxPassed)
{
continue;
}
//
XSignal iSignal;
bool hasGrid = data[i].HasGrid(
iSignal,
GridDistance(),
GridVolumeMultiplier() //
);
//
if (hasGrid)
{
//
// Check Max Volume ...
iSignal.volume =
maxAllowedVolume <= 0
? iSignal.volume
: MathMin(iSignal.volume, maxAllowedVolume);
//
AddRef(
iSignal,
signals //
);
}
}
//
result = ArraySize(signals);
//
return result;
}
//
int RequestForRecovery(XSignal &signals[])
{
//
int result = 0;
//
Clean(signals);
//
if (!EnableRecovery())
{
return result;
}
//
int maxAllowed = MaxNumberOfRecoveries();
double maxAllowedVolume = MaxAllowedRecoveryVolume();
//
int count = Count();
if (!IsValidSize(count))
{
return result;
}
//
for (int i = 0; i < count; i++)
{
//
// Check Count ...
bool isMaxPassed =
maxAllowed <= 0
? true
: data[i].rLevel < maxAllowed;
if (!isMaxPassed)
{
continue;
}
//
XSignal iSignal;
bool hasRecovery = data[i].HasRecovery(
iSignal,
RecoveryDistance(),
RecoveryVolumeMultiplier() //
);
//
if (hasRecovery)
{
//
// Check Max Volume ...
iSignal.volume =
maxAllowedVolume <= 0
? iSignal.volume
: MathMin(iSignal.volume, maxAllowedVolume);
//
AddRef(
iSignal,
signals //
);
}
}
//
result = ArraySize(signals);
//
return result;
}
//
int FindSetupIndex(
string symbol,
XSCX121SetupCycles *&setups[] //
)
{
//
int result = 0;
//
if (!IsValid(symbol))
{
return result;
}
//
for (int i = 0; i < ArraySize(setups); i++)
{
//
if (setups[i].GetSymbol() == symbol)
{
//
result = i;
break;
}
}
//
return result;
}
//
void AddHotLevelsToZones(
XSCZones *zones //
)
{
//
zones.AddLevelColor(
0.25,
clrRed //
);
zones.AddLevelColor(
0.20,
clrOrange //
);
zones.AddLevelColor(
0.15,
clrYellow //
);
}
};
//
// Class ...
class XSCX121SetupEA : public XSCBaseEA
{
//
// Public ...
public:
//
// Props ...
X121SignalGenerator signalGenerator;
//
// 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 //
)
{
//
mTradeHandler = new XTradeHandler(mTrader);
//
// Implement Default Configs ...
DefaultConfigs();
}
//
// Deconstructor ...
~XSCX121SetupEA()
{
//
delete mTradeHandler;
//
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) ...
//
/// Signals ...
//
bool AllowLong()
{
return mAllowLong;
}
//
void AllowLong(bool value)
{
mAllowLong = value;
}
//
bool AllowShort()
{
return mAllowShort;
}
//
void AllowShort(bool value)
{
mAllowShort = value;
}
//
int DelayBetweenTwoSignal()
{
return mDelayBetweenTwoSignal;
}
//
void DelayBetweenTwoSignal(int value)
{
//
if (value < 0)
{
value = 0;
}
//
mDelayBetweenTwoSignal = 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;
}
//
bool ExecuteSignalsOnBreakout()
{
return mExecuteSignalsOnBreakout;
}
//
void ExecuteSignalsOnBreakout(bool value)
{
mExecuteSignalsOnBreakout = value;
}
//
// Risk Management ...
//
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;
}
//
int MaxAllowedTrades()
{
return mMaxAllowedTrades;
}
//
void MaxAllowedTrades(int value)
{
//
if (value < 0)
{
value = 0;
}
//
mMaxAllowedTrades = value;
// mTrader.SetMaxAllowedPositions(value);
}
//
bool UseMaxAllowedPerDirection()
{
return mUseMaxAllowedPerDirection;
}
//
void UseMaxAllowedPerDirection(bool value)
{
mUseMaxAllowedPerDirection = value;
}
//
bool IgnoreTP()
{
return mIgnoreTP;
}
//
void IgnoreTP(bool value)
{
mIgnoreTP = value;
}
//
bool IgnoreSL()
{
return mIgnoreSL;
}
//
void IgnoreSL(bool value)
{
mIgnoreSL = value;
}
//
bool IncreaseNextSignalsVolume()
{
return mIncreaseNextSignalsVolume;
}
//
void IncreaseNextSignalsVolume(bool value)
{
mIncreaseNextSignalsVolume = value;
}
//
double IncreaseNextSignalsVolumeMultiplier()
{
return mIncreaseNextSignalsVolumeMultiplier;
}
//
void IncreaseNextSignalsVolumeMultiplier(double value)
{
//
if (value <= 0)
{
value = 0;
}
//
mIncreaseNextSignalsVolumeMultiplier = value;
}
//
bool AcceptNextDirectionalSignalsWhenFirstInProfit()
{
return mAcceptNextDirectionalSignalsWhenFirstInProfit;
}
//
void AcceptNextDirectionalSignalsWhenFirstInProfit(bool value)
{
mAcceptNextDirectionalSignalsWhenFirstInProfit = value;
}
//
// Signalling ...
//
int StartSignallingHoure()
{
return mStartSignallingHoure;
}
//
void StartSignallingHoure(int value)
{
//
if (value < -1)
{
value = -1;
}
//
mStartSignallingHoure = value;
}
//
int EndSignallingHoure()
{
return mEndSignallingHoure;
}
//
void EndSignallingHoure(int value)
{
//
if (value < -1)
{
value = -1;
}
//
mEndSignallingHoure = value;
}
//
int CloseOnSpecificTime()
{
return mCloseOnSpecificTime;
}
//
void CloseOnSpecificTime(int value)
{
//
if (value < -1)
{
value = -1;
}
//
mCloseOnSpecificTime = value;
}
//
bool CloseOnOpposit()
{
return mCloseOnOpposit;
}
//
void CloseOnOpposit(bool value)
{
mCloseOnOpposit = value;
}
//
// Trailling ...
//
bool AllowTrailStop()
{
return mTradeHandler.AllowTrailStop();
}
//
void AllowTrailStop(bool value)
{
mTradeHandler.AllowTrailStop(value);
}
//
bool DisableTrailingWhenOpposit()
{
return mTradeHandler.DisableTrailingWhenOpposit();
}
//
void DisableTrailingWhenOpposit(bool value)
{
mTradeHandler.DisableTrailingWhenOpposit(value);
}
//
double NextTrailPoint()
{
return mTradeHandler.NextTrailPoint();
}
//
void NextTrailPoint(double value)
{
mTradeHandler.NextTrailPoint(value);
}
//
double FirstTrailPoint()
{
return mTradeHandler.FirstTrailPoint();
}
//
void FirstTrailPoint(double value)
{
mTradeHandler.FirstTrailPoint(value);
}
//
double NextTrailDistance()
{
return mTradeHandler.NextTrailDistance();
}
//
void NextTrailDistance(double value)
{
mTradeHandler.NextTrailDistance(value);
}
//
double FirstTrailDistance()
{
return mTradeHandler.FirstTrailDistance();
}
//
void FirstTrailDistance(double value)
{
mTradeHandler.FirstTrailDistance(value);
}
//
// Supporting ...
//
bool AllowSupport()
{
return mTradeHandler.AllowSupport();
}
//
void AllowSupport(bool value)
{
mTradeHandler.AllowSupport(value);
}
//
bool SupportOnlyForces()
{
return mTradeHandler.SupportOnlyForces();
}
//
void SupportOnlyForces(bool value)
{
mTradeHandler.SupportOnlyForces(value);
}
//
bool EnableSupport()
{
return mTradeHandler.EnableSupport();
}
//
double SupportDistance()
{
return mTradeHandler.SupportDistance();
}
//
void SupportDistance(double value)
{
mTradeHandler.SupportDistance(value);
}
//
int MaxNumberOfSupports()
{
return mTradeHandler.MaxNumberOfSupports();
}
//
void MaxNumberOfSupports(int value)
{
mTradeHandler.MaxNumberOfSupports(value);
}
//
double SupportVolumeMultiplier()
{
return mTradeHandler.SupportVolumeMultiplier();
}
//
void SupportVolumeMultiplier(double value)
{
mTradeHandler.SupportVolumeMultiplier(value);
}
//
double MaxAllowedSupportVolume()
{
return mTradeHandler.MaxAllowedSupportVolume();
}
//
void MaxAllowedSupportVolume(double value)
{
mTradeHandler.MaxAllowedSupportVolume(value);
}
//
// Grid ...
//
bool AllowGrid()
{
return mTradeHandler.AllowGrid();
}
//
void AllowGrid(bool value)
{
mTradeHandler.AllowGrid(value);
}
//
bool GridOnlyForces()
{
return mTradeHandler.GridOnlyForces();
}
//
void GridOnlyForces(bool value)
{
mTradeHandler.GridOnlyForces(value);
}
//
bool EnableGrid()
{
return mTradeHandler.EnableGrid();
}
//
int MaxNumberOfGrids()
{
return mTradeHandler.MaxNumberOfGrids();
}
//
void MaxNumberOfGrids(int value)
{
mTradeHandler.MaxNumberOfGrids(value);
}
//
double GridDistance()
{
return mTradeHandler.GridDistance();
}
//
void GridDistance(double value)
{
mTradeHandler.GridDistance(value);
}
//
double GridVolumeMultiplier()
{
return mTradeHandler.GridVolumeMultiplier();
}
//
void GridVolumeMultiplier(double value)
{
mTradeHandler.GridVolumeMultiplier(value);
}
//
double MaxAllowedGridVolume()
{
return mTradeHandler.MaxAllowedGridVolume();
}
//
void MaxAllowedGridVolume(double value)
{
mTradeHandler.MaxAllowedGridVolume(value);
}
//
// Recovery System ...
//
bool AllowRecovery()
{
return mTradeHandler.AllowRecovery();
}
//
void AllowRecovery(bool value)
{
mTradeHandler.AllowRecovery(value);
}
//
bool RecoverOnlyForces()
{
return mTradeHandler.RecoverOnlyForces();
}
//
void RecoverOnlyForces(bool value)
{
mTradeHandler.RecoverOnlyForces(value);
}
//
bool EnableRecovery()
{
return mTradeHandler.EnableRecovery();
}
//
int MaxNumberOfRecoveries()
{
return mTradeHandler.MaxNumberOfRecoveries();
}
//
void MaxNumberOfRecoveries(int value)
{
mTradeHandler.MaxNumberOfRecoveries(value);
}
//
double RecoveryDistance()
{
return mTradeHandler.RecoveryDistance();
}
//
void RecoveryDistance(double value)
{
mTradeHandler.RecoveryDistance(value);
}
//
double RecoveryVolumeMultiplier()
{
return mTradeHandler.RecoveryVolumeMultiplier();
}
//
void RecoveryVolumeMultiplier(double value)
{
mTradeHandler.RecoveryVolumeMultiplier(value);
}
//
double MaxAllowedRecoveryVolume()
{
return mTradeHandler.MaxAllowedRecoveryVolume();
}
//
void MaxAllowedRecoveryVolume(double value)
{
mTradeHandler.MaxAllowedRecoveryVolume(value);
}
//
// Others ...
//
bool SaveResults()
{
return mTradeHandler.GetSave();
}
//
void SaveResults(bool value)
{
mTradeHandler.SetSave(value);
}
//
bool SaveSignalsOnly()
{
return mTradeHandler.GetSaveSignalsOnly();
}
//
void SaveSignalsOnly(bool value)
{
mTradeHandler.SetSaveSignalsOnly(value);
}
//
double MinFreeMargingForOpenTrades()
{
return mMinFreeMargingForOpenTrades;
}
//
void MinFreeMargingForOpenTrades(double value)
{
//
if (value < 0)
{
value = 0;
}
//
mMinFreeMargingForOpenTrades = value;
}
//
double MaxAllowedDrawdownPercent()
{
return mMaxAllowedDrawdownPercent;
}
//
void MaxAllowedDrawdownPercent(double value)
{
//
if (value < 0)
{
value = 0;
}
//
if (value > 50)
{
value = 50;
}
//
mMaxAllowedDrawdownPercent = value;
}
//
// Hedging ...
//
double MinProfitPerTrade()
{
return mTradeHandler.MinProfitPerTrade();
}
//
void MinProfitPerTrade(double value)
{
//
MinRequiredProfitPerTrade(value);
mTradeHandler.MinProfitPerTrade(value);
}
//
double MinProfitPerVolumeFactor()
{
return mTradeHandler.MinProfitPerVolumeFactor();
}
//
void MinProfitPerVolumeFactor(double value)
{
//
MinRequiredProfitPerVolumeFactor(value);
mTradeHandler.MinProfitPerVolumeFactor(value);
}
//
// Overrides ...
//
// Customize Token ...
string GetToken() override
{
return GetSpecificToken(this);
}
//
string GetTag() override
{
return this.GetToken();
}
//
// Tools ...
//
// 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;
}
//
// Current ...
double cTP = 0;
double cSL = 0;
XSignal cSignal;
int cPusher = 0;
bool cHasSignal = false;
string cProvider = NULL;
X121SetupConditions cConditions;
//
// Short ...
double sTP = 0;
double sSL = 0;
XSignal sSignal;
int sPusher = 0;
bool sHasSignal = false;
string sProvider = NULL;
X121SetupConditions sConditions;
//
// Medium ...
double mTP = 0;
double mSL = 0;
XSignal mSignal;
int mPusher = 0;
bool mHasSignal = false;
string mProvider = NULL;
X121SetupConditions mConditions;
//
// Long ...
double lTP = 0;
double lSL = 0;
XSignal lSignal;
int lPusher = 0;
bool lHasSignal = false;
string lProvider = NULL;
X121SetupConditions lConditions;
//
// Hind ...
double hTP = 0;
double hSL = 0;
XSignal hSignal;
int hPusher = 0;
bool hHasSignal = false;
string hProvider = NULL;
X121SetupConditions hConditions;
//
bool canSupport =
//
EnableSupport() &&
!SupportOnlyForces()
//
;
bool canGrid =
//
EnableGrid() &&
!GridOnlyForces()
//
;
bool canRecover =
//
EnableRecovery() &&
!RecoverOnlyForces()
//
;
//
double volume = Volume();
double slPoint = SLPoint();
double tpPoint = TPPoint();
bool ignoreSL = IgnoreSL();
bool ignoreTP = IgnoreTP();
bool allowLong = AllowLong();
bool allowShort = AllowShort();
//
bool useCMarket = true;
bool useSMarket = true;
bool useMMarket = true;
bool useLMarket = true;
bool useHMarket = true;
//
for (int i = 0; i < count; i++)
{
//
// Current Market ...
//
cPusher = 0;
cSignal.Clean();
cProvider = NULL;
cHasSignal = false;
cConditions.Clean();
//
cHasSignal =
!useCMarket
? false
: mSetups[i].ProcessMarket(
cSignal,
cConditions,
cPusher,
cProvider,
cTP,
cSL,
X_MARKET_CYCLE_UNKNOWN,
canSupport,
allowLong,
allowShort,
volume,
slPoint,
ignoreSL,
tpPoint,
ignoreTP,
0,
5 //
);
//
// Short Market ...
//
sPusher = 0;
sSignal.Clean();
sProvider = NULL;
sHasSignal = false;
sConditions.Clean();
//
sHasSignal =
!useSMarket
? false
: mSetups[i].ProcessMarket(
sSignal,
sConditions,
sPusher,
sProvider,
sTP,
sSL,
X_MARKET_CYCLE_SHORT,
canSupport,
allowLong,
allowShort,
volume,
slPoint,
ignoreSL,
tpPoint,
ignoreTP,
0,
5 //
);
//
// Medium Market ...
//
mPusher = 0;
mSignal.Clean();
mProvider = NULL;
mHasSignal = false;
mConditions.Clean();
//
mHasSignal = !useMMarket
? false
: mSetups[i].ProcessMarket(
mSignal,
mConditions,
mPusher,
mProvider,
mTP,
mSL,
X_MARKET_CYCLE_MEDIUM,
canSupport,
allowLong,
allowShort,
volume,
slPoint,
ignoreSL,
tpPoint,
ignoreTP,
0,
5 //
);
//
// Long Market ...
//
lPusher = 0;
lSignal.Clean();
lProvider = NULL;
lHasSignal = false;
lConditions.Clean();
//
lHasSignal = !useLMarket
? false
: mSetups[i].ProcessMarket(
lSignal,
lConditions,
lPusher,
lProvider,
lTP,
lSL,
X_MARKET_CYCLE_LONG,
canSupport,
allowLong,
allowShort,
volume,
slPoint,
ignoreSL,
tpPoint,
ignoreTP,
0,
5 //
);
//
// Hind Market ...
//
hPusher = 0;
hSignal.Clean();
hProvider = NULL;
hHasSignal = false;
hConditions.Clean();
//
hHasSignal = !useHMarket
? false
: mSetups[i].ProcessMarket(
hSignal,
hConditions,
hPusher,
hProvider,
hTP,
hSL,
X_MARKET_CYCLE_HIND,
canSupport,
allowLong,
allowShort,
volume,
slPoint,
ignoreSL,
tpPoint,
ignoreTP,
0,
5 //
);
//
// Parse Signals and Add them for Executing ...
//
// Check if there is a Signal or Not ...
bool hasSignal = cHasSignal || sHasSignal || mHasSignal || lHasSignal || hHasSignal;
if (hasSignal)
{
//
XSignal signal;
X121SetupConditions otherConditions[];
//
if (cHasSignal)
{
//
signal.Clean();
signal = cSignal;
//
AddRef(
cConditions,
otherConditions //
);
AddRef(
sConditions,
otherConditions //
);
AddRef(
mConditions,
otherConditions //
);
AddRef(
lConditions,
otherConditions //
);
AddRef(
hConditions,
otherConditions //
);
}
//
if (sHasSignal)
{
//
signal.Clean();
signal = sSignal;
//
AddRef(
cConditions,
otherConditions //
);
AddRef(
sConditions,
otherConditions //
);
AddRef(
mConditions,
otherConditions //
);
AddRef(
lConditions,
otherConditions //
);
AddRef(
hConditions,
otherConditions //
);
}
//
if (mHasSignal)
{
//
signal.Clean();
signal = mSignal;
//
AddRef(
cConditions,
otherConditions //
);
AddRef(
sConditions,
otherConditions //
);
AddRef(
mConditions,
otherConditions //
);
AddRef(
lConditions,
otherConditions //
);
AddRef(
hConditions,
otherConditions //
);
}
//
if (lHasSignal)
{
//
signal.Clean();
signal = lSignal;
//
AddRef(
cConditions,
otherConditions //
);
AddRef(
sConditions,
otherConditions //
);
AddRef(
mConditions,
otherConditions //
);
AddRef(
lConditions,
otherConditions //
);
AddRef(
hConditions,
otherConditions //
);
}
//
if (hHasSignal)
{
//
signal.Clean();
signal = hSignal;
//
AddRef(
cConditions,
otherConditions //
);
AddRef(
sConditions,
otherConditions //
);
AddRef(
mConditions,
otherConditions //
);
AddRef(
lConditions,
otherConditions //
);
AddRef(
hConditions,
otherConditions //
);
}
//
int pushers = cPusher + sPusher + mPusher + lPusher + hPusher;
//
bool isLong = IsLong(signal.type);
//
// Validate Signal ...
bool isValid =
//
// Handle Pusher Validations ...
(mReuiredSignalVerifications <= 0
? true
: pushers >= mReuiredSignalVerifications)
//
&&
//
// Handle Other Conditions Validations ...
(!mGetVerificationFromOtherTimeFrames
? true
: isLong
? signalGenerator.HasLongVerifications(otherConditions)
: signalGenerator.HasShortVerifications(otherConditions))
//
;
//
// bool forceState = mSetups[i].ForceState();
bool forceState = mForce;
//
if (isValid && !forceState)
{
//
// Add Signal to Execution Result ...
AddRef(
signal,
signals //
);
//
// Add new Signal Info ...
mTradeHandler.Add(
signal,
pushers,
canGrid,
canRecover,
canSupport,
cConditions,
sConditions,
mConditions,
lConditions,
hConditions //
);
}
else
{
//
// Clear Other Conditions ...
Clean(otherConditions);
//
// Fill All Conditions to Other Conditions ...
AddRef(
cConditions,
otherConditions //
);
AddRef(
sConditions,
otherConditions //
);
AddRef(
mConditions,
otherConditions //
);
AddRef(
lConditions,
otherConditions //
);
AddRef(
hConditions,
otherConditions //
);
//
// If Recieved Any Unverified Signal
// we Passed it to EQM Manager ...
EQMHandleInvalidSignal(
signal,
pushers,
isValid,
otherConditions //
);
}
}
}
//
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[];
XSignal eSignals[]; // Must Executed
Copy(
signals,
tmpSignals //
);
//
Clean(signals);
//
int maxAllowed = MaxAllowedTrades();
bool perDirection = UseMaxAllowedPerDirection();
//
XPosition positions[];
int positionsCount = mTrader.GetPositions(positions);
bool hasPositions = IsValidSize(positionsCount);
//
double minProfitPerTrade = MinProfitPerTrade();
double minProfitPerTradeVolumeFactor = MinProfitPerVolumeFactor();
//
XSymbolPositions symbolPositions[];
int smybolPositionsCount = ExtractSymbolPositions(
positions,
symbolPositions,
minProfitPerTrade,
minProfitPerTradeVolumeFactor //
);
bool hasSymbolPositions = IsValidSize(smybolPositionsCount);
//
for (int i = 0; i < signalsCount; i++)
{
//
XSignal iSignal = tmpSignals[i];
//
bool isLong = IsLong(iSignal.type);
//
bool isSignalValid = false;
bool hasSameTypeSignal = false;
bool isFirstSymbolSignal = false;
//
// Find Symbol Index ...
int symbolIDX = FindSymbolIndex(
iSignal.symbol,
symbolPositions //
);
bool isValidSymbolIDX = IsValidIndex(symbolIDX);
if (!isValidSymbolIDX)
{
//
// We Sure it is First Signal of Smybol in a While ...
hasSameTypeSignal = false;
isFirstSymbolSignal = true;
}
else
{
//
// We Sure it isnt First Signal of Symbol at current State ...
isFirstSymbolSignal = false;
//
// Check Has Same Type Signal or not ...
hasSameTypeSignal =
isLong
? symbolPositions[symbolIDX].CountLongs() > 1
: symbolPositions[symbolIDX].CountShorts() > 1;
}
//
// New Signals Only Accepted when there is not any Support Signals
// on their types ...
if (hasSameTypeSignal)
{
//
isSignalValid =
isLong
? symbolPositions[symbolIDX].CountLongSupports() <= 0
: symbolPositions[symbolIDX].CountShortSupports() <= 0;
}
else
{
isSignalValid = true;
}
if (!isSignalValid)
{
continue;
}
//
// Check Signal Delay Passed ...
isSignalValid =
!isValidSymbolIDX
? true
: IsSignalDelayPassed(
iSignal,
symbolPositions[symbolIDX] //
);
if (!isSignalValid)
{
continue;
}
//
// Handle Close All Positions when Opposit Signal Recieved ...
if (mCloseOnOpposit)
{
//
// Close Opposit Positions ...
int oppositCount =
!isValidSymbolIDX
? 0
: isLong
? symbolPositions[symbolIDX].CountShorts()
: symbolPositions[symbolIDX].CountLongs();
bool hasOpposit = IsValidSize(oppositCount);
if (hasOpposit)
{
//
XPosition opposit[];
if (isLong)
{
//
Copy(
symbolPositions[symbolIDX].shorts,
opposit //
);
}
else
{
//
Copy(
symbolPositions[symbolIDX].longs,
opposit //
);
}
//
string comment = "Close due Opposit ...";
//
int closeds = Close(
opposit,
comment //
);
if (IsValidSize(closeds))
{
//
string message = XEQMSupportToken + " Closed " + ToString(oppositCount) + " due Opposit Signal ...";
//
Alert(message);
}
//
Clean(opposit);
}
//
// Close Opposit Supports ...
int oppositSupportCount =
!isValidSymbolIDX
? 0
: isLong
? symbolPositions[symbolIDX].CountShortSupports()
: symbolPositions[symbolIDX].CountLongSupports();
bool hasOppositSupport = IsValidSize(oppositSupportCount);
if (hasOppositSupport)
{
//
XPosition opposit[];
if (isLong)
{
//
Copy(
symbolPositions[symbolIDX].shortSupports,
opposit //
);
}
else
{
//
Copy(
symbolPositions[symbolIDX].longSupports,
opposit //
);
}
//
string comment = "Close due Opposit ...";
//
int closeds = Close(
opposit,
comment //
);
if (IsValidSize(closeds))
{
//
string message = XEQMSupportToken + " Closed " + ToString(oppositCount) + " due Opposit Signal ...";
//
Alert(message);
}
//
Clean(opposit);
}
}
//
// Filter Signals Based On Max Allowed ...
if (maxAllowed > 0)
{
//
int usedCount =
!isValidSymbolIDX
? 0
: !perDirection
? symbolPositions[symbolIDX].Count()
: isLong
? symbolPositions[symbolIDX].CountLongs()
: symbolPositions[symbolIDX].CountShorts();
isSignalValid = !IsValidSize(usedCount)
? true
: usedCount < maxAllowed;
}
else
{
isSignalValid = true;
}
if (!isSignalValid)
{
continue;
}
//
// Only Accept Next Same Type when Previous in Profit ...
bool acceptNewOnlyWhenLastInProfit = AcceptNextDirectionalSignalsWhenFirstInProfit();
if (acceptNewOnlyWhenLastInProfit)
{
//
isSignalValid =
!hasSameTypeSignal
? true
: !isValidSymbolIDX
? true
: isLong
? symbolPositions[symbolIDX].longsProfit > 0
: symbolPositions[symbolIDX].shortsProfit > 0;
}
else
{
isSignalValid = true;
}
if (!isSignalValid)
{
continue;
}
//
// Multiply Signal Volume ...
// Create First Signal Opposit Protector ...
bool canIncreaseVolume = IncreaseNextSignalsVolume();
double volumeMultiplier = IncreaseNextSignalsVolumeMultiplier();
if (canIncreaseVolume)
{
//
double multiplier =
(!isValidSymbolIDX
? 0
: isLong
? symbolPositions[symbolIDX].CountLongs()
: symbolPositions[symbolIDX].CountShorts()) +
1;
//
multiplier = NormalizeDouble(multiplier * volumeMultiplier, 2);
iSignal.volume = iSignal.volume * multiplier;
}
//
// Handle Signal ...
if (isSignalValid)
{
//
AddRef(
iSignal,
eSignals //
);
}
//
}
//
result = ArraySize(eSignals);
//
// Cutom Signal Execution ...
if (IsValidSize(result))
{
//
// Execute Signals ...
HandleSignals(eSignals);
}
//
// Here we maker result to 0
// for prevent XBaseEA Calss for Executing Signal ...
result = 0;
Clean(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
{
//
bool result = false;
//
// Do all State Management here ...
//
// Check if there are open Positions
// and their doesn't have TP and SL and
// Youngest Age of Positions longest as enough
// Make State of Signalling to Force State for Recieving
// Signal and Clear their Tp and SL for allowing hedges ...
EQMHandleForceState();
//
DoHedge();
//
// Handle Close All Positions on Specific Time ...
DoEQMCloseOnSpecificTime();
//
// Do EQM Protection if Provided ...
DoEQMProtect();
//
// if Returns true, Signal Execution failed ...
return result;
}
//
// Signal Info ...
//
void OnSignalExecuted(const XSignal &signal) override
{
//
// Signal Info Manager ...
XSignal tSignal = signal;
bool isSupport = IsSupport(signal.comment);
if (!isSupport)
{
mTradeHandler.Update(tSignal);
}
//
mTradeHandler.Sync();
}
//
void OnSignalExecutionFailed(
const XSignal &signal,
const ENUM_X_SIGNAL_EXECUTION_RESULT reason //
) override
{
//
// Signal Info Manager ...
XSignal tSignal = signal;
mTradeHandler.Remove(tSignal);
mTradeHandler.Sync();
}
//
void OnPositionClosed(
const XPosition &position,
const string comment //
) override
{
//
// When a Position Closed Manually ...
// Signal Info Manager ...
XPosition tPosition = position;
bool isSupport = ExtractSupportedTicket(position.comment) > 0;
bool isEQMSupport = ExtractEQMSupportedTicket(position.comment) > 0;
tPosition.comment = comment;
if (!isSupport && !isEQMSupport)
{
mTradeHandler.Update(tPosition);
}
//
mTradeHandler.Sync();
}
//
void OnStopLossTriggered(const XDeal &deal) override
{
//
// When a Position's Stop Loss Triggered ...
// Signal Info Manager ...
XDeal tDeal = deal;
mTradeHandler.Update(tDeal);
mTradeHandler.Sync();
}
//
void OnTakeProfitTriggered(const XDeal &deal) override
{
//
// When a Position's Take Profit Triggered ...
// Signal Info Manager ...
XDeal tDeal = deal;
mTradeHandler.Update(tDeal);
mTradeHandler.Sync();
}
//
// Protected ...
protected:
//
// Tools ...
//
// Check Signalling Enable or not ...
bool IsEnable()
{
//
bool result = false;
//
// Check Signal Type is Enabled or not ...
bool isTypePassed = mAllowLong || mAllowShort;
//
// Check Signalling Time ...
MqlDateTime cTime;
bool isTimeRecieved = TimeCurrent(cTime);
//
int endHour = EndSignallingHoure();
int startHour = StartSignallingHoure();
//
bool isStartHourPassed =
startHour <= -1
? true
: cTime.hour >= startHour;
bool isEndHourPassed =
endHour <= -1
? true
: cTime.hour < endHour;
bool isTimePassed =
isTimeRecieved &&
isStartHourPassed &&
isEndHourPassed;
//
result =
isTypePassed &&
isTimePassed;
//
return result;
}
//
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;
}
//
// Custom Signal Execution ...
void HandleSignals(XSignal &signals[])
{
//
int signalsCount = ArraySize(signals);
if (!IsValidSize(signals))
{
return;
}
//
bool isMarginPassed = IsMarginPassed();
bool isDrawdownPassed = IsDrawdownPassed();
if (!isDrawdownPassed)
{
//
string message = "Desn't Have Good State For Execute Signals ...";
//
Alert(message);
//
mForce = true;
//
EQMHandleForceSignals(signals);
return;
}
else
{
mForce = false;
}
//
bool executeOnBreakouts = ExecuteSignalsOnBreakout();
if (executeOnBreakouts)
{
//
XSignal bSignals[];
int bSignalsCount = mTradeHandler.GetBreakoutsSignals(bSignals);
if (IsValidSize(bSignalsCount))
{
//
ENUM_X_SIGNAL_EXECUTION_RESULT states[];
int executedSignalsCount = ExecuteSignals(
signals,
states,
false //
);
}
}
else
{
//
ENUM_X_SIGNAL_EXECUTION_RESULT states[];
int executedSignalsCount = ExecuteSignals(
signals,
states,
false //
);
}
}
//
// Check Delay Between Two Signals ...
bool IsSignalDelayPassed(
XSignal &signal,
XSymbolPositions &positions //
)
{
//
bool result = false;
//
// Check Signal Validation ...
result = signal.IsValid();
if (!result)
{
return result;
}
//
// Check Delay Signals Allowed ...
int delay = DelayBetweenTwoSignal();
result = delay <= 0;
if (result)
{
return result;
}
//
XPosition youngest;
int youngestAge = positions.GetYoungest(
youngest,
signal.type //
);
result = !IsValidIndex(youngestAge);
if (result)
{
return result;
}
//
result = youngestAge >= delay;
//
return result;
}
//
bool IsMarginPassed()
{
//
double freeMargin = mTrader.mAccount.GetFreeMargin();
double minFreeMargingForHandleForce = MinFreeMargingForOpenTrades();
//
bool result = minFreeMargingForHandleForce <= 0
? true
: freeMargin >= minFreeMargingForHandleForce;
//
return result;
}
//
bool IsDrawdownPassed()
{
//
bool result = false;
//
double maxAllowedDrawdownPercent = MaxAllowedDrawdownPercent();
double drawdownPercent = GetDrawdownPercent();
//
result = maxAllowedDrawdownPercent <= 0
? true
: drawdownPercent <= maxAllowedDrawdownPercent;
//
return result;
}
//
// EQM Functions ...
//
// Force Close All Positions Due EQM Hedge ...
bool DoEQMForceClose()
{
//
bool result = false;
//
XPosition positions[];
int positionsCount = mTrader.GetPositions(positions);
result = IsValidSize(positionsCount);
if (!result)
{
return result;
}
//
double profit = SpecifiedCalculatePositionsProfit(
positions //
);
//
string comment = XEQMSupportToken + " Hedge ...";
int closed = Close(
positions,
comment //
);
//
result = IsValidSize(closed);
if (result)
{
//
mTradeHandler.Sync();
EQMClearAllForceStates();
}
//
// Handle Sleeping ...
int restingTime = RestingAfterHedge();
if (result && IsValidSize(restingTime))
{
Sleeping(restingTime);
}
//
return result;
}
//
// Do All Protecting Mechanism ...
void DoEQMProtect()
{
//
XSignal supports[];
int supportsCount = mTradeHandler.DoProtect(
supports,
mSetups //
);
//
if (IsValidSize(supportsCount))
{
EQMExecuteSignals(supports);
}
}
//
// 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);
}
}
//
// Handle any Invalid Signals ...
// this Signals passed From Request For Signal Function ...
// these need to add to Trade Handler ....
void EQMHandleInvalidSignal(
XSignal &signal, // Invalid Signal
int pushers, // Pushers
bool isValid, // IsValid Signal ...
X121SetupConditions &conditions[] // All Time Frames Conditions
)
{
//
int setupIDX = FindSetupIndex(signal.symbol);
if (!IsValidIndex(setupIDX))
{
return;
}
//
// bool isForce = mSetups[setupIDX].ForceState();
if (!mForce)
{
return;
}
//
// TODO: Implement this later ...
return;
//
XSignal signals[];
//
if (isValid)
{
//
bool canSupport =
//
EnableSupport() &&
SupportOnlyForces()
//
;
bool canGrid =
//
EnableGrid() &&
GridOnlyForces()
//
;
bool canRecover =
//
EnableRecovery() &&
RecoverOnlyForces()
//
;
//
AddRef(
signal,
signals //
);
//
// Add new Signal Info ...
mTradeHandler.Add(
signal,
pushers,
canGrid,
canRecover,
canSupport,
conditions[0],
conditions[1],
conditions[2],
conditions[3],
conditions[4] //
);
}
//
if (ArraySize(signals) > 0)
{
EQMExecuteSignals(signals);
}
}
//
// When Margin not passed and Happens an Invalid Signal
// HandleSignals Functions passed Signals to this Method ...
// these Signals Added to Trade Handler Before ...
void EQMHandleForceSignals(
XSignal &signals[] //
)
{
//
if (!mForce)
{
return;
}
//
int count = ArraySize(signals);
if (!IsValidSize(count))
{
return;
}
//
// TODO:
// Implement what we want ...
}
//
void EQMHandleForceState()
{
//
if (!mForce)
{
return;
}
//
// Exit From Force State ...
//
// One: Based On Positions Count ...
XPosition positions[];
int positionsCount = mTrader.GetPositions(positions);
if (!IsValidSize(positionsCount))
{
//
mForce = false;
return;
}
//
// Two: Based On Free Margin ...
bool isMarginPassed = IsMarginPassed();
bool isDrawdownPassed = IsDrawdownPassed();
if (isDrawdownPassed)
{
//
mForce = false;
return;
}
//
// Additional Works on Force States ...
//
double drawdown = GetDrawdownPercent();
double margin = mTrader.mAccount.GetMargin();
double callMargin = mTrader.mAccount.GetMarginCall();
double stopoutMargin = mTrader.mAccount.GetMarginStopOut();
//
double workingMargin = MathMax(callMargin, stopoutMargin) * 0.75;
//
// Checking Call Margin ...
// if (drawdown > workingMargin)
// {
// //
// int maxInDPIDX = FindMaxDrawdownIndex(
// positions //
// );
// if (IsValidIndex(maxInDPIDX))
// {
// //
// // We Close Max In Drawdown Position to Guard Account ...
// string comment = XEQMSupportToken + " Close Max Due Guard ...";
// bool isClosed = Close(
// positions[maxInDPIDX].ticket,
// comment //
// );
// if (isClosed)
// {
// //
// string message = XEQMSupportToken + " Close Position (" + ToString(positions[maxInDPIDX].ticket) + ") Due Guard Account ...";
// //
// Alert(message);
// }
// }
// }
}
//
// Execute Signals which Provided through
// EQM Protecting Senarios and must be Executed withouth
// any Policies ...
void EQMExecuteSignals(
XSignal &signals[] //
)
{
//
int signalsCount = ArraySize(signals);
if (!IsValidSize(signals))
{
return;
}
//
//
// Execute Supports ...
ENUM_X_SIGNAL_EXECUTION_RESULT states[];
int executed = ExecuteSignals(
signals,
states,
false // Ignore Policies ...
);
if (executed != signalsCount)
{
//
// TODO: Dow What We Want ...
// Print("Error On Executing Support Signal ...");
}
//
// Remove Supported Signals TP and SL and leave them for Handling using HEDGE Mechanism ...
if (IsValidSize(executed))
{
//
for (int i = 0; i < signalsCount; i++)
{
//
ENUM_X_SIGNAL_EXECUTION_RESULT iState = states[i];
if (iState != X_SIGNAL_EXECUTION_SUCCEED)
{
continue;
}
//
XSignal iSignal = signals[i];
if (!iSignal.IsValid() || !iSignal.IsExecuted())
{
continue;
}
//
ulong iParentTicket = ExtractParentTicket(iSignal.comment);
if (iParentTicket <= 0)
{
continue;
}
//
XPosition iParent;
bool hasParent = mTrader.GetPosition(
iParentTicket,
iParent //
);
if (!hasParent)
{
continue;
}
//
// Check Parent Has TP or SL ...
if (iParent.tp == 0 && iParent.sl == 0)
{
continue;
}
//
// Remove TP and SL of Supported Positions ...
string comment = "EQM Remove TPSL ...";
bool isModified = Modify(
iParentTicket,
0,
0,
comment //
);
if (isModified)
{
//
// TODO:
// do What we want ...
}
}
}
}
//
// Clear All Force States of Setups ...
void EQMClearAllForceStates()
{
//
int setupsCount = CountSetups();
if (!IsValidSize(setupsCount))
{
return;
}
//
for (int i = 0; i < setupsCount; i++)
{
mSetups[i].ForceState(false);
}
}
//
// Private ...
private:
//
// Props ...
//
// Signals ...
bool mAllowLong; // Allow Long
bool mAllowShort; // Allow Short
int mReuiredSignalVerifications; // Required Verifications for Validate Signals
bool mExecuteSignalsOnBreakout; // Execute Signals On Breakouts
bool mGetVerificationFromOtherTimeFrames; // Get Verifications from Other Time Frames
//
// Risk Management ...
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 mUseMaxAllowedPerDirection; // Use Max Allowed Positions Per Direction
bool mIncreaseNextSignalsVolume; // Increase Next Signals Volume
double mIncreaseNextSignalsVolumeMultiplier; // Increase Next Signals Volume Multiplier
bool mAcceptNextDirectionalSignalsWhenFirstInProfit; // Accept Same Symbol/Type Signal when Last in Profit
//
// Signalling ...
bool mCloseOnOpposit; // Close all Positions on Opposit
int mEndSignallingHoure; // End Signalling at Specific Time
int mCloseOnSpecificTime; // Close All Trades in Specific Time
int mStartSignallingHoure; // Start Signalling at Specific Time
//
// Force State:
// we can do many things in force state:
// - Prepare Force Hedging;
// - Receive Signals with minimal Verifications;
// - Increase Volume Size of in Profit Positions;
// - etc ...
bool mForce; // Determine in Force State or not
int mDelayBetweenTwoSignal; // Delay between two same signal
double mMinFreeMargingForOpenTrades; // Min Free Margin for Open Trades
double mMaxAllowedDrawdownPercent; // Max Allowed Drawdown for Open Trades
//
XSCX121SetupCycles *mSetups[]; // Number of Setups
XTradeHandler *mTradeHandler; // Handle all Event which related to Signals and Positions
//
// Apply Default Configurations ...
void DefaultConfigs()
{
//
// Signals ...
AllowLong(false);
AllowShort(false);
ReuiredSignalVerifications(0);
GetVerificationFromOtherTimeFrames(false);
//
// Risk Management ...
TPPoint(0);
SLPoint(0);
Volume(0.01);
IgnoreTP(false);
IgnoreSL(false);
MaxAllowedTrades(0);
UseMaxAllowedPerDirection(false);
IncreaseNextSignalsVolume(false);
IncreaseNextSignalsVolumeMultiplier(1);
AcceptNextDirectionalSignalsWhenFirstInProfit(false);
//
// Signalling ...
CloseOnOpposit(false);
EndSignallingHoure(-1);
CloseOnSpecificTime(-1);
StartSignallingHoure(-1);
//
// Trailling ...
AllowTrailStop(false);
NextTrailPoint(0);
FirstTrailPoint(0);
NextTrailDistance(0);
FirstTrailDistance(0);
//
// Supporting ...
AllowSupport(false);
MaxNumberOfSupports(0);
SupportOnlyForces(false);
SupportVolumeMultiplier(0.01);
MaxAllowedSupportVolume(0.08);
//
// Grid ...
GridDistance(0);
AllowGrid(false);
MaxNumberOfGrids(0);
GridOnlyForces(false);
GridVolumeMultiplier(0.01);
MaxAllowedGridVolume(0.08);
//
// Recovery ...
RecoveryDistance(0);
AllowRecovery(false);
MaxNumberOfRecoveries(0);
RecoverOnlyForces(false);
RecoveryVolumeMultiplier(0.01);
MaxAllowedRecoveryVolume(0.08);
//
MaxAllowedDrawdownPercent(5);
MinFreeMargingForOpenTrades(0);
//
SaveResults(false);
SaveSignalsOnly(true);
}
//
// Tools ...
int CountSetups()
{
return ArraySize(mSetups);
}
//
// Find Setup Index by Symbol and Period ...
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;
}
//
// Find Setup Index by Providing Symbol ...
int FindSetupIndex(
string symbol //
)
{
//
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)
{
//
result = i;
break;
}
}
//
return result;
}
//
};
//