diff --git a/Documents/BKP/XFIMA Signals/x-saherelm.xfima.signaller.class copy 2.mq5 b/Documents/BKP/XFIMA Signals/x-saherelm.xfima.signaller.class copy 2.mq5 new file mode 100644 index 00000000..40fdf46d --- /dev/null +++ b/Documents/BKP/XFIMA Signals/x-saherelm.xfima.signaller.class copy 2.mq5 @@ -0,0 +1,3727 @@ +/////////////////////////////////////////////////////// +// +// 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 = false; + drawZones = false; + drawIZones = false; + drawTrends = false; + drawSCTrend = false; + drawMCTrend = false; + drawLCTrend = false; + drawHCTrend = false; + drawSupport = false; + drawISupport = false; + drawOrderFlow = false; + drawResistance = false; + drawIResistance = false; + + // + manageLegs = true; + manageZones = true; + manageIZones = true; + manageTrends = false; + manageOrderFlow = 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); + return result; + + // + int positionsCount = ArraySize(positions); + if (!IsValidSize(positionsCount)) + { + return result; + } + + // + // Requirements ... + XGuard iGuard; + bool has = false; + int samePeaks = 0; + int sameVales = 0; + double iValue = 0; + double points10 = 0; + double points50 = 0; + double points100 = 0; + int samePVValidation = 5; + bool isPeakOverLast = false; + bool isValeUnderLast = false; + + // + for (int i = 0; i < positionsCount; i++) + { + // + points10 = 10 * positions[i].GetPointsValue(); + points50 = 50 * positions[i].GetPointsValue(); + points100 = 100 * positions[i].GetPointsValue(); + + // + // Near to TP Guard ... + has = positions[i].profit > 0; + if (has) + { + // + // Has Same Peaks or Vales ... + samePeaks = fimaParser.CountSamePeaks(barIndex); + sameVales = fimaParser.CountSameVales(barIndex); + isPeakOverLast = (fimaParser.IsPeakOverLast(barIndex) || + fimaParser.IsPeakOverLast(barIndex + 1)); + isValeUnderLast = (fimaParser.IsValeUnderLast(barIndex) || + fimaParser.IsValeUnderLast(barIndex + 1)); + has = (positions[i].IsBullish() + ? ( + isPeakOverLast && + sameVales >= samePVValidation && + fimaHelper.GetVale(barIndex) > positions[i].sl) + : positions[i].IsBearish() + ? ( + isValeUnderLast && + samePeaks >= samePVValidation && + fimaHelper.GetPeak(barIndex) < positions[i].sl) + : false); + if (has) + { + // + iGuard.Clean(); + iGuard.time = TimeCurrent(); + iGuard.symbol = positions[i].symbol; + iGuard.period = positions[i].period; + iGuard.ticket = positions[i].ticket; + iGuard.provider = positions[i].provider; + iGuard.sl = positions[i].IsBullish() + ? fimaHelper.GetVale(barIndex) - points10 + : fimaHelper.GetPeak(barIndex) + points10; + iGuard.action = X_GUARD_ACTION_TRAIL_STOP; + + // + has = iGuard.IsValid(); + if (has) + { + AddRef(iGuard, guards); + + // + // Remove TP if in Profit SL ... + iValue = (positions[i].IsBullish() ? positions[i].entry + points10 : positions[i].entry - points10); + has = + (positions[i].IsBullish() && HasResistance()) + ? (iGuard.sl >= iValue && + positions[i].tp < resistance.lower) + : (positions[i].IsBearish() && HasSupport()) + ? (iGuard.sl <= iValue && + positions[i].tp > support.upper) + : false; + if (has) + { + // + iGuard.Clean(); + iGuard.force = false; + iGuard.tp = positions[i].IsBullish() + ? resistance.lower + : support.upper; + iGuard.time = TimeCurrent(); + iGuard.symbol = positions[i].symbol; + iGuard.period = positions[i].period; + iGuard.ticket = positions[i].ticket; + iGuard.provider = positions[i].provider; + iGuard.action = X_GUARD_ACTION_TRAIL_TARGET; + + // + 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); + ManageTrends(bar); + ManageZones(p2Bar); + ManageIZones(p2Bar); + ManageOrderFlow(p3Bar); + + // + // Cleanup ... + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + } + + // + // Private ... + private: + // + // Props ... + + // + // Leg ... + + XLeg leg; // Exists Leg ... + bool drawLeg; // Draw Leg ... + bool manageLegs; + + // + 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[]; + bool manageOrderFlow; + 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(); + } + } + + // + // Zone ... + + // + XBoxZone support; + XBoxZone resistance; + bool drawZones; + bool drawSupport; + bool manageZones; + bool drawResistance; + + // + bool HasZones() + { + return HasSupport() || + HasResistance(); + } + + // + bool HasSupport() + { + return support.IsValid(); + } + + // + bool HasResistance() + { + return resistance.IsValid(); + } + + // + bool ValidateZones(XOHCL &bar) + { + // + bool result = false; + + // + // Validate ... + result = bar.IsValid() && + HasZones(); + if (!result) + { + return result; + } + + // + // Support ... + bool hasSupport = HasSupport(); + if (hasSupport) + { + // + result = bar.close > support.lower && + !IsBreaked(support, X_PRICE_CLOSE); + if (!result) + { + // + iResistance = support; + iResistance.breakAt = NULL; + iResistance.dir = X_DIRECTION_BEARISH; + iResistance.to = bar.time + (PeriodSeconds(bar.period)); + iResistance.from = bar.time - (PeriodSeconds(bar.period)); + + // + support.breakAt = bar.time; + support.Clean(); + } + } + + // + // Resistance ... + bool hasResistance = HasResistance(); + if (hasResistance) + { + // + result = bar.close < resistance.upper && + !IsBreaked(resistance, X_PRICE_CLOSE); + if (!result) + { + // + iSupport = resistance; + iSupport.breakAt = NULL; + iSupport.dir = X_DIRECTION_BULLISH; + iSupport.to = bar.time + (PeriodSeconds(bar.period)); + iSupport.from = bar.time - (PeriodSeconds(bar.period)); + + // + resistance.breakAt = bar.time; + resistance.Clean(); + } + } + + // + result = + (hasSupport && !HasSupport()) || + (hasResistance && !HasResistance()); + + // + return result; + } + + // + void DrawZones() + { + // + if (!drawZones || !HasZones()) + { + return; + } + + // + if (drawSupport && HasSupport()) + { + poiDrawer.DrawZone(support, structureDrawConfig.drawConfig); + } + + // + if (drawResistance && HasResistance()) + { + poiDrawer.DrawZone(resistance, structureDrawConfig.drawConfig); + } + } + + // + void ManageZones(XOHCL &bar) + { + // + // Validate Exists ... + if (HasZones()) + { + // + if (!ValidateZones(bar)) + { + // + // Invalidate Zones ... + + // + // Support ... + if (IsXValid(support.breakAt)) + { + // + iResistance = support; + iResistance.breakAt = NULL; + iResistance.dir = X_DIRECTION_BEARISH; + iResistance.to = bar.time + (PeriodSeconds(bar.period)); + iResistance.from = bar.time - (PeriodSeconds(bar.period)); + + // + support.Clean(); + } + + // + // Resistance ... + if (IsXValid(resistance.breakAt)) + { + // + iSupport = resistance; + iSupport.breakAt = NULL; + iSupport.dir = X_DIRECTION_BULLISH; + iSupport.to = bar.time + (PeriodSeconds(bar.period)); + iSupport.from = bar.time - (PeriodSeconds(bar.period)); + + // + resistance.Clean(); + } + } + } + + // + // Detect New ... + XOHCL tmpBar; + bool has = false; + + // + // Detect Support ... + if (!HasSupport()) + { + // + has = poiDetector.HasSupport( + bar, + tmpBar, + structureConfig.barsAnalysisConfig.supportAndResistanceValidationLength, + structureConfig.barsAnalysisConfig.supportAndResistanceLoopbackLength // + ); + if (has) + { + // + has = ToSupportBox(tmpBar, support, bar.time); + has = + has && + !IsBreaked(support, X_PRICE_CLOSE); + if (!has) + { + // + if (support.IsValid()) + { + // + iResistance = support; + iResistance.breakAt = NULL; + iResistance.dir = X_DIRECTION_BEARISH; + iResistance.to = bar.time + (PeriodSeconds(bar.period)); + iResistance.from = bar.time - (PeriodSeconds(bar.period)); + } + + // + support.Clean(); + } + } + } + + // + // Detect Resistance ... + if (!HasResistance()) + { + // + has = poiDetector.HasResistance( + bar, + tmpBar, + structureConfig.barsAnalysisConfig.supportAndResistanceValidationLength, + structureConfig.barsAnalysisConfig.supportAndResistanceLoopbackLength // + ); + if (has) + { + // + has = ToResistanceBox(tmpBar, resistance, bar.time); + has = + has && + !IsBreaked(resistance, X_PRICE_CLOSE); + if (!has) + { + // + if (resistance.IsValid()) + { + // + iSupport = resistance; + iSupport.breakAt = NULL; + iSupport.dir = X_DIRECTION_BULLISH; + iSupport.to = bar.time + (PeriodSeconds(bar.period)); + iSupport.from = bar.time - (PeriodSeconds(bar.period)); + } + + // + resistance.Clean(); + } + } + } + + // + // Update Exists ... + if (HasZones()) + { + // + if (HasSupport()) + { + // + support.to = bar.time; + support.type = "XFIMASup"; + } + + // + if (HasResistance()) + { + // + resistance.to = bar.time; + resistance.type = "XFIMARes"; + } + + // + DrawZones(); + } + + // + // Cleanup ... + tmpBar.Clean(); + } + + // + XBoxZone iSupport; + XBoxZone iResistance; + bool drawIZones; + bool drawISupport; + bool manageIZones; + bool drawIResistance; + + // + bool HasIZones() + { + // + return HasISupport() || + HasIResistance(); + } + + // + bool HasISupport() + { + return iSupport.IsValid(); + } + + // + bool HasIResistance() + { + return iResistance.IsValid(); + } + + // + void DrawIZones() + { + // + if (!drawIZones || !HasIZones()) + { + return; + } + + // + if (drawISupport && HasISupport()) + { + poiDrawer.DrawZone(iSupport, structureDrawConfig.drawConfig); + } + + // + if (drawIResistance && HasIResistance()) + { + poiDrawer.DrawZone(iResistance, structureDrawConfig.drawConfig); + } + } + + // + bool ValidateIZones(XOHCL &bar) + { + // + bool result = false; + + // + // Validate ... + result = bar.IsValid() && + HasIZones(); + if (!result) + { + return result; + } + + // + + // + // Support ... + bool hasSupport = HasISupport(); + if (hasSupport) + { + // + result = bar.close > iSupport.lower && + !IsBreaked(iSupport, X_PRICE_CLOSE); + if (!result) + { + // + iSupport.breakAt = bar.time; + iSupport.Clean(); + } + } + + // + // Resistance ... + bool hasResistance = HasIResistance(); + if (hasResistance) + { + // + result = bar.close < iResistance.upper && + !IsBreaked(iResistance, X_PRICE_CLOSE); + if (!result) + { + // + iResistance.breakAt = bar.time; + iResistance.Clean(); + } + } + + // + result = + (hasSupport && !HasISupport()) || + (hasResistance && !HasIResistance()); + + // + return result; + } + + // + void ManageIZones(XOHCL &bar) + { + // + // Validate Exists ... + if (HasIZones()) + { + // + if (!ValidateIZones(bar)) + { + // + // Invalidate Zones ... + + // + // Support ... + if (IsXValid(iSupport.breakAt)) + { + iSupport.Clean(); + } + + // + // Resistance ... + if (IsXValid(iResistance.breakAt)) + { + iResistance.Clean(); + } + } + } + + // + // Update Exists ... + if (HasIZones()) + { + // + if (HasISupport()) + { + // + iSupport.to = bar.time; + iSupport.type = "XFIMAISup"; + } + + // + if (HasIResistance()) + { + // + iResistance.to = bar.time; + iResistance.type = "XFIMAIRes"; + } + + // + DrawIZones(); + } + } + + // + // Trends ... + + // + XTrend scTrend; + XTrend mcTrend; + XTrend lcTrend; + XTrend hcTrend; + + // + bool drawTrends; + bool drawSCTrend; + bool drawMCTrend; + bool drawLCTrend; + bool drawHCTrend; + bool manageTrends; + + // + bool HasTrend() + { + // + bool result = + HasSCTrend() || + HasMCTrend() || + HasLCTrend() || + HasHCTrend(); + + // + return result; + } + + // + bool HasSCTrend() + { + return scTrend.IsValid() && + scTrend.HasTrend(); + } + + // + bool HasMCTrend() + { + return mcTrend.IsValid() && + mcTrend.HasTrend(); + } + + // + bool HasLCTrend() + { + return lcTrend.IsValid() && + lcTrend.HasTrend(); + } + + // + bool HasHCTrend() + { + return hcTrend.IsValid() && + hcTrend.HasTrend(); + } + + // + void DrawTrends() + { + // + if (!drawTrends || !HasTrend()) + { + return; + } + + // + // SC ... + if (drawSCTrend && HasSCTrend()) + { + poiDrawer.DrawTrendLine(scTrend, structureDrawConfig.drawConfig); + } + + // + // MC ... + if (drawMCTrend && HasMCTrend()) + { + poiDrawer.DrawTrendLine(mcTrend, structureDrawConfig.drawConfig); + } + + // + // LC ... + if (drawLCTrend && HasLCTrend()) + { + poiDrawer.DrawTrendLine(lcTrend, structureDrawConfig.drawConfig); + } + + // + // HC ... + if (drawHCTrend && HasHCTrend()) + { + poiDrawer.DrawTrendLine(hcTrend, structureDrawConfig.drawConfig); + } + } + + // + void ManageTrends(XOHCL &bar) + { + // + // Validate ... + bool has = bar.IsValid(); + if (!has) + { + return; + } + + // + XTrend tmpTrend; + + // + // SC ... + tmpTrend.Clean(); + has = fimaParser.HasSCTrend(tmpTrend, bar.Index()); + if (has) + { + scTrend = tmpTrend; + } + + // + // MC ... + tmpTrend.Clean(); + has = fimaParser.HasMCTrend(tmpTrend, bar.Index()); + if (has) + { + mcTrend = tmpTrend; + } + + // + // LC ... + tmpTrend.Clean(); + has = fimaParser.HasLCTrend(tmpTrend, bar.Index()); + if (has) + { + lcTrend = tmpTrend; + } + + // + // HC ... + tmpTrend.Clean(); + has = fimaParser.HasHCTrend(tmpTrend, bar.Index()); + if (has) + { + hcTrend = tmpTrend; + } + + // + DrawTrends(); + + // + // Cleanup ... + tmpTrend.Clean(); + } + + // + // 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 = true; + bool useSignaller2 = false; + bool useSignaller3 = false; + bool useSignaller4 = false; + + // + XBoxZone tmpZone; + string provider = NULL; + ENUM_X_DIRECTION tmpDir; + + // + bool signaller1HasSignal = false; + bool signaller2HasSignal = false; + bool signaller3HasSignal = false; + bool signaller4HasSignal = false; + + // + // Validator Flags ... + bool validateByOrderFlow = false; + + // + // Target Flags ... + bool hasPartialCloseOnTp1 = false; + + // + bool doRFOnEntryOnTP1 = false; + + // + // Draw Flags ... + bool draw = true; + bool drawZone = true; + bool drawMarketStructurePivots = false; + bool drawMarketStructureAnalysis = false; + bool drawMarketStructureOrderFlow = false; + XPOIDrawConfig iDrawConfig; + + // + drawLeg = false; + drawZones = false; + drawIZones = false; + drawTrends = false; + drawSCTrend = false; + drawMCTrend = false; + drawLCTrend = false; + drawHCTrend = false; + drawSupport = false; + drawISupport = false; + drawOrderFlow = false; + drawResistance = false; + drawIResistance = false; + + // + // Signal Checking ... + + // + // Analyse Market Strucutre ... + XFIMAMarketStructure marketStructure; + + // + // Signal Detection Flags ... + + // + // Signaller 1 ... + if (useSignaller1) + { + // + signaller1HasSignal = Strategy1HasSignal( + bar, + tmpZone, + targets, + tmpDir // + ); + + // + if (signaller1HasSignal) + { + // + provider += "1"; + + // + if (!zone.IsValid()) + { + // + dir = tmpDir; + zone = tmpZone; + } + } + + // + tmpZone.Clean(); + tmpDir = X_DIRECTION_NONE; + } + + // + // Signaller 2 ... + if (useSignaller2) + { + // + signaller2HasSignal = Strategy2HasSignal( + bar, + tmpZone, + targets, + tmpDir // + ); + + // + if (signaller2HasSignal) + { + // + provider += "2"; + + // + if (!zone.IsValid()) + { + // + dir = tmpDir; + zone = tmpZone; + } + } + + // + tmpZone.Clean(); + tmpDir = X_DIRECTION_NONE; + } + + // + // Signaller 3 ... + if (useSignaller3) + { + // + signaller3HasSignal = Strategy3HasSignal( + bar, + tmpZone, + targets, + tmpDir // + ); + + // + if (signaller3HasSignal) + { + // + provider += "3"; + + // + if (!zone.IsValid()) + { + // + dir = tmpDir; + zone = tmpZone; + } + } + + // + tmpZone.Clean(); + tmpDir = X_DIRECTION_NONE; + } + + // + // Signaller 4 ... + if (useSignaller4) + { + // + signaller4HasSignal = Strategy4HasSignal( + bar, + tmpZone, + targets, + tmpDir // + ); + + // + if (signaller4HasSignal) + { + // + provider += "4"; + + // + if (!zone.IsValid()) + { + // + dir = tmpDir; + zone = tmpZone; + } + } + + // + tmpZone.Clean(); + tmpDir = X_DIRECTION_NONE; + } + + // + // Summarize Signallers Result ... + result = signaller1HasSignal || + signaller2HasSignal || + signaller3HasSignal || + signaller4HasSignal; + + // + // 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 ... + Print("Signaller Providers: ", provider); + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + + // + // Cleanup ... + tmpZone.Clean(); + iDrawConfig.Clean(); + marketStructure.Clean(); + + // + return result; + } + + // + // Custom Signal Strategies ... + + /** + * 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; + 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 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 ... + XOHCL _tmpBar; + XPivot _tmpPivot; + XBoxZone _support; + XBoxZone _resistance; + XPatternAnalysis pBarPatterns; + poiDetector.AnalyseBarPatterns( + pBar, + pBarPatterns, + structureConfig.barsAnalysisConfig // + ); + bool hasSupport = pBarPatterns.IsSupport(); + bool hasResistance = pBarPatterns.IsResistance(); + if (hasSupport) + { + hasSupport = pBarPatterns.GetSupport(_tmpBar, _tmpPivot, _support); + } + if (hasResistance) + { + hasResistance = pBarPatterns.GetResistance(_tmpBar, _tmpPivot, _resistance); + } + + // + // Check Bar Patterns ... + bool isPBarHasBullishPatterns = + (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) + // + ); + bool isPBarHasBearishPatterns = + (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) + // + ); + + // + // 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 // + ); + + // + // Detecting Boundary Trend ... + XTrend boundaryTrend; + double boundaryMin = fimaParser.GetBoundaryMin(pBar.Index()); + double boundaryMax = fimaParser.GetBoundaryMax(pBar.Index()); + bool hasBoundaryTrend = fimaParser.HasBoundaryTrend(boundaryTrend, pBar.Index()); + bool hasBoundaryBullishTrend = hasBoundaryTrend && boundaryTrend.IsBullish(); + bool hasBoundaryBearishTrend = hasBoundaryTrend && boundaryTrend.IsBearish(); + + // + // 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(); + + // + // Zone Validations ... + if (result) + { + // + if (boundaryTrend.IsValid()) + { + poiDrawer.DrawTrendLine(boundaryTrend, structureDrawConfig.drawConfig); + } + + // + poiDrawer.DrawZone(zone, structureDrawConfig.drawConfig); + poiDrawer.DrawPatternAnalysis(pBarPatterns, structureDrawConfig.barAnalysisDrawConfig); + + // + if (hasSupport) + { + poiDrawer.DrawZone(_support, structureDrawConfig.drawConfig); + } + + // + if (hasResistance) + { + poiDrawer.DrawZone(_resistance, structureDrawConfig.drawConfig); + } + + // + if (HasChild(affectedZones)) + { + poiDrawer.DrawZones(affectedZones, structureDrawConfig.drawConfig); + } + + // + if (NotEmptyZero(boundaryMin)) + { + // + XTrend trend; + trend.Init( + pBar.symbol, + pBar.period, + bar.time, + boundaryMin, + pBar.BeforeOn(), + boundaryMin, + pBar.NextAt() // + ); + if (trend.IsValid()) + { + // + XPOIDrawConfig iConfig = structureDrawConfig.drawConfig; + iConfig.trendRayLeft = false; + iConfig.trendRayRight = false; + + // + poiDrawer.DrawTrendLine(trend, iConfig); + + // + iConfig.Clean(); + } + + // + trend.Clean(); + } + + // + if (NotEmptyZero(boundaryMax)) + { + // + XTrend trend; + trend.Init( + pBar.symbol, + pBar.period, + bar.time, + boundaryMax, + pBar.BeforeOn(), + boundaryMax, + pBar.NextAt() // + ); + if (trend.IsValid()) + { + // + XPOIDrawConfig iConfig = structureDrawConfig.drawConfig; + iConfig.trendRayLeft = false; + iConfig.trendRayRight = false; + + // + poiDrawer.DrawTrendLine(trend, iConfig); + + // + iConfig.Clean(); + } + + // + trend.Clean(); + } + + // + DebugBreak(); + } + + // + result = zone.IsValid(); + + // + // Reset Flags ... + if (!result) + { + // + zone.Clean(); + isBullish = false; + isBearish = false; + } + } + + // + // Prepare Targets ... + if (result) + { + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + pBar.Clean(); + p2Bar.Clean(); + XClean(zones); + _tmpBar.Clean(); + _support.Clean(); + _tmpPivot.Clean(); + _resistance.Clean(); + pBarPatterns.Clean(); + boundaryTrend.Clean(); + XClean(affectedZones); + XClean(affectedZonesBullish); + XClean(affectedZonesBearish); + + // + return result; + } + + /** + * Check Bar Has Signal Based on Strategy 2 ... + * + * Strategy 2: + * =========== + * - Works Based On PBar Patterns Focused on PinBar ... + * - Looking for a Bar Directional Pattern Happens ... + * - Validate Fast Ma Over/Under Slow ... + * - Validate P2Peak/Vale doesnt Under or Over Last (InDirectional) ... + * - Validate P2Bar Has Directional Market Strucuture Zone (OB, FVG, Support/Resistance) ... + * + * 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 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; + 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; + } + + // + // Reading pBar Patterns ... + XPatternAnalysis pBarPatterns; + poiDetector.AnalyseBarPatterns( + pBar, + pBarPatterns, + structureConfig.barsAnalysisConfig // + ); + bool hasSupport = pBarPatterns.IsSupport(); + bool hasResistance = pBarPatterns.IsResistance(); + + // + // Check Boundary Trend ... + XTrend boundaryTrend; + bool hasBoundaryTrend = fimaParser.HasBoundaryTrend(boundaryTrend, pBar.Index()); + bool hasBoundaryBullishTrend = hasBoundaryTrend && boundaryTrend.IsBullish(); + bool hasBoundaryBearishTrend = hasBoundaryTrend && boundaryTrend.IsBearish(); + + // + // Check Bar Patterns ... + + // + // Bars Sequences ... + bool hasBullishSequence = p3Bar.IsBearish() && + pBar.IsBullish(); + bool hasBearishSequence = p3Bar.IsBullish() && + pBar.IsBearish(); + + // + // Bullish ... + bool isPBarHasBullishPatterns = + (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 = + (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) + // + ); + + // + 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); + + // + // Check Based On LC and HC MA State ... + + // + bool isLCMABullish = fimaParser.IsLCMABullish(pBar.Index()); + bool isHCMABullish = fimaParser.IsHCMABullish(pBar.Index()); + bool isCycleMABullish = isLCMABullish && isHCMABullish; + + // + bool isLCMABearish = fimaParser.IsLCMABearish(pBar.Index()); + bool isHCMABearish = fimaParser.IsHCMABearish(pBar.Index()); + bool isCycleMABearish = isLCMABearish && isHCMABearish; + + // + // Do ... + + // + isBullish = + // + hasSupport && + isFastOverLast && + isValeUnderLast && + isCycleMABullish && + hasBullishSequence && + !isP2PeakUnderLast && + isPBarCloseOverFast && + isP2BarBullishPinned && + hasBoundaryBullishTrend && + isPBarHasBullishPatterns + // + ; + + // + isBearish = + // + hasResistance && + isPeakOverLast && + isFastUnderLast && + isCycleMABearish && + !isP2ValeOverLast && + hasBearishSequence && + isPBarCloseUnderFast && + isP2BarBearishPinned && + hasBoundaryBearishTrend && + 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 // + ); + + // + // Draws ... + if (result) + { + // + // XPOIDrawConfig iConfig = structureDrawConfig.drawConfig; + // iConfig.trendRayLeft = false; + // iConfig.trendRayRight = false; + // poiDrawer.DrawTrendLine(boundaryTrend, iConfig); + // poiDrawer.DrawZone(zone, structureDrawConfig.drawConfig); + // iConfig.Clean(); + + // + // DebugBreak(); + } + + // + result = zone.IsValid(); + } + + // + // Prepare Targets ... + if (result) + { + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + pBarPatterns.Clean(); + boundaryTrend.Clean(); + + // + return result; + } + + /** + * Check Bar Has Signal Based on Strategy 3 ... + * + * Strategy 3: + * =========== + * - Works Based On Breaked Support or Resistances ... + * - Looking for a Support or Resistance to Breaked ... + * - Validate Breaker Bar to Change Peak or Vale ... + * - Validate Bar Opposit Side of Breaker Bar's Shadow ... + * - Validate by Checking Market Strucutre to Has Directional Zone + * (Support for Resistance Break / Resistance for Support Break) ... + * - Validate Breaker Bar to Has Directional FVG ... + * + * 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 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; + } + + // + // Validation Flags ... + + // + bool validateByPVChanges = true; + bool validateByGapExists = true; + bool validateByBarShadows = true; + bool validateHasDirectionalZone = 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 ... + XBoxZone _fvg; + XBoxZone _support; + XBoxZone _resistance; + XPatternAnalysis pBarPatterns; + XPatternAnalysis p2BarPatterns; + XPatternAnalysisConfig patternConfig = structureConfig.barsAnalysisConfig; + + // + poiDetector.AnalyseBarPatterns( + pBar, + pBarPatterns, + patternConfig // + ); + poiDetector.AnalyseBarPatterns( + p2Bar, + p2BarPatterns, + patternConfig // + ); + + // + // Price Must Break Support or Resistance ... + + // + // Extract Support and Resistance ... + bool hasSupport = p2BarPatterns.IsSupport(); + bool hasResistance = p2BarPatterns.IsResistance(); + if (hasSupport) + { + // + XOHCL tmpBar; + XPivot tmpPivot; + hasSupport = p2BarPatterns.GetSupport(tmpBar, tmpPivot, _support); + tmpBar.Clean(); + tmpPivot.Clean(); + } + if (hasResistance) + { + // + XOHCL tmpBar; + XPivot tmpPivot; + hasResistance = p2BarPatterns.GetResistance(tmpBar, tmpPivot, _resistance); + tmpBar.Clean(); + tmpPivot.Clean(); + } + + // + bool hasBreakedSupport = hasSupport && + pBar.close < _support.lower && + p2Bar.close > _support.lower; + bool hasBreakedResistance = hasResistance && + pBar.close > _resistance.upper && + p2Bar.close < _resistance.upper; + + // + isBullish = hasBreakedResistance; + isBearish = hasBreakedSupport; + + // + result = isBullish || isBearish; + + // + // Validate By PV Changed ... + // Breaker Bar must Change Peak or Value ... + if (result && validateByPVChanges) + { + // + bool isPeakOverLast = fimaParser.IsPeakOverLast(pBar.Index()); + bool isValeUnderLast = fimaParser.IsValeUnderLast(pBar.Index()); + + // + isBullish = + isBullish && + isPeakOverLast; + + // + isBearish = + isBearish && + isValeUnderLast; + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + // + // Validate by Bar Shadows ... + // Breakre Bar Side Shadow must not Reached ... + if (result && validateByBarShadows) + { + // + isBullish = + isBullish && + pBar.low > p2Bar.low; + + // + isBearish = + isBearish && + pBar.high < p2Bar.high; + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + // + // Validate Has Directional Zone ... + if (result && validateHasDirectionalZone) + { + // + isBullish = + isBullish && + hasSupport; + + // + isBearish = + isBearish && + hasResistance; + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + // + // Validate By Gap Exists ... + if (result && validateByGapExists) + { + // + ENUM_X_DIRECTION tmpDir; + bool hasFVG = poiDetector.HasFVG( + pBar, + tmpDir, + _fvg // + ); + + // + isBullish = + isBullish && + hasFVG && + IsXBullish(tmpDir); + + // + isBearish = + isBearish && + hasFVG && + IsXBearish(tmpDir); + + // + // Summarize Result ... + result = isBullish || isBearish; + } + + // + // Prepare Direction and Zone ... + if (result) + { + // + if (isBullish) + { + // + zone = _resistance; + zone.dir = Opposit(_resistance.dir); + dir = zone.dir; + zone.upper = MathMax(zone.upper, _fvg.upper); + zone.lower = MathMin(zone.lower, _fvg.lower); + } + + // + if (isBearish) + { + // + zone = _support; + zone.dir = Opposit(_support.dir); + dir = zone.dir; + zone.upper = MathMax(zone.upper, _fvg.upper); + zone.lower = MathMin(zone.lower, _fvg.lower); + } + + // + // Zone Validation Base ... + result = zone.IsValid(); + if (result) + { + // + // Validate By Trend of Zone ... + XTrend zoneTrend; + XTrend zoneToTrend; + + // + // Detecting Trends ... + result = poiDetector.HasBoundaryTrend(zone, zoneTrend, false); + result = result && + poiDetector.HasBoundaryTrend(zone, zoneToTrend, true); + + // + // Validate Trend ... + result = + result && + zone.dir == zoneTrend.dir && + zone.dir == zoneToTrend.dir; + + // + // Draw ... + if (result) + { + // // + // XPOIDrawConfig iConfig = structureDrawConfig.drawConfig; + // iConfig.trendRayLeft = false; + // iConfig.trendRayRight = false; + + // // + // poiDrawer.DrawTrendLine(zoneTrend, iConfig); + // poiDrawer.DrawTrendLine(zoneToTrend, iConfig); + + // // + // iConfig.Clean(); + } + + // + // Cleanup ... + zoneTrend.Clean(); + zoneToTrend.Clean(); + + // + // Reset Flags ... + if (!result) + { + // + zone.Clean(); + isBullish = false; + isBearish = false; + } + } + + // + result = zone.IsValid(); + } + + // + if (result) + { + // + if (_support.IsValid()) + { + poiDrawer.DrawZone(_support, structureDrawConfig.drawConfig); + } + + // + if (_resistance.IsValid()) + { + poiDrawer.DrawZone(_resistance, structureDrawConfig.drawConfig); + } + + // + if (pBarPatterns.IsValid()) + { + poiDrawer.DrawPatternAnalysis(pBarPatterns, structureDrawConfig.barAnalysisDrawConfig); + } + } + + // + // Cleanup ... + if (!result) + { + // + zone.Clean(); + XClean(targets); + dir = X_DIRECTION_NONE; + } + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + pBarPatterns.Clean(); + p2BarPatterns.Clean(); + patternConfig.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 validateByXFIMABoundary = true; + bool validateByBarInsideATRBand = true; + bool validateByBarBasedOnATRBand = true; + bool validateByXFIMABoundaryTrend = 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 // + ); + + // + XTrend boundaryTrend; + XTrend boundaryZoneTrend; + + // + 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 and do Zone Based Validations ... + 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); + + // + // Validate by XFIMA Boundary ... + if (result && validateByXFIMABoundary) + { + // + // Try to Retrieve Boundary To Trend ... + result = poiDetector.HasBoundaryTrend( + zone, + boundaryTrend, + true // + ); + + // + // Try to Retrieve Boundary Zone Trend ... + result = + result && + poiDetector.HasBoundaryTrend( + zone, + boundaryZoneTrend, + false // + ); + + // + // Check and Validate Trend Direction ... + result = + result && + zone.dir == boundaryTrend.dir && + zone.dir == boundaryZoneTrend.dir; + + // + // Reset Flags ... + if (!result) + { + // + zone.Clean(); + result = false; + isBullish = false; + isBearish = false; + } + } + + // + // Manage Stops ... + if (result) + { + // + // Since Stop Management Changes Zones Edge(s) ... + // we do it here for Refining Zone ... + } + + // + 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(oFlow); + pBarPatterns.Clean(); + boundaryTrend.Clean(); + patternConfig.Clean(); + boundaryZoneTrend.Clean(); + + // + return result; + } + + // +}; + +// \ No newline at end of file diff --git a/Libraries/x-saherelm.x-poi.lib.mq5 b/Libraries/x-saherelm.x-poi.lib.mq5 index a5cb0614..0e53a36b 100644 --- a/Libraries/x-saherelm.x-poi.lib.mq5 +++ b/Libraries/x-saherelm.x-poi.lib.mq5 @@ -501,7 +501,8 @@ struct XTrend // if (IsValid()) { - result = "XTRND_" + ToXString(dir) + "_" + ToXString(TimeToSeconds(time)); + double ifv = NormalizePrice(fromValue, symbol); + result = "XTRND_" + ToXString(dir) + "_" + ToXString(ifv) + "_" + ToXString(TimeToSeconds(fromTime)); } // diff --git a/XFIMAEA/Classes/x-saherelm.xfima.parser.class.mq5 b/XFIMAEA/Classes/x-saherelm.xfima.parser.class.mq5 index 5d6c06db..c26f667d 100644 --- a/XFIMAEA/Classes/x-saherelm.xfima.parser.class.mq5 +++ b/XFIMAEA/Classes/x-saherelm.xfima.parser.class.mq5 @@ -1882,6 +1882,350 @@ class XCXFIMAHelperParser : XCBase return result; } + /** + * Check Price is Over HK Band Lower ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * + * @return ( bool ) + */ + bool IsOverHKBandLower( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + XOHCL bar; + result = bar.Init(symbol, period, barIndex); + double price = bar.GetPrice(priceType); + double value = helper.GetHKBandLower(barIndex); + result = + result && + price > value; + + // + // Cleanup ... + bar.Clean(); + + // + return result; + } + + /** + * Check Price is Over HK Band Upper ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * + * @return ( bool ) + */ + bool IsOverHKBandUpper( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + XOHCL bar; + result = bar.Init(symbol, period, barIndex); + double price = bar.GetPrice(priceType); + double value = helper.GetHKBandUpper(barIndex); + result = + result && + price > value; + + // + // Cleanup ... + bar.Clean(); + + // + return result; + } + + /** + * Check Price is Under HK Band Lower ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * + * @return ( bool ) + */ + bool IsUnderHKBandLower( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + XOHCL bar; + result = bar.Init(symbol, period, barIndex); + double price = bar.GetPrice(priceType); + double value = helper.GetHKBandLower(barIndex); + result = + result && + price < value; + + // + // Cleanup ... + bar.Clean(); + + // + return result; + } + + /** + * Check Price is Under HK Band Upper ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * + * @return ( bool ) + */ + bool IsUnderHKBandUpper( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + XOHCL bar; + result = bar.Init(symbol, period, barIndex); + double price = bar.GetPrice(priceType); + double value = helper.GetHKBandUpper(barIndex); + result = + result && + price < value; + + // + // Cleanup ... + bar.Clean(); + + // + return result; + } + + /** + * Check Price Crossed Over HK Band Lower ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * + * @return ( bool ) + */ + bool IsCrossedOverHKBandLower( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + bool isC = IsOverHKBandLower(barIndex, priceType); + bool isP = IsOverHKBandLower(barIndex + 1, priceType); + + // + result = isC && !isP; + + // + return result; + } + + /** + * Check Price Crossed Under HK Band Lower ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * + * @return ( bool ) + */ + bool IsCrossedUnderHKBandLower( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + bool isC = IsUnderHKBandLower(barIndex, priceType); + bool isP = IsUnderHKBandLower(barIndex + 1, priceType); + + // + result = isC && !isP; + + // + return result; + } + + /** + * Check Price Crossed Over HK Band Upper ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * + * @return ( bool ) + */ + bool IsCrossedOverHKBandUpper( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + bool isC = IsOverHKBandUpper(barIndex, priceType); + bool isP = IsOverHKBandUpper(barIndex + 1, priceType); + + // + result = isC && !isP; + + // + return result; + } + + /** + * Check Price Crossed Under HK Band Upper ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * + * @return ( bool ) + */ + bool IsCrossedUnderHKBandUpper( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + bool isC = IsUnderHKBandUpper(barIndex, priceType); + bool isP = IsUnderHKBandUpper(barIndex + 1, priceType); + + // + result = isC && !isP; + + // + return result; + } + /** * Count Bullish HK(s) ... * @@ -2988,6 +3332,361 @@ class XCXFIMAHelperParser : XCBase return result; } + // + // XATR ... + + /** + * Check Price is Over ATR Band Lower ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * + * @return ( bool ) + */ + bool IsOverATRBandLower( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = + IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + XOHCL bar; + result = bar.Init(symbol, period, barIndex); + double price = bar.GetPrice(priceType); + double value = helper.GetATRBandLower(barIndex); + result = + result && + NotEmptyZero(value) && + NotEmptyZero(price) && + price > value; + + // + // Cleanup ... + bar.Clean(); + + // + return result; + } + + /** + * Check Price is Over ATR Band Upper ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * + * @return ( bool ) + */ + bool IsOverATRBandUpper( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = + IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + XOHCL bar; + result = bar.Init(symbol, period, barIndex); + double price = bar.GetPrice(priceType); + double value = helper.GetATRBandUpper(barIndex); + result = + result && + NotEmptyZero(value) && + NotEmptyZero(price) && + price > value; + + // + // Cleanup ... + bar.Clean(); + + // + return result; + } + + /** + * Check Price is Under ATR Band Lower ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * + * @return ( bool ) + */ + bool IsUnderATRBandLower( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = + IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + XOHCL bar; + result = bar.Init(symbol, period, barIndex); + double price = bar.GetPrice(priceType); + double value = helper.GetATRBandLower(barIndex); + result = + result && + NotEmptyZero(value) && + NotEmptyZero(price) && + price < value; + + // + // Cleanup ... + bar.Clean(); + + // + return result; + } + + /** + * Check Price is Under ATR Band Upper ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * + * @return ( bool ) + */ + bool IsUnderATRBandUpper( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + result = + IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + XOHCL bar; + result = bar.Init(symbol, period, barIndex); + double price = bar.GetPrice(priceType); + double value = helper.GetATRBandUpper(barIndex); + result = + result && + NotEmptyZero(value) && + NotEmptyZero(price) && + price < value; + + // + // Cleanup ... + bar.Clean(); + + // + return result; + } + + /** + * Check Price is Crossed Over ATR Band Lower ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * + * @return ( bool ) + */ + bool IsCrossedOverATRBandLower( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + bool isC = IsOverATRBandLower(barIndex, priceType); + bool isP = IsOverATRBandLower(barIndex + 1, priceType); + + // + result = isC && !isP; + + // + return result; + } + + /** + * Check Price is Crossed Under ATR Band Lower ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * + * @return ( bool ) + */ + bool IsCrossedUnderATRBandLower( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + bool isC = IsUnderATRBandLower(barIndex, priceType); + bool isP = IsUnderATRBandLower(barIndex + 1, priceType); + + // + result = isC && !isP; + + // + return result; + } + + /** + * Check Price is Crossed Over ATR Band Upper ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * + * @return ( bool ) + */ + bool IsCrossedOverATRBandUpper( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + bool isC = IsOverATRBandUpper(barIndex, priceType); + bool isP = IsOverATRBandUpper(barIndex + 1, priceType); + + // + result = isC && !isP; + + // + return result; + } + + /** + * Check Price is Crossed Under ATR Band Upper ... + * + * @param barIndex: int, Specified Bar Index ... + * @param priceType: ENUM_X_PRICE, Specified Price Type ... + * + * @return ( bool ) + */ + bool IsCrossedUnderATRBandUpper( + int barIndex = 0, + ENUM_X_PRICE priceType = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + // Normalize ... + barIndex = NormalizeBarIndex(barIndex); + + // + result = IsValid() && + IsXValid(priceType); + if (!result) + { + return result; + } + + // + bool isC = IsUnderATRBandUpper(barIndex, priceType); + bool isP = IsUnderATRBandUpper(barIndex + 1, priceType); + + // + result = isC && !isP; + + // + return result; + } + // // Cycles Tools ... @@ -7469,7 +8168,7 @@ class XCXFIMAHelperParser : XCBase /** * Retrieve Cycles MA(s) ... - * + * * @param scMA: double, reference to holds cycle value ... * @param mcMA: double, reference to holds cycle value ... * @param lcMA: double, reference to holds cycle value ... @@ -7512,7 +8211,7 @@ class XCXFIMAHelperParser : XCBase /** * Retrieve Cycles MA State(s) ... - * + * * @param scMAState: double, reference to holds cycle value ... * @param mcMAState: double, reference to holds cycle value ... * @param lcMAState: double, reference to holds cycle value ... @@ -8507,6 +9206,115 @@ class XCXFIMAHelperParser : XCBase return result; } + // + // Other Tools ... + + int CollectPivots( + XPivot &pivots[], + int barIndex = 0, + int loopback = 500 // + ) + { + // + int result = 0; + + // + // Prepare ... + XClean(pivots); + + // + // Normalize ... + loopback = NormalizeInt(loopback, 50); + barIndex = NormalizeBarIndex(barIndex); + + // + // Validate ... + bool has = IsValid(); + if (!has) + { + return result; + } + + // + has = false; + XOHCL tmpBar; + XPivot tmpPivot; + double tmpValue; + datetime tmpTime; + bool isBullish = false; + bool isBearish = false; + string tmpSymbol = symbol; + ENUM_TIMEFRAMES tmpPeriod = period; + ENUM_X_DIRECTION tmpDir = X_DIRECTION_NONE; + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + tmpBar.Clean(); + tmpPivot.Clean(); + + // + has = tmpBar.Init(tmpSymbol, tmpPeriod, i); + if (!has) + { + continue; + } + + // + // XSAR ... + isBullish = IsSARSwitchedToBullish(i); + isBearish = IsSARSwitchedToBearish(i); + has = isBullish || isBearish; + if (has) + { + } + + // + // XMA Fast / Slow ... + + // + // States ... + isBullish = IsMASlowSwitchedToBullish(i); + isBearish = IsMASlowSwitchedToBearish(i); + has = isBullish || isBearish; + if (has) + { + } + + // + // Crossed Fast Slow ... + isBullish = IsMAFastCrossedOverSlow(i); + isBearish = IsMAFastCrossedUnderSlow(i); + has = isBullish || isBearish; + if (has) + { + } + + // + // Crossed Last ... + isBullish = IsMASlowCrossedOverLast(i); + isBearish = IsMASlowCrossedUnderLast(i); + has = isBullish || isBearish; + if (has) + { + } + + // + // XHK ... + isBullish = IsHKSwitchedToBullish(i); + isBearish = IsHKSwitchedToBearish(i); + has = isBullish || isBearish; + if (has) + { + } + } + + // + result = ArraySize(pivots); + + // + return result; + } + // // Protected ... protected: diff --git a/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 b/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 index df4cb2f5..e20baed2 100644 --- a/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 +++ b/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 @@ -1564,10 +1564,10 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller // // Signaller Flags ... - bool useSignaller1 = true; - bool useSignaller2 = false; - bool useSignaller3 = false; - bool useSignaller4 = false; + bool useSignaller1 = false; + bool useSignaller2 = true; + bool useSignaller3 = true; + bool useSignaller4 = true; // XBoxZone tmpZone; @@ -2049,6 +2049,7 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller // XOHCL pBar; XOHCL p2Bar; + XOHCL p3Bar; bool isBullish = false; bool isBearish = false; @@ -2057,56 +2058,19 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller result = bar.GetPreviousBar(pBar); result = result && pBar.GetPreviousBar(p2Bar); + result = result && + p2Bar.GetPreviousBar(p3Bar); if (!result) { // pBar.Clean(); p2Bar.Clean(); + p3Bar.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 pBarPatterns; @@ -2115,9 +2079,18 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller pBarPatterns, structureConfig.barsAnalysisConfig // ); + bool hasSupport = pBarPatterns.IsSupport(); + bool hasResistance = pBarPatterns.IsResistance(); // - // Check Bar Patterns ... + // Check Boundary Trend ... + XTrend boundaryTrend; + bool hasBoundaryTrend = fimaParser.HasBoundaryTrend(boundaryTrend, pBar.Index()); + bool hasBoundaryBullishTrend = hasBoundaryTrend && boundaryTrend.IsBullish(); + bool hasBoundaryBearishTrend = hasBoundaryTrend && boundaryTrend.IsBearish(); + + // + // Bullish ... bool isPBarHasBullishPatterns = (bar.close > pBar.low || bar.open > pBar.low) && @@ -2130,6 +2103,9 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller pBarPatterns.IsSignalKey(X_DIRECTION_BULLISH) // ); + + // + // Bearish ... bool isPBarHasBearishPatterns = (bar.close < pBar.high || bar.open < pBar.high) && @@ -2144,94 +2120,78 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller ); // - // 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( + // Check Pull Back Pattern ... + XBoxZone pullbackZone; + ENUM_X_DIRECTION pullbackDir; + bool isPullback = poiDetector.IsPullbackPattern( pBar, - zones, // - 5, // Zones Loopback ... - 3 // Zones Validation Length ... - // Required Zones ... - // Loopback ... + pullbackZone, + pullbackDir // ); - int affectedZonesCount = ExtractAffectedZones( + bool isBullishPullback = isPullback && IsXBullish(pullbackDir); + bool isBearishPullback = isPullback && IsXBearish(pullbackDir); + + // + // 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); + + // + // Checking For Leg Pattern ... + XLeg _leg; + XBoxZone legZone; + bool hasLeg = poiDetector.IsLegPattern( pBar, - zones, - affectedZones // - ); - int affectedZonesBullishCount = ExtractByDirection( - affectedZonesBullish, - affectedZones, - X_DIRECTION_BULLISH // - ); - int affectedZonesBearishCount = ExtractByDirection( - affectedZonesBearish, - affectedZones, - X_DIRECTION_BEARISH // + _leg, + 3, + 100 // ); + if (hasLeg) + { + hasLeg = _leg.ToBox(legZone); + } + bool hasBullishLeg = hasLeg && _leg.IsBullish(); + bool hasBearishLeg = hasLeg && _leg.IsBearish(); // - int insideBullishIDX = -1; - int insideBearishIDX = -1; - bool hasBullishInside = - pBar.IsBullish() && - HasInside( - insideBullishIDX, - pBar, - affectedZonesBullish // - ); - bool hasBearishInside = - pBar.IsBearish() && - HasInside( - insideBearishIDX, - pBar, - affectedZonesBearish // - ); + // Check Based On LC and HC MA State ... // - // Detecting Boundary Trend ... - XTrend boundaryTrend; - bool hasBoundaryTrend = fimaParser.HasBoundaryTrend(boundaryTrend, pBar.Index()); - bool hasBoundaryBullishTrend = hasBoundaryTrend && boundaryTrend.IsBullish(); - bool hasBoundaryBearishTrend = hasBoundaryTrend && boundaryTrend.IsBearish(); + bool isLCMABullish = fimaParser.IsLCMABullish(pBar.Index()); + bool isHCMABullish = fimaParser.IsHCMABullish(pBar.Index()); + bool isCycleMABullish = isLCMABullish && isHCMABullish; // - // Do ... + bool isLCMABearish = fimaParser.IsLCMABearish(pBar.Index()); + bool isHCMABearish = fimaParser.IsHCMABearish(pBar.Index()); + bool isCycleMABearish = isLCMABearish && isHCMABearish; + + // + // + // // isBullish = - // - hasBullishInside && - isPullbackBullish && - isPBarHasBullishPatterns && - fimaParser.IsSARBullish(pBar.Index()) && - (pVale >= affectedZonesBullish[insideBullishIDX].lower && - pVale <= affectedZonesBullish[insideBullishIDX].upper) - // - ; + hasBullishLeg && + isCycleMABullish && + isBullishPullback && + isP2BarBullishPinned; // isBearish = - // - hasBearishInside && - isPullbackBearish && - isPBarHasBearishPatterns && - fimaParser.IsSARBearish(pBar.Index()) && - (pPeak >= affectedZonesBearish[insideBearishIDX].lower && - pPeak <= affectedZonesBearish[insideBearishIDX].upper) - // - ; + hasBearishLeg && + isCycleMABearish && + isBearishPullback && + isP2BarBearishPinned; // // Validate ... @@ -2255,48 +2215,35 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller { // zone.Clean(); - if (isBullish) - { - zone = affectedZonesBullish[insideBullishIDX]; - } - else - { - zone = affectedZonesBearish[insideBearishIDX]; - } + zone = pullbackZone; // - result = zone.IsValid(); - - // - // Zone Validations ... + // Draws ... if (result) { // - if (boundaryTrend.IsValid()) - { - poiDrawer.DrawTrendLine(boundaryTrend, structureDrawConfig.drawConfig); - } + XPOIDrawConfig iConfig = structureDrawConfig.drawConfig; + iConfig.trendRayLeft = false; + iConfig.trendRayRight = false; // - poiDrawer.DrawZone(zone, structureDrawConfig.drawConfig); + poiDrawer.DrawZone(legZone, iConfig); + poiDrawer.DrawZone(pullbackZone, iConfig); + + // + // poiDrawer.DrawTrendLine(boundaryTrend, iConfig); + // poiDrawer.DrawZone(zone, structureDrawConfig.drawConfig); poiDrawer.DrawPatternAnalysis(pBarPatterns, structureDrawConfig.barAnalysisDrawConfig); + // + iConfig.Clean(); + // DebugBreak(); } // result = zone.IsValid(); - - // - // Reset Flags ... - if (!result) - { - // - zone.Clean(); - isBullish = false; - isBearish = false; - } } // @@ -2316,12 +2263,10 @@ class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller } pBar.Clean(); p2Bar.Clean(); - XClean(zones); + p3Bar.Clean(); + pullbackZone.Clean(); pBarPatterns.Clean(); boundaryTrend.Clean(); - XClean(affectedZones); - XClean(affectedZonesBullish); - XClean(affectedZonesBearish); // return result;