From fd82d07995b2bb14fbdd5b43167a838dded2c2e3 Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Mon, 29 Sep 2025 16:22:30 +0330 Subject: [PATCH] last ... --- .../BKP/x-saherelm.xfima.signaller.class.mq5 | 3804 +++++++++++++++++ Experts/x-saherelm.xfima.backtester.ea.mq5 | 22 +- .../x-saherelm.common.extensions.lib.mq5 | 23 + Libraries/x-saherelm.x-enums.lib.mq5 | 34 + .../x-saherelm.xfima.signaller.class.mq5 | 570 ++- 5 files changed, 4238 insertions(+), 215 deletions(-) create mode 100644 Documents/BKP/x-saherelm.xfima.signaller.class.mq5 diff --git a/Documents/BKP/x-saherelm.xfima.signaller.class.mq5 b/Documents/BKP/x-saherelm.xfima.signaller.class.mq5 new file mode 100644 index 00000000..bffdfd93 --- /dev/null +++ b/Documents/BKP/x-saherelm.xfima.signaller.class.mq5 @@ -0,0 +1,3804 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class +// ------------------------------------------------- +// Name: XCXFIMASignaller ... +// Description: XFIMA Signaller Class ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://saherelm.ir" +#property version "1.00" +#property description "SaherElm XFIMA Signaller Class" +#property strict + +// +// Imports ... +#include "../../Classes/x-saherelm.x-signaller.class.mq5" +#include "../../Helpers/x-saherelm.xfima.helper.mq5" +#include "../Classes/x-saherelm.xfima.x-poi.detector.class.mq5" +#include "../Classes/x-saherelm.xfima.x-poi.drawer.class.mq5" + +// +// Implementation ... + +// +// Base XFIMA base Signaller ... +class XCXFIMABaseSignaller : public XCBaseSignaller +{ + // + // Public ... + public: + // + // Props ... + + // + XFIMAInputs fimaInputs; // XFIMA Inputs ... + XCXFIMAHelper *fimaHelper; // XFIMA Indicator Helper ... + XCXFIMAPOIDrawer *poiDrawer; // XFIMA POI Drawer ... + XCXFIMAPOIDetector *poiDetector; // XFIMA POI Detector ... + + // + // Constructor ... + XCXFIMABaseSignaller( + string _name, // Name ... + string _symbol, // Symbol ... + ENUM_TIMEFRAMES _period, // Period ... + XFIMAInputs &_fimaInputs, // XFIMAInputs ... + bool _processAllTicks = false, // Process All Ticks ... + double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ... + double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ... + double _defaultSignalVolume = 0.01 // Default Signal Volume ... + ) : XCBaseSignaller(_name, + _symbol, + _period, + _processAllTicks, + _defaultSignalR2R, + _defaultSignalRiskInPoint, + _defaultSignalVolume // + ) + { + // + // Instantiating XFIMA Indicator Helper Class ... + if (_fimaInputs.IsValid()) + { + // + fimaHelper = new XCXFIMAHelper(); + bool isInited = fimaHelper.Init( + _symbol, + _period, + _fimaInputs // + ); + if (isInited) + { + fimaInputs = _fimaInputs; + } + else + { + // + delete fimaHelper; + ZeroMemory(fimaHelper); + } + } + + // + poiDrawer = new XCXFIMAPOIDrawer(); + poiDetector = new XCXFIMAPOIDetector(fimaHelper); + } + + // + // Deconstructor ... + ~XCXFIMABaseSignaller() + { + Destroy(); + } + + // + // Overrides ... + + // + // Actions ... + + /** + * Destroy ... + */ + void Destroy() + { + // + BeforeDestroy(); + + // + fimaInputs.Clean(); + + // + delete fimaHelper; + ZeroMemory(fimaHelper); + + // + delete poiDrawer; + ZeroMemory(poiDrawer); + + // + delete poiDetector; + ZeroMemory(poiDetector); + } + + // + // Virtuals ... + + /** + * Before Destroy ... + */ + void virtual BeforeDestroy() + { + } + + /** + * Processing Tick ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessTick(int barIndex = 0) + { + } + + /** + * Processing New Bar ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessNewBar(int barIndex = 0) + { + } + + /** + * Check Guards Based on MarketConditions ... + * + * @param guards: XGuard[] + * @param barIndex: int + * + * @return ( int ) + */ + int virtual CheckForGuard( + XGuard &guards[], + int barIndex = 0 // + ) + { + // + int result = 0; + + // + SpecifiedClean(guards); + + // + result = ArraySize(guards); + + // + return result; + } + + /** + * Check Additional Validations on Childs Instances ... + * + * @return ( bool virtual ) + */ + bool virtual CheckAdditionslSignallerValidations() + { + // + bool result = false; + + // + // Validate Fima Helper Requirements ... + result = fimaInputs.IsValid() && + fimaHelper != NULL && + poiDetector != NULL; + + // + return result; + } + + /** + * Normalizing Signal by Signaller Custom Props ... + * + * @param signal: XSignal ... + */ + void virtual NormalizeSignal(XSignal &signal) + { + } + + // + // Protected ... + protected: + // + + // + // Private ... + private: + // +}; + +// +// XFIMA Strategy 1 Signaller Class ... +class XCXFIMAStrategy1Signaller : public XCXFIMABaseSignaller +{ + // + // Public ... + public: + // + // Props ... + int fvgLookupLenght; // Maximum Lenght for Looking up FVG before Crosses + + // + // Constructor ... + XCXFIMAStrategy1Signaller( + string _symbol, // Symbol ... + ENUM_TIMEFRAMES _period, // Period ... + XFIMAInputs &_fimaInputs, // XFIMAInputs ... + bool _processAllTicks = false, // Process All Ticks ... + double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ... + double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ... + double _defaultSignalVolume = 0.01 // Default Signal Volume ... + ) : XCXFIMABaseSignaller("XFIMA1", + _symbol, + _period, + _fimaInputs, + _processAllTicks, + _defaultSignalR2R, + _defaultSignalRiskInPoint, + _defaultSignalVolume // + ) + { + // + fvgLookupLenght = 5; + } + + // + // Overrides ... + + /** + * Processing Tick ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessTick(int barIndex = 0) + { + } + + /** + * Processing New Bar ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessNewBar(int barIndex = 0) + { + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + // Update Helper ... + fimaHelper.Update(barIndex); + + // + XOHCL bar; + XSignal signal; + bool has = false; + int cIdx = barIndex + 1; + int pIdx = cIdx + 1; + ENUM_X_DIRECTION signalDir = X_DIRECTION_NONE; + + // + // Initialize Bar as CBar ... + has = bar.Init( + symbol, + period, + cIdx // + ); + if (!has) + { + // + bar.Clean(); + return; + } + + // + // Retrieve Conditions ... + XFIMAConditions fimaConditions; + has = fimaHelper.GetConditions( + fimaConditions, + barIndex, + 10 // Loopback ... + ); + if (!has) + { + // + bar.Clean(); + fimaConditions.Clean(); + + // + return; + } + + // + // Analyse Conditions for Finding Signal ... + + // + // TODO: Remove this ... + + // + bool isFastCrossedOverSlow = + fimaConditions.maFastBuffer[cIdx] > fimaConditions.maSlowBuffer[cIdx] && + fimaConditions.maFastBuffer[pIdx] < fimaConditions.maSlowBuffer[pIdx]; + + // + bool isFastCrossedUnderSlow = + fimaConditions.maFastBuffer[cIdx] < fimaConditions.maSlowBuffer[cIdx] && + fimaConditions.maFastBuffer[pIdx] > fimaConditions.maSlowBuffer[pIdx]; + + // + has = + isFastCrossedOverSlow || + isFastCrossedUnderSlow; + if (has) + { + // + // Do Conditions Validating ... + // TODO: Igmore All Validations for Testing Purposes ... + + // + // Validate MA Positions ... + double iFastMa = fimaConditions.maFastBuffer[cIdx]; + double iSlowMa = fimaConditions.maSlowBuffer[cIdx]; + double iFiboUpper = fimaConditions.fiboUpperBuffer[cIdx]; + double iFiboLower = fimaConditions.fiboLowerBuffer[cIdx]; + + // + // Checking Has FVG ... + XBoxZone fvg; + ENUM_X_DIRECTION fvgDir; + bool hasFVG = patternDetector.HasFVG( + bar, + fvgDir, + fvg, + fvgLookupLenght // + ); + + // + // Checking Crossed On Shadow ... + + // + bool isCrossedOverHappensOnShadow = + isFastCrossedOverSlow && + iFastMa <= bar.GetDown() && + iFastMa >= bar.low; + + // + bool isCrossedUnderHappensOnShadow = + isFastCrossedUnderSlow && + iFastMa <= bar.high && + iFastMa >= bar.GetUp(); + + // + // Bullish Validation ... + bool isBullish = + // + // Has Cross ... + isFastCrossedOverSlow + // + // && + // // + // // Cross Places Based on Fibo ... + // MathMax(iFastMa, iSlowMa) < iFiboLower + // // + // && + // // + // ( + // // + // // Checking FVG ... + // (hasFVG && + // fvg.IsBullish()) + // // + // || + // // + // // Checking Crossed Place ... + // isCrossedOverHappensOnShadow + // // + // ) + // // + ; + + // + // Bearish Validation ... + bool isBearish = + // + // Has Cross ... + isFastCrossedUnderSlow + // + // && + // // + // // Cross Places Based on Fibo ... + // MathMin(iFastMa, iSlowMa) > iFiboUpper + // // + // && + // // + // ( + // // + // // Checking FVG ... + // (hasFVG && + // fvg.IsBearish()) + // // + // || + // // + // // Checking Crossed Place ... + // isCrossedUnderHappensOnShadow + // // + // ) + // // + ; + + // + has = + (isBullish && !isBearish) || + (isBearish && !isBullish); + if (has) + { + // + signalDir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + } + + // + // Check Signal Founded ... + has = HasDirection(signalDir); + if (has) + { + // + // Prepare Founded Signal ... + XTarget targets[]; + has = PrepareSignal( + signal, + signalDir, + targets // + ); + if (has) + { + // + // Notify On Signal Event ... + NotifySignalEventListeners(signal); + } + } + + // + // Cleanup Resources ... + bar.Clean(); + signal.Clean(); + fimaConditions.Clean(); + } + + /** + * Check Guards Based on MarketConditions ... + * + * @param guards: XGuard[] + * @param barIndex: int + * + * @return ( int ) + */ + int virtual CheckForGuard( + XGuard &guards[], + int barIndex = 0 // + ) + { + // + int result = 0; + + // + SpecifiedClean(guards); + + // + result = ArraySize(guards); + + // + return result; + } + + // + // Private ... + private: + // + // Props ... + + // + // Lookup FVG ... + bool LookupFVG( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + XBoxZone &fvgBox // + ) + { + // + bool result = false; + + // + return result; + } + + // +}; + +// +// XFIMA Strategy 2 Signaller Class ... +class XCXFIMAStrategy2Signaller : public XCXFIMABaseSignaller +{ + // + // Public ... + public: + // + // Props ... + XFIMAPatternDetectorConfig analyserConfig; + + // + // Constructor ... + XCXFIMAStrategy2Signaller( + string _symbol, // Symbol ... + ENUM_TIMEFRAMES _period, // Period ... + XFIMAInputs &_fimaInputs, // XFIMAInputs ... + bool _processAllTicks = false, // Process All Ticks ... + double _defaultSignalR2R = 1.5, // Default Signal Risk To Reward Ratio ... + double _defaultSignalRiskInPoint = 50, // Default Signal Risk In Point ... + double _defaultSignalVolume = 0.01 // Default Signal Volume ... + ) : XCXFIMABaseSignaller("XFIMA2", + _symbol, + _period, + _fimaInputs, + _processAllTicks, + _defaultSignalR2R, + _defaultSignalRiskInPoint, + _defaultSignalVolume // + ) + { + // + // Configure Detector ... + analyserConfig.Default(); + analyserConfig.FullDetect(); + } + + // + // Deconstructor ... + ~XCXFIMAStrategy2Signaller() + { + // + Destroy(); + + // + analyserConfig.Clean(); + } + + // + // Overrides ... + + /** + * Processing Tick ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessTick(int barIndex = 0) + { + } + + /** + * Processing New Bar ... + * + * @param barIndex: int, Specified Bar Index ... + */ + void ProcessNewBarNKP(int barIndex = 0) + { + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + // Update Helper ... + fimaHelper.Update(barIndex); + + // + XOHCL bar; + XSignal signal; + XBoxZone iZone; + int count = 0; + bool has = false; + int cIdx = barIndex + 1; + int pIdx = cIdx + 1; + string iName = NULL; + XBoxZone supports[]; + XBoxZone resistances[]; + bool isBullish = false; + bool isBearish = false; + double iPrice = EMPTY_VALUE; + XFIMAMarketStructure structure; + XFIMAConditions fimaConditions; + ENUM_X_PRICE iPriceType = X_PRICE_NONE; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + + // + XPivot pvPivots[]; + string pvTrendName = "XXIFMA2PVTrend"; + CChartObjectTrend *pvTrendLine = NULL; + ENUM_X_DIRECTION pvTrend = X_DIRECTION_NONE; + + // + XPivot zgPivots[]; + string zgTrendName = "XFIMA2ZGTrend"; + CChartObjectTrend *zgTrendLine = NULL; + ENUM_X_DIRECTION zgTrend = X_DIRECTION_NONE; + + // + // Initialize Bar as CBar ... + has = bar.Init( + symbol, + period, + cIdx // + ); + if (!has) + { + // + bar.Clean(); + return; + } + + // + // Retrieve Conditions ... + has = fimaHelper.GetConditions( + fimaConditions, + barIndex, + 10 // Loopback ... + ); + if (!has) + { + // + bar.Clean(); + fimaConditions.Clean(); + + // + return; + } + + // + // Analyse Market ... + poiDetector.AnalyseMarket( + bar, + structure, + analyserConfig // + ); + + // + // Check Required Pattern Exists ... + bool hasPinnedBar = HasDirection(structure.pinnedDir); + bool hasEngulfedBar = HasDirection(structure.engulfedDir); + bool hasFlagPattern = HasDirection(structure.flagPatternDir); + bool hasStarPattern = HasDirection(structure.starPatternDir); + bool hasRisingPattern = HasDirection(structure.risingPatternDir); + bool hasPiercingPattern = HasDirection(structure.piercingPatternDir); + bool hasSignalKeyBar = HasDirection(structure.signalKeyBarPatternDir); + + // + // Check Bar Pattern Exists ... + has = hasPinnedBar || + hasEngulfedBar || + hasFlagPattern || + hasStarPattern || + hasSignalKeyBar || + hasRisingPattern || + hasPiercingPattern; + + // + // Select Pattern Direction and Price and Price Type ... + if (has) + { + // + if (hasPinnedBar) + { + // + iDir = structure.pinnedDir; + iName = "XPinned_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasEngulfedBar) + { + // + iDir = structure.engulfedDir; + iName = "XEngulfed_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasFlagPattern) + { + // + iDir = structure.flagPatternDir; + iName = "XFlag_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasStarPattern) + { + // + iDir = structure.starPatternDir; + iName = "XStar_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasSignalKeyBar) + { + // + iDir = structure.risingPatternDir; + iName = "XRising_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasRisingPattern) + { + // + iDir = structure.piercingPatternDir; + iName = "XPiercing_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasPiercingPattern) + { + // + iDir = structure.signalKeyBarPatternDir; + iName = "XSignalKey_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + + // + isBullish = IsSpecifiedBullish(iDir); + isBearish = IsSpecifiedBearish(iDir); + + // + // Retrieve Price Type for Validate ... + iPriceType = isBullish + ? X_PRICE_LOW + : X_PRICE_HIGH; + iPrice = bar.GetPrice(iPriceType); + + // + has = HasDirection(iDir); + } + + // + // Chekc Bullish or Bearish Starter Conditions Exists ... + has = + isBullish || + isBearish; + if (has) + { + // + // Do Conditions Validating ... + + // + // Retrieve MA Band for Validation ... + double iMABandUpper = fimaHelper.GetMABandUpper(barIndex); + double iMABandLower = fimaHelper.GetMABandLower(barIndex); + + // + // Validate ... + has = isBullish + ? iPrice < iMABandLower + : iPrice > iMABandUpper; + if (!has) + { + // + isBullish = false; + isBearish = false; + iDir = X_DIRECTION_NONE; + } + } + + // + // Collect Support and Resistance Zones and Validate by them ... + + // + // PV Trend Line ... + bool hasPVAnalysis = structure.pvAnalysis.IsValid(); + if (hasPVAnalysis) + { + // + // Support ... + XBoxZone supportBox; + has = structure.pvAnalysis.HasSupportBox(supportBox); + if (has) + { + // + supportBox.to = bar.time; + AddIfNotExists( + supportBox, + supports // + ); + // has = poiDrawer.DrawBox( + // supportBox, + // iSupportObj, + // true, // Ignore At ... + // supportBox.type // Name ... + // ); + // if (has) + // { + // // + // XPOIStyle iStyle; + // poiDrawer.GetBoxStyle( + // iStyle, + // supportBox.dir // + // ); + // poiDrawer.ApplyBoxStyle( + // iSupportObj, + // iStyle // + // ); + // iStyle.Clean(); + // } + } + + // + // Resistance ... + XBoxZone resistanceBox; + has = structure.pvAnalysis.HasResistanceBox(resistanceBox); + if (has) + { + // + resistanceBox.to = bar.time; + AddIfNotExists( + resistanceBox, + supports // + ); + // has = poiDrawer.DrawBox( + // resistanceBox, + // iResistanceObj, + // true, // Ignore At ... + // resistanceBox.type // Name ... + // ); + // if (has) + // { + // // + // XPOIStyle iStyle; + // poiDrawer.GetBoxStyle( + // iStyle, + // resistanceBox.dir // + // ); + // poiDrawer.ApplyBoxStyle( + // iResistanceObj, + // iStyle // + // ); + // iStyle.Clean(); + // } + } + + // + // Pivots ... + XPivot pivots[]; + count = poiDetector.ExtractPVPivots( + pivots, + barIndex, + 50 // + ); + has = IsValidSize(count); + + // + // Sort ... + Sort( + pivots, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + // Remove Newest ... + ArrayRemove( + pivots, + 0, + 1 // + ); + + // + // Check Trend ... + if (has) + { + // + XPivot highs[]; + int highsCount = ExtractPivots( + highs, + pivots, + X_PIVOT_TYPE_PEAK // + ); + Sort( + highs, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + XPivot lows[]; + int lowsCount = ExtractPivots( + lows, + pivots, + X_PIVOT_TYPE_VALE // + ); + Sort( + lows, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + // Check Highs and Lows ... + has = IsValidSize(lowsCount) && + IsValidSize(highsCount) && + lowsCount >= 2 && + highsCount >= 2; + if (has) + { + // + // Try to Get Market Strucutre ... + + // + bool hasLowerHigh = highs[0].value < highs[1].value; + bool hasLowerLow = lows[0].value < lows[1].value; + + // + bool hasHigherHigh = highs[0].value > highs[1].value; + bool hasHigherLow = lows[0].value > lows[1].value; + + // + pvTrend = + (hasHigherHigh && + hasHigherLow) + ? X_DIRECTION_BULLISH + : (hasLowerHigh && + hasLowerLow) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + has = HasDirection(pvTrend); + if (has) + { + // + // Select Swings for Trend Line ... + XOHCL tmpBar; + int llIDX = -1; + int hhIDX = -1; + datetime toTime = NULL; + datetime fromTime = NULL; + double toPrice = EMPTY_VALUE; + color trendColor = CLR_NONE; + double fromPrice = EMPTY_VALUE; + if (IsSpecifiedBullish(pvTrend)) + { + // + llIDX = GetLowest(lows); + hhIDX = GetHighest(lows); + + // + trendColor = clrAqua; + + // + toTime = lows[hhIDX].time; + toPrice = lows[hhIDX].value; + + // + fromTime = lows[llIDX].time; + fromPrice = lows[llIDX].value; + } + else + { + // + llIDX = GetLowest(highs); + hhIDX = GetHighest(highs); + + // + trendColor = clrMagenta; + + // + toTime = highs[llIDX].time; + toPrice = highs[llIDX].value; + + // + fromTime = highs[hhIDX].time; + fromPrice = highs[hhIDX].value; + } + + // + // Check Requirements for Trend ... + has = + NotEmptyZero(toPrice) && + NotEmptyZero(fromPrice) && + IsSpecifiedValid(toTime) && + IsSpecifiedValid(fromTime); + if (has) + { + // + has = poiDrawer.DrawTrendLine( + fromPrice, + fromTime, + toPrice, + toTime, + pvTrendLine, + pvTrendName, + true // Ray Right ... + ); + if (has) + { + pvTrendLine.Color(trendColor); + } + } + + // + // Cleanup Resources ... + tmpBar.Clean(); + } + + // + if (!has) + { + SpecifiedClean(pivots); + } + } + + // + // Cleanup Resources ... + SpecifiedClean(lows); + SpecifiedClean(highs); + } + + // + // Draw Pivots ... + has = HasChild(pivots); + if (has) + { + // + Copy( + pivots, + pvPivots // + ); + } + + // + // Cleanup Resources ... + SpecifiedClean(pivots); + } + + // + // ZigZag Trend Line ... + bool hasZGAnalysis = structure.zigzagAnalysis.IsValid(); + if (hasZGAnalysis) + { + // + // Support ... + XBoxZone supportBox; + has = structure.zigzagAnalysis.HasSupportBox(supportBox); + if (has) + { + // + supportBox.to = bar.time; + AddIfNotExists( + supportBox, + supports // + ); + } + + // + // Resistance ... + XBoxZone resistanceBox; + has = structure.zigzagAnalysis.HasResistanceBox(resistanceBox); + if (has) + { + // + resistanceBox.to = bar.time; + AddIfNotExists( + resistanceBox, + supports // + ); + } + + // + // Pivots ... + XPivot pivots[]; + count = poiDetector.ExtractZigZagPivots( + pivots, + barIndex, + 10 // + ); + has = IsValidSize(count); + + // + // Sort ... + Sort( + pivots, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + // Remove Newest ... + ArrayRemove( + pivots, + 0, + 1 // + ); + + // + // Check Trend ... + if (has) + { + // + XPivot highs[]; + int highsCount = ExtractPivots( + highs, + pivots, + X_PIVOT_TYPE_PEAK // + ); + Sort( + highs, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + XPivot lows[]; + int lowsCount = ExtractPivots( + lows, + pivots, + X_PIVOT_TYPE_VALE // + ); + Sort( + lows, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + // Check Highs and Lows ... + has = IsValidSize(lowsCount) && + IsValidSize(highsCount) && + lowsCount >= 2 && + highsCount >= 2; + if (has) + { + // + // Try to Get Market Strucutre ... + + // + bool hasLowerHigh = highs[0].value < highs[1].value; + bool hasLowerLow = lows[0].value < lows[1].value; + + // + bool hasHigherHigh = highs[0].value > highs[1].value; + bool hasHigherLow = lows[0].value > lows[1].value; + + // + zgTrend = + (hasHigherHigh && + hasHigherLow) + ? X_DIRECTION_BULLISH + : (hasLowerHigh && + hasLowerLow) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + has = HasDirection(zgTrend); + if (has) + { + // + // Select Swings for Trend Line ... + XOHCL tmpBar; + int llIDX = -1; + int hhIDX = -1; + datetime toTime = NULL; + datetime fromTime = NULL; + double toPrice = EMPTY_VALUE; + color trendColor = CLR_NONE; + double fromPrice = EMPTY_VALUE; + if (IsSpecifiedBullish(zgTrend)) + { + // + llIDX = GetLowest(lows); + hhIDX = GetHighest(lows); + + // + trendColor = clrAqua; + + // + toTime = lows[hhIDX].time; + toPrice = lows[hhIDX].value; + + // + fromTime = lows[llIDX].time; + fromPrice = lows[llIDX].value; + } + else + { + // + llIDX = GetLowest(highs); + hhIDX = GetHighest(highs); + + // + trendColor = clrMagenta; + + // + toTime = highs[llIDX].time; + toPrice = highs[llIDX].value; + + // + fromTime = highs[hhIDX].time; + fromPrice = highs[hhIDX].value; + } + + // + // Check Requirements for Trend ... + has = + NotEmptyZero(toPrice) && + NotEmptyZero(fromPrice) && + IsSpecifiedValid(toTime) && + IsSpecifiedValid(fromTime); + if (has) + { + // + has = poiDrawer.DrawTrendLine( + fromPrice, + fromTime, + toPrice, + toTime, + zgTrendLine, + zgTrendName, + true // Ray Right ... + ); + if (has) + { + zgTrendLine.Color(trendColor); + } + } + + // + // Cleanup Resources ... + tmpBar.Clean(); + } + + // + if (!has) + { + SpecifiedClean(pivots); + } + } + + // + // Cleanup Resources ... + SpecifiedClean(lows); + SpecifiedClean(highs); + } + + // + // Draw Pivots ... + has = HasChild(pivots); + if (has) + { + // + Copy( + pivots, + zgPivots // + ); + } + + // + // Cleanup Resources ... + SpecifiedClean(pivots); + } + + // + // Support ... + bool hasSupport = structure.support.IsValid(); + if (hasSupport) + { + // + AddIfNotExists( + structure.support, + supports // + ); + + // // + // XCBoxObject *iObj; + // has = fima2Signaller.poiDrawer.DrawBox( + // structure.support, + // iObj); + // if (has) + // { + // } + } + + // + // Resistance ... + bool hasResistance = structure.resistance.IsValid(); + if (hasResistance) + { + // + AddIfNotExists( + structure.resistance, + resistances // + ); + + // // + // XCBoxObject *iObj; + // has = fima2Signaller.poiDrawer.DrawBox( + // structure.resistance, + // iObj); + // if (has) + // { + // } + } + + // + // Validate Positions Support and Resistance Zone ... + int insideZoneIDX = -1; + has = has && + (isBullish + ? HasInside( + insideZoneIDX, + bar, + supports // + ) + : HasInside( + insideZoneIDX, + bar, + resistances // + )); + + // + // Validate Selected Inside Zone ... + // whith Bars Edge ... + has = IsValidIndex(insideZoneIDX); + if (has) + { + // + if (isBullish) + { + iZone = supports[insideZoneIDX]; + } + else + { + iZone = resistances[insideZoneIDX]; + } + + // + has = isBullish + ? bar.high > supports[insideZoneIDX].upper + : bar.low < resistances[insideZoneIDX].lower; + if (!has) + { + // + isBullish = false; + isBearish = false; + iDir = X_DIRECTION_NONE; + } + } + else + { + // + isBullish = false; + isBearish = false; + iDir = X_DIRECTION_NONE; + } + + // + // Checking Liquidities ... + + // + // Do all Draws Here ... + bool canDraw = false; + if (canDraw) + { + // + int iWidth = 2; + XPOIStyle iStyle; + XCBoxObject *iBoxObj = NULL; + color iClr = isBullish + ? clrYellow + : clrDarkOrange; + + // + // Supports ... + has = HasChild(supports); + if (has) + { + // + count = ArraySize(supports); + for (int i = 0; i < count; i++) + { + // + has = poiDrawer.DrawBox( + supports[i], + iBoxObj, + true, // Ignore At ... + supports[i].type // Name ... + ); + if (has) + { + // + poiDrawer.GetBoxStyle( + iStyle, + supports[i].dir // + ); + + // + poiDrawer.ApplyBoxStyle( + iBoxObj, + iStyle // + ); + } + + // + iStyle.Clean(); + ZeroMemory(iBoxObj); + } + } + + // + // Resistances ... + has = HasChild(resistances); + if (has) + { + // + count = ArraySize(resistances); + for (int i = 0; i < count; i++) + { + // + has = poiDrawer.DrawBox( + resistances[i], + iBoxObj, + true, // Ignore At ... + resistances[i].type // Name ... + ); + if (has) + { + // + poiDrawer.GetBoxStyle( + iStyle, + resistances[i].dir // + ); + + // + poiDrawer.ApplyBoxStyle( + iBoxObj, + iStyle // + ); + } + + // + iStyle.Clean(); + ZeroMemory(iBoxObj); + } + } + + // + // Selected Zone ... + has = iZone.IsValid(); + if (has) + { + // + has = poiDrawer.DrawBox( + iZone, + iBoxObj, + true, // Ignore At ... + iZone.type // Name ... + ); + if (has) + { + // + poiDrawer.GetBoxStyle( + iStyle, + iZone.dir // + ); + + // + iStyle.clr = iClr; + iStyle.width = iWidth; + + // + poiDrawer.ApplyBoxStyle( + iBoxObj, + iStyle // + ); + } + } + + // + // TrendLines ... + + // + // Pivots ... + + // + has = HasChild(pvPivots); + if (has) + { + // + CArrayObj *drawnPivots = new CArrayObj(); + count = poiDrawer.DrawPivots( + pvPivots, + drawnPivots // + ); + } + + // + has = HasChild(zgPivots); + if (has) + { + // + CArrayObj *drawnPivots = new CArrayObj(); + count = poiDrawer.DrawPivots( + zgPivots, + drawnPivots // + ); + } + + // + // Patterns Bar ... + has = HasDirection(iDir); + if (has) + { + // + int iCode = 159; + ENUM_ARROW_ANCHOR iAnchor = isBullish + ? ANCHOR_TOP + : ANCHOR_BOTTOM; + + // + XCBarArrowObject *iPatternObj; + has = poiDrawer.DrawBarArrow( + bar, + iPatternObj, + iPriceType, + iCode, + iClr, + iWidth, + iAnchor, + iName, + true, // Ignore Bar Tag ... + 10 // Threshold ... + ); + } + } + + // + // Check Signal Founded ... + has = HasDirection(iDir); + if (has) + { + // + // TODO: Provided SL ... + double _point = GetPoints(bar.symbol); + double slAddition = 5 * _point; + double slPrice = + isBullish + ? iZone.lower - slAddition + : iZone.upper + slAddition; + + // + // Prepare Founded Signal ... + XTarget targets[]; + has = PrepareSignal( + signal, + iDir, + targets, + 0, // Use Default R2R ... + slPrice, // Provided Price for SL ... + 0 // Specified Risk in Point .... + ); + if (has) + { + // + // Notify On Signal Event ... + NotifySignalEventListeners(signal); + } + } + + // + // Cleanup Resources ... + bar.Clean(); + iZone.Clean(); + signal.Clean(); + structure.Clean(); + fimaConditions.Clean(); + SpecifiedClean(pvPivots); + SpecifiedClean(zgPivots); + SpecifiedClean(supports); + SpecifiedClean(resistances); + } + + /** + * Processing New Bar ... + * + * @param barIndex: int, Specified Bar Index ... + */ + void ProcessNewBarNKP1(int barIndex = 0) + { + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + // Update Helper ... + fimaHelper.Update(barIndex); + + // + XOHCL bar; + XSignal signal; + XBoxZone iZone; + int count = 0; + bool has = false; + int cIdx = 0; + int pIdx = cIdx + 1; + string iName = NULL; + XBoxZone supports[]; + XBoxZone resistances[]; + bool isBullish = false; + bool isBearish = false; + double iPrice = EMPTY_VALUE; + double iPriceEdge = EMPTY_VALUE; + XFIMAMarketStructure structure; + XFIMAConditions fimaConditions; + ENUM_X_PRICE iPriceType = X_PRICE_NONE; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + ENUM_X_PRICE iPriceEdgeType = X_PRICE_NONE; + + // + XPivot pvPivots[]; + string pvTrendName = "XXIFMA2PVTrend"; + CChartObjectTrend *pvTrendLine = NULL; + ENUM_X_DIRECTION pvTrend = X_DIRECTION_NONE; + + // + XPivot zgPivots[]; + string zgTrendName = "XFIMA2ZGTrend"; + CChartObjectTrend *zgTrendLine = NULL; + ENUM_X_DIRECTION zgTrend = X_DIRECTION_NONE; + + // + // Initialize Bar as CBar ... + has = bar.Init( + symbol, + period, + barIndex // + ); + if (!has) + { + // + bar.Clean(); + return; + } + + // + // Retrieve Conditions ... + has = fimaHelper.GetConditions( + fimaConditions, + barIndex, + 10 // Loopback ... + ); + if (!has) + { + // + bar.Clean(); + fimaConditions.Clean(); + + // + return; + } + + // + // Analyse Market ... + poiDetector.AnalyseMarket( + bar, + structure, + analyserConfig // + ); + + // + // Collect Support and Resistance Zones and Validate by them ... + + // + // PV Trend Line ... + bool hasPVAnalysis = structure.pvAnalysis.IsValid(); + if (hasPVAnalysis) + { + // + // Support ... + XBoxZone supportBox; + has = structure.pvAnalysis.HasSupportBox(supportBox); + if (has) + { + // + supportBox.to = bar.time; + AddIfNotExists( + supportBox, + supports // + ); + } + + // + // Resistance ... + XBoxZone resistanceBox; + has = structure.pvAnalysis.HasResistanceBox(resistanceBox); + if (has) + { + // + resistanceBox.to = bar.time; + AddIfNotExists( + resistanceBox, + supports // + ); + } + + // + // Pivots ... + XPivot pivots[]; + count = poiDetector.ExtractPVPivots( + pivots, + barIndex, + 50 // + ); + has = IsValidSize(count); + + // + // Sort ... + Sort( + pivots, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + // Remove Newest ... + ArrayRemove( + pivots, + 0, + 1 // + ); + + // + // Check Trend ... + if (has) + { + // + XPivot highs[]; + int highsCount = ExtractPivots( + highs, + pivots, + X_PIVOT_TYPE_PEAK // + ); + Sort( + highs, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + XPivot lows[]; + int lowsCount = ExtractPivots( + lows, + pivots, + X_PIVOT_TYPE_VALE // + ); + Sort( + lows, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + // Check Highs and Lows ... + has = IsValidSize(lowsCount) && + IsValidSize(highsCount) && + lowsCount >= 2 && + highsCount >= 2; + if (has) + { + // + // Try to Get Market Strucutre ... + + // + bool hasLowerHigh = highs[0].value < highs[1].value; + bool hasLowerLow = lows[0].value < lows[1].value; + + // + bool hasHigherHigh = highs[0].value > highs[1].value; + bool hasHigherLow = lows[0].value > lows[1].value; + + // + pvTrend = + (hasHigherHigh && + hasHigherLow) + ? X_DIRECTION_BULLISH + : (hasLowerHigh && + hasLowerLow) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + has = HasDirection(pvTrend); + if (has) + { + // + // Select Swings for Trend Line ... + XOHCL tmpBar; + int llIDX = -1; + int hhIDX = -1; + datetime toTime = NULL; + datetime fromTime = NULL; + double toPrice = EMPTY_VALUE; + color trendColor = CLR_NONE; + double fromPrice = EMPTY_VALUE; + if (IsSpecifiedBullish(pvTrend)) + { + // + llIDX = GetLowest(lows); + hhIDX = GetHighest(lows); + + // + trendColor = clrAqua; + + // + toTime = lows[hhIDX].time; + toPrice = lows[hhIDX].value; + + // + fromTime = lows[llIDX].time; + fromPrice = lows[llIDX].value; + } + else + { + // + llIDX = GetLowest(highs); + hhIDX = GetHighest(highs); + + // + trendColor = clrMagenta; + + // + toTime = highs[llIDX].time; + toPrice = highs[llIDX].value; + + // + fromTime = highs[hhIDX].time; + fromPrice = highs[hhIDX].value; + } + + // + // Check Requirements for Trend ... + has = + NotEmptyZero(toPrice) && + NotEmptyZero(fromPrice) && + IsSpecifiedValid(toTime) && + IsSpecifiedValid(fromTime); + if (has) + { + // + has = poiDrawer.DrawTrendLine( + fromPrice, + fromTime, + toPrice, + toTime, + pvTrendLine, + pvTrendName, + true // Ray Right ... + ); + if (has) + { + pvTrendLine.Color(trendColor); + } + } + + // + // Cleanup Resources ... + tmpBar.Clean(); + } + + // + if (!has) + { + SpecifiedClean(pivots); + } + } + + // + // Cleanup Resources ... + SpecifiedClean(lows); + SpecifiedClean(highs); + } + + // + // Draw Pivots ... + has = HasChild(pivots); + if (has) + { + // + Copy( + pivots, + pvPivots // + ); + } + + // + // Cleanup Resources ... + SpecifiedClean(pivots); + } + + // + // ZigZag Trend Line ... + bool hasZGAnalysis = structure.zigzagAnalysis.IsValid(); + if (hasZGAnalysis) + { + // + // Support ... + XBoxZone supportBox; + has = structure.zigzagAnalysis.HasSupportBox(supportBox); + if (has) + { + // + supportBox.to = bar.time; + AddIfNotExists( + supportBox, + supports // + ); + } + + // + // Resistance ... + XBoxZone resistanceBox; + has = structure.zigzagAnalysis.HasResistanceBox(resistanceBox); + if (has) + { + // + resistanceBox.to = bar.time; + AddIfNotExists( + resistanceBox, + supports // + ); + } + + // + // Pivots ... + XPivot pivots[]; + count = poiDetector.ExtractZigZagPivots( + pivots, + barIndex, + 10 // + ); + has = IsValidSize(count); + + // + // Sort ... + Sort( + pivots, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + // Remove Newest ... + ArrayRemove( + pivots, + 0, + 1 // + ); + + // + // Check Trend ... + if (has) + { + // + XPivot highs[]; + int highsCount = ExtractPivots( + highs, + pivots, + X_PIVOT_TYPE_PEAK // + ); + Sort( + highs, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + XPivot lows[]; + int lowsCount = ExtractPivots( + lows, + pivots, + X_PIVOT_TYPE_VALE // + ); + Sort( + lows, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + // Check Highs and Lows ... + has = IsValidSize(lowsCount) && + IsValidSize(highsCount) && + lowsCount >= 2 && + highsCount >= 2; + if (has) + { + // + // Try to Get Market Strucutre ... + + // + bool hasLowerHigh = highs[0].value < highs[1].value; + bool hasLowerLow = lows[0].value < lows[1].value; + + // + bool hasHigherHigh = highs[0].value > highs[1].value; + bool hasHigherLow = lows[0].value > lows[1].value; + + // + zgTrend = + (hasHigherHigh && + hasHigherLow) + ? X_DIRECTION_BULLISH + : (hasLowerHigh && + hasLowerLow) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + has = HasDirection(zgTrend); + if (has) + { + // + // Select Swings for Trend Line ... + XOHCL tmpBar; + int llIDX = -1; + int hhIDX = -1; + datetime toTime = NULL; + datetime fromTime = NULL; + double toPrice = EMPTY_VALUE; + color trendColor = CLR_NONE; + double fromPrice = EMPTY_VALUE; + if (IsSpecifiedBullish(zgTrend)) + { + // + llIDX = GetLowest(lows); + hhIDX = GetHighest(lows); + + // + trendColor = clrAqua; + + // + toTime = lows[hhIDX].time; + toPrice = lows[hhIDX].value; + + // + fromTime = lows[llIDX].time; + fromPrice = lows[llIDX].value; + } + else + { + // + llIDX = GetLowest(highs); + hhIDX = GetHighest(highs); + + // + trendColor = clrMagenta; + + // + toTime = highs[llIDX].time; + toPrice = highs[llIDX].value; + + // + fromTime = highs[hhIDX].time; + fromPrice = highs[hhIDX].value; + } + + // + // Check Requirements for Trend ... + has = + NotEmptyZero(toPrice) && + NotEmptyZero(fromPrice) && + IsSpecifiedValid(toTime) && + IsSpecifiedValid(fromTime); + if (has) + { + // + has = poiDrawer.DrawTrendLine( + fromPrice, + fromTime, + toPrice, + toTime, + zgTrendLine, + zgTrendName, + true // Ray Right ... + ); + if (has) + { + zgTrendLine.Color(trendColor); + } + } + + // + // Cleanup Resources ... + tmpBar.Clean(); + } + + // + if (!has) + { + SpecifiedClean(pivots); + } + } + + // + // Cleanup Resources ... + SpecifiedClean(lows); + SpecifiedClean(highs); + } + + // + // Draw Pivots ... + has = HasChild(pivots); + if (has) + { + // + Copy( + pivots, + zgPivots // + ); + } + + // + // Cleanup Resources ... + SpecifiedClean(pivots); + } + + // + // Support ... + bool hasSupport = structure.support.IsValid(); + if (hasSupport) + { + // + AddIfNotExists( + structure.support, + supports // + ); + } + + // + // Resistance ... + bool hasResistance = structure.resistance.IsValid(); + if (hasResistance) + { + // + AddIfNotExists( + structure.resistance, + resistances // + ); + } + + // + // Check Required Pattern Exists ... + bool hasPinnedBar = HasDirection(structure.pinnedDir); + bool hasEngulfedBar = HasDirection(structure.engulfedDir); + bool hasFlagPattern = HasDirection(structure.flagPatternDir); + bool hasStarPattern = HasDirection(structure.starPatternDir); + bool hasRisingPattern = HasDirection(structure.risingPatternDir); + bool hasPiercingPattern = HasDirection(structure.piercingPatternDir); + bool hasSignalKeyBar = HasDirection(structure.signalKeyBarPatternDir); + + // + // Check Bar Pattern Exists ... + // and Select Pattern Direction and Price and Price Type ... + has = hasPinnedBar || + hasEngulfedBar || + hasFlagPattern || + hasStarPattern || + hasSignalKeyBar || + hasRisingPattern || + hasPiercingPattern; + if (has) + { + // + if (hasPinnedBar) + { + // + iDir = structure.pinnedDir; + iName = "XPinned_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasEngulfedBar) + { + // + iDir = structure.engulfedDir; + iName = "XEngulfed_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasFlagPattern) + { + // + iDir = structure.flagPatternDir; + iName = "XFlag_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasStarPattern) + { + // + iDir = structure.starPatternDir; + iName = "XStar_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasSignalKeyBar) + { + // + iDir = structure.risingPatternDir; + iName = "XRising_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasRisingPattern) + { + // + iDir = structure.piercingPatternDir; + iName = "XPiercing_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasPiercingPattern) + { + // + iDir = structure.signalKeyBarPatternDir; + iName = "XSignalKey_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + + // + isBullish = IsSpecifiedBullish(iDir); + isBearish = IsSpecifiedBearish(iDir); + + // + // Retrieve Price Type for Validate ... + iPriceType = isBullish + ? X_PRICE_DOWN + : X_PRICE_UP; + iPriceEdgeType = isBullish + ? X_PRICE_LOW + : X_PRICE_HIGH; + + // + iPrice = bar.GetPrice(iPriceType); + iPriceEdge = bar.GetPrice(iPriceEdgeType); + + // + // Validate Calculations ... + has = HasDirection(iDir) && + (isBullish || + isBearish) && + NotEmptyZero(iPrice) && + NotEmptyZero(iPriceEdge) && + iPrice != iPriceEdge; + if (!has) + { + // + isBullish = false; + isBearish = false; + iDir = X_DIRECTION_NONE; + } + } + + // + // Check Petterns Happens ... + // Chekc Bullish or Bearish Starter Conditions Exists ... + has = HasDirection(iDir); + if (has) + { + // + // Do Conditions Validating ... + + // + // Retrieve MA Band for Validation ... + double iMABandUpper = fimaConditions.maBandUpperBuffer[cIdx]; + double iMABandLower = fimaConditions.maBandLowerBuffer[cIdx]; + + // + // Validate ... + + // + // Validate by Edge Price ... + has = isBullish + ? iPriceEdge < iMABandLower + : iPriceEdge > iMABandUpper; + + // + // Validate by Body Price ... + // has = isBullish + // ? iPrice < iMABandLower + // : iPrice > iMABandUpper; + if (!has) + { + // + isBullish = false; + isBearish = false; + iDir = X_DIRECTION_NONE; + } + } + + // + // Validate ... + // Detect Support and Resistances ... + // and Validate Price based on it's ... + has = HasDirection(iDir); + if (has) + { + // + // Validate Positions Support and Resistance Zone ... + int insideZoneIDX = -1; + has = has && + (isBullish + ? HasInside( + insideZoneIDX, + bar, + supports // + ) + : HasInside( + insideZoneIDX, + bar, + resistances // + )); + + // + // Validate Selected Inside Zone ... + // whith Bars Edge ... + has = IsValidIndex(insideZoneIDX); + if (has) + { + // + if (isBullish) + { + iZone = supports[insideZoneIDX]; + } + else + { + iZone = resistances[insideZoneIDX]; + } + + // + has = isBullish + ? bar.high > supports[insideZoneIDX].upper + : bar.low < resistances[insideZoneIDX].lower; + if (!has) + { + // + isBullish = false; + isBearish = false; + iDir = X_DIRECTION_NONE; + } + } + else + { + // + isBullish = false; + isBearish = false; + iDir = X_DIRECTION_NONE; + } + } + + // + // Checking Liquidities ... + + // + // Do all Draws Here ... + bool canDraw = true; + if (canDraw) + { + // + int iWidth = 2; + XPOIStyle iStyle; + XCBoxObject *iBoxObj = NULL; + color iClr = isBullish + ? clrYellow + : clrDarkOrange; + + // + // Supports ... + has = HasChild(supports); + if (has) + { + // + count = ArraySize(supports); + for (int i = 0; i < count; i++) + { + // + has = poiDrawer.DrawBox( + supports[i], + iBoxObj, + true, // Ignore At ... + supports[i].type // Name ... + ); + if (has) + { + // + poiDrawer.GetBoxStyle( + iStyle, + supports[i].dir // + ); + + // + poiDrawer.ApplyBoxStyle( + iBoxObj, + iStyle // + ); + } + + // + iStyle.Clean(); + ZeroMemory(iBoxObj); + } + } + + // + // Resistances ... + has = HasChild(resistances); + if (has) + { + // + count = ArraySize(resistances); + for (int i = 0; i < count; i++) + { + // + has = poiDrawer.DrawBox( + resistances[i], + iBoxObj, + true, // Ignore At ... + resistances[i].type // Name ... + ); + if (has) + { + // + poiDrawer.GetBoxStyle( + iStyle, + resistances[i].dir // + ); + + // + poiDrawer.ApplyBoxStyle( + iBoxObj, + iStyle // + ); + } + + // + iStyle.Clean(); + ZeroMemory(iBoxObj); + } + } + + // + // Selected Zone ... + has = iZone.IsValid(); + if (has) + { + // + has = poiDrawer.DrawBox( + iZone, + iBoxObj, + true, // Ignore At ... + iZone.type // Name ... + ); + if (has) + { + // + poiDrawer.GetBoxStyle( + iStyle, + iZone.dir // + ); + + // + iStyle.clr = iClr; + iStyle.width = iWidth; + + // + poiDrawer.ApplyBoxStyle( + iBoxObj, + iStyle // + ); + } + } + + // + // TrendLines ... + + // + // Pivots ... + + // + has = HasChild(pvPivots); + if (has) + { + // + CArrayObj *drawnPivots = new CArrayObj(); + count = poiDrawer.DrawPivots( + pvPivots, + drawnPivots // + ); + } + + // + has = HasChild(zgPivots); + if (has) + { + // + CArrayObj *drawnPivots = new CArrayObj(); + count = poiDrawer.DrawPivots( + zgPivots, + drawnPivots // + ); + } + + // + // Patterns Bar ... + has = HasDirection(iDir); + if (has) + { + // + int iCode = 159; + ENUM_ARROW_ANCHOR iAnchor = isBullish + ? ANCHOR_TOP + : ANCHOR_BOTTOM; + + // + XCBarArrowObject *iPatternObj; + has = poiDrawer.DrawBarArrow( + bar, + iPatternObj, + iPriceType, + iCode, + iClr, + iWidth, + iAnchor, + iName, + true, // Ignore Bar Tag ... + 10 // Threshold ... + ); + } + } + + // + // Check Signal Founded ... + has = HasDirection(iDir); + + // + if (has) + { + Print("a Valid ", ToXString(iDir), " Pattern Exists ..."); + } + + // + if (has) + { + // + // TODO: Provided SL ... + double _point = GetPoints(bar.symbol); + double slAddition = 5 * _point; + double slPrice = + isBullish + ? iZone.lower - slAddition + : iZone.upper + slAddition; + + // + // Prepare Founded Signal ... + XTarget targets[]; + has = PrepareSignal( + signal, + iDir, + targets, + 0, // Use Default R2R ... + slPrice, // Provided Price for SL ... + 0 // Specified Risk in Point .... + ); + if (has) + { + // + // Notify On Signal Event ... + NotifySignalEventListeners(signal); + } + } + + // + // Cleanup Resources ... + bar.Clean(); + iZone.Clean(); + signal.Clean(); + structure.Clean(); + fimaConditions.Clean(); + SpecifiedClean(pvPivots); + SpecifiedClean(zgPivots); + SpecifiedClean(supports); + SpecifiedClean(resistances); + } + + /** + * Processing New Bar ... + * + * @param barIndex: int, Specified Bar Index ... + */ + virtual void ProcessNewBar(int barIndex = 0) + { + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + // Update Helper ... + fimaHelper.Update(barIndex); + + // + XOHCL bar; + XSignal signal; + XBoxZone iZone; + int count = 0; + bool has = false; + int cIdx = 0; + int pIdx = cIdx + 1; + string iName = NULL; + XBoxZone supports[]; + XBoxZone resistances[]; + bool isBullish = false; + bool isBearish = false; + double iPrice = EMPTY_VALUE; + double iPriceEdge = EMPTY_VALUE; + XFIMAMarketStructure structure; + XFIMAConditions fimaConditions; + ENUM_X_PRICE iPriceType = X_PRICE_NONE; + ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + ENUM_X_PRICE iPriceEdgeType = X_PRICE_NONE; + + // + XPivot pvPivots[]; + string pvTrendName = "XXIFMA2PVTrend"; + CChartObjectTrend *pvTrendLine = NULL; + ENUM_X_DIRECTION pvTrend = X_DIRECTION_NONE; + + // + XPivot zgPivots[]; + string zgTrendName = "XFIMA2ZGTrend"; + CChartObjectTrend *zgTrendLine = NULL; + ENUM_X_DIRECTION zgTrend = X_DIRECTION_NONE; + + // + // Initialize Bar as CBar ... + has = bar.Init( + symbol, + period, + barIndex // + ); + if (!has) + { + // + bar.Clean(); + return; + } + + // + // Retrieve Conditions ... + has = fimaHelper.GetConditions( + fimaConditions, + barIndex, + 10 // Loopback ... + ); + if (!has) + { + // + bar.Clean(); + fimaConditions.Clean(); + + // + return; + } + + // + // Analyse Market ... + poiDetector.AnalyseMarket( + bar, + structure, + analyserConfig // + ); + + // + // Collect Support and Resistance Zones and Validate by them ... + + // + // PV Trend Line ... + bool hasPVAnalysis = structure.pvAnalysis.IsValid(); + if (hasPVAnalysis) + { + // + // Support ... + XBoxZone supportBox; + has = structure.pvAnalysis.HasSupportBox(supportBox); + if (has) + { + // + supportBox.to = bar.time; + AddIfNotExists( + supportBox, + supports // + ); + } + + // + // Resistance ... + XBoxZone resistanceBox; + has = structure.pvAnalysis.HasResistanceBox(resistanceBox); + if (has) + { + // + resistanceBox.to = bar.time; + AddIfNotExists( + resistanceBox, + supports // + ); + } + + // + // Pivots ... + XPivot pivots[]; + count = poiDetector.ExtractPVPivots( + pivots, + barIndex, + 50 // + ); + has = IsValidSize(count); + + // + // Sort ... + Sort( + pivots, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + // Remove Newest ... + ArrayRemove( + pivots, + 0, + 1 // + ); + + // + // Check Trend ... + if (has) + { + // + XPivot highs[]; + int highsCount = ExtractPivots( + highs, + pivots, + X_PIVOT_TYPE_PEAK // + ); + Sort( + highs, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + XPivot lows[]; + int lowsCount = ExtractPivots( + lows, + pivots, + X_PIVOT_TYPE_VALE // + ); + Sort( + lows, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + // Check Highs and Lows ... + has = IsValidSize(lowsCount) && + IsValidSize(highsCount) && + lowsCount >= 2 && + highsCount >= 2; + if (has) + { + // + // Try to Get Market Strucutre ... + + // + bool hasLowerHigh = highs[0].value < highs[1].value; + bool hasLowerLow = lows[0].value < lows[1].value; + + // + bool hasHigherHigh = highs[0].value > highs[1].value; + bool hasHigherLow = lows[0].value > lows[1].value; + + // + pvTrend = + (hasHigherHigh && + hasHigherLow) + ? X_DIRECTION_BULLISH + : (hasLowerHigh && + hasLowerLow) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + has = HasDirection(pvTrend); + if (has) + { + // + // Select Swings for Trend Line ... + XOHCL tmpBar; + int llIDX = -1; + int hhIDX = -1; + datetime toTime = NULL; + datetime fromTime = NULL; + double toPrice = EMPTY_VALUE; + color trendColor = CLR_NONE; + double fromPrice = EMPTY_VALUE; + if (IsSpecifiedBullish(pvTrend)) + { + // + llIDX = GetLowest(lows); + hhIDX = GetHighest(lows); + + // + trendColor = clrAqua; + + // + toTime = lows[hhIDX].time; + toPrice = lows[hhIDX].value; + + // + fromTime = lows[llIDX].time; + fromPrice = lows[llIDX].value; + } + else + { + // + llIDX = GetLowest(highs); + hhIDX = GetHighest(highs); + + // + trendColor = clrMagenta; + + // + toTime = highs[llIDX].time; + toPrice = highs[llIDX].value; + + // + fromTime = highs[hhIDX].time; + fromPrice = highs[hhIDX].value; + } + + // + // Check Requirements for Trend ... + has = + NotEmptyZero(toPrice) && + NotEmptyZero(fromPrice) && + IsSpecifiedValid(toTime) && + IsSpecifiedValid(fromTime); + if (has) + { + // + has = poiDrawer.DrawTrendLine( + fromPrice, + fromTime, + toPrice, + toTime, + pvTrendLine, + pvTrendName, + true // Ray Right ... + ); + if (has) + { + pvTrendLine.Color(trendColor); + } + } + + // + // Cleanup Resources ... + tmpBar.Clean(); + } + + // + if (!has) + { + SpecifiedClean(pivots); + } + } + + // + // Cleanup Resources ... + SpecifiedClean(lows); + SpecifiedClean(highs); + } + + // + // Draw Pivots ... + has = HasChild(pivots); + if (has) + { + // + Copy( + pivots, + pvPivots // + ); + } + + // + // Cleanup Resources ... + SpecifiedClean(pivots); + } + + // + // ZigZag Trend Line ... + bool hasZGAnalysis = structure.zigzagAnalysis.IsValid(); + if (hasZGAnalysis) + { + // + // Support ... + XBoxZone supportBox; + has = structure.zigzagAnalysis.HasSupportBox(supportBox); + if (has) + { + // + supportBox.to = bar.time; + AddIfNotExists( + supportBox, + supports // + ); + } + + // + // Resistance ... + XBoxZone resistanceBox; + has = structure.zigzagAnalysis.HasResistanceBox(resistanceBox); + if (has) + { + // + resistanceBox.to = bar.time; + AddIfNotExists( + resistanceBox, + supports // + ); + } + + // + // Pivots ... + XPivot pivots[]; + count = poiDetector.ExtractZigZagPivots( + pivots, + barIndex, + 10 // + ); + has = IsValidSize(count); + + // + // Sort ... + Sort( + pivots, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + // Remove Newest ... + ArrayRemove( + pivots, + 0, + 1 // + ); + + // + // Check Trend ... + if (has) + { + // + XPivot highs[]; + int highsCount = ExtractPivots( + highs, + pivots, + X_PIVOT_TYPE_PEAK // + ); + Sort( + highs, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + XPivot lows[]; + int lowsCount = ExtractPivots( + lows, + pivots, + X_PIVOT_TYPE_VALE // + ); + Sort( + lows, + X_SORT_BY_DATE, + X_DIRECTION_BEARISH // + ); + + // + // Check Highs and Lows ... + has = IsValidSize(lowsCount) && + IsValidSize(highsCount) && + lowsCount >= 2 && + highsCount >= 2; + if (has) + { + // + // Try to Get Market Strucutre ... + + // + bool hasLowerHigh = highs[0].value < highs[1].value; + bool hasLowerLow = lows[0].value < lows[1].value; + + // + bool hasHigherHigh = highs[0].value > highs[1].value; + bool hasHigherLow = lows[0].value > lows[1].value; + + // + zgTrend = + (hasHigherHigh && + hasHigherLow) + ? X_DIRECTION_BULLISH + : (hasLowerHigh && + hasLowerLow) + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + has = HasDirection(zgTrend); + if (has) + { + // + // Select Swings for Trend Line ... + XOHCL tmpBar; + int llIDX = -1; + int hhIDX = -1; + datetime toTime = NULL; + datetime fromTime = NULL; + double toPrice = EMPTY_VALUE; + color trendColor = CLR_NONE; + double fromPrice = EMPTY_VALUE; + if (IsSpecifiedBullish(zgTrend)) + { + // + llIDX = GetLowest(lows); + hhIDX = GetHighest(lows); + + // + trendColor = clrAqua; + + // + toTime = lows[hhIDX].time; + toPrice = lows[hhIDX].value; + + // + fromTime = lows[llIDX].time; + fromPrice = lows[llIDX].value; + } + else + { + // + llIDX = GetLowest(highs); + hhIDX = GetHighest(highs); + + // + trendColor = clrMagenta; + + // + toTime = highs[llIDX].time; + toPrice = highs[llIDX].value; + + // + fromTime = highs[hhIDX].time; + fromPrice = highs[hhIDX].value; + } + + // + // Check Requirements for Trend ... + has = + NotEmptyZero(toPrice) && + NotEmptyZero(fromPrice) && + IsSpecifiedValid(toTime) && + IsSpecifiedValid(fromTime); + if (has) + { + // + has = poiDrawer.DrawTrendLine( + fromPrice, + fromTime, + toPrice, + toTime, + zgTrendLine, + zgTrendName, + true // Ray Right ... + ); + if (has) + { + zgTrendLine.Color(trendColor); + } + } + + // + // Cleanup Resources ... + tmpBar.Clean(); + } + + // + if (!has) + { + SpecifiedClean(pivots); + } + } + + // + // Cleanup Resources ... + SpecifiedClean(lows); + SpecifiedClean(highs); + } + + // + // Draw Pivots ... + has = HasChild(pivots); + if (has) + { + // + Copy( + pivots, + zgPivots // + ); + } + + // + // Cleanup Resources ... + SpecifiedClean(pivots); + } + + // + // Support ... + bool hasSupport = structure.support.IsValid(); + if (hasSupport) + { + // + AddIfNotExists( + structure.support, + supports // + ); + } + + // + // Resistance ... + bool hasResistance = structure.resistance.IsValid(); + if (hasResistance) + { + // + AddIfNotExists( + structure.resistance, + resistances // + ); + } + + // + // Check Required Pattern Exists ... + bool hasPinnedBar = HasDirection(structure.pinnedDir); + bool hasEngulfedBar = HasDirection(structure.engulfedDir); + bool hasFlagPattern = HasDirection(structure.flagPatternDir); + bool hasStarPattern = HasDirection(structure.starPatternDir); + bool hasRisingPattern = HasDirection(structure.risingPatternDir); + bool hasPiercingPattern = HasDirection(structure.piercingPatternDir); + bool hasSignalKeyBar = HasDirection(structure.signalKeyBarPatternDir); + + // + // Check Bar Pattern Exists ... + // and Select Pattern Direction and Price and Price Type ... + has = hasPinnedBar || + hasEngulfedBar || + hasFlagPattern || + hasStarPattern || + hasSignalKeyBar || + hasRisingPattern || + hasPiercingPattern; + if (has) + { + // + if (hasPinnedBar) + { + // + iDir = structure.pinnedDir; + iName = "XPinned_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasEngulfedBar) + { + // + iDir = structure.engulfedDir; + iName = "XEngulfed_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasFlagPattern) + { + // + iDir = structure.flagPatternDir; + iName = "XFlag_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasStarPattern) + { + // + iDir = structure.starPatternDir; + iName = "XStar_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasSignalKeyBar) + { + // + iDir = structure.risingPatternDir; + iName = "XRising_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasRisingPattern) + { + // + iDir = structure.piercingPatternDir; + iName = "XPiercing_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasPiercingPattern) + { + // + iDir = structure.signalKeyBarPatternDir; + iName = "XSignalKey_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + + // + isBullish = IsSpecifiedBullish(iDir); + isBearish = IsSpecifiedBearish(iDir); + + // + // Retrieve Price Type for Validate ... + iPriceType = isBullish + ? X_PRICE_DOWN + : X_PRICE_UP; + iPriceEdgeType = isBullish + ? X_PRICE_LOW + : X_PRICE_HIGH; + + // + iPrice = bar.GetPrice(iPriceType); + iPriceEdge = bar.GetPrice(iPriceEdgeType); + + // + // Validate Calculations ... + has = HasDirection(iDir) && + (isBullish || + isBearish) && + NotEmptyZero(iPrice) && + NotEmptyZero(iPriceEdge) && + iPrice != iPriceEdge; + if (!has) + { + // + isBullish = false; + isBearish = false; + iDir = X_DIRECTION_NONE; + } + } + + // + // Strategy 1 ... + has = Strategy1HasSignal( + bar, + iZone, + iName, + supports, + resistances, + iDir, + fimaConditions, + structure // + ); + + // + // Do all Draws Here ... + bool canDraw = true; + if (canDraw && has) + { + // + int iWidth = 2; + XPOIStyle iStyle; + XCBoxObject *iBoxObj = NULL; + color iClr = isBullish + ? clrYellow + : clrDarkOrange; + + // + // Supports ... + has = HasChild(supports); + if (has) + { + // + count = ArraySize(supports); + for (int i = 0; i < count; i++) + { + // + has = poiDrawer.DrawBox( + supports[i], + iBoxObj, + true, // Ignore At ... + supports[i].type // Name ... + ); + if (has) + { + // + poiDrawer.GetBoxStyle( + iStyle, + supports[i].dir // + ); + + // + poiDrawer.ApplyBoxStyle( + iBoxObj, + iStyle // + ); + } + + // + iStyle.Clean(); + ZeroMemory(iBoxObj); + } + } + + // + // Resistances ... + has = HasChild(resistances); + if (has) + { + // + count = ArraySize(resistances); + for (int i = 0; i < count; i++) + { + // + has = poiDrawer.DrawBox( + resistances[i], + iBoxObj, + true, // Ignore At ... + resistances[i].type // Name ... + ); + if (has) + { + // + poiDrawer.GetBoxStyle( + iStyle, + resistances[i].dir // + ); + + // + poiDrawer.ApplyBoxStyle( + iBoxObj, + iStyle // + ); + } + + // + iStyle.Clean(); + ZeroMemory(iBoxObj); + } + } + + // + // Selected Zone ... + has = iZone.IsValid(); + if (has) + { + // + has = poiDrawer.DrawBox( + iZone, + iBoxObj, + true, // Ignore At ... + iZone.type // Name ... + ); + if (has) + { + // + poiDrawer.GetBoxStyle( + iStyle, + iZone.dir // + ); + + // + iStyle.clr = iClr; + iStyle.width = iWidth; + + // + poiDrawer.ApplyBoxStyle( + iBoxObj, + iStyle // + ); + } + } + + // + // TrendLines ... + + // + // Pivots ... + + // + has = HasChild(pvPivots); + if (has) + { + // + CArrayObj *drawnPivots = new CArrayObj(); + count = poiDrawer.DrawPivots( + pvPivots, + drawnPivots // + ); + } + + // + has = HasChild(zgPivots); + if (has) + { + // + CArrayObj *drawnPivots = new CArrayObj(); + count = poiDrawer.DrawPivots( + zgPivots, + drawnPivots // + ); + } + + // + // Patterns Bar ... + has = HasDirection(iDir); + if (has) + { + // + int iCode = 159; + ENUM_ARROW_ANCHOR iAnchor = isBullish + ? ANCHOR_TOP + : ANCHOR_BOTTOM; + + // + XCBarArrowObject *iPatternObj; + has = poiDrawer.DrawBarArrow( + bar, + iPatternObj, + iPriceType, + iCode, + iClr, + iWidth, + iAnchor, + iName, + true, // Ignore Bar Tag ... + 10 // Threshold ... + ); + } + } + + // + if (has) + { + Print("a Valid ", ToXString(iDir), " Pattern Exists ..."); + } + + // + if (has) + { + // + // TODO: Provided SL ... + double _point = GetPoints(bar.symbol); + double slAddition = 5 * _point; + double slPrice = + isBullish + ? iZone.lower - slAddition + : iZone.upper + slAddition; + + // + // Prepare Founded Signal ... + XTarget targets[]; + has = PrepareSignal( + signal, + iDir, + targets, + 0, // Use Default R2R ... + slPrice, // Provided Price for SL ... + 0 // Specified Risk in Point .... + ); + if (has) + { + // + // Notify On Signal Event ... + NotifySignalEventListeners(signal); + } + } + + // + // Cleanup Resources ... + bar.Clean(); + iZone.Clean(); + signal.Clean(); + structure.Clean(); + fimaConditions.Clean(); + SpecifiedClean(pvPivots); + SpecifiedClean(zgPivots); + SpecifiedClean(supports); + SpecifiedClean(resistances); + } + + /** + * Check Guards Based on MarketConditions ... + * + * @param guards: XGuard[] + * @param barIndex: int + * + * @return ( int ) + */ + int virtual CheckForGuard( + XGuard &guards[], + int barIndex = 0 // + ) + { + // + int result = 0; + + // + SpecifiedClean(guards); + + // + result = ArraySize(guards); + + // + return result; + } + + // + // Private ... + private: + // + // Props ... + + // + // Implementing Strategies ... + + /** + * Validate a Pattern based on MA Band ... + * + * @param bar: XOHCL, reference to Pattern Bar ... + * @param patternName: string, detected pattern's name ... + * @param patternDir: ENUM_X_DIRECTION, detected pattern's direction ... + * @param fimaConditions: XFIMAConditions, reference to Bar Specified XFIMA Conditions ... + * + * @return ( bool ) + */ + bool ValidatePatternBasedOnMABand( + XOHCL &bar, + string patternName, + ENUM_X_DIRECTION patternDir, + XFIMAConditions &fimaConditions // + ) + { + // + bool result = false; + + // + // Validate ... + result = bar.IsValid() && + IsXValid(patternName) && + HasDirection(patternDir) && + fimaConditions.IsValid(); + if (!result) + { + return result; + } + + // + // Define Requirements ... + bool isBullish = false; + bool isBearish = false; + double iPrice = EMPTY_VALUE; + double iPriceEdge = EMPTY_VALUE; + ENUM_X_PRICE iPriceType = X_PRICE_NONE; + ENUM_X_PRICE iPriceEdgeType = X_PRICE_NONE; + + // + // Calculating Price and Price Types ... + + // + isBullish = IsXBullish(patternDir); + isBearish = IsXBearish(patternDir); + + // + iPriceType = isBullish + ? X_PRICE_DOWN + : X_PRICE_UP; + + // + iPriceEdgeType = isBullish + ? X_PRICE_LOW + : X_PRICE_HIGH; + + // + iPrice = bar.GetPrice(iPriceType); + iPriceEdge = bar.GetPrice(iPriceEdgeType); + + // + // Validate ... + result = + NotEmptyZero(iPrice) && + IsXValid(iPriceType) && + NotEmptyZero(iPriceEdge) && + IsXValid(iPriceEdgeType) && + ((isBullish && !isBearish) || + (isBearish && !isBullish)); + if (!result) + { + return result; + } + + // + // Validate Pattern based on MA Band ... + + // + // Retrieve MA Band for Validation ... + double iMABandUpper = fimaConditions.maBandUpperBuffer[cIdx]; + double iMABandLower = fimaConditions.maBandLowerBuffer[cIdx]; + + // + // Validate by Edge Price ... + result = isBullish + ? iPriceEdge < iMABandLower + : iPriceEdge > iMABandUpper; + if (!result) + { + return result; + } + + // + return result; + } + + /** + * Check Pattern Has Signal Based on Strategy 1 ... + * + * @param bar: XOHCL, reference to Pattern Bar ... + * @param iZone: XBoxZone, reference to holds affected zone ... + * @param patternName: string, detected pattern's name ... + * @param supports: XBoxZone, array reference to Provide Exists Supports ... + * @param resistances: XBoxZone, array reference to Provide Exists Resistances ... + * @param patternDir: ENUM_X_DIRECTION, detected pattern's direction ... + * @param fimaConditions: XFIMAConditions, reference to Bar Specified XFIMA Conditions ... + * @param fimaMarketStructure: XFIMAMarketStructure, refrence to Provides Market Structure ... + * + * @return ( bool ) + */ + bool Strategy1HasSignal( + XOHCL &bar, + XBoxZone &iZone, + string patternName, + XBoxZone &supports[], + XBoxZone &resistances[], + ENUM_X_DIRECTION patternDir, + XFIMAMarketStructure &structure, + XFIMAConditions &fimaConditions, + XFIMAMarketStructure &fimaMarketStructure // + ) + { + // + bool result = false; + + // + // Prepare ... + iZone.Clean(); + + // + // Validate ... + result = bar.IsValid() && + IsXValid(patternName) && + HasDirection(patternDir) && + fimaConditions.IsValid(); + if (!result) + { + return result; + } + + // + // Validate Pattern Based on MA Band ... + result = ValidatePatternBasedOnMABand( + bar, + patternName, + patternDir, + fimaConditions // + ); + if (!result) + { + return result; + } + + // + // Check Affected Zone ... + // Select a Support or Resistance ... + int insideZoneIDX = -1; + result = + (isBullish + ? HasInside( + insideZoneIDX, + bar, + supports // + ) + : HasInside( + insideZoneIDX, + bar, + resistances // + )); + if (!result) + { + return result; + } + + // + // Filling Affected Zone ... + // and Validate it ... + if (IsXBullish(patternDir)) + { + iZone = supports[insideZoneIDX]; + } + else if (IsXBearish(patternDir)) + { + iZone = resistances[insideZoneIDX]; + } + result = iZOne.IsValid(); + if (!result) + { + return result; + } + + // + // Validate affected Zone based on Pattern's Bar ... + result = IsXBullish(patternDir) + ? bar.high > iZZone.upper + : IsXBearish(patternDir) + ? bar.low < iZone.lower + : false; + // + // Cleanup Resources ... + if (!result) + { + iZone.Clean(); + } + + // + return result; + } + + /** + * Check Pattern Has Signal Based on Strategy 1 ... + * + * @param bar: XOHCL, reference to Pattern Bar ... + * @param iZone: XBoxZone, reference to holds affected zone ... + * @param patternName: string, detected pattern's name ... + * @param supports: XBoxZone, array reference to Provide Exists Supports ... + * @param resistances: XBoxZone, array reference to Provide Exists Resistances ... + * @param patternDir: ENUM_X_DIRECTION, detected pattern's direction ... + * @param fimaConditions: XFIMAConditions, reference to Bar Specified XFIMA Conditions ... + * @param fimaMarketStructure: XFIMAMarketStructure, refrence to Provides Market Structure ... + * + * @return ( bool ) + */ + bool Strategy2HasSignal( + XOHCL &bar, + XBoxZone &iZone, + string patternName, + XBoxZone &supports[], + XBoxZone &resistances[], + ENUM_X_DIRECTION patternDir, + XFIMAMarketStructure &structure, + XFIMAConditions &fimaConditions, + XFIMAMarketStructure &fimaMarketStructure // + ) + { + // + bool result = false; + + // + // Prepare ... + + // + // Validate ... + + // + // Do Detection ... + + // + // Validate result ... + + // + // Cleanup Resources ... + + // + return result; + } + + // +}; + +// \ No newline at end of file diff --git a/Experts/x-saherelm.xfima.backtester.ea.mq5 b/Experts/x-saherelm.xfima.backtester.ea.mq5 index 69a02530..906f7e02 100644 --- a/Experts/x-saherelm.xfima.backtester.ea.mq5 +++ b/Experts/x-saherelm.xfima.backtester.ea.mq5 @@ -453,11 +453,15 @@ void OnTick() } // - // fima1Signaller.OnTick(); - fima2Signaller.OnTick(); + // Bar Index ... + int barIndex = 1; // - AnalyseMarket(1); + // fima1Signaller.OnTick(barIndex); + fima2Signaller.OnTick(barIndex); + + // + // AnalyseMarket(barIndex); } // @@ -613,7 +617,7 @@ void OnSignalTriggered(XSignal &signal) // // TODO: Fix this ... - return; + // return; // // Draw Signal on Chart ... @@ -627,6 +631,12 @@ void OnSignalTriggered(XSignal &signal) // if (has) { + // + ENUM_X_SIGNAL_EXECUTION_RESULT result; + eaExpert.eaTrader.ExecuteSignal( + signal, + result // + ); Print("Signal Issued: ", signal.GetObjectID()); } @@ -923,8 +933,8 @@ void AnalyseMarket(int barIndex = 0) ); // - // XFIMASIgballer2First(bar); - HandleLookupSignal(bar); + XFIMASIgballer2First(bar); + // HandleLookupSignal(bar); // bar.Clean(); diff --git a/Libraries/x-saherelm.common.extensions.lib.mq5 b/Libraries/x-saherelm.common.extensions.lib.mq5 index b9d1cf96..97b5a565 100644 --- a/Libraries/x-saherelm.common.extensions.lib.mq5 +++ b/Libraries/x-saherelm.common.extensions.lib.mq5 @@ -83,6 +83,10 @@ bool IsValid(string value) // return result; } +bool IsXValid(string value) +{ + return IsValid(value); +} bool IsSpecifiedValid(string value) { return IsValid(value); @@ -106,6 +110,10 @@ bool IsValid(datetime value) // return result; } +bool IsXValid(datetime value) +{ + return IsValid(value); +} bool IsSpecifiedValid(datetime value) { return IsValid(value); @@ -133,6 +141,11 @@ bool IsValid(ENUM_TIMEFRAMES value) // return result; } +bool IsXValid(ENUM_TIMEFRAMES value) +{ + // + return IsValid(value); +} bool IsSpecifiedValid(ENUM_TIMEFRAMES value) { // @@ -171,6 +184,16 @@ bool IsValid( // return result; } +bool IsXValid( + ENUM_X_PERIOD_METHOD mMethod, + ENUM_TIMEFRAMES mPeriod // +) +{ + return IsValid( + mMethod, + mPeriod // + ); +} bool IsSpecifiedValid( ENUM_X_PERIOD_METHOD mMethod, ENUM_TIMEFRAMES mPeriod // diff --git a/Libraries/x-saherelm.x-enums.lib.mq5 b/Libraries/x-saherelm.x-enums.lib.mq5 index 2e90cf4f..b66cb6e7 100644 --- a/Libraries/x-saherelm.x-enums.lib.mq5 +++ b/Libraries/x-saherelm.x-enums.lib.mq5 @@ -346,6 +346,10 @@ bool IsValid(ENUM_X_BOUNDARY_PRICE value) // return result; } +bool IsXValid(ENUM_X_BOUNDARY_PRICE value) +{ + return IsValid(value); +} bool IsSpecifiedValid(ENUM_X_BOUNDARY_PRICE value) { return IsValid(value); @@ -417,6 +421,10 @@ bool IsValid(ENUM_X_DIRECTION value) // return result; } +bool IsXValid(ENUM_X_DIRECTION value) +{ + return IsValid(value); +} bool IsSpecifiedValid(ENUM_X_DIRECTION value) { return IsValid(value); @@ -460,6 +468,17 @@ bool IsBullish(ENUM_X_DIRECTION value) // return result; } +bool IsXBullish(ENUM_X_DIRECTION value) +{ + // + bool result = false; + + // + result = value == X_DIRECTION_BULLISH; + + // + return result; +} bool IsSpecifiedBullish(ENUM_X_DIRECTION value) { // @@ -490,6 +509,17 @@ bool IsBearish(ENUM_X_DIRECTION value) // return result; } +bool IsXBearish(ENUM_X_DIRECTION value) +{ + // + bool result = false; + + // + result = value == X_DIRECTION_BEARISH; + + // + return result; +} bool IsSpecifiedBearish(ENUM_X_DIRECTION value) { // @@ -943,6 +973,10 @@ bool IsValid(ENUM_X_MARKET_CYCLES value) // return result; } +bool IsXValid(ENUM_X_MARKET_CYCLES value) +{ + return IsValid(value); +} bool IsSpecifiedValid(ENUM_X_MARKET_CYCLES value) { return IsValid(value); diff --git a/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 b/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 index 70860638..15e95b6d 100644 --- a/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 +++ b/XFIMAEA/Classes/x-saherelm.xfima.signaller.class.mq5 @@ -617,7 +617,7 @@ class XCXFIMAStrategy2Signaller : public XCXFIMABaseSignaller XBoxZone iZone; int count = 0; bool has = false; - int cIdx = barIndex + 1; + int cIdx = 0; int pIdx = cIdx + 1; string iName = NULL; XBoxZone supports[]; @@ -625,10 +625,12 @@ class XCXFIMAStrategy2Signaller : public XCXFIMABaseSignaller bool isBullish = false; bool isBearish = false; double iPrice = EMPTY_VALUE; + double iPriceEdge = EMPTY_VALUE; XFIMAMarketStructure structure; XFIMAConditions fimaConditions; ENUM_X_PRICE iPriceType = X_PRICE_NONE; ENUM_X_DIRECTION iDir = X_DIRECTION_NONE; + ENUM_X_PRICE iPriceEdgeType = X_PRICE_NONE; // XPivot pvPivots[]; @@ -647,7 +649,7 @@ class XCXFIMAStrategy2Signaller : public XCXFIMABaseSignaller has = bar.Init( symbol, period, - cIdx // + barIndex // ); if (!has) { @@ -681,118 +683,6 @@ class XCXFIMAStrategy2Signaller : public XCXFIMABaseSignaller analyserConfig // ); - // - // Check Required Pattern Exists ... - bool hasPinnedBar = HasDirection(structure.pinnedDir); - bool hasEngulfedBar = HasDirection(structure.engulfedDir); - bool hasFlagPattern = HasDirection(structure.flagPatternDir); - bool hasStarPattern = HasDirection(structure.starPatternDir); - bool hasRisingPattern = HasDirection(structure.risingPatternDir); - bool hasPiercingPattern = HasDirection(structure.piercingPatternDir); - bool hasSignalKeyBar = HasDirection(structure.signalKeyBarPatternDir); - - // - // Check Bar Pattern Exists ... - has = hasPinnedBar || - hasEngulfedBar || - hasFlagPattern || - hasStarPattern || - hasSignalKeyBar || - hasRisingPattern || - hasPiercingPattern; - - // - // Select Pattern Direction and Price and Price Type ... - if (has) - { - // - if (hasPinnedBar) - { - // - iDir = structure.pinnedDir; - iName = "XPinned_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); - } - else if (hasEngulfedBar) - { - // - iDir = structure.engulfedDir; - iName = "XEngulfed_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); - } - else if (hasFlagPattern) - { - // - iDir = structure.flagPatternDir; - iName = "XFlag_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); - } - else if (hasStarPattern) - { - // - iDir = structure.starPatternDir; - iName = "XStar_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); - } - else if (hasSignalKeyBar) - { - // - iDir = structure.risingPatternDir; - iName = "XRising_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); - } - else if (hasRisingPattern) - { - // - iDir = structure.piercingPatternDir; - iName = "XPiercing_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); - } - else if (hasPiercingPattern) - { - // - iDir = structure.signalKeyBarPatternDir; - iName = "XSignalKey_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); - } - - // - isBullish = IsSpecifiedBullish(iDir); - isBearish = IsSpecifiedBearish(iDir); - - // - // Retrieve Price Type for Validate ... - iPriceType = isBullish - ? X_PRICE_LOW - : X_PRICE_HIGH; - iPrice = bar.GetPrice(iPriceType); - - // - has = HasDirection(iDir); - } - - // - // Chekc Bullish or Bearish Starter Conditions Exists ... - has = - isBullish || - isBearish; - if (has) - { - // - // Do Conditions Validating ... - - // - // Retrieve MA Band for Validation ... - double iMABandUpper = fimaHelper.GetMABandUpper(barIndex); - double iMABandLower = fimaHelper.GetMABandLower(barIndex); - - // - // Validate ... - has = isBullish - ? iPrice < iMABandLower - : iPrice > iMABandUpper; - if (!has) - { - // - isBullish = false; - isBearish = false; - iDir = X_DIRECTION_NONE; - } - } - // // Collect Support and Resistance Zones and Validate by them ... @@ -813,26 +703,6 @@ class XCXFIMAStrategy2Signaller : public XCXFIMABaseSignaller supportBox, supports // ); - // has = poiDrawer.DrawBox( - // supportBox, - // iSupportObj, - // true, // Ignore At ... - // supportBox.type // Name ... - // ); - // if (has) - // { - // // - // XPOIStyle iStyle; - // poiDrawer.GetBoxStyle( - // iStyle, - // supportBox.dir // - // ); - // poiDrawer.ApplyBoxStyle( - // iSupportObj, - // iStyle // - // ); - // iStyle.Clean(); - // } } // @@ -847,26 +717,6 @@ class XCXFIMAStrategy2Signaller : public XCXFIMABaseSignaller resistanceBox, supports // ); - // has = poiDrawer.DrawBox( - // resistanceBox, - // iResistanceObj, - // true, // Ignore At ... - // resistanceBox.type // Name ... - // ); - // if (has) - // { - // // - // XPOIStyle iStyle; - // poiDrawer.GetBoxStyle( - // iStyle, - // resistanceBox.dir // - // ); - // poiDrawer.ApplyBoxStyle( - // iResistanceObj, - // iStyle // - // ); - // iStyle.Clean(); - // } } // @@ -1296,15 +1146,6 @@ class XCXFIMAStrategy2Signaller : public XCXFIMABaseSignaller structure.support, supports // ); - - // // - // XCBoxObject *iObj; - // has = fima2Signaller.poiDrawer.DrawBox( - // structure.support, - // iObj); - // if (has) - // { - // } } // @@ -1317,53 +1158,99 @@ class XCXFIMAStrategy2Signaller : public XCXFIMABaseSignaller structure.resistance, resistances // ); - - // // - // XCBoxObject *iObj; - // has = fima2Signaller.poiDrawer.DrawBox( - // structure.resistance, - // iObj); - // if (has) - // { - // } } // - // Validate Positions Support and Resistance Zone ... - int insideZoneIDX = -1; - has = has && - (isBullish - ? HasInside( - insideZoneIDX, - bar, - supports // - ) - : HasInside( - insideZoneIDX, - bar, - resistances // - )); + // Check Required Pattern Exists ... + bool hasPinnedBar = HasDirection(structure.pinnedDir); + bool hasEngulfedBar = HasDirection(structure.engulfedDir); + bool hasFlagPattern = HasDirection(structure.flagPatternDir); + bool hasStarPattern = HasDirection(structure.starPatternDir); + bool hasRisingPattern = HasDirection(structure.risingPatternDir); + bool hasPiercingPattern = HasDirection(structure.piercingPatternDir); + bool hasSignalKeyBar = HasDirection(structure.signalKeyBarPatternDir); // - // Validate Selected Inside Zone ... - // whith Bars Edge ... - has = IsValidIndex(insideZoneIDX); + // Check Bar Pattern Exists ... + // and Select Pattern Direction and Price and Price Type ... + has = hasPinnedBar || + hasEngulfedBar || + hasFlagPattern || + hasStarPattern || + hasSignalKeyBar || + hasRisingPattern || + hasPiercingPattern; if (has) { // - if (isBullish) + if (hasPinnedBar) { - iZone = supports[insideZoneIDX]; + // + iDir = structure.pinnedDir; + iName = "XPinned_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); } - else + else if (hasEngulfedBar) { - iZone = resistances[insideZoneIDX]; + // + iDir = structure.engulfedDir; + iName = "XEngulfed_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasFlagPattern) + { + // + iDir = structure.flagPatternDir; + iName = "XFlag_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasStarPattern) + { + // + iDir = structure.starPatternDir; + iName = "XStar_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasSignalKeyBar) + { + // + iDir = structure.risingPatternDir; + iName = "XRising_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasRisingPattern) + { + // + iDir = structure.piercingPatternDir; + iName = "XPiercing_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); + } + else if (hasPiercingPattern) + { + // + iDir = structure.signalKeyBarPatternDir; + iName = "XSignalKey_" + ToXString(iDir) + ToXString(TimeToSeconds(bar.time)); } // - has = isBullish - ? bar.high > supports[insideZoneIDX].upper - : bar.low < resistances[insideZoneIDX].lower; + isBullish = IsSpecifiedBullish(iDir); + isBearish = IsSpecifiedBearish(iDir); + + // + // Retrieve Price Type for Validate ... + iPriceType = isBullish + ? X_PRICE_DOWN + : X_PRICE_UP; + iPriceEdgeType = isBullish + ? X_PRICE_LOW + : X_PRICE_HIGH; + + // + iPrice = bar.GetPrice(iPriceType); + iPriceEdge = bar.GetPrice(iPriceEdgeType); + + // + // Validate Calculations ... + has = HasDirection(iDir) && + (isBullish || + isBearish) && + NotEmptyZero(iPrice) && + NotEmptyZero(iPriceEdge) && + iPrice != iPriceEdge; if (!has) { // @@ -1372,21 +1259,24 @@ class XCXFIMAStrategy2Signaller : public XCXFIMABaseSignaller iDir = X_DIRECTION_NONE; } } - else - { - // - isBullish = false; - isBearish = false; - iDir = X_DIRECTION_NONE; - } // - // Checking Liquidities ... + // Strategy 1 ... + has = Strategy1HasSignal( + bar, + iZone, + iName, + supports, + resistances, + iDir, + structure, + fimaConditions // + ); // // Do all Draws Here ... - bool canDraw = false; - if (canDraw) + bool canDraw = true; + if (canDraw && has) { // int iWidth = 2; @@ -1548,7 +1438,7 @@ class XCXFIMAStrategy2Signaller : public XCXFIMABaseSignaller has = poiDrawer.DrawBarArrow( bar, iPatternObj, - iPriceType, + iPriceEdgeType, iCode, iClr, iWidth, @@ -1561,8 +1451,6 @@ class XCXFIMAStrategy2Signaller : public XCXFIMABaseSignaller } // - // Check Signal Founded ... - has = HasDirection(iDir); if (has) { // @@ -1638,6 +1526,270 @@ class XCXFIMAStrategy2Signaller : public XCXFIMABaseSignaller // // Props ... + // + // Implementing Strategies ... + + /** + * Validate a Pattern based on MA Band ... + * + * @param bar: XOHCL, reference to Pattern Bar ... + * @param patternName: string, detected pattern's name ... + * @param patternDir: ENUM_X_DIRECTION, detected pattern's direction ... + * @param fimaConditions: XFIMAConditions, reference to Bar Specified XFIMA Conditions ... + * + * @return ( bool ) + */ + bool ValidatePatternBasedOnMABand( + XOHCL &bar, + string patternName, + ENUM_X_DIRECTION patternDir, + XFIMAConditions &fimaConditions // + ) + { + // + bool result = false; + + // + // Validate ... + result = bar.IsValid() && + IsXValid(patternName) && + HasDirection(patternDir); + if (!result) + { + return result; + } + + // + // Define Requirements ... + bool isBullish = false; + bool isBearish = false; + double iPrice = EMPTY_VALUE; + double iPriceEdge = EMPTY_VALUE; + ENUM_X_PRICE iPriceType = X_PRICE_NONE; + ENUM_X_PRICE iPriceEdgeType = X_PRICE_NONE; + + // + // Calculating Price and Price Types ... + + // + isBullish = IsXBullish(patternDir); + isBearish = IsXBearish(patternDir); + + // + iPriceType = isBullish + ? X_PRICE_DOWN + : X_PRICE_UP; + + // + iPriceEdgeType = isBullish + ? X_PRICE_LOW + : X_PRICE_HIGH; + + // + iPrice = bar.GetPrice(iPriceType); + iPriceEdge = bar.GetPrice(iPriceEdgeType); + + // + // Validate ... + result = + NotEmptyZero(iPrice) && + IsXValid(iPriceType) && + NotEmptyZero(iPriceEdge) && + IsXValid(iPriceEdgeType) && + ((isBullish && !isBearish) || + (isBearish && !isBullish)); + if (!result) + { + return result; + } + + // + // Validate Pattern based on MA Band ... + + // + // Retrieve MA Band for Validation ... + double iMABandUpper = fimaConditions.maBandUpperBuffer[0]; + double iMABandLower = fimaConditions.maBandLowerBuffer[0]; + + // + // Validate by Edge Price ... + result = + NotEmptyZero(iMABandUpper) && + NotEmptyZero(iMABandLower) && + (isBullish + ? iPriceEdge < iMABandLower + : iPriceEdge > iMABandUpper); + if (!result) + { + return result; + } + + // + return result; + } + + /** + * Check Pattern Has Signal Based on Strategy 1 ... + * + * @param bar: XOHCL, reference to Pattern Bar ... + * @param iZone: XBoxZone, reference to holds affected zone ... + * @param patternName: string, detected pattern's name ... + * @param supports: XBoxZone, array reference to Provide Exists Supports ... + * @param resistances: XBoxZone, array reference to Provide Exists Resistances ... + * @param patternDir: ENUM_X_DIRECTION, detected pattern's direction ... + * @param structure: XFIMAMarketStructure, refrence to Provides Market Structure ... + * @param fimaConditions: XFIMAConditions, reference to Bar Specified XFIMA Conditions ... + * + * @return ( bool ) + */ + bool Strategy1HasSignal( + XOHCL &bar, + XBoxZone &iZone, + string patternName, + XBoxZone &supports[], + XBoxZone &resistances[], + ENUM_X_DIRECTION patternDir, + XFIMAMarketStructure &structure, + XFIMAConditions &fimaConditions // + ) + { + // + bool result = false; + + // + // Prepare ... + iZone.Clean(); + + // + // Validate ... + result = bar.IsValid() && + IsXValid(patternName) && + HasDirection(patternDir); + if (!result) + { + return result; + } + + // + // Validate Pattern Based on MA Band ... + result = ValidatePatternBasedOnMABand( + bar, + patternName, + patternDir, + fimaConditions // + ); + if (!result) + { + return result; + } + + // + // Check Affected Zone ... + // Select a Support or Resistance ... + int insideZoneIDX = -1; + result = + (IsXBullish(patternDir) + ? HasInside( + insideZoneIDX, + bar, + supports // + ) + : IsXBearish(patternDir) + ? HasInside( + insideZoneIDX, + bar, + resistances // + ) + : false // + ); + if (!result) + { + return result; + } + + // + // Filling Affected Zone ... + // and Validate it ... + if (IsXBullish(patternDir)) + { + iZone = supports[insideZoneIDX]; + } + else if (IsXBearish(patternDir)) + { + iZone = resistances[insideZoneIDX]; + } + result = iZone.IsValid(); + if (!result) + { + return result; + } + + // + // Validate affected Zone based on Pattern's Bar ... + result = IsXBullish(patternDir) + ? bar.high > iZone.upper + : IsXBearish(patternDir) + ? bar.low < iZone.lower + : false; + // + // Cleanup Resources ... + if (!result) + { + iZone.Clean(); + } + + // + return result; + } + + /** + * Check Pattern Has Signal Based on Strategy 1 ... + * + * @param bar: XOHCL, reference to Pattern Bar ... + * @param iZone: XBoxZone, reference to holds affected zone ... + * @param patternName: string, detected pattern's name ... + * @param supports: XBoxZone, array reference to Provide Exists Supports ... + * @param resistances: XBoxZone, array reference to Provide Exists Resistances ... + * @param patternDir: ENUM_X_DIRECTION, detected pattern's direction ... + * @param fimaConditions: XFIMAConditions, reference to Bar Specified XFIMA Conditions ... + * @param fimaMarketStructure: XFIMAMarketStructure, refrence to Provides Market Structure ... + * + * @return ( bool ) + */ + bool Strategy2HasSignal( + XOHCL &bar, + XBoxZone &iZone, + string patternName, + XBoxZone &supports[], + XBoxZone &resistances[], + ENUM_X_DIRECTION patternDir, + XFIMAMarketStructure &structure, + XFIMAConditions &fimaConditions, + XFIMAMarketStructure &fimaMarketStructure // + ) + { + // + bool result = false; + + // + // Prepare ... + + // + // Validate ... + + // + // Do Detection ... + + // + // Validate result ... + + // + // Cleanup Resources ... + + // + return result; + } + // };