diff --git a/Classes/x-saherelm.x5.provider.class.mq5 b/Classes/x-saherelm.x5.provider.class.mq5 index 21a66c9a..971a1bd0 100644 --- a/Classes/x-saherelm.x5.provider.class.mq5 +++ b/Classes/x-saherelm.x5.provider.class.mq5 @@ -94962,8 +94962,15 @@ private: // // Model Provider Descriptor ... -struct X5ProvierDescriptor +struct X5ProviderDescriptor { + // + string symbol; // Trading Symbol + ENUM_TIMEFRAMES period; // Trading Timeframe + bool allowLong = true; // Allow Long Signals + bool allowShort = true; // Allow Short Signals + ENUM_X5_SIGNAL_PROVIDERS signallers[]; // Allowed Signal Providers + // X5ProviderInputs inputs; XSCX5Provider *provider; @@ -94975,6 +94982,127 @@ struct X5ProvierDescriptor // // Tools ... + // + bool Init() + { + // + bool result = false; + + // + result = this.Init( + this.symbol, + this.period, + this.signallers, + this.allowLong, + this.allowShort // + ); + + // + return result; + } + + // + bool Init( + ENUM_X5_SIGNAL_PROVIDERS &mSignallers[], // Allowed Signal Providers + bool mAllowLong = true, // Allow Long Signals + bool mAllowShort = true // Allow Short Signals + ) + { + // + bool result = false; + + // + result = this.Init( + this.symbol, + this.period, + mSignallers, + mAllowLong, + mAllowShort // + ); + + // + return result; + } + + // + bool Init( + string mSymbol, // Trading Symbol + ENUM_TIMEFRAMES mPeriod, // Trading Timeframe + ENUM_X5_SIGNAL_PROVIDERS &mSignallers[], // Allowed Signal Providers + bool mAllowLong = true, // Allow Long Signals + bool mAllowShort = true // Allow Short Signals + ) + { + // + bool result = false; + + // + result = + // + inputs.IsValid() && + IsValid(mSymbol) && + IsValid(mPeriod) && + (allowLong || allowShort) && + ArraySize(mSignallers) > 0 + // + ; + if (!result) + { + return result; + } + + // + this.symbol = mSymbol; + this.period = mPeriod; + this.allowLong = mAllowLong; + this.allowShort = mAllowShort; + Copy( + this.signallers, + mSignallers // + ); + + // + // Instantiate Provider ... + provider = new XSCX5Provider( + this.symbol, + this.period // + ); + + // + // Set Long/Short State ... + + // + provider + .SetSignalTypeState( + POSITION_TYPE_BUY, + this.allowLong // + ); + + // + provider + .SetSignalTypeState( + POSITION_TYPE_SELL, + this.allowShort // + ); + + // + // Enable Required Signallers ... + provider + .SetSignalProviderStates( + this.signallers, + true // + ); + + // + // Now Must to Initialize Provider ... + result = provider.Init( + this.inputs // + ); + + // + return result; + } + // // Cleanup ... void Clean() @@ -94984,6 +95112,30 @@ struct X5ProvierDescriptor conditions.Clear(); } + // + // Validate ... + bool IsValid(bool validateInputs = true) + { + // + bool result = false; + + // + result = + // + IsValid(symbol) && + IsValid(period) && + (validateInputs + ? inputs.IsValid() + : true) && + (allowLong || allowShort) && + ArraySize(signallers) > 0 + // + ; + + // + return result; + } + // // Check Signal ... bool HasSignal(int barIndex = 0) diff --git a/Classes/x-saherelm.x5.xea.class.mq5 b/Classes/x-saherelm.x5.xea.class.mq5 new file mode 100644 index 00000000..bbb71ae5 --- /dev/null +++ b/Classes/x-saherelm.x5.xea.class.mq5 @@ -0,0 +1,259 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// ---------------------------------------------- +// Name: XSCX5EA +// Description: provides all X5 EA requirements ... +// - X5 Provider; +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +// Imports ... +#include "../Classes/x-saherelm.xea.class.mq5" +#include "../Classes/x-saherelm.x5.provider.class.mq5" + +// +// Define On Signal Event Handler Type Specified for X5 ... +typedef void (*TX5OnSignal)(X5ProviderDescriptor &descriptor); + +// +// Class Definition ... + +class XSCX5EA : XSCBaseEA +{ + // + // Public ... +public: + // + // Props ... + + // + // Constructors ... + XSCX5EA( + // + // XTrade Class Requirements ... + int slippage, // Specify Slippage + ulong magicNumber, // Specify Magic Number + int manageInterval, // Manager Check Intervals Seconds + double maxAllowedSpread, // Max Allowed Spred for Opening Trades + int maxAllowedPositions, // Max Allowed Positions + double maxAllowedDrawdownFactor, // Max Allowed Drawdown Factor + // + // Position Management ... + bool allowLong = true, // Allow Long Trades + bool allowShort = true, // Allow Short Trades + double minProfitPerTrade = 0, // Min Profit Per Trade based On Volume Factor (Hedge) + double minProfitPerVolumeFactor = 0, // Min Volume Factor for Calculating Profit (Hedge) + // + // Event Handlers ... + TOnStopLoss onStopLossTriggered = NULL, // On StopLoass Triggered Event Handler + TOnTakeProfit onTakeProfitTriggered = NULL, // On TakeProfit Triggered Event Handler + TOnDealsChanged onDealsChangedHandler = NULL, // On Deals Changed Event Handler + TOnOrdersChanged onOrdersChangedHandler = NULL, // On Orders Changed Event Handler + TOnPositionsChanged onPositionsChangedHandler = NULL, // On Positions Changed Event Handler + TOnTradeStateChanged onTradeStateChangedHandler = NULL, // On Trade State Changed Event Handler + // + TOnSignal onSignalHandler = NULL, // On Signal Event Handler + // + // Log Handler ... + bool enableAlerts = true, // Enable Alerts + bool logAlerts = true, // Log Alerts + bool terminalAlerts = false, // Terminal Alerts + bool mailAlerts = false, // Mail Alerts + bool pushAlerts = false // Push Alerts + ) : XSCBaseEA(slippage, + magicNumber, + manageInterval, + maxAllowedSpread, + maxAllowedPositions, + maxAllowedDrawdownFactor, + allowLong, + allowShort, + minProfitPerTrade, + minProfitPerVolumeFactor, + onStopLossTriggered, + onTakeProfitTriggered, + onDealsChangedHandler, + onOrdersChangedHandler, + onPositionsChangedHandler, + onTradeStateChangedHandler, + enableAlerts, + logAlerts, + terminalAlerts, + mailAlerts, + pushAlerts // + ) + { + } + + // + // Deconstructor ... + ~XSCX5EA() {} + + // + // Properties Getter(s) / Setter(s) ... + + // + // Add X5 Specified Signal Event Handler ... + void AddOnSignalEventHandler(TX5OnSignal listener) + { + // + Add( + listener, + mX5OnSignalEventHandlers + // + ); + } + + // + // Add Specified X5 Provider ... + bool AddProvider(X5ProviderDescriptor &descriptor) + { + // + bool result = false; + + // + // Validate Inputs ... + result = descriptor.Init(); + if (!result) + { + return result; + } + + // + AddRef( + descriptor, + mDescriptors // + ); + + // + return result; + } + + // + // Overrides ... + + // + // Customize Token ... + string GetToken() override + { + return GetSpecificToken(this); + } + + // + string GetTag() override + { + return this.GetToken(); + } + + // + // Check Provider for any Guards ... + bool CheckForGuard(XGuard &guards[]) override + { + // + // TODO: Implement this ... + return false; + } + + // + // Request Provider to Collect all + // Potentially Signals and then + // filters theme here and passed them + // for Executing ... + int RequestForSignal( + XSignal &signals[] // Holds Signals ... + ) override + { + // + // TODO: Implement this ... + return 0; + } + + // + // Handl Management Actions ... + // if returns true, it is going to prevent for processing forward ... + bool HandleStateManagement() override + { + // + // TODO: Implement this ... + return false; + } + + // + // Request for Support Signals using Guard ... + bool RequestForSupport( + XSignal &support, // Holds Support Signal, if Provided + string provider, // Positions Provided by Specific Provider + string symbol, // Trading Symbol + ENUM_POSITION_TYPE type, // Trading Type + ENUM_TIMEFRAMES period // Specified Time Frame + ) override + { + // + // TODO: Implement this ... + return false; + } + + // + // Tools ... + + // + // Protected ... +protected: + // + // Tools ... + + // + void NotifyX5OnSignalEventHandlers(X5ProviderDescriptor &descriptor) + { + // + int listenersCount = ArraySize(mX5OnSignalEventHandlers); + if (listenersCount <= 0) + { + return; + } + + // + for (int i = 0; i < listenersCount; i++) + { + // + TX5OnSignal iListener = mX5OnSignalEventHandlers[i]; + + // + iListener(descriptor); + } + } + + // + // Private ... +private: + // + // Props ... + + // + // Collection of Signal Event Listeners ... + TX5OnSignal mX5OnSignalEventHandlers[]; + + // + // a Collection of X5 Provider Descriptors ... + X5ProviderDescriptor mDescriptors[]; + + // + // Tools ... +}; + +// +// Tools ... \ No newline at end of file diff --git a/Classes/x-saherelm.xea.class.mq5 b/Classes/x-saherelm.xea.class.mq5 index a7fcefae..3b205753 100644 --- a/Classes/x-saherelm.xea.class.mq5 +++ b/Classes/x-saherelm.xea.class.mq5 @@ -25,6 +25,10 @@ #include "../Classes/x-saherelm.xalert.class.mq5" #include "../Classes/x-saherelm.xtrade.class.mq5" +// +// Define On Signal Event Handler Type ... +typedef void (*TOnSignal)(XSignal &signals[]); + // // Class Definition ... @@ -153,7 +157,12 @@ public: // // Deconstractor ... - ~XSCBaseEA() {} + ~XSCBaseEA() + { + // + delete mTrader; + delete mAlert; + } // // Properties Getter(s) / Setter(s) ... @@ -330,6 +339,18 @@ public: mAlert.SetTerminalAlerts(value); } + // + // Event Listeners ... + void AddOnSignalEventHandler(TOnSignal listener) + { + // + Add( + listener, + mOnSignalEventHandlers + // + ); + } + // // Overrides ... @@ -364,6 +385,10 @@ public: // OnTick Handler ... virtual void OnTick() { + // + // Check Trade Events ... + OnTrade(); + // // First Check For Any Guard Actions ... // then Handle Guards if Provided ... @@ -387,43 +412,15 @@ public: // Second Check For Signals ... // then Execute Signals if Provided ... XSignal signals[]; - int signalsCount = CheckForSignal(signals); + int signalsCount = RequestForSignal(signals); if (signalsCount <= 0) { return; } // - // Try to Execute Signals ... - ENUM_X_SIGNAL_EXECUTION_RESULT reasons[]; - int executedSignalsCount = mTrader.ExecuteSignals( - signals, - reasons); - - // - string message = NULL; - if (executedSignalsCount == 0) - { - message = "(" + ToString(signalsCount) + ") Signals Execution Failed ..."; - } - else if (executedSignalsCount < signalsCount) - { - // - int diff = signalsCount - executedSignalsCount; - - // - message = "Failed to Execute (" + ToString(diff) + ") Signals ..."; - } - else if (executedSignalsCount == signalsCount) - { - message = "(" + ToString(executedSignalsCount) + ") Signals Executed Successfully ..."; - } - - // - if (IsValid(message)) - { - mAlert.Alert(message); - } + // Execute Signals ... + HandleSignalsExecution(signals); } // @@ -542,7 +539,7 @@ public: // When a Guard Notified to Do Support Signal ... // this Method Calls For Retrieve Support Signal ... // if it's Provided, Execute it ... - virtual bool CheckForSupport( + virtual bool RequestForSupport( XSignal &support, // Holds Support Signal, if Provided string provider, // Positions Provided by Specific Provider string symbol, // Trading Symbol @@ -566,19 +563,120 @@ public: // on our Strategy for Trading ... // and if a Good Entry founded ... // model it as an XSignal struct and passed it to result ... - virtual int CheckForSignal( + virtual int RequestForSignal( XSignal &signals[] // Holds Signals ... ) { return 0; } + // + // Execute Provided Signals ... + virtual void HandleSignalsExecution(XSignal &signals[]) + { + // + int signalsCount = ArraySize(signals); + if (signalsCount <= 0) + { + return; + } + + // + // Filter Signals Based on their Types ... + XSignal filteredSignals[]; + + // + // Try to Filter Signals ... + for (int i = 0; i < signalsCount; i++) + { + // + XSignal iSignal = signals[i]; + + // + bool isLong = IsLong(iSignal.type); + + // + if ((isLong && !GetAllowLong()) || (!isLong && !GetAllowShort())) + { + continue; + } + + // + AddRef( + iSignal, + filteredSignals // + ); + } + + // + int filteredSignalsCount = ArraySize(filteredSignals); + if (filteredSignalsCount <= 0) { + return; + } + + // + // Try to Execute Signals ... + ENUM_X_SIGNAL_EXECUTION_RESULT reasons[]; + int executedSignalsCount = mTrader.ExecuteSignals( + filteredSignals, + reasons + // + ); + + // + string message = NULL; + if (executedSignalsCount == 0) + { + message = "(" + ToString(filteredSignals) + ") Signals Execution Failed ..."; + } + else if (executedSignalsCount < filteredSignalsCount) + { + // + int diff = filteredSignalsCount - executedSignalsCount; + + // + message = "Failed to Execute (" + ToString(diff) + ") Signals ..."; + } + else if (executedSignalsCount == filteredSignalsCount) + { + message = "(" + ToString(executedSignalsCount) + ") Signals Executed Successfully ..."; + } + + // + if (IsValid(message)) + { + mAlert.Alert(message); + } + } + // // Protected ... protected: // // Props ... + // + // Signal Event Listeners ... + void NotifyOnSignalEventHandlers(XSignal &signals[]) + { + // + int listenersCount = ArraySize(mOnSignalEventHandlers); + if (listenersCount <= 0) + { + return; + } + + // + for (int i = 0; i < listenersCount; i++) + { + // + TOnSignal iListener = mOnSignalEventHandlers[i]; + + // + iListener(signals); + } + } + // // Position Management ... @@ -1037,7 +1135,7 @@ protected: { // XSignal support; - bool hasSupport = CheckForSupport( + bool hasSupport = RequestForSupport( support, provider, symbol, @@ -1134,6 +1232,10 @@ private: // Check in Test Mode or not ... bool mIsInTestMode; + // + // Signal Event Listeners ... + TOnSignal mOnSignalEventHandlers[]; + // // Position Management ... bool mAllowLong; // Allow Long Trades @@ -1149,6 +1251,6 @@ private: TOnOrdersChanged mOnOrdersChangedHandler; TOnPositionsChanged mOnPositionsChangedHandler; TOnTradeStateChanged mOnTradeStateChangedHandler; -} +}; // \ No newline at end of file diff --git a/Experts/x-test.x5ea.mq5 b/Experts/x-test.x5ea.mq5 index bb4407d1..971bc7b3 100644 --- a/Experts/x-test.x5ea.mq5 +++ b/Experts/x-test.x5ea.mq5 @@ -47,7 +47,7 @@ MqlTick x5EATick; XSignal signal; // -X5ProvierDescriptor mProviderDescriptors[]; +X5ProviderDescriptor mProviderDescriptors[]; // // Event Handlers ... @@ -197,7 +197,7 @@ bool InitialProviders() { // // Define Structure ... - X5ProvierDescriptor iDescriptor; + X5ProviderDescriptor iDescriptor; // // Set Inputs to Default ... @@ -286,7 +286,7 @@ void ProcessProvidersTick() for (int i = 0; i < descriptorsCount; i++) { // - X5ProvierDescriptor iDescriptor = mProviderDescriptors[i]; + X5ProviderDescriptor iDescriptor = mProviderDescriptors[i]; // bool iHasSignal = iDescriptor.HasSignal(0);