/////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 Class Library // -------------------------------------- // Name: XPOI // Description: Bar Analysing ... // // Maintainer: // ------------ // Hadi Khazaee Asl (hadi_khazaee_asl@yahoo.com) // ////////////////////////////////////////////////////// // // Global Properties ... #property library #property copyright "Copyright 2023, SaherElm IT Center" #property link "https://www.saherelm.ir" #property version "1.00" #property strict // // Imports ... #include "../Classes/x-saherelm.base.class.mq5" #include "../Libraries/x-saherelm.x-poi.lib.mq5" // // Definitions ... // // Implementations ... class XCBarAnalyser : public XCBase { // public: // // // Constructor(s) ... void XCBarAnalyser() { } // // Deconstructor ... void ~XCBarAnalyser() { } // // Getter(s) / Setter(s) ... // // Providers ... // // Actions ... /** * Calculate Loopback Data for Specific Bar ... * * @param index: Integer, Bar Current Index ... * @param start: Integer, Start of Loopback ... * @param end: Integer, End of Loopback ... * @param count: Integer, Number of Calculating Bars ... * @param bar: XOHCL instance, Specified Bar ... * @param loopback: Integer, Loopback Length ... * @return ( bool ) */ bool CalculateLoopBackData( int &index, int &start, int &end, int &count, XOHCL &bar, int loopback = 1 // ) { // bool result = false; // if (loopback < 1) { loopback = 1; } // index = -1; start = -1; end = -1; count = -1; // result = bar.IsValid(); if (!result) { return result; } // index = bar.Index(); start = index + 1; end = start + loopback; count = end - start; result = count >= 1; if (!result) { return result; } // return result; } /** * Retrieve Loopback HH & LL Data ... * * @param hhIDX: Integer, HH Index ... * @param hh: Double, HH Value ... * @param llIDX: Integer, LL Index ... * @param ll: Double, LL Value ... * @param bar: XOHCL instance ... * @param loopback: Integer, Loopback Length ... * * @return ( bool ) */ bool CalculateLoopbackHLData( int &hhIDX, double &hh, int &llIDX, double &ll, XOHCL &bar, int loopback // ) { // bool result = false; // if (loopback < 1) { loopback = 1; } // int index = -1; int start = -1; int end = -1; int count = -1; result = CalculateLoopBackData( index, start, end, count, bar, loopback // ); if (!result) { return result; } // hhIDX = iHighest( bar.symbol, bar.period, MODE_HIGH, count, start // ); result = IsValidIndex(hhIDX); if (!result) { return result; } // llIDX = iLowest( bar.symbol, bar.period, MODE_LOW, count, start // ); result = IsValidIndex(llIDX); if (!result) { return result; } // hh = iHigh( bar.symbol, bar.period, hhIDX // ); ll = iLow( bar.symbol, bar.period, llIDX // ); // return result; } /** * Calculate Bar Range ... * * @param bar: XOHCL instance ... * * @return ( double ) */ double GetBarRangePercent(XOHCL &bar) { // double result = 0; // result = bar.GetRange() / 100; // return result; } /** * Detect Same Bars ... * * @param bar: XOHCL instance, Start Bar ... * @param dir: ENUM_X_DIRECTION member, Holds Result Direction ... * @param index: Integer, Holds Result Index ... * @param sameBars: Iteger, Required Same Bar ... * * @return ( bool ) */ bool HasSameBars( XOHCL &bar, ENUM_X_DIRECTION &dir, int &index, int sameBars = 3 // ) { // bool result = false; // dir = X_DIRECTION_NONE; // if (sameBars < 1) { sameBars = 1; } // result = bar.IsValid(); if (!result) { return result; } // index = bar.Index(); bool canContinue = true; int sameBullishBarsFounded = 0; int sameBearishBarsFounded = 0; bool canContinueForBullish = true; bool canContinueForBearish = true; while (canContinue) { // XOHCL iBar; result = iBar.Init( bar.symbol, bar.period, index // ); if (!result) { break; } // bool isBullish = iBar.IsBullish(); bool isBearish = iBar.IsBearish(); result = isBullish || isBearish; if (!result) { break; } // if (isBullish) { // sameBullishBarsFounded++; canContinueForBearish = false; } else { // sameBearishBarsFounded++; canContinueForBullish = false; } // result = canContinueForBullish || canContinueForBearish; if (!result) { break; } // canContinueForBullish = canContinueForBullish && sameBullishBarsFounded > 0; // canContinueForBearish = canContinueForBearish && sameBearishBarsFounded > 0; // canContinue = canContinueForBullish || canContinueForBearish; if (canContinue) { index++; } } // bool hasBullishSameBars = sameBullishBarsFounded >= sameBars; // bool hasBearishSameBars = sameBearishBarsFounded >= sameBars; // result = hasBullishSameBars || hasBearishSameBars; if (!result) { return result; } // dir = hasBullishSameBars ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; // return result; } /** * Detect Price Consolidation ... * * @param bar: XOHCL instance Reference, Start Bar ... * @param loopback: Integer, Consolidation Range Finder ... * @param upper: Double Reference ... * @param lower: Double Reference ... * @param upperAppliedTo: ENUM_APPLIED_PRICE member, Upper Price ... * @param lowerAppliedTo: ENUM_APPLIED_PRICE member, Lower Price ... * * @return ( bool ) */ bool IsConsolidate( XOHCL &bar, double &upper, double &lower, int loopback = 30, ENUM_APPLIED_PRICE upperAppliedTo = PRICE_HIGH, ENUM_APPLIED_PRICE lowerAppliedTo = PRICE_LOW // ) { // bool result = false; // upper = 0; lower = 0; // if (loopback < 7) { loopback = 7; } // result = bar.IsValid(); if (!result) { return result; } // int consolidationRange = 30; double points = GetPoints(bar.symbol); int index = bar.Index(); // double upperPrice[]; int upperPriceCount = FillPrice( upperPrice, upperAppliedTo, bar.symbol, bar.period, index, loopback // ); // double lowerPrice[]; int lowerPriceCount = FillPrice( lowerPrice, lowerAppliedTo, bar.symbol, bar.period, index, loopback // ); // result = upperPriceCount == lowerPriceCount && lowerPriceCount == loopback; if (!result) { return result; } // upper = upperPrice[ArrayMaximum(upperPrice)]; lower = lowerPrice[ArrayMinimum(lowerPrice)]; // double range = upper - lower; result = range <= consolidationRange * points; // return result; } /** * Check Bar Has Bullish Trend or not ... * * @param bar: XOHCL instance ... * @param forceAll: Boolean ... * * @return ( bool ) */ bool HasBullishTrend( XOHCL &bar, bool forceAll = false // ) { // bool result = false; // result = bar.IsValid(); if (!result) { return result; } // XOHCL tmpHSW[]; XOHCL tmpLSW[]; // bool trend1 = bar.HasBullishTrend( tmpHSW, tmpLSW, true // ); // bool trend2 = bar.HasBullishTrend( tmpHSW, tmpLSW, false // ); // if (!forceAll) { // result = trend1; if (!result) { return result; } } // result = trend1 || trend2; // return result; } /** * Check Bar Has Bearish Trend or not ... * * @param bar: XOHCL instance ... * @param forceAll: Boolean ... * * @return ( bool ) */ bool HasBearishTrend( XOHCL &bar, bool forceAll = false // ) { // bool result = false; // result = bar.IsValid(); if (!result) { return result; } // XOHCL tmpHSW[]; XOHCL tmpLSW[]; // bool trend1 = bar.HasBearishTrend( tmpHSW, tmpLSW, true // ); // bool trend2 = bar.HasBearishTrend( tmpHSW, tmpLSW, false // ); // if (!forceAll) { // result = trend1; if (!result) { return result; } } // result = trend1 || trend2; // return result; } /** * Check Specified Bar Has Bullish Pattern or not ... * * @param bar: XOHCL instance, Specified Bar ... * @param loopback: Integer, Loopback Length for Patterns ... * @param verifications: Integer, Number of Given Verifications ... * @param checkHammer: Boolean, Specified Check Hammer Pattern ... * @param checkMorningStar: Boolean, Specified Check Morning Star Pattern ... * @param checkBullishMarubozu: Boolean, Specified Check Marubozu Pattern ... * @param checkBullishEngulfing: Boolean, Specified Check Engulfing Pattern ... * * @return ( bool ) */ bool HasBullishPattern( XOHCL &bar, int loopback = 0, int verifications = 1, bool checkHammer = true, bool checkMorningStar = true, bool checkBullishMarubozu = true, bool checkBullishEngulfing = true // ) { // bool result = false; // result = bar.IsValid(); if (!result) { return result; } // if (verifications <= 0) { verifications = 1; } // int founded = 0; // int idx = bar.Index(); for (int i = idx; i <= idx + loopback; i++) { // XOHCL iBar; result = iBar.Init( bar.symbol, bar.period, i // ); if (!result) { break; } // bool isHammer = !checkHammer ? false : iBar.IsHammer(); if (isHammer) { founded++; } // bool isMorningStar = !checkMorningStar ? false : iBar.IsMorningStar(); if (isMorningStar) { founded++; } // bool isBullishMarubozu = !checkBullishMarubozu ? false : iBar.IsBullishMarubozu(); if (isBullishMarubozu) { founded++; } // bool isBullishEngulfing = !checkBullishEngulfing ? false : iBar.IsBullishEngulfing(); if (isBullishEngulfing) { founded++; } // } // result = result && founded >= verifications; // return result; } /** * Check Specified Bar Has Bearish Pattern or not ... * * @param bar: XOHCL instance, Specified Bar ... * @param loopback: Integer, Loopback Length for Patterns ... * @param verifications: Integer, Number of Given Verifications ... * @param checkShootingStar: Boolean, Specified Check Shooting Star Pattern ... * @param checkEveningStar: Boolean, Specified Check Evening Star Pattern ... * @param checkBearishMarubozu: Boolean, Specified Check Marubozu Pattern ... * @param checkBearishEngulfing: Boolean, Specified Check Engulfing Pattern ... * * @return ( bool ) */ bool HasBearishPattern( XOHCL &bar, int loopback = 0, int verifications = 1, bool checkShootingStar = true, bool checkEveningStar = true, bool checkBearishMarubozu = true, bool checkBearishEngulfing = true // ) { // bool result = false; // result = bar.IsValid(); if (!result) { return result; } // if (verifications <= 0) { verifications = 1; } // int founded = 0; // int idx = bar.Index(); for (int i = idx - 1; i <= idx + loopback; i++) { // XOHCL iBar; result = iBar.Init( bar.symbol, bar.period, i // ); if (!result) { break; } // bool isShootingStar = !checkShootingStar ? false : iBar.IsShootingStar(); if (isShootingStar) { founded++; } // bool isEveningStar = !checkEveningStar ? false : iBar.IsEveningStar(); if (isEveningStar) { founded++; } // bool isBearishMarubozu = !checkBearishMarubozu ? false : iBar.IsBearishMarubozu(); if (isBearishMarubozu) { founded++; } // bool isBearishEngulfing = !checkBearishEngulfing ? false : iBar.IsBearishEngulfing(); if (isBearishEngulfing) { founded++; } // } // result = result && founded >= verifications; // return result; } // // Commons ... /** * Check Specified Bar's Range is Extended or not ... * * @param bar: XOHCL instance, Specified Bar ... * @param loopback: Integer, Loopback Length ... * * @return ( bool ) */ bool HasExtendedRange( XOHCL &bar, int loopback = 3 // ) { // bool result = false; // if (loopback < 3) { loopback = 3; } // result = bar.IsValid(); if (!result) { return result; } // int index = bar.Index(); int start = index + 1; int end = start + loopback; int count = end - start; result = count >= 1; if (!result) { return result; } // double sum = 0; XOHCL iBar = bar; for (int i = start; i < end; i++) { // bool isRetrieved = iBar.GetPreviousBar(iBar); if (!isRetrieved) { continue; } // sum += iBar.GetRange(); } // result = sum > 0; if (!result) { return result; } // double avg = sum / count; // result = bar.GetRange() >= avg; // return result; } /** * Check Specified Bar's Body is Extended or not ... * * @param bar: XOHCL instance, Specified Bar ... * @param loopback: Integer, Loopback Length ... * * @return ( bool ) */ bool HasExtendedBody( XOHCL &bar, int loopback = 3 // ) { // bool result = false; // if (loopback < 3) { loopback = 3; } // result = bar.IsValid(); if (!result) { return result; } // int index = bar.Index(); int start = index + 1; int end = start + loopback; int count = end - start; result = count >= 1; if (!result) { return result; } // double sum = 0; XOHCL iBar = bar; for (int i = start; i < end; i++) { // bool isRetrieved = iBar.GetPreviousBar(iBar); if (!isRetrieved) { continue; } // sum += iBar.GetBody(); } // result = sum > 0; if (!result) { return result; } // double avg = sum / count; // result = bar.GetBody() >= avg; // return result; } /** * Check Specified Bar's Body and Range is Extended or not ... * * @param bar: XOHCL instance, Specified Bar ... * @param loopback: Integer, Loopback Length ... * * @return ( bool ) */ bool IsExtended( XOHCL &bar, int loopback = 3 // ) { // bool result = false; // bool hasExtendedBody = HasExtendedBody(bar, loopback); bool hasExtendedRange = HasExtendedRange(bar, loopback); result = hasExtendedBody && hasExtendedRange; // return result; } /** * Check Specified Bar is Swing High or not ... * * @param bar: XOHCL instnce ... * @param range: Integer, Specified Range ... * * @return ( bool ) */ bool IsSwingHigh( XOHCL &bar, int range = 2 // ) { // bool result = false; // if (range < 1) { range = 1; } // result = bar.IsValid(); if (!result) { return result; } // int index = bar.Index(); result = range > 0 && index >= range; if (!result) { return result; } // string symbol = bar.symbol; ENUM_TIMEFRAMES period = bar.period; // for (int i = 1; i <= range; i++) { // // Prev Bar ... XOHCL iPrevBar; result = iPrevBar.Init( symbol, period, index + i // ); if (!result) { break; } // // Next Bar ... XOHCL iNextBar; result = iNextBar.Init( symbol, period, index - i // ); if (!result) { break; } // result = bar.high >= iPrevBar.high && bar.high >= iNextBar.high; if (!result) { break; } } // return result; } /** * Check Specified Bar is Swing Low or not ... * * @param bar: XOHCL instnce ... * @param range: Integer, Specified Range ... * * @return ( bool ) */ bool IsSwingLow( XOHCL &bar, int range = 2 // ) { // bool result = false; // if (range < 1) { range = 1; } // result = bar.IsValid(); if (!result) { return result; } // int index = bar.Index(); result = range > 0 && index >= range; if (!result) { return result; } // string symbol = bar.symbol; ENUM_TIMEFRAMES period = bar.period; // for (int i = 1; i <= range; i++) { // // Prev Bar ... XOHCL iPrevBar; result = iPrevBar.Init( symbol, period, index + i // ); if (!result) { break; } // // Next Bar ... XOHCL iNextBar; result = iNextBar.Init( symbol, period, index - i // ); if (!result) { break; } // result = bar.low <= iPrevBar.low && bar.low <= iNextBar.low; if (!result) { break; } } // return result; } /** * Check a Bar is Momentum Bar or not ... * * @param bar: XOHCL instance ... * @param dir: ENUM_X_DIRECTION member ... * @param extend: Integer ... * @param bodyPercent: Double ... * * @return ( bool ) */ bool IsMomentumBar( XOHCL &bar, ENUM_X_DIRECTION &dir, int extend = 1, double bodyPercent = 70 // ) { // bool result = false; // if (extend < 0) { extend = 0; } // if (bodyPercent < 50) { bodyPercent = 50; } // dir = X_DIRECTION_NONE; // result = bar.IsValid() && bar.Index() > 0; if (!result) { return result; } // if (extend > 0) { // result = IsExtended( bar, extend // ); // if (!result) { return result; } } // double body = bar.GetBody(); double rp = GetBarRangePercent(bar); // result = body >= rp * bodyPercent; // if (result) { // dir = bar.IsBullish() ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; } // return result; } /** * Check a Bar is Rejection Bar or not ... * * @param bar: XOHCL instance ... * @param dir: ENUM_X_DIRECTION member ... * @param extend: Integer ... * @param shadowPercent: Double ... * * @return ( bool ) */ bool IsRejectionBar( XOHCL &bar, ENUM_X_DIRECTION &dir, int extend = 1, double shadowPercent = 60 // ) { // bool result = false; // if (extend < 0) { extend = 0; } // if (shadowPercent < 50) { shadowPercent = 50; } // dir = X_DIRECTION_NONE; // result = bar.IsValid() && bar.Index() > 0; if (!result) { return result; } // if (extend > 0) { // result = IsExtended( bar, extend // ); // if (!result) { return result; } } // double body = bar.GetBody(); double range = bar.GetRange(); double shadows = bar.GetShadows(); double lowShadow = bar.GetLowShadow(); double highShadow = bar.GetHighShadow(); double rp = GetBarRangePercent(bar); // result = shadows >= rp * shadowPercent; // if (result) { // dir = lowShadow > highShadow ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; } // return result; } /** * Check Specified Bar is Engulfing Bar or not ... * * @param bar: XOHCL instance ... * @param dir: ENUM_X_DIRECTION member ... * @param extend: Integer ... * @param bodyPercent: Double ... * * @return ( bool ) */ bool IsEngulfBar( XOHCL &bar, ENUM_X_DIRECTION &dir, int extend = 1, double bodyPercent = 60 // ) { // bool result = false; // if (extend < 0) { extend = 0; } // if (bodyPercent < 50) { bodyPercent = 50; } // dir = X_DIRECTION_NONE; // result = bar.IsValid() && bar.Index() > 0; if (!result) { return result; } // // Previous Bar ... XOHCL pBar; result = bar.GetPreviousBar(pBar); if (!result) { return result; } // if (extend > 0) { // result = IsExtended( pBar, extend // ); // if (!result) { return result; } } // // Check Engulfig ... result = bar.GetUp() > pBar.GetUp() && bar.GetDown() < pBar.GetDown(); if (!result) { return result; } // // Check Engulfing Direction ... bool isBullishEngulfed = pBar.IsBearish() && bar.IsBullish(); bool isBearishEngulfed = pBar.IsBullish() && bar.IsBearish(); // result = isBullishEngulfed || isBearishEngulfed; if (!result) { return result; } // dir = isBullishEngulfed ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; // return result; } /** * Check Specified Bar is Pin Bar or not ... * * @param bar: XOHCL instance ... * @param dir: ENUM_X_DIRECTION member ... * @param extend: Integer ... * @param shadowPercent: Double ... * @param bodyPercent: Double ... * * @return ( bool ) */ bool IsPinBar( XOHCL &bar, ENUM_X_DIRECTION &dir, int extend = 1, double shadowPercent = 65, double bodyPercent = 25 // ) { // bool result = false; // dir = X_DIRECTION_NONE; // result = bar.IsValid() && bar.Index() > 0 && bodyPercent > 0 && shadowPercent > 0 && bodyPercent < shadowPercent; if (!result) { return result; } // // Chack Range Extends ... if (extend > 0) { // result = HasExtendedRange( bar, extend // ); if (!result) { return result; } } // // Check Body ... double rangePercent = GetBarRangePercent(bar); // double body = bar.GetBody(); double highShadow = bar.GetHighShadow(); double lowShadow = bar.GetLowShadow(); // // Check Body ... result = body / rangePercent >= bodyPercent; if (!result) { return result; } // bool isPassedHighShadow = highShadow / rangePercent >= shadowPercent; bool isPassedLowShadow = lowShadow / rangePercent >= shadowPercent; result = isPassedLowShadow || isPassedHighShadow; if (!result) { return result; } // dir = isPassedLowShadow ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; // return result; } /** * Decision Bar (Pin, Momentum or Rejection) ... * * @param bar: XOHCL instance ... * @param dir: ENUM_X_DIRECTION member ... * @param extend: Integer ... * @param shadowForPinAndRejectionBarPercent: Double ... * @param bodyForPinBarPercent: Double ... * @param bodyForEngulfBarPercent: Double ... * @param bodyForMomentumBarPercent: Double ... * * @return ( bool ) */ bool IsDecisionBar( XOHCL &bar, ENUM_X_DIRECTION &dir, int extend = 1, double shadowForPinAndRejectionBarPercent = 65, double bodyForPinBarPercent = 25, double bodyForEngulfBarPercent = 65, double bodyForMomentumBarPercent = 70 // ) { // bool result = false; // dir = X_DIRECTION_NONE; // result = bar.IsValid() && bar.Index() > 0; if (!result) { return result; } // // Pin Bar ... ENUM_X_DIRECTION pinDir; bool isPiBar = IsPinBar( bar, pinDir, extend, shadowForPinAndRejectionBarPercent, bodyForPinBarPercent // ); // // Engulfing Bar ... ENUM_X_DIRECTION engulfDir; bool isEngulfBar = IsEngulfBar( bar, engulfDir, extend, bodyForEngulfBarPercent // ); // // Momentum Bar ... ENUM_X_DIRECTION momentumDir; bool isMomentumBar = IsMomentumBar( bar, momentumDir, extend, bodyForMomentumBarPercent // ); // // Rejection Bar ... ENUM_X_DIRECTION rejectionDir; bool isRejectionBar = IsRejectionBar( bar, rejectionDir, extend, shadowForPinAndRejectionBarPercent // ); // result = isPiBar || isEngulfBar || isMomentumBar || isRejectionBar; if (result) { // if (isPiBar) { dir = pinDir; } else if (isEngulfBar) { dir = engulfDir; } else if (isMomentumBar) { dir = momentumDir; } else { dir = rejectionDir; } } // result = IsBullish(dir) || IsBearish(dir); // return result; } // // Support and Resistance Zones ... /** * Check a Bar is Support Bar or not ... * * @param bar: XOHCL instance ... * @param range: Integer, Specified Verifiation Range ... * * @return ( bool ) */ bool IsSupport( XOHCL &bar, int range = 21 // ) { // bool result = false; // if (range < 2) { range = 2; } // result = bar.IsValid(); if (!result) { return result; } // int index = bar.Index(); result = range > 0 && index >= range; if (!result) { return result; } // string symbol = bar.symbol; ENUM_TIMEFRAMES period = bar.period; // for (int i = 1; i <= range; i++) { // int prevIDX = index + i; int nextIDX = index - 1; // // Prev Bar ... XOHCL iPrevBar; result = iPrevBar.Init( symbol, period, prevIDX // ); if (!result) { break; } // // Next Bar ... XOHCL iNextBar; result = iNextBar.Init( symbol, period, nextIDX // ); if (!result) { break; } // result = bar.low <= iPrevBar.low && bar.low <= iNextBar.low; if (!result) { break; } } // return result; } /** * Check a Bar is Resistance Bar or not ... * * @param bar: XOHCL instance ... * @param range: Integer, Specified Verifiation Range ... * * @return ( bool ) */ bool IsResistance( XOHCL &bar, int range = 21 // ) { // bool result = false; // if (range < 2) { range = 2; } // result = bar.IsValid(); if (!result) { return result; } // int index = bar.Index(); result = range > 0 && index >= range; if (!result) { return result; } // string symbol = bar.symbol; ENUM_TIMEFRAMES period = bar.period; // for (int i = 1; i <= range; i++) { // int prevIDX = index + i; int nextIDX = index - 1; // // Prev Bar ... XOHCL iPrevBar; result = iPrevBar.Init( symbol, period, prevIDX // ); if (!result) { break; } // // Next Bar ... XOHCL iNextBar; result = iNextBar.Init( symbol, period, nextIDX // ); if (!result) { break; } // result = bar.high >= iPrevBar.high && bar.high >= iNextBar.high; if (!result) { break; } } // return result; } // // Order Blocks ... /** * Detect an Order Block Based on Given Bar ... * * @param bar: XOHCL instance, Specified Start Bar ... * @param ob: XOHCL instance, Fill it if Order Block Found ... * @param dir: ENUM_X_DIRECTION member, Specified Founded Order Block Direction ... * @param sameBars: Integer, Specified Min Same Bars for Detecting Order Block ... * * @return ( bool ) */ bool HasOrderBlock( XOHCL &bar, XOHCL &ob, ENUM_X_DIRECTION &dir, int sameBars = 3 // ) { // bool result = false; // ob.Clean(); dir = X_DIRECTION_NONE; // if (sameBars < 1) { sameBars = 1; } // result = bar.IsValid(); if (!result) { return result; } // int index = 0; result = HasSameBars( bar, dir, index, sameBars // ); if (!result) { return result; } // int obIndex = index; result = ob.Init( bar.symbol, bar.period, obIndex // ); if (!result) { return result; } // return result; } // // Fair Value Gaps ... /** * Detect a Fair Value Gap Based on Given Bar ... * * @param bar: XOHCL instance, Specified Start Bar ... * @param dir: ENUM_X_DIRECTION member, Specified Founded Order Block Direction ... * @param sameBars: Integer, Specified Min Same Bars for Detecting Order Block ... * * @return ( bool ) */ bool HasFairValueGap( XOHCL &bar, XOHCL &prevBar, XOHCL &nextBar, ENUM_X_DIRECTION &dir, int sameBars = 3 // ) { // bool result = false; // prevBar.Clean(); nextBar.Clean(); dir = X_DIRECTION_NONE; // if (sameBars < 1) { sameBars = 1; } // result = bar.IsValid(); if (!result) { return result; } // int index = 0; result = HasSameBars( bar, dir, index, sameBars // ); if (!result) { return result; } // bool isBullish = IsBullish(dir); // int to = bar.Index() + 1; int from = index + 1; for (int i = from; i > to; i--) { // result = prevBar.Init( bar.symbol, bar.period, i // ); if (!result) { break; } // result = nextBar.Init( bar.symbol, bar.period, i - 2 // ); if (!result) { break; } // result = isBullish ? prevBar.high < nextBar.low : prevBar.low > nextBar.high; if (result) { break; } } // if (!result) { // prevBar.Clean(); nextBar.Clean(); dir = X_DIRECTION_NONE; } // return result; } // // Bar CHOCH ... /** * Check Specified Bar Has PullBack or not ... * * @param dir: ENUM_X_DIRECTION member, Specified Direction ... * @param bar: XOHCL instance, Speciied Bar ... * @param loopback: Integer, loopback Length ... * @param forceBody: Boolean, Specified Choch Happens only by Bar's Body ... * * @return ( bool ) */ bool HasPullBack( ENUM_X_DIRECTION &dir, XOHCL &bar, int loopback = 3, bool forceBody = false // ) { // bool result = false; // dir = X_DIRECTION_NONE; // if (loopback < 1) { loopback = 1; } // result = bar.IsValid(); if (!result) { return result; } // string symbol = bar.symbol; ENUM_TIMEFRAMES period = bar.period; // // Calculate Loopback Data ... int index = -1; int start = -1; int end = -1; int count = -1; result = CalculateLoopBackData( index, start, end, count, bar, loopback // ); if (!result) { return result; } // // Calculate Loopback HH and LL Data ... int hhIDX = -1; double hh = -1; int llIDX = -1; double ll = -1; result = CalculateLoopbackHLData( hhIDX, hh, llIDX, ll, bar, loopback // ); if (!result) { return result; } // bool isBullishDirection = bar.high > hh && bar.low > ll; bool isBearishDirection = bar.high < hh && bar.low < ll; result = isBullishDirection || isBearishDirection; if (!result) { return result; } // if (forceBody) { // isBullishDirection = bar.GetUp() > hh && bar.GetDown() > ll; isBearishDirection = bar.GetUp() < hh && bar.GetDown() < ll; result = isBullishDirection || isBearishDirection; if (!result) { return result; } } // // Check Bar's Direction in related to CHOCH Direction ... result = isBullishDirection ? bar.IsBullish() : bar.IsBearish(); if (!result) { return result; } // // Set Direction ... dir = isBullishDirection ? X_DIRECTION_BULLISH : X_DIRECTION_BEARISH; // // Check Loopback End Bar ... XOHCL endBar; result = endBar.Init( symbol, period, end - 1 // ); if (!result) { return result; } // // End Bar Must be InDirect by Specified Bar ... result = isBullishDirection ? endBar.IsBearish() : endBar.IsBullish(); // // Check Loopback for Directional Bars ... // return result; } // protected: // // private: // // // Props ... // // Actions ... // }; //