/////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 Class // ------------------------------------------------- // Name: XCXOM1Signaller ... // Description: XOM1EA Signaller 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 XOM1EA Signaller Class" #property strict // // Imports ... #include "../../Helpers/x-saherelm.xom1.helper.mq5" #include "../Classes/xom1ea.x-poi.drawer.class.mq5" #include "../Libraries/xom1ea.lib.mq5" // // Definitions ... // // All Available Signaller Configurations // which allow to Decide Based on Zones ... struct XOM1SignallerConfig { // // Props ... bool processAllTicks; // Do Process All Ticks ... // // Constructor ... XOM1SignallerConfig() { Clean(); } // // Tools ... /** * Cleanup ... */ void Clean() { ZeroMemory(this); } }; // // Implementation ... // // Base Signaller Class ... // Provides Zone Detection Mechanism ... class XCXOM1SignallerBase { // // Public ... public: // // Props ... string name; // Name ... string symbol; // Symbol ... XOM1Zone zones[]; // Detected Zones ... XOM1Inputs inputs; // Indicator Inputs ... ENUM_TIMEFRAMES period; // Period ... XCXOM1POIDrawer drawer; // POI Drawer ... XOM1SignallerConfig config; // Configuration ... TCanAnalyse canAnalyseEventListener; // CanAnalyse Event Listener ... // // Constructor ... XCXOM1SignallerBase( string _name, // Name ... string _symbol, // Symbol ... ENUM_TIMEFRAMES _period, // Period ... XOM1Inputs &_inputs, // Indicator Inputs ... XOM1SignallerConfig &_config // Config ... ) { // // Validate ... bool isValid = IsSpecifiedValid(_name) && IsSpecifiedValid(_symbol) && IsSpecifiedValid(_period) && _inputs.IsValid(); if (!isValid) { return; } // // Make Helper Class Instance ... mHelper = new XCXOM1Helper(); bool isInited = mHelper.Init( _symbol, _period, _inputs // ); if (!isInited) { // delete mHelper; ZeroMemory(mHelper); return; } // // Set Props ... name = _name; symbol = _symbol; period = _period; inputs = _inputs; config = _config; // // Set Dfault Values ... mProcessedTicksCount = 0; mLastCheckedBarTime = NULL; } // // Deconstructor ... ~XCXOM1SignallerBase() { // inputs.Clean(); // SpecifiedClean(zones); // delete mHelper; ZeroMemory(mHelper); } // // Signal Event Handlers ... // void AddOnSignalEventHandler(TOnSignal handler) { // if (handler == NULL) { return; } // Add( handler, mOnSignalEventHandlers // ); } // void NotifyOnSignalEvent(XSignal &signal) { // int count = ArraySize(mOnSignalEventHandlers); bool has = IsValidSize(count) && signal.IsValid(); if (!has) { return; } // // Calling Event Handlers ... for (int i = 0; i < count; i++) { mOnSignalEventHandlers[i](signal); } } // // Actions ... /** * Handle Ticks Process ... * * @param barIndex: int */ virtual void ProcessTick(int barIndex = 0) { } /** * Check Guards Based on MarketConditions ... * * @param guards: XGuard[] * @param barIndex: int * * @return ( int ) */ int CheckForGuard( XGuard &guards[], int barIndex = 0 // ) { // int result = 0; // SpecifiedClean(guards); // result = ArraySize(guards); // return result; } // // Virtuals ... // // Protected ... protected: // // Props ... // XCXOM1Helper *mHelper; // Indicator Helper ... // int mProcessedTicksCount; // Prcoessed Ticks Count ... datetime mLastCheckedBarTime; // Last Checked Bar Time ... /** * Check Permissions for Analysing Market ... * * @param _symbol: Symbol ... * @param _period: Period ... * @param time: Specified Date Time ... * * @return ( bool ) */ bool CanAnalyse( string _symbol, ENUM_TIMEFRAMES _period, datetime time // ) { // bool result = false; // if (canAnalyseEventListener != NULL) { // result = canAnalyseEventListener( _symbol, _period, time // ); } else { result = true; } // return result; } /** * Handle New Bar's Process ... * * @param barIndex: int */ void ProcessNewBar(int barIndex = 0) { // // Normalize Bar Index ... if (barIndex < 0) { barIndex = 0; } // // Try to Update Zone's Lifetime ... int count = ArraySize(zones); bool has = count > 0; if (has) { // // Loop through Zones ... for (int i = 0; i < count; i++) { // // Update Lifetime by Bar Index ... // zones[i].UpdateByBarIndex(barIndex); // // drawer.DrawZone( // zones[i], // true, // Draw Price ... // true, // Draw Middle ... // true // Draw From ... // ); } } // // Check XOMZones Validations ... } /** * Process Exists Zones ... * Detect a Zone for trigger ... * * @param barIndex: int */ void ProcessZones(int barIndex = 0) { // // Check Zones Exists ... int count = ArraySize(zones); bool has = IsValidSize(count); if (!has) { return; } // // Loop Through Zones ... for (int i = 0; i < count; i++) { // } } /** * Converts iZone to Signal and Notify Signal ... * * @param iZone: XOM1Zone */ void PrepareSignal(XOM1Zone &zone) { // // Validate Zone ... if (!zone.IsValid()) { return; } // // Create Signal ... XSignal signal; // signal.time = zone.to; signal.provider = name; signal.symbol = zone.symbol; signal.period = zone.period; signal.mode = X_ORDER_MODE_MARKET; signal.conditions = "XConditions"; signal.comment = ToXString(zone.reason); signal.type = zone.IsBullish() ? POSITION_TYPE_BUY : POSITION_TYPE_SELL; // // Get Entry ... signal.entry = GetXEntry(zone.symbol, zone.dir); // // Calculate SL ... double providedSL = zone.IsBullish() ? zone.lower : zone.upper; signal.sl = providedSL; // // Calculate Risk ... double risk = MathAbs(signal.entry - signal.sl); // // Calculate Reward ... double r2r = 2; double reward = risk * r2r; // // Calculate TP ... double providedTP = zone.IsBullish() ? signal.entry + reward : signal.entry - reward; signal.tp = providedTP; // // Calculate Targets ... // TODO: Handle this ... // // Set Min Volume ... signal.volume = 0.01; // NotifyOnSignalEvent(signal); } // // Private ... private: // // Props ... // TOnSignal mOnSignalEventHandlers[]; // Signal Recieved Event Handlers ... }; // class XCXOM1FIMASignaller : public XCXOM1SignallerBase { // // Public ... public: // // // Constructor ... XCXOM1FIMASignaller( string _name, // Name ... string _symbol, // Symbol ... ENUM_TIMEFRAMES _period, // Period ... XOM1Inputs &_inputs, // Indicator Inputs ... XOM1SignallerConfig &_config // Config ... ) : XCXOM1SignallerBase(_name, _symbol, _period, _inputs, _config // ) { } // // Deconstructor ... ~XCXOM1FIMASignaller() { } // // Overrides ... /** * Handle Ticks Process ... * * @param barIndex: int */ virtual void ProcessTick(int barIndex = 0) { // // Normalize Bar Index ... if (barIndex < 0) { barIndex = 0; } // // Define Requirements ... XOHCL iBar; bool has = false; bool isNewBar = false; // // Get Current Bar Time ... datetime cBarTime = GetBarTime( symbol, period, barIndex // ); // // Validate Bar Time ... has = IsSpecifiedValid(cBarTime); if (!has) { return; } // // Check Process Permissions ... has = CanAnalyse(symbol, period, cBarTime); if (!has) { return; } // // Check if new Bar, Reset Processed Ticks Count ... isNewBar = cBarTime > mLastCheckedBarTime; if (isNewBar) { // mProcessedTicksCount = 0; ProcessNewBar(barIndex); } // // Check Allow Process ... // Process All Ticks ... // Process New Bars ... has = config.processAllTicks || (!config.processAllTicks && isNewBar); if (!has) { return; } // // Set Last Works ... mProcessedTicksCount++; mLastCheckedBarTime = cBarTime; // // Initialize iBar ... has = iBar.Init( symbol, period, barIndex // ); if (!has) { // iBar.Clean(); return; } // // Update Indicator Helper ... mHelper.Update(barIndex); // // Process Exists Zone ... ProcessZones(barIndex); // // Do All Processing Mechanism ... // // Reading Conditions from Helper ... XOM1Conditions iConditions; has = mHelper.GetConditions( iConditions, barIndex // ); if (!has) { // iBar.Clean(); iConditions.Clean(); return; } // int zIdx = 0; int cIdx = zIdx + 1; int pIdx = cIdx + 1; int p2Idx = pIdx + 1; // // Check Zones Flags ... bool checkPVZones = false; bool checkMAZones = true; // // Check PV Zones ... if (checkPVZones) { // // Check New Peak or Vale Happens ... // // New Vale Over Last ... bool isValeReason = iConditions.valeBuffer[cIdx] > iConditions.valeBuffer[pIdx]; // // New Peak Under Last ... bool isPeakReason = iConditions.peakBuffer[cIdx] < iConditions.peakBuffer[pIdx]; // has = isValeReason || isPeakReason; if (has) { // // Prepare Reason ... ENUM_XOM1_ZONE_REASON iReason = isValeReason ? X_OM1_ZONE_REASON_VALE : X_OM1_ZONE_REASON_PEAK; // // Extract Upper / Lower Values ... double iUpper = iConditions.peakBuffer[pIdx]; double iLower = iConditions.valeBuffer[pIdx]; // // Calculate Mid Range ... double iMiddle = iLower + ((iUpper - iLower) / 2); if (iMiddle > 0) { iMiddle = NormalizePrice(iMiddle, symbol); } // // Detect Reason Price ... double iPrice = isValeReason ? iConditions.valeBuffer[cIdx] : iConditions.peakBuffer[cIdx]; if (iPrice > 0) { iPrice = NormalizePrice(iPrice, symbol); } // // Detect Reason Direction ... ENUM_X_DIRECTION iDir = iPrice > iMiddle ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; // // Try to Initialize Zone ... XOM1Zone iZone; has = iZone.Init( symbol, period, name, // Signaller Name ... iUpper, iLower, iPrice, iDir, iReason, iConditions.bars[pIdx].time, // From ... iConditions.bars[zIdx].time // To ); if (has) { // // Add New Detected Zone to Zones ... AddRef( iZone, zones // ); // // Prepare Signal ... PrepareSignal(iZone); } // iZone.Clean(); } } // // Check MA Zones ... if (checkMAZones) { // // Crossed Over ... bool isFastCrossedOverSlow = iConditions.maFastBuffer[cIdx] > iConditions.maSlowBuffer[cIdx] && !(iConditions.maFastBuffer[pIdx] >= iConditions.maSlowBuffer[pIdx]); // // Crossed Under ... bool isFastCrossedUnderSlow = iConditions.maFastBuffer[cIdx] < iConditions.maSlowBuffer[cIdx] && !(iConditions.maFastBuffer[pIdx] <= iConditions.maSlowBuffer[pIdx]); // double iFast = iConditions.maFastBuffer[cIdx]; double iSlow = iConditions.maSlowBuffer[cIdx]; double iFibUpper = iConditions.fiboUpperBuffer[cIdx]; double iFibLower = iConditions.fiboLowerBuffer[cIdx]; // double iValues[] = { iFast, iSlow, iFibUpper, iFibLower // }; // // Extract Upper / Lower Values ... double iUpper = GetMax(iValues); double iLower = GetMin(iValues); // double iZoneUpper = MathMax(iFibUpper, iFibLower); double iZoneLower = MathMin(iFibUpper, iFibLower); // has = isFastCrossedOverSlow || isFastCrossedUnderSlow; // // Validate Cross Between Zone ... if (has) { // // Validate MA Place ... has = iFast >= iZoneLower && iFast <= iZoneUpper && iSlow >= iZoneLower && iSlow <= iZoneUpper; // // Validate PSar ... bool isSarBullish = iConditions.sarStateBuffer[cIdx] > 0; bool isSarBearish = iConditions.sarStateBuffer[cIdx] < 0; has = has && (isFastCrossedOverSlow ? isSarBullish : isSarBearish // ); // // Validate Fibo Zone ... for (int idx = cIdx; idx < cIdx + 2; idx++) { // // Check Fibo Upper ... has = has && iConditions.fiboUpperBuffer[idx] == iConditions.fiboUpperBuffer[idx + 1]; if (!has) { break; } // // Check Fibo Lower ... has = has && iConditions.fiboLowerBuffer[idx] == iConditions.fiboLowerBuffer[idx + 1]; if (!has) { break; } } } // // Moving Forward if Validated ... if (has) { // // Prepare Reason ... ENUM_XOM1_ZONE_REASON iReason = isFastCrossedOverSlow ? X_OM1_ZONE_REASON_FCOS : X_OM1_ZONE_REASON_FCUS; // // Calculate Mid Range ... double iMiddle = iLower + ((iUpper - iLower) / 2); if (iMiddle > 0) { iMiddle = NormalizePrice(iMiddle, symbol); } // // Detect Reason Price ... double iPrice = iConditions.maFastBuffer[cIdx]; if (iPrice > 0) { iPrice = NormalizePrice(iPrice, symbol); } // // Detect Reason Direction ... ENUM_X_DIRECTION iDir = isFastCrossedOverSlow ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; // // Try to Initialize Zone ... XOM1Zone iZone; has = iZone.Init( symbol, period, name, // Signaller Name ... iZoneUpper, iZoneLower, iPrice, iDir, iReason, iConditions.bars[pIdx].time, // From ... iConditions.bars[zIdx].time // To ); if (has) { // // Add New Detected Zone to Zones ... AddRef( iZone, zones // ); // // Prepare Signal ... PrepareSignal(iZone); } // iZone.Clean(); } // Clean(iValues); } // // Clean Resources ... iBar.Clean(); iConditions.Clean(); } }; // class XCXIMAC5020Signaller : public XCXOM1SignallerBase { // // Public ... public: // // // Constructor ... XCXIMAC5020Signaller( string _name, // Name ... string _symbol, // Symbol ... ENUM_TIMEFRAMES _period, // Period ... XOM1Inputs &_inputs, // Indicator Inputs ... XOM1SignallerConfig &_config // Config ... ) : XCXOM1SignallerBase(_name, _symbol, _period, _inputs, _config // ) { } // // Deconstructor ... ~XCXIMAC5020Signaller() { } // // Overrides ... /** * Handle Ticks Process ... * * @param barIndex: int */ virtual void ProcessTick(int barIndex = 0) { } }; // // Extensions ... //