From e46cac2ab1c33c817773128b6807523851c0feba Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Thu, 5 Jun 2025 05:35:47 +0330 Subject: [PATCH] - Create a Data Collector Class; - Add Support for Save Logs in Alert Class; - Add Propper inputs for Handle Saving Logs in EA and Expert Class; - remove x-trade.manager Class Data Collector and use General Developed Data Collector; - Add Support for Reading Fles in Data Collector Class for Support Configuration Parsing; - Remove XCBaseAlert class and add Support for get XCAlert instance reference pointer as Dependency Injection in all used classed and Refactor all Changes; - Apply Fix some UnImplemented Event Handlers on Ea Expert Class of XCATBEA and also change Event Handler Binding to Collection Based Model; - Test all Functionalities ... - Apply Some Fixes on Prevent Double Saing Same Log Messages ... --- Classes/x-saherelm.x-alert.class.mq5 | 288 ++--- Classes/x-saherelm.x-data.collector.class.mq5 | 371 ++++++ Classes/x-saherelm.x-guard.class.mq5 | 34 +- Documents/BKP/tmp.base.signal.class.mq5 | 214 ++++ .../BKP}/x-saherelm.x-expert.class.mq5 | 0 Documents/BKP/x-saherelm.x.expert.class.mq5 | 1070 +++++++++++++++++ {Experts => Documents/BKP}/xcatb.test.ea.mq5 | 0 .../BKP}/xcatbea.x-data.collector.class.mq5 | 0 Experts/x-saherelm.x121.xcatb.ea.mq5 | 20 +- XCATBEA/Classes/xcatbea.expert.class.mq5 | 382 +++++- .../Classes/xcatbea.x-trade.manager.class.mq5 | 44 +- XCATBEA/Libraries/xcatbea.lib.mq5 | 611 ---------- 12 files changed, 2107 insertions(+), 927 deletions(-) create mode 100644 Classes/x-saherelm.x-data.collector.class.mq5 create mode 100644 Documents/BKP/tmp.base.signal.class.mq5 rename {Classes => Documents/BKP}/x-saherelm.x-expert.class.mq5 (100%) create mode 100644 Documents/BKP/x-saherelm.x.expert.class.mq5 rename {Experts => Documents/BKP}/xcatb.test.ea.mq5 (100%) rename {XCATBEA/Classes => Documents/BKP}/xcatbea.x-data.collector.class.mq5 (100%) diff --git a/Classes/x-saherelm.x-alert.class.mq5 b/Classes/x-saherelm.x-alert.class.mq5 index 227c74d7..467348fc 100644 --- a/Classes/x-saherelm.x-alert.class.mq5 +++ b/Classes/x-saherelm.x-alert.class.mq5 @@ -22,6 +22,7 @@ // // Imports ... #include "../Classes/x-saherelm.base.class.mq5" +#include "../Classes/x-saherelm.x-data.collector.class.mq5" // // Class Definition ... @@ -42,7 +43,8 @@ class XCAlert : public XCBase bool logAlerts = true, // Log Alerts bool terminalAlerts = false, // Terminal Alerts bool mailAlerts = false, // Mail Alerts - bool pushAlerts = false // Push Alerts + bool pushAlerts = false, // Push Alerts + bool saveAlerts = false // Save Alerts ) { // @@ -50,6 +52,7 @@ class XCAlert : public XCBase mLogAlerts = logAlerts; mMailAlerts = mailAlerts; mPushAlerts = pushAlerts; + mSaveAlerts = saveAlerts; mEnableAlerts = enableAlerts; mTerminalAlerts = terminalAlerts; @@ -59,12 +62,21 @@ class XCAlert : public XCBase { mPrefix = GetTag(); } + + // + // Initialize Collector ... + collector = new XCDataCollector(); + collector.Path(mPrefix); } // // Deconstructor ... ~XCAlert() { + // + // Cleanup Resources ... + delete collector; + ZeroMemory(collector); } // @@ -86,7 +98,9 @@ class XCAlert : public XCBase // void SetPrefix(string value) { + // mPrefix = value; + collector.Path(mPrefix); } // @@ -113,6 +127,18 @@ class XCAlert : public XCBase mEnableAlerts = value; } + // + bool GetSaveAlerts() + { + return mSaveAlerts; + } + + // + void SetSaveAlerts(bool value) + { + mSaveAlerts = value; + } + // bool GetPushAlerts() { @@ -166,8 +192,12 @@ class XCAlert : public XCBase return; } + // + message = PrepareMessage(message); + // Log(message); + Save(message); } // @@ -187,6 +217,7 @@ class XCAlert : public XCBase // Send Terminal Alert ... Alert(message); + Save(message); } // @@ -203,6 +234,7 @@ class XCAlert : public XCBase // // Send Mail Alert ... SendMail(GetPrefix(), message); + Save(message); } // @@ -223,6 +255,7 @@ class XCAlert : public XCBase // // Send Push Notification Alert ... SendNotification(message); + Save(message); } // @@ -1334,16 +1367,55 @@ class XCAlert : public XCBase return result; } + // + void Save(string message) + { + // + if (!mSaveAlerts || + !IsValid(message) || + message == mLastSavedMessage || + PrepareMessage(message) == mLastSavedMessage) + { + return; + } + + // + string filePath = collector.GetFilePath("XLogs"); + if (!IsValid(filePath)) + { + return; + } + + // + // Attach Time ... + string savedMessage = ToString(TimeCurrent()) + " " + message; + + // + bool has = collector.Append( + filePath, + savedMessage // + ); + if (has) + { + mLastSavedMessage = message; + } + } + private: // // Props ... string mPrefix; // Alerts Prefixe bool mEnableAlerts; // Enable Alerts + bool mSaveAlerts; // Save Alerts bool mLogAlerts; // Log Alerts bool mTerminalAlerts; // Terminal Alerts bool mMailAlerts; // Mail Alerts bool mPushAlerts; // Push Alerts + // + string mLastSavedMessage; // For Prevent Multiple Saving Same Mesage ... + XCDataCollector *collector; + // // Tools ... @@ -1363,218 +1435,4 @@ class XCAlert : public XCBase } }; -// -// a Base Class by Support Alert ... -class XCBaseAlert : public XCBase -{ - // - // Public ... - public: - // - // Props ... - - // - // Constructor(s) ... - void XCBaseAlert() - { - // - // Instance Alert ... - mAlert = new XCAlert(); - } - - // - // Deconstructors ... - void ~XCBaseAlert() - { - // - delete mAlert; - - // - ZeroMemory(mAlert); - } - - // - // Alert Handler Functions ... - - // - // Alert Functions Getter(s) / Setters(s) ... - - // - string GetAlertPrefix() - { - return mAlert.GetPrefix(); - } - - // - void SetAlertPrefix(string value) - { - mAlert.SetPrefix(value); - } - - // - bool GetAlertLogAlerts() - { - return mAlert.GetLogAlerts(); - } - - // - void SetAlertLogAlerts(bool value) - { - mAlert.SetLogAlerts(value); - } - - // - bool GetAlertEnableAlerts() - { - return mAlert.GetEnableAlerts(); - } - - // - void SetAlertEnableAlerts(bool value) - { - mAlert.SetEnableAlerts(value); - } - - // - bool GetAlertPushAlerts() - { - return mAlert.GetPushAlerts(); - } - - // - void SetAlertPushAlerts(bool value) - { - mAlert.SetPushAlerts(value); - } - - // - bool GetAlertMailAlerts() - { - return mAlert.GetMailAlerts(); - } - - // - void SetAlertMailAlerts(bool value) - { - mAlert.SetMailAlerts(value); - } - - // - bool GetAlertTerminalAlerts() - { - return mAlert.GetTerminalAlerts(); - } - - // - void SetAlertTerminalAlerts(bool value) - { - mAlert.SetTerminalAlerts(value); - } - - // - // Alert Actions ... - - // - // Logging an Alert ... - void LogAlert(string message) - { - mAlert.LogAlert(message); - } - - // - // Terminal Alert ... - void TerminalAlert(string message) - { - mAlert.TerminalAlert(message); - } - - // - // Mail Alert ... - void MailAlert(string message) - { - mAlert.MailAlert(message); - } - - // - // Send Push Notification ... - void PushAlert(string message) - { - mAlert.PushAlert(message); - } - - // - // Send an Alert by Handling all Different Specified - // type's of Alert's if they are Enabled ... - void SendAlert(string message) - { - mAlert.SendAlert(message); - } - - // - // Logs ... - - // - // Log a Message ... - void Log(string message) - { - mAlert.Log(message); - } - void Log(string tag, string message) - { - mAlert.Log(tag, message); - } - void LogEmpty() - { - mAlert.LogEmpty(); - } - - // - // Log Specific Array ... - template - void LogArray( - T &array[], // Array to Log - string label = NULL // Array Label - ) - { - mAlert.LogArray(array, label); - } - - // - // Error ... - - // - // Log an Error ... - void LogError( - int error = -1 // Specific Error, if it's equal to -1, use Last Error ... - ) - { - mAlert.LogError(error); - } - - // - // Retrieve Specified Error Code Description ... - string GetErrorDescription(int err_code) - { - return mAlert.GetErrorDescription(err_code); - } - - // - // Retrieve Specified Error Code Description ... - string GetTradeServerReturnCodeDescription(int return_code) - { - return mAlert.GetTradeServerReturnCodeDescription(return_code); - } - - // - // Protected ... - protected: - // - // Alert ... - XCAlert *mAlert; - - // - // Private ... - private: -}; - // \ No newline at end of file diff --git a/Classes/x-saherelm.x-data.collector.class.mq5 b/Classes/x-saherelm.x-data.collector.class.mq5 new file mode 100644 index 00000000..c9027d28 --- /dev/null +++ b/Classes/x-saherelm.x-data.collector.class.mq5 @@ -0,0 +1,371 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: XCDataCollector ... +// Description: Class for Handling Data Read or Write ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm Class for Handling Data Read or Write" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.base.class.mq5" + +// +// Definitions ... + +// +// Implementation ... +class XCDataCollector : public XCBase +{ + // + // Public ... + public: + // + // Constructors ... + XCDataCollector() + { + mPath = "XDataCollector"; + } + + // + // Deconstructor ... + ~XCDataCollector() + { + } + + // + // Properties ... + + // + string Path() + { + return mPath; + } + + // + void Path(string value) + { + // + // Normalizing Collector Path ... + if (IsValid(value)) + { + mPath = value; + } + else + { + mPath = "XDataCollector"; + } + } + + // + // Tools ... + + // + string GetFilePath(string fileName) + { + // + string result = ""; + + // + result = + // + mPath + "\\" + fileName + ".x121.log" + // + ; + + // + return result; + } + + // + int GetFileHandlerForWrite(string filePath) + { + // + int result = INVALID_HANDLE; + + // + if (!IsValid(filePath)) + { + return result; + } + + // + result = FileOpen( + filePath, + FILE_READ | FILE_WRITE | FILE_TXT // + ); + + // + return result; + } + + // + int GetFileHandlerForRead(string filePath) + { + // + int result = INVALID_HANDLE; + + // + if (!IsValid(filePath)) + { + return result; + } + + // + result = FileOpen( + filePath, + FILE_READ | FILE_TXT // + ); + + // + return result; + } + + /** + * Save Specified Content into Specified File Name ... + * + * @param fileName: string, file name ... + * @param content: string, content ... + * + * @return ( bool ) + */ + bool Save( + string fileName, + string content // + ) + { + // + bool result = false; + + // + result = IsValid(fileName) && + IsValid(content); + if (!result) + { + return result; + } + + // + int mHandler = GetFileHandlerForWrite(fileName); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + FileWrite(mHandler, content); + FileFlush(mHandler); + FileClose(mHandler); + + // + return result; + } + + /** + * Append Specified Content into Specified File Name ... + * + * @param fileName: string, file name ... + * @param content: string, content ... + * + * @return ( bool ) + */ + bool Append( + string fileName, + string content // + ) + { + // + bool result = false; + + // + result = IsValid(fileName) && + IsValid(content); + if (!result) + { + return result; + } + + // + int mHandler = GetFileHandlerForWrite(fileName); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + FileSeek(mHandler, 0, SEEK_END); + FileWrite(mHandler, content); + FileFlush(mHandler); + FileClose(mHandler); + + // + return result; + } + + /** + * Read Specified File Content ... + * + * @param fileName: string, file name ... + * @param content: string reference, hold's reading content ... + * + * @return ( bool ) + */ + bool Read( + string fileName, + string &content // + ) + { + // + bool result = false; + + // + // Normalize Args ... + content = NULL; + + // + // Validate Args ... + result = IsValid(fileName); + if (!result) + { + return result; + } + + // + int mHandler = GetFileHandlerForRead(fileName); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // Reading File ... + while (!FileIsEnding(mHandler)) + { + // + string iLine = FileReadString(mHandler); + content += iLine; + } + + // + // Close File ... + FileClose(mHandler); + + // + return result; + } + + /** + * Read Specified File Content ... + * + * @param fileName: string, file name ... + * @param content: string reference collection, hold's reading content lines ... + * + * @return ( bool ) + */ + bool Read( + string fileName, + string &content[] // + ) + { + // + bool result = false; + + // + // Normalize Args ... + Clean(content); + + // + // Validate Args ... + result = IsValid(fileName); + if (!result) + { + return result; + } + + // + int mHandler = GetFileHandlerForRead(fileName); + result = mHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + + // + // Reading File ... + while (!FileIsEnding(mHandler)) + { + // + string iLine = FileReadString(mHandler); + Add( + iLine, + content // + ); + } + + // + // Close File ... + FileClose(mHandler); + + // + return result; + } + + /** + * Check Specified File Exists or not ... + * + * @param fileName: string, Full Path of File to Check ... + * + * @return ( bool ) + */ + bool IsExists(string fileName) + { + // + bool result = false; + + // + // Validate Args ... + result = IsValid(fileName); + if (!result) + { + return result; + } + + // + // Check File Exists or not ... + int mHandler = GetFileHandlerForRead(fileName); + result = mHandler != INVALID_HANDLE; + FileClose(mHandler); + + // + return result; + } + + // + // Protected ... + protected: + // + // Private ... + private: + // + // Props ... + + // + string mPath; // Base Collector Path ... +}; diff --git a/Classes/x-saherelm.x-guard.class.mq5 b/Classes/x-saherelm.x-guard.class.mq5 index 0213aa60..eddbf3ae 100644 --- a/Classes/x-saherelm.x-guard.class.mq5 +++ b/Classes/x-saherelm.x-guard.class.mq5 @@ -213,7 +213,7 @@ int AddGuard( // // Implementation ... -class XCGuard : public XCBaseAlert +class XCGuard : public XCBase { // // public ... @@ -226,10 +226,12 @@ class XCGuard : public XCBaseAlert // // Constructor(s) ... XCGuard( - XCTrade *&_trader // + XCAlert *_alert, + XCTrade *_trader // ) { // + alert = _alert; trader = _trader; // @@ -242,6 +244,7 @@ class XCGuard : public XCBaseAlert ~XCGuard() { // + ZeroMemory(alert); ZeroMemory(trader); } @@ -1005,7 +1008,7 @@ class XCGuard : public XCBaseAlert " Position (" + ToString(position.ticket) + ") Successfully ..."; // - SendAlert(message); + alert.SendAlert(message); } // @@ -1070,7 +1073,7 @@ class XCGuard : public XCBaseAlert " Positions Successfully ..."; // - SendAlert(message); + alert.SendAlert(message); } // @@ -1135,7 +1138,7 @@ class XCGuard : public XCBaseAlert " In Lost Positions Successfully ..."; // - SendAlert(message); + alert.SendAlert(message); } // @@ -1200,7 +1203,7 @@ class XCGuard : public XCBaseAlert " In Profit Positions Successfully ..."; // - SendAlert(message); + alert.SendAlert(message); } // @@ -1265,7 +1268,7 @@ class XCGuard : public XCBaseAlert " Long Positions Successfully ..."; // - SendAlert(message); + alert.SendAlert(message); } // @@ -1330,7 +1333,7 @@ class XCGuard : public XCBaseAlert " In Lost Longs Positions Successfully ..."; // - SendAlert(message); + alert.SendAlert(message); } // @@ -1395,7 +1398,7 @@ class XCGuard : public XCBaseAlert " In Profit Longs Positions Successfully ..."; // - SendAlert(message); + alert.SendAlert(message); } // @@ -1477,7 +1480,7 @@ class XCGuard : public XCBaseAlert " In Lost Shorts Positions Successfully ..."; // - SendAlert(message); + alert.SendAlert(message); } // @@ -1542,7 +1545,7 @@ class XCGuard : public XCBaseAlert " In Profit Shorts Positions Successfully ..."; // - SendAlert(message); + alert.SendAlert(message); } // @@ -1634,7 +1637,7 @@ class XCGuard : public XCBaseAlert " Position (" + ToString(position.ticket) + ") Successfully ..."; // - SendAlert(message); + alert.SendAlert(message); } // @@ -1743,7 +1746,7 @@ class XCGuard : public XCBaseAlert " Successfully ..."; // - SendAlert(message); + alert.SendAlert(message); } // @@ -1848,7 +1851,7 @@ class XCGuard : public XCBaseAlert " Successfully ..."; // - SendAlert(message); + alert.SendAlert(message); } // @@ -1983,7 +1986,7 @@ class XCGuard : public XCBaseAlert " Successfully ..."; // - SendAlert(message); + alert.SendAlert(message); } // @@ -1998,6 +2001,7 @@ class XCGuard : public XCBaseAlert private: // XCTrade *trader; + XCAlert *alert; // }; diff --git a/Documents/BKP/tmp.base.signal.class.mq5 b/Documents/BKP/tmp.base.signal.class.mq5 new file mode 100644 index 00000000..7ddfc929 --- /dev/null +++ b/Documents/BKP/tmp.base.signal.class.mq5 @@ -0,0 +1,214 @@ + +// +// a Base Class by Support Alert ... +class XCBaseAlert : public XCBase +{ + // + // Public ... + public: + // + // Props ... + + // + // Constructor(s) ... + void XCBaseAlert() + { + // + // Instance Alert ... + mAlert = new XCAlert(); + } + + // + // Deconstructors ... + void ~XCBaseAlert() + { + // + delete mAlert; + + // + ZeroMemory(mAlert); + } + + // + // Alert Handler Functions ... + + // + // Alert Functions Getter(s) / Setters(s) ... + + // + string GetAlertPrefix() + { + return mAlert.GetPrefix(); + } + + // + void SetAlertPrefix(string value) + { + mAlert.SetPrefix(value); + } + + // + bool GetAlertLogAlerts() + { + return mAlert.GetLogAlerts(); + } + + // + void SetAlertLogAlerts(bool value) + { + mAlert.SetLogAlerts(value); + } + + // + bool GetAlertEnableAlerts() + { + return mAlert.GetEnableAlerts(); + } + + // + void SetAlertEnableAlerts(bool value) + { + mAlert.SetEnableAlerts(value); + } + + // + bool GetAlertPushAlerts() + { + return mAlert.GetPushAlerts(); + } + + // + void SetAlertPushAlerts(bool value) + { + mAlert.SetPushAlerts(value); + } + + // + bool GetAlertMailAlerts() + { + return mAlert.GetMailAlerts(); + } + + // + void SetAlertMailAlerts(bool value) + { + mAlert.SetMailAlerts(value); + } + + // + bool GetAlertTerminalAlerts() + { + return mAlert.GetTerminalAlerts(); + } + + // + void SetAlertTerminalAlerts(bool value) + { + mAlert.SetTerminalAlerts(value); + } + + // + // Alert Actions ... + + // + // Logging an Alert ... + void LogAlert(string message) + { + mAlert.LogAlert(message); + } + + // + // Terminal Alert ... + void TerminalAlert(string message) + { + mAlert.TerminalAlert(message); + } + + // + // Mail Alert ... + void MailAlert(string message) + { + mAlert.MailAlert(message); + } + + // + // Send Push Notification ... + void PushAlert(string message) + { + mAlert.PushAlert(message); + } + + // + // Send an Alert by Handling all Different Specified + // type's of Alert's if they are Enabled ... + void SendAlert(string message) + { + mAlert.SendAlert(message); + } + + // + // Logs ... + + // + // Log a Message ... + void Log(string message) + { + mAlert.Log(message); + } + void Log(string tag, string message) + { + mAlert.Log(tag, message); + } + void LogEmpty() + { + mAlert.LogEmpty(); + } + + // + // Log Specific Array ... + template + void LogArray( + T &array[], // Array to Log + string label = NULL // Array Label + ) + { + mAlert.LogArray(array, label); + } + + // + // Error ... + + // + // Log an Error ... + void LogError( + int error = -1 // Specific Error, if it's equal to -1, use Last Error ... + ) + { + mAlert.LogError(error); + } + + // + // Retrieve Specified Error Code Description ... + string GetErrorDescription(int err_code) + { + return mAlert.GetErrorDescription(err_code); + } + + // + // Retrieve Specified Error Code Description ... + string GetTradeServerReturnCodeDescription(int return_code) + { + return mAlert.GetTradeServerReturnCodeDescription(return_code); + } + + // + // Protected ... + protected: + // + // Alert ... + XCAlert *mAlert; + + // + // Private ... + private: +}; diff --git a/Classes/x-saherelm.x-expert.class.mq5 b/Documents/BKP/x-saherelm.x-expert.class.mq5 similarity index 100% rename from Classes/x-saherelm.x-expert.class.mq5 rename to Documents/BKP/x-saherelm.x-expert.class.mq5 diff --git a/Documents/BKP/x-saherelm.x.expert.class.mq5 b/Documents/BKP/x-saherelm.x.expert.class.mq5 new file mode 100644 index 00000000..ef09eb3e --- /dev/null +++ b/Documents/BKP/x-saherelm.x.expert.class.mq5 @@ -0,0 +1,1070 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Base Expert Class +// ------------------------------------------------- +// Name: XCExpert ... +// Description: Base Expert Class ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm Base Expert Class" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.x-guard.class.mq5" +#include "../Classes/x-saherelm.x-trade.class.mq5" +#include "../Classes/x-saherelm.x-volume.class.mq5" + +// +// Definitions ... + +// +// Implementation ... +class XCExpert : public XCBase +{ + // + // public ... + public: + // + // Props ... + + // + // Common ... + long eaMagicNumber; // Magic Number + int eaSlippage; // Slippgae + string eaLogSuffix; // Log Suffix + + // + // Volume ... + ENUM_X_VOLUME_SELECT_TYPE eaVolumeSelect; // Volume Applying Type + double eaStaticVoluem; // Static Volume + double eaDynamicVolumeStepBalance; // Step of Balance for Increase Volume + double eaDynamicVolumeStepVolume; // Step of Volume Increasing + double eaConstantRiskBalance; // Constant Risk Balance per Trade + double eaConstantPercent; // Constant Percent of Balance Per Trade + double eaConstantBalance; // Constant Balance for Calculations + + // + // Management ... + string eaSymbols; // Allowed Trading Symbols + bool eaAllowGuards; // Allow Guards + bool eaAllowTrade; // Allow Trade on Signals + bool eaAllowLongs; // Allow Long Trades + bool eaAllowShorts; // Allow Short Trades + ENUM_XCATBEA_TRADE_RESTRICTION_PERIOD eaRestrictionsPeriod; // Restrictions Period + int eaMaxAllowedTPs; // Max Allowed TP(s) in Restrictions Period + int eaMaxAllowedSLs; // Max Allowed SL(s) in Restrictions Period + int eaMaxAllowedTrades; // Max Allowed Trades in Restrictions Period + int eaMaxAllowedPositions; // Max Allowed Same Time Trades + double eaMaxAllowedSpread; // Max Allowed Spread For Trade + double eaMaxAllowedDrawdownFactor; // Max Allowed DrawDown for Trade + string eaCloseAllOpenTradesAt; // Close All Open Trades per Day At Specified Time + + // + // Alert ... + bool eaEnableAlerts; // Enable Alerts + bool eaSaveAlerts; // Save Alerts + bool eaLogAlerts; // Log Alerts + bool eaMailAlerts; // Mail Alerts + bool eaPushAlerts; // Push Alerts + bool eaTerminalAlerts; // Terminal Alerts + + // + // Time Report ... + bool eaReportNewMonths; // Report New Month + bool eaReportNewWeeks; // Report New Weeks + bool eaReportNewDays; // Report New Days + bool eaReportNewHours; // Report New Hours + bool eaReportTrades; // Report Trades + bool eaReportSignals; // Report Signals + bool eaReportProtector; // Report Protector Actions + bool eaReportRestrictions; // Report Restrictions + bool eaReportAfterTradesBalance; // Report Balance after a Trade Finished + + // + // Collector ... + bool eaSaveTrades; // Save Trades + bool eaSaveSignals; // Save Signals + bool eaSaveWins; // Save Winning Conditions + bool eaSaveLosts; // Save Lost Conditions + bool eaSaveRestrictions; // Save Restriction Reports + + // + // Trade Event Handlers ... + TOnModify OnModifyEventHandler; + TOnStopLoss OnStopLossEventHandler; + TOnForceClose OnForceCloseEventHandler; + TOnTakeProfit OnTakeProfitEventHandler; + TOnPartialClose OnPartialCloseEventHandler; + TOnDealsChanged OnDealsChangedEventHandler; + TOnOrdersChanged OnOrdersChangedEventHandler; + TOnPositionsChanged OnPositionsChangedEventHandler; + TOnTradeStateChanged OnTradeStateChangedEventHandler; + + // + // Requirements ... + + // + XCAlert *eaAlert; // EA Scope Alert Handler ... + XCTrade *eaTrade; // EA Scope Trade Handler ... + XCGuard *eaGuard; // EA Scope Guard Handler ... + XCVolume *eaVolume; // EA Scope Voluem Handler ... + XTimeTracker eaTimeTracker; // EA Scope Time Tracker ... + + // + // Tools / Actions / Handlers ... + + // + // Validators ... + + /** + * Validate Inputs ... + * + * @return ( bool ) + */ + bool ValidateInputs() + { + // + bool result = false; + + // + // Implement all Inputs Validation ... + result = eaMagicNumber > 0 && + eaSignalR2R > 0; + + // + return result; + } + + // + // Expert Advisor Event Handlers ... + + /** + * Handle Initialization of Expert ... + * + * @return ( bool ) + */ + bool HandleOnInit() + { + // + bool result = false; + + // + // Validate Inputs ... + result = ValidateInputs(); + if (!result) + { + return result; + } + + // + // Initialize Alert Handler ... + eaAlert = new XCAlert(); + eaAlert.SetPrefix(eaLogSuffix); + eaAlert.SetLogAlerts(eaLogAlerts); + eaAlert.SetMailAlerts(eaMailAlerts); + eaAlert.SetPushAlerts(eaPushAlerts); + eaAlert.SetEnableAlerts(eaEnableAlerts); + eaAlert.SetTerminalAlerts(eaTerminalAlerts); + + // + // Initialize Volume Manager ... + eaVolume = new XCVolume(); + result = eaVolume.Init( + eaVolumeSelect, + eaStaticVoluem, + eaDynamicVolumeStepBalance, + eaDynamicVolumeStepVolume, + eaConstantRiskBalance, + eaConstantPercent, + eaConstantBalance // + ); + if (!result) + { + return result; + } + + // + // Initialize Trader ... + eaTrade = new XCTrade( + eaSlippage, + eaMagicNumber, + eaMaxAllowedSpread, + eaMaxAllowedPositions, + eaMaxAllowedDrawdownFactor // + ); + eaTrade.AddOnStopLossEventHandler(OnStopLossEventHandler); + eaTrade.AddOnTakeProfitEventHandler(OnTakeProfitEventHandler); + eaTrade.AddOnModifyPositionEventHandler(OnModifyEventHandler); + eaTrade.AddOnDealsChangedEventHandler(OnDealsChangedEventHandler); + eaTrade.AddOnOrdersChangedEventHandler(OnOrdersChangedEventHandler); + eaTrade.AddOnForceClosePositionEventHandler(OnForceCloseEventHandler); + eaTrade.AddOnPartialClosePositionEventHandler(OnPartialCloseEventHandler); + eaTrade.AddOnPositionsChangedEventHandler(OnPositionsChangedEventHandler); + eaTrade.AddOnTradeStateChangedEventHandler(OnTradeStateChangedEventHandler); + + // + // Initialize Guard Handler ... + eaGuard = new XCGuard( + eaAlert, + eaTrade // + ); + + // + // Initialize Trae Manager ... + eaTradeManager = new XCXCATBEATradeManager( + eaAlert, + eaTrade // + ); + + // + eaTradeManager.SaveWins(eaSaveWins); + eaTradeManager.SaveLosts(eaSaveLosts); + eaTradeManager.SaveTrades(eaSaveTrades); + eaTradeManager.SaveSignals(eaSaveSignals); + eaTradeManager.SaveRestrictions(eaSaveRestrictions); + + // + // Enable Force Close At ... + eaTradeManager.SetForceCloseTradesAt(eaCloseAllOpenTradesAt); + + // + // Setting Trade Reports ... + eaTradeManager + .SetTradeReports( + eaReportTrades, + eaReportSignals, + eaReportProtector, + eaReportRestrictions, + eaReportAfterTradesBalance // + ); + + // + // Setting Trade Permissions ... + eaTradeManager + .SetTradePermissions( + eaAllowTrade, + eaAllowLongs, + eaAllowShorts // + ); + + // + // Setting Trade Restrictions ... + eaTradeManager + .SetTradeRestrictions( + eaRestrictionsPeriod, + eaMaxAllowedTPs, + eaMaxAllowedSLs, + eaMaxAllowedTrades // + ); + + // + // Parsing Symbols ... + + // + string symbols[]; + int symbolsCount = 0; + if (IsValid(eaSymbols)) + { + // + symbolsCount = SplitContent( + symbols, + eaSymbols, + "," // + ); + } + + // + // Adding Default Symbol, if eaSymbols not Filled ... + if (!HasChild(symbols)) + { + // + Add( + _Symbol, + symbols // + ); + + // + symbolsCount = ArraySize(symbols); + } + bool hasSymbols = HasChild(symbols); + + // + // Initializing Sessions ... + string sessions[]; + int sessionsCount = 0; + bool hasSession = IsValid(eaSessions); + if (hasSession) + { + // + // Extract Per Symbol Sessions ... + sessionsCount = SplitContent( + sessions, + eaSessions, + "," // + ); + + // + // Try to Extract Start and End Times Series ... + hasSession = IsValidSize(sessionsCount); + if (hasSession) + { + // + // Iterate Sessions ... + for (int i = 0; i < sessionsCount; i++) + { + // + // Ignore unused Cases and Extracts only Content ... + string iSessionDescriptorStr = ExtractString(sessions[i]); + bool isInited = IsValid(iSessionDescriptorStr); + if (isInited) + { + // + // Extract Session Descriptor Data ... + string parts[]; + int partsCount = SplitContent( + parts, + iSessionDescriptorStr, + "_" // + ); + isInited = IsValidSize(partsCount) && partsCount == 3; + if (isInited) + { + // + string iName = parts[0]; + string iStart = parts[1]; + string iEnd = parts[2]; + isInited = IsValid(iName) && + IsValid(iStart) && + IsValid(iEnd); + if (isInited) + { + // + // Set Active Session Per Symbols ... + if (hasSymbols) + { + // + for (int j = 0; j < symbolsCount; j++) + { + // + eaTradeManager + .SetTradeSession( + symbols[j], + iStart, + iEnd, + iName // + ); + } + } + } + } + } + } + } + } + + // + // Initialize Signallers ... + if (hasSymbols) + { + // + // Prepare Signaller Inputs ... + XCATBEASignallerInputs iSignallerInputs; + + // + // Common Configs ... + + // + // Provider Name ... + iSignallerInputs.period = _Period; + iSignallerInputs.allowDraws = true; + iSignallerInputs.provider = "XTRGB"; + iSignallerInputs.allowGuards = eaAllowGuards; + iSignallerInputs.riskToRewardRatio = eaSignalR2R; + iSignallerInputs.slATRMultiplier = eaSLATRMultiplier; + + // + // CATB Indicator ... + iSignallerInputs.catbInputs.Default(); + iSignallerInputs.catbInputs.Hide(); + + // + // Make Available all Requirement Buffers of XCATB indicator ... + iSignallerInputs.catbInputs.showPV = false; + iSignallerInputs.catbInputs.showKI = false; + iSignallerInputs.catbInputs.showSar = false; + iSignallerInputs.catbInputs.showTrend = false; + iSignallerInputs.catbInputs.showATRBand = false; + iSignallerInputs.catbInputs.showPVGolden = false; + + // + // Signalling Configurations ... + iSignallerInputs.signallerConfigs.allowSignallingBasedOnConditions = eaAllowSignallingBasedOnConditions; + iSignallerInputs.signallerConfigs.allowSignallingBasedOnTriggerBlocks = eaAllowSignallingBasedOnTriggerBlocks; + iSignallerInputs.signallerConfigs.secondsTriggersSLUsingFirstTriggerBlock = eaSecondsTriggersSLUsingFirstTriggerBlock; + iSignallerInputs.signallerConfigs.applyValidateAndFilterOnSelectInsideOthers = eaApplyValidateAndFilterOnSelectInsideOthers; + iSignallerInputs.signallerConfigs.allowSignallingBasedOnTriggerBlocksInsideOther = eaAllowSignallingBasedOnTriggerBlocksInsideOther; + iSignallerInputs.signallerConfigs.allowSignallingConditions1 = eaAllowSignallingConditions1; + iSignallerInputs.signallerConfigs.allowSignallingConditions2 = eaAllowSignallingConditions2; + iSignallerInputs.signallerConfigs.allowSignallingConditions3 = eaAllowSignallingConditions3; + iSignallerInputs.signallerConfigs.allowSignallingConditions4 = eaAllowSignallingConditions4; + iSignallerInputs.signallerConfigs.allowSignallingConditions5 = eaAllowSignallingConditions5; + iSignallerInputs.signallerConfigs.allowSignallingConditions6 = eaAllowSignallingConditions6; + // + // Prepare Trigger Block Validations ... + + // + iSignallerInputs.validations.forceHasSwing = eaForceHasSwing; + iSignallerInputs.validations.forceOBBarType = eaForceOBBarType; + iSignallerInputs.validations.minRequiredOBBar = eaMinRequiredOBBar; + iSignallerInputs.validations.forceFVGBarType = eaForceFVGBarType; + iSignallerInputs.validations.liquidityLoopback = eaLiquidityLoopback; + iSignallerInputs.validations.maxAllowedRange = eaMaxAllowedRange; + iSignallerInputs.validations.minAllowedRange = eaMinAllowedRange; + iSignallerInputs.validations.forceHasFLiquidity = eaForceHasFLiquidity; + iSignallerInputs.validations.forceHasRLiquidity = eaForceHasRLiquidity; + iSignallerInputs.validations.validateGapSequence = eaValidateGapSequence; + iSignallerInputs.validations.minAllowedBlockLength = eaMinAllowedBlockLength; + iSignallerInputs.validations.validateBlockEdgeBreakout = eaValidateBlockEdgeBreakout; + + // + // Prepare Trigger Block Filters ... + + // + iSignallerInputs.filters.filterBasedOnPV = eaFilterBasedOnPV; + iSignallerInputs.filters.bosLoopback = eaBosLoopback; + + // + iSignallerInputs.filters.filterBasedOnSar = eaFilterBasedOnSar; + iSignallerInputs.filters.forceSarSwitched = eaForceSarSwitched; + iSignallerInputs.filters.forceSarOnBothSide = eaForceSarOnBothSide; + iSignallerInputs.filters.forceSarHasBreakout = eaForceSarHasBreakout; + iSignallerInputs.filters.forceSarHasReversalSide = eaForceSarHasReversalSide; + + // + iSignallerInputs.filters.filterBasedOnRSI = eaFilterBasedOnRSI; + iSignallerInputs.filters.forceHasRSITrending = eaForceHasRSITrending; + iSignallerInputs.filters.forceHasRSIVPattern = eaForceHasRSIVPattern; + iSignallerInputs.filters.forceHasRSICrossing = eaForceHasRSICrossing; + + // + iSignallerInputs.filters.filterBasedOnADX = eaFilterBasedOnADX; + iSignallerInputs.filters.forceHasADXTrending = eaForceHasADXTrending; + iSignallerInputs.filters.forceHasADXCrossing = eaForceHasADXCrossing; + + // + iSignallerInputs.filters.filterBasedOnATR = eaFilterBasedOnATR; + iSignallerInputs.filters.forceHasATRTrending = eaForceHasATRTrending; + iSignallerInputs.filters.forceHasATRBreakout = eaForceHasATRBreakout; + + // + iSignallerInputs.filters.filterBasedOnTrend = eaFilterBasedOnTrend; + iSignallerInputs.filters.forceHasTrendDir = eaForceHasTrendDir; + iSignallerInputs.filters.forceHasTrendPlace = eaForceHasTrendPlace; + iSignallerInputs.filters.forceHasTrendChange = eaForceHasTrendChange; + iSignallerInputs.filters.forceHasTrendTrending = eaForceHasTrendTrending; + iSignallerInputs.filters.forceHasTrendRejection = eaForceHasTrendRejection; + iSignallerInputs.filters.forceHasTrendLineInside = eaForceHasTrendLineInside; + iSignallerInputs.filters.forceHasTrendDirOnBothSide = eaForceHasTrendDirOnBothSide; + + // + iSignallerInputs.filters.filterBasedOnKI = eaFilterBasedOnKI; + iSignallerInputs.filters.filterBasedOnDelta = eaFilterBasedOnDelta; + iSignallerInputs.filters.filterBasedOnVolume = eaFilterBasedOnVolume; + iSignallerInputs.filters.filterBasedOnSignalBar = eaFilterBasedOnSignalBar; + iSignallerInputs.filters.filterBasedOnHKSignalBar = eaFilterBasedOnHKSignalBar; + + // + // Loop through Symbols and Initialize Signaller + // for it, then Attached it to eaSignallers ... + for (int i = 0; i < symbolsCount; i++) + { + // + iSignallerInputs.symbol = symbols[i]; + if (iSignallerInputs.IsValid()) + { + // + // Initialize Signaller ... + XCXCATBEASignaller *iSignaller = new XCXCATBEASignaller(iSignallerInputs); + + // + // Add it to the Signallers List ... + Add( + iSignaller, + eaSignallers // + ); + + // + ZeroMemory(iSignaller); + } + } + + // + // Cleanup Resources ... + iSignallerInputs.Clean(); + } + + // + // since atleast one Signaller must + // exists to Expert works ... + // we check it as Last Step ... + result = hasSymbols && + HasChild(eaSignallers); + if (result) + { + // + string message = "Initialized Successfully ..."; + eaAlert.SendAlert(message); + } + else + { + // + string message = "Initialization Failed ..."; + eaAlert.SendAlert(message); + } + + // + return result; + } + + /** + * Handle De Initialization of Expert ... + */ + void HandleOnDeInit() + { + // + delete eaTrade; + ZeroMemory(eaTrade); + + // + delete eaGuard; + ZeroMemory(eaGuard); + + // + delete eaVolume; + ZeroMemory(eaVolume); + + // + eaTimeTracker.Clean(); + + // + Clean(eaSignallers); + + // + delete eaTradeManager; + ZeroMemory(eaTradeManager); + + // + string message = "DeInitialized Successfully ..."; + eaAlert.SendAlert(message); + + // + delete eaAlert; + ZeroMemory(eaAlert); + } + + /** + * Handle Tick ... + */ + void HandleOnTick() + { + // + // Time Report Handling ... + HandleTimeReport(); + + // + // Position Management / Protections Handling ... + eaTradeManager.Manage(); + + // + // Check Signallers Registered ... + bool has = HasChild(eaSignallers); + if (!has) + { + return; + } + + // + // Define Collection of Requirements ... + XGuard guards[]; + XCATBEAStrategyConditions conditions[]; + + // + // Loop through Registered Signallers to Proccess Ticks and + // Collect: + // - Guards; + // - Triggered Conditions; + // - ... + int count = ArraySize(eaSignallers); + for (int i = 0; i < count; i++) + { + // + // Retrieve indexed Signaller ... + XCXCATBEASignaller *iSignaller = eaSignallers[i]; + + // + string iSymbol = iSignaller.GetSymbol(); + string iProvider = iSignaller.GetProvider(); + ENUM_TIMEFRAMES iPeriod = iSignaller.GetPeriod(); + + // + // Now we Have to Check Handle Tick Resoult ... + + // + // Requirements ... + XGuard iGuards[]; // Hold Provided Guards ... + XPosition iPositions[]; // Retrieve Signaller Positions ... + XCATBEAStrategyConditions iConditions; // Recieve Triggered Conditions ... + + // + // Check Active Session ... + bool isActiveSession = eaTradeManager.IsActiveSession(iSymbol); + + // + // Reading Signaller Positions ... + eaTradeManager.GetPositions( + iPositions, + iSymbol, + iProvider, + iPeriod // + ); + + // + // Processing Tick for Signaller ... + iSignaller.ProcessTick( + iPositions, + iGuards, + iConditions, + isActiveSession // + ); + + // + // Check Results ... + has = HasChild(iGuards); + if (has) + { + // + Copy( + iGuards, + guards, + false // Force Clean ... + ); + } + + // + // Check Triggered Conditions ... + has = iConditions.IsValid() && + iConditions.IsSetuped() && + iConditions.CanTrigger(); + if (has) + { + // + AddRef( + iConditions, + conditions // + ); + } + + // + // Cleanup Resources ... + Clean(iGuards); + Clean(iPositions); + iConditions.Clean(); + } + + // + // Do Actions Based on Provided Info ... + + // + // Guards ... + has = HasChild(guards); + if (has) + { + // + // Handle Guards Firing ... + eaGuard.DoGuards(guards); + } + + // + // Triggers ... + has = HasChild(conditions); + if (has) + { + // + // Handle Conditions Triggering ... + TriggerConditions(conditions); + } + + // + // Cleanup Resources ... + + // + Clean(guards); + Clean(conditions); + } + + /** + * Handle Trade ... + */ + void HandleOnTrade() + { + } + + /** + * Handle Timer ... + */ + void HandleOnTimer() + { + } + + /** + * Handle Chart Event ... + * + * @param id: int, Event id ... + * @param lparam: long, Event Long Parameter ... + * @param dparam: double, Event Double Parameter ... + * @param sparam: string, Event String Parameter ... + */ + void HandleOnChartEvent( + const int id, + const long &lparam, + const double &dparam, + const string &sparam // + ) + { + } + + // + // Trade Event Handlers ... + + /** + * Handle Stop Loss Event Triggered ... + * + * @param deal: XDeal instance refrence, provides Triggered Deal info ... + */ + void HandleOnStopLossTriggered(const XDeal &deal) + { + } + + /** + * Handle Take Profit Event Triggered ... + * + * @param deal: XDeal instance refrence, provides Triggered Deal info ... + */ + void HandleOnTakeProfitTriggered(const XDeal &deal) + { + } + + /** + * Handle Position Force Closed Event ... + * + * @param ticket: ulong, triggered Positions ticket ... + * @param position: XPosition instance refrence, Triggered Position ... + * @param comment: string, Comment ... + */ + void HandleOnPositionForceClosed( + const ulong ticket, + const XPosition &position, + const string comment // + ) + { + } + + /** + * Handle Position Modified Event ... + * + * @param ticket: ulong, triggered Positions ticket ... + * @param profit: double, Position Profit ... + * @param comment: string, Comment ... + */ + void HandleOnPositionModified( + const ulong ticket, + const double profit, + const string comment // + ) + { + } + + /** + * Handle Position Partially Closed Event ... + * + * @param ticket: ulong, triggered Positions ticket ... + * @param profit: double, Position Profit ... + * @param comment: string, Comment ... + */ + void HandleOnPositionPartialClosed( + const ulong ticket, + const double profit, + const string comment // + ) + { + } + + /** + * Handle Deals Changed ... + * + * @param count: int, number of changes ... + * if the count is positive, means new added ... + * if the count is negative, means removed ... + */ + void HandleOnDealsChanged(int count) + { + } + + /** + * Handle Orders Changed ... + * + * @param count: int, number of changes ... + * if the count is positive, means new added ... + * if the count is negative, means removed ... + */ + void HandleOnOrdersChanged(int count) + { + } + + /** + * Handle Positions Changed ... + * + * @param count: int, number of changes ... + * if the count is positive, means new added ... + * if the count is negative, means removed ... + */ + void HandleOnPositionsChanged(int count) + { + } + + /** + * Handle all Trades States Changed Event ... + * + * @param state: XOnTradeHandlerState instance refrence, Changed Trade State data ... + */ + void HandleOnTradeStateChanged(const XOnTradeHandlerState &state) + { + } + + // + // protected ... + protected: + // + + /** + * Report Time Changes based on Given Configurations ... + */ + void HandleTimeReport() + { + // + if (eaAlert == NULL) + { + return; + } + + // + // Monthly Report .... + if (eaReportNewMonths && + eaTimeTracker.IsNewMonth()) + { + // + string msg = "New Month ..."; + + // + eaAlert.SendAlert(msg); + } + + // + // Weekly Report .... + if (eaReportNewWeeks && + eaTimeTracker.IsNewWeek()) + { + // + string msg = "New Week ..."; + + // + eaAlert.SendAlert(msg); + } + + // + // Daily Report .... + if (eaReportNewDays && + eaTimeTracker.IsNewDay()) + { + // + string msg = "New Day ..."; + + // + eaAlert.SendAlert(msg); + } + + // + // Hourly Report .... + if (eaReportNewHours && + eaTimeTracker.IsNewHour()) + { + // + string msg = "New Hour ..."; + + // + eaAlert.SendAlert(msg); + } + } + + /** + * Update Signal Targets ... + */ + void UpdateSignalTargets(XSignal &signal) + { + // + bool has = signal.IsValid(); + if (!has) + { + return; + } + + // + // Clean Signal Targets ... + Clean(signal.targets); + + // + // Calculate Requirements ... + double r2r = eaSignalR2R > 0 + ? eaSignalR2R + : 1; + double risk = signal.GetRisk(); + double reward = risk * r2r; + + // + double isLong = IsLong(signal.type); + + // + // Handling Signal TP ... + signal.tp = + isLong + ? signal.entry + reward + : signal.entry - reward; + + // + // Try to Apply Money Management ... + + // + // Sort Targets ... + ENUM_X_DIRECTION sortingDir = + isLong + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + ApplySortOnTargets( + sortingDir, + signal.targets // + ); + } + + /** + * Convert a Triggered Conditions to Signal and + * Execute it ... + */ + void TriggerConditions(XCATBEAStrategyConditions &conditions[]) + { + // + int count = 0; + bool has = false; + + // + has = HasChild(conditions); + if (!has) + { + return; + } + + // + count = ArraySize(conditions); + for (int i = 0; i < count; i++) + { + // + // Retrieve Indexed Conditions ... + XCATBEAStrategyConditions iConditions = conditions[i]; + + // + // Define Signal Structure ... + XSignal iSignal; + + // + // Check Conditions is Valid Triggered Conditions ... + has = + iConditions.IsValid() && + iConditions.IsSetuped() && + iConditions.CanTrigger(); + if (has) + { + // + // Preparing Signal ... + has = ToSignal( + iSignal, + iConditions // + ); + } + + // + // Validate Signal ... + has = iSignal.IsValid(); + if (has) + { + // + // Retrieve Signal Type ... + bool isLong = IsLong(iSignal.type); + + // + // Update Signal Entry ... + iSignal.entry = GetEntry( + iSignal.symbol, + iSignal.type // + ); + + // + // Update Signal Targets ... + UpdateSignalTargets(iSignal); + + // + // Handle Volume Management ... + double iVolume = eaVolume.CalculateVolume(iSignal); + has = iVolume > X_MIN_VOLUME && + iVolume != iSignal.volume; + if (has) + { + iSignal.volume = iVolume; + } + + // + // Execute Signal ... + has = eaTradeManager.Execute( + iSignal, + iConditions // + ); + } + + // + // Cleanup Resources ... + + // + iSignal.Clean(); + iConditions.Clean(); + } + } + + // + // private ... + private: + // + + // +}; + +// \ No newline at end of file diff --git a/Experts/xcatb.test.ea.mq5 b/Documents/BKP/xcatb.test.ea.mq5 similarity index 100% rename from Experts/xcatb.test.ea.mq5 rename to Documents/BKP/xcatb.test.ea.mq5 diff --git a/XCATBEA/Classes/xcatbea.x-data.collector.class.mq5 b/Documents/BKP/xcatbea.x-data.collector.class.mq5 similarity index 100% rename from XCATBEA/Classes/xcatbea.x-data.collector.class.mq5 rename to Documents/BKP/xcatbea.x-data.collector.class.mq5 diff --git a/Experts/x-saherelm.x121.xcatb.ea.mq5 b/Experts/x-saherelm.x121.xcatb.ea.mq5 index 4cc3fd02..107f2c06 100644 --- a/Experts/x-saherelm.x121.xcatb.ea.mq5 +++ b/Experts/x-saherelm.x121.xcatb.ea.mq5 @@ -143,6 +143,7 @@ input string eaCloseAllOpenTradesAt = ""; // Configuring Alert Provider ... input group "Alert"; input bool eaEnableAlerts = true; // Enable Alerts +input bool eaSaveAlerts = true; // Save Alerts input bool eaLogAlerts = true; // Log Alerts input bool eaMailAlerts = false; // Mail Alerts input bool eaPushAlerts = true; // Push Alerts @@ -318,6 +319,7 @@ int OnInit() eaExpert.eaLogAlerts = eaLogAlerts; eaExpert.eaMailAlerts = eaMailAlerts; eaExpert.eaPushAlerts = eaPushAlerts; + eaExpert.eaSaveAlerts = eaSaveAlerts; eaExpert.eaEnableAlerts = eaEnableAlerts; eaExpert.eaTerminalAlerts = eaTerminalAlerts; @@ -343,15 +345,15 @@ int OnInit() // // Attach Event Handlers ... - eaExpert.OnModifyEventHandler = OnPositionModified; - eaExpert.OnDealsChangedEventHandler = OnDealsChanged; - eaExpert.OnStopLossEventHandler = OnStopLossTriggered; - eaExpert.OnOrdersChangedEventHandler = OnOrdersChanged; - eaExpert.OnForceCloseEventHandler = OnPositionForceClosed; - eaExpert.OnTakeProfitEventHandler = OnTakeProfitTriggered; - eaExpert.OnPositionsChangedEventHandler = OnPositionsChanged; - eaExpert.OnPartialCloseEventHandler = OnPositionPartialClosed; - eaExpert.OnTradeStateChangedEventHandler = OnTradeStateChanged; + eaExpert.AddOnDealsChangedEventHandler(OnDealsChanged); + eaExpert.AddOnStopLossEventHandler(OnStopLossTriggered); + eaExpert.AddOnOrdersChangedEventHandler(OnOrdersChanged); + eaExpert.AddOnTakeProfitEventHandler(OnTakeProfitTriggered); + eaExpert.AddOnModifyPositionEventHandler(OnPositionModified); + eaExpert.AddOnPositionsChangedEventHandler(OnPositionsChanged); + eaExpert.AddOnTradeStateChangedEventHandler(OnTradeStateChanged); + eaExpert.AddOnForceClosePositionEventHandler(OnPositionForceClosed); + eaExpert.AddOnPartialClosePositionEventHandler(OnPositionPartialClosed); // bool isInited = eaExpert.HandleOnInit(); diff --git a/XCATBEA/Classes/xcatbea.expert.class.mq5 b/XCATBEA/Classes/xcatbea.expert.class.mq5 index b0775320..fc5a42dc 100644 --- a/XCATBEA/Classes/xcatbea.expert.class.mq5 +++ b/XCATBEA/Classes/xcatbea.expert.class.mq5 @@ -107,12 +107,12 @@ class XCXCATBEAExpert : public XCBase bool eaAllowSignallingBasedOnTriggerBlocksInsideOther; // Signalling Based on Trigger Blocks Seccond inputs bool eaSecondsTriggersSLUsingFirstTriggerBlock; // Use First Trigger Block for SL of Seconds Trigger Block Signalss bool eaApplyValidateAndFilterOnSelectInsideOthers; // Select Trigger Blocks by Applying Validations and Filterss - bool eaAllowSignallingConditions1; // Allow Market Conditions Signaller to Using Sar Starter Signals - bool eaAllowSignallingConditions2; // Allow Market Conditions Signaller to Using Trend Starter Signals - bool eaAllowSignallingConditions3; // Allow Market Conditions Signaller to Using Delta Starter Signals - bool eaAllowSignallingConditions4; // Allow Market Conditions Signaller to Using Volume Starter Signals - bool eaAllowSignallingConditions5; // Allow Market Conditions Signaller to Using Signal Bar Starter Signals - bool eaAllowSignallingConditions6; // Allow Market Conditions Signaller to Using HK Signal Bar Starter Signals + bool eaAllowSignallingConditions1; // Allow Market Conditions Signaller to Using Sar Starter Signals + bool eaAllowSignallingConditions2; // Allow Market Conditions Signaller to Using Trend Starter Signals + bool eaAllowSignallingConditions3; // Allow Market Conditions Signaller to Using Delta Starter Signals + bool eaAllowSignallingConditions4; // Allow Market Conditions Signaller to Using Volume Starter Signals + bool eaAllowSignallingConditions5; // Allow Market Conditions Signaller to Using Signal Bar Starter Signals + bool eaAllowSignallingConditions6; // Allow Market Conditions Signaller to Using HK Signal Bar Starter Signals // // Volume ... @@ -144,6 +144,7 @@ class XCXCATBEAExpert : public XCBase // // Alert ... bool eaEnableAlerts; // Enable Alerts + bool eaSaveAlerts; // Save Alerts bool eaLogAlerts; // Log Alerts bool eaMailAlerts; // Mail Alerts bool eaPushAlerts; // Push Alerts @@ -169,18 +170,6 @@ class XCXCATBEAExpert : public XCBase bool eaSaveLosts; // Save Lost Conditions bool eaSaveRestrictions; // Save Restriction Reports - // - // Trade Event Handlers ... - TOnModify OnModifyEventHandler; - TOnStopLoss OnStopLossEventHandler; - TOnForceClose OnForceCloseEventHandler; - TOnTakeProfit OnTakeProfitEventHandler; - TOnPartialClose OnPartialCloseEventHandler; - TOnDealsChanged OnDealsChangedEventHandler; - TOnOrdersChanged OnOrdersChangedEventHandler; - TOnPositionsChanged OnPositionsChangedEventHandler; - TOnTradeStateChanged OnTradeStateChangedEventHandler; - // // Requirements ... @@ -196,6 +185,162 @@ class XCXCATBEAExpert : public XCBase // // Tools / Actions / Handlers ... + // + // Trade Event Handlers ... + + // + void AddOnStopLossEventHandler(TOnStopLoss handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mStopLossEventHandlers + // + ); + } + + // + void AddOnTakeProfitEventHandler(TOnTakeProfit handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mTakeProfitEventHandlers + // + ); + } + + // + void AddOnDealsChangedEventHandler(TOnDealsChanged handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mDealsChangedEventHandlers + // + ); + } + + // + void AddOnOrdersChangedEventHandler(TOnOrdersChanged handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOrdersChangedEventHandlers + // + ); + } + + // + void AddOnModifyPositionEventHandler(TOnModify handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOnModifyEventHandlers + // + ); + } + + // + void AddOnPositionsChangedEventHandler(TOnPositionsChanged handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mPositionsChangedEventHandlers + // + ); + } + + // + void AddOnTradeStateChangedEventHandler(TOnTradeStateChanged handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mTradeStateChangedEventHandlers + // + ); + } + + // + void AddOnForceClosePositionEventHandler(TOnForceClose handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOnForceCloseEventHandlers + // + ); + } + + // + void AddOnPartialClosePositionEventHandler(TOnPartialClose handler) + { + // + if (handler == NULL) + { + return; + } + + // + Add( + handler, + mOnPartialCloseEventHandlers + // + ); + } + // // Validators ... @@ -239,6 +384,10 @@ class XCXCATBEAExpert : public XCBase return result; } + // + bool has = false; + int count = -1; + // // Initialize Alert Handler ... eaAlert = new XCAlert(); @@ -246,6 +395,7 @@ class XCXCATBEAExpert : public XCBase eaAlert.SetLogAlerts(eaLogAlerts); eaAlert.SetMailAlerts(eaMailAlerts); eaAlert.SetPushAlerts(eaPushAlerts); + eaAlert.SetSaveAlerts(eaSaveAlerts); eaAlert.SetEnableAlerts(eaEnableAlerts); eaAlert.SetTerminalAlerts(eaTerminalAlerts); @@ -275,44 +425,139 @@ class XCXCATBEAExpert : public XCBase eaMaxAllowedPositions, eaMaxAllowedDrawdownFactor // ); - eaTrade.AddOnStopLossEventHandler(OnStopLossEventHandler); - eaTrade.AddOnTakeProfitEventHandler(OnTakeProfitEventHandler); - eaTrade.AddOnModifyPositionEventHandler(OnModifyEventHandler); - eaTrade.AddOnDealsChangedEventHandler(OnDealsChangedEventHandler); - eaTrade.AddOnOrdersChangedEventHandler(OnOrdersChangedEventHandler); - eaTrade.AddOnForceClosePositionEventHandler(OnForceCloseEventHandler); - eaTrade.AddOnPartialClosePositionEventHandler(OnPartialCloseEventHandler); - eaTrade.AddOnPositionsChangedEventHandler(OnPositionsChangedEventHandler); - eaTrade.AddOnTradeStateChangedEventHandler(OnTradeStateChangedEventHandler); + + // + // Trade Handler Attachments ... + + // + // Position Modifiy Event Handlers ... + count = ArraySize(mOnModifyEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnModifyPositionEventHandler(mOnModifyEventHandlers[i]); + } + } + + // + // Position Stop Loss Event Handlers ... + if (has) + { + // + count = ArraySize(mStopLossEventHandlers); + has = IsValidSize(count); + for (int i = 0; i < count; i++) + { + eaTrade.AddOnStopLossEventHandler(mStopLossEventHandlers[i]); + } + } + + // + // Position Take Profit Event Handlers ... + count = ArraySize(mTakeProfitEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnTakeProfitEventHandler(mTakeProfitEventHandlers[i]); + } + } + + // + // Position Force Close Event Handlers ... + count = ArraySize(mOnForceCloseEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnForceClosePositionEventHandler(mOnForceCloseEventHandlers[i]); + } + } + + // + // Deals Changed Event Handlers ... + count = ArraySize(mDealsChangedEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnDealsChangedEventHandler(mDealsChangedEventHandlers[i]); + } + } + + // + // Orders Changed Event Handlers ... + count = ArraySize(mOrdersChangedEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnOrdersChangedEventHandler(mOrdersChangedEventHandlers[i]); + } + } + + // + // Positions Changed Event Handlers ... + count = ArraySize(mPositionsChangedEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnPositionsChangedEventHandler(mPositionsChangedEventHandlers[i]); + } + } + // + // Trade Changed Event Handlers ... + count = ArraySize(mTradeStateChangedEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnTradeStateChangedEventHandler(mTradeStateChangedEventHandlers[i]); + } + } + // + // Postion Partially Close Event Handlers ... + count = ArraySize(mOnPartialCloseEventHandlers); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + eaTrade.AddOnPartialClosePositionEventHandler(mOnPartialCloseEventHandlers[i]); + } + } // // Initialize Guard Handler ... eaGuard = new XCGuard( + eaAlert, eaTrade // ); - // - eaGuard.SetAlertPrefix(eaLogSuffix); - eaGuard.SetAlertLogAlerts(eaLogAlerts); - eaGuard.SetAlertMailAlerts(eaMailAlerts); - eaGuard.SetAlertPushAlerts(eaPushAlerts); - eaGuard.SetAlertEnableAlerts(eaEnableAlerts); - eaGuard.SetAlertTerminalAlerts(eaTerminalAlerts); - // // Initialize Trae Manager ... eaTradeManager = new XCXCATBEATradeManager( + eaAlert, eaTrade // ); - // - eaTradeManager.SetAlertPrefix(eaLogSuffix); - eaTradeManager.SetAlertLogAlerts(eaLogAlerts); - eaTradeManager.SetAlertMailAlerts(eaMailAlerts); - eaTradeManager.SetAlertPushAlerts(eaPushAlerts); - eaTradeManager.SetAlertEnableAlerts(eaEnableAlerts); - eaTradeManager.SetAlertTerminalAlerts(eaTerminalAlerts); - // eaTradeManager.SaveWins(eaSaveWins); eaTradeManager.SaveLosts(eaSaveLosts); @@ -804,6 +1049,7 @@ class XCXCATBEAExpert : public XCBase */ void HandleOnTrade() { + eaTrade.HandleOnTrade(); } /** @@ -840,6 +1086,7 @@ class XCXCATBEAExpert : public XCBase */ void HandleOnStopLossTriggered(const XDeal &deal) { + eaTradeManager.HandleSL(deal); } /** @@ -849,6 +1096,7 @@ class XCXCATBEAExpert : public XCBase */ void HandleOnTakeProfitTriggered(const XDeal &deal) { + eaTradeManager.HandleTP(deal); } /** @@ -864,21 +1112,7 @@ class XCXCATBEAExpert : public XCBase const string comment // ) { - } - - /** - * Handle Position Modified Event ... - * - * @param ticket: ulong, triggered Positions ticket ... - * @param profit: double, Position Profit ... - * @param comment: string, Comment ... - */ - void HandleOnPositionModified( - const ulong ticket, - const double profit, - const string comment // - ) - { + eaTradeManager.HandleForceClose(position); } /** @@ -894,6 +1128,12 @@ class XCXCATBEAExpert : public XCBase const string comment // ) { + // + eaTradeManager.HandlePartiallyClosed( + ticket, + profit, + comment // + ); } /** @@ -929,6 +1169,21 @@ class XCXCATBEAExpert : public XCBase { } + /** + * Handle Position Modified Event ... + * + * @param ticket: ulong, triggered Positions ticket ... + * @param profit: double, Position Profit ... + * @param comment: string, Comment ... + */ + void HandleOnPositionModified( + const ulong ticket, + const double profit, + const string comment // + ) + { + } + /** * Handle all Trades States Changed Event ... * @@ -1149,6 +1404,17 @@ class XCXCATBEAExpert : public XCBase private: // + // + TOnModify mOnModifyEventHandlers[]; + TOnStopLoss mStopLossEventHandlers[]; + TOnTakeProfit mTakeProfitEventHandlers[]; + TOnForceClose mOnForceCloseEventHandlers[]; + TOnDealsChanged mDealsChangedEventHandlers[]; + TOnOrdersChanged mOrdersChangedEventHandlers[]; + TOnPartialClose mOnPartialCloseEventHandlers[]; + TOnPositionsChanged mPositionsChangedEventHandlers[]; + TOnTradeStateChanged mTradeStateChangedEventHandlers[]; + // }; diff --git a/XCATBEA/Classes/xcatbea.x-trade.manager.class.mq5 b/XCATBEA/Classes/xcatbea.x-trade.manager.class.mq5 index 84dd467b..2d25d136 100644 --- a/XCATBEA/Classes/xcatbea.x-trade.manager.class.mq5 +++ b/XCATBEA/Classes/xcatbea.x-trade.manager.class.mq5 @@ -22,10 +22,10 @@ // // Imports ... #include "../../Classes/x-saherelm.x-alert.class.mq5" +#include "../../Classes/x-saherelm.x-data.collector.class.mq5" #include "../../Classes/x-saherelm.x-poi.drawer.class.mq5" #include "../../Classes/x-saherelm.x-trade.class.mq5" #include "../../Libraries/x-saherelm.x-poi.lib.mq5" -#include "../Classes/xcatbea.x-data.collector.class.mq5" #include "../Libraries/xcatbea.lib.mq5" #include "../Libraries/xcatbea.signaller.lib.mq5" @@ -1594,27 +1594,29 @@ struct XCATBEATrade // // Implementations ... -class XCXCATBEATradeManager : public XCBaseAlert +class XCXCATBEATradeManager : public XCBase { // // Public ... public: // // Props ... + XCAlert *alert; XCTrade *trader; bool drawSignal; XCPOIDrawer *drawer; XTimeTracker timeTracker; - XCXCATBEADataCollector *collector; + XCDataCollector *collector; // // Constructors ... XCXCATBEATradeManager( - XCTrade *&_trader, - string _path = NULL // Base Path + XCAlert *_alert, + XCTrade *_trader // ) { // + alert = _alert; trader = _trader; drawSignal = true; drawer = new XCPOIDrawer(); @@ -1644,15 +1646,12 @@ class XCXCATBEATradeManager : public XCBaseAlert SaveTrades(false); // - // Normalizing Collector Path ... - if (!IsValid(_path)) - { - _path = "X121XCATBEATradeManager" + "\\" + trader.mAccount.GetCompany(); - } - + collector = new XCDataCollector(); + // - collector = new XCXCATBEADataCollector(); - collector.Path(_path); + // Setting Collector Path ... + string mPath = alert.GetPrefix() + "\\" + trader.mAccount.GetCompany(); + collector.Path(mPath); } // @@ -1666,8 +1665,15 @@ class XCXCATBEATradeManager : public XCBaseAlert timeTracker.Clean(); // + ZeroMemory(alert); ZeroMemory(trader); + + // + delete drawer; ZeroMemory(drawer); + + // + delete collector; ZeroMemory(collector); } @@ -2283,7 +2289,7 @@ class XCXCATBEATradeManager : public XCBaseAlert { // string message = signal.GetMessage("Provided"); - SendAlert(message); + alert.SendAlert(message); } // @@ -2474,7 +2480,7 @@ class XCXCATBEATradeManager : public XCBaseAlert } // - SendAlert(message); + alert.SendAlert(message); } // @@ -3183,10 +3189,10 @@ class XCXCATBEATradeManager : public XCBaseAlert // string message = (IsValid(prefix) - ? prefix + "\n" + ? prefix + " | " : "") + "Account Balance: " + ToString(balance) + currency; - SendAlert(message); + alert.SendAlert(message); } // @@ -3199,7 +3205,7 @@ class XCXCATBEATradeManager : public XCBaseAlert } // - SendAlert(message); + alert.SendAlert(message); } // @@ -3595,7 +3601,7 @@ class XCXCATBEATradeManager : public XCBaseAlert { // string message = iInfo.GetRestrictionDescription(restrictionsPeriod); - SendAlert(message); + alert.SendAlert(message); } SaveRestrictions(iInfo); diff --git a/XCATBEA/Libraries/xcatbea.lib.mq5 b/XCATBEA/Libraries/xcatbea.lib.mq5 index e27840ba..992ab893 100644 --- a/XCATBEA/Libraries/xcatbea.lib.mq5 +++ b/XCATBEA/Libraries/xcatbea.lib.mq5 @@ -2678,617 +2678,6 @@ void ValidateTriggerBlockLiquidities( // TODO: Implement Liquidity Validation ... } -// -bool DetectSignalZone( - XCPOIDrawer *&drawer, - XCX121XCatbHelper *helper, - XCBarAnalyser *barAnalyser, - XBoxZone &signalZone, - X121XCatbConditions &conditions, - int barIndex = 0, - int loopback = 10 // -) -{ - // - bool result = false; - - // - // Checking Conditions ... - - // - // Normalize Args ... - signalZone.Clean(); - conditions.Clean(); - barIndex = NormalizeInt(barIndex, 0); - loopback = NormalizeInt(loopback, 0); - - // - // Validate Args ... - result = helper != NULL && - barAnalyser != NULL; - if (!result) - { - return result; - } - - // - // Reading Market Conditions ... - result = helper.GetConditions( - conditions, - barIndex, - loopback // - ); - if (!result) - { - // - signalZone.Clean(); - conditions.Clean(); - - // - return result; - } - - // - int zIDX = 0; - int cIDX = zIDX + 1; - int pIDX = cIDX + 1; - int p2IDX = pIDX + 1; - int p3IDX = p2IDX + 1; - int p4IDX = p3IDX + 1; - - // - double sl = 0; - double tp = 0; - double upper = 0; - double lower = 0; - datetime to = NULL; - datetime from = NULL; - string signalProvider = NULL; - - // - // Checking Conditions ... - - // - // Detect Bar Verifications ... - - // - ENUM_X_DIRECTION iDir; - - // - // Rejected ... - bool isRejected = - barAnalyser - .IsRejected( - conditions.bars[cIDX], - iDir // - ); - bool isBullishRejected = - isRejected && - IsBullish(iDir); - bool isBearishRejected = - isRejected && - IsBearish(iDir); - - // - // Engulfed ... - bool isEngulfed = - barAnalyser - .IsEngulfed( - conditions.bars[cIDX], - iDir // - ); - bool isBullishEngulfed = - isEngulfed && - IsBullish(iDir); - bool isBearishEngulfed = - isEngulfed && - IsBearish(iDir); - - // - // Momentum ... - bool isMomentum = - barAnalyser - .IsMomentum( - conditions.bars[cIDX], - iDir // - ); - bool isBullishMomentum = - isMomentum && - IsBullish(iDir); - bool isBearishMomentum = - isMomentum && - IsBearish(iDir); - - // - bool isBarBullishPressured = - isBullishRejected || - isBullishEngulfed || - isBullishMomentum; - - // - bool isBarBearishPressured = - isBearishRejected || - isBearishEngulfed || - isBearishMomentum; - - // - // Detect Indicator Base Start Directional Movement ... - - // - // SAR ... - - // - bool isSarBullishStart = - // - ( - // - // Current SAR is Directional ... - conditions.isSarBullish && - // - // Previous InDirectional Sar Exists ... - helper.lastSarBearish.IsValid() && - // - // Current Close is Over previous Sar ... - conditions.bars[cIDX].close > helper.lastSarBearish.after && - // - // Before Close is not Over previous Sar ... - conditions.bars[pIDX].close <= helper.lastSarBearish.after - // - ) - // - ; - - // - bool isSarBearishStart = - // - ( - // - // Current SAR is Directional ... - conditions.isSarBearish && - // - // Previous InDirectional Sar Exists ... - helper.lastSarBullish.IsValid() && - // - // Current Close is Under previous ... - conditions.bars[cIDX].close < helper.lastSarBullish.after && - // - // Before Close is not Under previous ... - conditions.bars[pIDX].close >= helper.lastSarBullish.after - // - ) - // - ; - - // - // TREND ... - - // - bool isTrendBullishStart = - // - ( - // - // Current Trend is Directional ... - conditions.isTrendBullish && - // - // Previous InDirectiona; Trend Exists ... - helper.lastTrendBearish.IsValid() && - // - // Current Close is Over previous ... - conditions.bars[cIDX].close > helper.lastTrendBearish.after && - // - // Before close is not Over previous ... - conditions.bars[pIDX].close <= helper.lastTrendBearish.after - // - ) - // - ; - - // - bool isTrendBearishStart = - // - ( - // - // Current Trend is Directional ... - conditions.isTrendBearish && - // - // Previous InDirectiona; Trend Exists ... - helper.lastTrendBullish.IsValid() && - // - // Current Close is Under previous ... - conditions.bars[cIDX].close < helper.lastTrendBullish.after && - // - // Before close is not Under previous ... - conditions.bars[pIDX].close >= helper.lastTrendBullish.after - // - ) - // - ; - - // - // ADX ... - - // - bool isADXBullishStart = - // - ( - // - // ADX Value is Switched to Strong ... - conditions.adxBuffer[cIDX] > conditions.adxThreshold && - conditions.adxBuffer[pIDX] <= conditions.adxThreshold && - // - // ADX must Up ... - conditions.adxBuffer[cIDX] > conditions.adxBuffer[pIDX] && - // - // ADX +DI is Bigger than -DI ... - conditions.adxpBuffer[cIDX] > conditions.adxnBuffer[cIDX] && - // - // ADX +DI is Up ... - conditions.adxpBuffer[cIDX] > conditions.adxpBuffer[pIDX] - // - ) - // - ; - - // - bool isADXBearishStart = - // - ( - // - // ADX Value is Switched to Strong ... - conditions.adxBuffer[cIDX] > conditions.adxThreshold && - conditions.adxBuffer[pIDX] <= conditions.adxThreshold && - // - // ADX must Up ... - conditions.adxBuffer[cIDX] > conditions.adxBuffer[pIDX] && - // - // ADX -DI is Bigger than +DI ... - conditions.adxnBuffer[cIDX] > conditions.adxpBuffer[cIDX] && - // - // ADX -DI is Up ... - conditions.adxnBuffer[cIDX] > conditions.adxnBuffer[pIDX] - // - ) - // - ; - - // - // DELTA ... - - // - bool isDeltaBullishStart = - // - // Check State ... - ( - // - // Delta is Up ... - conditions.deltaBuffer[cIDX] > conditions.deltaBuffer[pIDX] && - // - // Delta Signal is Up ... - conditions.deltaSignalBuffer[cIDX] > conditions.deltaSignalBuffer[pIDX] && - // - // Delta Crossed Over Delta Signal ... - conditions.deltaBuffer[cIDX] > conditions.deltaSignalBuffer[cIDX] - // - ) - // - && - // - // Check Last InDirectional Exists ... - helper.lastDeltaBearish.IsValid() && - // - // Current Close is Over last ... - conditions.bars[cIDX].close > helper.lastDeltaBearish.after && - // - // Before Close is not Over last ... - conditions.bars[pIDX].close <= helper.lastDeltaBearish.after - // - ; - - // - bool isDeltaBearishStart = - // - // Check State ... - ( - // - // Delta is Down ... - conditions.deltaBuffer[cIDX] < conditions.deltaBuffer[pIDX] && - // - // Delta Signal is Down ... - conditions.deltaSignalBuffer[cIDX] < conditions.deltaSignalBuffer[pIDX] && - // - // Delta Crossed Under Delta Signal ... - conditions.deltaBuffer[cIDX] < conditions.deltaSignalBuffer[cIDX] - // - ) - // - && - // - // Check Last InDirectional Exists ... - helper.lastDeltaBullish.IsValid() && - // - // Current Close is Under last ... - conditions.bars[cIDX].close < helper.lastDeltaBullish.after && - // - // Before Close is not Under last ... - conditions.bars[pIDX].close >= helper.lastDeltaBullish.after - // - ; - - // - // VOLUME ... - - // - bool isVolumeBullishStart = - // - ( - // - // - // Volume is Up ... - conditions.bullishVolumeBuffer[1] > conditions.bullishVolumeBuffer[2] && - // - // Volume Signal is Up ... - conditions.bullishVolumeSignalBuffer[1] > conditions.bullishVolumeSignalBuffer[2] && - // - // Volume Signals Crossed Over ... - conditions.bullishVolumeSignalBuffer[1] > conditions.bearishVolumeSignalBuffer[1] - // - ) - // - && - // - // Check Last InDirectional Exists ... - helper.lastVolumeBearish.IsValid() && - // - // Current Close is Over last ... - conditions.bars[cIDX].close > helper.lastVolumeBearish.after && - // - // Before Close is not Over last ... - conditions.bars[pIDX].close <= helper.lastVolumeBearish.after - // - ; - - // - bool isVolumeBearishStart = - // - ( - // - // - // Volume is Up ... - conditions.bearishVolumeBuffer[1] > conditions.bearishVolumeBuffer[2] && - // - // Volume Signal is Up ... - conditions.bearishVolumeSignalBuffer[1] > conditions.bearishVolumeSignalBuffer[2] && - // - // Volume Signals Crossed Over ... - conditions.bearishVolumeSignalBuffer[1] > conditions.bullishVolumeSignalBuffer[1] - // - ) - // - && - // - // Check Last InDirectional Exists ... - helper.lastVolumeBullish.IsValid() && - // - // Current Close is Over last ... - conditions.bars[cIDX].close < helper.lastVolumeBullish.after && - // - // Before Close is not Over last ... - conditions.bars[pIDX].close >= helper.lastVolumeBullish.after - // - ; - - // - // SIGNAL Bar ... - - // - bool isSBarBullishStart = - // - ( - // - // Check Direction ... - conditions.isSBarBullish && - // - // Previous InDirectional Exists ... - helper.lastSignalBarBearish.IsValid() && - // - // Current Signal Bar close over prev ... - conditions.sBarCloseBuffer[cIDX] > helper.lastSignalBarBearish.after && - // - // Prev Signal Bar not close over prev ... - conditions.sBarCloseBuffer[pIDX] <= helper.lastSignalBarBearish.after - // - ) - // - ; - - // - bool isSBarBearishStart = - // - ( - // - // Check Direction ... - conditions.isSBarBearish && - // - // Previous InDirectional Exists ... - helper.lastSignalBarBullish.IsValid() && - // - // Current Signal Bar close over prev ... - conditions.sBarCloseBuffer[cIDX] < helper.lastSignalBarBullish.after && - // - // Prev Signal Bar not close over prev ... - conditions.sBarCloseBuffer[pIDX] >= helper.lastSignalBarBullish.after - // - ) - // - ; - - // - // HKSIGNAL Bar ... - - // - bool isHKSBarBullishStart = - // - ( - // - // Check Direction ... - conditions.isHKSBarBullish && - // - // Previous InDirectional Exists ... - helper.lastHKSignalBarBearish.IsValid() && - // - // Current Signal Bar close over prev ... - conditions.hkSBarCloseBuffer[cIDX] > helper.lastHKSignalBarBearish.after && - // - // Prev Signal Bar not close over prev ... - conditions.hkSBarCloseBuffer[pIDX] <= helper.lastHKSignalBarBearish.after - // - ) - // - ; - - // - bool isHKSBarBearishStart = - // - ( - // - // Check Direction ... - conditions.isHKSBarBearish && - // - // Previous InDirectional Exists ... - helper.lastHKSignalBarBullish.IsValid() && - // - // Current Signal Bar close over prev ... - conditions.hkSBarCloseBuffer[cIDX] < helper.lastHKSignalBarBullish.after && - // - // Prev Signal Bar not close over prev ... - conditions.hkSBarCloseBuffer[pIDX] >= helper.lastHKSignalBarBullish.after - // - ) - // - ; - - // - // Check for Vale and Peak ... - - // - bool isPeakOverLast = - // - (conditions.peakBuffer[cIDX] > conditions.peakBuffer[pIDX] && - conditions.peakBuffer[pIDX] <= conditions.peakBuffer[p2IDX] && - conditions.bars[cIDX].close > conditions.peakBuffer[pIDX]) - // - ; - - // - bool isValeUnderLast = - // - (conditions.valeBuffer[cIDX] < conditions.valeBuffer[pIDX] && - conditions.valeBuffer[pIDX] >= conditions.valeBuffer[p2IDX] && - conditions.bars[cIDX].close < conditions.valeBuffer[pIDX]) - // - ; - - // - // Start Different Conditions Implemntation ... - - // - // Condition 1: - // --------------------------- - // Descriptions: - // - // - // --------------------------- - - // - // Bullish ... - bool isCond1Bullish = false; - - // - // Bearish ... - bool isCond1Bearish = false; - - // - bool isCond1 = - isCond1Bullish || - isCond1Bearish; - if (isCond1) - { - // - // Prepare Cond1 Based Requirements ... - - // - to = NULL; - upper = 0; - lower = 0; - from = NULL; - - // - // Provider Definition ... - signalProvider = "Cond1"; - } - - // - // Try to Summarize Conditions ... - - // - bool isBullish = - // - isCond1Bullish - // - ; - - // - bool isBearish = - // - isCond1Bearish - // - ; - - // - // Summarize Result ... - result = - isBullish || - isBearish; - if (result) - { - // - // Prepare Signal Zone ... - - // - signalZone.to = to; - signalZone.from = from; - signalZone.upper = upper; - signalZone.lower = lower; - signalZone.type = signalProvider; - signalZone.symbol = conditions.symbol; - signalZone.period = conditions.period; - - // - signalZone.dir = - isBullish - ? X_DIRECTION_BULLISH - : X_DIRECTION_BEARISH; - - // - // Validate Signal Zone ... - result = signalZone.IsValid(); - } - - // - // Cleanup Resources ... - - // - if (!result) - { - // - signalZone.Clean(); - conditions.Clean(); - } - - // - return result; -} - // // Draw Specific Trigger Block ... bool DrawTriggerBlock(