/////////////////////////////////////////////////////// // // 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 ... // bool ignoreTargets; // Ignore Signal Targets ... CArrayObj drawnObjects; // Drawing Objects Holder ... XFIMAInputs fimaInputs; // XFIMA Inputs ... XCXFIMAHelper *fimaHelper; // XFIMA Indicator Helper ... XCXFIMAPOIDrawer *poiDrawer; // XFIMA POI Drawer ... XCXFIMAPOIDetector *poiDetector; // XFIMA POI Detector ... XFIMAMarketStructureConfig structureConfig; // XFIMA Market Structure Detector Config ... XFIMAMarketStructureDrawerConfig structureDrawConfig; // XFIMA Market Structure Draw Config ... // // 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); // // Configure ... structureConfig.Default(); structureDrawConfig.Default(); } // // Deconstructor ... ~XCXFIMABaseSignaller() { Destroy(); } // // Overrides ... // // Actions ... /** * Destroy ... */ void Destroy() { // BeforeDestroy(); // fimaInputs.Clean(); // delete fimaHelper; ZeroMemory(fimaHelper); // delete poiDrawer; ZeroMemory(poiDrawer); // delete poiDetector; ZeroMemory(poiDetector); // structureConfig.Clean(); structureDrawConfig.Clean(); } // // 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, reference collection to holds result ... * @param positions: XPosition, reference collection to provides positions ... * @param barIndex: int * * @return ( int ) */ int virtual CheckForGuard( XGuard &guards[], XPosition &positions[], 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 ... // // Private ... private: // }; // // XFIMA Strategy 2 Signaller Class ... class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller { // // Public ... public: // // Props ... XFIMAMarketStructure structure; // XFIMA Market Structure ... // // 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 // ) { // // Configure ... structureConfig.Default(); structureDrawConfig.Default(); // structure.Clean(); // // Ignore Signal Targets ... ignoreTargets = false; } // // Deconstructor ... ~XCXFIMAStrategy1Signaller() { // Destroy(); // structure.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 iTargets[]; string iName = NULL; bool isBullish = false; bool isBearish = false; XFIMAConditions iFIMAConditions; ENUM_X_DIRECTION iDir = 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; } // structure.Clean(); poiDetector.AnalyseMarket( structure, structureConfig, barIndex // ); // poiDrawer.drawnObjects.Clear(); // poiDrawer.DrawMarketStructure( // structure, // structureDrawConfig // // ); // // Strategy 1 ... // has = Strategy1HasSignal( // iBar, // iZone, // iTargets, // iDir, // iFIMAConditions, // structure // // ); // // Strategy 2 ... if (!has) { // // // has = Strategy2HasSignal( // iBar, // iZone, // iTargets, // iDir, // iFIMAConditions, // structure // // ); } // // Strategy 3 ... if (!has) { // // has = Strategy3HasSignal( // iBar, // iZone, // iTargets, // iDir, // iFIMAConditions, // structure // // ); } // // Strategy 4 ... has = false; if (!has) { // has = Strategy4HasSignal( iBar, iZone, iTargets, iDir, iFIMAConditions, structure // ); } // has = HasDirection(iDir) && iZone.IsValid(); if (has) { // has = false; iZone.Clean(); iDir = X_DIRECTION_NONE; } // if (has) { // isBullish = IsXBullish(iDir); isBearish = IsXBearish(iDir); // // TODO: Provided SL ... double _point = GetPoints(iBar.symbol); double slAddition = 5 * _point; double atrAddition = GetAverageTrueRange( iZone.symbol, iZone.period, 0 // ); double slPrice = isBullish ? iZone.lower - slAddition : iZone.upper + slAddition; // // Prepare Founded Signal ... // // Handle Signal Targets ... if (ignoreTargets) { XClean(iTargets); } // has = PrepareSignal( iSignal, iDir, iTargets, 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(); iFIMAConditions.Clean(); SpecifiedClean(iTargets); } /** * Check Guards Based on MarketConditions ... * * @param guards: XGuard, reference collection to holds result ... * @param positions: XPosition, reference collection to provides positions ... * @param barIndex: int * * @return ( int ) */ int virtual CheckForGuard( XGuard &guards[], XPosition &positions[], 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 zone: XBoxZone, reference to holds affected zone ... * @param targets: XTarget, reference to detected Signal's Targets collections ... * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... * @param conditions: XFIMAConditions, reference to Bar Specified XFIMA Conditions ... * @param structure: XFIMAMarketStructure, refrence to Provides Market Structure ... * * @return ( bool ) */ bool Strategy1HasSignal( XOHCL &bar, XBoxZone &zone, XTarget &targets[], ENUM_X_DIRECTION &dir, XFIMAConditions &conditions, XFIMAMarketStructure &_structure // ) { // bool result = false; // // Prepare ... zone.Clean(); XClean(targets); dir = X_DIRECTION_NONE; // // Validate ... result = bar.IsValid(); if (!result) { return result; } // // Testing Porposes ... result = result && fimaHelper.IsBoundaryFakeBreaked( dir, bar.Index(), X_PRICE_CLOSE, X_PRICE_CLOSE // ); // // Nearest Noisy ZG Pivot Must has Same Direction // by Boundary Faked Break ... result = result && HasDirection(dir) && _structure.zgAnalysis.IsValid() && _structure.zgAnalysis.HasPivots() && _structure.zgAnalysis.pivots[0].dir == dir; // // We Have to Detect a Zone which Nearest ZG Pivot Reject or goes inside it ... // int idx = -1; XOHCL tmpBar; XPivot pivot; XPivot pivots[]; XBoxZone zones[]; bool has = false; int zonesCount = 0; int pivotIndex = -1; XBoxZone affectedZone; double bullishScore = 0; double bearishScore = 0; int prevPivotIndex = -1; XBoxZone affectedZones[]; int affectedZonesCount = 0; // Copy( _structure.zgAnalysis.pivots, pivots // ); pivot = pivots[0]; ArrayRemove(pivots, 0, 1); // bool isBullish = IsXBullish(dir); bool isBearish = IsXBearish(dir); // zonesCount = _structure.CollectZones( zones, dir // ); result = result && IsValidSize(zonesCount); // // Noisey ZG Pivot must inside atleast one of Zones ... // // Initial Pivots Bar ... result = result && bar.BarAt(pivot.time, tmpBar); // // Extract Affected Zones ... if (result) { // affectedZonesCount = ExtractAffectedZones( tmpBar, zones, affectedZones, dir // ); } // // Validate Affected Zones ... result = result && HasChild(affectedZones) && affectedZonesCount >= 1; if (result) { affectedZone = affectedZones[0]; } result = result && affectedZone.IsValid() && (isBullish ? bar.close > affectedZone.upper : bar.close < affectedZone.lower); // // There Must another Same Directional ZG Pivot Exists // which is Affect another Zone ... idx = GetYoungest(pivots, pivot.type); result = result && IsValidIndex(idx) && affectedZone.IsValid() && (isBullish ? pivots[idx].value < pivot.value : pivots[idx].value > pivot.value); if (result) { // pivot.Clean(); tmpBar.Clean(); pivot = pivots[idx]; XClean(affectedZones); ArrayRemove(pivots, idx, 1); // result = bar.BarAt(pivot.time, tmpBar); } // // Extract Affected Zones ... XClean(affectedZones); affectedZonesCount = 0; if (result) { // affectedZonesCount = ExtractAffectedZones( tmpBar, zones, affectedZones, dir // ); } result = result && HasChild(affectedZones) && affectedZonesCount >= 1; // // Handling Scores ... if (result) { // for (int i = 0; i < ArraySize(_structure.barsAnalysis); i++) { // bullishScore += _structure.barsAnalysis[i].Count(X_DIRECTION_BULLISH); bearishScore += _structure.barsAnalysis[i].Count(X_DIRECTION_BEARISH); } } result = isBullish ? bullishScore > bearishScore : bearishScore > bullishScore; // // Last Validation is Candlestick Patterns of Bar ... // XPatternAnalysis barAnalysis; // result = // result && // poiDetector.AnalyseBarPatterns( // bar, // barAnalysis, // structureConfig.barsAnalysisConfig // // ); // if (!result) { // dir = X_DIRECTION_NONE; // return result; } // // Drawa ... if (result) { // // Affected Zone ... XCBoxObject *iObj; has = poiDrawer.DrawBox( affectedZone, iObj, true, affectedZone.type + "_" + ToXString(TimeToSeconds(affectedZone.from)) // ); if (has) { // XPOIStyle iStyle; poiDrawer.GetBoxStyle( iStyle, affectedZone.dir // ); iStyle.clr = clrYellow; poiDrawer.ApplyBoxStyle( iObj, iStyle // ); iStyle.Clean(); // Print("Affected Zone ..."); } // // Draw Bar Pattern ... // poiDrawer.DrawPatternAnalysis(barAnalysis, structureDrawConfig.barAnalysisDrawConfig); } // // Prepare zone ... if (result) { // zone = affectedZone; // zone.type = name + "_" + ToXString(dir); // double entry = GetEntry(bar.symbol, dir); double points = GetPoints(bar.symbol); double risk = MathAbs(entry - (isBullish ? zone.lower : zone.upper)); double reward = risk * defaultSignalR2R; // // Partially Close on TP 1 ... double tp1 = isBullish ? entry + (risk * 1) : entry - (risk * 1); XTarget target1; target1.target = tp1; target1.doRF = false; target1.actingDistance = 2; target1.volumeMultiplier = 0.5; // // TP 3 ... double tp3 = isBullish ? entry + (risk * 3) : entry - (risk * 3); XTarget target3; target3.target = tp3; target3.doRF = true; target3.actingDistance = 10; // // TP 5 ... double tp5 = isBullish ? entry + (risk * 5) : entry - (risk * 5); XTarget target5; target5.target = tp5; target5.doRF = true; target5.actingDistance = 10; // AddRef( target1, targets // ); AddRef( target3, targets // ); AddRef( target5, targets // ); // result = zone.IsValid(); } // // Check Result ... if (result) { // // dir = structure.maCrossDir; // // Handle Targets Detection ... } // // Cleanup ... if (!result) { // zone.Clean(); XClean(targets); } // pivot.Clean(); XClean(zones); tmpBar.Clean(); XClean(pivots); affectedZone.Clean(); XClean(affectedZones); // return result; } /** * Check Bar Has Signal Based on Strategy 2 ... * * @param bar: XOHCL, reference to Bar ... * @param zone: XBoxZone, reference to holds affected zone ... * @param targets: XTarget, reference to detected Signal's Targets collections ... * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... * @param conditions: XFIMAConditions, reference to Bar Specified XFIMA Conditions ... * @param structure: XFIMAMarketStructure, refrence to Provides Market Structure ... * * @return ( bool ) */ bool Strategy2HasSignal( XOHCL &bar, XBoxZone &zone, XTarget &targets[], ENUM_X_DIRECTION &dir, XFIMAConditions &conditions, XFIMAMarketStructure &_structure // ) { // bool result = false; // // Prepare ... XOHCL pBar; XOHCL p2Bar; zone.Clean(); pBar.Clean(); p2Bar.Clean(); XClean(targets); dir = X_DIRECTION_NONE; // // Validate ... result = bar.IsValid() && bar.GetPreviousBar(pBar) && pBar.GetPreviousBar(p2Bar); if (!result) { return result; } // result = false; bool isBullish = false; bool isBearish = false; ENUM_X_DIRECTION tmpDir; // // Do Signal Detection ... // // Preparing Requirement Conditions ... // Here we Have to Prepare Some Directional Confirmations Using Indicators ... // for Validate Signals ... // int verifierBarIndex = pBar.Index(); // bool hasSarSwitch = fimaHelper.HasSARSwitch(tmpDir, verifierBarIndex); bool isSarSwitchedToBullish = hasSarSwitch && IsXBullish(tmpDir); bool isSarSwitchedToBearish = hasSarSwitch && IsXBearish(tmpDir); // bool hasMACross = fimaHelper.HasMACross( tmpDir, verifierBarIndex, structureConfig.maCrossValidationDiffMultiplier // ); bool isCrossedOver = hasMACross && IsXBullish(tmpDir); bool isCrossedUnder = hasMACross && IsXBearish(tmpDir); // bool hasHKSwitch = fimaHelper.HasHKSwitch(tmpDir, verifierBarIndex); bool isHKSwitchedToBullish = hasHKSwitch && IsXBullish(tmpDir); bool isHKSwitchedToBearish = hasHKSwitch && IsXBearish(tmpDir); // bool isBoundaryFakeBreaked = fimaHelper.IsBoundaryFakeBreaked(tmpDir, verifierBarIndex); bool isBoundaryFakeBreakedBullish = isBoundaryFakeBreaked && IsXBullish(tmpDir); bool isBoundaryFakeBreakedBearish = isBoundaryFakeBreaked && IsBearish(tmpDir); // bool hasZigZagHigherLow = fimaHelper.HasZigZagHigherLow(bar.Index(), true); bool hasZigZagLowerHigh = fimaHelper.HasZigZagLowerHigh(bar.Index(), true); // // Summarize Confirmations ... // bool isBullishConfirmed = (hasZigZagHigherLow && ( // isCrossedOver || isHKSwitchedToBullish || isSarSwitchedToBullish || isBoundaryFakeBreakedBullish // )); // bool isBearishConfirmed = (hasZigZagLowerHigh && ( // isCrossedUnder || isHKSwitchedToBearish || isSarSwitchedToBearish || isBoundaryFakeBreakedBullish // )); // // Validation Patterns ... int directionalPatternsValidations = 3; // // Check Bullish Conditions ... isBullish = // // Confirmations Passed ... isBullishConfirmed && // // Quarters Has Minor Support Zone ... _structure.barAnalysis.HasMinorSupport() && // // Current Bar's Price Placed Propper ... bar.open > _structure.barAnalysis.minorSupport.upper && bar.close > _structure.barAnalysis.minorSupport.upper && // // Required Number of Pivots Validation Exists ... (_structure.barsAnalysis[1].Count(X_DIRECTION_BULLISH) >= directionalPatternsValidations) && // // Bar or PBar ReTested Quarter Zone ... (IsTested( pBar, _structure.barAnalysis.minorSupport // ) || IsTested( p2Bar, _structure.barAnalysis.minorSupport // )) // ; // // Check Bearish Conditions ... isBearish = // // Confirmations Passed ... isBearishConfirmed && // // Quarters Has Minor Resistance Zone ... _structure.barAnalysis.HasMinorResistance() && // // Current Bar's Price Placed Propper ... bar.open < _structure.barAnalysis.minorResistance.lower && bar.close < _structure.barAnalysis.minorResistance.lower && // // Required Number of Pivots Validation Exists ... (_structure.barsAnalysis[1].Count(X_DIRECTION_BEARISH) >= directionalPatternsValidations) && // // Bar or pBar ReTested Quarter Zone ... (IsTested( pBar, _structure.barAnalysis.minorResistance // ) || IsTested( p2Bar, _structure.barAnalysis.minorResistance // )) // ; // // Summarize Conditions ... result = isBullish || isBearish; // // Assign Direction ... if (result) { // dir = isBullish ? X_DIRECTION_BULLISH : isBearish ? X_DIRECTION_BEARISH : X_DIRECTION_NONE; // if (isBullish) { zone = _structure.barAnalysis.minorSupport; } // if (isBearish) { zone = _structure.barAnalysis.minorResistance; } } // // Validate Result ... result = result && zone.IsValid() && HasDirection(dir); // if (result) // { // // // XPOIDrawConfig iConfig = structureDrawConfig // .barAnalysisDrawConfig // .quarterMinorsDrawConfig; // iConfig.zonesWidth = 3; // iConfig.zonesFill = true; // iConfig.bullishColor = clrYellow; // iConfig.bearishColor = clrYellow; // // // if (isBullish) // { // // // poiDrawer.DrawZone( // _structure.barAnalysis.minorSupport, // iConfig // // ); // // // Print("Bullish Condition ..."); // } // // // if (isBearish) // { // // // poiDrawer.DrawZone( // _structure.barAnalysis.minorResistance, // iConfig // // ); // // // Print("Bearish Condition ..."); // } // // // Print(ToXString(dir), " Detected ..."); // } // // Provide Direction and Targets if Required ... if (result) { // // Handle Targets Detection ... // double spread = GetSpread(zone.symbol); double entry = GetEntry(zone.symbol, dir); // double risk = isBullish ? entry - zone.lower : zone.upper - entry; double reward1 = entry + (isBullish ? risk : (-1 * risk) // ); double reward4 = entry + (isBullish ? 4 * risk : (-4 * risk) // ); double requiredDistance = PriceToPoint(spread * 2, zone.symbol); // XTarget iRFOnEntryOnTP1; iRFOnEntryOnTP1.target = reward1; iRFOnEntryOnTP1.tpValue = reward4; iRFOnEntryOnTP1.doRFOnEntry = true; iRFOnEntryOnTP1.volumeMultiplier = 0.5; iRFOnEntryOnTP1.actingDistance = requiredDistance; // AddRef( iRFOnEntryOnTP1, targets // ); } // // Cleanup Resources ... if (!result) { // zone.Clean(); XClean(targets); } pBar.Clean(); p2Bar.Clean(); // return result; } /** * Check Bar Has Signal Based on Strategy 3 ... * * @param bar: XOHCL, reference to Bar ... * @param zone: XBoxZone, reference to holds affected zone ... * @param targets: XTarget, reference to detected Signal's Targets collections ... * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... * @param conditions: XFIMAConditions, reference to Bar Specified XFIMA Conditions ... * @param structure: XFIMAMarketStructure, refrence to Provides Market Structure ... * * @return ( bool ) */ bool Strategy3HasSignal( XOHCL &bar, XBoxZone &zone, XTarget &targets[], ENUM_X_DIRECTION &dir, XFIMAConditions &conditions, XFIMAMarketStructure &_structure // ) { // bool result = false; // // Prepare ... zone.Clean(); XClean(targets); dir = X_DIRECTION_NONE; // // Validate ... result = bar.IsValid(); if (!result) { return result; } // // Define Requirements ... bool isBullish = false; bool isBearish = false; // XOHCL pBar; int barIndex = bar.Index(); int pBarIndex = barIndex + 1; result = bar.GetPreviousBar(pBar); if (!result) { return result; } // // Do Conditions Checking ... // XBoxZone zones[]; int zonesCount = 0; ENUM_X_PRICE bullishPriceType = X_PRICE_LOW; ENUM_X_PRICE bearishPriceType = X_PRICE_HIGH; // isBullish = fimaHelper.IsSwitchedUnderHKBondLower(bullishPriceType, pBarIndex); // isBearish = fimaHelper.IsSwitchedOverHKBondUpper(bearishPriceType, pBarIndex); // result = isBullish || isBearish; // // Do Validations ... if (result) { // // Direction Assignment ... dir = isBullish ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; // int lastIDX; XBoxZone tmpZones[]; int tmpZonesCount = 0; int validationCount = 0; ENUM_X_PRICE priceType = isBullish ? bullishPriceType : bearishPriceType; // // Detect Last Direction Change ... if (isBullish) { result = fimaHelper.FindLastUnderHKBondLower(lastIDX, bullishPriceType, pBarIndex); } else { result = fimaHelper.FindLastOverHKBondUpper(lastIDX, bearishPriceType, pBarIndex); } // // Validate Direction Changed ... if (result) { // validationCount = lastIDX - pBarIndex; result = validationCount >= 10; } // // Collect Zones ... if (result) { // // Support and Resistances ... tmpZonesCount = poiDetector.CollectZones( pBar, tmpZones, 5, 14, // Zones Validation Length ... 0, // Required Count ... validationCount // Loopback ... ); if (IsValidSize(tmpZonesCount)) { // Copy( tmpZones, zones, false // ignore Clean ... ); } // // OB ... tmpZonesCount = poiDetector.CollectOBs( pBar, tmpZones, 5, // Zones Loopback ... 0, // Required Count ... validationCount // Loopback ... ); if (IsValidSize(tmpZonesCount)) { // Copy( tmpZones, zones, false // ignore Clean ... ); } // // FVG ... tmpZonesCount = poiDetector.CollectFVGs( pBar, tmpZones, 5, // Zones Loopback ... 0, // Required Count ... validationCount // Loopback ... ); if (IsValidSize(tmpZonesCount)) { // Copy( tmpZones, zones, false // ignore Clean ... ); } // // Filter Zones Based on pBar ... zonesCount = poiDetector.FilterZones( pBar, zones, dir, priceType, dir // ); // // Extract Affected Zones ... XClean(tmpZones); tmpZonesCount = ExtractAffectedZones( pBar, zones, tmpZones, dir // ); Copy(tmpZones, zones); zonesCount = ArraySize(zones); // // Update Zones Time ... UpdateToTime(zones); } // // Draw Zones ... result = IsValidSize(zonesCount); if (result) { // for (int i = 0; i < zonesCount; i++) { poiDrawer.DrawZone(zones[i], structureDrawConfig.drawConfig); } } // XClean(tmpZones); } // // Prepare Zone ... if (result) { // // Zone Detection ... zone.Clean(); if (isBullish) { // int idx = GetLowest(zones); if (IsValidIndex(idx)) { zone = zones[idx]; } } else { // int idx = GetHighest(zones); if (IsValidIndex(idx)) { zone = zones[idx]; } } // zone.dir = dir; // zone.type = name; // zone.to = bar.time; // zone.at = pBar.time; // zone.from = pBar.time; // zone.symbol = bar.symbol; // zone.period = bar.period; // zone.lower = MathMin(pBar.low, bar.low); // zone.upper = MathMax(pBar.high, bar.high); // result = zone.IsValid(); } // // Prepare Targets ... if (result) { // // Target Handling ... } // // Cleanup ... if (!result) { // zone.Clean(); XClean(targets); dir = X_DIRECTION_NONE; } pBar.Clean(); XClean(zones); // return result; } /** * Check Bar Has Signal Based on Strategy 4 ... * * @param bar: XOHCL, reference to Bar ... * @param zone: XBoxZone, reference to holds affected zone ... * @param targets: XTarget, reference to detected Signal's Targets collections ... * @param dir: ENUM_X_DIRECTION, detected Signal's direction ... * @param conditions: XFIMAConditions, reference to Bar Specified XFIMA Conditions ... * @param structure: XFIMAMarketStructure, refrence to Provides Market Structure ... * * @return ( bool ) */ bool Strategy4HasSignal( XOHCL &bar, XBoxZone &zone, XTarget &targets[], ENUM_X_DIRECTION &dir, XFIMAConditions &conditions, XFIMAMarketStructure &_structure // ) { // bool result = false; // // Prepare ... zone.Clean(); XClean(targets); dir = X_DIRECTION_NONE; // // Validate ... result = bar.IsValid(); if (!result) { return result; } // // Define Requirements ... bool isBullish = false; bool isBearish = false; // XOHCL pBar; int barIndex = bar.Index(); int pBarIndex = barIndex + 1; result = bar.GetPreviousBar(pBar); if (!result) { return result; } // // Do Conditions Checking ... // // Reading HK Bond ... double hkBondUpper = fimaHelper.GetHKBondUpper(pBarIndex); double hkBondLower = fimaHelper.GetHKBondLower(pBarIndex); bool hasHKBoundary = NotEmptyZero(hkBondUpper) && NotEmptyZero(hkBondLower); // // Pullback Detection ... bool isPullback = poiDetector.IsPullbackPattern( pBar, zone, dir, 2, false // ); // isBullish = isPullback && hasHKBoundary && IsXBullish(dir) && zone.lower > hkBondLower; // isBearish = isPullback && hasHKBoundary && IsXBearish(dir) && zone.upper < hkBondUpper; // result = isBullish || isBearish; // // Do Validations ... if (result) { // // Direction Assignment ... dir = isBullish ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; // // TEMP ... poiDrawer.DrawZone( zone, structureDrawConfig.drawConfig // ); } // // Prepare Decision Zone ... if (result) { // // Zone Detection ... zone.Clean(); // // zone.dir = dir; // zone.type = name; // zone.to = bar.time; // zone.at = pBar.time; // zone.from = pBar.time; // zone.symbol = bar.symbol; // zone.period = bar.period; // zone.lower = MathMin(pBar.low, bar.low); // zone.upper = MathMax(pBar.high, bar.high); // result = zone.IsValid(); } // // Prepare Targets ... if (result) { // // Target Handling ... } // // Cleanup ... if (!result) { // zone.Clean(); XClean(targets); dir = X_DIRECTION_NONE; } pBar.Clean(); // return result; } // }; //