Files
MQL5Data/Libraries/x-saherelm.x-trade.lib.mq5
T
2026-01-03 17:28:07 +03:30

6613 lines
128 KiB
Plaintext

///////////////////////////////////////////////////////
//
// SaherElm IT Center MQL5 Seriallize Library
// ---------------------------------------
// Name: XTradeLib
// Description: All models related to Trade ...
//
//
// 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 "../Libraries/x-saherelm.common.lib.mq5"
#include "../Libraries/x-saherelm.x-guard.lib.mq5"
#include <Trade/Trade.mqh>
//
// Definitions ...
//
// a List of Used Tokens ...
//
// Common ...
string XIDToken = "ID";
string XTicketToken = "TK";
string XModeToken = "MD";
string XTypeToken = "TY";
string XPeriodToken = "PR";
string XProviderToken = "PRV";
string XProfitToken = "PF";
//
string XTPToken = "TP";
string XSLToken = "SL";
string XTimeToken = "TM";
string XEntryToken = "EN";
string XVolumeToken = "VL";
string XSymbolToken = "SMBL";
//
string XSupportToken = "SP";
string XEQMSupportToken = "EQM";
string XEQPToken = "EQP";
//
string XSLTrailToken = "SLT";
//
string XActionToken = "A";
//
string XDirectionalToken = "D";
string XINDirectionalToken = "IND";
//
string XRecoveryToken = "XRCV";
//
// Available Order Modes ...
enum ENUM_X_ORDER_MODES
{
X_ORDER_MODE_NOTHING, // Nothing
X_ORDER_MODE_MARKET, // Market Order
X_ORDER_MODE_STOP, // Pending Stop Order
X_ORDER_MODE_LIMIT, // Pending Limit Order
X_ORDER_MODE_STOP_LIMIT, // Pending Stop Limit Order
};
//
string ToString(ENUM_X_ORDER_MODES value)
{
//
string result = NULL;
//
switch (value)
{
//
case X_ORDER_MODE_MARKET:
result = "Market";
break;
//
case X_ORDER_MODE_LIMIT:
result = "Limit";
break;
//
case X_ORDER_MODE_STOP:
result = "Stop";
break;
//
case X_ORDER_MODE_STOP_LIMIT:
result = "StopLimit";
break;
}
//
return result;
}
//
// Select Positions Type ...
enum ENUM_X_POSITION_SELECT_METHODS
{
X_POSITION_SELECT_NONE, // None
X_POSITION_SELECT_MAX, // Max
X_POSITION_SELECT_MIN, // Min
X_POSITION_SELECT_BOTH, // Min and Max
X_POSITION_SELECT_ALL, // All
};
//
// Signal Execution Result ...
// note that some of them must be handles in
// EA's ...
enum ENUM_X_SIGNAL_EXECUTION_RESULT
{
//
X_SIGNAL_EXECUTION_UNKNOWN, // Unknown
X_SIGNAL_EXECUTION_SUCCEED, // Succed
X_SIGNAL_EXECUTION_FAILED_SPREAD, // Spread more than Max Allowed
X_SIGNAL_EXECUTION_FAILED_NOT_ALLOWED, // Not Allowed Trade Type
X_SIGNAL_EXECUTION_FAILED_NO_EQUITY, // No Equity for Trade
X_SIGNAL_EXECUTION_FAILED_PRICE_ERROR, // Price Error
X_SIGNAL_EXECUTION_FAILED_PREV_PROFIT_ERROR, // Prev Profit Error
X_SIGNAL_EXECUTION_FAILED_MAX_REACHED, // Max Allowed Positions Reached
X_SIGNAL_EXECUTION_FAILED_DELAY_NOT_PASSED, // Same Positions Delay Not Passed
X_SIGNAL_EXECUTION_FAILED_INVALID_PARAMS, // Invalid Params
};
//
enum ENUM_X_POSITION_TYPES
{
X_POSITION_TYPE_NONE = 0,
X_POSITION_TYPE_ALL = 1,
X_POSITION_TYPE_LONG = 2,
X_POSITION_TYPE_SHORT = 3,
};
//
bool IsValid(ENUM_X_POSITION_TYPES value)
{
return value != X_POSITION_TYPE_NONE;
}
//
bool HasSpecifiedType(ENUM_X_POSITION_TYPES value)
{
//
return value == X_POSITION_TYPE_LONG ||
value == X_POSITION_TYPE_SHORT;
}
//
string ToString(ENUM_X_POSITION_TYPES value)
{
//
string result = NULL;
//
switch (value)
{
//
case X_POSITION_TYPE_ALL:
result = "All";
break;
//
case X_POSITION_TYPE_NONE:
result = "NONE";
break;
//
case X_POSITION_TYPE_SHORT:
result = "Short";
break;
//
case X_POSITION_TYPE_LONG:
result = "Long";
break;
}
//
return result;
}
string ToXString(ENUM_X_POSITION_TYPES value)
{
return ToString(value);
}
//
bool IsLong(ENUM_X_POSITION_TYPES value)
{
return value == X_POSITION_TYPE_LONG;
}
//
bool IsShort(ENUM_X_POSITION_TYPES value)
{
return value == X_POSITION_TYPE_SHORT;
}
//
bool ToPositionType(
ENUM_POSITION_TYPE &dest,
ENUM_X_POSITION_TYPES source //
)
{
//
bool result = false;
//
result = source == X_POSITION_TYPE_LONG ||
source == X_POSITION_TYPE_SHORT;
if (!result)
{
return result;
}
//
dest =
source == X_POSITION_TYPE_LONG
? POSITION_TYPE_BUY
: POSITION_TYPE_SELL;
//
return result;
}
//
ENUM_X_POSITION_TYPES ToPositionType(ENUM_POSITION_TYPE value)
{
return IsLong(value)
? X_POSITION_TYPE_LONG
: X_POSITION_TYPE_SHORT;
}
//
ENUM_X_POSITION_TYPES OppositPositionType(ENUM_POSITION_TYPE type)
{
//
ENUM_X_POSITION_TYPES result = X_POSITION_TYPE_NONE;
//
bool isLong = IsLong(type);
bool isShort = IsShort(type);
//
result =
//
isLong
? X_POSITION_TYPE_SHORT
: isShort
? X_POSITION_TYPE_LONG
: X_POSITION_TYPE_NONE
//
;
//
return result;
}
//
ENUM_X_DIRECTION ToDirection(ENUM_POSITION_TYPE value)
{
//
ENUM_X_DIRECTION result = X_DIRECTION_NONE;
//
result = IsLong(value)
? X_DIRECTION_BULLISH
: X_DIRECTION_BEARISH;
//
return result;
}
//
ENUM_X_DIRECTION ToDirection(ENUM_X_POSITION_TYPES value)
{
//
ENUM_X_DIRECTION result = X_DIRECTION_NONE;
//
result = value == X_POSITION_TYPE_ALL
? X_DIRECTION_ALL
: value == X_POSITION_TYPE_LONG
? X_DIRECTION_BULLISH
: value == X_POSITION_TYPE_SHORT
? X_DIRECTION_BEARISH
: X_DIRECTION_NONE;
//
return result;
}
//
// All Awailable Trade Restrictions ...
enum ENUM_XTRADE_RESTRICTION_PERIOD
{
XTRADE_RESTRICATION_NONE, // None
XTRADE_RESTRICATION_HOURLY, // Per Hour
XTRADE_RESTRICATION_DAILY, // Per Day
XTRADE_RESTRICATION_WEEKLY, // Per Week
XTRADE_RESTRICATION_MONTHLY, // Per Month
};
//
string ToXString(ENUM_XTRADE_RESTRICTION_PERIOD value)
{
//
string result = NULL;
//
result = EnumToString(value);
//
return result;
}
//
ENUM_XTRADE_RESTRICTION_PERIOD ToXRestrictionPeriod(string value)
{
//
ENUM_XTRADE_RESTRICTION_PERIOD result = XTRADE_RESTRICATION_NONE;
//
if (!IsSpecifiedValid(value))
{
return result;
}
//
// None ...
if (value == ToXString(XTRADE_RESTRICATION_NONE))
{
result = XTRADE_RESTRICATION_NONE;
}
//
// Per Hour ...
else if (value == ToXString(XTRADE_RESTRICATION_HOURLY))
{
result = XTRADE_RESTRICATION_HOURLY;
}
//
// Per Day ...
else if (value == ToXString(XTRADE_RESTRICATION_DAILY))
{
result = XTRADE_RESTRICATION_DAILY;
}
//
// Per Week ...
else if (value == ToXString(XTRADE_RESTRICATION_WEEKLY))
{
result = XTRADE_RESTRICATION_WEEKLY;
}
//
// Per Month ...
else if (value == ToXString(XTRADE_RESTRICATION_MONTHLY))
{
result = XTRADE_RESTRICATION_MONTHLY;
}
//
return result;
}
//
int GetXRestrictionsPeriodSeconds(ENUM_XTRADE_RESTRICTION_PERIOD value)
{
//
int result = 0;
//
if (!HasRestrictions(value))
{
return result;
}
//
switch (value)
{
//
// None ...
case XTRADE_RESTRICATION_NONE:
result = 0;
break;
//
// Hour ...
case XTRADE_RESTRICATION_HOURLY:
result = PeriodSeconds(PERIOD_H1);
break;
//
// Dayly ...
case XTRADE_RESTRICATION_DAILY:
result = PeriodSeconds(PERIOD_D1);
break;
//
// Weekly ...
case XTRADE_RESTRICATION_WEEKLY:
result = PeriodSeconds(PERIOD_W1);
break;
//
// Monthly ...
case XTRADE_RESTRICATION_MONTHLY:
result = PeriodSeconds(PERIOD_M1);
break;
}
//
return result;
}
/**
* Check a Value Has Trade Restrictions or not ...
*
* @param value: ENUM_XTRADE_RESTRICTION_PERIOD
* ّ
* @return ( bool )
*/
bool HasRestrictions(ENUM_XTRADE_RESTRICTION_PERIOD value)
{
return value != XTRADE_RESTRICATION_NONE;
}
//
// All Awailable Trade Finalizations ...
enum ENUM_XTRADE_FINALIZATION
{
XTRADE_FINAL_NONE, // None
XTRADE_FINAL_TP, // TP
XTRADE_FINAL_SL, // SL
XTRADE_FINAL_CLOSE_IN_PROFIT, // Profit
XTRADE_FINAL_CLOSE_IN_LOSE, // Lost
};
//
string ToXString(ENUM_XTRADE_FINALIZATION value)
{
return EnumToString(value);
}
//
// Position Selecting Methods ...
enum ENUM_XPOSITION_SELECT_TYPES
{
XPOSITION_SELECT_NONE = 0, // None
XPOSITION_SELECT_ALL = 1, // All
XPOSITION_SELECT_IN_PROFITS = 2, // In Profit Positions
XPOSITION_SELECT_IN_DRAWDOWNS = 3, // In Drawdown Positions
XPOSITION_SELECT_OLDEST = 4, // Oldest Position
XPOSITION_SELECT_YOUNGEST = 5, // Youngest Position
XPOSITION_SELECT_IN_PROFITS_OLDEST = 6, // In Profit Positions Oldest one
XPOSITION_SELECT_IN_PROFITS_YOUNGEST = 7, // In Profit Positions Youngest one
XPOSITION_SELECT_IN_PROFITS_MIN = 8, // Minimum Profitable Position
XPOSITION_SELECT_IN_PROFITS_MAX = 9, // Maximum Profitable Position
XPOSITION_SELECT_IN_DRAWDOWN_OLDEST = 10, // In Drawdown Positions Oldest one
XPOSITION_SELECT_IN_DRAWDOWN_YOUNGEST = 11, // In Drawdown Positions Youngest one
XPOSITION_SELECT_IN_DRAWDOWN_MIN = 12, // Minimum in Drawdown Position
XPOSITION_SELECT_IN_DRAWDOWN_MAX = 13, // Maximum in Drawdown Position
XPOSITION_SELECT_SAMES = 14, // Same Type Positions
XPOSITION_SELECT_SAMES_OLDEST = 15, // Same Type Positions Oldest one
XPOSITION_SELECT_SAMES_YOUNGEST = 16, // Same Type Positions Youngest one
XPOSITION_SELECT_OPPOSITS = 17, // Opposit Type Positions
XPOSITION_SELECT_OPPOSIT_OLDEST = 18, // Opposit Type Positions Oldest one
XPOSITION_SELECT_OPPOSIT_YOUNGEST = 19, // Opposit Type Positions Youngest one
XPOSITION_SELECT_SAME_IN_PROFITS = 20, // Same Type In Profit Positions
XPOSITION_SELECT_SAME_IN_PROFITS_OLDEST = 21, // Same Type In Profit Positions Oldest one
XPOSITION_SELECT_SAME_IN_PROFITS_YOUNGEST = 22, // Same Type In Profit Positions Youngest one
XPOSITION_SELECT_SAME_IN_PROFITS_MIN = 23, // Minimum Profitable of Same Type Positions
XPOSITION_SELECT_SAME_IN_PROFITS_MAX = 24, // Maximum Profitable of Same Type Positions
XPOSITION_SELECT_OPPOSIT_IN_PROFITS = 25, // Opposit Type In Profit Positions
XPOSITION_SELECT_OPPOSIT_IN_PROFITS_OLDEST = 26, // Opposit Type In Profit Positions Oldest one
XPOSITION_SELECT_OPPOSIT_IN_PROFITS_YOUNGEST = 27, // Opposit Type In Profit Positions Youngest one
XPOSITION_SELECT_OPPOSIT_IN_PROFITS_MIN = 28, // Minimum Profitable of Opposit Type Positions
XPOSITION_SELECT_OPPOSIT_IN_PROFITS_MAX = 29, // Maximum Profitable of Opposit Type Positions
XPOSITION_SELECT_SAME_IN_DRAWDOWNS = 30, // Same Type In Deawdown Positions
XPOSITION_SELECT_SAME_IN_DRAWDOWN_OLDEST = 31, // Same Type In Deawdown Positions Oldest one
XPOSITION_SELECT_SAME_IN_DRAWDOWN_YOUNGEST = 32, // Same Type In Deawdown Positions Youngest one
XPOSITION_SELECT_SAME_IN_DRAWDOWN_MIN = 33, // Minimum In Drawdown of Same Type Positions
XPOSITION_SELECT_SAME_IN_DRAWDOWN_MAX = 34, // Maximum In Drawdown of Same Type Positions
XPOSITION_SELECT_OPPOSITS_IN_DRAWDOWNS = 35, // Opposit Type In Deawdown Positions
XPOSITION_SELECT_OPPOSITS_IN_DRAWDOWN_OLDEST = 36, // Opposit Type In Deawdown Positions Oldest one
XPOSITION_SELECT_OPPOSITS_IN_DRAWDOWN_YOUNGEST = 37, // Opposit Type In Deawdown Positions Youngest one
XPOSITION_SELECT_OPPOSITS_IN_DRAWDOWN_MIN = 38, // Minimum In Drawdown of Opposit Type Positions
XPOSITION_SELECT_OPPOSITS_IN_DRAWDOWN_MAX = 39, // Maximum In Drawdown of Opposit Type Positions
};
/**
* Validate Position Select Type ...
*
* @param value: ENUM_XPOSITION_SELECT_TYPES
*
* @return ( bool )
*/
bool IsXValid(ENUM_XPOSITION_SELECT_TYPES value)
{
return value != XPOSITION_SELECT_NONE;
}
//
string ToXString(ENUM_XPOSITION_SELECT_TYPES value)
{
return EnumToString(value);
}
//
// Structs ...
//
struct XRR
{
//
double tps[];
//
double sl;
double entry;
//
string prefix;
string symbol;
datetime time;
ENUM_TIMEFRAMES period;
//
ENUM_X_POSITION_TYPES type;
//
// Constructor ...
XRR()
{
Clean();
}
//
// Tools ...
//
void Clean()
{
//
sl = 0;
entry = 0;
//
time = NULL;
prefix = NULL;
period = NULL;
symbol = NULL;
//
type = X_POSITION_TYPE_NONE;
//
SpecifiedClean(tps);
//
ZeroMemory(this);
}
//
bool Init(
string _symbol,
ENUM_TIMEFRAMES _period,
double _sl,
double _entry,
ENUM_X_POSITION_TYPES _type,
string _prefix = NULL //
)
{
//
bool result = false;
//
result =
_sl > 0 &&
_entry > 0 &&
IsSpecifiedValid(_symbol) &&
IsSpecifiedValid(_period) &&
_type != X_POSITION_TYPE_ALL &&
_type != X_POSITION_TYPE_NONE &&
(_type == X_POSITION_TYPE_LONG
? _entry > _sl
: _entry < _sl);
if (!result)
{
return result;
}
//
Default();
//
sl = _sl;
type = _type;
entry = _entry;
symbol = _symbol;
period = _period;
prefix = _prefix;
//
time = TimeCurrent();
//
result = IsValid();
//
return result;
}
//
void Default()
{
//
Add(
1.0,
tps //
);
Add(
1.5,
tps //
);
Add(
2.0,
tps //
);
Add(
3.0,
tps //
);
Add(
4.0,
tps //
);
Add(
5.0,
tps //
);
Add(
6.0,
tps //
);
}
//
bool IsValid()
{
//
bool result = false;
//
result =
sl > 0 &&
entry > 0 &&
IsSpecifiedValid(time) &&
IsSpecifiedValid(symbol) &&
IsSpecifiedValid(period) &&
IsValidSize(ArraySize(tps)) &&
type != X_POSITION_TYPE_ALL &&
type != X_POSITION_TYPE_NONE &&
(type == X_POSITION_TYPE_LONG
? entry > 0
: entry < sl);
//
return result;
}
//
string GetTag()
{
//
string result = NULL;
//
if (!IsValid())
{
//
result = GetTypeName(this);
return result;
}
//
string sep = "_";
//
result =
GetTypeName(this) + sep + (IsSpecifiedValid(prefix) ? prefix + sep : "") + symbol + sep + ToXString(period) + sep + ToFormatString(time) + sep + ToString(type);
//
return result;
}
};
//
// Model a Target ...
struct XTarget
{
//
// Props ...
bool doRF; // Do RF on Target
bool doRFOnEntry; // Do RF on Entry
double actingDistance; // Acting Distances
double target; // Target Price for Actions
double volumeMultiplier; // Volume Multiplier for Partial Close
double tpValue; // TP Value Changed ...
//
// Constructor ...
XTarget()
{
Clean();
}
//
// Tools ...
//
// Cleanup ...
void Clean()
{
//
target = 0;
tpValue = 0;
doRF = false;
actingDistance = 0;
doRFOnEntry = false;
volumeMultiplier = 0;
}
//
// Validate ...
bool IsValid()
{
//
bool result = false;
//
result = target > 0;
//
return result;
}
};
//
// Get Lowest Target index ...
int GetLowest(XTarget &targets[])
{
//
int result = -1;
//
if (!HasChild(targets))
{
return result;
}
//
XTarget iTarget;
int count = ArraySize(targets);
for (int i = 0; i < count; i++)
{
//
bool canSet =
!iTarget.IsValid()
? true
: iTarget.target > targets[i].target;
if (canSet)
{
//
result = i;
iTarget = targets[i];
}
}
//
iTarget.Clean();
//
return result;
}
//
// Get Highest Target index ...
int GetHighest(XTarget &targets[])
{
//
int result = -1;
//
if (!HasChild(targets))
{
return result;
}
//
XTarget iTarget;
int count = ArraySize(targets);
for (int i = 0; i < count; i++)
{
//
bool canSet =
!iTarget.IsValid()
? true
: iTarget.target < targets[i].target;
if (canSet)
{
//
result = i;
iTarget = targets[i];
}
}
//
iTarget.Clean();
//
return result;
}
//
// Apply Sorting on Targets ...
void ApplySortOnTargets(
ENUM_X_DIRECTION forDir, // Target Sorting Direction ...
XTarget &targets[] // Targets to Apply Sorting ...
)
{
//
bool has = HasChild(targets) &&
HasDirection(forDir);
if (!has)
{
return;
}
//
bool isBullish = IsBullish(forDir);
bool isBearish = IsBearish(forDir);
//
XTarget tmp[];
Copy(
targets,
tmp //
);
Clean(targets);
while (HasChild(tmp))
{
//
int idx = -1;
if (isBullish)
{
idx = GetLowest(tmp);
}
else if (isBearish)
{
idx = GetHighest(tmp);
}
//
has = IsValidIndex(idx);
if (!has)
{
break;
}
//
XTarget iTarget = tmp[idx];
ArrayRemove(
tmp,
idx,
1 //
);
AddRef(
iTarget,
targets //
);
}
//
Clean(tmp);
}
//
// Model an Open Position ...
struct XPosition
{
//
// Props ...
//
// Magic Number ...
ulong magic;
//
// Ticket ID ...
ulong ticket;
//
// Tradinng Symbol ...
string symbol;
//
// Trading Period ...
ENUM_TIMEFRAMES period;
//
// Position Type ...
ENUM_POSITION_TYPE type;
//
// Take Profit ...
double tp;
//
// Stop Loss ...
double sl;
//
// Position Current Profit ...
double profit;
//
// Position Open Price ...
double entry;
//
// Current Symbol Price ...
double price;
//
// Position Swap ...
double swap;
//
// Position Commission ...
double commission;
//
// Volume ...
double volume;
//
// Position Open Time ...
datetime openAt;
//
// Sifnal Provider ...
string provider;
//
// Position Comment ...
string comment;
//
// Constructor ...
XPosition()
{
Clean();
}
//
// Initializers ...
bool ByIndex(int index)
{
//
bool result = false;
//
static CPositionInfo mPositionInfo;
//
result = mPositionInfo.SelectByIndex(index);
if (!result)
{
return result;
}
//
ulong mTicket = mPositionInfo.Ticket();
//
result = ByTicket(mTicket);
//
return result;
}
bool ByTicket(ulong mTicket)
{
//
bool result = false;
//
static CPositionInfo mPositionInfo;
//
result = mPositionInfo.SelectByTicket(mTicket);
if (!result)
{
return result;
}
//
swap = mPositionInfo.Swap();
magic = mPositionInfo.Magic();
openAt = mPositionInfo.Time();
sl = mPositionInfo.StopLoss();
ticket = mPositionInfo.Ticket();
symbol = mPositionInfo.Symbol();
tp = mPositionInfo.TakeProfit();
profit = mPositionInfo.Profit();
volume = mPositionInfo.Volume();
comment = mPositionInfo.Comment();
entry = mPositionInfo.PriceOpen();
type = mPositionInfo.PositionType();
price = mPositionInfo.PriceCurrent();
commission = mPositionInfo.Commission();
//
period = ExtractPeriod(comment);
provider = ExtractProvider(comment);
//
return result;
}
//
// Tools ...
//
// Cleanup ...
void Clean()
{
magic = 0;
ticket = 0;
tp = 0;
sl = 0;
swap = 0;
entry = 0;
price = 0;
profit = 0;
volume = 0;
openAt = 0;
commission = 0;
//
type = NULL;
period = NULL;
//
symbol = NULL;
comment = NULL;
provider = NULL;
//
ZeroMemory(this);
}
//
// Validate ...
bool IsValid()
{
//
bool result = false;
//
result =
//
IsSpecifiedValid(symbol) &&
NotEmpty(ticket)
//
;
//
return result;
}
//
bool IsLong()
{
return IsValid() &&
IsXBullish(type);
}
//
bool IsBullish()
{
return IsLong();
}
//
bool IsShort()
{
return IsValid() &&
IsXBearish(type);
}
//
bool IsBearish()
{
return IsShort();
}
//
ENUM_X_DIRECTION GetDirection()
{
//
return IsBullish()
? X_DIRECTION_BULLISH
: IsBearish()
? X_DIRECTION_BEARISH
: X_DIRECTION_NONE;
}
//
// Retrieve Entry Price ...
double GetEntry()
{
//
double result = 0;
//
if (!IsValid())
{
return result;
}
//
result = GetXEntry(
symbol,
type
//
);
//
return result;
}
//
// Retrieve Exit ...
double GetExit()
{
//
double result = 0;
//
if (!IsValid())
{
return result;
}
//
result = GetXExit(
symbol,
type
//
);
//
return result;
}
//
// Get Spread by Point ...
double GetSpread()
{
//
double result = 0;
//
if (!IsValid())
{
return result;
}
//
result = PriceToPoint(GetXSpread(symbol));
//
return result;
}
//
double GetPointsValue()
{
//
double result = 0;
//
if (!IsValid())
{
return result;
}
//
result = GetPoints(symbol);
//
return result;
}
//
double GetProfitInPoint()
{
//
double result = 0;
//
if (!IsValid())
{
return result;
}
//
double tickSize = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE); // Tick size
double tickValue = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE); // Tick value
double pointSize = SymbolInfoDouble(symbol, SYMBOL_POINT); // Point size
double pointValue = tickValue * pointSize / tickSize; // Point value
//
result = profit / (volume * tickValue);
//
return result;
}
//
// Find Risk ...
double GetRisk()
{
//
double result = 0;
//
if (!IsValid())
{
return 0;
}
//
result = MathAbs(entry - sl);
//
return result;
}
//
double GetRiskInPoint()
{
//
double result = 0;
//
result = GetRisk() / GetPoints();
//
return result;
}
//
// Find Reward ...
double GetReward()
{
//
double result = 0;
//
if (!IsValid())
{
return result;
}
//
result = MathAbs(tp - entry);
//
return result;
}
//
double GetRewardInPoint()
{
//
double result = 0;
//
result = GetReward() / GetPoints();
//
return result;
}
//
// Find Risk Reward Ratio ...
double GetRiskRewardRatio()
{
//
double result = 0;
//
if (!IsValid())
{
return result;
}
//
result = GetReward() / GetRisk();
//
return result;
}
//
// Calculate TP Levels ...
int CalculateTPLevels(double &tps[])
{
//
int result = 0;
//
SpecifiedClean(tps);
//
bool isValid = IsValid();
if (!isValid)
{
return result;
}
//
double risk = GetRisk();
int r2r = (int)GetRiskRewardRatio();
bool isLong = IsLong();
for (int i = 0; i < r2r; i++)
{
//
double iValue =
isLong
? entry + risk + (i * risk)
: entry - risk - (i * risk);
//
Add(
iValue,
tps //
);
}
//
result = ArraySize(tps);
//
return result;
}
//
// Calculate Reached TP Levels ...
void CalculateReahedTP(
double &reachedLevel,
double &reachedPrice //
)
{
//
reachedLevel = -1;
reachedPrice = 0;
double tps[];
bool isLong = IsLong();
double exitPrice = GetExit();
int tpLevels = CalculateTPLevels(tps);
if (!IsValidSize(tpLevels) || exitPrice <= 0)
{
return;
}
//
for (int i = 0; i < tpLevels - 1; i++)
{
//
double cTP = tps[i];
double nTP = tps[i + 1];
//
bool isReached =
isLong
? exitPrice > cTP &&
exitPrice < nTP
: exitPrice < cTP &&
exitPrice > nTP;
if (isReached)
{
//
reachedLevel = i + 1;
reachedPrice = cTP;
}
}
}
//
// Calculate Touched Reward ...
double CalculateTouchedReward()
{
//
double result = 0.0;
//
bool has = IsValid() &&
profit > 0;
if (!has)
{
return result;
}
//
double risk = MathAbs(entry - sl);
double currentReward = MathAbs(price - entry);
//
result = currentReward / risk;
//
return result;
}
//
// Calculate Age ...
int GetAge(
ENUM_TIMEFRAMES mPeriod // Calculate Age based on this period
)
{
return GetXAge(this, mPeriod);
}
//
// Check this instance is Same os Given instance or not ...
bool IsSameAs(
const XPosition &value // instance for Compare
)
{
//
bool result = false;
//
result =
//
type == value.type &&
magic == value.magic &&
entry == value.entry &&
ticket == value.ticket &&
volume == value.volume &&
symbol == value.symbol &&
provider == value.provider
//
;
//
return result;
}
//
// Find index in a Collection ...
int FindIndex(
XPosition &values[] // Collection to Find
)
{
//
return FindXIndex(
this,
values
//
);
}
//
// Check Items Passed Specific Filters or not ...
bool IsFiltersPassed(
string mSymbol = NULL, // Trading Symbol
string mProvider = NULL, // Signal Provider
ENUM_TIMEFRAMES mPeriod = NULL, // Trading Timeframe
ENUM_X_POSITION_TYPES mType = NULL, // Long (Buy), Short (Sell)
ulong mMagic = NULL, // Magic Number
bool mFilterByMagic = true // Get Only Self Open Positions
)
{
//
bool result = false;
//
result =
//
// Magic Filter ...
IsMagicFilterPassed(
mMagic,
mFilterByMagic,
this
//
)
//
&&
//
// Symbol Filter ...
IsSymbolFilterPassed(
mSymbol,
this
//
)
//
&&
//
// Provider Filter ...
IsProviderFilterPassed(
mProvider,
this
//
)
//
&&
//
// Period Filter ...
IsPeriodFilterPassed(
mPeriod,
this
//
)
//
&&
//
// Type Filter ...
IsTypeFilterPassed(
mType,
this
//
)
//
;
//
return result;
}
};
//
// Model a Signal ...
struct XSignal
{
//
// Props ...
//
ulong positionId; // if Executed this filled ...
//
datetime time; // Issue Time ...
//
double tp; // Take Profit ...
double sl; // Stop Loss ...
double entry; // Exntry or Execution Price ...
double volume; // Position Volume ...
//
string symbol; // Trading Symbol ...
string comment; // Comment ...
string provider; // Signaller ...
//
ENUM_TIMEFRAMES period; // Trading TimeFrame ...
ENUM_POSITION_TYPE type; // Long (Buy) or Short (Sell) ...
ENUM_X_ORDER_MODES mode; // Execution Mode ...
//
string conditions; // Signal Conditions ...
//
// Additional ...
//
// Traget ...
XTarget targets[]; // Provided Targets ...
int appliedTargetIDX; // Last Applied Target Index ...
bool ignoreEAVolume; // Ignore EA Volume ...
bool isTargetApplied; // Check if Target Applied or not ...
//
// Constructor ...
XSignal()
{
Default();
}
//
// Tools ...
//
// Cleanup ...
void Clean()
{
//
entry = 0;
volume = 0;
positionId = 0;
//
time = NULL;
type = NULL;
mode = NULL;
symbol = NULL;
period = NULL;
comment = NULL;
provider = NULL;
conditions = NULL;
//
SpecifiedClean(targets);
appliedTargetIDX = -1;
ignoreEAVolume = false;
isTargetApplied = false;
//
ZeroMemory(this);
}
//
// Default Values ...
void Default()
{
//
entry = 0;
volume = 0;
positionId = 0;
//
time = NULL;
type = NULL;
mode = NULL;
symbol = NULL;
period = NULL;
comment = NULL;
provider = NULL;
conditions = NULL;
//
SpecifiedClean(targets);
appliedTargetIDX = -1;
ignoreEAVolume = false;
isTargetApplied = false;
}
//
// Validate ...
bool IsValid()
{
//
bool result = false;
//
result =
//
IsSpecifiedValid(period) &&
IsSpecifiedValid(symbol) &&
NotEmpty(volume) &&
NotEmpty(entry)
//
;
//
if (!result)
{
return result;
}
//
return result;
}
//
// DO All Calculations and Normalizations ...
bool Normalize()
{
//
bool result = false;
//
// Normalizations ...
symbol = NormalizeSymbol(symbol);
period = NormalizePeriod(period);
//
time = NormalizeTime(time);
//
sl = NormalizePrice(sl, symbol);
tp = NormalizePrice(tp, symbol);
entry = NormalizePrice(entry, symbol);
volume = NormalizeVolume(volume, symbol);
//
result = IsValid();
//
return result;
}
//
// Check Signal Executed or not ...
bool IsExecuted()
{
//
bool result = false;
//
result =
//
IsValid() &&
NotEmpty(positionId)
//
;
//
return result;
}
//
// Generate Comment for Signal ...
string GenerateComment()
{
//
string result = NULL;
//
if (!IsValid())
{
return result;
}
//
if (IsSpecifiedValid(provider))
{
//
// Generate Provider Tag ...
result += GenerateProviderTag(provider);
}
//
if (IsSpecifiedValid(period))
{
//
// Generate Period Tag ...
result += GeneratePeriodTag(period);
}
//
return result;
}
//
int GetAge()
{
//
return GetXAge(
this,
this.period //
);
}
//
// Find Risk ...
double GetRisk()
{
//
double result = 0;
//
if (!IsValid())
{
return 0;
}
//
result = MathAbs(entry - sl);
//
return result;
}
//
// Find Reward ...
double GetReward()
{
//
double result = 0;
//
if (!IsValid())
{
return result;
}
//
result = MathAbs(tp - entry);
//
return result;
}
//
// Find Risk Reward Ratio ...
double GetRiskRewardRatio()
{
//
double result = 0;
//
if (!IsValid())
{
return result;
}
//
result = GetReward() / GetRisk();
//
return result;
}
//
string GetTag()
{
//
string result = NULL;
//
result = "XSignal_" +
symbol + "_" +
ToXString(period) + "_" +
ToXString(type) + "_" +
ToXString(sl) + "_" +
ToXString(tp) + "_" +
ToXString(entry);
//
return result;
}
//
string GetObjectID()
{
//
string result = "";
//
if (!IsValid())
{
return result;
}
//
result = "XSignal_" +
symbol + "_" +
ToXString(period) + "_" +
ToXString(type) + "_" +
ToXString(TimeToSeconds(time));
//
return result;
}
//
// Retrieve String Representation of Signal ...
string ToString()
{
//
string result = NULL;
//
result =
//
ToXString("Symbol", symbol) +
ToXString("Period", period) +
ToXString("Provider", provider) +
ToXString("Type", type) +
ToXString("Mode", mode) +
ToXString("Volume", volume) +
ToXString("Entry", entry) +
ToXString("TP", tp) +
ToXString("SL", sl) +
ToXString("Time", time) +
ToXString("Comment", comment) +
//
""
//
;
//
return result;
}
//
bool IsSameAs(XSignal &item)
{
//
bool result = false;
//
result =
//
IsValid() &&
item.IsValid() &&
//
tp == item.tp &&
sl == item.sl &&
mode == item.mode &&
time == item.time &&
type == item.type &&
entry == item.entry &&
symbol == item.symbol &&
period == item.period &&
provider == item.provider
//
;
//
return result;
}
//
string GetMessage(string action = NULL)
{
//
string result = NULL;
//
if (!IsValid())
{
return result;
}
//
result = ToXString(type) +
" Signal" +
(!IsSpecifiedValid(action)
? ""
: " " + action) +
" by: " + provider +
" on (" + symbol + ")" +
" in: " + ToXString(period);
//
return result;
}
//
string GetFileName()
{
//
string result = NULL;
//
if (!IsValid())
{
return result;
}
//
result =
//
symbol + "\\" +
ToXString(type) + "\\" +
ToXString(period) + "_" +
ToFormatString(time)
//
;
//
return result;
}
};
//
// Model an Order ...
struct XOrder
{
//
// Time of order placement ...
datetime setupAt;
//
// Time of order expiration ...
datetime expiredAt;
//
// Time of order execution or cancellation ...
datetime executedAt;
//
// Order type ...
ENUM_ORDER_TYPE type;
//
// Order state ...
ENUM_ORDER_STATE state;
//
// Type of execution by remainder ...
ENUM_ORDER_TYPE_FILLING filling;
//
// Order lifetime ...
ENUM_ORDER_TYPE_TIME lifetime;
//
// Order ticket ...
ulong ticket;
//
// Magic Number ...
long magic;
//
// Position id, that is placed on order,
// when it is executed. Each executed order invokes a
// deal, that opens new or changes existing
// position. Id of that position is placed on
// executed order in this moment.
long positionId;
//
// Initial volume on order placement ...
double initialVolume;
//
// Unfilled volume ...
double currentVolume;
//
// Price, specified in the order ...
double openPrice;
//
// Current price by order symbol ...
double currentPrice;
//
// Price of placing Limit order when StopLimit order is triggered ...
double stopLimitPrice;
//
// Take Profit level ...
double tp;
//
// Stop Loss level ...
double sl;
//
// Trading Symbol ...
string symbol;
//
// Signal Provider ...
string provider;
//
// Order Comment ...
string comment;
//
ENUM_TIMEFRAMES period;
//
// Constructor ...
XOrder()
{
Clean();
}
//
// Initializers ...
bool ByIndex(
int index // Fill By Index ...
)
{
//
bool result = false;
//
int ordersCount = OrdersTotal();
if (ordersCount <= 0)
{
return result;
}
//
static COrderInfo mOrderInfo;
//
result = mOrderInfo.SelectByIndex(index);
if (!result)
{
return result;
}
//
// Reading Order Info ...
magic = mOrderInfo.Magic();
sl = mOrderInfo.StopLoss();
tp = mOrderInfo.TakeProfit();
ticket = mOrderInfo.Ticket();
openPrice = mOrderInfo.PriceOpen();
positionId = mOrderInfo.PositionId();
currentPrice = mOrderInfo.PriceCurrent();
initialVolume = mOrderInfo.VolumeInitial();
currentVolume = mOrderInfo.VolumeCurrent();
stopLimitPrice = mOrderInfo.PriceStopLimit();
//
symbol = mOrderInfo.Symbol();
comment = mOrderInfo.Comment();
//
state = mOrderInfo.State();
type = mOrderInfo.OrderType();
lifetime = mOrderInfo.TypeTime();
filling = mOrderInfo.TypeFilling();
//
setupAt = mOrderInfo.TimeSetup();
executedAt = mOrderInfo.TimeDone();
expiredAt = mOrderInfo.TimeExpiration();
//
period = ExtractPeriod(comment);
provider = ExtractProvider(comment);
//
result = IsValid();
//
return result;
}
//
// Retrieve Specific History Order ...
bool HistoryByIndex(
int index // Fill By Index ...
)
{
//
bool result = false;
//
int ordersCount = HistoryOrdersTotal();
if (ordersCount <= 0)
{
return result;
}
//
static CHistoryOrderInfo mOrderInfo;
//
result = mOrderInfo.SelectByIndex(index);
if (!result)
{
return result;
}
//
// Reading Order Info ...
magic = mOrderInfo.Magic();
sl = mOrderInfo.StopLoss();
tp = mOrderInfo.TakeProfit();
ticket = mOrderInfo.Ticket();
openPrice = mOrderInfo.PriceOpen();
positionId = mOrderInfo.PositionId();
currentPrice = mOrderInfo.PriceCurrent();
initialVolume = mOrderInfo.VolumeInitial();
currentVolume = mOrderInfo.VolumeCurrent();
stopLimitPrice = mOrderInfo.PriceStopLimit();
//
symbol = mOrderInfo.Symbol();
comment = mOrderInfo.Comment();
//
state = mOrderInfo.State();
type = mOrderInfo.OrderType();
lifetime = mOrderInfo.TypeTime();
filling = mOrderInfo.TypeFilling();
//
setupAt = mOrderInfo.TimeSetup();
executedAt = mOrderInfo.TimeDone();
expiredAt = mOrderInfo.TimeExpiration();
//
period = ExtractPeriod(comment);
provider = ExtractProvider(comment);
//
result = IsValid();
//
return result;
}
//
// Tools ...
//
// Cleanup ...
void Clean()
{
//
tp = 0;
sl = 0;
magic = 0;
ticket = 0;
positionId = 0;
openPrice = 0;
currentPrice = 0;
initialVolume = 0;
currentVolume = 0;
stopLimitPrice = 0;
//
setupAt = NULL;
expiredAt = NULL;
executedAt = NULL;
//
symbol = NULL;
comment = NULL;
provider = NULL;
//
type = NULL;
state = NULL;
period = NULL;
filling = NULL;
lifetime = NULL;
//
ZeroMemory(this);
}
//
// Validate ...
bool IsValid()
{
//
bool result = false;
//
result =
//
IsSpecifiedValid(symbol) &&
NotEmpty(ticket) &&
NotEmpty(positionId)
//
;
//
return result;
}
//
// Calculate Age ...
int GetAge(
ENUM_TIMEFRAMES mPeriod // Calculate Age based on this period
)
{
return GetXAge(this, mPeriod);
}
//
// Check this instance is Same os Given instance or not ...
bool IsSameAs(
const XOrder &value // instance for Compare
)
{
//
bool result = false;
//
result =
//
type == value.type &&
state == value.state &&
magic == value.magic &&
ticket == value.ticket &&
symbol == value.symbol &&
provider == value.provider &&
positionId == value.positionId
//
;
//
return result;
}
//
// Find index in a Collection ...
int FindIndex(
XOrder &values[] // Collection to Find
)
{
//
return FindXIndex(
this,
values
//
);
}
//
// Check Items Passed Specific Filters or not ...
bool IsFiltersPassed(
string mSymbol = NULL, // Trading Symbol
string mProvider = NULL, // Signal Provider
ENUM_TIMEFRAMES mPeriod = NULL, // Trading Timeframe
ENUM_X_POSITION_TYPES mType = NULL, // Long (Buy), Short (Sell)
ENUM_ORDER_STATE mState = NULL, // Order State
ulong mMagic = NULL, // Magic Number
bool mFilterByMagic = true // Get Only Self Open Positions
)
{
//
bool result = false;
//
result =
//
// Magic Filter ...
IsMagicFilterPassed(
mMagic,
mFilterByMagic,
this
//
)
//
&&
//
// Symbol Filter ...
IsSymbolFilterPassed(
mSymbol,
this
//
)
//
&&
//
// Provider Filter ...
IsProviderFilterPassed(
mProvider,
this
//
)
//
&&
//
// Period Filter ...
IsPeriodFilterPassed(
mPeriod,
this
//
)
//
&&
//
// Type Filter ...
IsTypeFilterPassed(
mType,
this
//
)
//
&&
//
// State Filter ...
IsStateFilterPassed(
mState,
this
//
)
//
;
//
return result;
}
};
//
// Model a Deal ...
struct XDeal
{
//
// the ID of the Expert Advisor, that executed the deal ...
ulong magic;
//
// the ID of position, in which the deal was involved ...
ulong positionId;
//
// Ticket ...
ulong ticket;
//
// the name of the deal symbol ...
string symbol;
//
// order by which the deal is executed ...
ulong order;
//
// the time of deal execution ...
datetime time;
//
// Deal price ...
double price;
//
// the financial result of the deal (in deposit currency) ...
double profit;
//
// the amount of swap when position is closed ...
double swap;
//
// the amount of commission of the deal ...
double commission;
//
// the volume of deal ...
double volume;
//
// the deal comment ...
string comment;
//
string provider;
//
ENUM_TIMEFRAMES period;
//
// the deal type ...
// ------------------------------------------------------------------
// DEAL_TYPE_BUY => Buy ...
// DEAL_TYPE_SELL => Sell ...
// DEAL_TYPE_BUY_CANCELED => Canceled buy deal ...
// There can be a situation when a previously executed buy deal is canceled. In this case,
// the type of the previously executed deal (DEAL_TYPE_BUY) is changed to DEAL_TYPE_BUY_CANCELED,
// and its profit/loss is zeroized. Previously obtained profit/loss is charged/withdrawn using a separated balance operation ...
//
// DEAL_TYPE_SELL_CANCELED => Canceled sell deal ...
// There can be a situation when a previously executed sell deal is canceled. In this case,
// the type of the previously executed deal (DEAL_TYPE_SELL) is changed to DEAL_TYPE_SELL_CANCELED,
// and its profit/loss is zeroized. Previously obtained profit/loss is charged/withdrawn using a separated balance operation
//
// DEAL_TYPE_BALANCE => Balance ...
// DEAL_TYPE_CREDIT => Credit ...
// DEAL_TYPE_CHARGE => Additional charge ...
// DEAL_TYPE_CORRECTION => Correction ...
// DEAL_TAX => Tax charges ...
// DEAL_TYPE_BONUS => Bonus ...
// DEAL_TYPE_INTEREST => Interest rate ...
// DEAL_DIVIDEND => Dividend operations...
// DEAL_DIVIDEND_FRANKED => Franked (non-taxable) dividend operations ...
// DEAL_TYPE_COMMISSION => Additional commission ...
// DEAL_TYPE_COMMISSION_DAILY => Daily commission ...
// DEAL_TYPE_COMMISSION_MONTHLY => Monthly commission ...
// DEAL_TYPE_COMMISSION_AGENT_DAILY => Daily agent commission ...
// DEAL_TYPE_COMMISSION_AGENT_MONTHLY => Monthly agent commission
ENUM_DEAL_TYPE type;
//
// the deal direction ...
// ----------------------------------
// DEAL_ENTRY_IN => Entry in ...
// DEAL_ENTRY_OUT => Entry out ...
// DEAL_ENTRY_INOUT => Reverse ...
// DEAL_ENTRY_OUT_BY => Close a position by an opposite one ...
ENUM_DEAL_ENTRY entry;
//
// deal reson ...
// ---------------------
// DEAL_REASON_SL => The deal was executed as a result of Stop Loss activation ...
// DEAL_REASON_TP => The deal was executed as a result of Take Profit activation ...
// DEAL_REASON_SO => The deal was executed as a result of the Stop Out event ...
// DEAL_REASON_WEB => The deal was executed as a result of activation of an order placed from the web platform ...
// DEAL_REASON_SPLIT => The deal was executed after the split (price reduction) of an instrument, which had an open position during split announcement ...
// DEAL_REASON_CLIENT => The deal was executed as a result of activation of an order placed from a desktop terminal ...
// DEAL_REASON_MOBILE => The deal was executed as a result of activation of an order placed from a mobile application ...
// DEAL_REASON_EXPERT => The deal was executed as a result of activation of an order placed from an MQL5 program, i.e. an Expert Advisor or a script ...
// DEAL_REASON_VMARGIN => The deal was executed after charging the variation margin ...
// DEAL_REASON_ROLLOVER => The deal was executed due to a rollover ...
ENUM_DEAL_REASON reason;
//
// Constructor ...
XDeal()
{
Clean();
}
//
// Initializers ...
bool ByIndex(
int index // Deal Index
)
{
//
bool result = false;
//
int dealsCount = HistoryDealsTotal();
result = dealsCount > 0;
if (!result)
{
return result;
}
//
static CDealInfo mDealInfo;
//
result = mDealInfo.SelectByIndex(index);
if (!result)
{
//
return result;
}
//
// Reading Order Info ...
swap = mDealInfo.Swap();
magic = mDealInfo.Magic();
order = mDealInfo.Order();
ticket = mDealInfo.Ticket();
time = mDealInfo.Time();
price = mDealInfo.Price();
symbol = mDealInfo.Symbol();
profit = mDealInfo.Profit();
volume = mDealInfo.Volume();
comment = mDealInfo.Comment();
positionId = mDealInfo.PositionId();
entry = mDealInfo.Entry();
commission = mDealInfo.Commission();
type = mDealInfo.DealType();
reason = (ENUM_DEAL_REASON)HistoryDealGetInteger(
ticket,
DEAL_REASON);
//
period = ExtractPeriod(comment);
provider = ExtractProvider(comment);
//
result = IsValid();
//
return result;
}
//
// Tools ...
//
// Cleanup ...
void Clean()
{
//
magic = 0;
positionId = 0;
ticket = 0;
order = 0;
time = 0;
price = 0;
profit = 0;
swap = 0;
commission = 0;
volume = 0;
//
symbol = NULL;
comment = NULL;
provider = NULL;
//
type = NULL;
entry = NULL;
period = NULL;
reason = NULL;
//
ZeroMemory(this);
}
//
// Validate ...
bool IsValid()
{
//
bool result = false;
//
result =
//
IsSpecifiedValid(symbol) &&
NotEmpty(ticket) &&
NotEmpty(positionId)
//
;
//
return result;
}
//
// Calculate Age ...
int GetAge(
ENUM_TIMEFRAMES mPeriod // Calculate Age based on this period
)
{
return GetXAge(this, mPeriod);
}
//
// Check this instance is Same os Given instance or not ...
bool IsSameAs(
const XDeal &value // instance for Compare
)
{
//
bool result = false;
//
result =
//
type == value.type &&
magic == value.magic &&
entry == value.entry &&
reason == value.reason &&
ticket == value.ticket &&
volume == value.volume &&
symbol == value.symbol &&
provider == value.provider &&
positionId == value.positionId
//
;
//
return result;
}
//
// Find index in a Collection ...
int FindIndex(
XDeal &values[] // Collection to Find
)
{
//
return FindXIndex(
this,
values
//
);
}
//
// Check Items Passed Specific Filters or not ...
bool IsFiltersPassed(
string mSymbol = NULL, // Trading Symbol
string mProvider = NULL, // Signal Provider
ENUM_TIMEFRAMES mPeriod = NULL, // Trading Timeframe
ENUM_DEAL_TYPE mType = NULL, // Deal Type
ENUM_DEAL_ENTRY mEntry = NULL, // Deal Entry
ENUM_DEAL_REASON mReason = NULL, // Deal Reason
ulong mMagic = NULL, // Magic Number
bool mFilterByMagic = true // Get Only Self Open Positions
)
{
//
bool result = false;
//
result =
//
// Magic Filter ...
IsMagicFilterPassed(
mMagic,
mFilterByMagic,
this
//
)
//
&&
//
// Symbol Filter ...
IsSymbolFilterPassed(
mSymbol,
this
//
)
//
&&
//
// Provider Filter ...
IsProviderFilterPassed(
mProvider,
this
//
)
//
&&
//
// Period Filter ...
IsPeriodFilterPassed(
mPeriod,
this
//
)
//
&&
//
// Type Filter ...
IsTypeFilterPassed(
mType,
this
//
)
//
&&
//
// Entry Filter ...
IsEntryFilterPassed(
mEntry,
this
//
)
//
&&
//
// Reason Filter ...
IsReasonFilterPassed(
mReason,
this
//
)
//
;
//
return result;
}
};
//
// Model OnTrade Event Handler Result on XCTrade Class ...
struct XOnTradeHandlerState
{
//
bool hasNewDeal;
int newDeals;
//
bool hasNewOrder;
int newOrders;
//
bool hasNewPosition;
int newPositions;
//
bool hasNewHistoryOrder;
int newHistoryOrders;
//
// Constructor ...
XOnTradeHandlerState()
{
Clean();
}
//
// Tools ...
//
// Cleanup ...
void Clean()
{
//
hasNewDeal = false;
hasNewOrder = false;
hasNewPosition = false;
hasNewHistoryOrder = false;
//
newDeals = 0;
newOrders = 0;
newPositions = 0;
newHistoryOrders = 0;
//
ZeroMemory(this);
}
//
// Validate ...
bool IsValid()
{
//
bool result = false;
//
result =
//
(
//
hasNewDeal
? newDeals > 0
: true
//
)
//
&&
//
(
//
hasNewOrder
? newOrders > 0
: true
//
)
//
&&
//
(
//
hasNewPosition
? newPositions > 0
: true
//
)
//
&&
//
(
//
hasNewHistoryOrder
? newHistoryOrders > 0
: true
//
)
//
;
//
return result;
}
};
//
// an Structure for Describe aTrading Session ...
struct XTradeSession
{
//
// Properties ...
string start; // Session Start Time (hh:mm)
string end; // Session End Time (hh:mm)
string name; // Session Name
//
// Constructor ...
XTradeSession()
{
Clean();
}
//
// Tools ...
//
// Cleanup ...
void Clean()
{
//
end = NULL;
name = NULL;
start = NULL;
//
ZeroMemory(this);
}
//
// Validate ...
bool IsValid()
{
//
bool result = false;
//
result = IsSpecifiedValid(start) &&
IsSpecifiedValid(end);
if (!result)
{
return result;
}
//
return result;
}
//
// Check Session is Active or Not ...
bool IsActive(datetime time = NULL)
{
//
bool result = false;
//
time = NormalizeTime(time);
//
result = IsValid();
if (!result)
{
return result;
}
//
result = IsTimeInRange(
time,
start,
end //
);
//
return result;
}
};
//
// an Structure for Describe an Specified Symbols
// Trading Sessions ...
struct XSymbolTradeConfig
{
//
// Propeties ...
//
int longs; // All Long Trades
int shorts; // All Short Trades
int trades; // All Trades
int losses; // All Loosing Trades
int profits; // All Winning Trades
string name; // Provider Name
string symbol; // Trading Symbol
int managedSLs; // Managed SL(s)
int managedTPs; // Managed TP(s)
int managedTrades; // Managed Trades
int maxAllowedTPs; // Max Allowed TP(s) in Restrictions Period
int maxAllowedSLs; // Max Allowed SL(s) in Restrictions Period
int maxAllowedTrades; // Max Allowed Trades in Restrictions Period
datetime managedStart; // Managed Start Time
double managedBalance; // Managed Start Balance
double managedProfits; // Managed Profit(s)
ENUM_TIMEFRAMES period; // Trading Period
int maxAllowedPositions; // Max Allowed Same Time Trades
double maxAllowedSpread; // Max Allowed Spread For Trade
bool isForceCloseAtTime; // a Flag for Determines Force Closed or not
XTradeSession sessions[]; // Trading Sessions
string closeAllOpenTradesAt; // Close All Open Trades per Day At Specified Time
int restrictionsPeriodMultiplier; // Specified Restrictions Period Multiplier
ENUM_XTRADE_RESTRICTION_PERIOD restrictionsPeriod; // Trade Restrictions Period
//
// Constructor ...
XSymbolTradeConfig()
{
Clean();
}
//
// Tools ...
//
// Cleanup ...
void Clean()
{
//
name = NULL;
symbol = NULL;
period = NULL;
SpecifiedClean(sessions);
//
longs = 0;
shorts = 0;
trades = 0;
losses = 0;
profits = 0;
//
managedStart = NULL;
//
managedSLs = 0;
managedTPs = 0;
managedTrades = 0;
//
managedBalance = 0;
managedProfits = 0;
//
maxAllowedTPs = 0;
maxAllowedSLs = 0;
maxAllowedTrades = 0;
maxAllowedSpread = 25;
maxAllowedPositions = 5;
closeAllOpenTradesAt = "";
isForceCloseAtTime = false;
restrictionsPeriod = XTRADE_RESTRICATION_NONE;
//
ZeroMemory(this);
}
/**
* Initial ...
*
* @param _symbol: Trading Symbol
* @param _period: Trading Period
* @param _sessionsDescriptor: Sessions Description
* @param _maxAllowedSpread: Max Allowed Spread for Open Trade
* @param _maxAllowedPositions: Max Allowed Same Time Position
* @param _restrictionsDescriptor: Restrictions Descriptor
*
* @return ( bool )
*/
bool Init(
string _name,
string _symbol = NULL,
ENUM_TIMEFRAMES _period = NULL,
string _sessionsDescriptor = NULL,
double _maxAllowedSpread = 25,
int _maxAllowedPositions = 5,
string _restrictionsDescriptor = NULL //
)
{
//
bool result = false;
//
// Normalize Symbol ...
_symbol = NormalizeSymbol(_symbol);
_period = NormalizePeriod(_period);
//
name = _name;
symbol = _symbol;
period = _period;
maxAllowedSpread = _maxAllowedSpread;
maxAllowedPositions = _maxAllowedPositions;
//
// Parse Sessions ...
ParseSessions(_sessionsDescriptor);
//
// Parse Restrictions ...
ParseRestrictions(_restrictionsDescriptor);
//
// Check Validation ...
result = IsValid();
//
return result;
}
//
// Check Same ...
bool IsSame(XSymbolTradeConfig &dest)
{
//
bool result = false;
//
// Validate ...
result = IsValid() &&
dest.IsValid() &&
name == dest.name &&
symbol == dest.symbol &&
period == dest.period;
//
return result;
}
//
// Validate ...
bool IsValid()
{
//
bool result = false;
//
result =
IsSpecifiedValid(name) &&
IsSpecifiedValid(symbol) &&
IsSpecifiedValid(period);
//
return result;
}
//
// Check Allow Trade in Active Sessions ...
bool CanTrade(datetime time = NULL)
{
//
bool result = false;
//
// Normalize Args ...
time = NormalizeTime(time);
//
// Validating ...
result = IsValid();
if (!result)
{
return result;
}
//
// if there is not any defined sessions for Symbol ...
// it's allow Trading in all times ...
result = !HasChild(sessions);
if (result)
{
return result;
}
//
// Detect an Active Session ...
int count = ArraySize(sessions);
for (int i = 0; i < count; i++)
{
//
result = sessions[i].IsActive(time);
if (result)
{
break;
}
}
//
return result;
}
//
// Checking Restrictions ...
bool IsRestricted(datetime time = NULL)
{
//
bool result = false;
//
// Normalize Time ...
time = NormalizeTime(time);
//
// Check Has Restrictions ...
bool has = HasRestrictions(restrictionsPeriod);
result = !has;
if (result)
{
return result;
}
//
// Check Restrictions Time ...
has = IsSpecifiedValid(managedStart) &&
time <= managedStart;
result = !has;
if (result)
{
return result;
}
//
// Validate Restrictions Timing ...
// Check Restrictions ...
//
bool isTPAllowed = maxAllowedTPs == 0
? true
: managedTPs < maxAllowedTPs;
bool isSLAllowed = maxAllowedSLs == 0
? true
: managedSLs < maxAllowedSLs;
bool isTradeAllowed = maxAllowedTrades == 0
? true
: managedTrades < maxAllowedTrades;
//
result = isTPAllowed &&
isSLAllowed &&
isTradeAllowed;
if (result)
{
return result;
}
//
// Check Restrictions Reset ...
HandleRestrictions();
//
return result;
}
//
// Parse Sessions ...
void ParseSessions(string descriptor)
{
//
// Validate ...
if (!IsSpecifiedValid(descriptor))
{
return;
}
//
bool has = false;
string _sessions[];
int sessionsCount = 0;
//
// Extract Per Symbol Sessions ...
sessionsCount = SplitContent(
_sessions,
descriptor,
"," //
);
//
// Try to Extract Start and End Times Series ...
has = IsValidSize(sessionsCount);
if (!has)
{
return;
}
//
// Iterate Sessions ...
for (int i = 0; i < sessionsCount; i++)
{
//
// Ignore unused Cases and Extracts only Content ...
string iSessionDescriptorStr = ExtractString(_sessions[i]);
has = IsSpecifiedValid(iSessionDescriptorStr);
if (has)
{
//
// Extract Session Descriptor Data ...
string parts[];
int partsCount = SplitContent(
parts,
iSessionDescriptorStr,
"_" //
);
has = IsValidSize(partsCount) && partsCount == 3;
if (has)
{
//
string iName = parts[0];
string iStart = parts[1];
string iEnd = parts[2];
has = IsSpecifiedValid(iName) &&
IsSpecifiedValid(iStart) &&
IsSpecifiedValid(iEnd);
if (has)
{
//
// Set Active Session Per Symbols ...
XTradeSession session;
//
session.end = iEnd;
session.name = iName;
session.start = iStart;
//
AddRef(
session,
sessions //
);
//
session.Clean();
}
}
//
SpecifiedClean(parts);
}
}
//
SpecifiedClean(_sessions);
}
//
// Parse Restrictions ...
void ParseRestrictions(string descriptor)
{
//
// Validate ...
if (!IsSpecifiedValid(descriptor))
{
return;
}
//
// Extract Content ...
descriptor = ExtractString(descriptor);
if (!IsSpecifiedValid(descriptor))
{
return;
}
//
int count = 0;
bool has = false;
string iRestrictionsParts[];
//
// Extract Parts ...
count = SplitContent(
iRestrictionsParts,
descriptor,
"," //
);
has = IsValidSize(count);
if (!has)
{
//
// Default Restrictions ...
ApplyDefaultRestrictions();
return;
}
//
// Try To Extract Required Parts ...
bool hasRestrictionsPeriod = count >= 1;
bool hasRestrictionsPeriodMultiplier = count >= 2;
bool hasMaxAllowedTPs = count >= 3;
bool hasMaxAllowedSLs = count >= 4;
bool hasMaxAllowedTrades = count >= 5;
bool hasCloseAllOpenTradesAt = count >= 6;
//
// Restrictions Period ...
restrictionsPeriod =
hasRestrictionsPeriod
? ToXRestrictionPeriod(Trim(iRestrictionsParts[0]))
: XTRADE_RESTRICATION_NONE;
//
// Restrictions Period Multiplier ...
restrictionsPeriodMultiplier =
hasRestrictionsPeriodMultiplier
? (int)(Trim(iRestrictionsParts[1]))
: 1;
//
// Max Allowed TPs ...
maxAllowedTPs =
hasMaxAllowedTPs
? (int)(Trim(iRestrictionsParts[2]))
: 0;
//
// Max Allowed SLs ...
maxAllowedSLs =
hasMaxAllowedSLs
? (int)(Trim(iRestrictionsParts[3]))
: 0;
//
// Max Allowed Trades ...
maxAllowedTrades =
hasMaxAllowedTrades
? (int)(Trim(iRestrictionsParts[4]))
: 0;
//
// Close All Open Trades At ...
closeAllOpenTradesAt =
hasCloseAllOpenTradesAt
? Trim(iRestrictionsParts[5])
: NULL;
}
//
// Apply Default Restrictions ...
void ApplyDefaultRestrictions()
{
//
maxAllowedTPs = 0;
maxAllowedSLs = 0;
maxAllowedTrades = 0;
closeAllOpenTradesAt = NULL;
restrictionsPeriod = XTRADE_RESTRICATION_NONE;
}
//
// Handle Restrictions ...
void HandleRestrictions(datetime time = NULL)
{
//
// Normalize Time ...
time = NormalizeTime(time);
//
// Check Restrictions Requirements ...
bool has = HasRestrictions(restrictionsPeriod) &&
restrictionsPeriodMultiplier >= 1;
if (!has)
{
return;
}
//
// Check Restrictions Start ...
has = IsSpecifiedValid(managedStart);
if (!has)
{
managedStart = time;
}
//
// Calculating Expiration Date based on Config ...
int expiredDelay = restrictionsPeriodMultiplier * GetXRestrictionsPeriodSeconds(restrictionsPeriod);
datetime expiredDate = (datetime)(TimeToSeconds(managedStart) + expiredDelay);
//
// Check Expiration ...
has = time >= expiredDate;
if (!has)
{
return;
}
//
ResetRestrictions();
}
//
// Reset Restrictions ...
void ResetRestrictions()
{
//
managedSLs = 0;
managedTPs = 0;
managedTrades = 0;
managedBalance = 0;
managedProfits = 0;
managedStart = TimeCurrent();
}
//
};
//
// an Structure to Describe a Trade ...
struct XTradeInfo
{
//
// Props ...
double swap;
double profit;
XSignal signal;
ulong positionID;
double commission;
string conditions;
double bullishScore;
double bearishScore;
ENUM_XTRADE_FINALIZATION finalize;
//
datetime signaledAt;
datetime executedAt;
datetime finalizedAt;
//
// Constructor ...
XTradeInfo()
{
Clean();
}
//
// Tools ...
/**
* Cleanup Model ...
*/
void Clean()
{
//
swap = 0;
profit = 0;
signal.Clean();
commission = 0;
positionID = 0;
conditions = NULL;
bullishScore = 0;
bearishScore = 0;
finalize = XTRADE_FINAL_NONE;
//
signaledAt = NULL;
executedAt = NULL;
finalizedAt = NULL;
//
ZeroMemory(this);
}
/**
* Check Has Signal ...
*
* @return ( bool )
*/
bool HasSignal()
{
//
bool result = false;
//
result = signal.IsValid();
//
return result;
}
/**
* Check Signal Executed or Not ...
*
* @return ( bool )
*/
bool IsExecuted()
{
//
bool result = false;
//
result = positionID > 0;
//
return result;
}
/**
* Check a Trade is Finalized or not ...
*
* @return ( bool )
*/
bool IsFinalized()
{
//
bool result = false;
//
result = HasSignal() &&
IsExecuted() &&
finalize != XTRADE_FINAL_NONE;
//
return result;
}
/**
* Generate Summary Info ...
*
* @return ( string )
*/
string Summary()
{
//
string result = NULL;
//
result =
//
ToXString("Swap", swap) +
ToXString("Profit", profit) +
ToXString("Commission", commission) +
ToXString("Finalize", ToXString(finalize)) +
ToXString("PositionID", positionID) +
ToXString("----------------") + "\n" +
ToXString("Signaled At", ToFormatString(signaledAt)) +
ToXString("Executed At", ToFormatString(executedAt)) +
ToXString("Finalized At", ToFormatString(finalizedAt))
//
;
//
return result;
}
/**
* Get Data Collection File Name ...
*
* @return ( string )
*/
string GetFileName()
{
//
string result = NULL;
//
bool hasSignal = HasSignal();
bool isExecuted = IsExecuted();
bool isFinalized = IsFinalized();
if (!hasSignal && !isExecuted && !isFinalized)
{
return result;
}
//
result =
//
signal.symbol + "\\" +
ToString(signal.type) + "\\" +
(profit >= 0 ? "Profit" : "Loss") + "\\" +
ToString(positionID) + "_" +
ToString(signal.period) + "_" +
ToFormatString(signaledAt)
//
;
//
return result;
}
/**
* Converts Model to String Representation ...
*
* @param onlySignals: Boolean, Specified Represent Only Signal or not ...
*
* @return ( string )
*/
string ToString(
bool includeSummary = true,
bool includeSignal = true,
bool includeConditions = true //
)
{
//
string result = NULL;
//
// Generating Model Summary ...
string summary = Summary();
//
// Generating Signal Summary ...
string signalSummary = signal.ToString();
//
if (includeSummary)
{
//
result +=
ToXString("----------------") + "\n" +
ToXString("Summary: ") + "\n" +
ToXString("----------------") + "\n" +
summary + "\n";
}
//
if (includeSignal)
{
//
result +=
ToXString("----------------") + "\n" +
ToXString("Signal: ") + "\n" +
ToXString("----------------") + "\n" +
signalSummary + "\n";
}
//
if (includeConditions)
{
//
result +=
ToXString("----------------") + "\n" +
ToXString("Conditions: ") + "\n" +
ToXString("----------------") + "\n" +
conditions + "\n";
}
//
return result;
}
string GetConditionsString()
{
//
string result = NULL;
//
string conditionsStr =
conditions;
string condParts[];
int condPartsCount = SplitContent(
condParts,
conditionsStr,
"\n" //
);
if (IsValidSize(condPartsCount))
{
//
conditionsStr = NULL;
while (HasChild(condParts))
{
//
string iStr = condParts[0];
ArrayRemove(
condParts,
0,
1 //
);
//
bool isLast = !HasChild(condParts);
//
bool isCond = Contains(
"is",
iStr,
false //
);
if (isCond)
{
//
string iParts[];
int iPartsCount = SplitContent(
iParts,
iStr,
":" //
);
if (iPartsCount == 2)
{
//
string iVal = iParts[1];
StringTrimLeft(iVal);
StringTrimRight(iVal);
bool isPassed = ToBoolean(iVal);
conditionsStr += (isPassed ? "" : "!") + "conditions." + iParts[0] + (!isLast ? " &&" : "") + "\n";
}
}
}
SpecifiedClean(condParts);
}
else
{
conditionsStr = NULL;
}
//
result =
"(" + "\n" +
"\\" + "\\" + " " + ToXString("Type", ToXString(signal.type)) +
"\\" + "\\" + " " + ToXString("Profit", profit) +
"\\" + "\\" + " " + ToXString("Finalize", ToXString(finalize)) +
"\\" + "\\" + " " + ToXString("PositionID", positionID) +
"\\" + "\\" + " " + ToXString("----------------") + "\n" +
"\\" + "\\" + " " + ToXString("Signaled At", ToFormatString(signaledAt)) +
"\\" + "\\" + " " + ToXString("Executed At", ToFormatString(executedAt)) +
"\\" + "\\" + " " + ToXString("Finalized At", ToFormatString(finalizedAt)) +
"\\" + "\\" + " " + ToXString("----------------") + "\n" +
"\\" + "\\" + " " + ToXString("Scores:") + "\n" +
"\\" + "\\" + " " + ToXString("Bullish", bullishScore) +
"\\" + "\\" + " " + ToXString("Bearish", bearishScore) +
"\\" + "\\" + " " + ToXString("----------------") + "\n" +
conditionsStr +
(IsValid(conditionsStr) ? "" : "") +
") && ";
//
return result;
}
};
//
// TypeDefs ...
//
typedef void (*TOnSignal)(XSignal &signal);
//
typedef bool (*TCanAnalyse)(
string _symbol,
ENUM_TIMEFRAMES _period,
datetime _time //
);
//
// an Event Type for Notify Guard Triggered ...
typedef void (*TOnGuarded)(
ENUM_X_GUARD_ACTIONS guard,
XPosition &positions[]);
//
typedef int (*TCheckForGuard)(
XGuard &guards[],
XPosition &positions[],
int barIndex = 0 //
);
//
typedef void (*TOnDealsChanged)(int count);
//
typedef void (*TOnOrdersChanged)(int count);
//
typedef void (*TOnPositionsChanged)(int count);
//
typedef void (*TOnStopLoss)(const XDeal &deal);
typedef void (*TOnTakeProfit)(const XDeal &deal);
//
typedef void (*TOnTradeStateChanged)(const XOnTradeHandlerState &state);
//
typedef void (*TOnForceClose)(
const ulong ticket,
const XPosition &position,
const string comment //
);
//
typedef void (*TOnPartialClose)(
const ulong ticket,
const double profit,
const string comment //
);
//
typedef void (*TOnModify)(
const ulong ticket,
const double profit,
const string comment //
);
//
// Classes ...
//
// Tools ...
//
bool IsValid(ENUM_X_ORDER_MODES value)
{
return value != X_ORDER_MODE_NOTHING;
}
//
bool IsXBullish(ENUM_POSITION_TYPE type)
{
return type == POSITION_TYPE_BUY;
}
//
bool IsXBullish(ENUM_X_POSITION_TYPES type)
{
return type == X_POSITION_TYPE_LONG;
}
//
bool IsXBearish(ENUM_POSITION_TYPE type)
{
return type == POSITION_TYPE_SELL;
}
//
bool IsXBearish(ENUM_X_POSITION_TYPES type)
{
return type == X_POSITION_TYPE_SHORT;
}
//
// Ages ...
//
// Retrieve a Position Age ...
int GetAge(
XSignal &signal, // Selected Signal ...
ENUM_TIMEFRAMES period = NULL // Dest Time Frame ...
)
{
//
int result = -1;
//
if (period == NULL)
{
period = _Period;
}
//
result = iBarShift(
signal.symbol,
period,
signal.time);
//
return result;
}
int GetXAge(
XSignal &signal, // Selected Signal ...
ENUM_TIMEFRAMES period = NULL // Dest Time Frame ...
)
{
return GetAge(signal, period);
}
//
// Retrieve a Position Age ...
int GetAge(
XPosition &position, // Selected Position ...
ENUM_TIMEFRAMES period = NULL // Dest Time Frame ...
)
{
//
int result = -1;
//
if (period == NULL)
{
period = _Period;
}
//
result = iBarShift(
position.symbol,
period,
position.openAt);
//
return result;
}
int GetXAge(
XPosition &position, // Selected Position ...
ENUM_TIMEFRAMES period = NULL // Dest Time Frame ...
)
{
return GetAge(position, period);
}
//
// Retrieve an Order Age ...
int GetAge(
XOrder &order, // Selected Order ...
ENUM_TIMEFRAMES period = NULL // Dest Time Frame ...
)
{
//
int result = -1;
//
if (period == NULL)
{
period = _Period;
}
//
result = iBarShift(
order.symbol,
period,
order.setupAt);
//
return result;
}
int GetXAge(
XOrder &order, // Selected Order ...
ENUM_TIMEFRAMES period = NULL // Dest Time Frame ...
)
{
return GetAge(order, period);
}
//
// Retrieve a Deal Age ...
int GetAge(
XDeal &deal, // Selected Deal ...
ENUM_TIMEFRAMES period = NULL // Dest Time Frame ...
)
{
//
int result = -1;
//
if (period == NULL)
{
period = _Period;
}
//
result = iBarShift(
deal.symbol,
period,
deal.time);
//
return result;
}
int GetXAge(
XDeal &deal, // Selected Deal ...
ENUM_TIMEFRAMES period = NULL // Dest Time Frame ...
)
{
return GetAge(deal, period);
}
//
// Get Oldest Deal ...
int GetOldest(
XDeal &item, // Hold Result ...
XDeal &items[] // Source Array ...
)
{
//
int result = -1;
//
int itemsCount = ArraySize(items);
if (itemsCount <= 0)
{
return result;
}
//
int tmpAge = 0;
XDeal tmpItem;
for (int i = 0; i < itemsCount; i++)
{
//
XDeal iItem = items[i];
//
int iAge = GetAge(iItem);
if (iAge > 0 &&
(tmpAge == 0 || tmpAge < iAge))
{
//
tmpAge = iAge;
tmpItem = iItem;
}
}
//
if (tmpAge > 0)
{
//
result = tmpAge;
item = tmpItem;
}
//
return result;
}
int GetXOldest(
XDeal &item, // Hold Result ...
XDeal &items[] // Source Array ...
)
{
return GetOldest(item, items);
}
//
// Get Youngest Deal ...
int GetYoungest(
XDeal &item, // Hold Result ...
XDeal &items[] // Source Array ...
)
{
//
int result = -1;
//
int itemsCount = ArraySize(items);
if (itemsCount <= 0)
{
return result;
}
//
int tmpAge = 0;
XDeal tmpItem;
for (int i = 0; i < itemsCount; i++)
{
//
XDeal iItem = items[i];
//
int iAge = GetAge(iItem);
if (iAge > 0 &&
(tmpAge == 0 || tmpAge > iAge))
{
//
tmpAge = iAge;
tmpItem = iItem;
}
}
//
if (tmpAge > 0)
{
//
result = tmpAge;
item = tmpItem;
}
//
return result;
}
int GetXYoungest(
XDeal &item, // Hold Result ...
XDeal &items[] // Source Array ...
)
{
return GetYoungest(item, items);
}
//
// Get Oldest Order ...
int GetOldest(
XOrder &item, // Hold Result ...
XOrder &items[] // Source Array ...
)
{
//
int result = -1;
//
int itemsCount = ArraySize(items);
if (itemsCount <= 0)
{
return result;
}
//
int tmpAge = 0;
XOrder tmpItem;
for (int i = 0; i < itemsCount; i++)
{
//
XOrder iItem = items[i];
//
int iAge = GetAge(iItem);
if (iAge > 0 &&
(tmpAge == 0 || tmpAge < iAge))
{
//
tmpAge = iAge;
tmpItem = iItem;
}
}
//
if (tmpAge > 0)
{
//
result = tmpAge;
item = tmpItem;
}
//
return result;
}
int GetXOldest(
XOrder &item, // Hold Result ...
XOrder &items[] // Source Array ...
)
{
return GetOldest(item, items);
}
//
// Get Youngest Order ...
int GetYoungest(
XOrder &item, // Hold Result ...
XOrder &items[] // Source Array ...
)
{
//
int result = -1;
//
int itemsCount = ArraySize(items);
if (itemsCount <= 0)
{
return result;
}
//
int tmpAge = 0;
XOrder tmpItem;
for (int i = 0; i < itemsCount; i++)
{
//
XOrder iItem = items[i];
//
int iAge = GetAge(iItem);
if (iAge > 0 &&
(tmpAge == 0 || tmpAge > iAge))
{
//
tmpAge = iAge;
tmpItem = iItem;
}
}
//
if (tmpAge > 0)
{
//
result = tmpAge;
item = tmpItem;
}
//
return result;
}
int GetXYoungest(
XOrder &item, // Hold Result ...
XOrder &items[] // Source Array ...
)
{
return GetYoungest(item, items);
}
//
// Get Oldes Position ...
int GetOldest(
XPosition &item, // Hold Result ...
XPosition &items[] // Source Array ...
)
{
//
int result = -1;
//
int itemsCount = ArraySize(items);
if (itemsCount <= 0)
{
return result;
}
//
int tmpAge = 0;
XPosition tmpItem;
for (int i = 0; i < itemsCount; i++)
{
//
XPosition iItem = items[i];
//
int iAge = GetAge(iItem);
if (iAge > 0 &&
(tmpAge == 0 || tmpAge < iAge))
{
//
tmpAge = iAge;
tmpItem = iItem;
}
}
//
if (tmpAge > 0)
{
//
result = tmpAge;
item = tmpItem;
}
//
return result;
}
int GetXOldest(
XPosition &item, // Hold Result ...
XPosition &items[] // Source Array ...
)
{
return GetOldest(item, items);
}
//
// Get Youngest Position ...
int GetYoungest(
XPosition &item, // Hold Result ...
XPosition &items[] // Source Array ...
)
{
//
int result = -1;
//
int itemsCount = ArraySize(items);
if (itemsCount <= 0)
{
return result;
}
//
int tmpAge = 0;
XPosition tmpItem;
for (int i = 0; i < itemsCount; i++)
{
//
XPosition iItem = items[i];
//
int iAge = GetAge(iItem);
if (iAge >= 0 &&
(tmpAge == 0 || tmpAge > iAge))
{
//
tmpAge = iAge;
tmpItem = iItem;
}
}
//
if (tmpAge >= 0)
{
//
result = tmpAge;
item = tmpItem;
}
//
return result;
}
int GetXYoungest(
XPosition &item, // Hold Result ...
XPosition &items[] // Source Array ...
)
{
return GetYoungest(item, items);
}
//
int FindMaxProfitIndex(
XPosition &positions[] // Position Collection
)
{
//
int result = -1;
//
int positionsCount = ArraySize(positions);
if (!IsValidSize(positionsCount))
{
return result;
}
//
double max = 0;
for (int i = 0; i < positionsCount; i++)
{
//
XPosition iPosition = positions[i];
if (iPosition.profit <= 0)
{
continue;
}
//
if (max == 0 ||
max < iPosition.profit)
{
//
result = i;
max = iPosition.profit;
}
}
//
return result;
}
//
int FindMinProfitIndex(
XPosition &positions[] // Position Collection
)
{
//
int result = -1;
//
int positionsCount = ArraySize(positions);
if (!IsValidSize(positionsCount))
{
return result;
}
//
double min = 0;
for (int i = 0; i < positionsCount; i++)
{
//
XPosition iPosition = positions[i];
if (iPosition.profit <= 0)
{
continue;
}
//
if (min == 0 ||
min > iPosition.profit)
{
//
result = i;
min = iPosition.profit;
}
}
//
return result;
}
//
int ExtractInProfitPositions(
XPosition &positions[], // Position Collection
XPosition &inProfits[] // Result
)
{
//
int result = 0;
//
Clean(inProfits);
//
int positionsCount = ArraySize(positions);
if (!IsValidSize(positionsCount))
{
return result;
}
//
for (int i = 0; i < positionsCount; i++)
{
//
XPosition iPosition = positions[i];
//
if (iPosition.profit > 0)
{
//
AddRef(
iPosition,
inProfits //
);
}
}
//
result = ArraySize(inProfits);
//
return result;
}
//
int FindMaxDrawdownIndex(
XPosition &positions[] // Position Collection
)
{
//
int result = -1;
//
int positionsCount = ArraySize(positions);
if (!IsValidSize(positionsCount))
{
return result;
}
//
double max = 0;
for (int i = 0; i < positionsCount; i++)
{
//
XPosition iPosition = positions[i];
if (iPosition.profit >= 0)
{
continue;
}
//
if (max == 0 ||
MathAbs(max) < MathAbs(iPosition.profit))
{
//
result = i;
max = iPosition.profit;
}
}
//
return result;
}
//
int FindMinDrawdownIndex(
XPosition &positions[] // Position Collection
)
{
//
int result = -1;
//
int positionsCount = ArraySize(positions);
if (!IsValidSize(positionsCount))
{
return result;
}
//
double min = 0;
for (int i = 0; i < positionsCount; i++)
{
//
XPosition iPosition = positions[i];
if (iPosition.profit >= 0)
{
continue;
}
//
if (min == 0 ||
min > iPosition.profit)
{
//
result = i;
min = iPosition.profit;
}
}
//
return result;
}
//
int ExtractInDrawdownPositions(
XPosition &positions[], // Position Collection
XPosition &inDradowns[] // Result
)
{
//
int result = 0;
//
Clean(inDradowns);
//
int positionsCount = ArraySize(positions);
if (!IsValidSize(positionsCount))
{
return result;
}
//
for (int i = 0; i < positionsCount; i++)
{
//
XPosition iPosition = positions[i];
//
if (iPosition.profit < 0)
{
//
AddRef(
iPosition,
inDradowns //
);
}
}
//
result = ArraySize(inDradowns);
//
return result;
}
//
// Check Filters ...
//
// Magic Filter ...
template <typename T>
bool IsMagicFilterPassed(
ulong magic,
bool filterByMagic,
T &item
//
)
{
//
return !filterByMagic
? true
: !NotEmpty(magic)
? false
: magic == item.magic;
}
//
// Symbol Filter ...
template <typename T>
bool IsSymbolFilterPassed(
string symbol,
T &item
//
)
{
//
return !IsValid(symbol)
? true
: symbol == item.symbol;
}
//
// Provider Filter ...
template <typename T>
bool IsProviderFilterPassed(
string provider,
T &item
//
)
{
//
return !IsValid(provider)
? true
: provider == item.provider ||
Contains(provider, item.provider);
}
//
// Period Filter ...
template <typename T>
bool IsPeriodFilterPassed(
ENUM_TIMEFRAMES period,
T &item
//
)
{
//
return !IsValid(period)
? true
: period == item.period;
}
//
// Type Filter ...
template <typename T>
bool IsTypeFilterPassed(
ENUM_POSITION_TYPE type,
T &item
//
)
{
//
bool result = type == item.type;
//
return result;
}
template <typename T>
bool IsTypeFilterPassed(
ENUM_X_POSITION_TYPES type,
T &item
//
)
{
//
bool result = type == NULL || type == X_POSITION_TYPE_ALL
? true
: ((type == X_POSITION_TYPE_LONG && ((int)item.type == (int)POSITION_TYPE_BUY || (int)item.type == (int)ORDER_TYPE_BUY)) ||
(type == X_POSITION_TYPE_SHORT && ((int)item.type == (int)POSITION_TYPE_SELL || (int)item.type == (int)ORDER_TYPE_SELL)));
//
return result;
}
template <typename T>
bool IsTypeFilterPassed(
ENUM_ORDER_TYPE type,
T &item
//
)
{
//
return type == NULL
? true
: type == item.type;
}
template <typename T>
bool IsTypeFilterPassed(
ENUM_DEAL_TYPE type,
T &item
//
)
{
//
return type == NULL
? true
: type == item.type;
}
//
// Mode Filter ...
template <typename T>
bool IsModeFilterPassed(
ENUM_X_ORDER_MODES mode,
T &item
//
)
{
//
return mode == NULL
? true
: mode == item.mode;
}
//
// Entry Filter ...
template <typename T>
bool IsEntryFilterPassed(
ENUM_DEAL_ENTRY entry,
T &item
//
)
{
//
return entry == NULL
? true
: entry == item.entry;
}
//
// Reason Filter ...
template <typename T>
bool IsReasonFilterPassed(
ENUM_DEAL_REASON reason,
T &item
//
)
{
//
return reason == NULL
? true
: reason == item.reason;
}
//
// State Filter ...
template <typename T>
bool IsStateFilterPassed(
ENUM_ORDER_STATE state,
T &item
//
)
{
//
return state == NULL
? true
: state == item.state;
}
//
//
//
// Calculate Positions Profit Summary ...
double SpecifiedCalculatePositionsProfit(
XPosition &positions[] // Source
)
{
//
double result = 0;
//
int positionsCount = ArraySize(positions);
if (positionsCount <= 0)
{
return result;
}
//
for (int i = 0; i < positionsCount; i++)
{
//
XPosition iPosition = positions[i];
//
result += iPosition.profit;
}
//
return result;
}
//
// Calculate Required Profit for Hedging ...
double SpecifiedCalculateRequiredProfitForHedge(
XPosition &positions[], // Source
double mMinProfitPerTrade,
double mMinProfitPerVolumeFactor //
)
{
//
double result = 0;
//
int positionsCount = ArraySize(positions);
if (positionsCount <= 0)
{
return result;
}
//
bool isHedgingEnable = mMinProfitPerTrade > 0 && mMinProfitPerVolumeFactor > 0;
if (!isHedgingEnable)
{
return result;
}
//
for (int i = 0; i < positionsCount; i++)
{
//
XPosition iPosition = positions[i];
//
if (mMinProfitPerTrade > 0 && mMinProfitPerVolumeFactor > 0)
{
//
result +=
((iPosition.volume / mMinProfitPerVolumeFactor) *
mMinProfitPerTrade) +
(-1 * iPosition.swap);
}
}
//
return result;
}
//
bool SpecifiedIsPositionsReadyForHedge(
XPosition &positions[], // Source
double mMinProfitPerTrade,
double mMinProfitPerVolumeFactor //
)
{
//
double profit = SpecifiedCalculatePositionsProfit(positions);
double requiredProfit = SpecifiedCalculateRequiredProfitForHedge(
positions,
mMinProfitPerTrade,
mMinProfitPerVolumeFactor //
);
//
bool result = requiredProfit > 0
? profit >= requiredProfit
: profit > requiredProfit;
//
return result;
}
//
int FindCoverageDrawdownPosition(
XPosition &position, // In Drawdown Position
XPosition &inProfits[], // In Profit Positions
XPosition &coverage[], // Coverage Positons
double mMinProfitPerTrade,
double mMinProfitPerVolumeFactor //
)
{
//
int result = 0;
//
Clean(coverage);
//
if (!position.IsValid() || position.profit >= 0)
{
return result;
}
//
int inProfitsCount = ArraySize(inProfits);
if (!IsValidSize(inProfitsCount))
{
return result;
}
//
// Copy in Profits to TMP ...
XPosition tmp[];
Copy(
inProfits,
tmp //
);
//
bool isCoverPassed = false;
while (!isCoverPassed || ArraySize(tmp) > 0)
{
//
XPosition max;
int idx = FindMaxProfitIndex(tmp);
if (idx >= 0)
{
//
if (tmp[idx].profit > 0)
{
AddRef(
tmp[idx],
coverage //
);
//
ArrayRemove(
tmp,
idx,
1 //
);
}
}
//
// Check Cover Passed ...
XPosition tmpPositions[];
Copy(
coverage,
tmpPositions //
);
AddRef(
position,
tmpPositions //
);
//
double profits = SpecifiedCalculatePositionsProfit(tmpPositions);
double requiredProfit = SpecifiedCalculateRequiredProfitForHedge(
tmpPositions,
mMinProfitPerTrade,
mMinProfitPerVolumeFactor //
);
isCoverPassed = profits >= requiredProfit;
if (isCoverPassed)
{
break;
}
//
if (!isCoverPassed && ArraySize(tmp) == 0)
{
break;
}
}
//
result = ArraySize(coverage);
//
return result;
}
//
// Extract a Collection of Positions SL ...
int ExtractSLs(
XPosition &positions[],
double &sls[] //
)
{
//
int result = 0;
//
Clean(sls);
//
int positionsCount = ArraySize(positions);
if (!IsValidSize(positionsCount))
{
return result;
}
//
for (int i = 0; i < positionsCount; i++)
{
//
XPosition iPosition = positions[i];
//
if (iPosition.sl > 0)
{
//
Add(
iPosition.sl,
sls //
);
}
}
//
result = ArraySize(sls);
//
return result;
}
//
// Extract a Colletion of Positions TP ...
int ExtractTPs(
XPosition &positions[],
double &tps[] //
)
{
//
int result = 0;
//
Clean(tps);
//
int positionsCount = ArraySize(positions);
if (!IsValidSize(positionsCount))
{
return result;
}
//
for (int i = 0; i < positionsCount; i++)
{
//
XPosition iPosition = positions[i];
//
if (iPosition.tp > 0)
{
//
Add(
iPosition.tp,
tps //
);
}
}
//
result = ArraySize(tps);
//
return result;
}
//
// Retrieve String Representation ...
string ToString(ENUM_X_SIGNAL_EXECUTION_RESULT value)
{
//
string result = NULL;
//
switch (value)
{
//
case X_SIGNAL_EXECUTION_UNKNOWN:
result = "Unknown";
break;
//
case X_SIGNAL_EXECUTION_SUCCEED:
result = "Succed";
break;
//
case X_SIGNAL_EXECUTION_FAILED_SPREAD:
result = "Spread more than Max Allowed";
break;
//
case X_SIGNAL_EXECUTION_FAILED_NOT_ALLOWED:
result = "not Allowed";
break;
//
case X_SIGNAL_EXECUTION_FAILED_NO_EQUITY:
result = "No Equity for Trade";
break;
//
case X_SIGNAL_EXECUTION_FAILED_PRICE_ERROR:
result = "Price Error";
break;
//
case X_SIGNAL_EXECUTION_FAILED_PREV_PROFIT_ERROR:
result = "Previous Position Profit not Passed for Accept Next";
break;
//
case X_SIGNAL_EXECUTION_FAILED_MAX_REACHED:
result = "Max Allowed Positions Reached";
break;
//
case X_SIGNAL_EXECUTION_FAILED_DELAY_NOT_PASSED:
result = "Min Delay Between to Signal not Passed";
break;
//
case X_SIGNAL_EXECUTION_FAILED_INVALID_PARAMS:
result = "Invalid Params";
break;
}
//
return result;
}
//
// Converts Position Type to Order Type ...
ENUM_ORDER_TYPE ToOrderType(ENUM_POSITION_TYPE value)
{
//
bool isLong = IsLong(value);
//
ENUM_ORDER_TYPE result =
isLong
? ORDER_TYPE_BUY
: ORDER_TYPE_SELL;
//
return result;
}
ENUM_ORDER_TYPE ToOrderType(ENUM_X_POSITION_TYPES value)
{
//
ENUM_POSITION_TYPE mType =
value == X_POSITION_TYPE_SHORT
? POSITION_TYPE_SELL
: POSITION_TYPE_BUY;
//
bool isLong = IsLong(mType);
//
ENUM_ORDER_TYPE result =
isLong
? ORDER_TYPE_BUY
: ORDER_TYPE_SELL;
//
return result;
}
//
// Tagging ...
//
// Generate Specified Tag for Using in Comments ...
string GeneratePeriodTag(ENUM_TIMEFRAMES period)
{
//
string strPeriod = ToXString(period);
return Surround(
XPeriodToken,
strPeriod
//
);
}
//
// Extract Period from a Tagged string ...
ENUM_TIMEFRAMES ExtractPeriod(string value)
{
//
ENUM_TIMEFRAMES result = NULL;
//
string pStr = ParseStringSurrounded(
value,
XPeriodToken
//
);
if (!IsValid(pStr))
{
return result;
}
//
result = ToPeriod(pStr);
//
return result;
}
// Generate Specified Tag for Using in Comments ...
string GenerateProviderTag(string provider)
{
//
return Surround(
XProviderToken,
provider
//
);
}
//
// Extract Provider from a Tagged string ...
string ExtractProvider(string value)
{
//
return ParseStringSurrounded(
value,
XProviderToken
//
);
}
//
// Generate Support Comment Tag ...
string GenerateSupportTag(ulong ticket)
{
//
return Surround(
XSupportToken,
ticket
//
);
}
//
// Extract Support Positions from a Tagged string ...
ulong ExtractSupportedTicket(string value)
{
//
return ParseLongSurrounded(
value,
XSupportToken
//
);
}
//
// Extract Support ...
template <typename T>
int ExtractSupports(
T &source[],
T &dest[] // Result ...
)
{
//
int result = 0;
//
Clean(dest);
//
int sourceCount = ArraySize(source);
if (!IsValidSize(sourceCount))
{
return result;
}
//
for (int i = 0; i < sourceCount; i++)
{
//
T iSource = source[i];
//
ulong isSupport = ExtractSupportedTicket(iSource.comment) > 0;
ulong iEQMSupport = ExtractEQMSupportedTicket(iSource.comment) > 0;
if (isSupport || iEQMSupport)
{
//
AddRef(
iSource,
dest //
);
}
}
//
result = ArraySize(dest);
//
return result;
}
//
// Generate EQM Support Comment Tag ...
string GenerateEQMSupportTag(ulong ticket)
{
//
return Surround(
XEQMSupportToken,
ticket
//
);
}
//
// Extract EQM Support Positions from a Tagged string ...
ulong ExtractEQMSupportedTicket(string value)
{
//
return ParseLongSurrounded(
value,
XEQMSupportToken
//
);
}
//
bool IsSupport(string value)
{
//
bool result = false;
//
bool isSupport = ExtractSupportedTicket(value) > 0;
bool isEQMSupport = ExtractEQMSupportedTicket(value) > 0;
//
result =
//
isSupport
//
||
//
isEQMSupport
//
;
//
return result;
}
//
ulong ExtractParentTicket(string value)
{
//
ulong result = 0;
//
if (!IsSupport(value))
{
return result;
}
//
result = ExtractSupportedTicket(value);
if (result > 0)
{
return result;
}
//
result = ExtractEQMSupportedTicket(value);
//
return result;
}
//
// XRecovery ...
//
string GenerateRecoveryTag(ulong ticket)
{
//
return Surround(
XRecoveryToken,
ticket //
);
}
//
ulong ExtractRecoveredTicket(string value)
{
//
return ParseLongSurrounded(
value,
XRecoveryToken //
);
}
//
// Extract Recoveries ...
template <typename T>
int ExtractRecoveries(
T &source[],
T &dest[] // Result ...
)
{
//
int result = 0;
//
Clean(dest);
//
int sourceCount = ArraySize(source);
if (!IsValidSize(sourceCount))
{
return result;
}
//
for (int i = 0; i < sourceCount; i++)
{
//
T iSource = source[i];
//
ulong isRecovery = ExtractRecoveredTicket(iSource.comment) > 0;
if (isRecovery)
{
//
AddRef(
iSource,
dest //
);
}
}
//
result = ArraySize(dest);
//
return result;
}
//
// Extract Specified Position's Recoveries ...
int ExtractRecoveries(
ulong ticket,
XPosition &source[],
XPosition &dest[] // Result ...
)
{
//
int result = 0;
//
Clean(dest);
//
int sourceCount = ArraySize(source);
if (!IsValidSize(sourceCount))
{
return result;
}
//
for (int i = 0; i < sourceCount; i++)
{
//
XPosition iSource = source[i];
//
ulong parentTicket = ExtractRecoveredTicket(iSource.comment);
bool isRecovery = parentTicket > 0;
if (isRecovery && parentTicket == ticket)
{
//
AddRef(
iSource,
dest //
);
}
}
//
result = ArraySize(dest);
//
return result;
}
//
// SL Trails ...
//
// Extract SL Trail Level ...
int ExtractSLTrailLevel(string comment)
{
//
int result = 0;
//
if (!IsValid(comment))
{
return result;
}
//
result = ParseIntSurrounded(
comment,
XSLTrailToken
//
);
//
return result;
}
//
// Generate SL Trail Comment Tag ...
string GenerateSLTrailTag(int level)
{
//
string result = NULL;
//
if (level <= 0)
{
return result;
}
//
result = Surround(
XSLTrailToken,
level
//
);
//
return result;
}
//
// Prepare SL Trail Comment ...
string PrepareSLTrailTag(
const string comment // Original Position Comment ...
)
{
//
string result = NULL;
//
int level = 0;
result = comment;
//
// Check Comment Contains SL Trailing or not ...
int lastTrailLevel = ExtractSLTrailLevel(comment);
if (lastTrailLevel <= 0)
{
level++;
}
else
{
//
level = lastTrailLevel + 1;
string lastLevelStr = GenerateSLTrailTag(lastTrailLevel);
StringReplace(
result,
lastLevelStr,
""
//
);
}
//
// Generate level Comment ...
string levelStr = GenerateSLTrailTag(level);
result += levelStr;
//
return result;
}
//
// Count Positions from a Collection ...
void CountPositions(
const XPosition &positions[],
int &longs,
double &longProfits,
double &longVolumes, //
//
int &shorts,
double &shortProfits,
double &shortVolumes //
)
{
//
longs = 0;
longProfits = 0;
longVolumes = 0;
//
shorts = 0;
shortProfits = 0;
shortVolumes = 0;
//
int positionsCount = ArraySize(positions);
if (!IsValidSize(positionsCount))
{
return;
}
//
for (int i = 0; i < positionsCount; i++)
{
//
XPosition iPosition = positions[i];
//
bool isLong = IsLong(iPosition.type);
if (isLong)
{
//
longs++;
longProfits += iPosition.profit;
longVolumes += iPosition.volume;
}
else
{
//
shorts++;
shortProfits += iPosition.profit;
shortVolumes += iPosition.volume;
}
}
}
//
// Extract Positions based On Type ...
void ExtractPositions(
XPosition &positions[],
XPosition &longs[],
XPosition &shorts[] //
)
{
//
int count = ArraySize(positions);
if (!IsValidSize(count))
{
return;
}
//
Clean(longs);
Clean(shorts);
//
for (int i = 0; i < count; i++)
{
//
XPosition iPosition = positions[i];
//
bool isLong = IsLong(iPosition.type);
if (isLong)
{
AddRef(
iPosition,
longs //
);
}
else
{
AddRef(
iPosition,
shorts //
);
}
}
}
//
// Apply a Collection of Targets
// on Specified Signal ...
void ApplyTargetsOnSignal(
ENUM_X_DIRECTION sortingDir, // Target Sorting Direction ...
XTarget &targets[], // Required Targets ...
XSignal &signal // Destination Signal ...
)
{
//
bool has =
HasChild(targets) &&
HasDirection(sortingDir);
if (!has)
{
return;
}
//
// Sort Targets ...
ApplySortOnTargets(
sortingDir,
targets //
);
//
// Compare TP with Targets ...
int idx = IsLong(signal.type)
? GetHighest(targets)
: GetLowest(targets);
has = IsValidIndex(idx);
if (has)
{
//
// Compare TP ...
has = IsLong(signal.type)
? targets[idx].target > signal.tp
: targets[idx].target < signal.tp;
if (has)
{
//
XTarget tpTarget;
tpTarget = targets[idx];
tpTarget.actingDistance = 0;
tpTarget.target = signal.tp;
//
signal.tp = targets[idx].target;
targets[idx].actingDistance = 0;
//
ArrayRemove(
targets,
idx,
1 //
);
//
AddRef(
tpTarget,
targets //
);
}
//
// Sort Targets ...
ApplySortOnTargets(
sortingDir,
targets //
);
}
//
Copy(
targets,
signal.targets //
);
}
/**
* Select Specified Position's Related Position(s)
* for Protecting ...
*
* @param selecteds: XPosition instance reference Collection, for Holding Selected Positions ...
* @param positions: XPosition instance reference Collection, All available source Positions ...
* @param forType: ENUM_X_POSITION_TYPES member, Spcified Position Type to Select for it ...
* @param selectType: ENUM_XPOSITION_SELECT_TYPES member, Specified Positions Selecting Senario ...
*
* @return ( bool )
*/
bool SelectPosition(
XPosition &selecteds[],
XPosition &positions[],
ENUM_X_POSITION_TYPES forType,
ENUM_XPOSITION_SELECT_TYPES selectType //
)
{
//
bool result = false;
//
// Normalize Args ...
Clean(selecteds);
//
// Validate Args ...
result =
IsValid(forType) &&
HasChild(positions) &&
IsXValid(selectType);
if (!result)
{
return result;
}
//
// Extract Separate Type of Positions ...
//
int idx = -1;
bool has = false;
XPosition iPosition;
//
bool isLong = IsLong(forType);
bool isShort = IsShort(forType);
int count = ArraySize(positions);
//
XPosition samePositions[];
XPosition oppositPositions[];
XPosition inProfitPositions[];
XPosition inDrawdownPositions[];
XPosition sameInProfitPositions[];
XPosition sameInDrawdownPositions[];
XPosition oppositInProfitPositions[];
XPosition oppositInDrawdownPositions[];
//
for (int i = 0; i < count; i++)
{
//
// Select Indexed Position ...
iPosition = positions[i];
//
bool isIPosLong = IsLong(iPosition.type);
bool isIPosShort = IsShort(iPosition.type);
//
// Select if Same Type ...
bool isSame =
(isLong && isIPosLong) ||
(isShort && isIPosShort);
if (isSame)
{
//
AddRef(
iPosition,
samePositions //
);
}
//
// Select if Opposit Type ...
bool isOpposit =
(isLong && isIPosShort) ||
(isShort && isIPosLong);
if (isOpposit)
{
//
AddRef(
iPosition,
oppositPositions //
);
}
//
iPosition.Clean();
}
//
// Filling Other Requirement Collections ...
//
ExtractInProfitPositions(
positions,
inProfitPositions //
);
//
ExtractInProfitPositions(
samePositions,
sameInProfitPositions //
);
//
ExtractInProfitPositions(
oppositPositions,
oppositInProfitPositions //
);
//
ExtractInDrawdownPositions(
positions,
inDrawdownPositions //
);
//
ExtractInDrawdownPositions(
samePositions,
sameInDrawdownPositions //
);
//
ExtractInDrawdownPositions(
oppositPositions,
oppositInDrawdownPositions //
);
//
// Implement Selection Senario ...
switch (selectType)
{
//
case XPOSITION_SELECT_ALL:
//
Copy(
positions,
selecteds //
);
break;
//
case XPOSITION_SELECT_IN_PROFITS:
//
Copy(
inProfitPositions,
selecteds //
);
break;
//
case XPOSITION_SELECT_IN_DRAWDOWNS:
//
Copy(
inDrawdownPositions,
selecteds //
);
break;
//
case XPOSITION_SELECT_OLDEST:
//
GetOldest(
iPosition,
positions //
);
if (iPosition.IsValid())
{
//
AddRef(
iPosition,
selecteds //
);
}
iPosition.Clean();
break;
//
case XPOSITION_SELECT_YOUNGEST:
//
GetYoungest(
iPosition,
positions //
);
if (iPosition.IsValid())
{
//
AddRef(
iPosition,
selecteds //
);
}
iPosition.Clean();
break;
//
case XPOSITION_SELECT_IN_PROFITS_OLDEST:
//
GetOldest(
iPosition,
inProfitPositions //
);
if (iPosition.IsValid())
{
//
AddRef(
iPosition,
selecteds //
);
}
iPosition.Clean();
break;
//
case XPOSITION_SELECT_IN_PROFITS_YOUNGEST:
//
GetYoungest(
iPosition,
inProfitPositions //
);
if (iPosition.IsValid())
{
//
AddRef(
iPosition,
selecteds //
);
}
iPosition.Clean();
break;
//
case XPOSITION_SELECT_IN_PROFITS_MIN:
//
idx = FindMinProfitIndex(inProfitPositions);
if (IsValidIndex(idx))
{
//
iPosition = inProfitPositions[idx];
//
AddRef(
iPosition,
selecteds //
);
}
iPosition.Clean();
break;
//
case XPOSITION_SELECT_IN_PROFITS_MAX:
//
idx = FindMaxProfitIndex(inProfitPositions);
if (IsValidIndex(idx))
{
//
iPosition = inProfitPositions[idx];
//
AddRef(
iPosition,
selecteds //
);
}
iPosition.Clean();
break;
//
case XPOSITION_SELECT_IN_DRAWDOWN_OLDEST:
//
GetOldest(
iPosition,
inDrawdownPositions //
);
if (iPosition.IsValid())
{
//
AddRef(
iPosition,
selecteds //
);
}
iPosition.Clean();
break;
//
case XPOSITION_SELECT_IN_DRAWDOWN_YOUNGEST:
//
GetYoungest(
iPosition,
inDrawdownPositions //
);
if (iPosition.IsValid())
{
//
AddRef(
iPosition,
selecteds //
);
}
iPosition.Clean();
break;
//
case XPOSITION_SELECT_IN_DRAWDOWN_MIN:
//
idx = FindMinDrawdownIndex(inDrawdownPositions);
if (IsValidIndex(idx))
{
//
iPosition = inDrawdownPositions[idx];
//
AddRef(
iPosition,
selecteds //
);
}
iPosition.Clean();
break;
//
case XPOSITION_SELECT_IN_DRAWDOWN_MAX:
//
idx = FindMaxDrawdownIndex(inDrawdownPositions);
if (IsValidIndex(idx))
{
//
iPosition = inDrawdownPositions[idx];
//
AddRef(
iPosition,
selecteds //
);
}
iPosition.Clean();
break;
//
case XPOSITION_SELECT_SAMES:
//
Copy(
samePositions,
selecteds //
);
break;
//
case XPOSITION_SELECT_SAMES_OLDEST:
//
GetOldest(
iPosition,
samePositions //
);
if (iPosition.IsValid())
{
//
AddRef(
iPosition,
selecteds //
);
}
iPosition.Clean();
break;
//
case XPOSITION_SELECT_SAMES_YOUNGEST:
//
GetYoungest(
iPosition,
samePositions //
);
if (iPosition.IsValid())
{
//
AddRef(
iPosition,
selecteds //
);
}
iPosition.Clean();
break;
//
case XPOSITION_SELECT_OPPOSITS:
//
Copy(
oppositPositions,
selecteds //
);
break;
//
case XPOSITION_SELECT_OPPOSIT_OLDEST:
//
GetOldest(
iPosition,
oppositPositions //
);
if (iPosition.IsValid())
{
//
AddRef(
iPosition,
selecteds //
);
}
iPosition.Clean();
break;
//
case XPOSITION_SELECT_OPPOSIT_YOUNGEST:
//
GetYoungest(
iPosition,
oppositPositions //
);
if (iPosition.IsValid())
{
//
AddRef(
iPosition,
selecteds //
);
}
iPosition.Clean();
break;
//
case XPOSITION_SELECT_SAME_IN_PROFITS:
//
Copy(
sameInProfitPositions,
selecteds //
);
break;
//
case XPOSITION_SELECT_SAME_IN_PROFITS_OLDEST:
//
GetOldest(
iPosition,
sameInProfitPositions //
);
if (iPosition.IsValid())
{
//
AddRef(
iPosition,
selecteds //
);
}
iPosition.Clean();
break;
//
case XPOSITION_SELECT_SAME_IN_PROFITS_YOUNGEST:
//
GetYoungest(
iPosition,
sameInProfitPositions //
);
if (iPosition.IsValid())
{
//
AddRef(
iPosition,
selecteds //
);
}
iPosition.Clean();
break;
//
case XPOSITION_SELECT_SAME_IN_PROFITS_MIN:
//
idx = FindMinProfitIndex(sameInProfitPositions);
if (IsValidIndex(idx))
{
//
iPosition = sameInProfitPositions[idx];
//
AddRef(
iPosition,
selecteds //
);
}
iPosition.Clean();
break;
//
case XPOSITION_SELECT_SAME_IN_PROFITS_MAX:
//
idx = FindMaxProfitIndex(sameInProfitPositions);
if (IsValidIndex(idx))
{
//
iPosition = sameInProfitPositions[idx];
//
AddRef(
iPosition,
selecteds //
);
}
iPosition.Clean();
break;
//
case XPOSITION_SELECT_OPPOSIT_IN_PROFITS:
//
Copy(
oppositInProfitPositions,
selecteds //
);
break;
//
case XPOSITION_SELECT_OPPOSIT_IN_PROFITS_OLDEST:
//
GetOldest(
iPosition,
oppositInProfitPositions //
);
if (iPosition.IsValid())
{
//
AddRef(
iPosition,
selecteds //
);
}
iPosition.Clean();
break;
//
case XPOSITION_SELECT_OPPOSIT_IN_PROFITS_YOUNGEST:
//
GetYoungest(
iPosition,
oppositInProfitPositions //
);
if (iPosition.IsValid())
{
//
AddRef(
iPosition,
selecteds //
);
}
iPosition.Clean();
break;
//
case XPOSITION_SELECT_OPPOSIT_IN_PROFITS_MIN:
//
idx = FindMinProfitIndex(oppositInProfitPositions);
if (IsValidIndex(idx))
{
//
iPosition = oppositInProfitPositions[idx];
//
AddRef(
iPosition,
selecteds //
);
}
iPosition.Clean();
break;
//
case XPOSITION_SELECT_OPPOSIT_IN_PROFITS_MAX:
//
idx = FindMaxProfitIndex(oppositInProfitPositions);
if (IsValidIndex(idx))
{
//
iPosition = oppositInProfitPositions[idx];
//
AddRef(
iPosition,
selecteds //
);
}
iPosition.Clean();
break;
//
case XPOSITION_SELECT_SAME_IN_DRAWDOWNS:
//
Copy(
sameInDrawdownPositions,
selecteds //
);
break;
//
case XPOSITION_SELECT_SAME_IN_DRAWDOWN_OLDEST:
//
GetOldest(
iPosition,
sameInDrawdownPositions //
);
if (iPosition.IsValid())
{
//
AddRef(
iPosition,
selecteds //
);
}
iPosition.Clean();
break;
//
case XPOSITION_SELECT_SAME_IN_DRAWDOWN_YOUNGEST:
//
GetYoungest(
iPosition,
sameInDrawdownPositions //
);
if (iPosition.IsValid())
{
//
AddRef(
iPosition,
selecteds //
);
}
iPosition.Clean();
break;
//
case XPOSITION_SELECT_SAME_IN_DRAWDOWN_MIN:
//
idx = FindMinDrawdownIndex(sameInDrawdownPositions);
if (IsValidIndex(idx))
{
//
iPosition = sameInDrawdownPositions[idx];
//
AddRef(
iPosition,
selecteds //
);
}
iPosition.Clean();
break;
//
case XPOSITION_SELECT_SAME_IN_DRAWDOWN_MAX:
//
idx = FindMaxDrawdownIndex(sameInDrawdownPositions);
if (IsValidIndex(idx))
{
//
iPosition = sameInDrawdownPositions[idx];
//
AddRef(
iPosition,
selecteds //
);
}
iPosition.Clean();
break;
//
case XPOSITION_SELECT_OPPOSITS_IN_DRAWDOWNS:
//
Copy(
oppositInDrawdownPositions,
selecteds //
);
break;
//
case XPOSITION_SELECT_OPPOSITS_IN_DRAWDOWN_OLDEST:
//
GetOldest(
iPosition,
oppositInDrawdownPositions //
);
if (iPosition.IsValid())
{
//
AddRef(
iPosition,
selecteds //
);
}
iPosition.Clean();
break;
//
case XPOSITION_SELECT_OPPOSITS_IN_DRAWDOWN_YOUNGEST:
//
GetYoungest(
iPosition,
oppositInDrawdownPositions //
);
if (iPosition.IsValid())
{
//
AddRef(
iPosition,
selecteds //
);
}
iPosition.Clean();
break;
//
case XPOSITION_SELECT_OPPOSITS_IN_DRAWDOWN_MIN:
//
idx = FindMinDrawdownIndex(oppositInDrawdownPositions);
if (IsValidIndex(idx))
{
//
iPosition = oppositInDrawdownPositions[idx];
//
AddRef(
iPosition,
selecteds //
);
}
iPosition.Clean();
break;
//
case XPOSITION_SELECT_OPPOSITS_IN_DRAWDOWN_MAX:
//
idx = FindMaxDrawdownIndex(oppositInDrawdownPositions);
if (IsValidIndex(idx))
{
//
iPosition = oppositInDrawdownPositions[idx];
//
AddRef(
iPosition,
selecteds //
);
}
iPosition.Clean();
break;
//
}
//
// Validate Result ...
result = HasChild(selecteds);
//
// Cleanup Resources ...
//
if (!result)
{
Clean(selecteds);
}
//
Clean(samePositions);
Clean(oppositPositions);
Clean(inProfitPositions);
Clean(inDrawdownPositions);
Clean(sameInProfitPositions);
Clean(sameInDrawdownPositions);
Clean(oppositInProfitPositions);
Clean(oppositInDrawdownPositions);
//
return result;
}
//