/////////////////////////////////////////////////////// // // 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.parser.class.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 ... // CArrayObj drawnObjects; // Drawing Objects Holder ... XFIMAInputs fimaInputs; // XFIMA Inputs ... XCXFIMAHelper *fimaHelper; // XFIMA Indicator Helper ... XCXFIMAPOIDrawer *poiDrawer; // XFIMA POI Drawer ... XCXFIMAHelperParser *fimaParser; // XFIMA Helper Parser ... 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); } } // // Instantiate XFIMA Helper Parser ... fimaParser = new XCXFIMAHelperParser(fimaHelper); // poiDrawer = new XCXFIMAPOIDrawer(); poiDetector = new XCXFIMAPOIDetector(fimaHelper, fimaParser); // // 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; if (!result) { return result; } // 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 ... // // 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 ... drawLeg = true; drawOrderFlow = true; structureConfig.Default(); structureDrawConfig.Default(); } // // Deconstructor ... ~XCXFIMAStrategy1Signaller() { // Destroy(); } // // 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; XBoxZone iZone; XSignal iSignal; bool has = false; XTarget iTargets[]; bool isBullish = false; bool isBearish = false; ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; // // Initialize Bar as CBar ... has = iBar.Init( symbol, period, barIndex // ); if (!has) { // iBar.Clean(); return; } // // Manage ... Manage(iBar); // // Strategy X ... has = HasSignal( iBar, iZone, iTargets, iDir // ); // // Handle Resting Signals ... has = HasDirection(iDir) && iZone.IsValid(); // // Prepare Signal ... if (has) { // isBullish = IsXBullish(iDir); isBearish = IsXBearish(iDir); // // Provided SL ... double points = GetPoints(symbol); double spread = GetSpread(symbol); double entry = GetEntry(symbol, iDir); // // Calculate SL Addition ... double slAddition = slAdditionDistance <= 0 ? 0 : slAdditionDistance * points; // // Calculate SL Price ... double sl = isBullish ? iZone.lower - slAddition : iZone.upper + slAddition; // // Prepare Signal ... has = PrepareSignal( iSignal, iDir, iTargets, 0, // Use Default R2R ... sl, // Provided Price for SL ... 0 // Specified Risk in Point .... ); } // // Notify On Signal Event ... if (has) { NotifySignalEventListeners(iSignal); } // // Cleanup ... iBar.Clean(); iZone.Clean(); iSignal.Clean(); XClean(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; // XClean(guards); // int positionsCount = ArraySize(positions); if (!IsValidSize(positionsCount)) { return result; } // // Requirements ... XGuard iGuard; bool has = false; // // Force Hedging ... // bool forceHedging = (positionsCount >= 2); // if (forceHedging) // { // // // // Minimum Required Reward ... // double minRequiredReward = 1.5; // // // // Summarizing Risk and Reward of Collections ... // // double risk = 0; // // double volume = 0; // // double reward = 0; // // for (int i = 0; i < positionsCount; i++) // // { // // // // // risk += positions[i].GetRisk() + positions[i].commission + (-1 * positions[i].swap); // // reward += positions[i].profit; // // volume += positions[i].volume; // // } // // // // // risk *= volume; // // reward *= volume; // // // // // // Calculating Can Hedge rops ... // // has = reward >= (risk * minRequiredReward); // // if (has) // // { // // // // // iGuard.Clean(); // // iGuard.force = true; // // iGuard.symbol = symbol; // // iGuard.period = period; // // iGuard.provider = name; // // iGuard.time = TimeCurrent(); // // iGuard.action = X_GUARD_ACTION_HEDGE; // // // // // // Validate Guard ... // // has = iGuard.IsValid(); // // if (has) // // { // // // // // AddRef( // // iGuard, // // guards // // // ); // // } // // } // } // result = ArraySize(guards); // // Cleanup ... iGuard.Clean(); // return result; } // // Protected ... protected: // // void Manage(XOHCL &bar) { // bool has = bar.IsValid(); if (!has) { return; } // XOHCL pBar; XOHCL p2Bar; XOHCL p3Bar; has = bar.GetPreviousBar(pBar); has = has && pBar.GetPreviousBar(p2Bar); has = has && p2Bar.GetPreviousBar(p3Bar); if (!has) { // pBar.Clean(); p2Bar.Clean(); p3Bar.Clean(); } // ManageLeg(bar); ManageOrderFlow(p3Bar); // // Cleanup ... pBar.Clean(); p2Bar.Clean(); p3Bar.Clean(); } // // Private ... private: // // Props ... // // Leg ... XLeg leg; // Exists Leg ... bool drawLeg; // Draw Leg ... // bool HasLeg() { return leg.IsValid(); } // bool ValidateLeg(XOHCL &bar) { // bool result = false; // result = HasLeg() && bar.IsValid(); if (!result) { return result; } // result = leg.IsBullish() ? bar.low > leg.lower : leg.IsBearish() ? bar.high < leg.upper : false; // return result; } // void DrawLeg() { // if (!drawLeg) { return; } // if (!HasLeg()) { return; } // // Update to Times ... leg.UpdateTimes(); // // Draw Leg Box ... XBoxZone legZone; leg.ToBox(legZone); if (legZone.IsValid()) { // legZone.to = TimeCurrent(); poiDrawer.DrawZone(legZone, structureDrawConfig.drawConfig); } // // Draw Legs Other Stufs ... return; // // FVGs ... poiDrawer.DrawZones(leg.bullishFVGs, structureDrawConfig.drawConfig); poiDrawer.DrawZones(leg.bearishFVGs, structureDrawConfig.drawConfig); // // Support and Resistances ... poiDrawer.DrawZones(leg.supports, structureDrawConfig.drawConfig); poiDrawer.DrawZones(leg.resistances, structureDrawConfig.drawConfig); // // Patterns ... poiDrawer.DrawPatternAnalysises(leg.patterns, structureDrawConfig.barAnalysisDrawConfig); } // void ManageLeg(XOHCL &bar) { // // Validate Exists ... if (HasLeg()) { // if (!ValidateLeg(bar)) { // // Invalidate XLeg ... leg.Clean(); } } // // Detect New ... if (!HasLeg()) { poiDetector.IsLegPattern(bar, leg); } // // Update Exists ... if (HasLeg()) { // // Update to Times ... leg.UpdateTimes(); // DrawLeg(); } } // // Order Flow ... // bool drawOrderFlow; XBoxZone orderFlow[]; ENUM_X_DIRECTION orderFlowDir; // bool HasOrderFlow() { // return HasChild(orderFlow) && HasDirection(orderFlowDir); } bool HasBullishOrderFlow() { return HasOrderFlow() && IsXBullish(orderFlowDir); } bool HasBearishOrderFlow() { return HasOrderFlow() && IsXBearish(orderFlowDir); } bool GetOrderFlowBoundary( double &upper, double &lower // ) { // bool result = false; // // Prepare ... upper = EMPTY_VALUE; lower = EMPTY_VALUE; // // Validate ... result = HasOrderFlow(); if (!result) { return result; } // int idx = -1; // // Upper ... idx = GetHighest(orderFlow); if (IsValidIndex(idx)) { upper = orderFlow[idx].upper; } // // Lower ... idx = GetLowest(orderFlow); if (IsValidIndex(idx)) { lower = orderFlow[idx].lower; } // result = NotEmptyZero(upper) && NotEmptyZero(lower) && upper > lower; // // Cleanup ... if (!result) { // upper = EMPTY_VALUE; lower = EMPTY_VALUE; } // return result; } bool ValidateOrderFlow(XOHCL &bar) { // bool result = false; // // Validate ... result = bar.IsValid() && HasOrderFlow(); if (!result) { return result; } // double upper = EMPTY_VALUE; double lower = EMPTY_VALUE; result = GetOrderFlowBoundary(upper, lower); result = result && HasBullishOrderFlow() ? bar.low > lower : bar.high < upper; // return result; } void DrawOrderFlow() { // if (!drawOrderFlow || !HasOrderFlow()) { return; } // poiDrawer.DrawZones(orderFlow, structureDrawConfig.drawConfig); } void ManageOrderFlow(XOHCL &bar) { // // Validate Exists ... if (HasOrderFlow()) { // if (!ValidateOrderFlow(bar)) { // // Invalidate OrderFlow ... XClean(orderFlow); orderFlowDir = X_DIRECTION_NONE; } } // // Detect New ... if (!HasOrderFlow()) { // XPatternAnalysisConfig patternConfig = structureConfig.barsAnalysisConfig; // patternConfig.Default(); // patternConfig.supportAndResistanceLoopbackLength = 21; // patternConfig.supportAndResistanceValidationLength = 7; // poiDetector.HasOrderFlow( bar, orderFlowDir, orderFlow, structureConfig.orderFlowValidation, structureConfig.orderFlowUseOB, structureConfig.orderFlowUseFVG, structureConfig.orderFlowUseSupportAndResistance, patternConfig.supportAndResistanceLoopbackLength, patternConfig.supportAndResistanceValidationLength, structureConfig.loopback // ); } // // Update Exists ... if (HasOrderFlow()) { // // Update to Times ... UpdateToTime(orderFlow, TimeCurrent()); // DrawOrderFlow(); } } // // Implementing Strategies ... /** * Check Bar Has Signal Based on Strategy X ... * * @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 ... * * @return ( bool ) */ bool HasSignal( XOHCL &bar, XBoxZone &zone, XTarget &targets[], ENUM_X_DIRECTION &dir // ) { // bool result = false; // // Configuration Flags ... // // Signaller Flags ... bool useSignaller1 = false; bool useSignaller2 = false; bool useSignaller3 = false; bool useSignaller4 = true; // // Validator Flags ... string provider = NULL; bool validateByOrderFlow = false; // // Target Flags ... bool hasPartialCloseOnTp1 = false; // bool doRFOnEntryOnTP1 = false; // // Draw Flags ... bool draw = true; bool drawZone = true; bool drawMarketStructurePivots = true; bool drawMarketStructureAnalysis = true; bool drawMarketStructureOrderFlow = true; XPOIDrawConfig iDrawConfig; // drawLeg = false; drawOrderFlow = false; // // Signal Checking ... // // Analyse Market Strucutre ... XFIMAMarketStructure marketStructure; // // Check Market ... // result = HasLeg() && // HasOrderFlow() && // orderFlowDir == leg.dir; // result = HasBearishOrderFlow(); // if (result) // { // // // result = false; // DebugBreak(); // } // // Signaller 1 ... if (!result && useSignaller1) { // result = Strategy1HasSignal( bar, zone, targets, dir // ); // if (result) { provider = "1"; } } // // Signaller 2 ... if (!result && useSignaller2) { // result = Strategy2HasSignal( bar, zone, targets, dir // ); // if (result) { provider = "2"; } } // // Signaller 3 ... if (!result && useSignaller3) { // result = Strategy3HasSignal( bar, zone, targets, dir // ); // if (result) { provider = "3"; } } // // Signaller 4 ... if (!result && useSignaller4) { // result = Strategy4HasSignal( bar, zone, targets, dir // ); // if (result) { provider = "4"; } } // // Signal Validating ... // // Validate Signals by Order Flow ... if (result && validateByOrderFlow) { // // Analyse Market Structure if Required ... if (!marketStructure.IsValid()) { // poiDetector.AnalyseMarket( marketStructure, structureConfig, bar.Index() // ); } // bool isBullish = IsXBullish(dir) && marketStructure.HasBullishOrderFlow(); // bool isBearish = IsXBearish(dir) && marketStructure.HasBearishOrderFlow(); // // Summarizing result ... result = isBullish || isBearish; } // // Targets, Restrictions and Risk Management ... if (result) { // // Requirements ... XTarget iTarget; // // Checking Direction of Signal ... bool isBullish = IsXBullish(dir); bool isBearish = IsXBearish(dir); // // Provided SL ... double points = GetPoints(symbol); double spread = GetSpread(symbol); double entry = GetEntry(symbol, dir); // // Calculate SL Addition ... double slAddition = slAdditionDistance <= 0 ? 0 : slAdditionDistance * points; // // Calculate SL Price ... double sl = isBullish ? zone.lower - slAddition : zone.upper + slAddition; // // Calculate Risk ... double risk = MathAbs(entry - sl); // // Calculate Reward ... double reward = defaultSignalR2R * risk; // // Calculate TP1 ... double tp1 = isBullish ? entry + risk : entry - risk; double tp2 = isBullish ? entry + (2 * risk) : entry - (2 * risk); // // Calculate TP ... double tp = isBullish ? entry + reward : entry - reward; // // Check Max Allowed Risk ... bool hasTooMuchRisk = maxAllowedRiskDistance <= 0 ? false : risk >= (maxAllowedRiskDistance * points); if (hasTooMuchRisk) { // // Clean Signal if Too much Risk ... zone.Clean(); dir = X_DIRECTION_NONE; } // // Common Targets ... // // Partial Close on TP 1 ... if (hasPartialCloseOnTp1) { // iTarget.Clean(); iTarget.target = tp1; iTarget.actingDistance = 5; iTarget.volumeMultiplier = 0.8; iTarget.doRFOnEntry = doRFOnEntryOnTP1; // AddRef(iTarget, targets); } // // Custom Signaller Targets ... // // Restrictions Handling ... if (risk > 0 && HasRestrictions()) { // // Reset Restricitons if necessary ... ResetRestrictions(); // // Handle Custom Restrictions Senario ... } // // Ignore Targets ... if (ignoreTargets) { XClean(targets); } // // Summarize Result ... result = zone.IsValid() && HasDirection(dir); // // Cleanup ... iTarget.Clean(); } // // Draws ... if (result && draw) { // // Prepare Draw Config ... iDrawConfig = structureDrawConfig.drawConfig; iDrawConfig.zonesWidth = 3; iDrawConfig.zonesStyle = STYLE_DASH; iDrawConfig.bullishColor = clrYellow; iDrawConfig.bearishColor = clrDarkOrange; // // Draw Zone ... if (drawZone) { poiDrawer.DrawZone(zone, iDrawConfig); } // // Draw Market Structure ... // // Analyse Market Structure if Required ... if (!marketStructure.IsValid()) { // poiDetector.AnalyseMarket( marketStructure, structureConfig, bar.Index() // ); } if (marketStructure.IsValid()) { // // Order Flow ... if (drawMarketStructureOrderFlow && marketStructure.HasOrderFlow()) { poiDrawer.DrawZones(marketStructure.orderFlow, iDrawConfig); } // // Pivots ... if (drawMarketStructurePivots) { // XPivot pivots[]; int pivotsCount = marketStructure.CollectPivots( pivots, true // Contains Patterns ... ); if (IsValidSize(pivotsCount)) { poiDrawer.DrawPivots(pivots, iDrawConfig); } // XClean(pivots); } // // Analysis ... if (drawMarketStructureAnalysis) { // } } // // Other Drawing Materials ... } // // Cleanup ... if (!result) { // zone.Clean(); XClean(targets); dir = X_DIRECTION_NONE; } // // Debug Breake ... if (result) { DebugBreak(); } // // Cleanup ... iDrawConfig.Clean(); marketStructure.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 ... * * @return ( bool ) */ bool Strategy1HasSignal( XOHCL &bar, XBoxZone &zone, XTarget &targets[], ENUM_X_DIRECTION &dir // ) { // bool result = false; // // Prepare ... zone.Clean(); XClean(targets); dir = X_DIRECTION_NONE; // // Validate ... result = bar.IsValid(); if (!result) { return result; } // // Define Requirements ... // XOHCL pBar; bool isBullish = false; bool isBearish = false; // // Read PBar ... result = bar.GetPreviousBar(pBar); if (!result) { // pBar.Clean(); return result; } // // Reading Conditions ... int pullBackStartBar = -1; bool isPullBack = result && poiDetector.IsPullbackPattern( pBar, zone, dir, 2, false // Force Break ... ); bool isPullbackBullish = isPullBack && IsXBullish(dir); bool isPullbackBearish = isPullBack && IsXBearish(dir); if (isPullBack) { pullBackStartBar = zone.FromIndex(); } // // Reading HK Band ... // double pHKBandUpper = fimaHelper.GetHKBandUpper(pBar.Index()); double pHKBandLower = fimaHelper.GetHKBandLower(pBar.Index()); int overHKBandUpperCount = fimaParser.CountOverHKBandUpper(pullBackStartBar, X_PRICE_LOW); int underHKBandLowerCount = fimaParser.CountUnderHKBandLower(pullBackStartBar, X_PRICE_HIGH); // // Reading PV Requirements ... // int lastPeakOverLastIDX = -1; int lastValeUnderLastIDX = -1; double pPeak = fimaHelper.GetPeak(pBar.Index()); double pVale = fimaHelper.GetVale(pBar.Index()); int samePeaks = fimaParser.CountSamePeaks(pBar.Index()); int sameVales = fimaParser.CountSameVales(pBar.Index()); fimaParser.FindLastPeakOverLast(lastPeakOverLastIDX, pBar.Index()); fimaParser.FindLastValeUnderLast(lastValeUnderLastIDX, pBar.Index()); // // Reading pBar Patterns ... XPatternAnalysis pBarAnalysis; poiDetector.AnalyseBarPatterns( pBar, pBarAnalysis, structureConfig.barsAnalysisConfig // ); // // Check Bar Patterns ... bool isPBarHasBullishPatterns = (bar.close > pBar.low || bar.open > pBar.low) && ( // pBarAnalysis.IsPinned(X_DIRECTION_BULLISH) || pBarAnalysis.IsEngulfed(X_DIRECTION_BULLISH) || pBarAnalysis.IsMomentum(X_DIRECTION_BULLISH) || pBarAnalysis.IsPiercing(X_DIRECTION_BULLISH) || pBarAnalysis.IsSignalKey(X_DIRECTION_BULLISH) // ); bool isPBarHasBearishPatterns = (bar.close < pBar.high || bar.open < pBar.high) && ( // pBarAnalysis.IsPinned(X_DIRECTION_BEARISH) || pBarAnalysis.IsEngulfed(X_DIRECTION_BEARISH) || pBarAnalysis.IsMomentum(X_DIRECTION_BEARISH) || pBarAnalysis.IsPiercing(X_DIRECTION_BEARISH) || pBarAnalysis.IsSignalKey(X_DIRECTION_BEARISH) // ); // // Check PBar Close Over Under Fast Ma ... bool isPBarCloseOverFast = pBar.close > fimaHelper.GetMAFast(pBar.Index()); bool isPBarCloseUnderFast = pBar.close < fimaHelper.GetMAFast(pBar.Index()); // // Try To Find Affected Zone ... // // Collecting Zones ... XBoxZone zones[]; XBoxZone affectedZones[]; XBoxZone affectedZonesBullish[]; XBoxZone affectedZonesBearish[]; int zonesCount = poiDetector.CollectZones( pBar, zones, // 5, // Zones Loopback ... 3 // Zones Validation Length ... // Required Zones ... // Loopback ... ); int affectedZonesCount = ExtractAffectedZones( pBar, zones, affectedZones // ); int affectedZonesBullishCount = ExtractByDirection( affectedZonesBullish, affectedZones, X_DIRECTION_BULLISH // ); int affectedZonesBearishCount = ExtractByDirection( affectedZonesBearish, affectedZones, X_DIRECTION_BEARISH // ); // int insideBullishIDX = -1; int insideBearishIDX = -1; bool hasBullishInside = pBar.IsBullish() && HasInside( insideBullishIDX, pBar, affectedZonesBullish // ); bool hasBearishInside = pBar.IsBearish() && HasInside( insideBearishIDX, pBar, affectedZonesBearish // ); // // Do ... // isBullish = // hasBullishInside && isPullbackBullish && isPBarHasBullishPatterns && fimaParser.IsSARBullish(pBar.Index()) && (pVale >= affectedZonesBullish[insideBullishIDX].lower && pVale <= affectedZonesBullish[insideBullishIDX].upper) // ; // isBearish = // hasBearishInside && isPullbackBearish && isPBarHasBearishPatterns && fimaParser.IsSARBearish(pBar.Index()) && (pPeak >= affectedZonesBearish[insideBearishIDX].lower && pPeak <= affectedZonesBearish[insideBearishIDX].upper) // ; // // Validate ... result = isBullish || isBearish; if (result) { // dir = isBullish ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; // result = HasDirection(dir); } // // Prepare Zone ... if (result) { // zone.Clean(); if (isBullish) { zone = affectedZonesBullish[insideBullishIDX]; } else { zone = affectedZonesBearish[insideBearishIDX]; } // result = zone.IsValid(); } // // Prepare Targets ... if (result) { } // // Cleanup ... if (!result) { // zone.Clean(); XClean(targets); dir = X_DIRECTION_NONE; } pBar.Clean(); XClean(zones); pBarAnalysis.Clean(); XClean(affectedZones); XClean(affectedZonesBullish); XClean(affectedZonesBearish); // 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 ... * * @return ( bool ) */ bool Strategy2HasSignal( XOHCL &bar, XBoxZone &zone, XTarget &targets[], ENUM_X_DIRECTION &dir // ) { // bool result = false; // // Prepare ... zone.Clean(); XClean(targets); dir = X_DIRECTION_NONE; // // Validate ... result = bar.IsValid(); if (!result) { return result; } // // Define Requirements ... // XOHCL pBar; XOHCL p2Bar; bool isBullish = false; bool isBearish = false; // // Read PBar ... result = bar.GetPreviousBar(pBar); result = result && pBar.GetPreviousBar(p2Bar); if (!result) { // pBar.Clean(); p2Bar.Clean(); // return result; } // // Reading pBar Patterns ... XPatternAnalysis pBarAnalysis; poiDetector.AnalyseBarPatterns( pBar, pBarAnalysis, structureConfig.barsAnalysisConfig // ); // // Check Bar Patterns ... bool isPBarHasBullishPatterns = (bar.close > pBar.low || bar.open > pBar.low) && ( // pBarAnalysis.IsPinned(X_DIRECTION_BULLISH) || pBarAnalysis.IsEngulfed(X_DIRECTION_BULLISH) || pBarAnalysis.IsMomentum(X_DIRECTION_BULLISH) || pBarAnalysis.IsPiercing(X_DIRECTION_BULLISH) || pBarAnalysis.IsSignalKey(X_DIRECTION_BULLISH) // ); bool isPBarHasBearishPatterns = (bar.close < pBar.high || bar.open < pBar.high) && ( // pBarAnalysis.IsPinned(X_DIRECTION_BEARISH) || pBarAnalysis.IsEngulfed(X_DIRECTION_BEARISH) || pBarAnalysis.IsMomentum(X_DIRECTION_BEARISH) || pBarAnalysis.IsPiercing(X_DIRECTION_BEARISH) || pBarAnalysis.IsSignalKey(X_DIRECTION_BEARISH) // ); // double peak = fimaHelper.GetPeak(bar.Index()); double vale = fimaHelper.GetVale(bar.Index()); double pPeak = fimaHelper.GetPeak(pBar.Index()); double pVale = fimaHelper.GetVale(pBar.Index()); double p2Peak = fimaHelper.GetPeak(p2Bar.Index()); double p2Vale = fimaHelper.GetVale(p2Bar.Index()); bool isPPeakOverLast = fimaParser.IsPeakOverLast(pBar.Index()); bool isPValeUnderLast = fimaParser.IsValeUnderLast(pBar.Index()); bool isP2PeakOverLast = fimaParser.IsPeakOverLast(p2Bar.Index()); bool isP2ValeUnderLast = fimaParser.IsValeUnderLast(p2Bar.Index()); bool isPeakOverLast = isPPeakOverLast || isP2PeakOverLast; bool isValeUnderLast = isPValeUnderLast || isP2ValeUnderLast; bool isP2ValeOverLast = pVale > p2Vale; bool isP2PeakUnderLast = pPeak < p2Peak; // // Check PBar Close Over Under Fast Ma ... bool isPBarCloseOverFast = pBar.close > fimaHelper.GetMAFast(pBar.Index()); bool isPBarCloseUnderFast = pBar.close < fimaHelper.GetMAFast(pBar.Index()); bool isFastOverLast = fimaHelper.GetMAFast(pBar.Index()) > fimaHelper.GetMAFast(p2Bar.Index()); bool isFastUnderLast = fimaHelper.GetMAFast(pBar.Index()) < fimaHelper.GetMAFast(p2Bar.Index()); // // Force P2Bar is Pin Bar ... ENUM_X_DIRECTION p2Dir; bool isP2BarPinned = poiDetector.IsPinnedBar( p2Bar, p2Dir // ); bool isP2BarBullishPinned = isP2BarPinned && IsXBullish(p2Dir); bool isP2BarBearishPinned = isP2BarPinned && IsXBearish(p2Dir); // // Do ... // isBullish = // isFastOverLast && isValeUnderLast && !isP2PeakUnderLast && isPBarCloseOverFast && isP2BarBullishPinned && isPBarHasBullishPatterns // ; // isBearish = // isPeakOverLast && isFastUnderLast && !isP2ValeOverLast && isPBarCloseUnderFast && isP2BarBearishPinned && isPBarHasBearishPatterns // ; // // Validate ... result = isBullish || isBearish; if (result) { // dir = isBullish ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; // result = HasDirection(dir); } // // Prepare Zone ... if (result) { // zone.Clean(); result = ToBox( p2Bar, zone, dir, X_BAR_PATTERN_PINNED // ); // // Manage Stops ... if (result) { // double entry = GetEntry(zone.symbol, zone.dir); double riskSide = zone.IsBullish() ? zone.lower : zone.upper; double risk = MathAbs(entry - riskSide); // // Collecting Affected Zones ... XBoxZone tmps[]; XBoxZone zones[]; XBoxZone actedZones[]; XBoxZone insideZones[]; XBoxZone breakedZones[]; XBoxZone affectedZones[]; // // Support and Resistances ... poiDetector.CollectZones(bar, tmps); Copy(tmps, zones, false); // // OBS ... poiDetector.CollectOBs(bar, tmps); Copy(tmps, zones, false); // // FVGs ... poiDetector.CollectFVGs(bar, tmps); Copy(tmps, zones, false); // ExtractAffectedZones(bar, zones, affectedZones); // // Acteds Zones ... ExtractActeds(bar, actedZones, affectedZones); // // Inside Zones ... ExtractInsides(bar, insideZones, affectedZones); // // Breaked Zones ... ExtractBreakeds(bar, breakedZones, affectedZones); // // Cleanup ... XClean(tmps); XClean(zones); XClean(actedZones); XClean(insideZones); XClean(breakedZones); XClean(affectedZones); } // result = zone.IsValid(); } // // Prepare Targets ... if (result) { } // // Cleanup ... if (!result) { // zone.Clean(); XClean(targets); dir = X_DIRECTION_NONE; } pBar.Clean(); p2Bar.Clean(); // 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 ... * * @return ( bool ) */ bool Strategy3HasSignal( XOHCL &bar, XBoxZone &zone, XTarget &targets[], ENUM_X_DIRECTION &dir // ) { // bool result = false; // // Prepare ... zone.Clean(); XClean(targets); dir = X_DIRECTION_NONE; // // Validate ... result = bar.IsValid(); if (!result) { return result; } // // Define Requirements ... // XOHCL pBar; XOHCL p2Bar; bool isBullish = false; bool isBearish = false; // // Read PBar ... result = bar.GetPreviousBar(pBar); result = result && pBar.GetPreviousBar(p2Bar); if (!result) { // pBar.Clean(); p2Bar.Clean(); // return result; } // // Do ... // XFIMA Consolidation ... // bool isConsolidation = poiDetector.DetectPVConsolidationZone( zone, pBar.Index(), true, // Force PV Break ... true // Force Has Sar Switch ... ); // isBullish = isConsolidation && zone.IsBullish(); // isBearish = isConsolidation && zone.IsBearish(); // // Validate based on Bars Patterns ... bool validateByBarPatterns = true; if (validateByBarPatterns) { // // Reading pBar Patterns ... XPatternAnalysis pBarAnalysis; poiDetector.AnalyseBarPatterns( pBar, pBarAnalysis, structureConfig.barsAnalysisConfig // ); // // Bullish ... bool isPBarHasBullishPatterns = (bar.close > pBar.low || bar.open > pBar.low) && ( // pBarAnalysis.IsPinned(X_DIRECTION_BULLISH) || pBarAnalysis.IsEngulfed(X_DIRECTION_BULLISH) || pBarAnalysis.IsMomentum(X_DIRECTION_BULLISH) || pBarAnalysis.IsPiercing(X_DIRECTION_BULLISH) || pBarAnalysis.IsSignalKey(X_DIRECTION_BULLISH) // ); // // Bearish ... bool isPBarHasBearishPatterns = (bar.close < pBar.high || bar.open < pBar.high) && ( // pBarAnalysis.IsPinned(X_DIRECTION_BEARISH) || pBarAnalysis.IsEngulfed(X_DIRECTION_BEARISH) || pBarAnalysis.IsMomentum(X_DIRECTION_BEARISH) || pBarAnalysis.IsPiercing(X_DIRECTION_BEARISH) || pBarAnalysis.IsSignalKey(X_DIRECTION_BEARISH) // ); // isBullish = isBullish && isPBarHasBullishPatterns && !isPBarHasBearishPatterns; // isBearish = isBearish && isPBarHasBearishPatterns && !isPBarHasBullishPatterns; // // Summarize Result ... result = isBullish || isBearish; } // // Checking PullBack ... bool validateByPullback = false; if (validateByPullback) { // XBoxZone pullback; ENUM_X_DIRECTION pullbackDir; bool isPullBack = result && poiDetector.IsPullbackPattern( pBar, pullback, pullbackDir, 2, false // Force Break ... ); bool isPullbackBullish = isPullBack && IsXBullish(pullbackDir); bool isPullbackBearish = isPullBack && IsXBearish(pullbackDir); // isBullish = isBullish && isPullbackBullish; // isBearish = isBearish && isPullbackBearish; // // Summarize Result ... result = isBullish || isBearish; } // // Validate ... result = isBullish || isBearish; // // Prepare Zone ... if (result) { } // // Prepare Targets ... if (result) { } // // Cleanup ... if (!result) { // zone.Clean(); XClean(targets); dir = X_DIRECTION_NONE; } pBar.Clean(); p2Bar.Clean(); // return result; } /** * Check Bar Has Signal Based on Strategy 4 ... * * Strategy 4: * =========== * - Works Based on Order Flow ... * - Looking for new and Fresh Order Flow ... * - Validate Bar is Inside Order Flow ... * - Validate Bar has Proper Pattern ... * - Validate Bar Based on ATR Band in two Step: * - Step 1: Bars is Inside ATR Band (Middle) ... * - Step 2: Trigger Bars Close Price based on ATR Band ... * - Validate Order Flow based on Market Structure Zone ... * - Validate Trigger Bar based on InDirectional Market Structure Zones ... * * Manipulations: * ================ * there are Some Flags properties to Change Validations in Strategy ... * we can use them for Testing Purposes ... * * @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 ... * * @return ( bool ) */ bool Strategy4HasSignal( XOHCL &bar, XBoxZone &zone, XTarget &targets[], ENUM_X_DIRECTION &dir // ) { // bool result = false; // // Prepare ... zone.Clean(); XClean(targets); dir = X_DIRECTION_NONE; // // Validate ... result = bar.IsValid(); if (!result) { return result; } // // Validation Flags ... bool validateBarInsideZone = true; bool validateByBarPatterns = true; bool validateByBarInsideATRBand = true; bool validateByBarBasedOnATRBand = true; bool validateMarketStructureHasDirectionalZone = true; bool validateMarketStructureDirectionalZoneInsideOrderFlow = true; bool validateMarketStructureHasNotInDirectionalZoneOrUnReachedTP = true; // // Define Requirements ... // XOHCL pBar; XOHCL p2Bar; XOHCL p3Bar; bool isBullish = false; bool isBearish = false; // // Read PBar ... result = bar.GetPreviousBar(pBar); result = result && pBar.GetPreviousBar(p2Bar); result = result && p2Bar.GetPreviousBar(p3Bar); if (!result) { // pBar.Clean(); p2Bar.Clean(); p3Bar.Clean(); // return result; } // // Do ... // // Retrieve pBar Patterns ... XPatternAnalysis pBarPatterns; XPatternAnalysisConfig patternConfig = structureConfig.barsAnalysisConfig; // poiDetector.AnalyseBarPatterns( pBar, pBarPatterns, patternConfig // ); // // Detecting OrderFlow ... XBoxZone oFlow[]; bool hasOrderFlow = poiDetector.HasOrderFlow( p3Bar, dir, oFlow, structureConfig.orderFlowValidation, structureConfig.orderFlowUseOB, structureConfig.orderFlowUseFVG, structureConfig.orderFlowUseSupportAndResistance, patternConfig.supportAndResistanceLoopbackLength, patternConfig.supportAndResistanceValidationLength, structureConfig.loopback // ); // double atrBandUpper = EMPTY_VALUE; double atrBandLower = EMPTY_VALUE; double atrBandMiddle = EMPTY_VALUE; // isBullish = hasOrderFlow && IsXBullish(dir); // isBearish = hasOrderFlow && IsXBearish(dir); // // Summarize Result ... result = isBullish || isBearish; // // Force Price of p2Bar is Inside Order Flow ... if (result && validateBarInsideZone) { // double orderFlowUpper = 0; double orderFlowLower = 0; // int idx = -1; idx = GetHighest(oFlow); if (IsValidIndex(idx)) { orderFlowUpper = oFlow[idx].upper; } idx = GetLowest(oFlow); if (IsValidIndex(idx)) { orderFlowLower = oFlow[idx].lower; } // result = NotEmptyZero(orderFlowUpper) && NotEmptyZero(orderFlowLower) && orderFlowUpper > orderFlowLower && (isBullish ? p2Bar.low < orderFlowUpper : p2Bar.high > orderFlowLower); // // Reset Flags ... if (!result) { // isBullish = false; isBearish = false; } } // // Force PBar Has Pattern ... if (result && validateByBarPatterns) { // // Analyse Bar Patterns ... result = pBarPatterns.IsValid(); // // Bullish ... bool isPBarHasBullishPatterns = result && // (bar.close > pBar.low || // bar.open > pBar.low) && ( // pBarPatterns.IsPinned(X_DIRECTION_BULLISH) || pBarPatterns.IsEngulfed(X_DIRECTION_BULLISH) || pBarPatterns.IsMomentum(X_DIRECTION_BULLISH) || pBarPatterns.IsPiercing(X_DIRECTION_BULLISH) || pBarPatterns.IsSignalKey(X_DIRECTION_BULLISH) // ); // // Bearish ... bool isPBarHasBearishPatterns = result && // (bar.close < pBar.high || // bar.open < pBar.high) && ( // pBarPatterns.IsPinned(X_DIRECTION_BEARISH) || pBarPatterns.IsEngulfed(X_DIRECTION_BEARISH) || pBarPatterns.IsMomentum(X_DIRECTION_BEARISH) || pBarPatterns.IsPiercing(X_DIRECTION_BEARISH) || pBarPatterns.IsSignalKey(X_DIRECTION_BEARISH) // ); // isBullish = isBullish && isPBarHasBullishPatterns && !isPBarHasBearishPatterns; // isBearish = isBearish && isPBarHasBearishPatterns && !isPBarHasBullishPatterns; // // Summarize Result ... result = isBullish || isBearish; // // Reset Flags ... if (!result) { // isBullish = false; isBearish = false; } } // // Force P2Bar Place Checking based on ATR Band ... if (result && validateByBarInsideATRBand) { // atrBandUpper = fimaHelper.GetATRBandUpper(p2Bar.Index()); atrBandLower = fimaHelper.GetATRBandLower(p2Bar.Index()); // atrBandMiddle = atrBandLower + ((atrBandUpper - atrBandLower) / 2); // isBullish = isBullish && NotEmptyZero(atrBandMiddle) && p2Bar.low < atrBandMiddle; // isBearish = isBearish && NotEmptyZero(atrBandMiddle) && p2Bar.high > atrBandMiddle; // // Summarize Result ... result = isBullish || isBearish; // // Reset Flags ... if (!result) { // isBullish = false; isBearish = false; } } // // Force PBar Place Checking based on ATR Band ... if (result && validateByBarBasedOnATRBand) { // atrBandUpper = fimaHelper.GetATRBandUpper(pBar.Index()); atrBandLower = fimaHelper.GetATRBandLower(pBar.Index()); // result = NotEmptyZero(atrBandUpper) && NotEmptyZero(atrBandLower) && (isBullish ? pBar.close > atrBandLower : pBar.close < atrBandUpper); // // Reset Flags ... if (!result) { // isBullish = false; isBearish = false; } } // // for Bullish has Support ... // for Bearish has Resistance ... if (result && validateMarketStructureHasDirectionalZone) { // XOHCL tmpBar; XPivot tmpPivot; XBoxZone support; XBoxZone resistance; // // Check Market Strucutre Has Support / Resistance ... bool hasSupport = pBarPatterns.IsSupport(); bool hasResistance = pBarPatterns.IsResistance(); // // Retrieve Support / Resistance Zone ... if (hasSupport) { pBarPatterns.GetSupport(tmpBar, tmpPivot, support); } if (hasResistance) { pBarPatterns.GetResistance(tmpBar, tmpPivot, resistance); } // // Validate Support and Resistance by Order Flow ... // // Converts Order Flow to Zone ... XBoxZone ofZone; bool hasOFBox = ToBox(ofZone, oFlow); // // Check Market Strucutre Support and Resistance Validation ... if (validateMarketStructureDirectionalZoneInsideOrderFlow) { // hasSupport = hasOFBox && hasSupport && ofZone.lower < support.lower && ofZone.upper > support.upper; // hasResistance = hasOFBox && hasResistance && ofZone.lower < resistance.lower && ofZone.upper > resistance.upper; } // // Validate Directional Support or Resistance Exists ... // isBullish = isBullish && hasSupport; // isBearish = isBearish && hasResistance; // // Cleanup ... ofZone.Clean(); tmpBar.Clean(); support.Clean(); tmpPivot.Clean(); resistance.Clean(); // // Summarize Result ... result = isBullish || isBearish; } // // Validate Makret Structure Has Not Indirectional Zone ... if (result && validateMarketStructureHasNotInDirectionalZoneOrUnReachedTP) { // XOHCL tmpBar; XPivot tmpPivot; XBoxZone support; XBoxZone resistance; // // Check Market Strucutre Has Support / Resistance ... bool hasSupport = pBarPatterns.IsSupport(); bool hasResistance = pBarPatterns.IsResistance(); // // Retrieve Support / Resistance Zone ... if (hasSupport) { pBarPatterns.GetSupport(tmpBar, tmpPivot, support); } if (hasResistance) { pBarPatterns.GetResistance(tmpBar, tmpPivot, resistance); } // // Converts Order Flow to Zone ... XBoxZone ofZone; bool hasOFBox = ToBox(ofZone, oFlow); // bool hasIndirectionalZone = (isBullish && hasResistance) || (isBearish && hasSupport); if (hasIndirectionalZone) { // // Here we Have to Validate Zone Place ... // double point = GetPoints(bar.symbol); double entry = GetEntry(bar.symbol, dir); double slAddition = slAdditionDistance > 0 ? slAdditionDistance : 0; double risk = MathAbs(entry - (isBullish ? oFlow[0].lower : oFlow[0].upper)) + (slAddition * point); double reward = (defaultSignalR2R * risk); double tp = isBullish ? entry + reward : entry - reward; // // Bullish ... if (isBullish && hasResistance) { hasResistance = resistance.lower <= tp; } // // Bearish ... if (isBearish && hasSupport) { hasSupport = support.upper >= tp; } } // isBullish = isBullish && !hasResistance; // isBearish = isBearish && !hasSupport; // // Cleanup ... ofZone.Clean(); tmpBar.Clean(); support.Clean(); tmpPivot.Clean(); resistance.Clean(); // // Summarize Result ... result = isBullish || isBearish; } // // Validate ... result = isBullish || isBearish; if (result) { // dir = isBullish ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; // result = HasDirection(dir); } // // Prepare Zone ... if (result) { // zone.Clean(); result = ToBox( p2Bar, zone, dir, X_BAR_PATTERN_PINNED // ); // // Refine Zone ... zone.to = bar.time; zone.upper = MathMax(zone.upper, atrBandMiddle); zone.lower = MathMin(zone.lower, atrBandMiddle); // // Manage Stops ... if (result) { // // Since Stop Management Changes Zones Edge(s) ... // we do it here for Refining Zone ... // poiDrawer.DrawZone(zone, structureDrawConfig.drawConfig); poiDrawer.DrawPatternAnalysis(pBarPatterns, structureDrawConfig.barAnalysisDrawConfig); // DebugBreak(); } // result = zone.IsValid(); } // // Prepare Targets ... if (result) { // XTarget iTarget; // // Calculate Requirements ... double point = GetPoints(bar.symbol); double entry = GetEntry(bar.symbol, dir); double slAddition = slAdditionDistance > 0 ? slAdditionDistance : 0; double risk = MathAbs(entry - (isBullish ? zone.lower : zone.upper)) + (slAddition * point); double reward = (defaultSignalR2R * risk); double tp = isBullish ? entry + reward : entry - reward; // // High Risk Target is Used to Protect In Profit Positiions // from Reversal Patterns ... double highRiskR2r = (defaultSignalR2R / 5) * 4; double highRiskReward = highRiskR2r * risk; double highRiskTP = isBullish ? entry + highRiskReward : entry - highRiskReward; iTarget.Clean(); iTarget.actingDistance = 5; iTarget.doRFOnEntry = true; iTarget.target = highRiskTP; iTarget.volumeMultiplier = 0.8; AddRef(iTarget, targets); // // Cleanup ... iTarget.Clean(); } // // Cleanup ... if (!result) { // zone.Clean(); XClean(targets); dir = X_DIRECTION_NONE; } pBar.Clean(); p2Bar.Clean(); p3Bar.Clean(); XClean(orderFlow); pBarPatterns.Clean(); // return result; } // }; //