/////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 Indicator // ------------------------------------------------- // Name: X121 X3MA // Description: X3MA ... // // // Maintainer: // ------------ // Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) // ////////////////////////////////////////////////////// // // Global Properties ... #property copyright "Copyright 2023, SaherElm IT Center" #property link "https://saherelm.ir" #property version "1.00" #property description "SaherElm X121 X3MA Indicator" #property strict // // Definitions ... // #define ShortName "X121 XCZone" // // Includes Common Library ... #include "../Classes/x-saherelm.x-bar.analyser.class.mq5" #include "../Classes/x-saherelm.x-poi.drawer.class.mq5" #include "../Libraries/x-saherelm.common.lib.mq5" #include "../Libraries/x-saherelm.x-poi.lib.mq5" // // Inputs ... input group "Market"; 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 = 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 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 = 5000; // Calculate Last n Bars int sarArrowCode = 159; // Sar Arrow Code // // Buffers ... // #define hideColorIDX 0 #define bullishColorIDX 1 #define bearishColorIDX 2 #define neuturalColorIDX 3 // #define bullishState 1 #define neuturalState 0 #define bearishState -1 // #define emptyValue 0.0 // #property indicator_chart_window // #property indicator_buffers 10 #property indicator_plots 2 // // Plot Buffers ... // // TREND ... // #define trendBufferIndex 0 #define trendBufferPlotIndex 0 double trendBuffer[]; // #define trendColorBufferIndex 1 double trendColorBuffer[]; // #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 2 #define sarBufferPlotIndex 2 double sarBuffer[]; // #define sarColorBufferIndex 3 double sarColorBuffer[]; // #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 3 // #define trendStateBufferIndex mLastBufferIndex + 1 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 ... // int limit; // int maxLength; // 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; // // Event Handlers ... /** * Initialize Indicator ... * * @return ( int ) */ int OnInit() { // // Validate Inputs ... if (!ValidateInputs()) { return INIT_PARAMETERS_INCORRECT; } // // Initialize Indicator Handlers ... // drawer = new XCPOIDrawer(); barAnalyser = new XCBarAnalyser(); // // Initializing TrendPeriod ... int cPeriodSeconds = PeriodSeconds(_Period); if (trendPeriodMethod == X_PERIOD_AUTO) { // // Select Period ... mTrendPeriod = GetCyclePeriod( X_MARKET_CYCLE_HIND, _Period // ); } else { mTrendPeriod = trendPeriod; } if (IsValid(mTrendPeriod)) { mTrendPeriodLength = PeriodSeconds(mTrendPeriod) / cPeriodSeconds; } // // SAR ... sarHandler = iSAR( _Symbol, _Period, sarStep, sarMax // ); bool isInited = sarHandler != INVALID_HANDLE; if (!isInited) { 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( _Symbol, _Period, mTrendPeriodLength, 0, trendMode, trendAppliedTo // ); isInited = trendHandler != INVALID_HANDLE; if (!isInited) { 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 // untill we pass the biggest input length, here we get max Input length // and then wait until pass it ... maxLength = ExtractMaxLengthOfInputs(); // // Define Index Buffers ... DefineBuffers(); // // Set Indicator ShortName ... SetIndicatorName(); // // Init Succeed ... return INIT_SUCCEEDED; } /** * De Initialize Indicator ... * * @param reason: Integer, De Initialization Reason ... */ void OnDeinit(const int reason) { // // REASON_PROGRAM 0 The EA has stopped working calling the ExpertRemove() function // REASON_REMOVE 1 Program removed from a chart // REASON_RECOMPILE 2 Program recompiled // REASON_CHARTCHANGE 3 A symbol or a chart period is changed // REASON_CHARTCLOSE 4 Chart closed // REASON_PARAMETERS 5 Inputs changed by a user // REASON_ACCOUNT 6 Another account has been activated or reconnection to the trade server has occurred due to changes in the account settings // REASON_TEMPLATE 7 Another chart template applied // REASON_INITFAILED 8 The OnInit() handler returned a non-zero value // REASON_CLOSE 9 Terminal closed // Clean(analyseOBs); analysePivot.Clean(); // mObjects.Clear(); ZeroMemory(drawer); ZeroMemory(barAnalyser); // IndicatorRelease(sarHandler); IndicatorRelease(rsiHandler); IndicatorRelease(adxHandler); IndicatorRelease(trendHandler); } /** * Calculate Bars ... * * @param rates_total: Integer, Total Bars on Chart ... * @param prev_calculated: Integer, Total Calculated Bars on Charts ... * @param time: DateTime Array, History of Open Time ... * @param open: Double Array, History of Open Prices ... * @param high: Double Array, History of High Prices ... * @param low: Double Array, History of Low Prices ... * @param close: Double Array, History of Close Prices ... * @param tick_volume: Long, History of Tick Volumes on Bar ... * @param volume: Long, History of Trade Volumes ... * @param spread: Double, History of Spread Price ... * * @return ( int ) */ int OnCalculate( const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[] // ) { // // Prepare Buffers ... ArraySetAsSeries(time, true); ArraySetAsSeries(open, true); ArraySetAsSeries(high, true); ArraySetAsSeries(low, true); ArraySetAsSeries(close, true); ArraySetAsSeries(tick_volume, true); ArraySetAsSeries(volume, true); ArraySetAsSeries(spread, true); // // Validate Calculated Bars ... // // SAR ... int sarCalculatedBars = BarsCalculated(sarHandler); // // RSI ... int rsiCalculatedBars = BarsCalculated(rsiHandler); // // ADX ... int adxCalculatedBars = BarsCalculated(adxHandler); // // TREND ... int trendCalculatedBars = BarsCalculated(trendHandler); // bool isPassedRequiredCalculatedBars = // // SAR ... sarCalculatedBars >= maxLength && // // RSI ... rsiCalculatedBars >= maxLength && // // ADX ... adxCalculatedBars >= maxLength && // // TREND ... trendCalculatedBars >= maxLength // ; if (!isPassedRequiredCalculatedBars) { return prev_calculated; } // limit = (prev_calculated > rates_total || prev_calculated <= 0) ? rates_total : (rates_total - prev_calculated) + 1; // // Buffers Copy ... // // SAR ... 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 ... int copiedTrends = CopyBuffer(trendHandler, MAIN_LINE, 0, limit + 1, trendBuffer); // // Validate Copied Items ... bool isPassedRequiredCopiedItems = // // SAR ... copiedSars >= limit && // // RSI ... copiedRSIs >= limit && // // TREND ... copiedTrends >= limit // ; if (!isPassedRequiredCopiedItems) { return prev_calculated; } // // Main Loop ... for (int i = limit - 1; i >= 0 && !IsStopped(); i--) { // CalculateBuffers( i, prev_calculated, rates_total, // open, high, close, low, tick_volume // ); } // return rates_total; } // // Functions ... /** * Validate Input Args for Initialization ... * * @return ( bool ) */ bool ValidateInputs() { // bool result = false; // result = // sarMax > 0 && sarStep > 0 && adxLength > 0 && rsiLength > 0 && rsiOBLevel > 0 && rsiOSLevel > 0 && sarMax > sarStep && minZoneLength > 2 && IsValid(trendPeriodMethod, trendPeriod) // ; // return result; } /** * Extract Max Length of Inputs ... * * @return ( int ) */ int ExtractMaxLengthOfInputs() { // int result = 0; // result = MathMax(minZoneLength, rsiLength); result = MathMax(result, adxLength); // return result; } /** * Define Required Buffers ... */ void DefineBuffers() { // // Plot Buffers ... // // TREND ... // ArraySetAsSeries(trendBuffer, true); SetIndexBuffer(trendBufferIndex, trendBuffer, INDICATOR_DATA); // PlotIndexSetInteger(trendBufferPlotIndex, PLOT_SHOW_DATA, showTrend); // PlotIndexSetDouble(trendBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); // ArraySetAsSeries(trendColorBuffer, true); SetIndexBuffer(trendColorBufferIndex, trendColorBuffer, INDICATOR_COLOR_INDEX); // // SAR ... // ArraySetAsSeries(sarBuffer, true); SetIndexBuffer(sarBufferIndex, sarBuffer, INDICATOR_DATA); // PlotIndexSetInteger(sarBufferPlotIndex, PLOT_SHOW_DATA, showSar); // PlotIndexSetDouble(sarBufferPlotIndex, PLOT_EMPTY_VALUE, emptyValue); PlotIndexSetInteger(sarBufferPlotIndex, PLOT_ARROW, sarArrowCode); // ArraySetAsSeries(sarColorBuffer, true); SetIndexBuffer(sarColorBufferIndex, sarColorBuffer, INDICATOR_COLOR_INDEX); // // Data Buffers ... // ArraySetAsSeries(trendStateBuffer, true); SetIndexBuffer(trendStateBufferIndex, trendStateBuffer, INDICATOR_CALCULATIONS); // 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); } /** * Set Indicator Short Name and also we can define Buffers Labels ... */ void SetIndicatorName() { // IndicatorSetInteger(INDICATOR_DIGITS, _Digits); IndicatorSetString(INDICATOR_SHORTNAME, ShortName); } /** * Calculate Custom Buffers ... * * @param bar_index: Integer, Represent Current Bar ... * @param prevCalculated: Integer, Represent Previous Calculated Bars ... * @param ratesTotal: Integer, Represents All Available Bars ... * @param open: Double Array, History of Open Prices ... * @param high: Double Array, History of High Prices ... * @param close: Double Array, History of Close Prices ... * @param low: Double Array, History of Low Prices ... * @param tickVolume: Long, History of Tick Volumes on Bar ... */ void CalculateBuffers( 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[] // ) { // int barsLimit = startCalculationForLastBars > 0 ? startCalculationForLastBars : 0; // // bool canCalculate = true; bool canCalculate = barsLimit == 0 || bar_index <= barsLimit; if (canCalculate) { // // Calculate Values ... CalculateValues( bar_index, prevCalculated, ratesTotal, open, high, close, low, tickVolume // ); } else { FillBuffersZero(bar_index); } } /** * Fill All Bufers to Zero Vlue for Specified Bar Index ... * * @param barIndex: Integer ... */ void FillBuffersZero(int barIndex) { // // SAR ... sarBuffer[barIndex] = emptyValue; sarColorBuffer[barIndex] = hideColorIDX; sarStateBuffer[barIndex] = neuturalState; // // TREND ... trendBuffer[barIndex] = emptyValue; trendColorBuffer[barIndex] = hideColorIDX; trendStateBuffer[barIndex] = neuturalState; } /** * Calculate Values ... * * @param bar_index: int, Specified Bar Index ... * @param prevCalculated: int, Provides Previous Calculated Bars ... * @param ratesTotal: int, Provides All Availabled Bars ... * @param open: double Collection, Provides Open Prices Time Series ... * @param high: double Collection, Provides High Prices Time Series ... * @param close: double Collection, Provides Close Prices Time Series ... * @param low: double Collection, Provides Low Prices Time Series ... * @param tickVolume: long Collection, Provides Ticks Volume Prices Time Series ... */ void CalculateValues( 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; // double iLow = high[bar_index]; double iHigh = high[bar_index]; double iClose = close[bar_index]; // double points = GetPoints(_Symbol); // // Calculate Sar Color Buffer ... double iSar = sarBuffer[bar_index]; // double iSarState = neuturalState; double iSarColor = neuturalColorIDX; if (iLow > iSar) { // iSarState = bullishState; iSarColor = !showSar ? hideColorIDX : bullishColorIDX; } else if (iHigh < iSar) { // iSarState = bearishState; iSarColor = !showSar ? hideColorIDX : bearishColorIDX; } sarStateBuffer[bar_index] = iSarState; sarColorBuffer[bar_index] = iSarColor; // // Calculate Trend Color Buffer ... double iTrend = trendBuffer[bar_index]; // double iTrendState = neuturalState; double iTrendColor = neuturalColorIDX; if (iClose > iTrend) { // iTrendState = bullishState; iTrendColor = !showTrend ? hideColorIDX : bullishColorIDX; } else if (iClose < iTrend) { // iTrendState = bearishState; iTrendColor = !showTrend ? hideColorIDX : bearishColorIDX; } 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) { return; } // // Detect Consolidation Zone ... XOHCL iBar; bool has = iBar.Init( _Symbol, _Period, bar_index // ); if (!has) { return; } // // Checking Base Zone Exists ... XBoxZone iZone; has = barAnalyser.IsOB( iBar, iZone, true, // Force FVG Bar Type ... true // Force Two Bar ... ); if (!has) { // iBar.Clean(); iZone.Clean(); } bool isBullish = has && iZone.IsBullish(); bool isBearish = has && iZone.IsBearish(); // // Apply Max Range ... has = maxZoneRangeInPoints > 0; if (has) { // double range = iZone.GetRange(); has = range <= maxZoneRangeInPoints * points; if (!has) { // iBar.Clean(); iZone.Clean(); } } // XOHCL iPBar; has = iBar.GetPreviousBar(iPBar); if (!has) { // iBar.Clean(); iPBar.Clean(); iZone.Clean(); // return; } // // Ensure we Have Order Block ... ENUM_X_DIRECTION iDir; // // Validate FVG Gap Candle Breakeout by Body ... // // Check iPBar is Momentum Bar ... has = barAnalyser.IsMomentum( iPBar, iDir // ); bool isBullishMomentum = has && IsBullish(iDir); bool isBearishMomentum = has && IsBearish(iDir); // bool isBullishBreakedOut = isBullish && iPBar.IsBullish() && isBullishMomentum && iPBar.GetUp() > iZone.upper && iPBar.GetDown() < iZone.upper; // bool isBearishBreakedOut = isBearish && iPBar.IsBearish() && isBearishMomentum && iPBar.GetUp() > iZone.lower && iPBar.GetDown() < iZone.lower; // has = isBullishBreakedOut || isBearishBreakedOut; if (!has) { // iBar.Clean(); iPBar.Clean(); iZone.Clean(); // return; } // // Check Has Proper Swing ... // bool isIBarSimpleSwing = barAnalyser.IsSimpleSwing( iBar, iDir // ); bool isIBarBullishSimpleSwing = isIBarSimpleSwing && IsBullish(iDir); bool isIBarBearishSimpleSwing = isIBarSimpleSwing && IsBearish(iDir); // bool isIPBarSimpleSwing = barAnalyser.IsSimpleSwing( iPBar, iDir // ); bool isIPBarBullishSimpleSwing = isIPBarSimpleSwing && IsBullish(iDir); bool isIPBarBearishSimpleSwing = isIPBarSimpleSwing && IsBearish(iDir); // bool isBullishSwimpleSwing = isBullish && (isIBarBullishSimpleSwing || isIPBarBullishSimpleSwing); // bool isBearishSwimpleSwing = isBearish && (isIBarBearishSimpleSwing || isIPBarBearishSimpleSwing); // has = isBullishSwimpleSwing || isBearishSwimpleSwing; if (!has) { // iBar.Clean(); iPBar.Clean(); iZone.Clean(); // return; } // int toIDX = iZone.ToIndex(); int fromIDX = iZone.FromIndex(); // // Retrieve Box From Bar ... XOHCL fromBar; has = iZone.FromBar(fromBar); if (!has) { // iBar.Clean(); iPBar.Clean(); iZone.Clean(); fromBar.Clean(); // return; } // // Retrieve Highest High and Lowest Low ... double ll = fromBar.FindLowest(minZoneLength, MODE_LOW); double hh = fromBar.FindHighest(minZoneLength, MODE_HIGH); // // Validate Directional Based HH/LL Passed ... // bool isBullishLLPassed = isBullish && ll >= iZone.lower; // bool isBearishHHPassed = isBearish && hh <= iZone.upper; // has = isBullishLLPassed || isBearishHHPassed; if (!has) { // iBar.Clean(); iPBar.Clean(); iZone.Clean(); fromBar.Clean(); // return; } // // Update Zone From ... datetime iFrom = GetBarTime( _Symbol, _Period, fromBar.Index() + minZoneLength // ); iZone.from = iFrom; // toIDX = iZone.ToIndex(); fromIDX = iZone.FromIndex(); // // Apply Filters ... has = filterBasedOnSar || filterBasedOnRSI || filterBasedOnADX || filterBasedOnTrend || filterBasedOnAnalysePivots; if (has) { // // Retrieve Indexes ... int iBarIndex = iBar.Index(); int ipBarIndex = iPBar.Index(); int iBarPrevIndex = iBarIndex + 1; int ipBarPrevIndex = ipBarIndex + 1; // // Apply Using Sar ... if (filterBasedOnSar) { // double iSarState = sarStateBuffer[iBarIndex]; double iPSarState = sarStateBuffer[ipBarIndex]; double iSarPrevState = sarStateBuffer[iBarPrevIndex]; double iPSarPrevState = sarStateBuffer[ipBarPrevIndex]; // bool isISarBullish = iSarState > 0; bool isIPSarBullish = iPSarState > 0; bool isISarPrevBullish = iSarPrevState > 0; bool isIPSarPrevBullish = iPSarPrevState > 0; // bool isISarBearish = iSarState < 0; bool isIPSarBearish = iPSarState < 0; bool isISarPrevBearish = iSarPrevState < 0; bool isIPSarPrevBearish = iPSarPrevState < 0; // bool isISarSwitchedToBullish = isISarBullish && !isISarPrevBullish; bool isISarSwitchedToBearish = isISarBearish && !isISarPrevBearish; // bool isIPSarSwitchedToBullish = isIPSarBullish && !isIPSarPrevBullish; bool isIPSarSwitchedToBearish = isIPSarBearish && !isIPSarPrevBearish; // // Check iPBar (Gap Bar which Breaks Edge and is a Momentum Bar) is Sar Change Bar ... // bool isBullishSarFiltered = isBullish && (isISarSwitchedToBullish || isIPSarSwitchedToBullish); // bool isBearishSarFiltered = isBearish && (isISarSwitchedToBearish || isIPSarSwitchedToBearish); // has = isBullishSarFiltered || isBearishSarFiltered; if (!has) { // iBar.Clean(); iPBar.Clean(); iZone.Clean(); fromBar.Clean(); // return; } } // // 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) { // // Check and Validate Box using Trend ... // bearish boxs high must above trend // bullish box low must below trend // double iTrend = 0; bool isBullishTrendPassed = true; bool isBearishTrendPassed = true; for (int i = fromIDX; i >= toIDX; i--) { // iTrend = trendBuffer[i]; // if (isBullishTrendPassed) { // isBullishTrendPassed = isBullishTrendPassed && iZone.lower < iTrend; } // if (isBearishTrendPassed) { // isBearishTrendPassed = isBearishTrendPassed && iZone.upper > iTrend; } // if (!isBullishTrendPassed && !isBearishTrendPassed) { break; } } // bool isBullishTrendFiltered = isBullish && isBullishTrendPassed; // bool isBearishTrendFiltered = isBearish && isBearishTrendPassed; // has = isBullishTrendFiltered || isBearishTrendFiltered; if (!has) { // iBar.Clean(); iPBar.Clean(); iZone.Clean(); fromBar.Clean(); // 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; } } } // fromIDX = iZone.FromIndex(); // // Find Base of Movement ... if (rayLeft) { // 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(); } // // Draw Object ... XCBoxObject *iZoneObj; has = drawer.DrawBox( iZone, iZoneObj // ); if (has) { // ApplyStyle(iZoneObj, iZone.dir); // mObjects.Add(iZoneObj); } ZeroMemory(iZoneObj); // // Cleanup Resources ... // iBar.Clean(); iPBar.Clean(); 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); // } //