/////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 Class // ------------------------------------------------- // Name: XCX121XKIPoiDetector ... // Description: X121XKI POI Detector Class ... // // // Maintainer: // ------------ // Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) // ////////////////////////////////////////////////////// // // Global Properties ... #property library #property copyright "Copyright 2023, SaherElm IT Center" #property link "https://saherelm.ir" #property version "1.00" #property description "SaherElm X121XKI POI Detector Class" #property strict // // Imports ... #include "../../Classes/x-saherelm.base.class.mq5" #include "../../Classes/x-saherelm.x-bar.analyser.class.mq5" #include "../../Classes/x-saherelm.x-market.pattern.class.mq5" #include "../../Helpers/x-saherelm.x121.xki.helper.mq5" #include "../Classes/x-saherelm.x121.xki.parser.class.mq5" // // Definitions ... // // Implementation ... class XCX121XKIPOIDetector : public XCMarketPatternDetector { // // Public ... public: // // Props ... // string symbol; ENUM_TIMEFRAMES period; // XCBarAnalyser *barAnalyser; // Bar Analyser ... XCX121XKIHelper *kiHelper; // X121XKI Helper ... XCX121XKIHelperParser *kiParser; // X121XKI Helper Parser ... // // Constructor ... XCX121XKIPOIDetector( XCX121XKIHelper *_kiHelper, XCX121XKIHelperParser *_kiParser // ) : XCMarketPatternDetector() { // barAnalyser = new XCBarAnalyser(); kiHelper = _kiHelper; kiParser = _kiParser; // symbol = kiHelper.GetSymbol(); period = kiHelper.GetPeriod(); } // // Deconstructor ... ~XCX121XKIPOIDetector() { Destroy(); } // // Actions and Tools ... // #region POI Detectors ... bool NearestKIFastBullish( int &index, int barIndex = 0, int loopback = 50 // ) { // bool result = false; // index = -1; // // Normalize ... barIndex = kiParser.NormalizeBarIndex(barIndex); // // Loop Back ... bool isPassed = false; for (int i = barIndex; i < barIndex + loopback; i++) { // isPassed = kiParser.IsKIFastBullish(i); if (isPassed) { // index = i; break; } } // result = IsValidIndex(index); // return result; } bool NearestKIFastBearish( int &index, int barIndex = 0, int loopback = 50 // ) { // bool result = false; // index = -1; // // Normalize ... barIndex = kiParser.NormalizeBarIndex(barIndex); // // Loop Back ... bool isPassed = false; for (int i = barIndex; i < barIndex + loopback; i++) { // isPassed = kiParser.IsKIFastBearish(i); if (isPassed) { // index = i; break; } } // result = IsValidIndex(index); // return result; } bool NearestKIFastSwitchedToBullish( int &index, int barIndex = 0, int loopback = 50 // ) { // bool result = false; // index = -1; // // Normalize ... barIndex = kiParser.NormalizeBarIndex(barIndex); // // Loop Back ... bool isPassed = false; for (int i = barIndex; i < barIndex + loopback; i++) { // isPassed = kiParser.IsKIFastSwitchedToBullish(i); if (isPassed) { // index = i; break; } } // result = IsValidIndex(index); // return result; } bool NearestKIFastSwitchedToBearish( int &index, int barIndex = 0, int loopback = 50 // ) { // bool result = false; // index = -1; // // Normalize ... barIndex = kiParser.NormalizeBarIndex(barIndex); // // Loop Back ... bool isPassed = false; for (int i = barIndex; i < barIndex + loopback; i++) { // isPassed = kiParser.IsKIFastSwitchedToBearish(i); if (isPassed) { // index = i; break; } } // result = IsValidIndex(index); // return result; } bool NearestKISlowBullish( int &index, int barIndex = 0, int loopback = 50 // ) { // bool result = false; // index = -1; // // Normalize ... barIndex = kiParser.NormalizeBarIndex(barIndex); // // Loop Back ... bool isPassed = false; for (int i = barIndex; i < barIndex + loopback; i++) { // isPassed = kiParser.IsKISlowBullish(i); if (isPassed) { // index = i; break; } } // result = IsValidIndex(index); // return result; } bool NearestKISlowBearish( int &index, int barIndex = 0, int loopback = 50 // ) { // bool result = false; // index = -1; // // Normalize ... barIndex = kiParser.NormalizeBarIndex(barIndex); // // Loop Back ... bool isPassed = false; for (int i = barIndex; i < barIndex + loopback; i++) { // isPassed = kiParser.IsKISlowBearish(i); if (isPassed) { // index = i; break; } } // result = IsValidIndex(index); // return result; } bool NearestKISlowSwitchedToBullish( int &index, int barIndex = 0, int loopback = 50 // ) { // bool result = false; // index = -1; // // Normalize ... barIndex = kiParser.NormalizeBarIndex(barIndex); // // Loop Back ... bool isPassed = false; for (int i = barIndex; i < barIndex + loopback; i++) { // isPassed = kiParser.IsKISlowSwitchedToBullish(i); if (isPassed) { // index = i; break; } } // result = IsValidIndex(index); // return result; } bool NearestKISlowSwitchedToBearish( int &index, int barIndex = 0, int loopback = 50 // ) { // bool result = false; // index = -1; // // Normalize ... barIndex = kiParser.NormalizeBarIndex(barIndex); // // Loop Back ... bool isPassed = false; for (int i = barIndex; i < barIndex + loopback; i++) { // isPassed = kiParser.IsKISlowSwitchedToBearish(i); if (isPassed) { // index = i; break; } } // result = IsValidIndex(index); // return result; } // #endregion // #region Detectors ... bool IsPOI( ENUM_X_DIRECTION &forDir, int barIndex = 0 // ) { // bool result = false; // // Normalize ... forDir = X_DIRECTION_NONE; barIndex = kiParser.NormalizeBarIndex(barIndex); // bool isBullish = IsBullishPOI(barIndex); bool isBearish = IsBearishPOI(barIndex); result = isBullish || isBearish; if (!result) { return result; } // forDir = isBullish ? X_DIRECTION_BULLISH : isBearish ? X_DIRECTION_BEARISH : X_DIRECTION_NONE; result = HasDirection(forDir); // return result; } bool IsBullishPOI(int barIndex = 0) { // bool result = false; // barIndex = kiParser.NormalizeBarIndex(barIndex); // result = kiParser.IsTrendBullish(barIndex) && kiParser.IsRSIBullish(barIndex); if (!result) { return result; } // // Add candlestick confirmation ... XOHCL bar; result = result && bar.Init(symbol, period, barIndex); if (!result) { return result; } // result = result && HasCandlestickDirection( bar, X_DIRECTION_BULLISH // ); // bar.Clean(); // return result; } bool IsBearishPOI(int barIndex = 0) { // bool result = false; // barIndex = kiParser.NormalizeBarIndex(barIndex); // result = kiParser.IsTrendBearish(barIndex) && kiParser.IsRSIBearish(barIndex); if (!result) { return result; } // // Add candlestick confirmation ... XOHCL bar; result = result && bar.Init(symbol, period, barIndex); if (!result) { return result; } // result = result && HasCandlestickDirection( bar, X_DIRECTION_BEARISH // ); // bar.Clean(); // return result; } bool IsBreakoutPOI( ENUM_X_DIRECTION &forDir, int barIndex = 0 // ) { // bool result = false; // // Normalize ... forDir = X_DIRECTION_NONE; barIndex = kiParser.NormalizeBarIndex(barIndex); // bool isBullish = IsBullishBreakoutPOI(barIndex); bool isBearish = IsBearishBreakoutPOI(barIndex); result = isBullish || isBearish; if (!result) { return result; } // forDir = isBullish ? X_DIRECTION_BULLISH : isBearish ? X_DIRECTION_BEARISH : X_DIRECTION_NONE; result = HasDirection(forDir); // return result; } bool IsBullishBreakoutPOI(int barIndex = 0) { // bool result = false; // barIndex = kiParser.NormalizeBarIndex(barIndex); // result = kiParser.IsBullishBreakout(barIndex); if (!result) { return result; } // // Add candlestick confirmation ... XOHCL bar; result = result && bar.Init(symbol, period, barIndex); if (!result) { return result; } // result = result && HasCandlestickDirection( bar, X_DIRECTION_BULLISH // ); // bar.Clean(); // return result; } bool IsBearishBreakoutPOI(int barIndex = 0) { // bool result = false; // barIndex = kiParser.NormalizeBarIndex(barIndex); // result = kiParser.IsBearishBreakout(barIndex); if (!result) { return result; } // // Add candlestick confirmation ... XOHCL bar; result = result && bar.Init(symbol, period, barIndex); if (!result) { return result; } // result = result && HasCandlestickDirection( bar, X_DIRECTION_BEARISH // ); // bar.Clean(); // return result; } bool IsReversalPOI( ENUM_X_DIRECTION &forDir, int barIndex = 0 // ) { // bool result = false; // // Normalize ... forDir = X_DIRECTION_NONE; barIndex = kiParser.NormalizeBarIndex(barIndex); // bool isBullish = IsBullishReversalPOI(barIndex); bool isBearish = IsBearishReversalPOI(barIndex); result = isBullish || isBearish; if (!result) { return result; } // forDir = isBullish ? X_DIRECTION_BULLISH : isBearish ? X_DIRECTION_BEARISH : X_DIRECTION_NONE; result = HasDirection(forDir); // return result; } bool IsBullishReversalPOI(int barIndex = 0) { // bool result = false; // barIndex = kiParser.NormalizeBarIndex(barIndex); // result = kiParser.IsBullishReversal(barIndex); if (!result) { return result; } // // Add candlestick confirmation ... XOHCL bar; result = result && bar.Init(symbol, period, barIndex); if (!result) { return result; } // result = result && HasCandlestickDirection( bar, X_DIRECTION_BULLISH // ); // bar.Clean(); // return result; } bool IsBearishReversalPOI(int barIndex = 0) { // bool result = false; // barIndex = kiParser.NormalizeBarIndex(barIndex); // result = kiParser.IsBearishReversal(barIndex); if (!result) { return result; } // // Add candlestick confirmation ... XOHCL bar; result = result && bar.Init(symbol, period, barIndex); if (!result) { return result; } // result = result && HasCandlestickDirection( bar, X_DIRECTION_BEARISH // ); // bar.Clean(); // return result; } bool IsContinuationPOI( ENUM_X_DIRECTION &forDir, int barIndex = 0 // ) { // bool result = false; // // Normalize ... forDir = X_DIRECTION_NONE; barIndex = kiParser.NormalizeBarIndex(barIndex); // bool isBullish = IsBullishContinuationPOI(barIndex); bool isBearish = IsBearishContinuationPOI(barIndex); result = isBullish || isBearish; if (!result) { return result; } // forDir = isBullish ? X_DIRECTION_BULLISH : isBearish ? X_DIRECTION_BEARISH : X_DIRECTION_NONE; result = HasDirection(forDir); // return result; } bool IsBullishContinuationPOI(int barIndex = 0) { // bool result = false; // barIndex = kiParser.NormalizeBarIndex(barIndex); // result = kiParser.IsTrendStrongBullish(barIndex); if (!result) { return result; } // // Add candlestick confirmation ... XOHCL bar; ENUM_X_DIRECTION dir; result = result && bar.Init(symbol, period, barIndex); if (!result) { return result; } // XOHCL swingBar; result = result && IsFlagPattern(bar, dir, swingBar) && IsXBullish(dir); // bar.Clean(); swingBar.Clean(); // return result; } bool IsBearishContinuationPOI(int barIndex = 0) { // bool result = false; // barIndex = kiParser.NormalizeBarIndex(barIndex); // result = kiParser.IsTrendStrongBearish(barIndex); if (!result) { return result; } // // Add candlestick confirmation ... XOHCL bar; ENUM_X_DIRECTION dir; result = result && bar.Init(symbol, period, barIndex); if (!result) { return result; } // XOHCL swingBar; result = result && IsFlagPattern(bar, dir, swingBar) && IsXBearish(dir); // bar.Clean(); swingBar.Clean(); // return result; } bool IsExhaustionPOI( ENUM_X_DIRECTION &forDir, int barIndex = 0 // ) { // bool result = false; // // Normalize ... forDir = X_DIRECTION_NONE; barIndex = kiParser.NormalizeBarIndex(barIndex); // bool isBullish = IsBullishExhaustionPOI(barIndex); bool isBearish = IsBearishExhaustionPOI(barIndex); result = isBullish || isBearish; if (!result) { return result; } // forDir = isBullish ? X_DIRECTION_BULLISH : isBearish ? X_DIRECTION_BEARISH : X_DIRECTION_NONE; result = HasDirection(forDir); // return result; } bool IsBullishExhaustionPOI(int barIndex = 0) { // bool result = false; // barIndex = kiParser.NormalizeBarIndex(barIndex); // bool isTrendOk = kiParser.IsTrendStrongBullish(barIndex); bool isRSIOk = kiParser.IsRSIOverbought(barIndex); result = isTrendOk && isRSIOk; if (!result) { return result; } // // Add candlestick confirmation ... XOHCL bar; result = result && bar.Init(symbol, period, barIndex); if (!result) { return result; } // result = result && HasCandlestickDirection( bar, X_DIRECTION_BEARISH // ); // bar.Clean(); // return result; } bool IsBearishExhaustionPOI(int barIndex = 0) { // bool result = false; // barIndex = kiParser.NormalizeBarIndex(barIndex); // bool isTrendOk = kiParser.IsTrendStrongBearish(barIndex); bool isRSIOk = kiParser.IsRSIOversold(barIndex); result = isTrendOk && isRSIOk; if (!result) { return result; } // // Add candlestick confirmation ... XOHCL bar; result = result && bar.Init(symbol, period, barIndex); if (!result) { return result; } // result = result && HasCandlestickDirection( bar, X_DIRECTION_BULLISH // ); // bar.Clean(); // return result; } bool IsTrendExhaustedPOI( ENUM_X_DIRECTION &forDir, int barIndex = 0 // ) { // bool result = false; // // Normalize ... forDir = X_DIRECTION_NONE; barIndex = kiParser.NormalizeBarIndex(barIndex); // bool isBullish = IsBullishTrendExhaustedPOI(barIndex); bool isBearish = IsBearishTrendExhaustedPOI(barIndex); result = isBullish || isBearish; if (!result) { return result; } // forDir = isBullish ? X_DIRECTION_BULLISH : isBearish ? X_DIRECTION_BEARISH : X_DIRECTION_NONE; result = HasDirection(forDir); // return result; } bool IsBullishTrendExhaustedPOI(int barIndex = 0) { // bool result = false; // barIndex = kiParser.NormalizeBarIndex(barIndex); // // Trend was strong in last 3 bars ... bool isTrendOk = kiParser.IsTrendStrongBullish(barIndex + 1); for (int i = 1; i <= 3; i++) { // if (kiParser.IsTrendStrongBullish(barIndex + i)) { isTrendOk = true; break; } } // // RSI rolling over from overbought ... double rsiNow = kiHelper.GetRSI(barIndex); double rsiPrev = kiHelper.GetRSI(barIndex + 1); bool rsiFlip = (rsiPrev > 70 && rsiNow < rsiPrev); bool isRSIOk = rsiFlip || kiParser.IsRSIOverbought(barIndex); // bool volCooling = kiHelper.GetATR(barIndex) <= kiHelper.GetATRSmoothed(barIndex) * 1.05; bool isVolatilityOk = volCooling || kiParser.IsVolatilityLow(barIndex); // result = isRSIOk && isTrendOk && isVolatilityOk; if (!result) { return result; } // // Add candlestick confirmation ... XOHCL bar; result = result && bar.Init(symbol, period, barIndex); if (!result) { return result; } // result = result && HasCandlestickDirection( bar, X_DIRECTION_BEARISH // ); // bar.Clean(); // return result; } bool IsBearishTrendExhaustedPOI(int barIndex = 0) { // bool result = false; // barIndex = kiParser.NormalizeBarIndex(barIndex); // bool isTrendOk = kiParser.IsTrendStrongBearish(barIndex + 1); for (int i = 1; i <= 3; i++) { // if (kiParser.IsTrendStrongBearish(barIndex + i)) { isTrendOk = true; break; } } // // RSI rolling over from overbought ... double rsiNow = kiHelper.GetRSI(barIndex); double rsiPrev = kiHelper.GetRSI(barIndex + 1); bool rsiFlip = (rsiPrev < 30 && rsiNow > rsiPrev); bool isRSIOk = rsiFlip || kiParser.IsRSIOversold(barIndex); // bool volCooling = kiHelper.GetATR(barIndex) <= kiHelper.GetATRSmoothed(barIndex) * 1.05; bool isVolatilityOk = volCooling || kiParser.IsVolatilityLow(barIndex); // result = isRSIOk && isTrendOk && isVolatilityOk; if (!result) { return result; } // // Add candlestick confirmation ... XOHCL bar; result = result && bar.Init(symbol, period, barIndex); if (!result) { return result; } // result = result && HasCandlestickDirection( bar, X_DIRECTION_BULLISH // ); // bar.Clean(); // return result; } // #endregion // #region XDetectors ... bool IsKIPOI( ENUM_X_DIRECTION &dir, int barIndex = 0 // ) { // bool result = false; // dir = X_DIRECTION_NONE; // bool isBullish = IsKIBullishPOI(barIndex); bool isBearish = IsKIBearishPOI(barIndex); // dir = isBullish ? X_DIRECTION_BULLISH : isBearish ? X_DIRECTION_BEARISH : X_DIRECTION_NONE; // result = HasDirection(dir); // return result; } bool IsKIBullishPOI(int barIndex = 0) { // bool result = false; // barIndex = kiParser.NormalizeBarIndex(barIndex); // result = kiParser.IsValid() && kiParser.IsKISlowBullish(barIndex) && kiParser.IsKIFastBearish(barIndex); // return result; } bool IsKIBearishPOI(int barIndex = 0) { // bool result = false; // barIndex = kiParser.NormalizeBarIndex(barIndex); // result = kiParser.IsValid() && kiParser.IsKISlowBearish(barIndex) && kiParser.IsKIFastBullish(barIndex); // return result; } bool IsKISignal( ENUM_X_DIRECTION &dir, // int barIndex = 0 // ) { // bool result = false; // dir = X_DIRECTION_NONE; barIndex = kiParser.NormalizeBarIndex(barIndex); // // Retrieve KI State ... bool isBullish = kiParser.IsKIFastSwitchedToBullish(barIndex + 1) && kiParser.IsKIFastBullish(barIndex) && kiParser.IsKISlowBullish(barIndex); bool isBearish = kiParser.IsKIFastSwitchedToBearish(barIndex + 1) && kiParser.IsKIFastBearish(barIndex) && kiParser.IsKISlowBearish(barIndex); result = isBullish || isBearish; if (!result) { return result; } // dir = isBullish ? X_DIRECTION_BULLISH : isBearish ? X_DIRECTION_BEARISH : X_DIRECTION_NONE; result = HasDirection(dir); if (!result) { return result; } // XOHCL bar; result = bar.Init(symbol, period, barIndex + 1); if (!result) { return result; } // // Bar Direction Same as Dir ... // // Price Place Check ... double kiFast = kiHelper.GetKIFast(barIndex + 1); double kiSlow = kiHelper.GetKISlow(barIndex + 1); isBullish = isBullish && bar.close > kiFast && kiFast > kiSlow && (kiParser.IsKIFastOverLast(barIndex + 1) || kiParser.IsKISlowOverLast(barIndex + 1)); isBearish = isBearish && bar.close < kiFast && kiFast < kiSlow && (kiParser.IsKIFastUnderLast(barIndex + 1) || kiParser.IsKISlowUnderLast(barIndex + 1)); // result = result && (isBullish || isBearish); // // Cleanup Resources ... bar.Clean(); // return result; } // #endregion // #region Zone Detectors ... int DetectSupports( XBoxZone &zones[], int barIndex, int loopback = 50, bool forceValidation = true, int validationLength = 7, int minimumRetests = 2, double retestThreshold = 10, int retestLoopback = 100, string forSymbol = NULL, ENUM_TIMEFRAMES forPeriod = NULL // ) { // int result = 0; // XClean(zones); // // Normalize ... // if (barIndex < 0) { barIndex = 0; } // if (!IsXValid(forSymbol)) { forSymbol = symbol; } // if (!IsXValid(forPeriod)) { forPeriod = period; } // if (loopback < 2) { loopback = 2; } // if (validationLength < 2) { validationLength = 2; } // // Preparing Loops ... XOHCL tmpBar; bool has = false; double upper = 0; double lower = 0; XBoxZone tmpZone; string type = NULL; double tmpValue = 0; datetime from = NULL; int start = barIndex; int end = barIndex + loopback; datetime to = GetBarTime(forSymbol, forPeriod, barIndex); for (int i = start; i < end; i++) { // // Initialize Bar ... if (tmpBar.Init(forSymbol, forPeriod, i)) { // // Check Has Shadow ... has = tmpBar.GetHighShadow() > 0 || tmpBar.GetLowShadow() > 0; if (has) { // // Check Support or Resistance ... // // Support ... tmpValue = tmpBar.FindLowest(validationLength, MODE_LOW); has = NotEmptyZero(tmpValue) && tmpValue == tmpBar.low; // if (has) { // tmpZone.Clean(); lower = tmpValue; from = tmpBar.time; upper = tmpBar.GetDown(); type = ToXString(X_BAR_PATTERN_SUPPORT); has = tmpZone.Init( forSymbol, forPeriod, upper, lower, from, to, X_DIRECTION_BULLISH, type // ); if (has) { // AddRef( tmpZone, zones // ); // tmpZone.Clean(); } } } // tmpBar.Clean(); } } // // Validate ... if (HasChild(zones) && forceValidation) { // ValidateZones( zones, barIndex, minimumRetests, retestThreshold, retestLoopback // ); } // result = ArraySize(zones); // return result; } int DetectResistances( XBoxZone &zones[], int barIndex, int loopback = 50, bool forceValidation = true, int validationLength = 7, int minimumRetests = 2, double retestThreshold = 10, int retestLoopback = 100, string forSymbol = NULL, ENUM_TIMEFRAMES forPeriod = NULL // ) { // int result = 0; // XClean(zones); // // Normalize ... // if (barIndex < 0) { barIndex = 0; } // if (!IsXValid(forSymbol)) { forSymbol = symbol; } // if (!IsXValid(forPeriod)) { forPeriod = period; } // if (loopback < 2) { loopback = 2; } // if (validationLength < 2) { validationLength = 2; } // // Preparing Loops ... XOHCL tmpBar; bool has = false; double upper = 0; double lower = 0; XBoxZone tmpZone; string type = NULL; double tmpValue = 0; datetime from = NULL; int start = barIndex; int end = barIndex + loopback; datetime to = GetBarTime(forSymbol, forPeriod, barIndex); for (int i = start; i < end; i++) { // // Initialize Bar ... if (tmpBar.Init(forSymbol, forPeriod, i)) { // // Check Has Shadow ... has = tmpBar.GetHighShadow() > 0 || tmpBar.GetLowShadow() > 0; if (has) { // // Check Support or Resistance ... // // Resistance ... tmpValue = tmpBar.FindHighest(validationLength, MODE_HIGH); has = NotEmptyZero(tmpValue) && tmpValue == tmpBar.high; if (has) { // tmpZone.Clean(); upper = tmpValue; from = tmpBar.time; lower = tmpBar.GetUp(); type = ToXString(X_BAR_PATTERN_RESISTANCE); has = tmpZone.Init( forSymbol, forPeriod, upper, lower, from, to, X_DIRECTION_BEARISH, type // ); if (has) { // AddRef( tmpZone, zones // ); // tmpZone.Clean(); } } } // tmpBar.Clean(); } } // // Validate ... if (HasChild(zones) && forceValidation) { // ValidateZones( zones, barIndex, minimumRetests, retestThreshold, retestLoopback // ); } // result = ArraySize(zones); // return result; } void ValidateZones( XBoxZone &zones[], int barIndex = 0, int minimumRetests = 2, double retestThreshold = 10, int retestLoopback = 100, ENUM_X_BOUNDARY_PRICE forPriceType = X_BOUNDARY_PRICE_UP_DOWN // ) { // bool has = false; // // Validation ... has = HasChild(zones) && IsXValid(forPriceType); if (!has) { return; } // // Normalizetion ... barIndex = kiParser.NormalizeBarIndex(barIndex); minimumRetests = NormalizeInt(minimumRetests, 0); retestLoopback = NormalizeInt(retestLoopback, 50); retestThreshold = NormalizeDouble(retestThreshold, 5, 10); // XOHCL tmpBar; XBoxZone tmp; XBoxZone tmps[]; double tmpValue = 0; for (int i = 0; i < ArraySize(zones); i++) { // tmp = zones[i]; // if (minimumRetests > 0) { // int retests = CounteZoneTouches(tmp, retestThreshold, retestLoopback); if (retests < minimumRetests) { continue; } } // // Validate Zone ... has = false; for (int j = barIndex; j < tmp.FromIndex(); j++) { // // Initial Bar ... if (tmpBar.Init(tmp.symbol, tmp.period, j)) { // tmpValue = forPriceType == X_BOUNDARY_PRICE_UP_DOWN ? tmp.IsBullish() ? tmpBar.GetDown() : tmpBar.GetUp() : forPriceType == X_BOUNDARY_PRICE_HIGH_LOW ? tmp.IsBullish() ? tmpBar.low : tmpBar.high : EMPTY_VALUE; if (NotEmptyZero(tmpValue)) { // // Check Break ... has = tmp.IsBullish() ? tmpValue < tmp.lower : tmpValue > tmp.upper; // // If Breakes ... if (has) { break; } } // tmpBar.Clean(); } } // // Not Breaked ... if (!has) { // AddIfNotExists( tmp, tmps // ); } // tmp.Clean(); } // // Update Zones ... XClean(zones); Copy( tmps, zones // ); XClean(tmps); } void GetCurrentStructure( XBoxZone &supports[], XBoxZone &resistances[], XBoxZone &minorSupport, XBoxZone &majorSupport, XBoxZone &minorResistance, XBoxZone &majorResistance, int barIndex = 0, string forSymbol = NULL, ENUM_TIMEFRAMES forMinorPeriod = NULL, ENUM_TIMEFRAMES forMajorPeriod = NULL, int loopback = 50, int minorValidation = 7, int majorValidation = 14, int minimumRetests = 2, double retestThreshold = 10, int retestLoopback = 100 // ) { // bool has = false; // XClean(supports); XClean(resistances); minorSupport.Clean(); majorSupport.Clean(); minorResistance.Clean(); majorResistance.Clean(); // // Normalize ... barIndex = kiParser.NormalizeBarIndex(barIndex); if (!IsXValid(forSymbol)) { forSymbol = symbol; } if (!IsXValid(forMinorPeriod)) { forMinorPeriod = period; } if (!IsXValid(forMajorPeriod)) { forMajorPeriod = period; } // int tmpIDX = -1; int supportsCount = 0; XBoxZone tmpSupports[]; int resistancesCount = 0; XBoxZone tmpResistances[]; // // Detect Minors ... // supportsCount = DetectSupports( tmpSupports, barIndex, loopback, true, // Force Validation ... minorValidation, minimumRetests, retestThreshold, retestLoopback, forSymbol, forMinorPeriod // ); if (IsValidSize(supportsCount)) { // FillNotExists( supports, tmpSupports // ); // tmpIDX = GetYoungest(tmpSupports); if (IsValidIndex(tmpIDX)) { minorSupport = tmpSupports[tmpIDX]; } } // resistancesCount = DetectResistances( tmpResistances, barIndex, loopback, true, // Force Validation ... minorValidation, minimumRetests, retestThreshold, retestLoopback, forSymbol, forMinorPeriod // ); if (IsValidSize(resistancesCount)) { // FillNotExists( resistances, tmpResistances // ); // tmpIDX = GetYoungest(tmpResistances); if (IsValidIndex(tmpIDX)) { minorResistance = tmpResistances[tmpIDX]; } } // XClean(tmpSupports); XClean(tmpResistances); // // Detect Majors ... // supportsCount = DetectSupports( tmpSupports, barIndex, loopback, true, // Force Validation ... majorValidation, minimumRetests, retestThreshold, retestLoopback, forSymbol, forMajorPeriod // ); if (IsValidSize(supportsCount)) { // UpdateToTime(tmpSupports); // FillNotExists( supports, tmpSupports // ); // tmpIDX = GetLowest(tmpSupports); if (IsValidIndex(tmpIDX)) { majorSupport = tmpSupports[tmpIDX]; } } // resistancesCount = DetectResistances( tmpResistances, barIndex, loopback, true, // Force Validation ... majorValidation, minimumRetests, retestThreshold, retestLoopback, forSymbol, forMajorPeriod // ); if (IsValidSize(resistancesCount)) { // UpdateToTime(tmpResistances); // FillNotExists( resistances, tmpResistances // ); // tmpIDX = GetHighest(tmpResistances); if (IsValidIndex(tmpIDX)) { majorResistance = tmpResistances[tmpIDX]; } } // XClean(tmpSupports); XClean(tmpResistances); } void RefineStructure( XBoxZone &supports[], XBoxZone &resistances[], XBoxZone &minorSupport, XBoxZone &majorSupport, XBoxZone &minorResistance, XBoxZone &majorResistance, int loopback = 500, double breakThreshold = 5, ENUM_X_PRICE breakBy = X_PRICE_CLOSE // ) { // // Support ... if (HasChild(supports)) { // for (int i = 0; i < ArraySize(supports); i++) { // RefineZone( supports[i], loopback, breakThreshold, breakBy // ); } } // // Resistance ... if (HasChild(resistances)) { // for (int i = 0; i < ArraySize(resistances); i++) { // RefineZone( resistances[i], loopback, breakThreshold, breakBy // ); } } // RefineZone( minorSupport, loopback, breakThreshold, breakBy // ); // RefineZone( majorSupport, loopback, breakThreshold, breakBy // ); // RefineZone( minorResistance, loopback, breakThreshold, breakBy // ); // RefineZone( majorResistance, loopback, breakThreshold, breakBy // ); } int CounteZoneTouches( XBoxZone &zone, double threshold = 10, int loopback = 100 // ) { // int result = 0; // // Normalize ... loopback = NormalizeInt(loopback, 50); threshold = NormalizeDouble(threshold, 10); // if (!zone.IsValid()) { return result; } // XOHCL tmpBar; int start = zone.ToIndex(); bool isUpperTouched = false; bool isLowerTouched = false; double points = GetPoints(zone.symbol); double distance = points * threshold; int end = MathMin(start + loopback, zone.FromIndex()); for (int i = start; i < end; i++) { // if (tmpBar.Init(zone.symbol, zone.period, i)) { // isUpperTouched = MathAbs(tmpBar.high - zone.upper) <= distance; isLowerTouched = MathAbs(tmpBar.low - zone.lower) <= distance; // if ( (zone.IsBullish() && (isLowerTouched || MathAbs(tmpBar.close - zone.lower) <= distance)) || (zone.IsBearish() && (isUpperTouched || MathAbs(tmpBar.close - zone.upper) <= distance))) { // result++; Add( tmpBar.time, zone.tests // ); } // tmpBar.Clean(); } } // tmpBar.Clean(); // return result; } bool HasNearZone( int &index, double price, double threshold, XBoxZone &zones[] // ) { // bool result = false; // index = -1; // // Validate ... result = HasChild(zones) && NotEmptyZero(price) && NotEmptyZero(threshold) && price > 0 && threshold > 0; if (!result) { return result; } // double points = GetPoints(zones[0].symbol); double distance = points * threshold; for (int i = 0; i < ArraySize(zones); i++) { // // Check Price Distance by Upper ... result = price >= zones[i].lower - distance && price <= zones[i].upper + distance; if (result) { // index = i; break; } } // result = IsValidIndex(index); // return result; } bool IsNearZone( double price, XBoxZone &zone, double threshold = 0 // ) { // bool result = false; // result = zone.IsValid() && NotEmptyZero(price); if (!result) { return result; } // double points = GetPoints(zone.symbol); double distance = points * threshold; // result = price >= zone.lower - distance && price <= zone.upper + distance; // return result; } void RefineZone( XBoxZone &zone, int loopback = 500, double breakThreshold = 5, ENUM_X_PRICE breakBy = X_PRICE_CLOSE // ) { // bool has = zone.IsValid() && IsXValid(breakBy); if (!has) { return; } // // Normalize ... loopback = NormalizeInt(loopback, 1); breakThreshold = NormalizeDouble(breakThreshold, 0, 50); // XOHCL iBar; int start = zone.FromIndex(); int end = start + loopback; double point = GetPoints(zone.symbol); double breakDistance = point * breakThreshold; for (int i = start; i < end; i++) { // has = iBar.Init(zone.symbol, zone.period, i); if (has) { // // Check Rejections ... has = zone.IsBullish() ? iBar.low < zone.upper && iBar.GetDown() > zone.upper : iBar.high > zone.upper && iBar.GetUp() < zone.upper; if (has) { // Add( iBar.time, zone.tests // ); } // // Check Break ... double bPrice = iBar.GetPrice(breakBy); has = zone.IsBullish() ? bPrice < zone.lower - breakDistance : bPrice > zone.upper + breakDistance; if (has) { // zone.breakAt = iBar.time; break; } } // iBar.Clean(); } // has = IsXValid(zone.breakAt); if (has) { // zone.at = zone.from; zone.from = zone.breakAt; } } // #endregion // #region VolatilitySwitchedHigh ... bool IsVolatilitySwitchedHigh( int barIndex = 0, int loopback = 3 // ) { // bool result = false; // barIndex = kiParser.NormalizeBarIndex(barIndex); loopback = NormalizeInt(loopback, 1); // for (int i = barIndex; i < barIndex + loopback; i++) { // result = kiParser.IsVolatilitySwitchdToHigh(i); if (result) { break; } } // return result; } // #endregion // #region Bar Patterns ... bool HasRecentPatternTouched( XBoxZone &zone, double price, int barIndex = 0, int loopback = 5, int threshold = 5, ENUM_TIMEFRAMES forPeriod = NULL, ENUM_X_DIRECTION forDir = X_DIRECTION_NONE // ) { // bool result = false; // zone.Clean(); // // Validate ... result = NotEmptyZero(price); if (!result) { return result; } // // Normalize ... loopback = NormalizeInt(loopback, 2); barIndex = kiParser.NormalizeBarIndex(barIndex); if (IsXValid(forPeriod)) { forPeriod = period; } // XOHCL iBar; bool has = false; int iBullishIDX = -1; int iBearishIDX = -1; bool isBullish = false; bool isBearish = false; XBoxZone iBullishZones[]; XBoxZone iBearishZones[]; XPatternAnalysis iAnalysis; XPatternAnalysisConfig iConfig; // // Preparing Pattern Analysis Config ... iConfig.Default(); iConfig.FullPattern(); // // Looping Back ... for (int i = barIndex; i < barIndex + loopback; i++) { // // Initialize Bar ... has = iBar.Init(symbol, forPeriod, i); if (!has) { continue; } // // Analyse Patterns ... has = AnalyseBarPatterns(iBar, iAnalysis, iConfig); if (!has) { // iBar.Clean(); continue; } // // Bullish ... has = iAnalysis.Count(X_DIRECTION_BULLISH) > 0; if (has) { // iAnalysis.GetPatterns(iBullishZones, X_DIRECTION_BULLISH); has = HasChild(iBullishZones); if (has) { // has = HasNearZone( iBullishIDX, price, threshold, iBullishZones // ); if (has) { isBullish = true; } } } // // Bearish ... has = iAnalysis.Count(X_DIRECTION_BEARISH) > 0; if (has) { // iAnalysis.GetPatterns(iBearishZones, X_DIRECTION_BEARISH); has = HasChild(iBearishZones); if (has) { // has = HasNearZone( iBearishIDX, price, threshold, iBearishZones // ); if (has) { isBearish = true; } } } // // Summarizing Result ... has = HasDirection(forDir) ? (isBullish && !isBearish && IsXBullish(forDir)) || (isBearish && !isBullish && IsXBearish(forDir)) : (isBullish && !isBearish) || (isBearish && !isBullish); if (has) { // // Fill Zones ... if (isBullish) { zone = iBullishZones[iBullishIDX]; } else { zone = iBearishZones[iBearishIDX]; } break; } // // Cleanup Resource ... iBar.Clean(); iAnalysis.Clean(); XClean(iBullishZones); XClean(iBearishZones); } // // Cleanup Resources ... iBar.Clean(); iConfig.Clean(); iAnalysis.Clean(); XClean(iBullishZones); XClean(iBearishZones); // return result; } // #endregion // // Others ... /** * Destroy ... */ void Destroy() { // delete barAnalyser; ZeroMemory(barAnalyser); // ZeroMemory(kiHelper); ZeroMemory(kiParser); } // // Testers ... // // Protected ... protected: // // Props ... // // Private ... private: // // }; //