From 72c44466200a7eb2b890e6367b14b91a37bb5be2 Mon Sep 17 00:00:00 2001 From: Hadi Khazaee Asl Date: Mon, 18 Nov 2024 05:10:49 +0330 Subject: [PATCH] Last Works ... --- Documents/BKP/tmp.x121.smc.mq5 | 70 ++ .../Classes/x-121.smc.cobjects.class.mq5 | 170 +++++ X121SMCEA/Libraries/x-121.smc.lib.mq5 | 694 +++++++++++++++++- .../x-121.smc.test.strategy.class.mq5 | 467 ++++++++++-- 4 files changed, 1356 insertions(+), 45 deletions(-) create mode 100644 Documents/BKP/tmp.x121.smc.mq5 diff --git a/Documents/BKP/tmp.x121.smc.mq5 b/Documents/BKP/tmp.x121.smc.mq5 new file mode 100644 index 00000000..505f1c2a --- /dev/null +++ b/Documents/BKP/tmp.x121.smc.mq5 @@ -0,0 +1,70 @@ + + // + // Peaks ... + int peaksCount = ArraySize(conditions.peaks); + if (IsValidSize(peaksCount)) + { + // + for (int i = 0; i < peaksCount; i++) + { + // + XPVPivot iPivot = conditions.peaks[i]; + + // + XCXPVPivotObject *iObj; + iObj = new XCXPVPivotObject(); + + // + bool isCreated = iObj.Create( + mPOIDrawer.ChartIdentification(), + mPOIDrawer.SubWindowIdentification(), + iPivot // + ); + if (isCreated) + { + // + iObj.PivotWidth(1); + iObj.PivotFill(false); + iObj.PivotColor(clrAqua); + iObj.PivotStyle(STYLE_SOLID); + + // + AddObjectIfNotExists(iObj); + } + } + } + + // + // Vales ... + int valesCount = ArraySize(conditions.vales); + if (IsValidSize(valesCount)) + { + // + for (int i = 0; i < valesCount; i++) + { + // + XPVPivot iPivot = conditions.vales[i]; + + // + XCXPVPivotObject *iObj; + iObj = new XCXPVPivotObject(); + + // + bool isCreated = iObj.Create( + mPOIDrawer.ChartIdentification(), + mPOIDrawer.SubWindowIdentification(), + iPivot // + ); + if (isCreated) + { + // + iObj.PivotWidth(1); + iObj.PivotFill(false); + iObj.PivotStyle(STYLE_SOLID); + iObj.PivotColor(clrMagenta); + + // + AddObjectIfNotExists(iObj); + } + } + } diff --git a/X121SMCEA/Classes/x-121.smc.cobjects.class.mq5 b/X121SMCEA/Classes/x-121.smc.cobjects.class.mq5 index e69de29b..a524c83d 100644 --- a/X121SMCEA/Classes/x-121.smc.cobjects.class.mq5 +++ b/X121SMCEA/Classes/x-121.smc.cobjects.class.mq5 @@ -0,0 +1,170 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Class Library +// -------------------------------------- +// Name: XChartObjects +// Description: provides all require Chart Objects ... +// +// +// Maintainer: +// ------------ +// Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) +// +////////////////////////////////////////////////////// +// +// Global Properties ... +#property library +#property copyright "Copyright 2023, SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" +#property strict + +// +#include "../../Classes/x-saherelm.x-cobject.class.mq5" +#include "../Libraries/x-121.smc.lib.mq5" + +// +// Definitions ... + +enum ENUM_X121SMC_CHARTOBJECTS +{ + X_XPVPIVOT_OBJ, // XPVPivot Object ... +}; + +// +// Implementations ... + +// +// XPVPivot Object ... +class XCXPVPivotObject : public XCBaseObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param pivot: XPVPivot instance ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XPVPivot &pivot, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = pivot.IsValid(); + if (!result) + { + return result; + } + + // + string name = pivot.GetTag(); + if (IsValid(prefix)) + { + name = prefix + "_" + name; + } + + // + result = mRect.Create( + chart_id, + name, + window, + pivot.from, + pivot.upper, + pivot.to, + pivot.lower // + ); + + // + if (result) + { + ObjName(name); + } + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Set Pivot Width ... + * + * @param value: Integer ... + */ + void PivotWidth(int value) + { + // + if (value < 1) + { + value = 1; + } + + // + mRect.Width(value); + } + + /** + * Set Pivot Color ... + * + * @param value: Color ... + */ + void PivotColor(color value) + { + mRect.Color(value); + } + + /** + * Set Pivot Style ... + * + * @param value: ENUM_LINE_STYLE member ... + */ + void PivotStyle(ENUM_LINE_STYLE value) + { + mRect.Style(value); + } + + /** + * Set Pivot Fill ... + * + * @param value: Boolean ... + */ + void PivotFill(bool value) + { + mRect.Fill(value); + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_X121SMC_CHARTOBJECTS ) + */ + virtual ENUM_X121SMC_CHARTOBJECTS Type() + { + return X_XPVPIVOT_OBJ; + } + + // + private: + // + + // + // Props ... + CChartObjectRectangle mRect; +}; \ No newline at end of file diff --git a/X121SMCEA/Libraries/x-121.smc.lib.mq5 b/X121SMCEA/Libraries/x-121.smc.lib.mq5 index d762521d..0c2528bf 100644 --- a/X121SMCEA/Libraries/x-121.smc.lib.mq5 +++ b/X121SMCEA/Libraries/x-121.smc.lib.mq5 @@ -22,9 +22,9 @@ // // Imports ... #include "../../Classes/x-saherelm.base.class.mq5" -#include "../../Helpers/x-saherelm.xpv.helper.mq5" #include "../../Helpers/x-saherelm.x3ma.helper.mq5" #include "../../Helpers/x-saherelm.x3vwap.helper.mq5" +#include "../../Helpers/x-saherelm.xpv.helper.mq5" #include "../../Libraries/x-saherelm.common.lib.mq5" #include "../../Libraries/x-saherelm.x-poi.lib.mq5" #include "../../Libraries/x-saherelm.x-trade.lib.mq5" @@ -34,6 +34,339 @@ const string X121SMCStrategyToken = "X121SMC"; +enum ENUM_XPV_PIVOTS +{ + XPV_NONE, + XPV_PEAK, + XPV_VALE, +}; + +struct XPVPivot +{ + // + string symbol; + ENUM_TIMEFRAMES period; + + // + double upper; + double lower; + + // + datetime from; + datetime to; + + // + int repetition; + + // + ENUM_XPV_PIVOTS type; + + // + XPVPivot() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + upper = 0; + lower = 0; + + // + to = NULL; + from = NULL; + symbol = NULL; + period = NULL; + + // + repetition = 0; + + // + type = XPV_NONE; + } + + /** + * Validation ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + // + IsValid(to) && + IsValid(from) && + IsValid(symbol) && + IsValid(period) && + repetition > 0 && + type != XPV_NONE && + (upper > 0 || lower > 0) + // + ; + + // + return result; + } + + /** + * Check Pivot is Peak ... + * + * @return ( bool ) + */ + bool IsPeak() + { + // + bool result = false; + + // + result = IsValid() && + type == XPV_PEAK; + + // + return result; + } + + /** + * Check Pivot is Vale ... + * + * @return ( bool ) + */ + bool IsVale() + { + // + bool result = false; + + // + result = IsValid() && + type == XPV_VALE; + + // + return result; + } + + /** + * Calculate Lower for Peaks ... + * + * @return ( double ) + */ + double CalculateLower() + { + // + double result = 0; + + // + if (!IsValid() || + !IsPeak()) + { + return result; + } + + // + int fromIndex = iBarShift( + symbol, + period, + from // + ); + + // + int toIndex = iBarShift( + symbol, + period, + to // + ); + + // + int count = + fromIndex - toIndex; + + // + int llIDX = iLowest( + symbol, + period, + MODE_LOW, + count, + toIndex // + ); + + // + result = + iLow( + symbol, + period, + llIDX // + ); + + // + return result; + } + + /** + * Calculate Upper for Vales ... + * + * @return ( double ) + */ + double CalculateUpper() + { + // + double result = 0; + + // + if (!IsValid() || + !IsVale()) + { + return result; + } + + // + int fromIndex = iBarShift( + symbol, + period, + from // + ); + + // + int toIndex = iBarShift( + symbol, + period, + to // + ); + + // + int count = + fromIndex - toIndex; + + // + int hhIDX = iHighest( + symbol, + period, + MODE_HIGH, + count, + toIndex // + ); + + // + result = + iHigh( + symbol, + period, + hhIDX // + ); + + // + return result; + } + + /** + * Calculate Range of Pivot ... + * + * @return ( double ) + */ + double CalculateRange() + { + // + double result = 0; + + // + if (!IsValid() || + upper <= 0 || + lower <= 0) + { + return result; + } + + // + result = upper - lower; + + // + return result; + } + + /** + * Calculate Middle of Pivot ... + * Used for + * @return ( double ) + */ + double CalculateMid() + { + // + double result = 0; + + // + double range = CalculateRange(); + if (range <= 0) + { + return result; + } + + // + result = lower + (range / 2); + + // + return result; + } + + // + + /** + * Get Unique Identifier ... + * + * @return ( string ) + */ + string GetTag() + { + // + string result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + string hash = symbol + "_" + + ToString(period) + "_" + + ToString(upper) + "," + + ToString(lower) + "_" + + ToString(from) + "," + + ToString(to); + hash = ToMD5(hash); + + // + string typeStr = + type == XPV_PEAK + ? "Peak" + : "Vale"; + + // + result = + // + "XPV_" + + typeStr + "_" + + symbol + "_" + + ToString(period) + + "_" + hash + // + ; + + // + return result; + } + + // +}; + // // Model Signalling Conditions ... struct X121SMCStrategyConditions @@ -43,6 +376,9 @@ struct X121SMCStrategyConditions ENUM_TIMEFRAMES period; datetime time; + // + XPVPivot orderFlow[]; + // XPVConditions xpvConditions; X3MAConditions x3maConditions; @@ -163,6 +499,9 @@ struct X121SMCStrategyConditions x3maConditions.Clean(); x3vwapConditions.Clean(); + // + Clean(orderFlow); + // // D1 ... @@ -519,4 +858,357 @@ typedef void (*TOnX121SMCSignal)( X121SMCStrategyConditions &conditions // ); +// +// Extentions ... + +/** + * Find Oldest Pivot Index ... + * + * @param pivots: XPVPivot instance ... + * @return ( int ) + */ +int FindOldestPivotIndex( + XPVPivot &pivots[] // +) +{ + // + int result = -1; + + // + int count = ArraySize(pivots); + if (!IsValidSize(count)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + XPVPivot iPivot = pivots[i]; + + // + bool isOldest = true; + for (int j = 0; j < count; j++) + { + // + XPVPivot jPivot = pivots[j]; + + // + isOldest = iPivot.from <= jPivot.from; + if (!isOldest) + { + break; + } + } + + // + if (isOldest) + { + // + result = i; + break; + } + } + + // + return result; +} + +/** + * Sort Pivots Based On From Date ... + * + * @param pivots: XPVPivot instance Collection reference ... + */ +void SortPivots( + XPVPivot &pivots[] // +) +{ + // + XPVPivot tmp[]; + Copy( + pivots, + tmp // + ); + + // + Clean(pivots); + + // + while (ArraySize(tmp) > 0) + { + // + if (ArraySize(tmp) == 1) + { + // + AddRef( + tmp[0], + pivots // + ); + + // + ArrayRemove( + tmp, + 0, + 1); + } + else + { + // + int idx = FindOldestPivotIndex(tmp); + if (IsValidIndex(idx)) + { + // + AddRef( + tmp[idx], + pivots // + ); + + // + ArrayRemove( + tmp, + idx, + 1 // + ); + } + } + } + + // + Clean(tmp); +} + +bool IsPivotBreaked( + XPVPivot &pivot, + XPVPivot &pivots[] // +) +{ + // + bool result = false; + + // + result = pivot.IsValid(); + if (!result) + { + return result; + } + + // + int count = ArraySize(pivots); + result = IsValidSize(pivots); + if (!result) + { + return result; + } + + // + // For Peaks Highs Must not Broked ... + // For Vales Lows Must not Broked ... + bool isPeak = pivot.IsPeak(); + + // + for (int i = 0; i < count; i++) + { + // + XPVPivot iPivot = pivots[i]; + + // + result = isPeak + ? iPivot.upper > pivot.upper + : iPivot.lower < pivot.lower; + if (result) + { + break; + } + } + + // + return result; +} + +/** + * Filter Broken Pivots for Detect Order Flow ... + * + * @param pivots: XPVPivot instance Collection reference ... + */ +void FilterBrokenPivots( + XPVPivot &pivots[] // +) +{ + // + XPVPivot tmp[]; + Copy( + pivots, + tmp // + ); + + // + Clean(pivots); + + // + while (ArraySize(tmp) > 0) + { + // + if (ArraySize(tmp) == 1) + { + // + AddRef( + tmp[0], + pivots // + ); + + // + ArrayRemove( + tmp, + 0, + 1 // + ); + } + else + { + // + XPVPivot pivot = tmp[0]; + + // + ArrayRemove( + tmp, + 0, + 1 // + ); + + // + bool isBreaked = IsPivotBreaked( + pivot, + tmp // + ); + if (!isBreaked) + { + // + AddRef( + pivot, + pivots // + ); + } + } + } + + // + Clean(tmp); +} + +/** + * Calculate Order Flow Direction ... + * + * @param orderFlow: XPVPivot instance Collection reference ... + * @param dir: ENUM_X_DIRECTION member reference, Hold's Calculated Direction ... + * + * @return ( bool ) + */ +bool DetectPivotDirection( + XPVPivot &orderFlow[], + ENUM_X_DIRECTION &dir // +) +{ + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + + // + int count = ArraySize(orderFlow); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + // For Bullish Direction all Exists lowers must be Greater or Equal Prev ... + bool isBullish = false; + bool canLookupForBullish = true; + + // + // For Bearish Direction all Exists uppers must be Lesser or Equal Prev ... + bool isBearish = false; + bool canLookupForBearish = true; + + // + for (int i = 0; i < count; i++) + { + // + XPVPivot iPivot = orderFlow[i]; + + // + XPVPivot tmp[]; + Copy( + orderFlow, + tmp // + ); + ArrayRemove( + tmp, + 0, + i + 1 // + ); + + // + int tmpCount = ArraySize(tmp); + if (IsValidSize(tmpCount)) + { + // + for (int j = 0; j < tmpCount; j++) + { + // + XPVPivot jPivot = tmp[j]; + + // + // Check Bullish Direction ... + isBullish = + canLookupForBullish && + jPivot.lower >= iPivot.lower; + if (!isBullish) + { + canLookupForBullish = false; + } + + // + // Check Bearish Direction ... + isBearish = + canLookupForBearish && + jPivot.upper <= iPivot.upper; + if (!isBearish) + { + canLookupForBearish = false; + } + + // + if (!canLookupForBullish && + !canLookupForBearish) + { + break; + } + } + } + Clean(tmp); + } + + // + if (isBullish && + !isBearish) + { + dir = X_DIRECTION_BULLISH; + } + else if (isBearish && + !isBullish) + { + dir = X_DIRECTION_BEARISH; + } + + // + result = dir != X_DIRECTION_NONE; + + // + return result; +} + // \ No newline at end of file diff --git a/X121SMCEA/Strategy/x-121.smc.test.strategy.class.mq5 b/X121SMCEA/Strategy/x-121.smc.test.strategy.class.mq5 index cc155d3b..757dacce 100644 --- a/X121SMCEA/Strategy/x-121.smc.test.strategy.class.mq5 +++ b/X121SMCEA/Strategy/x-121.smc.test.strategy.class.mq5 @@ -174,50 +174,6 @@ class XCX121SMCTestStrategy : public XCX121SMCBaseStrategy return result; } - // - conditions.symbol = _symbol; - conditions.period = _period; - conditions.time = TimeCurrent(); - - // - int conditionsLoopback = 7; - - // - // XPV ... - result = xpvHelper.GetConditions( - conditions.xpvConditions, - cIndex, - conditionsLoopback // - ); - if (!result) - { - return result; - } - - // - // X3MA ... - result = x3maHelper.GetConditions( - conditions.x3maConditions, - cIndex, - conditionsLoopback // - ); - if (!result) - { - return result; - } - - // - // X3VWAP ... - result = x3vwapHelper.GetConditions( - conditions.x3vwapConditions, - cIndex, - conditionsLoopback // - ); - if (!result) - { - return result; - } - // // Try to Implement SMC Based Conditions ... result = DetectConditions(conditions); @@ -371,6 +327,137 @@ class XCX121SMCTestStrategy : public XCX121SMCBaseStrategy // bool result = false; + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + int zIndex = 0; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + conditions.symbol = symbol; + conditions.period = period; + conditions.time = TimeCurrent(); + + // + int conditionsLoopback = 7; + + // + // XPV ... + result = xpvHelper.GetConditions( + conditions.xpvConditions, + cIndex, + conditionsLoopback // + ); + if (!result) + { + return result; + } + + // + // X3MA ... + result = x3maHelper.GetConditions( + conditions.x3maConditions, + cIndex, + conditionsLoopback // + ); + if (!result) + { + return result; + } + + // + // X3VWAP ... + result = x3vwapHelper.GetConditions( + conditions.x3vwapConditions, + cIndex, + conditionsLoopback // + ); + if (!result) + { + return result; + } + + // + // Detect Swing Highs and Lows Based On XPV ... + + // + int samePivots = 40; + int requiredPivots = 10; + + // + DetectPVPivots( + cIndex, + samePivots, + requiredPivots, + conditions.orderFlow // + ); + + // + int orderFlowCount = ArraySize(conditions.orderFlow); + if (IsValidSize(orderFlowCount)) + { + // + for (int i = 0; i < orderFlowCount; i++) + { + // + XPVPivot iPivot = conditions.orderFlow[i]; + + // + XCXPVPivotObject *iObj; + iObj = new XCXPVPivotObject(); + bool isCreated = iObj.Create( + mPOIDrawer.ChartIdentification(), + mPOIDrawer.SubWindowIdentification(), + iPivot // + ); + if (isCreated) + { + // + if (iPivot.IsPeak()) + { + // + iObj.PivotWidth(1); + iObj.PivotFill(false); + iObj.PivotColor(clrAqua); + iObj.PivotStyle(STYLE_SOLID); + } + + // + if (iPivot.IsVale()) + { + // + iObj.PivotWidth(1); + iObj.PivotFill(false); + iObj.PivotStyle(STYLE_SOLID); + iObj.PivotColor(clrMagenta); + } + + // + AddObjectIfNotExists(iObj); + } + } + } + + // + result = IsValidSize(ArraySize(conditions.orderFlow)); + if (!result) + { + return result; + } + + // + // Filter Peaks and Vales ... + + if (result) + { + Print("Result: ", result); + } + return false; + // // Detect Market Structures ... @@ -820,6 +907,298 @@ class XCX121SMCTestStrategy : public XCX121SMCBaseStrategy return result; } + /** + * Detect XPV Based POI(s) ... + * + * @param barIndex: Start Bar Index ... + * @param minRepetition: minimum Repeate of POI for Validation ... + * @param requiredPivots: Number of Min Requirement POI(s) ... + * @param peaks: XPVPivot instance Array Reference ... + * @param vales: XPVPivot instance Array Reference ... + * @param maxAllowedLoopbackBars: Integer, Max Allowed Loopback Bars ... + * + * @return ( bool ) + */ + bool DetectPVPivots( + int barIndex, + int minRepetition, + int requiredPivots, + XPVPivot &orderFlow[], // OrderFlows ... + int maxAllowedLoopbackBars = 576 // + ) + { + // + bool result = false; + + // + if (maxAllowedLoopbackBars <= 0) + { + maxAllowedLoopbackBars = 1000; + } + + // + int start = barIndex; + int end = start + maxAllowedLoopbackBars; + + // + Clean(orderFlow); + + // + result = minRepetition > 0 && + requiredPivots > 0; + if (!result) + { + return result; + } + + // + string symbol = GetSymbol(); + ENUM_TIMEFRAMES period = GetPeriod(); + + // + double peak = 0; + XPVPivot peaks[]; + int peakRepeate = 0; + int peakToBarIndex = 0; + int peakFromBarIndex = 0; + + // + double vale = 0; + XPVPivot vales[]; + int valeRepeate = 0; + int valeToBarIndex = 0; + int valeFromBarIndex = 0; + + // + bool canLookupPeak = true; + bool canLookupVale = true; + bool canLookup = true; + while (canLookup) + { + // + // Check Peak ... + double iPeak = xpvHelper.GetPeak(barIndex); + if (iPeak != peak) + { + // + if (peak != 0 && + peakRepeate >= minRepetition) + { + // + bool isExists = false; + int count = ArraySize(peaks); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XPVPivot iPivot = peaks[i]; + + // + if (iPivot.upper == iPeak) + { + // + isExists = true; + break; + } + } + } + if (!isExists) + { + // + XPVPivot iPivot; + + // + iPivot.lower = 0; + iPivot.upper = peak; + iPivot.symbol = symbol; + iPivot.period = period; + iPivot.type = XPV_PEAK; + iPivot.repetition = peakRepeate; + iPivot.to = iTime( + symbol, + period, + peakToBarIndex // + ); + iPivot.from = iTime( + symbol, + period, + peakFromBarIndex // + ); + + // + iPivot.lower = iPivot.CalculateLower(); + + // + bool isValid = iPivot.IsValid(); + if (isValid) + { + // + AddRef( + iPivot, + peaks // + ); + } + } + } + + // + peak = iPeak; + peakRepeate = 0; + peakFromBarIndex = 0; + peakToBarIndex = barIndex; + } + else if (iPeak == peak) + { + // + peakRepeate++; + peakFromBarIndex = barIndex; + } + + // + // Check Vale ... + double iVale = xpvHelper.GetVale(barIndex); + if (iVale != vale) + { + // + if (vale != 0 && + valeRepeate >= minRepetition) + { + // + bool isExists = false; + int count = ArraySize(vales); + if (IsValidSize(count)) + { + // + for (int i = 0; i < count; i++) + { + // + XPVPivot iPivot = vales[i]; + + // + if (iPivot.lower == iVale) + { + // + isExists = true; + break; + } + } + } + if (!isExists) + { + // + XPVPivot iPivot; + + // + iPivot.upper = 0; + iPivot.lower = vale; + iPivot.symbol = symbol; + iPivot.period = period; + iPivot.type = XPV_VALE; + iPivot.repetition = valeRepeate; + iPivot.to = iTime( + symbol, + period, + valeToBarIndex // + ); + iPivot.from = iTime( + symbol, + period, + valeFromBarIndex // + ); + + // + iPivot.upper = iPivot.CalculateUpper(); + + // + bool isValid = iPivot.IsValid(); + if (isValid) + { + // + AddRef( + iPivot, + vales // + ); + } + } + } + + // + vale = iVale; + valeRepeate = 0; + valeFromBarIndex = 0; + valeToBarIndex = barIndex; + } + else if (iVale == vale) + { + // + valeRepeate++; + valeFromBarIndex = barIndex; + } + + // + canLookupPeak = ArraySize(peaks) < requiredPivots; + canLookupVale = ArraySize(vales) < requiredPivots; + canLookup = barIndex < end && + (canLookupPeak || + canLookupVale); + if (canLookup) + { + barIndex++; + } + } + + // + result = IsValidSize(ArraySize(peaks)) || + IsValidSize(ArraySize(vales)); + if (!result) + { + return result; + } + + // + // Detect Order Flow ... + Copy( + peaks, + orderFlow, + false // + ); + Copy( + vales, + orderFlow, + false // + ); + int count = ArraySize(orderFlow); + result = IsValidSize(orderFlow); + if (!result) + { + return result; + } + + // + // Sort Pivots ... + SortPivots(orderFlow); + + // + // Filter Broken Order Flows ... + FilterBrokenPivots(orderFlow); + + // + ENUM_X_DIRECTION orderFlowDirection; + result = DetectPivotDirection( + orderFlow, + orderFlowDirection // + ); + if (!result) + { + return result; + } + + // + return result; + } + /** * Detect Specified States Market Structure ... *