/////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 Class // ------------------------------------------------- // Name: XCXFIMASignaller ... // Description: XFIMA 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 XFIMA Signaller Class" #property strict // // Imports ... #include "../../Classes/x-saherelm.x-signaller.class.mq5" #include "../../Helpers/x-saherelm.xfima.helper.mq5" #include "../Classes/x-saherelm.xfima.x-poi.detector.class.mq5" #include "../Classes/x-saherelm.xfima.x-poi.drawer.class.mq5" // // Implementation ... // // Base XFIMA base Signaller ... class XCXFIMABaseSignaller : public XCBaseSignaller { // // Public ... public: // // Props ... // XFIMAInputs fimaInputs; // XFIMA Inputs ... XCXFIMAHelper *fimaHelper; // XFIMA Indicator Helper ... XCXFIMAPOIDrawer *poiDrawer; // XFIMA POI Drawer ... XCXFIMAPOIDetector *poiDetector; // XFIMA POI Detector ... // // Constructor ... XCXFIMABaseSignaller( string _name, // Name ... string _symbol, // Symbol ... ENUM_TIMEFRAMES _period, // Period ... XFIMAInputs &_fimaInputs, // XFIMAInputs ... bool _processAllTicks = false, // Process All Ticks ... double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ... double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ... double _defaultSignalVolume = 0.01 // Default Signal Volume ... ) : XCBaseSignaller(_name, _symbol, _period, _processAllTicks, _defaultSignalR2R, _defaultSignalRiskInPoint, _defaultSignalVolume // ) { // // Instantiating XFIMA Indicator Helper Class ... if (_fimaInputs.IsValid()) { // fimaHelper = new XCXFIMAHelper(); bool isInited = fimaHelper.Init( _symbol, _period, _fimaInputs // ); if (isInited) { fimaInputs = _fimaInputs; } else { // delete fimaHelper; ZeroMemory(fimaHelper); } } // poiDrawer = new XCXFIMAPOIDrawer(); poiDetector = new XCXFIMAPOIDetector(fimaHelper); } // // Deconstructor ... ~XCXFIMABaseSignaller() { Destroy(); } // // Overrides ... // // Actions ... /** * Destroy ... */ void Destroy() { // BeforeDestroy(); // fimaInputs.Clean(); // delete fimaHelper; ZeroMemory(fimaHelper); // delete poiDrawer; ZeroMemory(poiDrawer); // delete poiDetector; ZeroMemory(poiDetector); } // // Virtuals ... /** * Before Destroy ... */ void virtual BeforeDestroy() { } /** * Processing Tick ... * * @param barIndex: int, Specified Bar Index ... */ virtual void ProcessTick(int barIndex = 0) { } /** * Processing New Bar ... * * @param barIndex: int, Specified Bar Index ... */ virtual void ProcessNewBar(int barIndex = 0) { } /** * Check Guards Based on MarketConditions ... * * @param guards: XGuard[] * @param barIndex: int * * @return ( int ) */ int virtual CheckForGuard( XGuard &guards[], int barIndex = 0 // ) { // int result = 0; // SpecifiedClean(guards); // result = ArraySize(guards); // return result; } /** * Check Additional Validations on Childs Instances ... * * @return ( bool virtual ) */ bool virtual CheckAdditionslSignallerValidations() { // bool result = false; // // Validate Fima Helper Requirements ... result = fimaInputs.IsValid() && fimaHelper != NULL && poiDetector != NULL; // return result; } /** * Normalizing Signal by Signaller Custom Props ... * * @param signal: XSignal ... */ void virtual NormalizeSignal(XSignal &signal) { } // // Protected ... protected: // // // Protected Actions ... /** * Check Specified Bar has Pattern or not ... * * @param bar: XOHCL, reference to Specified Bar ... * @param name: string, reference to holds Detected Patterns Name ... * @param dir: ENUM_X_DIRECTION, reference to holds Detected Patterns Direction ... * @param structure: XFIMAMarketStructure, refrence to Provides Market Structure ... * * @return ( bool ) */ bool HasPattern( XOHCL &bar, string &patternName, ENUM_X_DIRECTION &patternDir, XFIMAMarketStructure &structure // ) { // bool result = false; // // Prepare ... patternName = NULL; patternDir = X_DIRECTION_NONE; // // Validate ... result = bar.IsValid(); if (!result) { return result; } // // Check Required Pattern Exists ... bool hasPinnedBar = HasDirection(structure.pinnedDir); bool hasEngulfedBar = HasDirection(structure.engulfedDir); bool hasFlagPattern = HasDirection(structure.flagPatternDir); bool hasStarPattern = HasDirection(structure.starPatternDir); bool hasRisingPattern = HasDirection(structure.risingPatternDir); bool hasPiercingPattern = HasDirection(structure.piercingPatternDir); bool hasSignalKeyBar = HasDirection(structure.signalKeyBarPatternDir); // // Check Bar Pattern Exists ... // and Select Pattern Direction and Price and Price Type ... result = hasPinnedBar || hasEngulfedBar || hasFlagPattern || hasStarPattern || hasSignalKeyBar || hasRisingPattern || hasPiercingPattern; // if (result) { // if (hasPinnedBar) { // patternDir = structure.pinnedDir; patternName = "XPinned_" + ToXString(patternDir) + ToXString(TimeToSeconds(bar.time)); } else if (hasEngulfedBar) { // patternDir = structure.engulfedDir; patternName = "XEngulfed_" + ToXString(patternDir) + ToXString(TimeToSeconds(bar.time)); } else if (hasFlagPattern) { // patternDir = structure.flagPatternDir; patternName = "XFlag_" + ToXString(patternDir) + ToXString(TimeToSeconds(bar.time)); } else if (hasStarPattern) { // patternDir = structure.starPatternDir; patternName = "XStar_" + ToXString(patternDir) + ToXString(TimeToSeconds(bar.time)); } else if (hasSignalKeyBar) { // patternDir = structure.risingPatternDir; patternName = "XRising_" + ToXString(patternDir) + ToXString(TimeToSeconds(bar.time)); } else if (hasRisingPattern) { // patternDir = structure.piercingPatternDir; patternName = "XPiercing_" + ToXString(patternDir) + ToXString(TimeToSeconds(bar.time)); } else if (hasPiercingPattern) { // patternDir = structure.signalKeyBarPatternDir; patternName = "XSignalKey_" + ToXString(patternDir) + ToXString(TimeToSeconds(bar.time)); } } // result = result && IsXValid(patternName) && HasDirection(patternDir); // return result; } /** * Validate a Pattern based on MA Band ... * * @param bar: XOHCL, reference to Pattern Bar ... * @param patternName: string, detected pattern's name ... * @param patternDir: ENUM_X_DIRECTION, detected pattern's direction ... * @param fimaConditions: XFIMAConditions, reference to Bar Specified XFIMA Conditions ... * * @return ( bool ) */ bool ValidatePatternBasedOnMABand( XOHCL &bar, string patternName, ENUM_X_DIRECTION patternDir, XFIMAConditions &fimaConditions // ) { // bool result = false; // // Validate ... result = bar.IsValid() && IsXValid(patternName) && HasDirection(patternDir); if (!result) { return result; } // // Define Requirements ... bool isBullish = false; bool isBearish = false; double iPrice = EMPTY_VALUE; double iPriceEdge = EMPTY_VALUE; ENUM_X_PRICE iPriceType = X_PRICE_NONE; ENUM_X_PRICE iPriceEdgeType = X_PRICE_NONE; // // Calculating Price and Price Types ... // isBullish = IsXBullish(patternDir); isBearish = IsXBearish(patternDir); // iPriceType = isBullish ? X_PRICE_DOWN : X_PRICE_UP; // iPriceEdgeType = isBullish ? X_PRICE_LOW : X_PRICE_HIGH; // iPrice = bar.GetPrice(iPriceType); iPriceEdge = bar.GetPrice(iPriceEdgeType); // // Validate ... result = NotEmptyZero(iPrice) && IsXValid(iPriceType) && NotEmptyZero(iPriceEdge) && IsXValid(iPriceEdgeType) && ((isBullish && !isBearish) || (isBearish && !isBullish)); if (!result) { return result; } // // Validate Pattern based on MA Band ... // // Retrieve MA Band for Validation ... double iMABandUpper = fimaConditions.maBandUpperBuffer[0]; double iMABandLower = fimaConditions.maBandLowerBuffer[0]; // // Validate by Edge Price ... result = NotEmptyZero(iMABandUpper) && NotEmptyZero(iMABandLower) && (isBullish ? iPriceEdge < iMABandLower : iPriceEdge > iMABandUpper); if (!result) { return result; } // return result; } // // Private ... private: // }; // // XFIMA Strategy 1 Signaller Class ... class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller { // // Public ... public: // // Props ... int fvgLookupLenght; // Maximum Lenght for Looking up FVG before Crosses // // Constructor ... XCXFIMAStrategy1Signaller( string _symbol, // Symbol ... ENUM_TIMEFRAMES _period, // Period ... XFIMAInputs &_fimaInputs, // XFIMAInputs ... bool _processAllTicks = false, // Process All Ticks ... double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ... double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ... double _defaultSignalVolume = 0.01 // Default Signal Volume ... ) : XCXFIMABaseSignaller("XFIMA1", _symbol, _period, _fimaInputs, _processAllTicks, _defaultSignalR2R, _defaultSignalRiskInPoint, _defaultSignalVolume // ) { // fvgLookupLenght = 5; } // // Overrides ... /** * Processing Tick ... * * @param barIndex: int, Specified Bar Index ... */ virtual void ProcessTick(int barIndex = 0) { } /** * Processing New Bar ... * * @param barIndex: int, Specified Bar Index ... */ virtual void ProcessNewBar(int barIndex = 0) { // // Normalize ... barIndex = NormalizeInt(barIndex, 0); // XOHCL bar; XSignal signal; bool has = false; int cIdx = barIndex + 1; int pIdx = cIdx + 1; ENUM_X_DIRECTION signalDir = X_DIRECTION_NONE; // // Initialize Bar as CBar ... has = bar.Init( symbol, period, cIdx // ); if (!has) { // bar.Clean(); return; } // // Retrieve Conditions ... XFIMAConditions fimaConditions; has = fimaHelper.GetConditions( fimaConditions, barIndex, 10 // Loopback ... ); if (!has) { // bar.Clean(); fimaConditions.Clean(); // return; } // // Analyse Conditions for Finding Signal ... // // TODO: Remove this ... // bool isFastCrossedOverSlow = fimaConditions.maFastBuffer[cIdx] > fimaConditions.maSlowBuffer[cIdx] && fimaConditions.maFastBuffer[pIdx] < fimaConditions.maSlowBuffer[pIdx]; // bool isFastCrossedUnderSlow = fimaConditions.maFastBuffer[cIdx] < fimaConditions.maSlowBuffer[cIdx] && fimaConditions.maFastBuffer[pIdx] > fimaConditions.maSlowBuffer[pIdx]; // has = isFastCrossedOverSlow || isFastCrossedUnderSlow; if (has) { // // Do Conditions Validating ... // TODO: Igmore All Validations for Testing Purposes ... // // Validate MA Positions ... double iFastMa = fimaConditions.maFastBuffer[cIdx]; double iSlowMa = fimaConditions.maSlowBuffer[cIdx]; double iFiboUpper = fimaConditions.fiboUpperBuffer[cIdx]; double iFiboLower = fimaConditions.fiboLowerBuffer[cIdx]; // // Checking Has FVG ... XBoxZone fvg; ENUM_X_DIRECTION fvgDir; bool hasFVG = patternDetector.HasFVG( bar, fvgDir, fvg, fvgLookupLenght // ); // // Checking Crossed On Shadow ... // bool isCrossedOverHappensOnShadow = isFastCrossedOverSlow && iFastMa <= bar.GetDown() && iFastMa >= bar.low; // bool isCrossedUnderHappensOnShadow = isFastCrossedUnderSlow && iFastMa <= bar.high && iFastMa >= bar.GetUp(); // // Bullish Validation ... bool isBullish = // // Has Cross ... isFastCrossedOverSlow // // && // // // // Cross Places Based on Fibo ... // MathMax(iFastMa, iSlowMa) < iFiboLower // // // && // // // ( // // // // Checking FVG ... // (hasFVG && // fvg.IsBullish()) // // // || // // // // Checking Crossed Place ... // isCrossedOverHappensOnShadow // // // ) // // ; // // Bearish Validation ... bool isBearish = // // Has Cross ... isFastCrossedUnderSlow // // && // // // // Cross Places Based on Fibo ... // MathMin(iFastMa, iSlowMa) > iFiboUpper // // // && // // // ( // // // // Checking FVG ... // (hasFVG && // fvg.IsBearish()) // // // || // // // // Checking Crossed Place ... // isCrossedUnderHappensOnShadow // // // ) // // ; // has = (isBullish && !isBearish) || (isBearish && !isBullish); if (has) { // signalDir = isBullish ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; } } // // Check Signal Founded ... has = HasDirection(signalDir); if (has) { // // Prepare Founded Signal ... XTarget targets[]; has = PrepareSignal( signal, signalDir, targets // ); if (has) { // // Notify On Signal Event ... NotifySignalEventListeners(signal); } } // // Cleanup Resources ... bar.Clean(); signal.Clean(); fimaConditions.Clean(); } /** * Check Guards Based on MarketConditions ... * * @param guards: XGuard[] * @param barIndex: int * * @return ( int ) */ int virtual CheckForGuard( XGuard &guards[], int barIndex = 0 // ) { // int result = 0; // SpecifiedClean(guards); // result = ArraySize(guards); // return result; } // // Private ... private: // // Props ... // // Lookup FVG ... bool LookupFVG( XOHCL &bar, ENUM_X_DIRECTION &dir, XBoxZone &fvgBox // ) { // bool result = false; // return result; } // }; // // XFIMA Strategy 2 Signaller Class ... class XCXFIMAStrategy2Signaller : public XCXFIMABaseSignaller { // // Public ... public: // // Props ... XFIMAPatternDetectorConfig analyserConfig; // // Constructor ... XCXFIMAStrategy2Signaller( string _symbol, // Symbol ... ENUM_TIMEFRAMES _period, // Period ... XFIMAInputs &_fimaInputs, // XFIMAInputs ... bool _processAllTicks = false, // Process All Ticks ... double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ... double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ... double _defaultSignalVolume = 0.01 // Default Signal Volume ... ) : XCXFIMABaseSignaller("XFIMA2", _symbol, _period, _fimaInputs, _processAllTicks, _defaultSignalR2R, _defaultSignalRiskInPoint, _defaultSignalVolume // ) { // // Configure Detector ... // analyserConfig.Default(); analyserConfig.validMACrossDiffMultiplier = 4; // analyserConfig.FullDetect(); } // // Deconstructor ... ~XCXFIMAStrategy2Signaller() { // Destroy(); // analyserConfig.Clean(); } // // Overrides ... /** * Processing Tick ... * * @param barIndex: int, Specified Bar Index ... */ virtual void ProcessTick(int barIndex = 0) { } /** * Processing New Bar ... * * @param barIndex: int, Specified Bar Index ... */ virtual void ProcessNewBar(int barIndex = 0) { // // Normalize ... barIndex = NormalizeInt(barIndex, 0); // XOHCL iBar; int count = 0; XBoxZone iZone; XSignal iSignal; bool has = false; XTarget targets[]; string iName = NULL; XBoxZone supports[]; XBoxZone resistances[]; bool isBullish = false; bool isBearish = false; int numberOfPivots = 25; XFIMAConditions iFIMAConditions; XFIMAMarketStructure iStructure; ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; // XPivot pvPivots[]; string pvTrendName = "XXIFMA2PVTrend"; CChartObjectTrend *pvTrendLine = NULL; ENUM_X_DIRECTION pvTrend = X_DIRECTION_NONE; // XPivot zgPivots[]; string zgTrendName = "XFIMA2ZGTrend"; CChartObjectTrend *zgTrendLine = NULL; ENUM_X_DIRECTION zgTrend = X_DIRECTION_NONE; // // Initialize Bar as CBar ... has = iBar.Init( symbol, period, barIndex // ); if (!has) { // iBar.Clean(); return; } // // Retrieve Conditions ... has = fimaHelper.GetConditions( iFIMAConditions, barIndex, 10 // Loopback ... ); if (!has) { // iBar.Clean(); iFIMAConditions.Clean(); // return; } // // Analyse Market ... poiDetector.AnalyseMarket( iBar, iStructure, analyserConfig // ); // // Collect Support and Resistance Zones and Validate by them ... // // PV Trend Line ... bool hasPVAnalysis = iStructure.pvAnalysis.IsValid(); if (hasPVAnalysis) { // // Support ... XBoxZone supportBox; has = iStructure.pvAnalysis.HasSupportBox(supportBox); if (has) { // supportBox.to = iBar.time; AddIfNotExists( supportBox, supports // ); } // // Resistance ... XBoxZone resistanceBox; has = iStructure.pvAnalysis.HasResistanceBox(resistanceBox); if (has) { // resistanceBox.to = iBar.time; AddIfNotExists( resistanceBox, supports // ); } // // Pivots ... XPivot pivots[]; count = poiDetector.ExtractPVPivots( pivots, barIndex, numberOfPivots // ); has = IsValidSize(count); // // Sort ... Sort( pivots, X_SORT_BY_DATE, X_DIRECTION_BEARISH // ); // // Remove Newest ... ArrayRemove( pivots, 0, 1 // ); // // Check Trend ... if (has) { // XPivot highs[]; int highsCount = ExtractPivots( highs, pivots, X_PIVOT_TYPE_PEAK // ); Sort( highs, X_SORT_BY_DATE, X_DIRECTION_BEARISH // ); // XPivot lows[]; int lowsCount = ExtractPivots( lows, pivots, X_PIVOT_TYPE_VALE // ); Sort( lows, X_SORT_BY_DATE, X_DIRECTION_BEARISH // ); // // Check Highs and Lows ... has = IsValidSize(lowsCount) && IsValidSize(highsCount) && lowsCount >= 2 && highsCount >= 2; if (has) { // // Try to Get Market Strucutre ... // bool hasLowerHigh = highs[0].value < highs[1].value; bool hasLowerLow = lows[0].value < lows[1].value; // bool hasHigherHigh = highs[0].value > highs[1].value; bool hasHigherLow = lows[0].value > lows[1].value; // pvTrend = (hasHigherHigh && hasHigherLow) ? X_DIRECTION_BULLISH : (hasLowerHigh && hasLowerLow) ? X_DIRECTION_BEARISH : X_DIRECTION_NONE; has = HasDirection(pvTrend); if (has) { // // Select Swings for Trend Line ... XOHCL tmpBar; int llIDX = -1; int hhIDX = -1; datetime toTime = NULL; datetime fromTime = NULL; double toPrice = EMPTY_VALUE; color trendColor = CLR_NONE; double fromPrice = EMPTY_VALUE; if (IsSpecifiedBullish(pvTrend)) { // llIDX = GetLowest(lows); hhIDX = GetHighest(lows); // trendColor = clrAqua; // toTime = lows[hhIDX].time; toPrice = lows[hhIDX].value; // fromTime = lows[llIDX].time; fromPrice = lows[llIDX].value; } else { // llIDX = GetLowest(highs); hhIDX = GetHighest(highs); // trendColor = clrMagenta; // toTime = highs[llIDX].time; toPrice = highs[llIDX].value; // fromTime = highs[hhIDX].time; fromPrice = highs[hhIDX].value; } // // Check Requirements for Trend ... has = NotEmptyZero(toPrice) && NotEmptyZero(fromPrice) && IsSpecifiedValid(toTime) && IsSpecifiedValid(fromTime); if (has) { // has = poiDrawer.DrawTrendLine( fromPrice, fromTime, toPrice, toTime, pvTrendLine, pvTrendName, true // Ray Right ... ); if (has) { pvTrendLine.Color(trendColor); } } // // Cleanup Resources ... tmpBar.Clean(); } // if (!has) { SpecifiedClean(pivots); } } // // Cleanup Resources ... SpecifiedClean(lows); SpecifiedClean(highs); } // has = HasChild(pivots); if (has) { // Copy( pivots, pvPivots // ); } // // Cleanup Resources ... SpecifiedClean(pivots); } // // ZigZag Trend Line ... bool hasZGAnalysis = iStructure.zigzagAnalysis.IsValid(); if (hasZGAnalysis) { // // Support ... XBoxZone supportBox; has = iStructure.zigzagAnalysis.HasSupportBox(supportBox); if (has) { // supportBox.to = iBar.time; AddIfNotExists( supportBox, supports // ); } // // Resistance ... XBoxZone resistanceBox; has = iStructure.zigzagAnalysis.HasResistanceBox(resistanceBox); if (has) { // resistanceBox.to = iBar.time; AddIfNotExists( resistanceBox, supports // ); } // // Pivots ... XPivot pivots[]; count = poiDetector.ExtractZigZagPivots( pivots, barIndex, numberOfPivots // ); has = IsValidSize(count); // // Sort ... Sort( pivots, X_SORT_BY_DATE, X_DIRECTION_BEARISH // ); // // Remove Newest ... ArrayRemove( pivots, 0, 1 // ); // // Check Trend ... if (has) { // XPivot highs[]; int highsCount = ExtractPivots( highs, pivots, X_PIVOT_TYPE_PEAK // ); Sort( highs, X_SORT_BY_DATE, X_DIRECTION_BEARISH // ); // XPivot lows[]; int lowsCount = ExtractPivots( lows, pivots, X_PIVOT_TYPE_VALE // ); Sort( lows, X_SORT_BY_DATE, X_DIRECTION_BEARISH // ); // // Check Highs and Lows ... has = IsValidSize(lowsCount) && IsValidSize(highsCount) && lowsCount >= 2 && highsCount >= 2; if (has) { // // Try to Get Market Strucutre ... // bool hasLowerHigh = highs[0].value < highs[1].value; bool hasLowerLow = lows[0].value < lows[1].value; // bool hasHigherHigh = highs[0].value > highs[1].value; bool hasHigherLow = lows[0].value > lows[1].value; // zgTrend = (hasHigherHigh && hasHigherLow) ? X_DIRECTION_BULLISH : (hasLowerHigh && hasLowerLow) ? X_DIRECTION_BEARISH : X_DIRECTION_NONE; has = HasDirection(zgTrend); if (has) { // // Select Swings for Trend Line ... XOHCL tmpBar; int llIDX = -1; int hhIDX = -1; datetime toTime = NULL; datetime fromTime = NULL; double toPrice = EMPTY_VALUE; color trendColor = CLR_NONE; double fromPrice = EMPTY_VALUE; if (IsSpecifiedBullish(zgTrend)) { // llIDX = GetLowest(lows); hhIDX = GetHighest(lows); // trendColor = clrAqua; // toTime = lows[hhIDX].time; toPrice = lows[hhIDX].value; // fromTime = lows[llIDX].time; fromPrice = lows[llIDX].value; } else { // llIDX = GetLowest(highs); hhIDX = GetHighest(highs); // trendColor = clrMagenta; // toTime = highs[llIDX].time; toPrice = highs[llIDX].value; // fromTime = highs[hhIDX].time; fromPrice = highs[hhIDX].value; } // // Check Requirements for Trend ... has = NotEmptyZero(toPrice) && NotEmptyZero(fromPrice) && IsSpecifiedValid(toTime) && IsSpecifiedValid(fromTime); if (has) { // has = poiDrawer.DrawTrendLine( fromPrice, fromTime, toPrice, toTime, zgTrendLine, zgTrendName, true // Ray Right ... ); if (has) { zgTrendLine.Color(trendColor); } } // // Cleanup Resources ... tmpBar.Clean(); } // if (!has) { SpecifiedClean(pivots); } } // // Cleanup Resources ... SpecifiedClean(lows); SpecifiedClean(highs); } // has = HasChild(pivots); if (has) { // Copy( pivots, zgPivots // ); } // // Cleanup Resources ... SpecifiedClean(pivots); } // // Support ... bool hasSupport = iStructure.support.IsValid(); if (hasSupport) { // iStructure.support.to = iBar.time; AddIfNotExists( iStructure.support, supports // ); } // // Resistance ... bool hasResistance = iStructure.resistance.IsValid(); if (hasResistance) { // iStructure.resistance.to = iBar.time; AddIfNotExists( iStructure.resistance, resistances // ); } // // Disable Signallers ... has = false; // // Strategy 1 ... // Works on Support or Resistances Areas ... // has = Strategy1HasSignal( // iBar, // iZone, // supports, // resistances, // iDir, // iStructure, // iFIMAConditions // // ); // // Strategy 2 ... // Works on MA Crosses ... has = Strategy2HasSignal( iBar, iZone, supports, resistances, iDir, iStructure, iFIMAConditions // ); // has = HasDirection(iDir); if (has) { // isBullish = IsXBullish(iDir); isBearish = IsXBearish(iDir); // // TODO: Provided SL ... double _point = GetPoints(iBar.symbol); double slAddition = 5 * _point; double slPrice = isBullish ? iZone.lower - slAddition : iZone.upper + slAddition; // // Prepare Founded Signal ... has = PrepareSignal( iSignal, iDir, targets, 0, // Use Default R2R ... slPrice, // Provided Price for SL ... 0 // Specified Risk in Point .... ); if (has) { // // Notify On Signal Event ... NotifySignalEventListeners(iSignal); } } // // Cleanup Resources ... iBar.Clean(); iZone.Clean(); iSignal.Clean(); iStructure.Clean(); iFIMAConditions.Clean(); SpecifiedClean(targets); SpecifiedClean(pvPivots); SpecifiedClean(zgPivots); SpecifiedClean(supports); SpecifiedClean(resistances); } /** * Check Guards Based on MarketConditions ... * * @param guards: XGuard[] * @param barIndex: int * * @return ( int ) */ int virtual CheckForGuard( XGuard &guards[], int barIndex = 0 // ) { // int result = 0; // SpecifiedClean(guards); // result = ArraySize(guards); // return result; } // // Private ... private: // // Props ... // // Implementing Strategies ... /** * Check Bar Has Signal Based on Strategy 1 ... * * @param bar: XOHCL, reference to Bar ... * @param iZone: XBoxZone, reference to holds affected zone ... * @param supports: XBoxZone, array reference to Provide Exists Supports ... * @param resistances: XBoxZone, array reference to Provide Exists Resistances ... * @param iDir: ENUM_X_DIRECTION, detected Signal's direction ... * @param structure: XFIMAMarketStructure, refrence to Provides Market Structure ... * @param conditions: XFIMAConditions, reference to Bar Specified XFIMA Conditions ... * * @return ( bool ) */ bool Strategy1HasSignal( XOHCL &bar, XBoxZone &iZone, XBoxZone &supports[], XBoxZone &resistances[], ENUM_X_DIRECTION &iDir, XFIMAMarketStructure &structure, XFIMAConditions &conditions // ) { // bool result = false; // // Prepare ... iZone.Clean(); iDir = X_DIRECTION_NONE; // // Validate ... result = bar.IsValid(); if (!result) { return result; } // // Check Pattern Exists ... string patternName = NULL; ENUM_X_DIRECTION patternDir = X_DIRECTION_NONE; result = HasPattern( bar, patternName, patternDir, structure // ); if (!result) { return result; } // // Validate Pattern Based on MA Band ... result = ValidatePatternBasedOnMABand( bar, patternName, patternDir, conditions // ); if (!result) { return result; } // // Check Affected Zone ... // Select a Support or Resistance ... int insideZoneIDX = -1; result = (IsXBullish(patternDir) ? HasInside( insideZoneIDX, bar, supports // ) : IsXBearish(patternDir) ? HasInside( insideZoneIDX, bar, resistances // ) : false // ); if (!result) { return result; } // // Filling Affected Zone ... // and Validate it ... if (IsXBullish(patternDir)) { iZone = supports[insideZoneIDX]; } else if (IsXBearish(patternDir)) { iZone = resistances[insideZoneIDX]; } result = iZone.IsValid(); if (!result) { return result; } // // Validate affected Zone based on Pattern's Bar ... result = IsXBullish(patternDir) ? bar.high > iZone.upper : IsXBearish(patternDir) ? bar.low < iZone.lower : false; if (result) { iDir = patternDir; } // // Cleanup Resources ... if (!result) { iZone.Clean(); } // return result; } /** * Check Bar Has Signal Based on Strategy 1 ... * * @param bar: XOHCL, reference to Bar ... * @param iZone: XBoxZone, reference to holds affected zone ... * @param supports: XBoxZone, array reference to Provide Exists Supports ... * @param resistances: XBoxZone, array reference to Provide Exists Resistances ... * @param iDir: ENUM_X_DIRECTION, detected Signal's direction ... * @param structure: XFIMAMarketStructure, refrence to Provides Market Structure ... * @param conditions: XFIMAConditions, reference to Bar Specified XFIMA Conditions ... * * @return ( bool ) */ bool Strategy2HasSignal( XOHCL &bar, XBoxZone &iZone, XBoxZone &supports[], XBoxZone &resistances[], ENUM_X_DIRECTION &iDir, XFIMAMarketStructure &structure, XFIMAConditions &conditions // ) { // bool result = false; // // Prepare ... iZone.Clean(); iDir = X_DIRECTION_NONE; // // Validate ... result = bar.IsValid(); if (!result) { return result; } // // Detect Specified MA Cross ... result = HasDirection(structure.maCrossDir); // // Validate Conditions ... // // Prepare iZone ... iZone.to = bar.time; iZone.from = GetBarTime( bar.symbol, bar.period, bar.Index() + 2 // ); iZone.symbol = bar.symbol; iZone.period = bar.period; iZone.dir = structure.maCrossDir; iZone.lower = bar.FindLowest(2, MODE_LOW); iZone.upper = bar.FindHighest(2, MODE_HIGH); iZone.type = name + "_" + ToXString(structure.maCrossDir); // // Check Result ... result = iZone.IsValid(); if (result) { iDir = structure.maCrossDir; } // // Cleanup Resources ... if (!result) { iZone.Clean(); } // return result; } // }; //