diff --git a/Classes/x-saherelm.x-bar.analyser.class.mq5 b/Classes/x-saherelm.x-bar.analyser.class.mq5 index f4aec983..a089b1a3 100644 --- a/Classes/x-saherelm.x-bar.analyser.class.mq5 +++ b/Classes/x-saherelm.x-bar.analyser.class.mq5 @@ -2040,6 +2040,234 @@ class XCBarAnalyser : public XCBase return result; } + bool IsTrigger( + XOHCL &bar, + XBoxZone &box, + bool forceFVGBarType = false, + bool forceOBTwoBar = false, // + int loopback = 5 // + ) + { + // + bool result = false; + + // + // Normalize Args ... + box.Clean(); + loopback = NormalizeInt(loopback, 5); + + // + // Validate Args ... + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + XOHCL pBar; // Previous of Provided Bar ... + XOHCL iBar; + XOHCL iPBar; + int barIndex; + int pBarIndex; + + // + result = bar.GetPreviousBar(pBar); + if (!result) + { + // + box.Clean(); + pBar.Clean(); + iBar.Clean(); + iPBar.Clean(); + + // + return result; + } + + // + barIndex = bar.Index(); + pBarIndex = pBar.Index(); + + // + // Loopback to Find a Block ... + for (int i = pBarIndex; i < pBarIndex + loopback; i++) + { + // + // Inital IBar ... + result = iBar.Init( + bar.symbol, + bar.period, + i // + ); + if (!result) + { + break; + } + + // + // Detect Block ... + result = IsOB( + iBar, + box, + forceFVGBarType, + forceOBTwoBar // + ); + if (result) + { + break; + } + + // + iBar.Clean(); + } + iBar.Clean(); + + // + // Validate Block Detected ... + result = box.IsValid(); + if (!result) + { + // + box.Clean(); + pBar.Clean(); + iBar.Clean(); + iPBar.Clean(); + + // + return result; + } + + // + int toIDX = box.ToIndex(); + int fromIDX = box.FromIndex(); + bool isBullish = box.IsBullish(); + bool isBearish = box.IsBearish(); + + // + // Detect Swing Bar ... + XOHCL swingBar; + int swingBarIDX = -1; + int swingLoopback = fromIDX - barIndex; + if (isBullish) + { + // + // Looking for Swing Low ... + swingBarIDX = bar.FindLowestIndex(swingLoopback, MODE_LOW); + } + else if (isBearish) + { + // + // Looking for Swing High ... + swingBarIDX = bar.FindLowestIndex(swingLoopback, MODE_LOW); + } + result = IsValidIndex(swingBarIDX); + if (!result) + { + // + box.Clean(); + iBar.Clean(); + iPBar.Clean(); + swingBar.Clean(); + + // + return result; + } + + // + // Initialize Swing Bar ... + result = swingBar.Init( + bar.symbol, + bar.period, + swingBarIDX // + ); + if (!result) + { + // + box.Clean(); + iBar.Clean(); + iPBar.Clean(); + swingBar.Clean(); + + // + return result; + } + + // + // Now we Have to Check Spike from Swing Bar Next till Current Bar ... + // To Validate Highs and Lows ... + for (int i = pBarIndex; i < pBarIndex + (swingBarIDX - pBarIndex) - 1; i++) + { + // + // Initialize iBar ... + result = iBar.Init( + bar.symbol, + bar.period, + i // + ); + result = + result && + iBar.GetPreviousBar(iPBar); + if (!result) + { + break; + } + + // + // Since we Go Backward Bars from Current Bar ... + // for Bullish: each Bar Low Must over Prev Bar Low ... + // for Bearish: each Bar High Must Under Prev Bar High ... + if (isBullish) + { + result = iBar.low > iPBar.low; + } + else if (isBearish) + { + result = iBar.high < iPBar.high; + } + if (!result) + { + break; + } + + // + iBar.Clean(); + iPBar.Clean(); + } + iBar.Clean(); + iPBar.Clean(); + + // + // Ensure Spike Happens ... + if (!result) + { + // + box.Clean(); + pBar.Clean(); + iBar.Clean(); + iPBar.Clean(); + + // + return result; + } + + // + // Cleanup Resources ... + + // + iBar.Clean(); + swingBar.Clean(); + + // + if (!result) + { + box.Clean(); + } + + // + return result; + } + // // Candlestick ... diff --git a/Indicators/x-saherelm.x121.xczone.2.mq5 b/Indicators/x-saherelm.x121.xczone.2.mq5 new file mode 100644 index 00000000..e56dfa58 --- /dev/null +++ b/Indicators/x-saherelm.x121.xczone.2.mq5 @@ -0,0 +1,2288 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Indicator +// ------------------------------------------------- +// Name: X121 XCZone V2 +// Description: XCZone V2 ... +// +// +// 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 XCZone V2 Indicator" +#property strict + +// +// Definitions ... +// +#define ShortName "X121 XCZone" + +// +// Includes Common Library ... +#include "../Classes/x-saherelm.x-alert.class.mq5" +#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 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 int minZoneLength = 7; // Minimum Length of Consolidation Zone +input double maxZoneRangeInPoints = 70; // Max Zone Range in Point +input double maxAllowedEntryDistance = 30; // Max Allowed Entry Distance +input bool forceGapBarsBreakout = true; // Force Zone's Gap Bar's Breakes Out +input bool forceHasSwing = true; // Force Zone's Has Propper Swing +input bool forceHasPinBarEntry = true; // Force Zone's Ends with a Pin Bar + +// +// 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 + +// +// 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 drawZones = true; // Draw Detected Zones +input bool drawRRofZones = true; // Draw Zone's Risk Reward Ratios +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 +int rrZoneLength = 7; // Draw Risk Reward Ratio till n Bars + +// +// Alert ... +input group "Alerts"; +input string alertPrefix = ""; // Alert Prefix +input bool _logAlerts = true; // Log Alerts +input bool _pushAlerts = true; // Push Alerts +input bool _mailAlerts = false; // Mail Alerts +input bool _terminalAlerts = true; // Terminal Alerts + +// +// 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; + +// +XCAlert *alert; +double mPoints = 0; +CArrayObj mObjects; +XCPOIDrawer *drawer; +bool mEnableAlerts = false; +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 ... + + // + // Configure Alert ... + alert = new XCAlert(); + mEnableAlerts = + _logAlerts || + _pushAlerts || + _mailAlerts || + _terminalAlerts; + string mPrefix = ShortName + + (!IsValid(alertPrefix) + ? "" + : "[" + alertPrefix + "]"); + alert.SetPrefix(mPrefix); + alert.SetLogAlerts(_logAlerts); + alert.SetMailAlerts(_mailAlerts); + alert.SetPushAlerts(_pushAlerts); + alert.SetEnableAlerts(mEnableAlerts); + alert.SetTerminalAlerts(_terminalAlerts); + + // + 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 + + // + mObjects.Clear(); + + // + delete alert; + delete drawer; + + // + ZeroMemory(alert); + 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, 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 // + ); +} + +// +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; + } + } + + // + // Validate Gap Endup with PinBar ... + has = forceHasPinBarEntry; + if (has) + { + // + bool isBullishRejected = + isBullish && + cBar.IsBullish() && + cBar.GetLowShadow() > cBar.GetHighShadow(); + + // + bool isBearishRejected = + isBearish && + cBar.IsBearish() && + cBar.GetLowShadow() < cBar.GetHighShadow(); + + // + has = isBullishRejected || + isBearishRejected; + 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(); + } + + // + // Validate Max Allowed Entry Distance ... + has = maxAllowedEntryDistance > 0; + if (has) + { + // + double base = + isBullish + ? zone.upper + : zone.lower; + double entryDistance = MathAbs(zBar.open - base); + has = entryDistance <= maxAllowedEntryDistance * mPoints; + if (!has) + { + // + zone.Clean(); + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + p2Bar.Clean(); + p3Bar.Clean(); + p4Bar.Clean(); + + // + return; + } + } + + // + // 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; + 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 ... + if (drawZones) + { + // + 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); + } + + // + // Draw RR Tool ... + if (drawRRofZones) + { + // + double rr[]{ + 1, + 1.5, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10 // + }; + XCRRObject *iRRObj; + iRRObj = new XCRRObject(); + has = iRRObj.CreateBoxRR( + drawer.ChartIdentification(), + drawer.SubWindowIdentification(), + zone, + rr, + rrZoneLength // + ); + if (has) + { + // + int iWidth = 2; + ENUM_LINE_STYLE iStyle = STYLE_SOLID; + + // + iRRObj.TPWidth(iWidth); + iRRObj.SLWidth(iWidth); + iRRObj.EntryWidth(iWidth); + iRRObj.TargetWidth(iWidth); + + // + iRRObj.TPStyle(iStyle); + iRRObj.SLStyle(iStyle); + iRRObj.EntryStyle(iStyle); + iRRObj.TargetStyle(iStyle); + + // + iRRObj.TPColor(clrLime); + iRRObj.SLColor(clrRed); + iRRObj.EntryColor(clrYellow); + iRRObj.TargetColor(clrLightBlue); + + // + mObjects.Add(iRRObj); + } + ZeroMemory(iRRObj); + } + + // + // Handle Alerst ... + bool canAlert = + mEnableAlerts && + prevCalculated > 0; + bool canLogOnly = + mEnableAlerts && + prevCalculated == 0; + if (canAlert || canLogOnly) + { + // + string message = + zone.symbol + "," + + ToString(zone.period) + "> " + + ToString(zone.dir) + + " Zone Detected at: " + ToString(zone.to); + + // + if (canLogOnly) + { + alert.LogAlert(message); + } + else if (canAlert) + { + alert.Alert(message); + } + } + + // + // 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/Indicators/x-saherelm.x121.xczone.mq5 b/Indicators/x-saherelm.x121.xczone.mq5 index f5321b92..ec4125f4 100644 --- a/Indicators/x-saherelm.x121.xczone.mq5 +++ b/Indicators/x-saherelm.x121.xczone.mq5 @@ -16,7 +16,7 @@ #property copyright "Copyright 2023, SaherElm IT Center" #property link "https://saherelm.ir" #property version "1.00" -#property description "SaherElm X121 X3MA Indicator" +#property description "SaherElm X121 XCZone Indicator" #property strict // diff --git a/XCAEA/Libraries/xcaea.trigger.block.lib.mq5 b/XCAEA/Libraries/xcaea.trigger.block.lib.mq5 index addb4fb9..1517b562 100644 --- a/XCAEA/Libraries/xcaea.trigger.block.lib.mq5 +++ b/XCAEA/Libraries/xcaea.trigger.block.lib.mq5 @@ -1595,4 +1595,53 @@ bool DetectTriggerBlock( return result; }; +bool DetectTriggerBlock1( + XBoxZone &triggerBlock, + XCAEAConditions &conditions, + XCXCAEAHelper *helper, + XCAEATriggerBlockConfiguration &config, + int bar_index = 0, + int loopback = 6 // +) { + // + bool result = false; + + // + conditions.Clean(); + triggerBlock.Clean(); + + // + // Normalize Args ... + loopback = NormalizeInt(loopback, 6); + bar_index = NormalizeInt(bar_index, 0); + + // + // Validate Args ... + result = helper != NULL; + if (!result) + { + return result; + } + + // + // Provide base Requirements ... + + // + string symbol = helper.GetSymbol(); + double points = GetPoints(symbol); + ENUM_TIMEFRAMES period = helper.GetPeriod(); + + // + // Conditions Reading Indexes ... + int zIDX = 0; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + int p2IDX = pIDX + 1; + int p3IDX = p2IDX + 1; + int p4IDX = p3IDX + 1; + + // + return result; +} + // \ No newline at end of file diff --git a/XCAEA/Signals/xcaea.signaller.class.mq5 b/XCAEA/Signals/xcaea.signaller.class.mq5 index e107f473..f6de1fea 100644 --- a/XCAEA/Signals/xcaea.signaller.class.mq5 +++ b/XCAEA/Signals/xcaea.signaller.class.mq5 @@ -288,10 +288,29 @@ class XCXCAEASignaller : XCBase XBoxZone tmpZone; XCAEATriggerBlockConfiguration config; + // + bool allowTwoFilters = false; + bool allowThreeFilters = false; + + // + bool hasFullFiltered = false; + bool hasSarRsiAdxFiltered = false; + bool hasSarRsiTrendFiltered = false; + bool hasSarAdxTrendFiltered = false; + bool hasRsiAdxTrendFiltered = false; + + // + bool hasSarRsiFiltered = false; + bool hasSarAdxFiltered = false; + bool hasRsiAdxFiltered = false; + bool hasSarTrendFiltered = false; + bool hasRsiTrendFiltered = false; + bool hasAdxTrendFiltered = false; + // // Full Filteres ... config.ConfigureFullFilter(); - bool hasFullFiltered = DetectTriggerBlock( + hasFullFiltered = DetectTriggerBlock( tmpZone, conditions, helper, @@ -312,232 +331,242 @@ class XCXCAEASignaller : XCBase } // - tmpZone.Clean(); - config.ConfigureSarRsiAdxFilter(); - bool hasSarRsiAdxFiltered = DetectTriggerBlock( - tmpZone, - conditions, - helper, - config, - zIndex, - loopback // - ); - if (hasSarRsiAdxFiltered) + // Check Three Filters ... + if (allowThreeFilters) { // - pushers++; + tmpZone.Clean(); + config.ConfigureSarRsiAdxFilter(); + hasSarRsiAdxFiltered = DetectTriggerBlock( + tmpZone, + conditions, + helper, + config, + zIndex, + loopback // + ); + if (hasSarRsiAdxFiltered) + { + // + pushers++; + + // + if (!decisionZone.IsValid()) + { + decisionZone = tmpZone; + } + } // - if (!decisionZone.IsValid()) + tmpZone.Clean(); + config.ConfigureSarRsiTrendFilter(); + hasSarRsiTrendFiltered = DetectTriggerBlock( + tmpZone, + conditions, + helper, + config, + zIndex, + loopback // + ); + if (hasSarRsiTrendFiltered) { - decisionZone = tmpZone; + // + pushers++; + + // + if (!decisionZone.IsValid()) + { + decisionZone = tmpZone; + } + } + + // + tmpZone.Clean(); + config.ConfigureSarAdxTrendFilter(); + hasSarAdxTrendFiltered = DetectTriggerBlock( + tmpZone, + conditions, + helper, + config, + zIndex, + loopback // + ); + if (hasSarAdxTrendFiltered) + { + // + pushers++; + + // + if (!decisionZone.IsValid()) + { + decisionZone = tmpZone; + } + } + + // + tmpZone.Clean(); + config.ConfigureRsiAdxTrendFilter(); + hasRsiAdxTrendFiltered = DetectTriggerBlock( + tmpZone, + conditions, + helper, + config, + zIndex, + loopback // + ); + if (hasRsiAdxTrendFiltered) + { + // + pushers++; + + // + if (!decisionZone.IsValid()) + { + decisionZone = tmpZone; + } } } // - tmpZone.Clean(); - config.ConfigureSarRsiTrendFilter(); - bool hasSarRsiTrendFiltered = DetectTriggerBlock( - tmpZone, - conditions, - helper, - config, - zIndex, - loopback // - ); - if (hasSarRsiTrendFiltered) + // Check two Filters ... + if (allowTwoFilters) { // - pushers++; - - // - if (!decisionZone.IsValid()) + tmpZone.Clean(); + config.ConfigureSarRsiFilter(); + hasSarRsiFiltered = DetectTriggerBlock( + tmpZone, + conditions, + helper, + config, + zIndex, + loopback // + ); + if (hasSarRsiFiltered) { - decisionZone = tmpZone; + // + pushers++; + + // + if (!decisionZone.IsValid()) + { + decisionZone = tmpZone; + } } - } - - // - tmpZone.Clean(); - config.ConfigureSarAdxTrendFilter(); - bool hasSarAdxTrendFiltered = DetectTriggerBlock( - tmpZone, - conditions, - helper, - config, - zIndex, - loopback // - ); - if (hasSarAdxTrendFiltered) - { - // - pushers++; // - if (!decisionZone.IsValid()) + tmpZone.Clean(); + config.ConfigureSarAdxFilter(); + hasSarAdxFiltered = DetectTriggerBlock( + tmpZone, + conditions, + helper, + config, + zIndex, + loopback // + ); + if (hasSarAdxFiltered) { - decisionZone = tmpZone; + // + pushers++; + + // + if (!decisionZone.IsValid()) + { + decisionZone = tmpZone; + } } - } - - // - tmpZone.Clean(); - config.ConfigureRsiAdxTrendFilter(); - bool hasRsiAdxTrendFiltered = DetectTriggerBlock( - tmpZone, - conditions, - helper, - config, - zIndex, - loopback // - ); - if (hasRsiAdxTrendFiltered) - { - // - pushers++; // - if (!decisionZone.IsValid()) + tmpZone.Clean(); + config.ConfigureSarTrendFilter(); + hasSarTrendFiltered = DetectTriggerBlock( + tmpZone, + conditions, + helper, + config, + zIndex, + loopback // + ); + if (hasSarTrendFiltered) { - decisionZone = tmpZone; + // + pushers++; + + // + if (!decisionZone.IsValid()) + { + decisionZone = tmpZone; + } } - } - - // - tmpZone.Clean(); - config.ConfigureSarRsiFilter(); - bool hasSarRsiFiltered = DetectTriggerBlock( - tmpZone, - conditions, - helper, - config, - zIndex, - loopback // - ); - if (hasSarRsiFiltered) - { - // - pushers++; // - if (!decisionZone.IsValid()) + tmpZone.Clean(); + config.ConfigureRsiAdxFilter(); + hasRsiAdxFiltered = DetectTriggerBlock( + tmpZone, + conditions, + helper, + config, + zIndex, + loopback // + ); + if (hasRsiAdxFiltered) { - decisionZone = tmpZone; + // + pushers++; + + // + if (!decisionZone.IsValid()) + { + decisionZone = tmpZone; + } } - } - - // - tmpZone.Clean(); - config.ConfigureSarAdxFilter(); - bool hasSarAdxFiltered = DetectTriggerBlock( - tmpZone, - conditions, - helper, - config, - zIndex, - loopback // - ); - if (hasSarAdxFiltered) - { - // - pushers++; // - if (!decisionZone.IsValid()) + tmpZone.Clean(); + config.ConfigureRsiTrendFilter(); + hasRsiTrendFiltered = DetectTriggerBlock( + tmpZone, + conditions, + helper, + config, + zIndex, + loopback // + ); + if (hasRsiTrendFiltered) { - decisionZone = tmpZone; + // + pushers++; + + // + if (!decisionZone.IsValid()) + { + decisionZone = tmpZone; + } } - } - - // - tmpZone.Clean(); - config.ConfigureSarTrendFilter(); - bool hasSarTrendFiltered = DetectTriggerBlock( - tmpZone, - conditions, - helper, - config, - zIndex, - loopback // - ); - if (hasSarTrendFiltered) - { - // - pushers++; // - if (!decisionZone.IsValid()) + tmpZone.Clean(); + config.ConfigureAdxTrendFilter(); + hasAdxTrendFiltered = DetectTriggerBlock( + tmpZone, + conditions, + helper, + config, + zIndex, + loopback // + ); + if (hasAdxTrendFiltered) { - decisionZone = tmpZone; - } - } + // + pushers++; - // - tmpZone.Clean(); - config.ConfigureRsiAdxFilter(); - bool hasRsiAdxFiltered = DetectTriggerBlock( - tmpZone, - conditions, - helper, - config, - zIndex, - loopback // - ); - if (hasRsiAdxFiltered) - { - // - pushers++; - - // - if (!decisionZone.IsValid()) - { - decisionZone = tmpZone; - } - } - - // - tmpZone.Clean(); - config.ConfigureRsiTrendFilter(); - bool hasRsiTrendFiltered = DetectTriggerBlock( - tmpZone, - conditions, - helper, - config, - zIndex, - loopback // - ); - if (hasRsiTrendFiltered) - { - // - pushers++; - - // - if (!decisionZone.IsValid()) - { - decisionZone = tmpZone; - } - } - - // - tmpZone.Clean(); - config.ConfigureAdxTrendFilter(); - bool hasAdxTrendFiltered = DetectTriggerBlock( - tmpZone, - conditions, - helper, - config, - zIndex, - loopback // - ); - if (hasAdxTrendFiltered) - { - // - pushers++; - - // - if (!decisionZone.IsValid()) - { - decisionZone = tmpZone; + // + if (!decisionZone.IsValid()) + { + decisionZone = tmpZone; + } } } @@ -1214,7 +1243,7 @@ class XCXCAEASignaller : XCBase inputs.x3maInputs.fastLength = 5; // - inputs.x3maInputs.showFast = true; + inputs.x3maInputs.showFast = false; inputs.x3maInputs.showSlow = false; inputs.x3maInputs.showMedium = false; @@ -1235,16 +1264,16 @@ class XCXCAEASignaller : XCBase inputs.caInputs.showMAH = false; inputs.caInputs.showMAL = false; inputs.caInputs.showMAC = false; - inputs.caInputs.showSar = true; + inputs.caInputs.showSar = false; inputs.caInputs.showVidya = false; - inputs.caInputs.showTrend = true; - inputs.caInputs.showSwings = true; + inputs.caInputs.showTrend = false; + inputs.caInputs.showSwings = false; inputs.caInputs.showFiboLevel1 = false; inputs.caInputs.showFiboLevel2 = false; inputs.caInputs.showFiboLevel3 = false; inputs.caInputs.showFiboLevel4 = false; inputs.caInputs.showFiboLevel5 = false; - inputs.caInputs.showPeaksAndVales = true; + inputs.caInputs.showPeaksAndVales = false; inputs.caInputs.showPeakAndValeGolden = false; inputs.caInputs.showSupportAndResistance = false;