diff --git a/Indicators/x-saherelm.x121.xczone.mq5 b/Indicators/x-saherelm.x121.xczone.mq5 index 62b40548..8f1f4be6 100644 --- a/Indicators/x-saherelm.x121.xczone.mq5 +++ b/Indicators/x-saherelm.x121.xczone.mq5 @@ -34,34 +34,51 @@ // // Inputs ... input group "Market"; -input int minZoneLength = 7; // Minimum Length of Consolidation Zone -input double maxZoneRangeInPoints = 0; // Max Zone Range in Point +input int minZoneLength = 15; // Minimum Length of Consolidation Zone +input double maxZoneRangeInPoints = 0; // Max Zone Range in Point input ENUM_X_PERIOD_METHOD trendPeriodMethod = X_PERIOD_AUTO; // How to Find Trend Period input ENUM_TIMEFRAMES trendPeriod = NULL; // Trend Time Period input ENUM_MA_METHOD trendMode = MODE_SMA; // Trend Mode input ENUM_APPLIED_PRICE trendAppliedTo = PRICE_CLOSE; // Trend Applied To input double sarStep = 0.02; // Sar Step input double sarMax = 0.2; // Sar Maximum +input int adxLength = 14; // ADX Length +input double adxThreshold = 25.0; // ADX Threshold +input int rsiLength = 14; // RSI Length +input double rsiOBLevel = 70.0; // RSI OB Level +input double rsiOSLevel = 30.0; // RSI OS Level +input ENUM_APPLIED_PRICE rsiAppliedTo = PRICE_CLOSE; // RSI Applied To + +// +// Validating ... +input group "Validating"; +input bool forceGapBarsBreakout = true; // Force Zone's Gap Bar's Breakes Out +input bool forceHasSwing = true; // Force Zone's Has Propper Swing // // Filtering ... input group "Filtering"; -input bool filterBasedOnSar = true; // Filter Pivots Based on Sar -input bool filterBasedOnTrend = false; // Filter Pivots Based on Trend +input bool filterBasedOnSar = false; // Filter Pivots Based on Sar +input bool filterBasedOnRSI = false; // Filter Pivots Based on RSI +input bool filterBasedOnADX = false; // Filter Pivots Based on ADX +input bool filterBasedOnTrend = false; // Filter Pivots Based on Trend +input bool filterBasedOnAnalysePivots = false; // Filter Pivots Based on Analyse Pivots // // Presentation ... input group "Presentation"; -input bool showUpper = true; // Show Upper -input bool showLower = true; // Show Lower -input bool showTrend = false; // Show Trend -input bool showSar = false; // Show Sar +input bool showSar = false; // Show Sar +input bool showTrend = false; // Show Trend +input bool rayLeft = false; // Ray to Left +input bool drawAnalysePivots = false; // Draw Analyse Pivots +input int boxWidth = 2; // Box Width +input color bullishColor = clrLime; // Bullish Color +input color bearishColor = clrRed; // Bearish Color +input ENUM_LINE_STYLE boxStyle = STYLE_SOLID; // Box Style // -input int startCalculationForLastBars = 1000; // Calculate Last n Bars +input int startCalculationForLastBars = 5000; // Calculate Last n Bars int sarArrowCode = 159; // Sar Arrow Code -int upperArrowCode = 117; // Upper Arrow Code -int lowerArrowCode = 117; // Lower Arrow Code // // Buffers ... @@ -84,81 +101,53 @@ int lowerArrowCode = 117; // Lower Arrow Code #property indicator_chart_window // -#property indicator_buffers 8 -#property indicator_plots 4 +#property indicator_buffers 10 +#property indicator_plots 2 // // Plot Buffers ... -// -// UPPER ... - -// -#define upperBufferIndex 0 -double upperBuffer[]; - -// -#property indicator_label1 "X121 Upper" -#property indicator_type1 DRAW_ARROW -#property indicator_color1 clrOrange -#property indicator_style1 STYLE_SOLID -#property indicator_width1 2 - -// -// LOWER ... - -// -#define lowerBufferIndex 1 -double lowerBuffer[]; - -// -#property indicator_label2 "X121 Lower" -#property indicator_type2 DRAW_ARROW -#property indicator_color2 clrOrange -#property indicator_style2 STYLE_DASHDOTDOT -#property indicator_width2 2 - // // TREND ... // -#define trendBufferIndex 2 -#define trendBufferPlotIndex 2 +#define trendBufferIndex 0 +#define trendBufferPlotIndex 0 double trendBuffer[]; // -#define trendColorBufferIndex 3 +#define trendColorBufferIndex 1 double trendColorBuffer[]; // -#property indicator_label3 "X121 Trend" -#property indicator_type3 DRAW_COLOR_LINE -#property indicator_color3 CLR_NONE, clrAqua, clrMagenta, clrGray -#property indicator_style3 STYLE_DASH -#property indicator_width3 2 +#property indicator_label1 "X121 Trend" +#property indicator_type1 DRAW_COLOR_LINE +#property indicator_color1 CLR_NONE, clrAqua, clrMagenta, clrGray +#property indicator_style1 STYLE_DASH +#property indicator_width1 2 // // SAR ... // -#define sarBufferIndex 4 -#define sarBufferPlotIndex 3 +#define sarBufferIndex 2 +#define sarBufferPlotIndex 2 double sarBuffer[]; // -#define sarColorBufferIndex 5 +#define sarColorBufferIndex 3 double sarColorBuffer[]; // -#property indicator_label4 "X121 SAR" -#property indicator_type4 DRAW_COLOR_ARROW -#property indicator_color4 CLR_NONE, clrAqua, clrMagenta, clrGray -#property indicator_width4 2 +#property indicator_label2 "X121 SAR" +#property indicator_type2 DRAW_COLOR_ARROW +#property indicator_color2 CLR_NONE, clrAqua, clrMagenta, clrGray +#property indicator_width2 2 // // Data Buffers ... -#define mLastBufferIndex 5 +#define mLastBufferIndex 3 // #define trendStateBufferIndex mLastBufferIndex + 1 @@ -168,6 +157,22 @@ double trendStateBuffer[]; #define sarStateBufferIndex mLastBufferIndex + 2 double sarStateBuffer[]; +// +#define rsiBufferIndex mLastBufferIndex + 3 +double rsiBuffer[]; + +// +#define adxBufferIndex mLastBufferIndex + 4 +double adxBuffer[]; + +// +#define adxpBufferIndex mLastBufferIndex + 5 +double adxpBuffer[]; + +// +#define adxnBufferIndex mLastBufferIndex + 6 +double adxnBuffer[]; + // // Variables, Properties and etc ... @@ -178,11 +183,16 @@ int limit; int maxLength; // -XCPOIDrawer *drawer; +double mPoints = 0; CArrayObj mObjects; +XCPOIDrawer *drawer; +XBoxZone analyseOBs[]; +XBoxZone analysePivot; XCBarAnalyser *barAnalyser; int mTrendPeriodLength = 0; int sarHandler = INVALID_HANDLE; +int rsiHandler = INVALID_HANDLE; +int adxHandler = INVALID_HANDLE; int trendHandler = INVALID_HANDLE; ENUM_TIMEFRAMES mTrendPeriod = NULL; @@ -245,6 +255,33 @@ int OnInit() return INIT_FAILED; } + // + // RSI ... + rsiHandler = iRSI( + _Symbol, + _Period, + rsiLength, + rsiAppliedTo // + ); + isInited = rsiHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + + // + // ADX ... + adxHandler = iADX( + _Symbol, + _Period, + adxLength // + ); + isInited = adxHandler != INVALID_HANDLE; + if (!isInited) + { + return INIT_FAILED; + } + // // TREND ... trendHandler = iMA( @@ -261,6 +298,9 @@ int OnInit() return INIT_FAILED; } + // + mPoints = GetPoints(_Symbol); + // // because in some cases we may have more than one input for // calculation and we must prevent any calculation @@ -300,6 +340,10 @@ void OnDeinit(const int reason) // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value // REASON_CLOSE 9 Terminal closed + // + Clean(analyseOBs); + analysePivot.Clean(); + // mObjects.Clear(); ZeroMemory(drawer); @@ -307,6 +351,8 @@ void OnDeinit(const int reason) // IndicatorRelease(sarHandler); + IndicatorRelease(rsiHandler); + IndicatorRelease(adxHandler); IndicatorRelease(trendHandler); } @@ -357,6 +403,14 @@ int OnCalculate( // SAR ... int sarCalculatedBars = BarsCalculated(sarHandler); + // + // RSI ... + int rsiCalculatedBars = BarsCalculated(rsiHandler); + + // + // ADX ... + int adxCalculatedBars = BarsCalculated(adxHandler); + // // TREND ... int trendCalculatedBars = BarsCalculated(trendHandler); @@ -367,6 +421,12 @@ int OnCalculate( // SAR ... sarCalculatedBars >= maxLength && // + // RSI ... + rsiCalculatedBars >= maxLength && + // + // ADX ... + adxCalculatedBars >= maxLength && + // // TREND ... trendCalculatedBars >= maxLength // @@ -386,7 +446,23 @@ int OnCalculate( // // SAR ... - int copiedSars = CopyBuffer(sarHandler, 0, 0, limit, sarBuffer); + int copiedSars = CopyBuffer(sarHandler, MAIN_LINE, 0, limit, sarBuffer); + + // + // RSI ... + int copiedRSIs = CopyBuffer(rsiHandler, MAIN_LINE, 0, limit, rsiBuffer); + + // + // ADX ... + int copiedADXs = CopyBuffer(adxHandler, MAIN_LINE, 0, limit, adxBuffer); + + // + // ADX Plus ... + int copiedADXPs = CopyBuffer(adxHandler, PLUSDI_LINE, 0, limit, adxpBuffer); + + // + // ADX Negative ... + int copiedADXNs = CopyBuffer(adxHandler, MINUSDI_LINE, 0, limit, adxnBuffer); // // TREND ... @@ -399,6 +475,9 @@ int OnCalculate( // SAR ... copiedSars >= limit && // + // RSI ... + copiedRSIs >= limit && + // // TREND ... copiedTrends >= limit // @@ -448,6 +527,10 @@ bool ValidateInputs() // sarMax > 0 && sarStep > 0 && + adxLength > 0 && + rsiLength > 0 && + rsiOBLevel > 0 && + rsiOSLevel > 0 && sarMax > sarStep && minZoneLength > 2 && IsValid(trendPeriodMethod, trendPeriod) @@ -469,7 +552,8 @@ int ExtractMaxLengthOfInputs() int result = 0; // - result = MathMax(minZoneLength, result); + result = MathMax(minZoneLength, rsiLength); + result = MathMax(result, adxLength); // return result; @@ -483,42 +567,6 @@ void DefineBuffers() // // Plot Buffers ... - // - // UPPER ... - - // - ENUM_DRAW_TYPE upperDrawType = showUpper ? DRAW_ARROW : DRAW_NONE; - - // - ArraySetAsSeries(upperBuffer, true); - SetIndexBuffer(upperBufferIndex, upperBuffer, INDICATOR_DATA); - - // - PlotIndexSetInteger(upperBufferIndex, PLOT_SHOW_DATA, showUpper); - PlotIndexSetInteger(upperBufferIndex, PLOT_DRAW_TYPE, upperDrawType); - - // - PlotIndexSetDouble(upperBufferIndex, PLOT_EMPTY_VALUE, emptyValue); - PlotIndexSetInteger(upperBufferIndex, PLOT_ARROW, upperArrowCode); - - // - // LOWER ... - - // - ENUM_DRAW_TYPE lowerDrawType = showLower ? DRAW_ARROW : DRAW_NONE; - - // - ArraySetAsSeries(lowerBuffer, true); - SetIndexBuffer(lowerBufferIndex, lowerBuffer, INDICATOR_DATA); - - // - PlotIndexSetInteger(lowerBufferIndex, PLOT_SHOW_DATA, showLower); - PlotIndexSetInteger(lowerBufferIndex, PLOT_DRAW_TYPE, lowerDrawType); - - // - PlotIndexSetDouble(lowerBufferIndex, PLOT_EMPTY_VALUE, emptyValue); - PlotIndexSetInteger(lowerBufferIndex, PLOT_ARROW, lowerArrowCode); - // // TREND ... @@ -564,6 +612,22 @@ void DefineBuffers() // ArraySetAsSeries(sarStateBuffer, true); SetIndexBuffer(sarStateBufferIndex, sarStateBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(rsiBuffer, true); + SetIndexBuffer(rsiBufferIndex, rsiBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(adxBuffer, true); + SetIndexBuffer(adxBufferIndex, adxBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(adxpBuffer, true); + SetIndexBuffer(adxpBufferIndex, adxpBuffer, INDICATOR_CALCULATIONS); + + // + ArraySetAsSeries(adxnBuffer, true); + SetIndexBuffer(adxnBufferIndex, adxnBuffer, INDICATOR_CALCULATIONS); } /** @@ -636,14 +700,6 @@ void CalculateBuffers( */ void FillBuffersZero(int barIndex) { - // - // UPPER ... - upperBuffer[barIndex] = emptyValue; - - // - // LOWER ... - lowerBuffer[barIndex] = emptyValue; - // // SAR ... sarBuffer[barIndex] = emptyValue; @@ -751,6 +807,19 @@ void CalculateValues( trendStateBuffer[bar_index] = iTrendState; trendColorBuffer[bar_index] = iTrendColor; + // + DetectTriggerZone( + bar_index, + prevCalculated, + ratesTotal, + open, + high, + close, + low, + tickVolume // + ); + return; + // // Prevent Calculation ... if (maxBarIndex - bar_index < minZoneLength) @@ -992,10 +1061,17 @@ void CalculateValues( ); iZone.from = iFrom; + // + toIDX = iZone.ToIndex(); + fromIDX = iZone.FromIndex(); + // // Apply Filters ... has = filterBasedOnSar || - filterBasedOnTrend; + filterBasedOnRSI || + filterBasedOnADX || + filterBasedOnTrend || + filterBasedOnAnalysePivots; if (has) { // @@ -1070,60 +1146,216 @@ void CalculateValues( } } + // + // Apply Using RSI ... + if (filterBasedOnRSI) + { + // + double iBarRSI = rsiBuffer[iBarIndex]; + double iBarPrevRSI = rsiBuffer[iBarPrevIndex]; + + // + bool isIBarRSICrossedOverOS = + iBarRSI > rsiOSLevel && + iBarPrevRSI < rsiOSLevel; + bool isIBarRSICrossedUnderOB = + iBarRSI < rsiOBLevel && + iBarPrevRSI > rsiOBLevel; + + // + double iPBarRSI = rsiBuffer[ipBarIndex]; + double iPBarPrevRSI = rsiBuffer[ipBarPrevIndex]; + + // + bool isIPBarRSICrossedOverOS = + iPBarRSI > rsiOSLevel && + iPBarPrevRSI < rsiOSLevel; + bool isIPBarRSICrossedUnderOB = + iPBarRSI < rsiOBLevel && + iPBarPrevRSI > rsiOBLevel; + + // + bool isBullishRSIFiltered = + isBullish && + (isIBarRSICrossedOverOS || + isIPBarRSICrossedOverOS); + + // + bool isBearishRSIFiltered = + isBearish && + (isIBarRSICrossedUnderOB || + isIPBarRSICrossedUnderOB); + + // + has = isBullishRSIFiltered || + isBearishRSIFiltered; + if (!has) + { + // + iBar.Clean(); + iPBar.Clean(); + iZone.Clean(); + fromBar.Clean(); + + // + return; + } + } + + // + // Apply Using ADX ... + if (filterBasedOnADX) + { + // + // Reading Required Values ... + + // + double iBarADX = adxBuffer[iBarIndex]; + double iBarPrevADX = adxBuffer[iBarPrevIndex]; + + // + bool iBarADXP = adxpBuffer[iBarIndex]; + bool iBarPrevADXP = adxpBuffer[iBarPrevIndex]; + + // + bool iBarADXN = adxnBuffer[iBarIndex]; + bool iBarPrevADXN = adxnBuffer[iBarPrevIndex]; + + // + // Creating Some Conditions ... + + // + bool isIADXBullish = iBarADXP > iBarADXN; + bool isIADXBullishPrev = iBarPrevADXP > iBarPrevADXN; + + // + bool isIADXBearish = iBarADXN > iBarADXP; + bool isIADXBearishPrev = iBarPrevADXN > iBarPrevADXP; + + // + bool isIADXUp = + adxThreshold > 0 + ? iBarADX > adxThreshold + : true; + bool isIADXUpPrev = + adxThreshold > 0 + ? iBarPrevADX > adxThreshold + : true; + + // + bool isIADXDown = + adxThreshold > 0 + ? iBarADX < adxThreshold + : true; + bool isIADXDownPrev = + adxThreshold > 0 + ? iBarPrevADX < adxThreshold + : true; + + // + bool isIADXSwitchedToBullish = isIADXBullish && + !isIADXBullishPrev; + + // + bool isIADXSwitchedToBearish = isIADXBearish && + !isIADXBearishPrev; + + // + bool isIADXSwitchedUp = isIADXUp && + !isIADXUpPrev; + + // + bool isIADXSwitchedDown = isIADXDown && + !isIADXDownPrev; + + // + // Summarize Filtering ... + + // + bool isBullishADXFiltered = + isBullish && + // (isIADXUp || + // isIADXSwitchedUp) && + (isIADXBullish || + isIADXSwitchedToBullish); + + // + bool isBearishADXFiltered = + isBearish && + // (isIADXDown || + // isIADXSwitchedDown) && + (isIADXBearish || + isIADXSwitchedToBearish); + + // + has = isBullishADXFiltered || + isBearishADXFiltered; + if (!has) + { + // + iBar.Clean(); + iPBar.Clean(); + iZone.Clean(); + fromBar.Clean(); + + // + return; + } + } + // // Apply Using Trend ... if (filterBasedOnTrend) { // - double iBarTrendState = trendStateBuffer[iBarIndex]; - double iBarPrevTrendState = trendStateBuffer[iBarPrevIndex]; + // Check and Validate Box using Trend ... + // bearish boxs high must above trend + // bullish box low must below trend // - double iPBarTrendState = trendStateBuffer[ipBarIndex]; - double iPBarPrevTrendState = trendStateBuffer[ipBarPrevIndex]; + double iTrend = 0; + bool isBullishTrendPassed = true; + bool isBearishTrendPassed = true; + for (int i = fromIDX; i >= toIDX; i--) + { + // + iTrend = trendBuffer[i]; - // - bool isIBarTrendBullish = iBarTrendState > 0; - bool isIBarPrevTrendBullish = iBarPrevTrendState > 0; + // + if (isBullishTrendPassed) + { + // + isBullishTrendPassed = + isBullishTrendPassed && + iZone.lower < iTrend; + } - // - bool isIBarTrendBearish = iBarTrendState < 0; - bool isIBarPrevTrendBearish = iBarPrevTrendState < 0; + // + if (isBearishTrendPassed) + { + // + isBearishTrendPassed = + isBearishTrendPassed && + iZone.upper > iTrend; + } - // - bool isITrendSwitchedToBullish = isIBarTrendBullish && - !isIBarPrevTrendBullish; - bool isITrendSwitchedToBearish = isIBarTrendBearish && - !isIBarPrevTrendBearish; - - // - bool isIPBarTrendBullish = iPBarTrendState > 0; - bool isIPBarPrevTrendBullish = iPBarPrevTrendState > 0; - - // - bool isIPBarTrendBearish = iPBarTrendState < 0; - bool isIPBarPrevTrendBearish = iPBarPrevTrendState < 0; - - // - bool isIPTrendSwitchedToBullish = isIPBarTrendBullish && - !isIPBarPrevTrendBullish; - bool isIPTrendSwitchedToBearish = isIPBarTrendBearish && - !isIPBarPrevTrendBearish; - - // - // Check iPBar (Gap Bar which Breaks Edge and is a Momentum Bar) is Trend Change Bar ... + // + if (!isBullishTrendPassed && + !isBearishTrendPassed) + { + break; + } + } // bool isBullishTrendFiltered = isBullish && - (isITrendSwitchedToBullish || - isIPTrendSwitchedToBullish); + isBullishTrendPassed; // bool isBearishTrendFiltered = isBearish && - (isITrendSwitchedToBearish || - isIPTrendSwitchedToBearish); + isBearishTrendPassed; // has = isBullishTrendFiltered || @@ -1140,17 +1372,120 @@ void CalculateValues( return; } } + + // + // Apply Using Analyse Pivots ... + // IsValid(analysePeriod) && + // HasChild(analyseOBs) && + if (analysePivot.IsValid() && + filterBasedOnAnalysePivots) + { + // + has = false; + // for (int i = 0; i < ArraySize(analyseOBs); i++) + // { + // // + // has = + // iZone.dir == analyseOBs[i].dir && + // ( + // // + // (iZone.upper < analyseOBs[i].upper && + // iZone.lower > analyseOBs[i].lower) || + // (iZone.lower < analyseOBs[i].upper && + // iZone.lower > analyseOBs[i].lower) || + // (iZone.upper > analyseOBs[i].lower && + // iZone.upper < analyseOBs[i].upper) + // // + // ); + // if (has) + // { + // break; + // } + // } + + // + has = + iZone.dir == analysePivot.dir && + ( + // + (iZone.upper < analysePivot.upper && + iZone.lower > analysePivot.lower) || + (iZone.lower < analysePivot.upper && + iZone.lower > analysePivot.lower) || + (iZone.upper > analysePivot.lower && + iZone.upper < analysePivot.upper) + // + ); + + // + if (!has) + { + // + iBar.Clean(); + iPBar.Clean(); + iZone.Clean(); + fromBar.Clean(); + + // + return; + } + } } // - // Fill Buffers Based on Object ... - toIDX = iZone.ToIndex(); fromIDX = iZone.FromIndex(); - for (int i = fromIDX; i > toIDX; i--) + + // + // Find Base of Movement ... + if (rayLeft) { // - upperBuffer[i] = iZone.upper; - lowerBuffer[i] = iZone.lower; + XOHCL tmpBar; + int start = fromIDX + 1; + bool isBaseValid = true; + while (isBaseValid) + { + // + has = tmpBar.Init( + _Symbol, + _Period, + start // + ); + if (!has) + { + // + tmpBar.Clean(); + break; + } + + // + bool isBullishPassed = + isBullish && + tmpBar.low >= iZone.lower; + + // + bool isBearishPassed = + isBearish && + tmpBar.high <= iZone.upper; + + // + has = + isBullishPassed || + isBearishPassed; + if (!has) + { + break; + } + + // + start++; + } + has = tmpBar.IsValid(); + if (has) + { + iZone.from = tmpBar.time; + } + tmpBar.Clean(); } // @@ -1162,6 +1497,10 @@ void CalculateValues( ); if (has) { + // + ApplyStyle(iZoneObj, iZone.dir); + + // mObjects.Add(iZoneObj); } ZeroMemory(iZoneObj); @@ -1175,4 +1514,1282 @@ void CalculateValues( iZone.Clean(); } +// +void DetectTriggerZone( + int bar_index, // Selected Bar Index + const int prevCalculated, + const int ratesTotal, + const double &open[], + const double &high[], + const double &close[], + const double &low[], + const long &tickVolume[] // +) +{ + // + // Check Prev Bar ... + + // + int lastBarIndex = bar_index + 1; + int maxBarIndex = startCalculationForLastBars > 0 + ? startCalculationForLastBars + : ratesTotal; + bool isFirstBar = + bar_index == maxBarIndex; + + // + // Prevent Calculation ... + if (maxBarIndex - bar_index < minZoneLength) + { + return; + } + + // + int zIDX = 0; + int cIDX = 0; + int pIDX = 0; + int p2IDX = 0; + int p3IDX = 0; + int p4IDX = 0; + double ll = 0; + double hh = 0; + bool has = false; + ENUM_X_DIRECTION iDir; + + // + // Retrieve Required Bars ... + + // + XOHCL zBar; // Current Start Checking Bar (Usually Used for Triggering) ... + XOHCL cBar; // Current Finished Bar which Start Detecting Structures based on it ( End of Block and FVG Bar ) ... + XOHCL pBar; // Determines Block Gap Bar (all Filtering must applied and Check using this Bar and it's Next Bar) ... + XOHCL p2Bar; // Determines FVG's Start Bar in a Block ... + XOHCL p3Bar; // First Verification of Block ... + XOHCL p4Bar; // Seccond Verification of Block ... + + // + has = zBar.Init( + _Symbol, + _Period, + bar_index // + ); + has = + has && + zBar.GetPreviousBar(cBar); + has = + has && + cBar.GetPreviousBar(pBar); + has = + has && + pBar.GetPreviousBar(p2Bar); + has = + has && + p2Bar.GetPreviousBar(p3Bar); + has = + has && + p3Bar.GetPreviousBar(p4Bar); + if (!has) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + return; + } + + // + // Define Zone Structure ... + XBoxZone zone; + + // + // Detect Based Order Block using CBar ... + has = barAnalyser.IsOB( + cBar, + zone, + true, // Force FVG Bar Type ... + true // Force Block Two Bar Checking ... + ); + + // + // Ensure a Block is Detected ... + if (!has) + { + // + zone.Clean(); + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + return; + } + + // + zIDX = zBar.Index(); + cIDX = cBar.Index(); + pIDX = pBar.Index(); + p2IDX = p2Bar.Index(); + p3IDX = p3Bar.Index(); + p4IDX = p4Bar.Index(); + + // + bool isBullish = + has && + zone.IsBullish(); + + // + bool isBearish = + has && + zone.IsBearish(); + + // + int toIDX = zone.ToIndex(); + int fromIDX = zone.FromIndex(); + + // + // Validating p2Bar and p3Bar Direction ... + if (has) + { + // + iDir = Opposit(zone.dir); + + // + has = + iDir == p3Bar.GetDirection() || + iDir == p4Bar.GetDirection(); + if (!has) + { + // + zone.Clean(); + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + return; + } + } + + // + // Start Validating Block based on + // Detected One ... + + // + // Validating Using Max Range ... + has = maxZoneRangeInPoints > 0; + if (has) + { + // + double range = zone.GetRange(); + has = range <= maxZoneRangeInPoints * mPoints; + if (!has) + { + // + zone.Clean(); + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + return; + } + } + + // + // Validating Gap Bar must a Momentum Bar and + // Breakes out Zone's Directional Edge ... + // for Bullish: Upper + // for Bearish: Lower + has = forceGapBarsBreakout; + if (has) + { + // + // Gap Bar is PBar ... + + // + // Check Gap Bar is Momentum Bar ... + has = barAnalyser.IsMomentum( + pBar, + iDir // + ); + bool isBullishMomentum = + has && + IsBullish(iDir); + bool isBearishMomentum = + has && + IsBearish(iDir); + + // + // Check Gap Bar's Breakout ... + + // + bool isBullishBreakedout = + isBullish && + pBar.IsBullish() && + isBullishMomentum && + pBar.GetUp() > zone.upper && + pBar.GetDown() < zone.upper; + + // + bool isBearishBreakedout = + isBearish && + pBar.IsBearish() && + isBearishMomentum && + pBar.GetUp() > zone.lower && + pBar.GetDown() < zone.lower; + + // + has = isBullishBreakedout || + isBearishBreakedout; + if (!has) + { + // + zone.Clean(); + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + return; + } + } + + // + // Validate Zone Has Propper Swing ... + // for Bullish: p2Bar or p3Bar must be a Swing Low ... + // for Bearish: p2Bar or p3Bar must be a Swing High ... + has = forceHasSwing; + if (has) + { + // + // p2Bar ... + bool isP2BarSwing = + barAnalyser + .IsSimpleSwing( + p2Bar, + iDir // + ); + bool isP2BarSwingLow = + isP2BarSwing && + IsBullish(iDir); + bool isP2BarSwingHigh = + isP2BarSwing && + IsBearish(iDir); + + // + // p3Bar ... + bool isP3BarSwing = + barAnalyser + .IsSimpleSwing( + p3Bar, + iDir // + ); + bool isP3BarSwingLow = + isP3BarSwing && + IsBullish(iDir); + bool isP3BarSwingHigh = + isP3BarSwing && + IsBearish(iDir); + + // + bool hasSwingLow = + isBullish && + (isP2BarSwingLow || + isP3BarSwingLow); + + // + bool hasSwingHigh = + isBearish && + (isP2BarSwingHigh || + isP3BarSwingHigh); + + // + has = + hasSwingLow || + hasSwingHigh; + if (!has) + { + // + zone.Clean(); + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + return; + } + } + + // + // Validating Using Swing Length ... + has = minZoneLength > 0; + if (has) + { + // + XOHCL fromBar; + has = zone.FromBar(fromBar); + if (has) + { + // + // Retrieve HH and LL ... + ll = fromBar.FindLowest(minZoneLength, MODE_LOW); + hh = fromBar.FindHighest(minZoneLength, MODE_HIGH); + + // + // Validate Using HH and LL ... + + // + bool isBullishValid = + isBullish && + ll >= zone.lower; + + // + bool isBearishValid = + isBearish && + hh <= zone.upper; + + // + has = isBullishValid || + isBearishValid; + if (!has) + { + // + zone.Clean(); + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + return; + } + + // + // Update Zone's From Time ... + zone.from = GetBarTime( + zone.symbol, + zone.period, + fromBar.Index() + minZoneLength // + ); + } + + // + fromBar.Clean(); + } + + // + // Here we Ensure which have a Valid Zone using Different Applied Validations ... + // from now we are Going to Filtered Validate Zones ... + + // + // Check Exists Filters or not ... + has = filterBasedOnSar || + filterBasedOnRSI || + filterBasedOnADX || + filterBasedOnTrend || + filterBasedOnAnalysePivots; + if (has) + { + // + // Do Apply Several Exists Filters ... + + // + // SAR Filter ... + if (filterBasedOnSar) + { + // + // Reading Conditions Values ... + + // + double zSar = sarBuffer[zIDX]; + double cSar = sarBuffer[cIDX]; + double pSar = sarBuffer[pIDX]; + double p2Sar = sarBuffer[p2IDX]; + double p3Sar = sarBuffer[p3IDX]; + double p4Sar = sarBuffer[p4IDX]; + + // + // Create Required Conditions ... + + // + bool isZSarBullish = zSar < zBar.low; + bool isZSarBearish = zSar > zBar.high; + + // + bool isCSarBullish = cSar < cBar.low; + bool isCSarBearish = cSar > cBar.high; + + // + bool isPSarBullish = pSar < pBar.low; + bool isPSarBearish = pSar > pBar.high; + + // + bool isP2SarBullish = p2Sar < p2Bar.low; + bool isP2SarBearish = p2Sar > p2Bar.high; + + // + bool isCSarSwitchedToBullish = + isZSarBullish && + isCSarBullish && + !isPSarBullish && + cBar.IsBullish() && + cBar.GetUp() > pSar; + + // + bool isCSarSwitchedToBearish = + isZSarBearish && + isCSarBearish && + !isPSarBearish && + cBar.IsBearish() && + cBar.GetDown() < pSar; + + // + bool isPSarSwitchedToBullish = + isZSarBullish && + isCSarBullish && + isPSarBullish && + !isP2SarBullish && + pBar.IsBullish() && + pBar.GetUp() > p2Sar; + + // + bool isPSarSwitchedToBearish = + isZSarBearish && + isCSarBearish && + isPSarBearish && + !isP2SarBearish && + pBar.IsBearish() && + pBar.GetDown() < p2Sar; + + // + // Summarize Filtering ... + + // + bool isBullishFiltered = + isBullish && + (isCSarSwitchedToBullish || + isPSarSwitchedToBullish); + + // + bool isBearishFiltered = + isBearish && + (isCSarSwitchedToBearish || + isPSarSwitchedToBearish); + + // + has = + isBullishFiltered || + isBearishFiltered; + if (!has) + { + // + zone.Clean(); + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + return; + } + } + + // + // RSI Filter ... + if (filterBasedOnRSI) + { + // + // Reading Conditions Values ... + + // + double rsiTrend = (rsiOBLevel + rsiOSLevel) / 2; + + // + double zRSI = rsiBuffer[zIDX]; + double cRSI = rsiBuffer[cIDX]; + double pRSI = rsiBuffer[pIDX]; + double p2RSI = rsiBuffer[p2IDX]; + double p3RSI = rsiBuffer[p3IDX]; + double p4RSI = rsiBuffer[p4IDX]; + + // + // Create Required Conditions ... + + // + bool isZRSIBullish = zRSI > rsiTrend; + bool isZRSIBearish = zRSI < rsiTrend; + + // + bool isCRSIBullish = cRSI > rsiTrend; + bool isCRSIBearish = cRSI < rsiTrend; + + // + bool isPRSIBullish = pRSI > rsiTrend; + bool isPRSIBearish = pRSI < rsiTrend; + + // + bool isP2RSIBullish = p2RSI > rsiTrend; + bool isP2RSIBearish = p2RSI < rsiTrend; + + // + bool isP3RSIBullish = p3RSI > rsiTrend; + bool isP3RSIBearish = p3RSI < rsiTrend; + + // + // Trending Conditions ... + + // + bool isCRSISwitchedToBullish = + isZRSIBullish && + isCRSIBullish && + !isPRSIBullish; + + // + bool isCRSISwitchedToBearish = + isZRSIBearish && + isCRSIBearish && + !isPRSIBearish; + + // + bool isPRSISwitchedToBullish = + isZRSIBullish && + isCRSIBullish && + isPRSIBullish && + !isP2RSIBullish; + + // + bool isPRSISwitchedToBearish = + isZRSIBearish && + isCRSIBearish && + isPRSIBearish && + !isP2RSIBearish; + + // + bool isP2RSISwitchedToBullish = + isZRSIBullish && + isCRSIBullish && + isPRSIBullish && + isP2RSIBullish && + !isP3RSIBullish; + + // + bool isP2RSISwitchedToBearish = + isZRSIBearish && + isCRSIBearish && + isPRSIBearish && + isP2RSIBearish && + !isP3RSIBearish; + + // + // Crosses Conditions ... + + // + bool isCBarCrossedOverOS = + zRSI > rsiOSLevel && + cRSI > rsiOSLevel && + pRSI <= rsiOSLevel; + + // + bool isCBarCrossedUnderOB = + zRSI < rsiOBLevel && + cRSI < rsiOBLevel && + pRSI >= rsiOBLevel; + + // + bool isPBarCrossedOverOS = + zRSI > rsiOSLevel && + cRSI > rsiOSLevel && + pRSI > rsiOSLevel && + p2RSI <= rsiOSLevel; + + // + bool isPBarCrossedUnderOB = + zRSI < rsiOBLevel && + cRSI < rsiOBLevel && + pRSI < rsiOBLevel && + p2RSI >= rsiOBLevel; + + // + // V Pattern Conditions ... + + // + bool isCRSIHasVBullishPattern = + zRSI >= cRSI && + cRSI > pRSI && + p2RSI > pRSI && + cRSI >= p2RSI; + + // + bool isCRSIHasVBearishPattern = + zRSI <= cRSI && + cRSI < pRSI && + p2RSI < pRSI && + cRSI <= p2RSI; + + // + // Continuation Conditions ... + + // + bool isRSIUp = + zRSI >= cRSI && + (cRSI >= pRSI || + pRSI >= p2RSI || + p2RSI >= p3RSI); + + // + bool isRSIDown = + zRSI <= cRSI && + (cRSI <= pRSI || + pRSI <= p2RSI || + p2RSI <= p3RSI); + + // + // Summarize Filtering ... + + // + bool isBullishFiltered = + isBullish && + ( + // + // Grows ... + isRSIUp + // + || + // + // Crosses ... + (isCBarCrossedOverOS || + isPBarCrossedOverOS) + // + || + // + // V Pattern ... + isCRSIHasVBullishPattern + // + || + // + // Trending ... + (isCRSISwitchedToBullish || + isPRSISwitchedToBullish || + isP2RSISwitchedToBullish) + // + ); + + // + bool isBearishFiltered = + isBearish && + ( + // + // Grows ... + isRSIDown + // + || + // + // Crosses ... + (isCBarCrossedUnderOB || + isPBarCrossedUnderOB) + // + || + // + // V Pattern ... + isCRSIHasVBearishPattern + // + || + // + // Trending ... + (isCRSISwitchedToBearish || + isPRSISwitchedToBearish || + isP2RSISwitchedToBearish) + // + ); + + // + has = + isBullishFiltered || + isBearishFiltered; + if (!has) + { + // + zone.Clean(); + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + return; + } + } + + // + // ADX Filter ... + if (filterBasedOnADX) + { + // + // Reading Conditions Values ... + + // + // ADX ... + double zADX = adxBuffer[zIDX]; + double cADX = adxBuffer[cIDX]; + double pADX = adxBuffer[pIDX]; + double p2ADX = adxBuffer[p2IDX]; + double p3ADX = adxBuffer[p3IDX]; + double p4ADX = adxBuffer[p4IDX]; + + // + // ADX +DI ... + double zADXP = adxpBuffer[zIDX]; + double cADXP = adxpBuffer[cIDX]; + double pADXP = adxpBuffer[pIDX]; + double p2ADXP = adxpBuffer[p2IDX]; + double p3ADXP = adxpBuffer[p3IDX]; + double p4ADXP = adxpBuffer[p4IDX]; + + // + // ADX -DI ... + double zADXN = adxnBuffer[zIDX]; + double cADXN = adxnBuffer[cIDX]; + double pADXN = adxnBuffer[pIDX]; + double p2ADXN = adxnBuffer[p2IDX]; + double p3ADXN = adxnBuffer[p3IDX]; + double p4ADXN = adxnBuffer[p4IDX]; + + // + // Create Required Conditions ... + + // + // Grows ... + + // + bool isADXUp = + zADX >= cADX && + (cADX >= pADX || + pADX >= p2ADX); + + // + bool isADXDown = + zADX <= cADX && + (cADX <= pADX || + pADX <= p2ADX); + + // + // Trending ... + + // + bool isZADXBullish = zADX > adxThreshold; + bool isZADXBearish = zADX < adxThreshold; + + // + bool isCADXBullish = cADX > adxThreshold; + bool isCADXBearish = cADX < adxThreshold; + + // + bool isPADXBullish = pADX > adxThreshold; + bool isPADXBearish = pADX < adxThreshold; + + // + bool isP2ADXBullish = p2ADX > adxThreshold; + bool isP2ADXBearish = p2ADX < adxThreshold; + + // + bool isP3ADXBullish = p3ADX > adxThreshold; + bool isP3ADXBearish = p3ADX < adxThreshold; + + // + bool isP4ADXBullish = p4ADX > adxThreshold; + bool isP4ADXBearish = p4ADX < adxThreshold; + + // + bool isCADXSwitchedToBullish = + isZADXBullish && + isCADXBullish && + !isPADXBullish; + + // + bool isCADXSwitchedToBearish = + isZADXBearish && + isCADXBearish && + !isPADXBearish; + + // + bool isPADXSwitchedToBullish = + isZADXBullish && + isCADXBullish && + isPADXBullish && + !isP2ADXBullish; + + // + bool isPADXSwitchedToBearish = + isZADXBearish && + isCADXBearish && + isPADXBearish && + !isP2ADXBearish; + + // + // Powering ... + + // + bool isZADXHasBullishPower = zADXP > zADXN; + bool isZADXHasBearishPower = zADXN > zADXP; + + // + bool isCADXHasBullishPower = cADXP > cADXN; + bool isCADXHasBearishPower = cADXN > cADXP; + + // + bool isPADXHasBullishPower = pADXP > pADXN; + bool isPADXHasBearishPower = pADXN > pADXP; + + // + bool isP2ADXHasBullishPower = p2ADXP > p2ADXN; + bool isP2ADXHasBearishPower = p2ADXN > p2ADXP; + + // + bool isP3ADXHasBullishPower = p3ADXP > p3ADXN; + bool isP3ADXHasBearishPower = p3ADXN > p3ADXP; + + // + bool isP4ADXHasBullishPower = p4ADXP > p4ADXN; + bool isP4ADXHasBearishPower = p4ADXN > p4ADXP; + + // + bool isCADXSwitchedToBullishPower = + isZADXHasBullishPower && + isCADXHasBullishPower && + !isPADXHasBullishPower; + + // + bool isCADXSwitchedToBearishPower = + isZADXHasBearishPower && + isCADXHasBearishPower && + !isPADXHasBearishPower; + + // + bool isPADXSwitchedToBullishPower = + isZADXHasBullishPower && + isCADXHasBullishPower && + isPADXHasBullishPower && + !isP2ADXHasBullishPower; + + // + bool isPADXSwitchedToBearishPower = + isZADXHasBearishPower && + isCADXHasBearishPower && + isPADXHasBearishPower && + !isP2ADXHasBearishPower; + + // + // Summarize Filtering ... + + // + bool isBullishFiltered = + isBullish && + ( + // + // Grows ... + isADXUp + // + || + // + // Trending ... + (isCADXSwitchedToBullish || + isPADXSwitchedToBullish) + // + || + // + // Powering ... + (isCADXSwitchedToBullishPower || + isPADXSwitchedToBullishPower) + // + ); + + // + bool isBearishFiltered = + isBearish && + ( + // + // Grows ... + isADXDown + // + || + // + // Trending ... + (isCADXSwitchedToBearish || + isPADXSwitchedToBearish) + // + || + // + // Powering ... + (isCADXSwitchedToBearishPower || + isPADXSwitchedToBearishPower) + // + ); + + // + has = + isBullishFiltered || + isBearishFiltered; + if (!has) + { + // + zone.Clean(); + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + return; + } + } + + // + // TREND Filter ... + if (filterBasedOnTrend) + { + // + // Reading Conditions Values ... + + // + double zTrend = trendBuffer[zIDX]; + double cTrend = trendBuffer[cIDX]; + double pTrend = trendBuffer[pIDX]; + double p2Trend = trendBuffer[p2IDX]; + double p3Trend = trendBuffer[p3IDX]; + double p4Trend = trendBuffer[p4IDX]; + + // + double trends[] = { + zTrend, + cTrend, + pTrend, + p2Trend, + p3Trend, + p4Trend // + }; + double trendsMin = GetMin(trends); + double trendsMax = GetMax(trends); + double trendsAVG = GetAverage(trends); + + // + double zTrendState = trendStateBuffer[zIDX]; + double cTrendState = trendStateBuffer[cIDX]; + double pTrendState = trendStateBuffer[pIDX]; + double p2TrendState = trendStateBuffer[p2IDX]; + double p3TrendState = trendStateBuffer[p3IDX]; + double p4TrendState = trendStateBuffer[p4IDX]; + + // + // Create Required Conditions ... + + // + // Grows ... + + // + bool isTrendUp = + zTrend >= cTrend && + cTrend >= trendsAVG && + cTrend > trendsMin; + + // + bool isTrendDown = + zTrend <= cTrend && + cTrend <= trendsAVG && + cTrend < trendsMax; + + // + // Stating ... + + // + bool isCTrendBullish = + zTrendState > 0 && + cTrendState > 0; + + // + bool isCTrendBearish = + zTrendState < 0 && + cTrendState < 0; + + // + bool isPTrendBullish = + zTrendState > 0 && + cTrendState > 0 && + pTrendState > 0; + + // + bool isPTrendBearish = + zTrendState < 0 && + cTrendState < 0 && + pTrendState < 0; + + // + bool isP2TrendBullish = + zTrendState > 0 && + cTrendState > 0 && + pTrendState > 0 && + p2TrendState > 0; + + // + bool isP2TrendBearish = + zTrendState < 0 && + cTrendState < 0 && + pTrendState < 0 && + p2TrendState < 0; + + // + bool isCTrendSwitchedToBullish = + isCTrendBullish && + !isPTrendBullish; + + // + bool isCTrendSwitchedToBearish = + isCTrendBearish && + !isPTrendBearish; + + // + bool isPTrendSwitchedToBullish = + isCTrendBullish && + isPTrendBullish && + !isP2TrendBullish; + + // + bool isPTrendSwitchedToBearish = + isCTrendBearish && + isPTrendBearish && + !isP2TrendBearish; + + // + // Summarize Filtering ... + + // + bool isBullishFiltered = + isBullish && + ( + // + // Grows ... + isTrendUp + // + || + // + // Trend Stating ... + (isCTrendBullish && + isPTrendBullish) + // + || + // + // Switching ... + (isCTrendSwitchedToBullish || + isPTrendSwitchedToBullish) + // + ); + + // + bool isBearishFiltered = + isBearish && + ( + // + // Grows ... + isTrendDown + // + || + // + // Trend Stating ... + (isCTrendBearish && + isPTrendBearish) + // + || + // + // Switching ... + (isCTrendSwitchedToBearish || + isPTrendSwitchedToBearish) + // + ); + + // + has = + isBullishFiltered || + isBearishFiltered; + if (!has) + { + // + zone.Clean(); + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + return; + } + } + + // + // SCORE Filter ... + + // + // VOLUME Filter ... + } + + // + // Detect Left Side of Box ... + XOHCL zoneLeftBar; + int idx = fromIDX + 1; + bool isBaseValid = true; + while (isBaseValid) + { + // + // Retrieve iteration Bar ... + has = zoneLeftBar.Init( + _Symbol, + _Period, + idx // + ); + if (!has) + { + // + zoneLeftBar.Clean(); + break; + } + + // + // Check Bar's Validation ... + + // + bool isBullishPassed = + isBullish && + zoneLeftBar.low >= zone.lower; + + // + bool isBearishPassed = + isBearish && + zoneLeftBar.high <= zone.upper; + + // + // Summarize Conditions ... + has = + isBullishPassed || + isBearishPassed; + if (!has) + { + break; + } + + // + idx++; + } + + // + // Ray to Left Side Zone, if Provided ... + if (rayLeft) + { + // + // Update Value ... + fromIDX = zone.FromIndex(); + + // + // Check Last Iteration Bar is Valid Bar ... + // then Update Zone from Time ... + has = zoneLeftBar.IsValid(); + if (has) + { + // + zone.from = zoneLeftBar.time; + fromIDX = zone.FromIndex(); + } + } + + // + // Draw Detected Zone ... + XCBoxObject *iZoneObj; + has = drawer.DrawBox( + zone, + iZoneObj // + ); + if (has) + { + // + ApplyStyle(iZoneObj, zone.dir); + + // + mObjects.Add(iZoneObj); + + // + // TODO: Enable This for Debugging ... + // string message = ToString(zone.dir) + " Zone Detected (" + cBar.time + ") ..."; + // Print(message); + } + ZeroMemory(iZoneObj); + + // + // Cleanup Resources ... + + // + zone.Clean(); + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + zoneLeftBar.Clean(); +} + +// +void ApplyStyle( + XCBoxObject *iObj, + ENUM_X_DIRECTION dir // +) +{ + // + if (!HasDirection(dir) || iObj == NULL) + { + return; + } + + // + int width = boxWidth > 0 + ? boxWidth + : 1; + int clr = IsBullish(dir) + ? bullishColor + : bearishColor; + + // + iObj.BoxColor(clr); + iObj.BoxWidth(width); + iObj.BoxStyle(boxStyle); + + // +} + // \ No newline at end of file diff --git a/XCAEA/Classes/xcaea.x-poi.detector.class.mq5 b/XCAEA/Classes/xcaea.x-poi.detector.class.mq5 index 9ea1cb5f..92118f56 100644 --- a/XCAEA/Classes/xcaea.x-poi.detector.class.mq5 +++ b/XCAEA/Classes/xcaea.x-poi.detector.class.mq5 @@ -32,19 +32,21 @@ // enum ENUM_XCA_PIVOTS { - XCA_NONE, // None - XCA_SWL, // Swing Low - XCA_SWH, // Swing High - XCA_PEAK, // Peak - XCA_VALE, // Vale - XCA_OB_BULL, // OBBull - XCA_OB_BEAR, // OBBear - XCA_FVG_BULL, // FVGBull - XCA_FVG_BEAR, // FVGBear - XCA_RSI_COOS, // RSICOOS - XCA_RSI_CUOB, // RSICUOB - XCA_TREND_BULL, // TrendBull - XCA_TREND_BEAR, // TrendBear + XCA_NONE, // None + XCA_SWL, // Swing Low + XCA_SWH, // Swing High + XCA_PEAK, // Peak + XCA_VALE, // Vale + XCA_OB_BULL, // OBBull + XCA_OB_BEAR, // OBBear + XCA_FVG_BULL, // FVGBull + XCA_FVG_BEAR, // FVGBear + XCA_RSI_COOS, // RSICOOS + XCA_RSI_CUOB, // RSICUOB + XCA_TREND_BULL, // TrendBull + XCA_TREND_BEAR, // TrendBear + XCA_TRIGGER_BULL, // TriggerBull + XCA_TRIGGER_BEAR, // TriggerBear }; // @@ -89,6 +91,7 @@ ENUM_X_DIRECTION GetDirection(ENUM_XCA_PIVOTS value) case XCA_FVG_BULL: case XCA_RSI_COOS: case XCA_TREND_BULL: + case XCA_TRIGGER_BULL: result = X_DIRECTION_BULLISH; break; @@ -99,6 +102,7 @@ ENUM_X_DIRECTION GetDirection(ENUM_XCA_PIVOTS value) case XCA_FVG_BEAR: case XCA_RSI_CUOB: case XCA_TREND_BEAR: + case XCA_TRIGGER_BEAR: result = X_DIRECTION_BEARISH; break; } @@ -141,6 +145,12 @@ string GetBoxType(ENUM_XCA_PIVOTS value) case XCA_TREND_BEAR: result = "XCA_TREND"; break; + + // + case XCA_TRIGGER_BULL: + case XCA_TRIGGER_BEAR: + result = "XCA_TRIGGER"; + break; } // @@ -185,6 +195,10 @@ ENUM_XCA_PIVOTS GetPivotType(XBoxZone &value) value.dir == GetDirection(XCA_TREND_BULL); bool isTrendBearish = value.type == GetBoxType(XCA_TREND_BEAR) && value.dir == GetDirection(XCA_TREND_BEAR); + bool isTriggerBullish = value.type == GetBoxType(XCA_TRIGGER_BULL) && + value.dir == GetDirection(XCA_TRIGGER_BULL); + bool isTriggerBearish = value.type == GetBoxType(XCA_TRIGGER_BEAR) && + value.dir == GetDirection(XCA_TRIGGER_BEAR); // if (isSWL) @@ -235,6 +249,14 @@ ENUM_XCA_PIVOTS GetPivotType(XBoxZone &value) { result = XCA_TREND_BEAR; } + else if (isTriggerBullish) + { + result = XCA_TRIGGER_BULL; + } + else if (isTriggerBearish) + { + result = XCA_TRIGGER_BEAR; + } // return result; @@ -907,6 +929,16 @@ class XCXCAEAPOIDetector : public XCBase detectTrendBullishPivots = false; detectTrendBearishPivots = false; + // + // Trigger Block ... + triggerBlockSwingLength = 7; + triggerBlockMaxAllowedRange = 0; + filterTriggerBlocksBySar = true; + triggerBlockBarHasProperSwing = true; + detectTriggerBlockBullishPivots = false; + detectTriggerBlockBearishPivots = false; + triggerBlockBarPressureValidation = true; + // } @@ -948,6 +980,8 @@ class XCXCAEAPOIDetector : public XCBase newFVGBearishPivotDetected = false; newTrendBullishPivotDetected = false; newTrendBearishPivotDetected = false; + newTriggerBlockBullishPivotDetected = false; + newTriggerBlockBearishPivotDetected = false; // int index = barIndex; @@ -1002,6 +1036,50 @@ class XCXCAEAPOIDetector : public XCBase continue; } + // + // Handle On Time Detection Pivots ... + bool isFirstBar = start == index; + if (isFirstBar) + { + // + // TRIGGER Block ... + // Since Trigger Block Pivots Only Used on Detection Time ... + // we have to Detect only when zBar Index is Zero, means at Last Bar ... + // in this Senario we Have to Ignore LoopBacks ... + + // + // Bullish ... + if (detectTriggerBlockBullishPivots) + { + // + newTriggerBlockBullishPivotDetected = DetectTriggerBlockPivot( + barIndex, + X_DIRECTION_BULLISH, + zBar, + cBar, + pBar, + p2Bar, + conditions // + ); + } + + // + // Bearish ... + if (detectTriggerBlockBearishPivots) + { + // + newTriggerBlockBearishPivotDetected = DetectTriggerBlockPivot( + barIndex, + X_DIRECTION_BEARISH, + zBar, + cBar, + pBar, + p2Bar, + conditions // + ); + } + } + // // Checking Pivots ... @@ -1242,6 +1320,13 @@ class XCXCAEAPOIDetector : public XCBase barIndex // ); + // + // TRIGGER Block ... + ValidateTriggerBlockPivots( + unavailables, + barIndex // + ); + // SortPivots(); } @@ -3856,6 +3941,709 @@ class XCXCAEAPOIDetector : public XCBase return ArraySize(trendBearishPivots); } + // + // TRIGGER Blocks ... + + // + int triggerBlockSwingLength; + int filterTriggerBlocksBySar; + double triggerBlockMaxAllowedRange; + bool triggerBlockBarHasProperSwing; + bool triggerBlockBarPressureValidation; + + // + bool DetectTriggerBlockPivot( + int barIndex, + ENUM_X_DIRECTION forDir, + XOHCL &zBar, + XOHCL &cBar, + XOHCL &pBar, + XOHCL &p2Bar, + XCAEAConditions &conditions // + ) + { + // + bool result = false; + + // + // Checking Direction ... + result = HasDirection(forDir); + if (!result) + { + return result; + } + + // + bool forBullish = IsBullish(forDir); + bool forBearish = IsBearish(forDir); + + // + // Check Allowed ... + result = + forBullish + ? detectTriggerBlockBullishPivots + : detectTriggerBlockBearishPivots; + if (!result) + { + return result; + } + + // + // Validate Args ... + result = + // + barIndex >= 0 && + zBar.IsValid() && + cBar.IsValid() && + pBar.IsValid() && + p2Bar.IsValid() + // + ; + if (!result) + { + return result; + } + + // + // Define Requirements ... + + // + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + int p3IDX = p2IDX + 1; + + // + datetime cTime = zBar.time; + string symbol = zBar.symbol; + ENUM_TIMEFRAMES period = zBar.period; + double points = GetPoints(symbol); + + // + // Reading Conditional Values ... + + // + // Prepare Conditinal Conditions ... + + // + // Checking Base Block Exists ... + XBoxZone iBlock; + result = helper.barAnalyser.IsOB( + cBar, + iBlock, + true, // Force FVG Bar Type ... + true // Force Two Bar ... + ); + if (!result) + { + // + iBlock.Clean(); + + // + return result; + } + + // + // Bullish ... + bool isBullish = + result && + forBullish && + iBlock.IsBullish(); + + // + // Bearish ... + bool isBearish = + result && + forBearish && + iBlock.IsBearish(); + + // + // Summarizing Conditions ... + + // + result = isBullish || + isBearish; + if (!result) + { + // + iBlock.Clean(); + + // + return result; + } + + // + // Adding Pivot to Box Type ... + string iType = isBullish + ? GetBoxType(XCA_TRIGGER_BULL) + : GetBoxType(XCA_TRIGGER_BEAR); + iBlock.type = iType; + + // + // Validate TriggerBlock ... + XOHCL p3Bar; + XOHCL p4Bar; + result = + p2Bar.GetPreviousBar(p3Bar); + result = + result && + p3Bar.GetPreviousBar(p4Bar); + if (!result) + { + // + p3Bar.Clean(); + p4Bar.Clean(); + iBlock.Clean(); + + // + return result; + } + ENUM_X_DIRECTION iDir; + + // + // Validating Range ... + if (triggerBlockMaxAllowedRange > 0) + { + // + double blockRange = iBlock.GetRange(); + result = blockRange <= triggerBlockMaxAllowedRange * points; + if (!result) + { + // + p3Bar.Clean(); + p4Bar.Clean(); + iBlock.Clean(); + + // + return result; + } + } + + // + // Validate Using Swing Bars ... + if (triggerBlockBarHasProperSwing) + { + // + // Check Has Proper Swing ... + + // + // CBar ... + bool isCBarSimpleSwing = + barAnalyser.IsSimpleSwing( + cBar, + iDir // + ); + bool isCBarBullishSimpleSwing = + isCBarSimpleSwing && + IsBullish(iDir); + bool isCBarBearishSimpleSwing = + isCBarSimpleSwing && + IsBearish(iDir); + + // + // PBar ... + bool isPBarSimpleSwing = + barAnalyser.IsSimpleSwing( + pBar, + iDir // + ); + bool isPBarBullishSimpleSwing = + isPBarSimpleSwing && + IsBullish(iDir); + bool isPBarBearishSimpleSwing = + isPBarSimpleSwing && + IsBearish(iDir); + + // + // P2Bar ... + bool isP2BarSimpleSwing = + barAnalyser.IsSimpleSwing( + p2Bar, + iDir // + ); + bool isP2BarBullishSimpleSwing = + isP2BarSimpleSwing && + IsBullish(iDir); + bool isP2BarBearishSimpleSwing = + isP2BarSimpleSwing && + IsBearish(iDir); + + // + // P3Bar ... + bool isP3BarSimpleSwing = + barAnalyser.IsSimpleSwing( + p3Bar, + iDir // + ); + bool isP3BarBullishSimpleSwing = + isP3BarSimpleSwing && + IsBullish(iDir); + bool isP3BarBearishSimpleSwing = + isP3BarSimpleSwing && + IsBearish(iDir); + + // + // P4Bar ... + bool isP4BarSimpleSwing = + barAnalyser.IsSimpleSwing( + p4Bar, + iDir // + ); + bool isP4BarBullishSimpleSwing = + isP4BarSimpleSwing && + IsBullish(iDir); + bool isP4BarBearishSimpleSwing = + isP4BarSimpleSwing && + IsBearish(iDir); + + // + // Summarise Validation ... + + // + bool isBullishSwimpleSwing = + isBullish && + (isCBarBullishSimpleSwing || + isPBarBullishSimpleSwing || + isP2BarBullishSimpleSwing || + isP3BarBullishSimpleSwing || + isP4BarBullishSimpleSwing); + + // + bool isBearishSwimpleSwing = + isBearish && + (isCBarBearishSimpleSwing || + isPBarBearishSimpleSwing || + isP2BarBearishSimpleSwing || + isP3BarBearishSimpleSwing || + isP4BarBearishSimpleSwing); + + // + result = isBullishSwimpleSwing || + isBearishSwimpleSwing; + if (!result) + { + // + p3Bar.Clean(); + p4Bar.Clean(); + iBlock.Clean(); + + // + return result; + } + } + + // + // Validating Using Bar Pressure ... + if (triggerBlockBarPressureValidation) + { + // + // Check pBar is Momentum Bar ... + // and Breakd Block Side ... + + // + bool isCBarMomentum = barAnalyser.IsMomentum( + pBar, + iDir // + ); + bool isCBarBullishMomentum = + isCBarMomentum && + IsBullish(iDir); + bool isCBarBearishMomentum = + isCBarMomentum && + IsBearish(iDir); + + // + bool isPBarMomentum = barAnalyser.IsMomentum( + pBar, + iDir // + ); + bool isPBarBullishMomentum = + isPBarMomentum && + IsBullish(iDir); + bool isPBarBearishMomentum = + isPBarMomentum && + IsBearish(iDir); + + // + bool isBullishBreakedOut = + isBullish && + forBullish && + pBar.IsBullish() && + (isCBarBullishMomentum || + isPBarBullishMomentum) && + pBar.GetUp() > iBlock.upper && + pBar.GetDown() < iBlock.upper; + + // + bool isBearishBreakedOut = + isBearish && + forBearish && + pBar.IsBearish() && + (isCBarBearishMomentum || + isPBarBearishMomentum) && + pBar.GetUp() > iBlock.lower && + pBar.GetDown() < iBlock.lower; + + // + result = + isBullishBreakedOut || + isBearishBreakedOut; + if (!result) + { + // + p3Bar.Clean(); + p4Bar.Clean(); + iBlock.Clean(); + + // + return result; + } + } + + // + // Extract to and from Info ... + + // + int toIDX = iBlock.ToIndex(); + int fromIDX = iBlock.FromIndex(); + + // + XOHCL toBar; + XOHCL fromBar; + + // + result = iBlock.ToBar(toBar); + result = result && + iBlock.FromBar(fromBar); + if (!result) + { + // + toBar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + iBlock.Clean(); + fromBar.Clean(); + + // + return result; + } + + // + // Validating Using HH and LL ... + if (triggerBlockSwingLength > 0) + { + // + double toLL = toBar.FindLowest(triggerBlockSwingLength, MODE_LOW); + double toHH = toBar.FindHighest(triggerBlockSwingLength, MODE_HIGH); + + // + double fromLL = fromBar.FindLowest(triggerBlockSwingLength, MODE_LOW); + double fromHH = fromBar.FindHighest(triggerBlockSwingLength, MODE_HIGH); + + // + double selectedLL = fromLL; // MathMin(toLL, fromLL); + double selectedHH = fromHH; // MathMax(toHH, fromHH); + + // + bool isBullishSwingPassed = + isBullish && + forBullish && + selectedLL >= iBlock.lower; + + // + bool isBearishSwingPassed = + isBearish && + forBearish && + selectedHH <= iBlock.upper; + + // + result = isBullishSwingPassed || + isBearishSwingPassed; + if (!result) + { + // + toBar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + iBlock.Clean(); + fromBar.Clean(); + + // + return result; + } + } + + // + // Apply Filters ... + bool hasFilter = + filterTriggerBlocksBySar; + if (hasFilter) + { + // + // Sar Filtering ... + if (filterTriggerBlocksBySar) + { + // + // Reading Conditions ... + + // + double zSar = conditions.sarBuffer[zIDX]; + double cSar = conditions.sarBuffer[cIDX]; + double pSar = conditions.sarBuffer[pIDX]; + double p2Sar = conditions.sarBuffer[p2IDX]; + double p3Sar = conditions.sarBuffer[p3IDX]; + + // + // Preparing Constom Conditions ... + + // + bool isZSarBullish = zSar < zBar.low; + bool isCSarBullish = cSar < cBar.low; + bool isPSarBullish = pSar < pBar.low; + bool isP2SarBullish = p2Sar < p2Bar.low; + bool isP3SarBullish = p3Sar < p3Bar.low; + + // + bool isZSarBearish = zSar > zBar.high; + bool isCSarBearish = cSar > cBar.high; + bool isPSarBearish = pSar > pBar.high; + bool isP2SarBearish = p2Sar > p2Bar.high; + bool isP3SarBearish = p3Sar > p3Bar.high; + + // + bool isCSarSwitchedToBullish = + isCSarBullish && + !isPSarBullish; + bool isPSarSwitchedToBullish = + isPSarBullish && + !isP2SarBullish; + bool isP2SarSwitchedToBullish = + isP2SarBullish && + !isP3SarBullish; + + // + bool isCSarSwitchedToBearish = + isCSarBearish && + !isPSarBearish; + bool isPSarSwitchedToBearish = + isPSarBearish && + !isP2SarBearish; + bool isP2SarSwitchedToBearish = + isP2SarBearish && + !isP3SarBearish; + + // + // Summarize Custom Conditions ... + + // + // Bullish ... + + // + bool isCSarBullishPassed = + isZSarBullish && + isCSarSwitchedToBullish; + + // + bool isPSarBullishPassed = + isZSarBullish && + isCSarBullish && + isPSarSwitchedToBullish; + + // + bool isP2SarBullishPassed = + isZSarBullish && + isCSarBullish && + isPSarBullish && + isP2SarSwitchedToBullish; + + // + // Bearish ... + + // + bool isCSarBearishPassed = + isZSarBearish && + isCSarSwitchedToBearish; + + // + bool isPSarBearishPassed = + isZSarBearish && + isCSarBearish && + isPSarSwitchedToBearish; + + // + bool isP2SarBearishPassed = + isZSarBearish && + isCSarBearish && + isPSarBearish && + isP2SarSwitchedToBearish; + + // + // Summarize Conditions ... + + // + bool isBullishFiltered = + isBullish && + forBullish && + (isCSarBullishPassed || + isPSarBullishPassed || + isP2SarBullishPassed); + + // + bool isBearishFiltered = + isBearish && + forBearish && + (isCSarBearishPassed || + isPSarBearishPassed || + isP2SarBearishPassed); + + // + result = isBullishFiltered || + isBearishFiltered; + if (!result) + { + // + toBar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + iBlock.Clean(); + fromBar.Clean(); + + // + return result; + } + } + } + + // + // Summarize ... + + // + isBullish = + isBullish && + forBullish && + iBlock.IsValid(); + + // + isBearish = + isBearish && + forBearish && + iBlock.IsValid(); + + // + result = isBullish || + isBearish; + if (!result) + { + iBlock.Clean(); + } + + // + // Storing Pivot ... + + // + if (isBullish) + { + // + result = AddBox( + iBlock, + triggerBlockBullishPivots // + ); + } + + // + if (isBearish) + { + // + result = AddBox( + iBlock, + triggerBlockBearishPivots // + ); + } + + // + // Cleanup Resource ... + + // + toBar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + iBlock.Clean(); + fromBar.Clean(); + + // + return result; + } + + // + void ValidateTriggerBlockPivots( + XBoxZone &unavailables[], + int barIndex = 0 // + ) + { + // + // Since Trigger Blocks Doesnt Use Multiple Times, + // there is not any Validation Required for them ... + bool has = false; + + // + // bool applyLifetimeValidating = maxAllowedTriggerBlockLifetime > 0; + + // + // Bullish ... + has = HasTriggerBlockBullishPivots(); + if (has) + { + } + + // + // Bearish ... + has = HasTriggerBlockBearishPivots(); + if (has) + { + } + } + + // + // Bullish ... + + // + XBoxZone triggerBlockBullishPivots[]; + bool detectTriggerBlockBullishPivots; + bool newTriggerBlockBullishPivotDetected; + + // + bool HasTriggerBlockBullishPivots() + { + return HasChild(triggerBlockBullishPivots); + } + + // + int CountTriggerBlockBullishPivots() + { + return ArraySize(triggerBlockBullishPivots); + } + + // + // Bearish ... + + // + bool detectTriggerBlockBearishPivots; + XBoxZone triggerBlockBearishPivots[]; + bool newTriggerBlockBearishPivotDetected; + + // + bool HasTriggerBlockBearishPivots() + { + return HasChild(triggerBlockBearishPivots); + } + + // + int CountTriggerBlockBearishPivots() + { + return ArraySize(triggerBlockBearishPivots); + } + // // Protected ... protected: @@ -4149,6 +4937,10 @@ class XCXCAEAPOIDetector : public XCBase // Clean(trendBullishPivots); Clean(trendBearishPivots); + + // + Clean(triggerBlockBullishPivots); + Clean(triggerBlockBearishPivots); } // @@ -4259,6 +5051,25 @@ class XCXCAEAPOIDetector : public XCBase { ApplySortOnBoxes(trendBearishPivots); } + + // + // TRIGGER Block ... + + // + // Bullish ... + has = HasTriggerBlockBullishPivots(); + if (has) + { + ApplySortOnBoxes(triggerBlockBullishPivots); + } + + // + // Bearish ... + has = HasTriggerBlockBearishPivots(); + if (has) + { + ApplySortOnBoxes(triggerBlockBearishPivots); + } } // diff --git a/XCAEA/Classes/xcaea.x-poi.drawer.class.mq5 b/XCAEA/Classes/xcaea.x-poi.drawer.class.mq5 index 6058e36d..aadcb344 100644 --- a/XCAEA/Classes/xcaea.x-poi.drawer.class.mq5 +++ b/XCAEA/Classes/xcaea.x-poi.drawer.class.mq5 @@ -94,6 +94,8 @@ class XCXCAEAPOIDrawer : public XCBase bool drawFVGBearishPivots; bool drawTrendBullishPivots; bool drawTrendBearishPivots; + bool drawTriggerBlockBullishPivots; + bool drawTriggerBlockBearishPivots; // // Styling ... @@ -122,6 +124,10 @@ class XCXCAEAPOIDrawer : public XCBase XCAPivotStyle trendBullishPivotStyle; XCAPivotStyle trendBearishPivotStyle; + // + XCAPivotStyle triggerBlockBullishPivotStyle; + XCAPivotStyle triggerBlockBearishPivotStyle; + // // Constructors ... XCXCAEAPOIDrawer( @@ -169,6 +175,8 @@ class XCXCAEAPOIDrawer : public XCBase drawFVGBearishPivots = false; drawTrendBullishPivots = false; drawTrendBearishPivots = false; + drawTriggerBlockBullishPivots = false; + drawTriggerBlockBearishPivots = false; // // Styling ... @@ -212,6 +220,11 @@ class XCXCAEAPOIDrawer : public XCBase // TREND ... trendBullishPivotStyle = defaultBullishStyle; trendBearishPivotStyle = defaultBearishStyle; + + // + // TRIGGER ... + triggerBlockBullishPivotStyle = defaultBullishStyle; + triggerBlockBearishPivotStyle = defaultBearishStyle; } // @@ -241,13 +254,19 @@ class XCXCAEAPOIDrawer : public XCBase // TREND ... DrawTrendBullishPivots(to); DrawTrendBearishPivots(to); + + // + // TRIGGER ... + DrawTriggerBullishPivots(to); + DrawTriggerBearishPivots(to); } // void DrawPivot( XBoxZone &pivot, datetime to = NULL // - ) { + ) + { // DrawBox( pivot, @@ -384,6 +403,24 @@ class XCXCAEAPOIDrawer : public XCBase to // ); break; + + // + case XCA_TRIGGER_BULL: + // + DrawTriggerBlockBullishPivot( + box, + to // + ); + break; + + // + case XCA_TRIGGER_BEAR: + // + DrawTriggerBlockBearishPivot( + box, + to // + ); + break; } } // @@ -889,6 +926,76 @@ class XCXCAEAPOIDrawer : public XCBase } } + // + void DrawTriggerBullishPivots(datetime to = NULL) + { + // + bool has = drawTriggerBlockBullishPivots; + if (!has) + { + return; + } + + // + has = detector.HasTriggerBlockBullishPivots(); + if (!has) + { + return; + } + + // + int count = detector.CountTriggerBlockBullishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = detector.triggerBlockBullishPivots[i]; + + // + DrawTriggerBlockBullishPivot( + iBox, + to // + ); + + // + iBox.Clean(); + } + } + + // + void DrawTriggerBearishPivots(datetime to = NULL) + { + // + bool has = drawTriggerBlockBearishPivots; + if (!has) + { + return; + } + + // + has = detector.HasTriggerBlockBearishPivots(); + if (!has) + { + return; + } + + // + int count = detector.CountTriggerBlockBearishPivots(); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = detector.triggerBlockBearishPivots[i]; + + // + DrawTriggerBlockBearishPivot( + iBox, + to // + ); + + // + iBox.Clean(); + } + } + // // One Item Drawers ... @@ -1422,6 +1529,116 @@ class XCXCAEAPOIDrawer : public XCBase ZeroMemory(iObj); } + // + void DrawTriggerBlockBullishPivot( + XBoxZone &item, + datetime to = NULL // + ) + { + // + bool has = drawTriggerBlockBullishPivots; + if (!has) + { + return; + } + + // + has = item.IsValid() && + item.type == GetBoxType(XCA_TRIGGER_BULL) && + item.dir == GetDirection(XCA_TRIGGER_BULL); + if (!has) + { + return; + } + + // + // Since Trigger Blocks only Used Once ... + to = NULL; + bool canUpdateTo = IsValid(to); + if (canUpdateTo) + { + item.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + item, + iObj // + ); + if (has) + { + // + // Style Object ... + ApplyPivotStyle( + iObj, + triggerBlockBullishPivotStyle // + ); + + // + // Store Object ... + mTriggerBlockBullishPivotObjects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + + // + void DrawTriggerBlockBearishPivot( + XBoxZone &item, + datetime to = NULL // + ) + { + // + bool has = drawTriggerBlockBearishPivots; + if (!has) + { + return; + } + + // + has = item.IsValid() && + item.type == GetBoxType(XCA_TRIGGER_BEAR) && + item.dir == GetDirection(XCA_TRIGGER_BEAR); + if (!has) + { + return; + } + + // + // Since Trigger Blocks only Used Once ... + to = NULL; + bool canUpdateTo = IsValid(to); + if (canUpdateTo) + { + item.to = to; + } + + // + XCBoxObject *iObj; + has = drawer.DrawBox( + item, + iObj // + ); + if (has) + { + // + // Style Object ... + ApplyPivotStyle( + iObj, + triggerBlockBearishPivotStyle // + ); + + // + // Store Object ... + mTriggerBlockBearishPivotObjects.Add(iObj); + } + + // + ZeroMemory(iObj); + } + // // Protected ... protected: @@ -1479,6 +1696,10 @@ class XCXCAEAPOIDrawer : public XCBase CArrayObj mTrendBullishPivotObjects; CArrayObj mTrendBearishPivotObjects; + // + CArrayObj mTriggerBlockBullishPivotObjects; + CArrayObj mTriggerBlockBearishPivotObjects; + // }; diff --git a/XCAEA/Libraries/xcaea.signaller.lib.mq5 b/XCAEA/Libraries/xcaea.signaller.lib.mq5 index 58480f6b..ce57c5de 100644 --- a/XCAEA/Libraries/xcaea.signaller.lib.mq5 +++ b/XCAEA/Libraries/xcaea.signaller.lib.mq5 @@ -1055,7 +1055,7 @@ bool DetectDecisionZone( // // Custom Senarios ... - +, // bool isCond1Bullish = // diff --git a/XCAEA/Signals/xcaea.signaller.class.mq5 b/XCAEA/Signals/xcaea.signaller.class.mq5 index 58db14ec..040de941 100644 --- a/XCAEA/Signals/xcaea.signaller.class.mq5 +++ b/XCAEA/Signals/xcaea.signaller.class.mq5 @@ -1030,6 +1030,20 @@ class XCXCAEASignaller : XCBase detector.detectTrendBullishPivots = false; detector.detectTrendBearishPivots = false; + // + // TRIGGER Blocks ... + + // + detector.triggerBlockSwingLength = 7; + detector.triggerBlockMaxAllowedRange = 0; + detector.filterTriggerBlocksBySar = true; + detector.triggerBlockBarHasProperSwing = true; + detector.triggerBlockBarPressureValidation = true; + + // + detector.detectTriggerBlockBullishPivots = true; + detector.detectTriggerBlockBearishPivots = true; + // // DRAWER ... @@ -1052,6 +1066,8 @@ class XCXCAEASignaller : XCBase drawer.drawFVGBearishPivots = false; drawer.drawTrendBullishPivots = false; drawer.drawTrendBearishPivots = false; + drawer.drawTriggerBlockBullishPivots = false; + drawer.drawTriggerBlockBearishPivots = false; // // Configure Styles ... @@ -1160,6 +1176,27 @@ class XCXCAEASignaller : XCBase trendBearishStyle.style = STYLE_DOT; drawer.trendBearishPivotStyle = trendBearishStyle; trendBearishStyle.Clean(); + + // + // TRIGGER ... + + // + // Bullish ... + XCAPivotStyle triggerBlockBullishStyle; + triggerBlockBullishStyle.width = 2; + triggerBlockBullishStyle.clr = clrLime; + triggerBlockBullishStyle.style = STYLE_DOT; + drawer.triggerBlockBullishPivotStyle = triggerBlockBullishStyle; + triggerBlockBullishStyle.Clean(); + + // + // Bearish ... + XCAPivotStyle triggerBlockBearishStyle; + triggerBlockBearishStyle.width = 2; + triggerBlockBearishStyle.clr = clrRed; + triggerBlockBearishStyle.style = STYLE_DOT; + drawer.triggerBlockBearishPivotStyle = triggerBlockBearishStyle; + triggerBlockBearishStyle.Clean(); } //