4349 lines
94 KiB
Plaintext
4349 lines
94 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 ...
|
|
|
|
//
|
|
// 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_TYPE 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
|
|
|
|
//
|
|
int bullishSigns; // Bullish Signs On Signal Time
|
|
int bearishSigns; // Bearish Signs On Signal Time
|
|
|
|
//
|
|
double bullishScore; // Bullish Score On Signal Time
|
|
double bearishScore; // Bearish Score On Signal Time
|
|
|
|
//
|
|
double volumeOSC; // Volume Weight On Signal 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;
|
|
volumeOSC = 0;
|
|
commission = 0;
|
|
bullishSigns = 0;
|
|
bearishSigns = 0;
|
|
bullishScore = 0;
|
|
bearishScore = 0;
|
|
|
|
//
|
|
cConditions.Clean();
|
|
sConditions.Clean();
|
|
mConditions.Clean();
|
|
lConditions.Clean();
|
|
hConditions.Clean();
|
|
|
|
//
|
|
ResetGrid();
|
|
ResetRecovery();
|
|
}
|
|
|
|
//
|
|
bool Fill(
|
|
const XSignal &_signal,
|
|
int _pushers,
|
|
double _volumeOSC,
|
|
int _bullishSigns,
|
|
int _bearishSigns,
|
|
double _bullishScore,
|
|
double _bearishScore,
|
|
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;
|
|
|
|
//
|
|
volumeOSC = _volumeOSC;
|
|
|
|
//
|
|
bullishSigns = _bullishSigns;
|
|
bearishSigns = _bearishSigns;
|
|
|
|
//
|
|
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(type) + "\\" +
|
|
(profit >= 0
|
|
? "Profit"
|
|
: "Loss") +
|
|
"\\" +
|
|
provider + "_" +
|
|
ToString(ticket) + "_" +
|
|
ToString(period) + "_" +
|
|
ToFormatString(time)
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
string ToString()
|
|
{
|
|
//
|
|
string result = NULL;
|
|
|
|
//
|
|
string cConditionsStr = cConditions
|
|
.GenerateSummary(
|
|
false, // Only Commons ...
|
|
true, // Only Conditions ...
|
|
false, // Include Score ...
|
|
false // Include False Conditions ...
|
|
);
|
|
string sConditionsStr = sConditions
|
|
.GenerateSummary(
|
|
false, // Only Commons ...
|
|
true, // Only Conditions ...
|
|
false, // Include Score ...
|
|
false // Include False Conditions ...
|
|
);
|
|
string mConditionsStr = mConditions
|
|
.GenerateSummary(
|
|
false, // Only Commons ...
|
|
true, // Only Conditions ...
|
|
false, // Include Score ...
|
|
false // Include False Conditions ...
|
|
);
|
|
string lConditionsStr = lConditions
|
|
.GenerateSummary(
|
|
false, // Only Commons ...
|
|
true, // Only Conditions ...
|
|
false, // Include Score ...
|
|
false // Include False Conditions ...
|
|
);
|
|
string hConditionsStr = hConditions
|
|
.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("Entry", entry) +
|
|
ToString("Provider", provider) +
|
|
ToString("Type", ToString(type)) +
|
|
ToString("Time", time) +
|
|
ToString("Pushers", pushers) +
|
|
"-------------" + "\n" +
|
|
ToString("VolumeOSC", volumeOSC) +
|
|
ToString("BullishSigns", bullishSigns) +
|
|
ToString("BearishSigns", bearishSigns) +
|
|
ToString("BullishScore", bullishScore) +
|
|
ToString("BearishScore", bearishScore) +
|
|
"-------------" + "\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" +
|
|
cConditionsStr + "\n" +
|
|
"-------------" + "\n" +
|
|
"SHORT [" + ToString(sConditions.period) + "]" + "\n" +
|
|
"-------------" + "\n" +
|
|
sConditionsStr + "\n" +
|
|
"-------------" + "\n" +
|
|
"MEDIUM [" + ToString(mConditions.period) + "]" + "\n" +
|
|
"-------------" + "\n" +
|
|
mConditionsStr + "\n" +
|
|
"-------------" + "\n" +
|
|
"LONG [" + ToString(lConditions.period) + "]" + "\n" +
|
|
"-------------" + "\n" +
|
|
lConditionsStr + "\n" +
|
|
"-------------" + "\n" +
|
|
"HIND [" + ToString(hConditions.period) + "]" + "\n" +
|
|
"-------------" + "\n" +
|
|
hConditionsStr + "\n" +
|
|
//
|
|
""
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// These are Some Helpers for Trading Controls and do not relate to Main
|
|
// purpose of Trade Handler ...
|
|
|
|
//
|
|
// Grid System Calculations ...
|
|
|
|
//
|
|
double gEntry; // Represents Next Grid Signal's Entry
|
|
double gVolume; // Represent Next Grid Signal's Volume
|
|
|
|
//
|
|
void ResetGrid()
|
|
{
|
|
gEntry = 0;
|
|
gVolume = 0;
|
|
}
|
|
|
|
//
|
|
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 //
|
|
);
|
|
}
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Recovery Zone System ...
|
|
|
|
//
|
|
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
|
|
|
|
//
|
|
void ResetRecovery()
|
|
{
|
|
//
|
|
rVolume = 0;
|
|
rLongEntry = 0;
|
|
rZoneUpper = 0;
|
|
rZoneLower = 0;
|
|
rShortEntry = 0;
|
|
}
|
|
|
|
//
|
|
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;
|
|
|
|
//
|
|
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,
|
|
rSL, // SL ...
|
|
rTP // TP ...
|
|
);
|
|
if (result)
|
|
{
|
|
//
|
|
// set Support Token ...
|
|
string comment = GenerateSupportTag(ticket);
|
|
signal.comment = comment;
|
|
|
|
//
|
|
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;
|
|
}
|
|
|
|
//
|
|
// 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 + "\\" + 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;
|
|
}
|
|
};
|
|
|
|
//
|
|
// 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;
|
|
}
|
|
|
|
//
|
|
// Supporting ...
|
|
|
|
//
|
|
bool AllowSupport()
|
|
{
|
|
return mAllowSupport;
|
|
}
|
|
|
|
//
|
|
void AllowSupport(bool value)
|
|
{
|
|
mAllowSupport = 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() &&
|
|
MaxNumberOfSupports() > 0 &&
|
|
SupportVolumeMultiplier() > 0
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Trailling Stop ...
|
|
|
|
//
|
|
bool AllowTrailStop()
|
|
{
|
|
return mAllowTrailStop;
|
|
}
|
|
|
|
//
|
|
void AllowTrailStop(bool value)
|
|
{
|
|
mAllowTrailStop = 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;
|
|
}
|
|
|
|
//
|
|
// Grid System ...
|
|
|
|
//
|
|
bool AllowGrid()
|
|
{
|
|
return mAllowGrid;
|
|
}
|
|
|
|
//
|
|
void AllowGrid(bool value)
|
|
{
|
|
mAllowGrid = 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 = 0;
|
|
}
|
|
|
|
//
|
|
mGridVolumeMultiplier = value;
|
|
}
|
|
|
|
//
|
|
// Check Grid Properties to Validate it's Enable or not ...
|
|
bool EnableGrid()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
//
|
|
AllowGrid() &&
|
|
GridDistance() > 0 &&
|
|
GridVolumeMultiplier() > 0
|
|
//
|
|
;
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// Recovery System ...
|
|
|
|
//
|
|
bool AllowRecovery()
|
|
{
|
|
return mAllowRecovery;
|
|
}
|
|
|
|
//
|
|
void AllowRecovery(bool value)
|
|
{
|
|
mAllowRecovery = 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 = 0;
|
|
}
|
|
|
|
//
|
|
mRecoveryVolumeMultiplier = value;
|
|
}
|
|
|
|
//
|
|
// Check Recovery Properties to Validate it's Enable or not ...
|
|
bool EnableRecovery()
|
|
{
|
|
//
|
|
bool result = false;
|
|
|
|
//
|
|
result =
|
|
//
|
|
AllowRecovery() &&
|
|
RecoveryDistance() > 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,
|
|
double volumeOSC,
|
|
int bullishSigns,
|
|
int bearishSigns,
|
|
double bullishScore,
|
|
double bearishScore,
|
|
X121SetupConditions &cConditions,
|
|
X121SetupConditions &sConditions,
|
|
X121SetupConditions &mConditions,
|
|
X121SetupConditions &lConditions,
|
|
X121SetupConditions &hConditions //
|
|
)
|
|
{
|
|
//
|
|
XTradeInfo signalInfo;
|
|
bool isFilled = signalInfo.Fill(
|
|
signal,
|
|
pushers,
|
|
volumeOSC,
|
|
bullishSigns,
|
|
bearishSigns,
|
|
bullishScore,
|
|
bearishScore,
|
|
cConditions,
|
|
sConditions,
|
|
mConditions,
|
|
lConditions,
|
|
hConditions //
|
|
);
|
|
if (!isFilled)
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
AddRef(
|
|
signalInfo,
|
|
data //
|
|
);
|
|
}
|
|
|
|
//
|
|
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].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 ...
|
|
data[infoIDX].PrepareNextGrid(
|
|
GridDistance(),
|
|
GridVolumeMultiplier() //
|
|
);
|
|
}
|
|
|
|
//
|
|
// Check if Recovery System Enable or Not ...
|
|
if (EnableRecovery())
|
|
{
|
|
//
|
|
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);
|
|
}
|
|
|
|
//
|
|
// Protection Handlers ...
|
|
|
|
//
|
|
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[];
|
|
int positionsCount = mTrader.GetInProfitPositions(positions);
|
|
if (!IsValidSize(positionsCount))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < positionsCount; i++)
|
|
{
|
|
//
|
|
XPosition iPosition = positions[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 =
|
|
iPosition.sl > 0 &&
|
|
isLong
|
|
? iPosition.sl < iPosition.entry
|
|
? iPosition.entry
|
|
: iPosition.sl
|
|
: iPosition.sl > iPosition.entry
|
|
? iPosition.entry
|
|
: iPosition.sl;
|
|
|
|
//
|
|
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;
|
|
}
|
|
|
|
//
|
|
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[], // Number of Setups
|
|
double supportDistance = 50,
|
|
double volumeMultiplier = 2 //
|
|
)
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
// TODO: Complete this Later ...
|
|
return result;
|
|
|
|
//
|
|
Clean(signals);
|
|
|
|
//
|
|
if (!AllowSupport())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
Sync();
|
|
|
|
//
|
|
// 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;
|
|
}
|
|
|
|
//
|
|
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;
|
|
}
|
|
|
|
//
|
|
// Now We Have all required Data to Decide What Supports for
|
|
// Specified In DrawDown Position ...
|
|
|
|
//
|
|
XSignal tmpSignal;
|
|
tmpSignal.Clean();
|
|
|
|
//
|
|
double longEntry = GetEntry(
|
|
iPosition.symbol,
|
|
POSITION_TYPE_BUY //
|
|
);
|
|
double shortEntry = GetEntry(
|
|
iPosition.symbol,
|
|
POSITION_TYPE_SELL //
|
|
);
|
|
double mVolume = iPosition.volume * 2;
|
|
double mSL = 0;
|
|
double mTP = 0;
|
|
|
|
//
|
|
bool isLong = IsLong(iPosition.type);
|
|
|
|
//
|
|
// Here we Can Start a Recovery Zone ...
|
|
if (data[index].rLongEntry <= 0 &&
|
|
data[index].rShortEntry <= 0 &&
|
|
data[index].rVolume <= 0)
|
|
{
|
|
//
|
|
data[index].PrepareNextRecovery(
|
|
supportDistance,
|
|
volumeMultiplier,
|
|
iPosition.type //
|
|
);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
bool hasRecovery = data[index].HasRecovery(
|
|
tmpSignal,
|
|
supportDistance,
|
|
volumeMultiplier //
|
|
);
|
|
if (hasRecovery)
|
|
{
|
|
//
|
|
// tmpSignal.sl = 0;
|
|
// tmpSignal.tp = 0;
|
|
string comment = GenerateEQMSupportTag(iPosition.ticket);
|
|
tmpSignal.comment = comment;
|
|
|
|
//
|
|
AddRef(
|
|
tmpSignal,
|
|
signals //
|
|
);
|
|
}
|
|
else if (priceDiffPoints >= supportDistance)
|
|
{
|
|
//
|
|
// Reset
|
|
if (longEntry > data[index].rZoneUpper || shortEntry < data[index].rZoneLower)
|
|
{
|
|
//
|
|
// data[index].ResetRecovery();
|
|
|
|
//
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
}
|
|
|
|
//
|
|
result = ArraySize(signals);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int RequestForGrid(XSignal &signals[])
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
Clean(signals);
|
|
|
|
//
|
|
if (!EnableGrid())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int count = Count();
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XSignal iSignal;
|
|
bool hasGrid = data[i].HasGrid(
|
|
iSignal,
|
|
GridDistance(),
|
|
GridVolumeMultiplier() //
|
|
);
|
|
|
|
//
|
|
if (hasGrid)
|
|
{
|
|
//
|
|
AddRef(
|
|
iSignal,
|
|
signals //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
result = ArraySize(signals);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int RequestForRecovery(XSignal &signals[])
|
|
{
|
|
//
|
|
int result = 0;
|
|
|
|
//
|
|
Clean(signals);
|
|
|
|
//
|
|
if (!EnableRecovery())
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
int count = Count();
|
|
if (!IsValidSize(count))
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
//
|
|
XSignal iSignal;
|
|
bool hasRecovery = data[i].HasRecovery(
|
|
iSignal,
|
|
RecoveryDistance(),
|
|
RecoveryVolumeMultiplier() //
|
|
);
|
|
|
|
//
|
|
if (hasRecovery)
|
|
{
|
|
//
|
|
AddRef(
|
|
iSignal,
|
|
signals //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
result = ArraySize(signals);
|
|
|
|
//
|
|
return result;
|
|
}
|
|
|
|
//
|
|
// 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 //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Protected ...
|
|
protected:
|
|
//
|
|
// Props ...
|
|
XSCTrade *mTrader;
|
|
XTradeInfo data[];
|
|
XTradeInfoCollector *collector;
|
|
|
|
//
|
|
bool mSave; // Save Results ...
|
|
|
|
//
|
|
// Tools ...
|
|
|
|
//
|
|
void Finish(int index)
|
|
{
|
|
//
|
|
XTradeInfo info = data[index];
|
|
if (!info.IsValid())
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
ArrayRemove(
|
|
data,
|
|
index,
|
|
1 //
|
|
);
|
|
|
|
//
|
|
if (GetSave())
|
|
{
|
|
collector.Save(info);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Supports ...
|
|
bool mAllowSupport; // Allow Support Signals
|
|
|
|
//
|
|
// Stop Trailling ...
|
|
bool mAllowTrailStop; // Enable Trailling Stop Losses
|
|
double mFirstTrailDistance; // Start Trailling Distance
|
|
double mFirstTrailPoint; // First Stop Trail
|
|
double mNextTrailDistance; // Next Trailling Distance
|
|
double mNextTrailPoint; // Next Trailling Step
|
|
|
|
//
|
|
// Grid ...
|
|
bool mAllowGrid; // Use Grid System to Recovery Positions
|
|
double mGridDistance; // Grid System Distance
|
|
double mGridVolumeMultiplier; // Grid System Volume Multiplier
|
|
|
|
//
|
|
// Recovery ...
|
|
bool mAllowRecovery; // Use Recovery System to Recovery Positions
|
|
double mRecoveryDistance; // Recovery System Distance
|
|
double mRecoveryVolumeMultiplier; // Recovery System Volume Multiplier
|
|
|
|
//
|
|
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 ...
|
|
|
|
//
|
|
// 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 ReuiredSignalVerifications()
|
|
{
|
|
return mReuiredSignalVerifications;
|
|
}
|
|
|
|
//
|
|
void ReuiredSignalVerifications(int value)
|
|
{
|
|
//
|
|
if (value < 1)
|
|
{
|
|
value = 1;
|
|
}
|
|
|
|
//
|
|
mReuiredSignalVerifications = value;
|
|
}
|
|
|
|
//
|
|
bool GetVerificationFromOtherTimeFrames()
|
|
{
|
|
return mGetVerificationFromOtherTimeFrames;
|
|
}
|
|
|
|
//
|
|
void GetVerificationFromOtherTimeFrames(bool value)
|
|
{
|
|
mGetVerificationFromOtherTimeFrames = 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 IgnoreTP()
|
|
{
|
|
return mIgnoreTP;
|
|
}
|
|
|
|
//
|
|
void IgnoreTP(bool value)
|
|
{
|
|
mIgnoreTP = value;
|
|
}
|
|
|
|
//
|
|
bool IgnoreSL()
|
|
{
|
|
return mIgnoreSL;
|
|
}
|
|
|
|
//
|
|
void IgnoreSL(bool value)
|
|
{
|
|
mIgnoreSL = 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);
|
|
}
|
|
|
|
//
|
|
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);
|
|
}
|
|
|
|
//
|
|
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);
|
|
}
|
|
|
|
//
|
|
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);
|
|
}
|
|
|
|
//
|
|
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);
|
|
}
|
|
|
|
//
|
|
// 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;
|
|
}
|
|
|
|
//
|
|
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,
|
|
mUseSupport,
|
|
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 ...
|
|
|
|
//
|
|
// Check if there is a Signal or Not ...
|
|
bool hasSignal = cHasSignal || sHasSignal || mHasSignal || lHasSignal || hHasSignal;
|
|
if (hasSignal)
|
|
{
|
|
//
|
|
// Handle Creating a new Signal Info ...
|
|
XSignal signal;
|
|
X121SetupConditions otherConditions[];
|
|
if (hHasSignal)
|
|
{
|
|
//
|
|
signal = hSignal;
|
|
|
|
//
|
|
AddRef(
|
|
cConditions,
|
|
otherConditions //
|
|
);
|
|
AddRef(
|
|
sConditions,
|
|
otherConditions //
|
|
);
|
|
}
|
|
else if (lHasSignal)
|
|
{
|
|
//
|
|
signal = lSignal;
|
|
|
|
//
|
|
AddRef(
|
|
cConditions,
|
|
otherConditions //
|
|
);
|
|
AddRef(
|
|
sConditions,
|
|
otherConditions //
|
|
);
|
|
AddRef(
|
|
mConditions,
|
|
otherConditions //
|
|
);
|
|
}
|
|
else if (mHasSignal)
|
|
{
|
|
//
|
|
signal = mSignal;
|
|
|
|
//
|
|
AddRef(
|
|
cConditions,
|
|
otherConditions //
|
|
);
|
|
AddRef(
|
|
sConditions,
|
|
otherConditions //
|
|
);
|
|
}
|
|
else if (sHasSignal)
|
|
{
|
|
//
|
|
signal = sSignal;
|
|
|
|
//
|
|
AddRef(
|
|
cConditions,
|
|
otherConditions //
|
|
);
|
|
AddRef(
|
|
mConditions,
|
|
otherConditions //
|
|
);
|
|
AddRef(
|
|
lConditions,
|
|
otherConditions //
|
|
);
|
|
AddRef(
|
|
hConditions,
|
|
otherConditions //
|
|
);
|
|
}
|
|
else if (cHasSignal)
|
|
{
|
|
//
|
|
signal = cSignal;
|
|
|
|
//
|
|
AddRef(
|
|
sConditions,
|
|
otherConditions //
|
|
);
|
|
AddRef(
|
|
mConditions,
|
|
otherConditions //
|
|
);
|
|
AddRef(
|
|
lConditions,
|
|
otherConditions //
|
|
);
|
|
AddRef(
|
|
hConditions,
|
|
otherConditions //
|
|
);
|
|
}
|
|
|
|
//
|
|
int pushers = cPusher + sPusher + mPusher + lPusher + hPusher;
|
|
|
|
//
|
|
bool isLong = IsLong(signal.type);
|
|
|
|
//
|
|
// Collecting Bullish/Bearish Signs ...
|
|
if (isLong)
|
|
{
|
|
mBullishSigns += pushers;
|
|
}
|
|
else
|
|
{
|
|
mBearishSigns += pushers;
|
|
}
|
|
|
|
//
|
|
// 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))
|
|
//
|
|
;
|
|
|
|
//
|
|
if (!isValid)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Add Signal to Execution Result ...
|
|
AddRef(
|
|
signal,
|
|
signals //
|
|
);
|
|
|
|
//
|
|
// Add new Signal Info ...
|
|
mTradeHandler.Add(
|
|
signal,
|
|
pushers,
|
|
mVolumeOSC,
|
|
mBullishSigns,
|
|
mBearishSigns,
|
|
mBullishScore,
|
|
mBearishScore,
|
|
cConditions,
|
|
sConditions,
|
|
mConditions,
|
|
lConditions,
|
|
hConditions //
|
|
);
|
|
}
|
|
}
|
|
|
|
// //
|
|
// // 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 = GetOppositPositionType(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 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 = ExtractSupportedTicket(signal.comment) > 0;
|
|
bool isEQMSupport = ExtractEQMSupportedTicket(signal.comment) > 0;
|
|
if (!isSupport && !isEQMSupport)
|
|
{
|
|
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 ...
|
|
|
|
//
|
|
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 ...
|
|
|
|
//
|
|
// Signals ...
|
|
bool mAllowLong; // Allow Long
|
|
bool mAllowShort; // Allow Short
|
|
int mReuiredSignalVerifications; // Required Verifications for Validate Signals
|
|
bool mGetVerificationFromOtherTimeFrames; // Get Verifications from Other Time Frames
|
|
|
|
//
|
|
// Risk Management ...
|
|
double mVolume; // Volume
|
|
double mTPPoint; // TP Point
|
|
double mSLPoint; // SL Point
|
|
int mMaxAllowedTrades; // Max Alloed Positions
|
|
bool mIgnoreTP; // Ignore Calculated TP
|
|
bool mIgnoreSL; // Ignore Calculated SL
|
|
|
|
//
|
|
// 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
|
|
|
|
//
|
|
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);
|
|
|
|
//
|
|
// 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);
|
|
SupportVolumeMultiplier(0.01);
|
|
MaxAllowedSupportVolume(0.08);
|
|
|
|
//
|
|
// Grid ...
|
|
AllowGrid(false);
|
|
GridDistance(0);
|
|
MaxNumberOfGrids(0);
|
|
GridVolumeMultiplier(0.01);
|
|
MaxAllowedGridVolume(0.08);
|
|
|
|
//
|
|
// Recovery ...
|
|
AllowRecovery(false);
|
|
MaxNumberOfRecoveries(0);
|
|
RecoveryDistance(0);
|
|
RecoveryVolumeMultiplier(0.01);
|
|
MaxAllowedRecoveryVolume(0.08);
|
|
|
|
//
|
|
SaveResults(false);
|
|
}
|
|
|
|
//
|
|
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;
|
|
}
|
|
|
|
//
|
|
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;
|
|
}
|
|
|
|
//
|
|
// EQM Functions ...
|
|
|
|
//
|
|
bool EnableTrailling()
|
|
{
|
|
return mTradeHandler.EnableTrailling();
|
|
}
|
|
|
|
//
|
|
bool EnableGrid()
|
|
{
|
|
return mTradeHandler.EnableGrid();
|
|
}
|
|
|
|
//
|
|
bool EnableRecovery()
|
|
{
|
|
return mTradeHandler.EnableRecovery();
|
|
}
|
|
|
|
//
|
|
bool EnableProtection()
|
|
{
|
|
return EnableGrid() || EnableRecovery() || EnableTrailling() || AllowSupport();
|
|
}
|
|
|
|
//
|
|
// 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 DoEQMProtect()
|
|
{
|
|
//
|
|
if (!EnableProtection())
|
|
{
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Trailling ...
|
|
if (EnableTrailling())
|
|
{
|
|
//
|
|
int trailsCount = mTradeHandler.HandleTrailling();
|
|
if (IsValidSize(trailsCount))
|
|
{
|
|
//
|
|
string message = XEQMSupportToken + " Successfully Trail Stop for: " + ToString(trailsCount) + " Position(s) ...";
|
|
|
|
//
|
|
// Alert(message);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Support ...
|
|
if (AllowSupport())
|
|
{
|
|
//
|
|
XSignal supports[];
|
|
int supportsCount = mTradeHandler.RequestForSupport(
|
|
supports,
|
|
mSetups //
|
|
);
|
|
if (IsValidSize(supportsCount))
|
|
{
|
|
EQMExecuteSignals(supports);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Grid ...
|
|
if (EnableGrid())
|
|
{
|
|
//
|
|
XSignal signals[];
|
|
int signalsCount = mTradeHandler
|
|
.RequestForGrid(signals);
|
|
if (IsValidSize(signalsCount))
|
|
{
|
|
EQMExecuteSignals(signals);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Recovery ...
|
|
if (EnableRecovery())
|
|
{
|
|
//
|
|
XSignal signals[];
|
|
int signalsCount = mTradeHandler
|
|
.RequestForRecovery(signals);
|
|
if (IsValidSize(signalsCount))
|
|
{
|
|
EQMExecuteSignals(signals);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
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 ...");
|
|
}
|
|
}
|
|
|
|
//
|
|
// 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);
|
|
}
|
|
}
|
|
};
|
|
|
|
//
|