diff --git a/Classes/x-saherelm.x-poi.drawer.class.mq5 b/Classes/x-saherelm.x-poi.drawer.class.mq5 index 0ffbe495..b4e03af8 100644 --- a/Classes/x-saherelm.x-poi.drawer.class.mq5 +++ b/Classes/x-saherelm.x-poi.drawer.class.mq5 @@ -256,7 +256,8 @@ class XCPOIDrawer : public XCBase color clr = clrYellow, int width = 3, ENUM_ARROW_ANCHOR anchor = ANCHOR_BOTTOM, - string name = NULL // + string name = NULL, + bool ignoreBarTag = true // ) { // @@ -285,7 +286,10 @@ class XCPOIDrawer : public XCBase (IsValid(prefix) ? prefix + "_" : prefix) + - ToMD5(barTag); + (IsSpecifiedValid(name) + ? name + : "") + + (ignoreBarTag ? "" : ToMD5(barTag)); // object = new XCBarArrowObject(); @@ -404,13 +408,13 @@ class XCPOIDrawer : public XCBase /** * Draw Specified Pivot Collection ... - * + * * @param pivots: XPivot, reference Collection to Draw ... * @param draws: CArrayObj, pointer reference to Hold Drawn Objects ... * @param peakArrow: int, Specified Arrow Code for Peak Pivots ... * @param valeArrow: int, Specified Arrow Code for Vale Pivots ... * @param threshold: int, distance between price and arrow in Point ... - * + * * @return ( int ) */ int DrawPivots( @@ -787,7 +791,7 @@ class XCPOIDrawer : public XCBase // // Prepare ... object = NULL; - + // int count = ArraySize(swings); result = HasChild(swings) && @@ -801,19 +805,31 @@ class XCPOIDrawer : public XCBase // bool isBullish = IsSpecifiedBullish(dir); + // + XOHCL _swings[]; + Copy( + swings, + _swings // + ); + SortBar( + _swings, + X_SORT_BY_DATE, + X_DIRECTION_BULLISH // + ); + // double price1 = isBullish - ? swings[0].low - : swings[0].high; - datetime time1 = swings[0].time; + ? _swings[0].low + : _swings[0].high; + datetime time1 = _swings[0].time; // double price2 = isBullish - ? swings[count - 1].low - : swings[count - 1].high; - datetime time2 = swings[count - 1].time; + ? _swings[count - 1].low + : _swings[count - 1].high; + datetime time2 = _swings[count - 1].time; // ulong chartId = ChartIdentification(); @@ -844,6 +860,9 @@ class XCPOIDrawer : public XCBase object.RayRight(rayRight); } + // + SpecifiedClean(_swings); + // return result; } diff --git a/Experts/x-saherelm.xfima.backtester.ea.mq5 b/Experts/x-saherelm.xfima.backtester.ea.mq5 index 122eda11..4623dd3f 100644 --- a/Experts/x-saherelm.xfima.backtester.ea.mq5 +++ b/Experts/x-saherelm.xfima.backtester.ea.mq5 @@ -385,9 +385,11 @@ int OnInit() // // Configure XFIMA POI Detector / Drawer ... - detectorConfig.Clean(); - detectorConfig.detectTrueGaped = true; + detectorConfig.Default(); + detectorConfig.OffDetectors(); + detectorConfig.detectSwingTrend = true; marketStructureDrawerConfig.FullDraw(); + marketStructureDrawerConfig.swingTrendRayLeft = false; // Print(ShortName, ": Initialized Successfully ..."); @@ -486,9 +488,17 @@ void OnTick() eaDraws // ); } - if (HasDirection(marketStructure.trueGapedDir)) + if (HasDirection(marketStructure.trendDir)) { - Print("true gap detected ..."); + Print("Detected ..."); + } + if (marketStructure.ob.IsValid() && marketStructure.fvg.IsValid()) + { + Print("Detected ..."); + } + if (marketStructure.support.IsValid() || marketStructure.resistance.IsValid()) + { + Print("Detected ..."); } } diff --git a/Libraries/x-saherelm.x-poi.extensions.lib.mq5 b/Libraries/x-saherelm.x-poi.extensions.lib.mq5 index 41e2b5c2..00a4b681 100644 --- a/Libraries/x-saherelm.x-poi.extensions.lib.mq5 +++ b/Libraries/x-saherelm.x-poi.extensions.lib.mq5 @@ -21,6 +21,7 @@ // // Imports ... +#include "../Libraries/x-saherelm.x-ohcl.lib.mq5" #include "../Libraries/x-saherelm.x-poi.lib.mq5" // @@ -29,6 +30,51 @@ //+------------------------------------------------------------------+ //| Oldest Detection | //+------------------------------------------------------------------+ +/** + * Get Oldest Index of Specified Collection ... + * + * @param source: Specified Collection ... + * + * @return ( int ) + */ +int GetOldestBar( + XOHCL &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XOHCL selected; + for (int i = 0; i < count; i++) + { + // + bool canSet = + !selected.IsValid() + ? true + : selected.time > source[i].time; + if (canSet) + { + // + result = i; + selected = source[i]; + } + } + + // + selected.Clean(); + + // + return result; +} + /** * Get Oldest Index of Specified Collection ... * @@ -54,23 +100,17 @@ int GetOldest( XBoxZone selected; for (int i = 0; i < count; i++) { - // - XBoxZone iBox = source[i]; - // bool canSet = !selected.IsValid() ? true - : selected.from > iBox.from; + : selected.from > source[i].from; if (canSet) { // result = i; - selected = iBox; + selected = source[i]; } - - // - iBox.Clean(); } // @@ -114,16 +154,9 @@ int GetOldestByBar( for (int i = 0; i < count; i++) { // - XBoxZone iBox = source[i]; - - // - bool isBoxValidForBar = IsBoxPlaceValidForBar(bar, iBox); + bool isBoxValidForBar = IsBoxPlaceValidForBar(bar, source[i]); if (!isBoxValidForBar) { - // - iBox.Clean(); - - // continue; } @@ -131,16 +164,13 @@ int GetOldestByBar( bool canSet = !selected.IsValid() ? true - : selected.from > iBox.from; + : selected.from > source[i].from; if (canSet) { // result = i; - selected = iBox; + selected = source[i]; } - - // - iBox.Clean(); } // @@ -224,6 +254,51 @@ int GetOldest( //+------------------------------------------------------------------+ //| Youngest Detection | //+------------------------------------------------------------------+ +/** + * Get Youngest Index of Specified Collection ... + * + * @param source: Specified Collection ... + * + * @return ( int ) + */ +int GetYoungestBar( + XOHCL &source[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XOHCL selected; + for (int i = 0; i < count; i++) + { + // + bool canSet = + !selected.IsValid() + ? true + : selected.time < source[i].time; + if (canSet) + { + // + result = i; + selected = source[i]; + } + } + + // + selected.Clean(); + + // + return result; +} + /** * Get Youngest Index of Specified Collection ... * @@ -249,23 +324,17 @@ int GetYoungest( XBoxZone selected; for (int i = 0; i < count; i++) { - // - XBoxZone iBox = source[i]; - // bool canSet = !selected.IsValid() ? true - : selected.from < iBox.from; + : selected.from < source[i].from; if (canSet) { // result = i; - selected = iBox; + selected = source[i]; } - - // - iBox.Clean(); } // @@ -309,16 +378,9 @@ int GetYoungestByBar( for (int i = 0; i < count; i++) { // - XBoxZone iBox = source[i]; - - // - bool isBoxValidForBar = IsBoxPlaceValidForBar(bar, iBox); + bool isBoxValidForBar = IsBoxPlaceValidForBar(bar, source[i]); if (!isBoxValidForBar) { - // - iBox.Clean(); - - // continue; } @@ -326,16 +388,13 @@ int GetYoungestByBar( bool canSet = !selected.IsValid() ? true - : selected.from < iBox.from; + : selected.from < source[i].from; if (canSet) { // result = i; - selected = iBox; + selected = source[i]; } - - // - iBox.Clean(); } // @@ -419,6 +478,65 @@ int GetYoungest( //+------------------------------------------------------------------+ //| Highest Detection | //+------------------------------------------------------------------+ +/** + * Get Highest Index of Specified Collection ... + * + * @param source: Specified Collection ... + * @param _priceType: Specified Price type ... + * + * @return ( int ) + */ +int GetHighestBar( + XOHCL &source[], + ENUM_X_PRICE _priceType = X_PRICE_HIGH // +) +{ + // + int result = -1; + + // + if (!IsXValid(_priceType)) + { + _priceType = X_PRICE_HIGH; + } + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XOHCL selected; + double iPrice = EMPTY_VALUE; + double selectedPrice = EMPTY_VALUE; + for (int i = 0; i < count; i++) + { + // + iPrice = source[i].GetPrice(_priceType); + selectedPrice = selected.GetPrice(_priceType); + + // + bool canSet = + !selected.IsValid() + ? true + : selectedPrice < iPrice; + if (canSet) + { + // + result = i; + selected = source[i]; + } + } + + // + selected.Clean(); + + // + return result; +} + /** * Get Highest Index of Specified Collection ... * @@ -444,23 +562,17 @@ int GetHighest( XBoxZone selected; for (int i = 0; i < count; i++) { - // - XBoxZone iBox = source[i]; - // bool canSet = !selected.IsValid() ? true - : selected.upper < iBox.upper; + : selected.upper < source[i].upper; if (canSet) { // result = i; - selected = iBox; + selected = source[i]; } - - // - iBox.Clean(); } // @@ -614,6 +726,64 @@ int GetHighest( //+------------------------------------------------------------------+ //| Loest Detection | //+------------------------------------------------------------------+ +/** + * Get Lowest Index of Specified Collection ... + * + * @param source: Specified Collection ... + * + * @return ( int ) + */ +int GetLowestBar( + XOHCL &source[], + ENUM_X_PRICE _priceType = X_PRICE_LOW // +) +{ + // + int result = -1; + + // + if (!IsXValid(_priceType)) + { + _priceType = X_PRICE_LOW; + } + + // + int count = ArraySize(source); + if (!IsValidSize(count)) + { + return result; + } + + // + XOHCL selected; + double iPrice = EMPTY_VALUE; + double selectedPrice = EMPTY_VALUE; + for (int i = 0; i < count; i++) + { + // + iPrice = source[i].GetPrice(_priceType); + selectedPrice = selected.GetPrice(_priceType); + + // + bool canSet = + !selected.IsValid() + ? true + : selectedPrice > iPrice; + if (canSet) + { + // + result = i; + selected = source[i]; + } + } + + // + selected.Clean(); + + // + return result; +} + /** * Get Lowest Index of Specified Collection ... * @@ -920,6 +1090,94 @@ int SelectItemForSorting( return result; } +/** + * Select Specified Index of a Collection by Sort Params ... + * + * @param source: Collection for Search ... + * @param sortBy: ENUM_X_SORT_BY, Specified Sort Param ... + * @param sortDir: ENUM_X_DIRECTION, Specified Sort Direction ... + * + * @return ( int ) + */ +int SelectBarForSorting( + XOHCL &source[], + ENUM_X_SORT_BY sortBy = X_SORT_BY_DATE, + ENUM_X_DIRECTION sortDir = X_DIRECTION_BULLISH, + ENUM_X_PRICE priceType = X_PRICE_NONE // +) +{ + // + int result = -1; + + // + // Validate ... + if (!HasChild(source) || + !IsXValid(sortBy) || + !HasDirection(sortDir)) + { + return result; + } + + // + // Sort By Date ... + if (sortBy == X_SORT_BY_DATE) + { + // + // Select Based on Sorting Direction ... + + // + // form Oldest to Youngest ... + if (sortDir == X_DIRECTION_BULLISH) + { + result = GetOldestBar(source); + } + // + // form Youngest to Oldest ... + else if (sortDir == X_DIRECTION_BEARISH) + { + result = GetYoungestBar(source); + } + // + // Not Valid ... + else + { + result = -1; + } + } + // + // Sort By Value ... + else if (sortBy == X_SORT_BY_VALUE) + { + // + // form Lowst to Highest ... + if (sortDir == X_DIRECTION_BULLISH) + { + result = GetLowestBar(source, priceType); + } + // + // form Highest to Lowest ... + else if (sortDir == X_DIRECTION_BEARISH) + { + result = GetHighestBar(source, priceType); + } + // + // Not Valid ... + else + { + result = -1; + } + } + // + // Not Valid ... + else + { + result = -1; + } + + // + return result; +} + /** * Apply Sort on Specified Collection ... * @@ -1014,6 +1272,103 @@ void Sort( // Cleanup Resources ... SpecifiedClean(tmps); } + +/** + * Apply Sort on Specified Collection ... + * + * @param source: Collection Reference to Sort ... + * @param sortBy: ENUM_X_SORT_BY, Specified Sort Param ... + * @param sortDir: ENUM_X_DIRECTION, Specified Sort Direction ... + * @param priceType: ENUM_X_PRICE, Price Selecting Method ... + * @param maxAllowed: int, Max Allowed Collection Size ... + */ +void SortBar( + XOHCL &source[], + ENUM_X_SORT_BY sortBy = X_SORT_BY_DATE, + ENUM_X_DIRECTION sortDir = X_DIRECTION_BULLISH, + ENUM_X_PRICE priceType = X_PRICE_NONE, + int maxAllowed = 0 // +) +{ + // + int idx = -1; + bool has = false; + + // + // Validate ... + has = + IsXValid(sortBy) && + HasChild(source) && + HasDirection(sortDir); + if (!has) + { + return; + } + + // + // Copy source for Manipulating ... + XOHCL tmps[]; + Copy( + source, + tmps // + ); + + // + // Clean Source Collection for Adding Sorted Items ... + Clean(source); + + // + // Loop Through Temp Collection Has Child ... + while (HasChild(tmps)) + { + // + // Select Based on Sorting Parameter ... + idx = SelectBarForSorting( + tmps, + sortBy, + sortDir, + priceType // + ); + + // + // Validate Detected Index ... + has = IsValidIndex(idx); + if (!has) + { + break; + } + + // + // Add Detected Indexed Item to Source ... + AddRef( + tmps[idx], + source // + ); + + // + // Remove Item From Temp Collection ... + ArrayRemove( + tmps, + idx, + 1 // + ); + } + + // + // Cleanup Collection if Max Items Reached ... + if (maxAllowed > 0) + { + // + CleanupArray( + source, + maxAllowed // + ); + } + + // + // Cleanup Resources ... + SpecifiedClean(tmps); +} //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ diff --git a/XFIMAEA/Classes/x-saherelm.xfima.x-poi.detector.class.mq5 b/XFIMAEA/Classes/x-saherelm.xfima.x-poi.detector.class.mq5 index c49bb63f..68c35803 100644 --- a/XFIMAEA/Classes/x-saherelm.xfima.x-poi.detector.class.mq5 +++ b/XFIMAEA/Classes/x-saherelm.xfima.x-poi.detector.class.mq5 @@ -779,7 +779,7 @@ class XCXFIMAPOIDetector : public XCMarketPatternDetector // // Detect Supports ... - if (config.detectSupports) + if (config.detectSupport) { // XOHCL support; diff --git a/XFIMAEA/Classes/x-saherelm.xfima.x-poi.drawer.class.mq5 b/XFIMAEA/Classes/x-saherelm.xfima.x-poi.drawer.class.mq5 index 26f7b328..ab15c748 100644 --- a/XFIMAEA/Classes/x-saherelm.xfima.x-poi.drawer.class.mq5 +++ b/XFIMAEA/Classes/x-saherelm.xfima.x-poi.drawer.class.mq5 @@ -33,6 +33,50 @@ class XCXFIMAPOIDrawer : public XCPOIDrawer public: // + // + // Constructor ... + XCXFIMAPOIDrawer() : XCPOIDrawer() + { + Default(); + } + + // + // Deconstructor ... + ~XCXFIMAPOIDrawer() + { + } + + // + // Overrides ... + + /** + * Do additional Configurations for Child Classes ... + */ + void virtual Default() override + { + // + // Apply Default Props ... + + // + Prefix(NULL); + ChartIdentification(0); + SubWindowIdentification(0); + + // + defaultBullishStyle.width = 1; + defaultBullishStyle.clr = clrAqua; + defaultBullishStyle.style = STYLE_SOLID; + + // + defaultBearishStyle.width = 1; + defaultBearishStyle.clr = clrMagenta; + defaultBearishStyle.style = STYLE_SOLID; + + // + boxBullishStyle = defaultBullishStyle; + boxBearishStyle = defaultBearishStyle; + } + // // Get Specified Directional Arrow Anchor ... ENUM_ARROW_ANCHOR GetArrowAnchor(ENUM_X_DIRECTION forDir) @@ -155,6 +199,15 @@ class XCXFIMAPOIDrawer : public XCPOIDrawer } } + /** + * Draw Specified Market Structure Based on Given Configs ... + * + * @param structure: XFIMAMarketStructure, reference to Provide Specifid Market Structure ... + * @param config: XFIMAMarketStructureDrawerConfig, reference to Provide Drawing Configurations ... + * @param objects: CArrayObj, pointer reference to Holds drawn Objects instances ... + * + * @return ( int ) + */ int DrawMarketStructure( XFIMAMarketStructure &structure, XFIMAMarketStructureDrawerConfig &config, @@ -314,9 +367,9 @@ class XCXFIMAPOIDrawer : public XCPOIDrawer has = DrawSwingTrend( structure.trendSwings, structure.trendDir, - iObj, // - true, // Ray Right ... - false // Ray Left ... + iObj, // + config.swingTrendRayRight, // Ray Right ... + config.swingTrendRayLeft // Ray Left ... ); if (has) { diff --git a/XFIMAEA/Libraries/x-saherelm.xfima.lib.mq5 b/XFIMAEA/Libraries/x-saherelm.xfima.lib.mq5 index f86425ad..c187861e 100644 --- a/XFIMAEA/Libraries/x-saherelm.xfima.lib.mq5 +++ b/XFIMAEA/Libraries/x-saherelm.xfima.lib.mq5 @@ -41,7 +41,7 @@ struct XFIMAPatternDetectorConfig // Flags ... // - bool detectSupports; + bool detectSupport; bool detectResistance; // @@ -138,7 +138,7 @@ struct XFIMAPatternDetectorConfig // detectOB = false; detectFVG = false; - detectSupports = false; + detectSupport = false; detectResistance = false; detectSwingTrend = false; detectStarPattern = false; @@ -185,14 +185,14 @@ struct XFIMAPatternDetectorConfig { // // OB / FVG ... - detectOB = true; - detectFVG = true; + detectOB = false; + detectFVG = false; // // Support and Resistances ... - detectSupports = true; - detectResistance = true; - detectSwingTrend = true; + detectSupport = false; + detectResistance = false; + detectSwingTrend = false; // // Patterns ... @@ -223,12 +223,12 @@ struct XFIMAPatternDetectorConfig // // Trending ... - trendingNumberOfSwings = 3; + trendingNumberOfSwings = 5; trendingSwingShoulders = 7; // // Support and Resistance ... - supportAndResistanceValidationLength = 21; + supportAndResistanceValidationLength = 100; supportAndResistanceMaxAllowedLoopback = 1500; // @@ -269,9 +269,6 @@ struct XFIMAPatternDetectorConfig */ void FullDetect() { - // - Default(); - // // OB / FVG ... detectOB = true; @@ -279,7 +276,7 @@ struct XFIMAPatternDetectorConfig // // Support and Resistances ... - detectSupports = true; + detectSupport = true; detectResistance = true; detectSwingTrend = true; @@ -306,6 +303,45 @@ struct XFIMAPatternDetectorConfig analyseFIMAZigZagPivots = true; } + /** + * Default Config, by turn off all detecting flags ... + */ + void OffDetectors() + { + // + // OB / FVG ... + detectOB = false; + detectFVG = false; + + // + // Support and Resistances ... + detectSupport = false; + detectResistance = false; + detectSwingTrend = false; + + // + // Patterns ... + detectStarPattern = false; + detectFlagPattern = false; + detectRisingPattern = false; + detectPiercingPattern = false; + detectSignalKeyBarPattern = false; + + // + // Bars ... + detectPinned = false; + detectMomentum = false; + detectEngulfed = false; + detectTrueGaped = false; + + // + // Analysers ... + analyseFIMAPVPivots = false; + analyseFIMAMAPivots = false; + analyseFIMASARPivots = false; + analyseFIMAZigZagPivots = false; + } + // }; @@ -418,6 +454,8 @@ struct XFIMAMarketStructureDrawerConfig // bool drawSwingTrend; + bool swingTrendRayLeft; + bool swingTrendRayRight; // bool drawOB; @@ -479,7 +517,9 @@ struct XFIMAMarketStructureDrawerConfig drawSwingTrend = false; drawStarPattern = false; drawFlagPattern = false; + swingTrendRayLeft = false; drawRisingPattern = false; + swingTrendRayRight = false; drawPiercingPattern = false; drawSignalKeyBarPattern = false; drawFIMAPVPivotsAnalysis = false; @@ -510,6 +550,8 @@ struct XFIMAMarketStructureDrawerConfig drawFlagPattern = true; drawRisingPattern = true; drawPiercingPattern = true; + swingTrendRayLeft = false; + swingTrendRayRight = true; drawSignalKeyBarPattern = true; drawFIMAPVPivotsAnalysis = true; drawFIMAMAPivotsAnalysis = true; @@ -542,6 +584,8 @@ struct XFIMAMarketStructureDrawerConfig drawStarPattern = true; drawFlagPattern = true; drawRisingPattern = true; + swingTrendRayLeft = true; + swingTrendRayRight = true; drawPiercingPattern = true; drawSignalKeyBarPattern = true; drawFIMAPVPivotsAnalysis = true;