diff --git a/MQLTestWorkspace/BKPS/BKP/Classes/x-saherelm.xdatacollector.class.mq5 b/MQLTestWorkspace/BKPS/BKP/Classes/x-saherelm.xdatacollector.class.mq5 new file mode 100644 index 0000000..f24164d --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/Classes/x-saherelm.xdatacollector.class.mq5 @@ -0,0 +1,1582 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XSCDataCollector +// Description: provides all Data Collection requirements ... +// +// +// 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 + +// +// START Definitions ... +// + +// +// Supported Data Types ... +enum ENUM_X_XDATACOLLECTOR_TYPES +{ + X_DATA_COLLECTOR_SIGNAL, + X_DATA_COLLECTOR_SUPRES, + X_DATA_COLLECTOR_POSITION, + X_DATA_COLLECTOR_DEAL, + X_DATA_COLLECTOR_LOG, +}; + +// +// END Definitions ... +// + +// +// START Import and Inclused requirements ... +// + +// +// Includes ... +#include "x-saherelm.xtrade.class.mq5" +#include "../Libraries/x-saherelm.log.lib.mq5" +#include "../Libraries/x-saherelm.models.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Import and Inclused requirements ... +// + +// +// START Overrides ... +// + +// +// END Overrides ... +// + +// +// a Class Definition ... +class XSCDataCollector +{ + // + // Public ... +public: + // + // Constructor ... + void XSCDataCollector() + { + // + XSCDataCollector("XDataCollector"); + + // + DefineTokens(); + } + void XSCDataCollector( + string path // Base Folder to Store Data + ) + { + // + // Set Properties ... + + // + Path(path); + + // + DefineTokens(); + } + + // + // Deconstructor ... + void ~XSCDataCollector() + { + } + + // + // START Getter(s)/Setter(s) ... + // + + // + // Path ... + void Path(string value) + { + mPath = value; + } + + string Path() + { + return mPath; + } + + // + // END Getter(s)/Setter(s) ... + // + + // + // START Provided Functions ... + // + + // + // Clean Exists Collected Data ... + void CleanStore() + { + // + ENUM_X_XDATACOLLECTOR_TYPES types[]; + RetrieveAllAvailableTypes(types); + int typesCount = ArraySize(types); + if (typesCount <= 0) + { + return; + } + + // + ResetLastError(); + + // + for (int i = 0; i < typesCount; i++) + { + // + ENUM_X_XDATACOLLECTOR_TYPES iType = types[i]; + string typeFilePath = GenerateTypeFilePath(iType); + + // + bool isExist = FileIsExist(typeFilePath); + if (isExist) + { + FileDelete(typeFilePath); + } + } + } + + // + // Add Specific Deal ... + void CollectDeal(const XDeal &deal) + { + // + string content = ToStringFormat(deal); + if (StringLen(content) <= 0) + { + return; + } + + // + string filePath = GenerateTypeFilePath(X_DATA_COLLECTOR_DEAL); + int mFileHandler = FileOpen( + filePath, + FILE_READ | FILE_WRITE | FILE_TXT); + if (mFileHandler == INVALID_HANDLE) + { + return; + } + + // + FileSeek(mFileHandler, 0, SEEK_END); + FileWrite(mFileHandler, content); + FileFlush(mFileHandler); + FileClose(mFileHandler); + } + + // + // Extract Collected Deals ... + void ExtreactDeals(XDeal &result[]) + { + // + Clean(result); + + // + string filePath = GenerateTypeFilePath(X_DATA_COLLECTOR_DEAL); + int mFileHandler = FileOpen( + filePath, + FILE_READ | FILE_TXT); + if (mFileHandler == INVALID_HANDLE) + { + return; + } + + // + while (!FileIsEnding(mFileHandler)) + { + // + string content = FileReadString(mFileHandler); + + // + XDeal deal = ToDeal(content); + + // + Add( + deal, + result); + } + + // + FileClose(mFileHandler); + } + + // + // Add Specific Signal ... + void CollectSignal(const XSignal &signal) + { + // + string content = ToStringFormat(signal); + if (StringLen(content) <= 0) + { + return; + } + + // + string filePath = GenerateTypeFilePath(X_DATA_COLLECTOR_SIGNAL); + int mFileHandler = FileOpen( + filePath, + FILE_READ | FILE_WRITE | FILE_TXT); + if (mFileHandler == INVALID_HANDLE) + { + LogMessage("Error: " + (string)GetLastError()); + return; + } + + // + FileSeek(mFileHandler, 0, SEEK_END); + FileWrite(mFileHandler, content); + FileFlush(mFileHandler); + FileClose(mFileHandler); + } + + // + // Extract Collected Signals ... + void ExtreactSignals(XSignal &result[]) + { + // + Clean(result); + + // + string filePath = GenerateTypeFilePath(X_DATA_COLLECTOR_SIGNAL); + int mFileHandler = FileOpen( + filePath, + FILE_READ | FILE_TXT); + if (mFileHandler == INVALID_HANDLE) + { + return; + } + + // + while (!FileIsEnding(mFileHandler)) + { + // + string content = FileReadString(mFileHandler); + + // + XSignal signal = ToSignal(content); + + // + Add( + signal, + result); + } + + // + FileClose(mFileHandler); + } + + // + // Add Specific Position ... + void CollectPosition(const XPosition &position) + { + // + string content = ToStringFormat(position); + if (StringLen(content) <= 0) + { + return; + } + + // + string filePath = GenerateTypeFilePath(X_DATA_COLLECTOR_POSITION); + int mFileHandler = FileOpen( + filePath, + FILE_READ | FILE_WRITE | FILE_TXT); + if (mFileHandler == INVALID_HANDLE) + { + return; + } + + // + FileSeek(mFileHandler, 0, SEEK_END); + FileWrite(mFileHandler, content); + FileFlush(mFileHandler); + FileClose(mFileHandler); + } + + // + // Extract Collected Positions ... + void ExtreacPositions(XPosition &result[]) + { + // + Clean(result); + + // + string filePath = GenerateTypeFilePath(X_DATA_COLLECTOR_POSITION); + int mFileHandler = FileOpen( + filePath, + FILE_READ | FILE_TXT); + if (mFileHandler == INVALID_HANDLE) + { + return; + } + + // + while (!FileIsEnding(mFileHandler)) + { + // + string content = FileReadString(mFileHandler); + + // + XPosition position = ToPosition(content); + + // + Add( + position, + result); + } + + // + FileClose(mFileHandler); + } + + // + // SUPPORT and RESISTANCE ... + void CollectSupRes(const XOHCLSupRes &item) + { + } + + // + void ExtractSupReses(XOHCLSupRes &result[]) + { + } + + // + // Add Specific Log ... + void CollectLog(string log) + { + // + if (StringLen(log) <= 0) + { + return; + } + + // + string content = ExtractTypePath(X_DATA_COLLECTOR_LOG) + + "[" + log + "]"; + + // + string filePath = GenerateTypeFilePath(X_DATA_COLLECTOR_LOG); + int mFileHandler = FileOpen( + filePath, + FILE_READ | FILE_WRITE | FILE_TXT); + if (mFileHandler == INVALID_HANDLE) + { + return; + } + + // + FileSeek(mFileHandler, 0, SEEK_END); + FileWrite(mFileHandler, content); + FileFlush(mFileHandler); + FileClose(mFileHandler); + } + + // + // Extract Collected Logs ... + void ExtractLogs(string &result[]) + { + // + Clean(result); + + // + string filePath = GenerateTypeFilePath(X_DATA_COLLECTOR_LOG); + string typeIdentifier = ExtractTypePath(X_DATA_COLLECTOR_LOG); + int mFileHandler = FileOpen( + filePath, + FILE_READ | FILE_TXT); + if (mFileHandler == INVALID_HANDLE) + { + return; + } + + // + while (!FileIsEnding(mFileHandler)) + { + // + string content = FileReadString(mFileHandler); + + // + string log = ExtractString( + content, + typeIdentifier + "[", + "]"); + + // + if (StringLen(log) > 0) + { + // + Add( + log, + result); + } + } + + // + FileClose(mFileHandler); + } + + // + // TYPE Specific Casting Functions ... + + // + // Signal ... + + // + // Convert to it's String Representation ... + string ToStringFormat(const XSignal &signal) + { + // + string result = ""; + + // + DefineTokens(); + + // + result += + ExtractTypePath(X_DATA_COLLECTOR_SIGNAL) + + "[" + + mProvidersToken + "(" + ToString(signal.providers) + ")" + + mSymbolToken + "(" + signal.symbol + ")" + + mPeriodToken + "(" + ToString(signal.period) + ")" + + mTypeToken + "(" + (string)((int)signal.type) + ")" + + mModeToken + "(" + (string)((int)signal.mode) + ")" + + mEntryToken + "(" + (string)signal.entry + ")" + + mRiskAmountToken + "(" + (string)signal.riskAmount + ")" + + mTPToken + "(" + (string)signal.tp + ")" + + mSLToken + "(" + (string)signal.sl + ")" + + mR2rToken + "(" + (string)signal.r2r + ")" + + mVolumeToken + "(" + (string)signal.volume + ")" + + mSupportResistanceToken + "(" + ToStringFormat(signal.supportAndResistance) + ")" + + "]"; + + // + return result; + } + + // + // Converts an string to XSignal ... + XSignal ToSignal(string content) + { + // + XSignal result; + + // + DefineTokens(); + + // + string typeIdentifier = ExtractTypePath(X_DATA_COLLECTOR_SIGNAL); + + // + if (StringLen(content) == 0 || StringFind(content, typeIdentifier) < 0) + { + return result; + } + + // + string signalContent = ExtractString( + content, + typeIdentifier + "[", + "]"); + if (StringLen(signalContent) == 0) + { + return result; + } + + // + // Providers ... + string providersStr = ExtractString( + signalContent, + mProvidersToken + "(", + ")"); + if (StringLen(providersStr) > 0) + { + // + string providers[]; + StringSplit( + providersStr, + StringGetCharacter(",", 0), + providers); + + // + ArrayCopy( + result.providers, + providers); + } + + // + // Symbol ... + string symbolStr = ExtractString( + signalContent, + mSymbolToken + "(", + ")"); + if (StringLen(symbolStr) > 0) + { + result.symbol = symbolStr; + } + + // + // Period ... + string periodStr = ExtractString( + signalContent, + mPeriodToken + "(", + ")"); + if (StringLen(periodStr) > 0) + { + // + ENUM_TIMEFRAMES period = ToPeriod(periodStr); + + // + result.period = period; + } + + // + // Type ... + string typeStr = ExtractString( + signalContent, + mTypeToken + "(", + ")"); + if (StringLen(typeStr) > 0) + { + // + ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE)((int)typeStr); + + // + result.type = type; + } + + // + // Mode ... + string modeStr = ExtractString( + signalContent, + mModeToken + "(", + ")"); + if (StringLen(modeStr) > 0) + { + // + ENUM_X_ORDER_MODES mode = (ENUM_X_ORDER_MODES)((int)modeStr); + + // + result.mode = mode; + } + + // + // Entry ... + string entryStr = ExtractString( + signalContent, + mEntryToken + "(", + ")"); + if (StringLen(entryStr) > 0) + { + // + double entry = (double)entryStr; + + // + result.entry = entry; + } + + // + // RiskAmount ... + string raStr = ExtractString( + signalContent, + mRiskAmountToken + "(", + ")"); + if (StringLen(raStr) > 0) + { + // + double ra = (double)raStr; + + // + result.riskAmount = ra; + } + + // + // TP ... + string tpStr = ExtractString( + signalContent, + mTPToken + "(", + ")"); + if (StringLen(tpStr) > 0) + { + // + double tp = (double)tpStr; + + // + result.tp = tp; + } + + // + // SL ... + string slStr = ExtractString( + signalContent, + mSLToken + "(", + ")"); + if (StringLen(slStr) > 0) + { + // + double sl = (double)slStr; + + // + result.sl = sl; + } + + // + // R2R ... + string r2rStr = ExtractString( + signalContent, + mR2rToken + "(", + ")"); + if (StringLen(r2rStr) > 0) + { + // + double r2r = (double)r2rStr; + + // + result.r2r = r2r; + } + + // + // Volume ... + string volumeStr = ExtractString( + signalContent, + mVolumeToken + "(", + ")"); + if (StringLen(volumeStr) > 0) + { + // + double volume = (double)volumeStr; + + // + result.volume = volume; + } + + // + // SupportResistance ... + string supportResistanceStr = ExtractString( + signalContent, + mSupportResistanceToken + "(", + ")"); + if (StringLen(supportResistanceStr) > 0) + { + // + XOHCLSupRes supRes = ToSupRes(supportResistanceStr); + + // + result.supportAndResistance = supRes; + } + + // + return result; + } + + // + // Deal ... + + // + // Convert to it's String Representation ... + string ToStringFormat(const XDeal &deal) + { + // + string result = ""; + + // + DefineTokens(); + + // + result += + ExtractTypePath(X_DATA_COLLECTOR_DEAL) + + "[" + + mMagicToken + "(" + (string)deal.magic + ")" + + mPositionIDToken + "(" + (string)deal.positionId + ")" + + mTicketToken + "(" + (string)deal.ticket + ")" + + mSymbolToken + "(" + (string)deal.symbol + ")" + + mOrderToken + "(" + (string)deal.order + ")" + + mTimeToken + "(" + (string)deal.time + ")" + + mPriceToken + "(" + (string)deal.price + ")" + + mProfitToken + "(" + (string)deal.profit + ")" + + mSwapToken + "(" + (string)deal.swap + ")" + + mCommissionToken + "(" + (string)deal.commission + ")" + + mVolumeToken + "(" + (string)deal.volume + ")" + + mCommentToken + "(" + (string)deal.comment + ")" + + mTypeToken + "(" + (string)((int)deal.type) + ")" + + mEntryToken + "(" + (string)((int)deal.entry) + ")" + + mReasonToken + "(" + (string)((int)deal.reason) + ")" + + "]"; + + // + return result; + } + + // + // Converts an string to XDeal ... + XDeal ToDeal(string content) + { + // + XDeal result; + + // + DefineTokens(); + + // + string typeIdentifier = ExtractTypePath(X_DATA_COLLECTOR_DEAL); + + // + if (StringLen(content) == 0 || StringFind(content, typeIdentifier) < 0) + { + return result; + } + + // + string dealContent = ExtractString( + content, + typeIdentifier + "[", + "]"); + if (StringLen(dealContent) == 0) + { + return result; + } + + // + // Magic ... + string magicStr = ExtractString( + dealContent, + mMagicToken + "(", + ")"); + if (StringLen(magicStr) > 0) + { + // + ulong magic = (ulong)magicStr; + + // + result.magic = magic; + } + + // + // PositionID ... + string posIDStr = ExtractString( + dealContent, + mPositionIDToken + "(", + ")"); + if (StringLen(posIDStr) > 0) + { + // + ulong posID = (ulong)posIDStr; + + // + result.positionId = posID; + } + + // + // Ticket ... + string ticketStr = ExtractString( + dealContent, + mTicketToken + "(", + ")"); + if (StringLen(ticketStr) > 0) + { + // + ulong ticket = (ulong)ticketStr; + + // + result.ticket = ticket; + } + + // + // Symbol ... + string symbolStr = ExtractString( + dealContent, + mSymbolToken + "(", + ")"); + if (StringLen(symbolStr) > 0) + { + result.symbol = symbolStr; + } + + // + // Order ... + string orderStr = ExtractString( + dealContent, + mOrderToken + "(", + ")"); + if (StringLen(orderStr) > 0) + { + // + ulong order = (ulong)orderStr; + + // + result.order = order; + } + + // + // Time ... + string timeStr = ExtractString( + dealContent, + mTimeToken + "(", + ")"); + if (StringLen(timeStr) > 0) + { + // + datetime time = StringToTime(timeStr); + + // + result.time = time; + } + + // + // Price ... + string priceStr = ExtractString( + dealContent, + mPriceToken + "(", + ")"); + if (StringLen(priceStr) > 0) + { + // + double price = (double)priceStr; + + // + result.price = price; + } + + // + // Profit ... + string profitStr = ExtractString( + dealContent, + mProfitToken + "(", + ")"); + if (StringLen(profitStr) > 0) + { + // + double profit = (double)profitStr; + + // + result.profit = profit; + } + + // + // Swap ... + string swapStr = ExtractString( + dealContent, + mSwapToken + "(", + ")"); + if (StringLen(swapStr) > 0) + { + // + double swap = (double)swapStr; + + // + result.swap = swap; + } + + // + // Commission ... + string commissionStr = ExtractString( + dealContent, + mCommissionToken + "(", + ")"); + if (StringLen(commissionStr) > 0) + { + // + double commission = (double)commissionStr; + + // + result.commission = commission; + } + + // + // Volume ... + string volumeStr = ExtractString( + dealContent, + mVolumeToken + "(", + ")"); + if (StringLen(volumeStr) > 0) + { + // + double volume = (double)volumeStr; + + // + result.volume = volume; + } + + // + // Comment ... + string commentStr = ExtractString( + dealContent, + mCommentToken + "(", + ")"); + if (StringLen(commentStr) > 0) + { + result.comment = commentStr; + } + + // + // Type ... + string typeStr = ExtractString( + dealContent, + mTypeToken + "(", + ")"); + if (StringLen(typeStr) > 0) + { + // + ENUM_DEAL_TYPE type = (ENUM_DEAL_TYPE)((int)typeStr); + + // + result.type = type; + } + + // + // Entry ... + string entryStr = ExtractString( + dealContent, + mEntryToken + "(", + ")"); + if (StringLen(entryStr) > 0) + { + // + ENUM_DEAL_ENTRY entry = (ENUM_DEAL_ENTRY)((int)entryStr); + + // + result.entry = entry; + } + + // + // Reason ... + string reasonStr = ExtractString( + dealContent, + mReasonToken + "(", + ")"); + if (StringLen(reasonStr) > 0) + { + // + ENUM_DEAL_REASON reason = (ENUM_DEAL_REASON)((int)reasonStr); + + // + result.reason = reason; + } + + // + return result; + } + + // + // SUPPORT and RESISTANCES ... + string ToStringFormat(const XOHCLSupRes &item) + { + // + string result = ""; + + // + DefineTokens(); + + // + result += + ExtractTypePath(X_DATA_COLLECTOR_SUPRES) + + "[" + + mResToken + "(" + ToString(item.res) + ")" + + mSupToken + "(" + ToString(item.sup) + ")" + + "]"; + + // + return result; + } + + // + XOHCLSupRes ToSupRes(string content) + { + // + XOHCLSupRes result; + + // + DefineTokens(); + + // + string typeIdentifier = ExtractTypePath(X_DATA_COLLECTOR_SUPRES); + + // + if (StringLen(content) == 0 || StringFind(content, typeIdentifier) < 0) + { + return result; + } + + // + string mainContent = ExtractString( + content, + typeIdentifier + "[", + "]"); + if (StringLen(mainContent) == 0) + { + return result; + } + + // + // Res ... + string resStr = ExtractString( + mainContent, + mResToken + "(", + ")"); + if (StringLen(resStr) > 0) + { + // + double res[]; + string parts[]; + StringSplit( + resStr, + StringGetCharacter(",", 0), + parts); + + // + int partsCount = ArraySize(parts); + if (partsCount > 0) + { + // + for (int i = 0; i < partsCount; i++) + { + // + string iPart = parts[i]; + + // + Add( + double(iPart), + result.res); + } + } + } + + // + // Sup ... + string supStr = ExtractString( + mainContent, + mSupToken + "(", + ")"); + if (StringLen(supStr) > 0) + { + // + double sup[]; + string parts[]; + StringSplit( + supStr, + StringGetCharacter(",", 0), + parts); + + // + int partsCount = ArraySize(parts); + if (partsCount > 0) + { + // + for (int i = 0; i < partsCount; i++) + { + // + string iPart = parts[i]; + + // + Add( + double(iPart), + result.sup); + } + } + } + + // + return result; + } + + // + // Position ... + + // + // Convert to it's String Representation ... + string ToStringFormat(const XPosition &position) + { + // + string result = ""; + + // + DefineTokens(); + + // + result += + ExtractTypePath(X_DATA_COLLECTOR_POSITION) + + "[" + + mMagicToken + "(" + (string)position.magic + ")" + + mTicketToken + "(" + (string)position.ticket + ")" + + mSymbolToken + "(" + (string)position.symbol + ")" + + mPeriodToken + "(" + (string)((int)position.period) + ")" + + mTypeToken + "(" + (string)((int)position.type) + ")" + + mTPToken + "(" + (string)position.tp + ")" + + mSLToken + "(" + (string)position.sl + ")" + + mProfitToken + "(" + (string)position.profit + ")" + + mEntryToken + "(" + (string)position.entry + ")" + + mPriceToken + "(" + (string)position.price + ")" + + mSwapToken + "(" + (string)position.swap + ")" + + mCommissionToken + "(" + (string)position.commission + ")" + + mVolumeToken + "(" + (string)position.volume + ")" + + mOpenAtToken + "(" + (string)position.openAt + ")" + + mCommentToken + "(" + (string)position.comment + ")" + + "]"; + + // + return result; + } + + // + // Converts an string to XPosition ... + XPosition ToPosition(string content) + { + // + XPosition result; + + // + DefineTokens(); + + // + string typeIdentifier = ExtractTypePath(X_DATA_COLLECTOR_POSITION); + + // + if (StringLen(content) == 0 || StringFind(content, typeIdentifier) < 0) + { + return result; + } + + // + string positionContent = ExtractString( + content, + typeIdentifier + "[", + "]"); + if (StringLen(positionContent) == 0) + { + return result; + } + + // + // Magic ... + string magicStr = ExtractString( + positionContent, + mMagicToken + "(", + ")"); + if (StringLen(magicStr) > 0) + { + // + ulong magic = (ulong)magicStr; + + // + result.magic = magic; + } + + // + // Ticket ... + string ticketStr = ExtractString( + positionContent, + mTicketToken + "(", + ")"); + if (StringLen(ticketStr) > 0) + { + // + ulong ticket = (ulong)ticketStr; + + // + result.ticket = ticket; + } + + // + // Symbol ... + string symbolStr = ExtractString( + positionContent, + mSymbolToken + "(", + ")"); + if (StringLen(symbolStr) > 0) + { + result.symbol = symbolStr; + } + + // + // Period ... + string periodStr = ExtractString( + positionContent, + mPeriodToken + "(", + ")"); + if (StringLen(periodStr) > 0) + { + // + ENUM_TIMEFRAMES period = ToPeriod(periodStr); + + // + result.period = period; + } + + // + // Type ... + string typeStr = ExtractString( + positionContent, + mTypeToken + "(", + ")"); + if (StringLen(typeStr) > 0) + { + // + ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE)((int)typeStr); + + // + result.type = type; + } + + // + // TP ... + string tpStr = ExtractString( + positionContent, + mTPToken + "(", + ")"); + if (StringLen(tpStr) > 0) + { + // + double tp = (double)tpStr; + + // + result.tp = tp; + } + + // + // SL ... + string slStr = ExtractString( + positionContent, + mSLToken + "(", + ")"); + if (StringLen(slStr) > 0) + { + // + double sl = (double)slStr; + + // + result.sl = sl; + } + + // + // Profit ... + string profitStr = ExtractString( + positionContent, + mProfitToken + "(", + ")"); + if (StringLen(profitStr) > 0) + { + // + double profit = (double)profitStr; + + // + result.profit = profit; + } + + // + // Entry ... + string entryStr = ExtractString( + positionContent, + mEntryToken + "(", + ")"); + if (StringLen(entryStr) > 0) + { + // + double entry = (double)entryStr; + + // + result.entry = entry; + } + + // + // Price ... + string priceStr = ExtractString( + positionContent, + mPriceToken + "(", + ")"); + if (StringLen(priceStr) > 0) + { + // + double price = (double)priceStr; + + // + result.price = price; + } + + // + // Swap ... + string swapStr = ExtractString( + positionContent, + mSwapToken + "(", + ")"); + if (StringLen(swapStr) > 0) + { + // + double swap = (double)swapStr; + + // + result.swap = swap; + } + + // + // Commission ... + string commissionStr = ExtractString( + positionContent, + mCommissionToken + "(", + ")"); + if (StringLen(commissionStr) > 0) + { + // + double commission = (double)commissionStr; + + // + result.commission = commission; + } + + // + // Volume ... + string volumeStr = ExtractString( + positionContent, + mVolumeToken + "(", + ")"); + if (StringLen(volumeStr) > 0) + { + // + double volume = (double)volumeStr; + + // + result.volume = volume; + } + + // + // OpenAt ... + string openAtStr = ExtractString( + positionContent, + mOpenAtToken + "(", + ")"); + if (StringLen(openAtStr) > 0) + { + // + datetime openAt = StringToTime(openAtStr); + + // + result.openAt = openAt; + } + + // + // Comment ... + string commentStr = ExtractString( + positionContent, + mCommentToken + "(", + ")"); + if (StringLen(commentStr) > 0) + { + result.comment = commentStr; + } + + // + return result; + } + + // + // END Provided Functions ... + // + + // + // Protected ... +protected: + // + // Destintion Folder Path ... + string mPath; + + // + void DefineTokens() + { + + // + // Define Required Variables ... + + // + // Define Some Modifier Tokens for Type Castings ... + mProvidersToken = "PVS"; + mSymbolToken = "SBL"; + mPeriodToken = "PR"; + mTypeToken = "TYP"; + mModeToken = "MD"; + mEntryToken = "EN"; + mRiskAmountToken = "RA"; + mTPToken = "TP"; + mSLToken = "SL"; + mR2rToken = "RR"; + mVolumeToken = "VL"; + + // + mMagicToken = "MGK"; + mTicketToken = "TK"; + mProfitToken = "PFT"; + mPriceToken = "CPR"; + mSwapToken = "SWP"; + mCommissionToken = "CMS"; + mOpenAtToken = "ODT"; + mCommentToken = "CMN"; + + // + mPositionIDToken = "PID"; + mOrderToken = "ORD"; + mTimeToken = "TDT"; + mReasonToken = "RSN"; + + // + mResToken = "RES"; + mSupToken = "SUP"; + mSupportResistanceToken = "SUPRES"; + } + + // + // Private ... +private: + // + // Generate Full File Path ... + string GetFilePath(string fileName) + { + // + string result = ""; + + // + result = + // + Path() + "\\" + fileName + // + ; + + // + return result; + } + + // + // Extract Each Type Specific File Name ... + string ExtractTypePath(ENUM_X_XDATACOLLECTOR_TYPES type) + { + // + string typeStr = EnumToString(type); + + // + string typeParts[]; + StringSplit( + typeStr, + StringGetCharacter("_", 0), + typeParts); + + // + string result = typeParts[ArraySize(typeParts) - 1]; + + // + return result; + } + + // + string GenerateTypeFilePath(ENUM_X_XDATACOLLECTOR_TYPES type) + { + // + string name = ExtractTypePath(type) + ".txt"; + + // + string result = GetFilePath(name); + + // + return result; + } + + // + // Retrieve all available data types ... + void RetrieveAllAvailableTypes(ENUM_X_XDATACOLLECTOR_TYPES &result[]) + { + // + ArrayFree(result); + ArrayResize(result, 0); + + // + Add( + X_DATA_COLLECTOR_LOG, + result); + + // + Add( + X_DATA_COLLECTOR_DEAL, + result); + + // + Add( + X_DATA_COLLECTOR_SIGNAL, + result); + + // + Add( + X_DATA_COLLECTOR_SUPRES, + result); + + // + Add( + X_DATA_COLLECTOR_POSITION, + result); + } + + // + // Define Some Modifier Tokens for Type Castings ... + string mProvidersToken; + string mSymbolToken; + string mPeriodToken; + string mTypeToken; + string mModeToken; + string mEntryToken; + string mRiskAmountToken; + string mTPToken; + string mSLToken; + string mR2rToken; + string mVolumeToken; + + // + string mMagicToken; + string mTicketToken; + string mProfitToken; + string mPriceToken; + string mSwapToken; + string mCommissionToken; + string mOpenAtToken; + string mCommentToken; + + // + string mPositionIDToken; + string mOrderToken; + string mTimeToken; + string mReasonToken; + + // + string mResToken; + string mSupToken; + string mSupportResistanceToken; +}; + +// +// START Usefull Functions ... +// +void Add(ENUM_X_XDATACOLLECTOR_TYPES type, + ENUM_X_XDATACOLLECTOR_TYPES &types[]) +{ + // + ArrayResize( + types, + ArraySize(types) + 1); + + // + types[ArraySize(types) - 1] = type; +} +// +// END Usefull Functions ... +// diff --git a/MQLTestWorkspace/BKPS/BKP/Classes/x-saherelm.xnotifier.class.mq5 b/MQLTestWorkspace/BKPS/BKP/Classes/x-saherelm.xnotifier.class.mq5 new file mode 100644 index 0000000..0c653eb --- /dev/null +++ b/MQLTestWorkspace/BKPS/BKP/Classes/x-saherelm.xnotifier.class.mq5 @@ -0,0 +1,295 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XSCNotifier +// Description: provides all Base Notification requirements ... +// +// +// 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 + +// +// START Definitions ... +// + +// +// a Notification Model ... +typedef void (*OnMessage)( + string, // action ... + string // payload ... +); + +// +struct XNotifierEventListener +{ + string action; + OnMessage listeners[]; +}; + +// +// END Definitions ... +// + +// +// START Import and Inclused requirements ... +// + +// +// Includes ... +#include "../Libraries/x-saherelm.models.lib.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" + +// +// END Import and Inclused requirements ... +// + +// +// START Overrides ... +// + +// +// END Overrides ... +// + +// +// a Class for Handle base requirements ... +// for indicators ... +class XSCNotifier +{ + // + // Public ... +public: + // + // Constructor ... + void XSCNotifier() + { + } + + // + // Deconstructor ... + void ~XSCNotifier() + { + } + + // + // START Properties ... + // + + // + // END Properties ... + // + + // + // START Provided Functions ... + // + bool AddEventListener( + string action, // Specific Action ... + OnMessage listener // Specific Listener ... + ) + { + // + bool result = false; + + // + int aIndex = FindActionIndex(action); + if (aIndex < 0) + { + // + // Create a New Structure ... + XNotifierEventListener model; + + // + model.action = action; + + // + Add( + listener, + model.listeners); + + // + Add( + model, + mEventListeners); + + // + result = true; + } + else + { + // + // Just Add Listener to Exists model ... + Add( + listener, + mEventListeners[aIndex].listeners); + + // + result = true; + } + + // + return result; + } + + // + bool NotifyEvent( + string action, // action ... + string payload // payload ... + ) + { + // + bool result = false; + + // + int actionIndex = FindActionIndex(action); + result = actionIndex >= 0; + if (!result) + { + return result; + } + + // + int aListenersCount = ArraySize(mEventListeners[actionIndex].listeners); + result = aListenersCount > 0; + if (!result) + { + return result; + } + + // + for (int i = 0; i < aListenersCount; i++) + { + // + OnMessage iListener = mEventListeners[actionIndex].listeners[i]; + + // + // Call Listener ... + iListener( + action, + payload); + } + + // + return result; + } + + // + // END Provided Functions ... + // + + // + // Protected ... +protected: + // + + // + // Private ... +private: + // + XNotifierEventListener mEventListeners[]; + + // + // Find Specific Actions Index in Registered Event Listeners ... + int FindActionIndex(string action) + { + // + int result = -1; + + // + int listenersCount = ArraySize(mEventListeners); + if (listenersCount <= 0) + { + return result; + } + + // + for (int i = 0; i < listenersCount; i++) + { + // + XNotifierEventListener iModel = mEventListeners[i]; + + // + if (iModel.action == action) + { + // + result = i; + break; + } + } + + // + return result; + } +}; + +// +// START Usefull Functions ... +// + +// +void Clean( + OnMessage &buffer[] // Buffer ... +) +{ + // + ArrayFree(buffer); + + // + ArrayResize( + buffer, + 0); +} +void Clean( + XNotifierEventListener &buffer[] // Buffer ... +) +{ + // + ArrayFree(buffer); + + // + ArrayResize( + buffer, + 0); +} + +// +void Add( + OnMessage item, // Item ... + OnMessage &buffer[] // Buffer ... +) +{ + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; +} +void Add( + XNotifierEventListener &item, // Item ... + XNotifierEventListener &buffer[] // Buffer ... +) +{ + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; +} + +// +// END Usefull Functions ... +//