Files
xMQL5/MQLTestWorkspace/BKPS/14030222/Libraries/x-saherelm.seriallizer.lib.mq5
T
2024-05-11 05:36:03 +03:30

1326 lines
30 KiB
Plaintext

///////////////////////////////////////////////////////
//
// SaherElm IT Center MQL5 Seriallize Library
// ---------------------------------------
// Name: XSeriallizer
// Description: provides Seriallizing EA abilities ...
//
//
// 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
//
#include "../Libraries/x-saherelm.models.lib.mq5"
#include "../Libraries/x-saherelm.common.lib.mq5"
#include "../Classes/x-saherelm.xtrade.class.mq5"
#include "../Classes/x-saherelm.x121.provider.class.mq5"
//
string XProviderToken = "PRV";
string XSupportToken = "SP";
string XSLTrailToken = "SLT";
string XPeriodToken = "PR";
//
string XConfigToken = "XPV";
string XItemSeparator = "|";
string XItemContentSeparator = ",";
//
string XFirstGenToken = "0";
//
// PERIOD ...
//
// Detect a Comment has period or not ...
bool HasPeriod(string comment)
{
//
bool result = false;
//
if (StringLen(comment) == 0)
{
return result;
}
//
int tokenPos = StringFind(
comment,
XPeriodToken);
result = tokenPos >= 0;
//
return result;
}
//
// Extract Period String ...
string ExtractPeriodString(string comment)
{
//
string result = "";
//
bool hasPeriod = HasPeriod(comment);
if (!hasPeriod)
{
return result;
}
//
result = ExtractString(
comment,
XPeriodToken + "(",
")");
//
return result;
}
//
// Extract Time Frame From Comment ...
ENUM_TIMEFRAMES ExtractPeriod(string comment)
{
//
ENUM_TIMEFRAMES result = NULL;
//
if (StringLen(comment) <= 0)
{
return result;
}
//
string periodStr = ExtractPeriodString(comment);
if (StringLen(periodStr) <= 0)
{
return result;
}
//
result = ToPeriod(periodStr);
//
return result;
}
//
// PROVIDER ...
//
// Extract a Provider name if exists from a Comment ...
string ExtractProvider(string comment)
{
//
string result = "";
if (StringLen(comment) <= 0)
{
return result;
}
//
result = ExtractString(
comment,
XProviderToken + "(",
")");
//
return result;
}
//
// Generate Provider String for Using in Positions Comment ...
// NOTE: if there is more than One Provider, it takes first
// provider as main and the others used to increase volume ...
string GenerateProvidersString(XSignal &signal)
{
//
string result = "";
//
int providersCount = ArraySize(signal.providers);
if (providersCount <= 0)
{
return result;
}
//
result = XProviderToken + "(" + signal.providers[0] + ")";
//
return result;
}
//
// SLTRAIL ...
//
string GenerateSLTrailComment(int level)
{
//
string result = "";
//
if (level <= 0)
{
return result;
}
//
result = XSLTrailToken + "(" + ToString(level) + ")";
//
return result;
}
//
int ExtractSLTrailLevel(string comment)
{
//
int result = 0;
//
if (StringLen(comment) == 0)
{
return result;
}
//
string levelStr = ExtractString(
comment,
XSLTrailToken + "(",
")");
if (StringLen(levelStr) == 0)
{
return result;
}
//
result = (int)levelStr;
//
return result;
}
//
string PrepareSLTrailComment(
const string comment // Original Position Comment ...
)
{
//
string result = "";
//
if (StringLen(comment) == 0)
{
return result;
}
//
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 = GenerateSLTrailComment(lastTrailLevel);
StringReplace(
result,
lastLevelStr,
"");
}
//
// Generate level Comment ...
string levelStr = GenerateSLTrailComment(level);
result += levelStr;
//
return result;
}
//
// SUPPORT ...
//
// Generate Specific Position's Support Comment
// index is number of Supports ...
string GenerateSupportSignalComment(
ulong ticket, // Position/Order Ticket
int index // Support Index ...
)
{
//
string result = "";
//
result = XSupportToken + "(" + (string)ticket + "," + ToString(index) + ")";
//
return result;
}
//
// Extract Support Parameters String from specified Comment ...
string ExtractSupportParam(string comment)
{
//
string result = "";
if (StringLen(comment) <= 0)
{
return result;
}
//
result = ExtractString(
comment,
XSupportToken + "(",
")");
//
return result;
}
//
// Extract Support Info as String array for Specific Comment ...
bool ExtractSupportParams(
string comment, // Specified Comment ...
string &params[] // Hold Result ...
)
{
//
bool result = false;
//
string supParam = ExtractSupportParam(comment);
if (StringLen(supParam) == 0)
{
return result;
}
//
SplitContent(
params,
supParam);
int paramsCount = ArraySize(params);
//
result = paramsCount == 2;
//
return result;
}
//
// Extract Support Parent Ticket ...
ulong ExtractParentTicket(string comment)
{
//
ulong result = 0;
//
string params[];
bool isSupport = ExtractSupportParams(
comment,
params);
if (!isSupport)
{
return result;
}
//
result = (ulong)params[0];
//
return result;
}
//
// Extract Support Index ...
int ExtractSupportIndex(string comment)
{
//
int result = -1;
//
string params[];
bool isSupport = ExtractSupportParams(
comment,
params);
if (!isSupport)
{
return result;
}
//
result = (int)params[1];
//
return result;
}
//
// XCONFIG X121Provider Struct ...
//
// Extract Signallers from User Input ...
int ExtractSignallers(
string &result[], // Hold Result
const string source // Source Content
)
{
//
int mResult = 0;
//
Clean(result);
//
SplitContent(
result,
source);
//
mResult = ArraySize(result);
//
return mResult;
}
//
// Validate Specified Provider Descriptor Model ...
bool IsValid(X121SignalProvider &item)
{
//
bool result = false;
//
result =
//
StringLen(item.symbol) > 0 &&
item.period != NULL &&
item.riskAmount > 0
//
;
//
return result;
}
//
// Compare Source item with Dest item to check their Same or not ...
bool IsSame(
X121SignalProvider &source, // Source Item
X121SignalProvider &dest // Dest Item
)
{
//
bool result = false;
//
bool isValidDest = IsValid(dest);
bool isValidSource = IsValid(source);
if (!isValidDest ||
!isValidSource)
{
return result;
}
//
result =
//
source.symbol == dest.symbol &&
source.period == dest.period &&
source.riskAmount == dest.riskAmount &&
source.useRiskAmountAsStaticVolume == dest.useRiskAmountAsStaticVolume
//
;
//
return result;
}
//
// Check Specified Provider Exists in a Collection or not ...
bool Contains(
X121SignalProvider &item, // Specified Item
X121SignalProvider &items[] // Given Collection
)
{
//
bool result = false;
//
int itemsCount = ArraySize(items);
if (itemsCount <= 0)
{
return result;
}
//
for (int i = 0; i < itemsCount; i++)
{
//
X121SignalProvider iProvider = items[i];
//
result = IsSame(item, iProvider);
if (result)
{
//
break;
}
}
//
return result;
}
//
// Extract Provider Descriptor Parts from given Source Input ...
int ExtractProviderDescriptorItems(
string &result[], // Hold Result
const string source // Source Descriptor
)
{
//
int mResult = 0;
//
Clean(result);
//
SplitContent(
result,
source,
XItemSeparator);
//
mResult = ArraySize(result);
//
return mResult;
}
//
// Extract Provider Descriptor Items Content from given Source Input ...
int ExtractProviderDescriptorItemsContent(
string &result[], // Hold Result
const string source // Source Descriptor
)
{
//
int mResult = 0;
//
Clean(result);
//
SplitContent(
result,
source,
XItemContentSeparator);
//
mResult = ArraySize(result);
//
return mResult;
}
//
// Validate and add provider to providers if not exists ...
bool AddProviderDescriptor(
X121SignalProvider &item,
X121SignalProvider &items[])
{
//
bool result = false;
//
// Validate and add ...
result = IsValid(item);
if (!result)
{
return result;
}
//
bool isExists = Contains(
item,
items);
if (isExists)
{
return result;
}
//
result = true;
//
Add(
item,
items);
//
return result;
}
//
// Extract Provider Descriptors from given Source Input ...
int ExtractProviderConfigurations(
X121SignalProvider &result[], // Hold Result
const string source, // Source String
const string defaultSignallers, // Default Available Signallers for Each Providers
const double defaultRiskAmount, // Default Risk Amount per Trade for Each Provider
const bool useRiskAmountAsStaticVolume = true // Use Provided Risk Amount as Static Volume
)
{
//
int mResult = 0;
//
Clean(result);
//
// if there is no Pairs ...
// Check as One Model ...
string descriptors[];
mResult = ExtractStrings(
descriptors,
source,
XConfigToken + "(",
")");
//
// Retrieve Signallers ...
string defaultSignallersArr[];
ExtractSignallers(
defaultSignallersArr,
defaultSignallers);
//
if (mResult == 0)
{
//
// Here we Check given source String Length ...
// if it is bigger than zero we assuem it is one line descriptor ...
if (StringLen(source) > 0)
{
//
// One Model ...
Add(
source,
descriptors);
}
}
//
// Each Provider Must Contains at least two things :
// - Asset;
int descriptorsCount = ArraySize(descriptors);
if (descriptorsCount > 0)
{
//
// Loop through descriptors to parse models ...
for (int i = 0; i < descriptorsCount; i++)
{
//
string iDescriptor = descriptors[i];
//
X121SignalProvider iProviderDescriptor;
iProviderDescriptor.symbol = "";
iProviderDescriptor.period = NULL;
iProviderDescriptor.riskAmount = 0;
Clean(iProviderDescriptor.providers);
//
string iParts[];
int iPartsCount = ExtractProviderDescriptorItems(
iParts,
iDescriptor);
//
// Check Parts Count ...
// Now we have to Decide How to Config Signal Providers using Parts ...
//
// asset => default;
// period => default;
// risk amount => default;
// signallers => default;
// use as static volume => default;
if (iPartsCount == 0)
{
//
// Here we Instance as Current Config Descriptor ...
iProviderDescriptor.symbol = _Symbol;
iProviderDescriptor.period = _Period;
iProviderDescriptor.riskAmount = defaultRiskAmount;
iProviderDescriptor.useRiskAmountAsStaticVolume = useRiskAmountAsStaticVolume;
//
// Add Default Signallers ...
Copy(
defaultSignallersArr,
iProviderDescriptor.providers);
//
AddProviderDescriptor(
iProviderDescriptor,
result);
//
continue;
}
//
// asset => provided;
// period => default;
// risk amount => default;
// signallers => default;
// use as static volume => default;
if (iPartsCount == 1)
{
//
iProviderDescriptor.period = _Period;
iProviderDescriptor.riskAmount = defaultRiskAmount;
iProviderDescriptor.useRiskAmountAsStaticVolume = useRiskAmountAsStaticVolume;
//
// Add Default Signallers ...
Copy(
defaultSignallersArr,
iProviderDescriptor.providers);
//
// Extract Provided Assets ...
string symbols[];
int symbolsCount = ExtractProviderDescriptorItemsContent(
symbols,
iParts[0]);
for (int j = 0; j < symbolsCount; j++)
{
//
string jSymbol = symbols[j];
//
iProviderDescriptor.symbol = jSymbol;
//
AddProviderDescriptor(
iProviderDescriptor,
result);
}
//
continue;
}
//
// asset => provided;
// period => provided;
// risk amount => default;
// signallers => default;
// use as static volume => default;
if (iPartsCount == 2)
{
//
iProviderDescriptor.riskAmount = defaultRiskAmount;
iProviderDescriptor.useRiskAmountAsStaticVolume = useRiskAmountAsStaticVolume;
//
// Add Default Signallers ...
Copy(
defaultSignallersArr,
iProviderDescriptor.providers);
//
// Extract Provided Assets ...
string symbols[];
int symbolsCount = ExtractProviderDescriptorItemsContent(
symbols,
iParts[0]);
for (int j = 0; j < symbolsCount; j++)
{
//
string jSymbol = symbols[j];
//
iProviderDescriptor.symbol = jSymbol;
//
// Extract Periods ...
string periods[];
int periodsCount = ExtractProviderDescriptorItemsContent(
periods,
iParts[1]);
for (int k = 0; k < periodsCount; k++)
{
//
string kPeriodStr = periods[k];
ENUM_TIMEFRAMES kPeriod = ToPeriod(kPeriodStr);
//
iProviderDescriptor.period = kPeriod;
//
AddProviderDescriptor(
iProviderDescriptor,
result);
}
}
//
continue;
}
//
// asset => provided;
// period => provided;
// risk amount => provided;
// signallers => default;
// use as static volume => default;
if (iPartsCount == 3)
{
//
iProviderDescriptor.useRiskAmountAsStaticVolume = useRiskAmountAsStaticVolume;
//
// Add Default Signallers ...
Copy(
defaultSignallersArr,
iProviderDescriptor.providers);
//
// Extract Provided Assets ...
string symbols[];
int symbolsCount = ExtractProviderDescriptorItemsContent(
symbols,
iParts[0]);
//
string riskAmounts[];
int riskAmountsCount = ExtractProviderDescriptorItemsContent(
riskAmounts,
iParts[2]);
//
for (int j = 0; j < symbolsCount; j++)
{
//
string jSymbol = symbols[j];
//
iProviderDescriptor.symbol = jSymbol;
//
// Extract Periods ...
string periods[];
int periodsCount = ExtractProviderDescriptorItemsContent(
periods,
iParts[1]);
for (int k = 0; k < periodsCount; k++)
{
//
string kPeriodStr = periods[k];
ENUM_TIMEFRAMES kPeriod = ToPeriod(kPeriodStr);
//
iProviderDescriptor.period = kPeriod;
//
string selectedRiskAmount =
riskAmountsCount == 0
? ToString(defaultRiskAmount)
: riskAmountsCount == periodsCount
? riskAmounts[k]
: riskAmounts[0];
double riskAmount = (double)selectedRiskAmount;
iProviderDescriptor.riskAmount = riskAmount;
//
AddProviderDescriptor(
iProviderDescriptor,
result);
}
}
//
continue;
}
//
// asset => provided;
// period => provided;
// risk amount => provided;
// signallers => provided;
// use as static volume => default;
if (iPartsCount == 4)
{
//
iProviderDescriptor.useRiskAmountAsStaticVolume = useRiskAmountAsStaticVolume;
//
// Extract Signallers ...
string signallers[];
int signallersCount = ExtractSignallers(
signallers,
iParts[3]);
if (signallersCount <= 0)
{
//
Copy(
defaultSignallersArr,
signallers);
}
//
// Set Extracted Signallers in Provider Descriptor ...
Copy(
signallers,
iProviderDescriptor.providers);
//
//
// Extract Provided Assets ...
string symbols[];
int symbolsCount = ExtractProviderDescriptorItemsContent(
symbols,
iParts[0]);
//
string riskAmounts[];
int riskAmountsCount = ExtractProviderDescriptorItemsContent(
riskAmounts,
iParts[2]);
//
for (int j = 0; j < symbolsCount; j++)
{
//
string jSymbol = symbols[j];
//
iProviderDescriptor.symbol = jSymbol;
//
// Extract Periods ...
string periods[];
int periodsCount = ExtractProviderDescriptorItemsContent(
periods,
iParts[1]);
for (int k = 0; k < periodsCount; k++)
{
//
string kPeriodStr = periods[k];
ENUM_TIMEFRAMES kPeriod = ToPeriod(kPeriodStr);
//
iProviderDescriptor.period = kPeriod;
//
string selectedRiskAmount =
riskAmountsCount == 0
? ToString(defaultRiskAmount)
: riskAmountsCount == periodsCount
? riskAmounts[k]
: riskAmounts[0];
double riskAmount = (double)selectedRiskAmount;
iProviderDescriptor.riskAmount = riskAmount;
//
AddProviderDescriptor(
iProviderDescriptor,
result);
}
}
//
continue;
}
//
// asset => provided;
// period => provided;
// risk amount => provided;
// signallers => provided;
// use as static volume => provided;
if (iPartsCount == 5)
{
//
// Extract Signallers ...
string signallers[];
int signallersCount = ExtractSignallers(
signallers,
iParts[3]);
if (signallersCount <= 0)
{
//
Copy(
defaultSignallersArr,
signallers);
}
//
// Set Extracted Signallers in Provider Descriptor ...
Copy(
signallers,
iProviderDescriptor.providers);
//
//
// Extract Provided Assets ...
string symbols[];
int symbolsCount = ExtractProviderDescriptorItemsContent(
symbols,
iParts[0]);
//
string riskAmounts[];
int riskAmountsCount = ExtractProviderDescriptorItemsContent(
riskAmounts,
iParts[2]);
//
string useRiskAmountAsStaticVolumes[];
int useRiskAmountAsStaticVolumesCount = ExtractProviderDescriptorItemsContent(
useRiskAmountAsStaticVolumes,
iParts[4]);
//
for (int j = 0; j < symbolsCount; j++)
{
//
string jSymbol = symbols[j];
//
iProviderDescriptor.symbol = jSymbol;
//
// Extract Periods ...
string periods[];
int periodsCount = ExtractProviderDescriptorItemsContent(
periods,
iParts[1]);
for (int k = 0; k < periodsCount; k++)
{
//
string kPeriodStr = periods[k];
ENUM_TIMEFRAMES kPeriod = ToPeriod(kPeriodStr);
//
iProviderDescriptor.period = kPeriod;
//
string selectedRiskAmount =
riskAmountsCount == 0
? ToString(defaultRiskAmount)
: riskAmountsCount == periodsCount
? riskAmounts[k]
: riskAmounts[0];
double riskAmount = (double)selectedRiskAmount;
iProviderDescriptor.riskAmount = riskAmount;
//
string selectedUseRiskAmountAsStaticVolume =
useRiskAmountAsStaticVolumesCount == 0
? ToString(useRiskAmountAsStaticVolume)
: useRiskAmountAsStaticVolumesCount == periodsCount
? useRiskAmountAsStaticVolumes[k]
: useRiskAmountAsStaticVolumes[0];
bool useRiskAmountAsStaticVolume = ToBoolean(selectedUseRiskAmountAsStaticVolume);
iProviderDescriptor.useRiskAmountAsStaticVolume = useRiskAmountAsStaticVolume;
//
AddProviderDescriptor(
iProviderDescriptor,
result);
}
}
//
continue;
}
}
}
else
{
//
// Use All Defaults to Create One Instance ...
X121SignalProvider iProviderDescriptor;
iProviderDescriptor.symbol = "";
iProviderDescriptor.period = NULL;
iProviderDescriptor.riskAmount = 0;
Clean(iProviderDescriptor.providers);
//
iProviderDescriptor.symbol = _Symbol;
iProviderDescriptor.period = _Period;
iProviderDescriptor.riskAmount = defaultRiskAmount;
iProviderDescriptor.useRiskAmountAsStaticVolume = useRiskAmountAsStaticVolume;
//
// Add Default Signallers ...
Copy(
defaultSignallersArr,
iProviderDescriptor.providers);
//
AddProviderDescriptor(
iProviderDescriptor,
result);
}
//
mResult = ArraySize(result);
//
return mResult;
}
//
// START XEQM Support ...
//
//
string XEQMSupportToken = "XEQM";
//
// Generate String Tag for EQM Support Signals ...
string GenerateXEQMSupportComment()
{
//
string result = XEQMSupportToken;
//
return result;
}
//
// Check a Comment belongs to a EQM Support or not ...
bool IsEQMSupport(string comment)
{
//
bool result = false;
//
if (StringLen(comment) <= 0)
{
return result;
}
//
int tokenPosition = StringFind(
comment,
XEQMSupportToken);
result = tokenPosition >= 0;
//
return result;
}
//
// Select EQM Support Orders ...
int GetEQMSupportOrders(
XOrder &supports[], // Hold Result ...
XOrder &orders[], // List of All Orders ...
ENUM_TIMEFRAMES period = NULL // Specified Period ...
)
{
//
int result = 0;
//
// Cleanup Array ...
Clean(supports);
//
// Count Orders ...
int ordersCount = ArraySize(orders);
if (ordersCount <= 0)
{
return result;
}
//
// Loop through Orders ...
for (int i = 0; i < ordersCount; i++)
{
//
// Select Indexed Order ...
XOrder iOrder = orders[i];
//
// Check Order is Support or not ...
bool isSupport = IsEQMSupport(iOrder.comment);
if (!isSupport)
{
continue;
}
//
// Check Order is not Triggered ...
if (iOrder.state != ORDER_STATE_PLACED)
{
continue;
}
//
// Check Period ...
if (period != NULL && iOrder.period != period)
{
continue;
}
//
// we now sure this order is EQM Support ...
Add(
iOrder,
supports);
}
//
// Count Result ...
result = ArraySize(supports);
//
return result;
}
//
// Select EQM Support Positions ...
int GetEQMSupportPositions(
XPosition &supports[], // Hold Result ...
XPosition &positions[], // List of All Positions ...
ENUM_TIMEFRAMES period = NULL // Specified Period ...
)
{
//
int result = 0;
//
// Cleanup Array ...
Clean(supports);
//
// Count Positions ...
int positionsCount = ArraySize(positions);
if (positionsCount <= 0)
{
return result;
}
//
// Loop through Positions ...
for (int i = 0; i < positionsCount; i++)
{
//
// Select Indexed Position ...
XPosition iPosition = positions[i];
//
// Check Position is Support or not ...
bool isSupport = IsEQMSupport(iPosition.comment);
if (!isSupport)
{
continue;
}
//
// Check Period ...
if (period != NULL && iPosition.period != period)
{
continue;
}
//
// we now sure this order is EQM Support ...
Add(
iPosition,
supports);
}
//
// Count Result ...
result = ArraySize(supports);
//
return result;
}
//
// END XEQM Support ...
//
//
// START FirstGen ...
//
//
string GenerateFirstGenIdentifier(const string signaller)
{
//
string result = "";
//
if (StringLen(signaller) <= 0)
{
return result;
}
//
return signaller + XFirstGenToken;
//
return result;
}
//
bool IsFirstGenOf(
const string signaller, // Specified Signaller
const string comment // Comment
)
{
//
bool result = false;
//
string id = GenerateFirstGenIdentifier(signaller);
//
int idPos = StringFind(
comment,
id
);
result = idPos >= 0;
//
return result;
}
//
// END FirstGen ...
//