5605 lines
121 KiB
Plaintext
5605 lines
121 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 ...
|
|
);
|
|
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 =
|
|
//
|
|
(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" +
|
|
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 ...
|
|
|
|
//
|
|
// 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();
|
|
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].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);
|
|
}
|
|
|
|
//
|
|
// 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 = cSignal;
|
|
|
|
//
|
|
AddRef(
|
|
sConditions,
|
|
otherConditions //
|
|
);
|
|
AddRef(
|
|
mConditions,
|
|
otherConditions //
|
|
);
|
|
}
|
|
|
|
//
|
|
if (sHasSignal)
|
|
{
|
|
//
|
|
signal = sSignal;
|
|
|
|
//
|
|
AddRef(
|
|
cConditions,
|
|
otherConditions //
|
|
);
|
|
AddRef(
|
|
mConditions,
|
|
otherConditions //
|
|
);
|
|
}
|
|
|
|
//
|
|
if (mHasSignal)
|
|
{
|
|
//
|
|
signal = mSignal;
|
|
|
|
//
|
|
AddRef(
|
|
sConditions,
|
|
otherConditions //
|
|
);
|
|
AddRef(
|
|
lConditions,
|
|
otherConditions //
|
|
);
|
|
}
|
|
|
|
//
|
|
if (lHasSignal)
|
|
{
|
|
//
|
|
signal = lSignal;
|
|
|
|
//
|
|
AddRef(
|
|
mConditions,
|
|
otherConditions //
|
|
);
|
|
AddRef(
|
|
hConditions,
|
|
otherConditions //
|
|
);
|
|
}
|
|
|
|
//
|
|
if (hHasSignal)
|
|
{
|
|
//
|
|
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();
|
|
|
|
//
|
|
for (int i = 0; i < signalsCount; i++)
|
|
{
|
|
//
|
|
XSignal iSignal = tmpSignals[i];
|
|
|
|
//
|
|
bool isSignalValid = false;
|
|
|
|
//
|
|
isSignalValid = IsSignalDelayPassed(iSignal);
|
|
if (!isSignalValid)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
// Handle Close All Positions when Opposit Signal Recieved ...
|
|
if (mCloseOnOpposit)
|
|
{
|
|
//
|
|
// Select Signal Opposit Positions ...
|
|
ENUM_X_POSITION_TYPES 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);
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Filter Signals Based On Max Allowed ...
|
|
if (maxAllowed > 0)
|
|
{
|
|
//
|
|
// Here we Get Opposite Signals of Same Symbol Valid ...
|
|
ENUM_X_POSITION_TYPES iType =
|
|
perDirection
|
|
? ToPositionType(iSignal.type)
|
|
: X_POSITION_TYPE_ALL;
|
|
XPosition iSymbolsPositions[];
|
|
int iSymbolsPositionsCount = mTrader.GetPositions(
|
|
iSymbolsPositions,
|
|
iSignal.symbol,
|
|
NULL, // Provider
|
|
NULL, // Period
|
|
iType, // Type
|
|
true //
|
|
);
|
|
|
|
//
|
|
int iSupportsCount = 0;
|
|
if (IsValidSize(iSymbolsPositionsCount))
|
|
{
|
|
//
|
|
// Filter Support Positions ...
|
|
XPosition iSupports[];
|
|
iSupportsCount = ExtractSupports(
|
|
iSymbolsPositions,
|
|
iSupports //
|
|
);
|
|
}
|
|
|
|
//
|
|
isSignalValid =
|
|
iSupportsCount <= 0
|
|
? iSymbolsPositionsCount < maxAllowed
|
|
: iSymbolsPositionsCount - iSupportsCount < maxAllowed;
|
|
if (!isSignalValid)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
isSignalValid = true;
|
|
}
|
|
|
|
//
|
|
// Only Accept Next Same Type when Previous in Profit ...
|
|
bool isSameTypeExists = false;
|
|
if (isSignalValid)
|
|
{
|
|
//
|
|
ENUM_X_POSITION_TYPES iType =
|
|
ToPositionType(iSignal.type);
|
|
XPosition iSymbolsPositions[];
|
|
int iSymbolsPositionsCount = mTrader.GetPositions(
|
|
iSymbolsPositions,
|
|
iSignal.symbol,
|
|
NULL, // Provider
|
|
NULL, // Period
|
|
iType, // Type
|
|
true //
|
|
);
|
|
|
|
//
|
|
int iSupportsCount = 0;
|
|
if (IsValidSize(iSymbolsPositionsCount))
|
|
{
|
|
//
|
|
// Filter Support Positions ...
|
|
XPosition iSupports[];
|
|
iSupportsCount = ExtractSupports(
|
|
iSymbolsPositions,
|
|
iSupports //
|
|
);
|
|
|
|
//
|
|
// Filter Support Positions ...
|
|
if (IsValidSize(iSupportsCount))
|
|
{
|
|
//
|
|
XPosition tmpPositions[];
|
|
Copy(
|
|
iSymbolsPositions,
|
|
tmpPositions //
|
|
);
|
|
|
|
//
|
|
Clean(iSymbolsPositions);
|
|
|
|
//
|
|
for (int i = 0; i < iSymbolsPositionsCount; i++)
|
|
{
|
|
//
|
|
XPosition iPosition = tmpPositions[i];
|
|
|
|
//
|
|
bool isSupport = IsSupport(iPosition.comment);
|
|
if (isSupport)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
//
|
|
AddRef(
|
|
iPosition,
|
|
iSymbolsPositions //
|
|
);
|
|
}
|
|
|
|
//
|
|
iSymbolsPositionsCount = ArraySize(iSymbolsPositions);
|
|
}
|
|
}
|
|
|
|
//
|
|
bool acceptNewOnlyWhenLastInProfit = AcceptNextDirectionalSignalsWhenFirstInProfit();
|
|
isSameTypeExists = IsValidSize(iSymbolsPositionsCount);
|
|
if (isSameTypeExists && acceptNewOnlyWhenLastInProfit)
|
|
{
|
|
//
|
|
XPosition youngest;
|
|
int youngestAge = GetYoungest(
|
|
youngest,
|
|
iSymbolsPositions //
|
|
);
|
|
|
|
//
|
|
isSignalValid = youngest.profit > 0.1;
|
|
}
|
|
|
|
//
|
|
if (!isSignalValid)
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Multiply Signal Volume ...
|
|
if (isSignalValid)
|
|
{
|
|
//
|
|
XPosition iSymbolsPositions[];
|
|
int iSymbolsPositionsCount = mTrader.GetPositions(
|
|
iSymbolsPositions,
|
|
iSignal.symbol,
|
|
NULL, // Provider
|
|
NULL, // Period
|
|
NULL, // Type
|
|
true //
|
|
);
|
|
|
|
//
|
|
int iSupportsCount = 0;
|
|
if (IsValidSize(iSymbolsPositionsCount))
|
|
{
|
|
//
|
|
// Filter Support Positions ...
|
|
XPosition iSupports[];
|
|
iSupportsCount = ExtractSupports(
|
|
iSymbolsPositions,
|
|
iSupports //
|
|
);
|
|
}
|
|
|
|
//
|
|
int multiplier =
|
|
iSupportsCount <= 0
|
|
? iSymbolsPositionsCount
|
|
: iSymbolsPositionsCount - iSupportsCount;
|
|
if (multiplier <= 0)
|
|
{
|
|
multiplier = 1;
|
|
}
|
|
else
|
|
{
|
|
multiplier++;
|
|
}
|
|
|
|
//
|
|
bool canIncreaseVolume = IncreaseNextSignalsVolume();
|
|
if (canIncreaseVolume)
|
|
{
|
|
//
|
|
double volumeMultiplier = IncreaseNextSignalsVolumeMultiplier();
|
|
iSignal.volume = iSignal.volume * (multiplier * volumeMultiplier);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Handle Signal ...
|
|
if (isSignalValid)
|
|
{
|
|
//
|
|
AddRef(
|
|
iSignal,
|
|
eSignals //
|
|
);
|
|
}
|
|
}
|
|
|
|
//
|
|
result = ArraySize(eSignals);
|
|
|
|
//
|
|
// Cutom Signal Execution ...
|
|
if (IsValidSize(result))
|
|
{
|
|
//
|
|
Copy(
|
|
eSignals,
|
|
signals //
|
|
);
|
|
|
|
//
|
|
Clean(eSignals);
|
|
|
|
//
|
|
HandleSignals(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 //
|
|
)
|
|
{
|
|
//
|
|
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;
|
|
}
|
|
|
|
//
|
|
// Retrieve Positions ...
|
|
// Based On Provider and Symbol and TimeFrame ...
|
|
XPosition positions[];
|
|
int positionsCount = mTrader.GetPositions(
|
|
positions,
|
|
signal.symbol,
|
|
NULL, // signal.provider,
|
|
NULL, // signal.period,
|
|
ToPositionType(signal.type),
|
|
true // Filter By Magic ...
|
|
);
|
|
result = !IsValidSize(positionsCount);
|
|
if (result)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
//
|
|
XPosition youngest;
|
|
int youngestAge = GetYoungest(
|
|
youngest,
|
|
positions //
|
|
);
|
|
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 ...
|
|
// TODO: Complete this ...
|
|
}
|
|
|
|
//
|
|
// 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;
|
|
}
|
|
|
|
//
|
|
};
|
|
|
|
//
|