diff --git a/Classes/x-saherelm.x-bar.analyser.class.mq5 b/Classes/x-saherelm.x-bar.analyser.class.mq5 index 2b4b613f..8ef12212 100644 --- a/Classes/x-saherelm.x-bar.analyser.class.mq5 +++ b/Classes/x-saherelm.x-bar.analyser.class.mq5 @@ -26,6 +26,9 @@ // // Definitions ... +// +#define X_PERCENTAGE_GOLDEN_MULTIPLIER 100000 + // // Implementations ... class XCBarAnalyser : public XCBase @@ -52,9 +55,6 @@ class XCBarAnalyser : public XCBase // // Providers ... - // - // Actions ... - /** * Calculate Loopback Data for Specific Bar ... * @@ -66,7 +66,7 @@ class XCBarAnalyser : public XCBase * @param loopback: Integer, Loopback Length ... * @return ( bool ) */ - bool CalculateLoopBackData( + bool CalculateLoopbackData( int &index, int &start, int &end, @@ -147,7 +147,7 @@ class XCBarAnalyser : public XCBase int start = -1; int end = -1; int count = -1; - result = CalculateLoopBackData( + result = CalculateLoopbackData( index, start, end, @@ -205,19 +205,304 @@ class XCBarAnalyser : public XCBase } /** - * Calculate Bar Range ... + * Fill Prices ... * - * @param bar: XOHCL instance ... + * @param prices: double collection + * @param bar: XOHCL instance reference, Provides Start ... + * @param loopback: int, Specified How Many Bars Process ... + * @param type: ENUM_X_PRICE member, Specified Price Type ... + * + * @return ( bool ) + */ + bool FillPrice( + double &prices[], + XOHCL &bar, + int loopback = 14, + ENUM_X_PRICE type = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + Clean(prices); + + // + loopback = NormalizeInt(loopback, 1); + + // + result = IsValid(type) && + 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; + } + + // + for (int i = index; i < count; i++) + { + // + XOHCL iBar; + bool isInited = iBar.Init( + symbol, + period, + i // + ); + if (!isInited) + { + // + iBar.Clean(); + continue; + } + + // + double iPrice = iBar.GetPrice(type); + + // + isInited = NotEmptyZero(iPrice); + if (isInited) + { + // + Add( + iPrice, + prices // + ); + } + + // + iBar.Clean(); + } + + // + result = ArraySize(prices) == count; + if (!result) + { + Clean(prices); + } + + // + ArrayReverse(prices); + + // + return result; + } + + /** + * Calculate Price Range ... + * + * @param ranges: double Collection, Calculated Ranges ... + * @param bar: XOHCL instance Reference, Start Bar ... + * @param forceBody: bool, Force to Calculate Range using Body ... + * @param loopback: int, loopback period for Range Calculated ... + * + * @return ( int ) + */ + int GetPriceRange( + double &ranges[], + XOHCL &bar, + bool forceBody = false, + int loopback = 14 // + ) + { + // + int result = 0; + + // + Clean(ranges); + + // + loopback = NormalizeInt(loopback, 1); + + // + if (!bar.IsValid()) + { + return result; + } + + // + bool has = false; + + // + // Select Uppers Prices ... + double uppers[]; + int uppersCount = 0; + if (forceBody) + { + // + has = FillPrice( + uppers, + bar, + loopback, + X_PRICE_UP // + ); + } + else + { + // + has = FillPrice( + uppers, + bar, + loopback, + X_PRICE_HIGH // + ); + } + if (has) + { + uppersCount = ArraySize(uppers); + } + + // + // Select Lower Prices ... + double lowers[]; + int lowersCount = 0; + if (forceBody) + { + // + has = FillPrice( + lowers, + bar, + loopback, + X_PRICE_DOWN // + ); + } + else + { + // + has = FillPrice( + lowers, + bar, + loopback, + X_PRICE_LOW // + ); + } + if (has) + { + lowersCount = ArraySize(lowers); + } + + // + // Validate Filled Prices ... + has = + IsValidSize(uppersCount) && + IsValidSize(lowersCount) && + uppersCount == lowersCount; + if (!has) + { + // + Clean(uppers); + Clean(lowers); + + // + return result; + } + + // + for (int i = 0; i < uppersCount; i++) + { + // + double iValue = uppers[i] - lowers[i]; + + // + Add( + iValue, + ranges // + ); + } + + // + result = ArraySize(ranges); + ArrayReverse(ranges); + + // + // Cleanup Resources ... + + // + Clean(uppers); + Clean(lowers); + + // + return result; + } + + /** + * Calculate Price Change Percent ... + * + * @param bar: XOHCL instance Reference, Start Bar ... + * @param type: ENUM_X_PRICE member, Specified Price Type ... + * @param loopback: int, loopback period for Range Calculated ... * * @return ( double ) */ - double GetBarRangePercent(XOHCL &bar) + double GetPriceChangeRate( + XOHCL &bar, + ENUM_X_PRICE type = X_PRICE_CLOSE, + int loopback = 14 // + ) { // double result = 0; // - result = bar.GetRange() / 100; + bool has = false; + + // + loopback = NormalizeInt(loopback, 1); + + // + has = + IsValid(type) && + bar.IsValid(); + if (!has) + { + return result; + } + + // + XOHCL oldBar; + has = oldBar.Init( + bar.symbol, + bar.period, + bar.Index() + loopback // + ); + if (!has) + { + // + oldBar.Clean(); + + // + return result; + } + double newPrice = bar.GetPrice(type); + double oldPrice = oldBar.GetPrice(type); + + // + result = ((newPrice - oldPrice) / oldPrice) / 100; + + // + oldBar.Clean(); // return result; @@ -369,1489 +654,6 @@ class XCBarAnalyser : public XCBase return result; } - /** - * Detect Price Consolidation ... - * - * @param bar: XOHCL instance Reference, Start Bar ... - * @param loopback: Integer, Consolidation Length Finder ... - * @param consolidationRange: 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, - int consolidationRange = 50, - 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; - } - - // - 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; - } - - bool HasConsolidationZone( - XOHCL &bar, - XConsolidationZone &zone, - int minLoopback = 3, - double range = 50, - ENUM_APPLIED_PRICE upperAppliedTo = PRICE_HIGH, - ENUM_APPLIED_PRICE lowerAppliedTo = PRICE_LOW // - ) - { - // - bool result = false; - - // - zone.Clean(); - - // - result = bar.IsValid() && - minLoopback > 0 && - range > 0; - if (!result) - { - return result; - } - - // - double points = GetPoints(bar.symbol); - int index = bar.Index() + 1; - int length = minLoopback; - - // - double upperPrice[]; - int upperPriceCount = FillPrice( - upperPrice, - upperAppliedTo, - bar.symbol, - bar.period, - index, - length // - ); - - // - double lowerPrice[]; - int lowerPriceCount = FillPrice( - lowerPrice, - lowerAppliedTo, - bar.symbol, - bar.period, - index, - length // - ); - - // - result = upperPriceCount == lowerPriceCount && - lowerPriceCount == length; - if (!result) - { - // - Clean(upperPrice); - Clean(lowerPrice); - - // - return result; - } - - // - double upper = upperPrice[ArrayMaximum(upperPrice)]; - double lower = lowerPrice[ArrayMinimum(lowerPrice)]; - - // - bool isBullishBreake = - bar.low > lower && - bar.high > upper && - bar.GetUp() > upper; - bool isBearishBreake = - bar.high < upper && - bar.low < lower && - bar.GetDown() < lower; - result = isBullishBreake || - isBearishBreake; - if (!result) - { - // - Clean(upperPrice); - Clean(lowerPrice); - - // - return result; - } - - // - double delta = upper - lower; - result = delta <= range * points; - if (!result) - { - // - Clean(upperPrice); - Clean(lowerPrice); - - // - return result; - } - - // - while (delta <= range * points) - { - // - length++; - - // - upperPriceCount = FillPrice( - upperPrice, - upperAppliedTo, - bar.symbol, - bar.period, - index, - length // - ); - - // - lowerPriceCount = FillPrice( - lowerPrice, - lowerAppliedTo, - bar.symbol, - bar.period, - index, - length // - ); - - // - bool isValid = upperPriceCount == lowerPriceCount && - lowerPriceCount == length; - if (!isValid) - { - break; - } - - // - double iUpper = upperPrice[ArrayMaximum(upperPrice)]; - double iLower = lowerPrice[ArrayMinimum(lowerPrice)]; - - // - delta = iUpper - iLower; - if (delta <= range * points) - { - // - upper = iUpper; - lower = iLower; - } - } - - // - Clean(upperPrice); - Clean(lowerPrice); - - // - // Filling Zone ... - zone.upper = upper; - zone.lower = lower; - zone.symbol = bar.symbol; - zone.period = bar.period; - zone.to = iTime( - bar.symbol, - bar.period, - bar.Index() + 1 // - ); - zone.from = iTime( - bar.symbol, - bar.period, - bar.Index() + length // - ); - zone.dir = isBullishBreake - ? X_DIRECTION_BULLISH - : X_DIRECTION_BEARISH; - - // - result = zone.IsValid(); - if (!result) - { - zone.Clean(); - } - - // - 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 = HasBullishTrend( - bar, - tmpHSW, - tmpLSW, - true // - ); - - // - bool trend2 = HasBullishTrend( - bar, - 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 = HasBearishTrend( - bar, - tmpHSW, - tmpLSW, - true // - ); - - // - bool trend2 = HasBearishTrend( - bar, - 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 - : IsHammer(iBar); - if (isHammer) - { - founded++; - } - - // - bool isMorningStar = - !checkMorningStar - ? false - : IsMorningStar(iBar); - if (isMorningStar) - { - founded++; - } - - // - bool isBullishMarubozu = - !checkBullishMarubozu - ? false - : IsBullishMarubozu(iBar); - if (isBullishMarubozu) - { - founded++; - } - - // - bool isBullishEngulfing = - !checkBullishEngulfing - ? false - : IsBullishEngulfing(iBar); - 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 - : IsShootingStar(iBar); - if (isShootingStar) - { - founded++; - } - - // - bool isEveningStar = - !checkEveningStar - ? false - : IsEveningStar(iBar); - if (isEveningStar) - { - founded++; - } - - // - bool isBearishMarubozu = - !checkBearishMarubozu - ? false - : IsBearishMarubozu(iBar); - if (isBearishMarubozu) - { - founded++; - } - - // - bool isBearishEngulfing = - !checkBearishEngulfing - ? false - : IsBearishEngulfing(iBar); - 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 Specified Bar is Swing or not ... - * - * @param bar: XOHCL instnce ... - * @param dir: ENUM_X_DIRECTION member ... - * @param range: Integer, Specified Range ... - * - * @return ( bool ) - */ - bool IsSwing( - XOHCL &bar, - ENUM_X_DIRECTION &dir, - int range = 2 // - ) - { - // - bool result = false; - - // - dir = X_DIRECTION_NONE; - - // - bool isSwingLow = IsSwingLow(bar, range); - bool isSwingHigh = IsSwingHigh(bar, range); - - // - result = isSwingLow || - isSwingHigh; - if (result) - { - // - if (isSwingLow) - { - dir = X_DIRECTION_BULLISH; - } - else - { - dir = X_DIRECTION_BEARISH; - } - } - - // - 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); - result = rangePercent > 0; - if (!result) - { - return result; - } - - // - 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; - } - /** * Check Fibonacci Level 382 Pressure ... * @@ -1906,384 +708,36 @@ class XCBarAnalyser : public XCBase } // - // Support and Resistance Zones ... + // Actions ... - /** - * Check a Bar is Support Bar or not ... - * - * @param bar: XOHCL instance ... - * @param range: Integer, Specified Verifiation Range ... - * - * @return ( bool ) - */ - bool IsSupport( + bool IsSpike( 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 Has Support or not ... - * - * @param bar: XOHCL instance ... - * @param supportBar: XOHCL instance Specified Support Bar ... - * @param rage: int, - * @return ( bool ) - */ - bool HasSupport( - XOHCL &bar, - XOHCL &supportBar, - int range = 21 // - ) - { - // - bool result = false; - - // - result = bar.IsValid(); - if (!result) - { - return result; - } - - // - int barIndex = bar.Index() + range; - result = IsValidIndex(barIndex); - if (!result) - { - // - supportBar.Clean(); - return result; - } - result = supportBar.Init( - bar.symbol, - bar.period, - barIndex // - ); - - // - result = supportBar.low < supportBar.GetDown(); - if (!result) - { - // - supportBar.Clean(); - return result; - } - - // - double selectedValue = supportBar.GetDown(); - - // - int llIDX = bar.FindLowestIndex(range - 1, MODE_LOW); - result = IsValidIndex(llIDX); - if (!result) - { - // - supportBar.Clean(); - return result; - } - - // - double llValue = iLow( - bar.symbol, - bar.period, - llIDX // - ); - - // - result = llValue >= selectedValue; - if (!result) - { - // - supportBar.Clean(); - return result; - } - - // - result = supportBar.IsValid(); - - // - 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; - } - - /** - * Check a Bar Has Resistance or not ... - * - * @param bar: XOHCL instance ... - * @param resistanceBar: XOHCL instance Specified Resistance Bar ... - * @param rage: int, - * @return ( bool ) - */ - bool HasResistance( - XOHCL &bar, - XOHCL &resistanceBar, - int range = 21 // - ) - { - // - bool result = false; - - // - result = bar.IsValid(); - if (!result) - { - return result; - } - - // - int barIndex = bar.Index() + range; - result = IsValidIndex(barIndex); - if (!result) - { - // - resistanceBar.Clean(); - return result; - } - result = resistanceBar.Init( - bar.symbol, - bar.period, - barIndex // - ); - - // - result = resistanceBar.low < resistanceBar.GetDown(); - if (!result) - { - // - resistanceBar.Clean(); - return result; - } - - // - double selectedValue = resistanceBar.GetUp(); - - // - int hhIDX = bar.FindHighestIndex(range - 1, MODE_HIGH); - result = IsValidIndex(hhIDX); - if (!result) - { - // - resistanceBar.Clean(); - return result; - } - - // - double hhValue = iHigh( - bar.symbol, - bar.period, - hhIDX // - ); - - // - result = hhValue >= selectedValue; - if (!result) - { - // - resistanceBar.Clean(); - return result; - } - - // - result = resistanceBar.IsValid(); - - // - 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, + XOHCL &fromBar, + XOHCL &toBar, ENUM_X_DIRECTION &dir, - int sameBars = 3 // + double minPriceChangePercent = 1.5, + ENUM_X_PRICE type = X_PRICE_CLOSE, + bool forcBodyInRange = true, + double rangeExtendMultiplier = 2, + int loopback = 14 // ) { // bool result = false; // - ob.Clean(); + toBar.Clean(); + fromBar.Clean(); dir = X_DIRECTION_NONE; + loopback = NormalizeInt(loopback, 1); + rangeExtendMultiplier = NormalizeDouble(rangeExtendMultiplier, 1); + minPriceChangePercent = NormalizeDouble(minPriceChangePercent, 1.5); // - if (sameBars < 1) - { - sameBars = 1; - } + int periodSeconds = PeriodSeconds(bar.period); + double divider = X_PERCENTAGE_GOLDEN_MULTIPLIER; + double periodMult = (periodSeconds / PeriodSeconds(PERIOD_M5)) * 0.2; + minPriceChangePercent /= (divider / periodMult); // result = bar.IsValid(); @@ -2293,3731 +747,77 @@ class XCBarAnalyser : public XCBase } // - int index = 0; - result = HasSameBars( - bar, - dir, - index, - sameBars // - ); - if (!result) - { - return result; - } - - // - int obIndex = index + 1; - 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(); - int from = - index > (to + sameBars) - ? to + sameBars - : index; - 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, + double ranges[]; + int rangesCount = GetPriceRange( + ranges, bar, + forcBodyInRange, loopback // ); + result = IsValidSize(rangesCount); if (!result) { + // + Clean(ranges); + + // 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, + double rangeMax = GetMax(ranges); + double rangeMin = GetMin(ranges); + double rangeAverage = GetAverage(ranges); + double priceChangePercent = GetPriceChangeRate( bar, + type, loopback // ); - if (!result) + + // + static double maxPriceChange = 0; + static double minPriceChange = 0; + if (maxPriceChange == 0 || maxPriceChange < priceChangePercent) { - return result; + maxPriceChange = priceChangePercent; + } + if (minPriceChange == 0 || minPriceChange > priceChangePercent) + { + minPriceChange = priceChangePercent; } // - 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) - { + bool isBullish = // - 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; - } - - // - // Tools ... - - // - bool IsStrong( - XOHCL &bar, - double percent = 50 // Percent of Body - ) - { - // - bool result = false; - - // - result = bar.IsValid() && - bar.Index() > 0; - if (!result) - { - return result; - } - - // - result = - (bar.GetRange() * percent) / 100 <= bar.GetBody(); - - // - return result; - } - - // - bool HasStrongLowShadow( - XOHCL &bar, - double percent = 50, // Percent of Body - int __loopback = 2, - double _sharpRatio = 2.5 // - ) - { - // - bool result = false; - - // - result = bar.IsValid() && - bar.Index() > 0; - if (!result) - { - return result; - } - - // - result = - (bar.GetRange() * percent) / 100 <= bar.GetLowShadow(); - if (!result) - { - return result; - } - - // - if (__loopback < 0) - { - __loopback = 2; - } - - // - if (_sharpRatio < 0) - { - _sharpRatio = 2.5; - } - - // - result = bar.Index() > __loopback; - if (!result) - { - return result; - } - - // - // Get Highest High and Lowest Low in loopback Range ... - int startIndex = bar.Index() - __loopback; - int endIndex = bar.Index() + __loopback; - int requiredBars = MathAbs(endIndex - startIndex); - - // - // Highs ... - double highs[]; - int copiedHighs = CopyHigh( - bar.symbol, - bar.period, - startIndex, - requiredBars, - highs // - ); - - // - result = copiedHighs == requiredBars; - if (!result) - { - return result; - } - - // - int highestHighIDX = ArrayMaximum(highs); - result = IsValidIndex(highestHighIDX); - if (!result) - { - return result; - } - - // - double highestHigh = highs[highestHighIDX]; - - // - // Lows ... - double lows[]; - int copiedLows = CopyLow( - bar.symbol, - bar.period, - startIndex, - requiredBars, - lows // - ); - - // - result = copiedLows == requiredBars; - if (!result) - { - return result; - } - - // - int lowestLowIDX = ArrayMinimum(lows); - result = IsValidIndex(lowestLowIDX); - if (!result) - { - return result; - } - - // - double lowestLow = lows[lowestLowIDX]; - - // - result = bar.low == lowestLow && - highestHigh > bar.high; - if (!result) - { - return result; - } - - // - // Try to Validate Sharp Ratio ... - - // - Clean(highs); - Clean(lows); - - // - // Left Side ... - startIndex = bar.Index() + 1; - endIndex = startIndex + (__loopback / 2) - 1; - requiredBars = MathAbs(endIndex - startIndex); - - // - copiedHighs = CopyHigh( - bar.symbol, - bar.period, - startIndex, - requiredBars, - highs // - ); - result = copiedHighs == requiredBars; - if (!result) - { - return result; - } - - // - highestHighIDX = ArrayMaximum(highs); - result = IsValidIndex(highestHighIDX); - if (!result) - { - return result; - } - - // - highestHigh = highs[highestHighIDX]; - - // - copiedLows = CopyLow( - bar.symbol, - bar.period, - startIndex, - requiredBars, - lows // - ); - result = copiedLows == requiredBars; - if (!result) - { - return result; - } - - // - lowestLowIDX = ArrayMinimum(lows); - result = IsValidIndex(lowestLowIDX); - if (!result) - { - return result; - } - - // - lowestLow = lows[lowestLowIDX]; - - // - double leftDiff = highestHigh - lowestLow; - - // - Clean(highs); - Clean(lows); - - // - // Right Side ... - startIndex = bar.Index() - 1; - endIndex = startIndex - (__loopback / 2) + 1; - requiredBars = MathAbs(endIndex - startIndex); - - // - copiedHighs = CopyHigh( - bar.symbol, - bar.period, - startIndex, - requiredBars, - highs // - ); - result = copiedHighs == requiredBars; - if (!result) - { - return result; - } - - // - highestHighIDX = ArrayMaximum(highs); - result = IsValidIndex(highestHighIDX); - if (!result) - { - return result; - } - - // - highestHigh = highs[highestHighIDX]; - - // - copiedLows = CopyLow( - bar.symbol, - bar.period, - startIndex, - requiredBars, - lows // - ); - result = copiedLows == requiredBars; - if (!result) - { - return result; - } - - // - lowestLowIDX = ArrayMinimum(lows); - result = IsValidIndex(lowestLowIDX); - if (!result) - { - return result; - } - - // - lowestLow = lows[lowestLowIDX]; - - // - double rightDiff = highestHigh - lowestLow; - double diff = MathMax(leftDiff, rightDiff); - result = bar.GetLowShadow() >= (diff / 100) * _sharpRatio; - - // - return result; - } - - // - bool HasStrongHighShadow( - XOHCL &bar, - double percent = 50, // Percent of Body - int __loopback = 2, - double _sharpRatio = 2.5 // - ) - { - // - bool result = false; - - // - result = bar.IsValid() && bar.Index() > 0; - if (!result) - { - return result; - } - - // - result = - (bar.GetRange() * percent) / 100 <= bar.GetHighShadow(); - if (!result) - { - return result; - } - - // - if (__loopback < 0) - { - __loopback = 2; - } - - // - if (_sharpRatio < 0) - { - _sharpRatio = 2.5; - } - - // - result = bar.Index() > __loopback; - if (!result) - { - return result; - } - - // - // Get Highest High and Lowest Low in loopback Range ... - int startIndex = bar.Index() - __loopback; - int endIndex = bar.Index() + __loopback; - int requiredBars = MathAbs(endIndex - startIndex); - - // - // Highs ... - double highs[]; - int copiedHighs = CopyHigh( - bar.symbol, - bar.period, - startIndex, - requiredBars, - highs // - ); - - // - result = copiedHighs == requiredBars; - if (!result) - { - return result; - } - - // - int highestHighIDX = ArrayMaximum(highs); - result = IsValidIndex(highestHighIDX); - if (!result) - { - return result; - } - - // - double highestHigh = highs[highestHighIDX]; - - // - // Lows ... - double lows[]; - int copiedLows = CopyLow( - bar.symbol, - bar.period, - startIndex, - requiredBars, - lows // - ); - - // - result = copiedLows == requiredBars; - if (!result) - { - return result; - } - - // - int lowestLowIDX = ArrayMinimum(lows); - result = IsValidIndex(lowestLowIDX); - if (!result) - { - return result; - } - - // - double lowestLow = lows[lowestLowIDX]; - - // - result = bar.high == highestHigh && - lowestLow < bar.low; - if (!result) - { - return result; - } - - // - // Try to Validate Sharp Ratio ... - - // - Clean(highs); - Clean(lows); - - // - // Left Side ... - startIndex = bar.Index() + 1; - endIndex = startIndex + (__loopback / 2) - 1; - requiredBars = MathAbs(endIndex - startIndex); - - // - copiedHighs = CopyHigh( - bar.symbol, - bar.period, - startIndex, - requiredBars, - highs // - ); - result = copiedHighs == requiredBars; - if (!result) - { - return result; - } - - // - highestHighIDX = ArrayMaximum(highs); - result = IsValidIndex(highestHighIDX); - if (!result) - { - return result; - } - - // - highestHigh = highs[highestHighIDX]; - - // - copiedLows = CopyLow( - bar.symbol, - bar.period, - startIndex, - requiredBars, - lows // - ); - result = copiedLows == requiredBars; - if (!result) - { - return result; - } - - // - lowestLowIDX = ArrayMinimum(lows); - result = IsValidIndex(lowestLowIDX); - if (!result) - { - return result; - } - - // - lowestLow = lows[lowestLowIDX]; - - // - double leftDiff = highestHigh - lowestLow; - - // - Clean(highs); - Clean(lows); - - // - // Right Side ... - startIndex = bar.Index() - 1; - endIndex = startIndex - (__loopback / 2) + 1; - requiredBars = MathAbs(endIndex - startIndex); - - // - copiedHighs = CopyHigh( - bar.symbol, - bar.period, - startIndex, - requiredBars, - highs // - ); - result = copiedHighs == requiredBars; - if (!result) - { - return result; - } - - // - highestHighIDX = ArrayMaximum(highs); - result = IsValidIndex(highestHighIDX); - if (!result) - { - return result; - } - - // - highestHigh = highs[highestHighIDX]; - - // - copiedLows = CopyLow( - bar.symbol, - bar.period, - startIndex, - requiredBars, - lows // - ); - result = copiedLows == requiredBars; - if (!result) - { - return result; - } - - // - lowestLowIDX = ArrayMinimum(lows); - result = IsValidIndex(lowestLowIDX); - if (!result) - { - return result; - } - - // - lowestLow = lows[lowestLowIDX]; - - // - double rightDiff = highestHigh - lowestLow; - double diff = MathMax(leftDiff, rightDiff); - result = bar.GetHighShadow() >= (diff / 100) * _sharpRatio; - - // - return result; - } - - // - bool IsStrongBullish( - XOHCL &bar, - double percent = 50 // Percent of Body - ) - { - // - bool result = false; - - // - result = - bar.IsValid() && - bar.IsBullish() && - IsStrong(bar, percent); - - // - return result; - } - - // - bool IsStrongBearish( - XOHCL &bar, - double percent = 50 // Percent of Body - ) - { - // - bool result = false; - - // - result = - bar.IsValid() && - bar.IsBearish() && - IsStrong(bar, percent); - - // - return result; - } - - // - bool IsSharpBullish( - XOHCL &bar, - int __loopback = 2, - double _sharpRatio = 2.5 // - ) - { - // - bool result = false; - - // - result = bar.IsValid(); - if (!result) - { - return result; - } - - // - if (__loopback < 0) - { - __loopback = 2; - } - - // - if (_sharpRatio < 0) - { - _sharpRatio = 2.5; - } - - // - int hIDX = bar.FindHighestIndex( - __loopback, - MODE_HIGH // - ); - int lIDX = bar.FindLowestIndex( - __loopback, - MODE_LOW // - ); - - // - result = - // - hIDX >= 0 && - lIDX >= 0 && - MathAbs(hIDX - bar.Index()) < 2 + priceChangePercent > 0 && + priceChangePercent >= minPriceChangePercent // ; // - if (!result) - { - return result; - } - - // - XOHCL hBar; - result = hBar.Init( - bar.symbol, - bar.period, - hIDX // - ); - if (!result) - { - return result; - } - - // - XOHCL lBar; - result = lBar.Init( - bar.symbol, - bar.period, - lIDX // - ); - if (!result) - { - return result; - } - - // - double lhDif = hBar.high - lBar.low; - - // - int hhIDX = hBar.FindHighestIndex( - __loopback, - MODE_HIGH // - ); - - // - int llIDX = lBar.FindLowestIndex( - __loopback, - MODE_LOW // - ); - - // - XOHCL hhBar; - result = hhBar.Init( - bar.symbol, - bar.period, - hhIDX + hIDX // - ); - if (!result) - { - return result; - } - - // - XOHCL llBar; - result = llBar.Init( - bar.symbol, - bar.period, - llIDX + lIDX // - ); - if (!result) - { - return result; - } - - // - double llhhDif = hhBar.high - llBar.low; - - // - result = + bool isBearish = // - lBar.low > llBar.low && - hBar.high > hhBar.high && - lhDif >= llhhDif * _sharpRatio + priceChangePercent < 0 && + MathAbs(priceChangePercent) >= minPriceChangePercent // ; // - return result; - } - - // - bool IsSharpBearish( - XOHCL &bar, - int __loopback = 2, - double _sharpRatio = 2.5 // - ) - { - // - bool result = false; - - // - result = bar.IsValid(); - if (!result) - { - return result; - } - - // - if (__loopback < 0) - { - __loopback = 2; - } - - // - if (_sharpRatio < 0) - { - _sharpRatio = 2.5; - } - - // - int hIDX = bar.FindHighestIndex( - __loopback, - MODE_HIGH // - ); - int lIDX = bar.FindLowestIndex( - __loopback, - MODE_LOW // - ); - - // - result = - // - hIDX >= 0 && - lIDX >= 0 && - MathAbs(hIDX - bar.Index()) < 2 - // - ; - - // - if (!result) - { - return result; - } - - // - XOHCL hBar; - result = hBar.Init( - bar.symbol, - bar.period, - hIDX // - ); - if (!result) - { - return result; - } - - // - XOHCL lBar; - result = lBar.Init( - bar.symbol, - bar.period, - lIDX // - ); - if (!result) - { - return result; - } - - // - double lhDif = hBar.high - lBar.low; - - // - int hhIDX = hBar.FindHighestIndex( - __loopback, - MODE_HIGH // - ); - - // - int llIDX = lBar.FindLowestIndex( - __loopback, - MODE_LOW // - ); - - // - XOHCL hhBar; - result = hhBar.Init( - bar.symbol, - bar.period, - hhIDX + hIDX // - ); - if (!result) - { - return result; - } - - // - XOHCL llBar; - result = llBar.Init( - bar.symbol, - bar.period, - llIDX + lIDX // - ); - if (!result) - { - return result; - } - - // - double llhhDif = hhBar.high - llBar.low; - - // - result = - // - lBar.low < llBar.low && - hBar.high < hhBar.high && - lhDif >= llhhDif * _sharpRatio - // - ; - - // - return result; - } - - // - // - // - - // - // Retrieve Bullish Pressure ... - double GetBullishPressure( - XOHCL &bar, - int __loopback = 7 // - ) - { - // - double result = 0; - - // - if (!bar.IsValid()) - { - return result; - } - - // - XOHCL bars[]; - int barsCount = GetBars( - bars, - bar.symbol, - bar.period, - bar.Index(), - __loopback // - ); - if (!IsValidSize(barsCount)) - { - return result; - } - - // - for (int i = 0; i < barsCount; i++) - { - result += bars[i].GetLowShadow(); - } - - // - return result; - } - - // - // Retrieve Bearish Pressure ... - double GetBearishPressure( - XOHCL &bar, - int __loopback = 7 // - ) - { - // - double result = 0; - - // - if (!bar.IsValid()) - { - return result; - } - - // - XOHCL bars[]; - int barsCount = GetBars( - bars, - bar.symbol, - bar.period, - bar.Index(), - __loopback // - ); - if (!IsValidSize(barsCount)) - { - return result; - } - - // - for (int i = 0; i < barsCount; i++) - { - result += bars[i].GetHighShadow(); - } - - // - return result; - } - - // - bool HasBullishPressure( - XOHCL &bar, - int __loopback = 7 // - ) - { - // - bool result = false; - - // - if (__loopback < 0) - { - __loopback = 7; - } - - // - result = bar.IsValid(); - if (!result) - { - return result; - } - - // - double bullishPressure = GetBullishPressure(bar, __loopback); - double bearishPressure = GetBearishPressure(bar, __loopback); - - // - result = - // - bullishPressure > 0 && - bearishPressure >= 0 && - bullishPressure > bearishPressure - // - ; - - // - return result; - } - - // - bool HasBearishPressure( - XOHCL &bar, - int __loopback = 7 // - ) - { - // - bool result = false; - - // - if (__loopback < 0) - { - __loopback = 7; - } - - // - result = bar.IsValid(); - if (!result) - { - return result; - } - - // - double bullishPressure = GetBullishPressure(bar, __loopback); - double bearishPressure = GetBearishPressure(bar, __loopback); - - // - result = - // - bearishPressure > 0 && - bullishPressure >= 0 && - bearishPressure > bullishPressure - // - ; - - // - return result; - } - - // - // Retrieve Bullish Power ... - double GetBullishPower( - XOHCL &bar, - int __loopback = 7 // - ) - { - // - double result = 0; - - // - if (!bar.IsValid()) - { - return result; - } - - // - XOHCL bars[]; - int barsCount = GetBars( - bars, - bar.symbol, - bar.period, - bar.Index(), - __loopback // - ); - if (!IsValidSize(barsCount)) - { - return result; - } - - // - for (int i = 0; i < barsCount; i++) - { - // - if (bars[i].IsBullish()) - { - result += bars[i].GetBody(); - } - } - - // - return result; - } - - // - // Retrieve Bearish Pressure ... - double GetBearishPower( - XOHCL &bar, - int __loopback = 7 // - ) - { - // - double result = 0; - - // - if (!bar.IsValid()) - { - return result; - } - - // - XOHCL bars[]; - int barsCount = GetBars( - bars, - bar.symbol, - bar.period, - bar.Index(), - __loopback // - ); - if (!IsValidSize(barsCount)) - { - return result; - } - - // - for (int i = 0; i < barsCount; i++) - { - // - if (bars[i].IsBearish()) - { - result += bars[i].GetBody(); - } - } - - // - return result; - } - - // - bool HasBullishPower( - XOHCL &bar, - int __loopback = 7 // - ) - { - // - bool result = false; - - // - if (__loopback < 0) - { - __loopback = 7; - } - - // - result = bar.IsValid(); - if (!result) - { - return result; - } - - // - double bullishPressure = GetBullishPower(bar, __loopback); - double bearishPressure = GetBearishPower(bar, __loopback); - - // - result = - // - bullishPressure > 0 && - bearishPressure >= 0 && - bullishPressure > bearishPressure - // - ; - - // - return result; - } - - // - bool HasBearishPower( - XOHCL &bar, - int __loopback = 7 // - ) - { - // - bool result = false; - - // - if (__loopback < 0) - { - __loopback = 7; - } - - // - result = bar.IsValid(); - if (!result) - { - return result; - } - - // - double bullishPressure = GetBullishPower(bar, __loopback); - double bearishPressure = GetBearishPower(bar, __loopback); - - // - result = - // - bearishPressure > 0 && - bullishPressure >= 0 && - bearishPressure > bullishPressure - // - ; - - // - return result; - } - - // - // Decisions ... - - // - bool IsBullishDecision( - XOHCL &bar, - double percent = 70 // Percent of Body - ) - { - // - bool result = false; - - // - result = - // - bar.IsValid() && - bar.Index() > 0 && - bar.IsBullish() && - (bar.GetRange() * percent) / 100 <= bar.GetBody() - // - ; - - // - return result; - } - - // - bool IsBearishDecision( - XOHCL &bar, - double percent = 70 // Percent of Body - ) - { - // - bool result = false; - - // - result = - // - bar.IsValid() && - bar.Index() > 0 && - bar.IsBearish() && - (bar.GetRange() * percent) / 100 <= bar.GetBody() - // - ; - - // - return result; - } - - // - // Candlestic Patterns ... - - // - // Check Doji ... - bool IsDoji( - XOHCL &bar // - ) - { - // - bool result = false; - - // - // Validate Content and Ignore 0 Bar - // since it is not Completed ... - result = bar.IsValid() && bar.Index() > 0; - if (!result) - { - return result; - } - - // - result = bar.open == bar.close; - - // - return result; - } - - // - // Check Hammer ... - bool IsHammer( - XOHCL &bar, - double _upShadowFactor = 0.1, - double _downShadowFactor = 0.6, - bool applyFib382Check = true, - bool applyPrevShadowCheck = true // - ) - { - // - bool result = false; - - // - // Validate Content and Ignore 0 Bar - // since it is not Completed ... - result = bar.IsValid() && bar.Index() > 0; - if (!result) - { - return result; - } - - // - if (_upShadowFactor < 0) - { - _upShadowFactor = 0.1; - } - - // - if (_downShadowFactor < 0) - { - _upShadowFactor = 0.6; - } - - // - double range = bar.GetRange(); - - // - // Check Upper Shadow Must be 0 or Under 10% ... - double upShadow = bar.GetHighShadow(); - result = upShadow < range * _upShadowFactor; - if (!result) - { - return result; - } - - // - // Check Down Shadow Must at least 60% ... - double downShadow = bar.GetLowShadow(); - result = downShadow > range * _downShadowFactor; - if (!result) - { - return result; - } - - // - // Check Fib 382 ... - if (result && applyFib382Check) - { - // - double fib382 = GetFibonacciLevel( - bar.high, - bar.low, - 0.382, - -1 // - ); - result = bar.GetDown() > fib382; - } - - // - // Check Shadow Based on Prev Bar ... - if (result && applyPrevShadowCheck) - { - // - XOHCL pBar; - result = bar.GetPreviousBar(pBar); - if (!result) - { - return result; - } - - // - result = bar.low < pBar.low; - } - - // - return result; - } - - // - // Check Sgooting Star ... - // Reversal Hammer ... - bool IsShootingStar( - XOHCL &bar, - double _upShadowFactor = 0.6, - double _downShadowFactor = 0.1, - bool applyFib382Check = true, - bool applyPrevShadowCheck = true // - ) - { - // - bool result = false; - - // - // Validate Content and Ignore 0 Bar - // since it is not Completed ... - result = bar.IsValid() && bar.Index() > 0; - if (!result) - { - return result; - } - - // - if (_upShadowFactor < 0) - { - _upShadowFactor = 0.6; - } - - // - if (_downShadowFactor < 0) - { - _upShadowFactor = 0.1; - } - - // - double range = bar.GetRange(); - - // - // Check Upper Shadow Must be 0 or Under 10% ... - double upShadow = bar.GetHighShadow(); - result = upShadow > range * _upShadowFactor; - if (!result) - { - return result; - } - - // - // Check Down Shadow Must at least 60% ... - double downShadow = bar.GetLowShadow(); - result = downShadow < range * _downShadowFactor; - if (!result) - { - return result; - } - - // - // Check Fib 382 ... - if (result && applyFib382Check) - { - // - double fib382 = GetFibonacciLevel( - bar.high, - bar.low, - 0.382, - 1 // - ); - result = bar.GetUp() < fib382; - } - - // - // Check Shadow Based on Prev Bar ... - if (result && applyPrevShadowCheck) - { - // - XOHCL pBar; - result = bar.GetPreviousBar(pBar); - if (!result) - { - return result; - } - - // - result = bar.high > pBar.high; - } - - // - return result; - } - - // - // Check Bullish Engulfing ... - bool IsBullishEngulfing( - XOHCL &bar, - double _engulfBarBodyFactor = 0.7 // - ) - { - // - bool result = false; - - // - // Validate Content and Ignore 0 Bar - // since it is not Completed ... - result = bar.IsValid() && bar.Index() > 0; - if (!result) - { - return result; - } - - // - if (_engulfBarBodyFactor < 0) - { - _engulfBarBodyFactor = 0.7; - } - - // - // Check Bar Is Bullish ... - result = bar.IsBullish(); - if (!result) - { - return result; - } - - // - // Retrieve Previous Bar ... - XOHCL pBar; - result = bar.GetPreviousBar(pBar); - if (!result) - { - return result; - } - - // - double range = bar.GetRange(); - double body = bar.GetBody(); - - // - // Check Prev Bar Must Bearish ... - result = pBar.IsBearish(); - if (!result) - { - return result; - } - - // - // Check Shadows Engulf Prev Bar ... - result = - // - bar.high > pBar.high && - bar.low <= pBar.low - // - ; - if (!result) - { - return result; - } - - // - // Check Engulfed Bar Must Inside Engulfer Body ... - result = - // - bar.GetUp() > pBar.GetUp() && - bar.GetDown() < pBar.GetDown() - // - ; - if (!result) - { - return result; - } - - // - // Check Body of Engulfing Bar ... - if (result && _engulfBarBodyFactor > 0) - { - result = body >= range * _engulfBarBodyFactor; - } - - // - return result; - } - - // - // Check Bearish Engulfing ... - bool IsBearishEngulfing( - XOHCL &bar, - double _engulfBarBodyFactor = 0.7 // - ) - { - // - bool result = false; - - // - // Validate Content and Ignore 0 Bar - // since it is not Completed ... - result = bar.IsValid() && bar.Index() > 0; - if (!result) - { - return result; - } - - // - if (_engulfBarBodyFactor < 0) - { - _engulfBarBodyFactor = 0.7; - } - - // - // Check Bar Is Bearish ... - result = bar.IsBearish(); - if (!result) - { - return result; - } - - // - // Retrieve Previous Bar ... - XOHCL pBar; - result = bar.GetPreviousBar(pBar); - if (!result) - { - return result; - } - - // - double range = bar.GetRange(); - double body = bar.GetBody(); - - // - // Check Prev Bar Must Bullish ... - result = pBar.IsBullish(); - if (!result) - { - return result; - } - - // - // Check Shadows Engulf Prev Bar ... - result = bar.high >= pBar.high && - bar.low < pBar.low; - if (!result) - { - return result; - } - - // - // Check Engulfed Bar Must Inside Engulfer Body ... - result = - // - bar.GetUp() > pBar.GetUp() && - bar.GetDown() < pBar.GetDown() - // - ; - if (!result) - { - return result; - } - - // - // Check Body of Engulfing Bar ... - if (result && _engulfBarBodyFactor > 0) - { - result = body >= range * _engulfBarBodyFactor; - } - - // - return result; - } - - // - // Check Morning Star Pattern ... - bool IsMorningStar( - XOHCL &bar, - double _middleRangeFactor = 0.3, - double _startBodyFactor = 0.6, - bool forceCheckMiddleBarDirection = true, - bool forceCheckStartBody = true // - ) - { - // - bool result = false; - - // - // Validate Content and Ignore 0 Bar - // since it is not Completed ... - result = bar.IsValid() && bar.Index() > 0; - if (!result) - { - return result; - } - - // - if (_middleRangeFactor < 0) - { - _middleRangeFactor = 0.3; - } - - // - if (_startBodyFactor < 0) - { - _startBodyFactor = 0.6; - } - - // - // Current Bar Must be Bullish ... - result = bar.IsBullish(); - if (!result) - { - return result; - } - - // - // Retrieve Previous Bar ... - XOHCL pBar; - result = bar.GetPreviousBar(pBar); - if (!result) - { - return result; - } - - // - // Prev Bar must be Bearish ... - if (result && forceCheckMiddleBarDirection) - { - // - result = pBar.IsBearish(); - if (!result) - { - return result; - } - } - - // - // Retrieve Previous Bar of Prev Bar ... - XOHCL ppBar; - result = pBar.GetPreviousBar(ppBar); - if (!result) - { - return result; - } - - // - // Prev Of Prev Bar Must be Bearish ... - result = ppBar.IsBearish(); - if (!result) - { - return result; - } - - // - double range = bar.GetRange(); - double pRange = pBar.GetRange(); - double ppRange = ppBar.GetRange(); - - // - // Middle Bar must be Smaller than Ratio of other ... - result = - // - pRange < range * _middleRangeFactor && - pRange < ppRange * _middleRangeFactor - // - ; - if (!result) - { - return result; - } - - // - if (result && forceCheckStartBody) - { - // - result = ppBar.GetBody() > ppRange * _startBodyFactor; - if (!result) - { - return result; - } - } - - // - return result; - } - - // - // Check Evening Star Pattern ... - bool IsEveningStar( - XOHCL &bar, - double _middleRangeFactor = 0.3, - double _startBodyFactor = 0.6, - bool forceCheckMiddleBarDirection = true, - bool forceCheckStartBody = true // - ) - { - // - bool result = false; - - // - // Validate Content and Ignore 0 Bar - // since it is not Completed ... - result = bar.IsValid() && bar.Index() > 0; - if (!result) - { - return result; - } - - // - if (_middleRangeFactor < 0) - { - _middleRangeFactor = 0.3; - } - - // - if (_startBodyFactor < 0) - { - _startBodyFactor = 0.6; - } - - // - // Current Bar Must be Bearish ... - result = bar.IsBearish(); - if (!result) - { - return result; - } - - // - // Retrieve Previous Bar ... - XOHCL pBar; - result = bar.GetPreviousBar(pBar); - if (!result) - { - return result; - } - - // - // Prev Bar must be Bullish ... - if (result && forceCheckMiddleBarDirection) - { - // - result = pBar.IsBullish(); - if (!result) - { - return result; - } - } - - // - // Retrieve Previous Bar of Prev Bar ... - XOHCL ppBar; - result = pBar.GetPreviousBar(ppBar); - if (!result) - { - return result; - } - - // - // Prev Of Prev Bar Must be Bullish ... - result = ppBar.IsBullish(); - if (!result) - { - return result; - } - - // - double range = bar.GetRange(); - double pRange = pBar.GetRange(); - double ppRange = ppBar.GetRange(); - - // - // Middle Bar must be Smaller than Ratio of other ... - result = - // - pRange < range * _middleRangeFactor && - pRange < ppRange * _middleRangeFactor - // - ; - if (!result) - { - return result; - } - - // - if (result && forceCheckStartBody) - { - // - result = ppBar.GetBody() > ppRange * _startBodyFactor; - if (!result) - { - return result; - } - } - - // - return result; - } - - // - // Bullish Marubozu ... - bool IsBullishMarubozu(XOHCL &bar) - { - // - bool result = false; - - // - result = bar.IsValid() && bar.Index() > 0; - if (!result) - { - return result; - } - - // - result = bar.IsBullish(); - if (!result) - { - return result; - } - - // - result = - // - bar.GetUp() == bar.high && - bar.GetDown() == bar.low - // - ; - - // - return result; - } - - // - // Bearish Marubozu ... - bool IsBearishMarubozu(XOHCL &bar) - { - // - bool result = false; - - // - result = bar.IsValid() && bar.Index() > 0; - if (!result) - { - return result; - } - - // - result = bar.IsBearish(); - if (!result) - { - return result; - } - - // - result = - // - bar.GetUp() == bar.high && - bar.GetDown() == bar.low - // - ; - - // - return result; - } - - // - // Contextual Patterns ... - - // - // Check Swing High ... - bool IsBarSwingHigh(XOHCL &bar) - { - // - bool result = false; - - // - // Validate Content and Ignore 0 Bar - // since it is not Completed ... - result = bar.IsValid() && bar.Index() > 0; - if (!result) - { - return result; - } - - // - // Current Bar Must be Bearish ... - result = bar.IsBearish(); - if (!result) - { - return result; - } - - // - // Retrieve Prev Bar ... - XOHCL pBar; - result = bar.GetPreviousBar(pBar); - if (!result) - { - return result; - } - - // - // Prev Bar Must be Bullish ... - result = pBar.IsBullish(); - if (!result) - { - return result; - } - - // - // Retrieve Prev of Prev Bar ... - XOHCL ppBar; - result = pBar.GetPreviousBar(ppBar); - if (!result) - { - return result; - } - - // - // Prev of Prev Bar Must be Bullish ... - result = ppBar.IsBullish(); - if (!result) - { - return result; - } - - // - // Check All Highs ... - result = - // - bar.high < pBar.high && - pBar.high > ppBar.high - // - ; - - // - return result; - } - - // - // Find Simple 3 Candle Based Swing High ... - bool IsSimpleSwingHigh( - XOHCL &bar, - double thresholdInPoint = 1 // - ) - { - // - bool result = false; - - // - int index = bar.Index(); - result = index > 0; - if (!result) - { - return result; - } - - // - XOHCL nextBar; - result = bar.GetNextBar(nextBar); - if (!result) - { - return result; - } - - // - XOHCL prevBar; - result = bar.GetPreviousBar(prevBar); - if (!result) - { - return result; - } - - // - double point = GetPoints(bar.symbol); - double requiredOffset = point * thresholdInPoint; - - // - result = - bar.high > nextBar.high && - bar.high > prevBar.high && - (thresholdInPoint <= 0 - ? true - : MathAbs( - MathMax( - nextBar.high, - prevBar.high) - - bar.high) >= requiredOffset); - - // - return result; - } - - // - // Find Last Swing High ... - bool FindLastSwingHigh( - XOHCL &bar, - XOHCL &swing // - ) - { - // - bool result = false; - - // - swing.Clean(); - - // - result = bar.IsValid(); - if (!result) - { - return result; - } - - // - int totalBars = iBars( - bar.symbol, - bar.period // - ); - int maxAllowed = MathMin(100, (totalBars / 100)); - - // - int idx = bar.Index(); - for (int i = idx; i <= idx + maxAllowed; i++) - { - // - swing.Clean(); - result = swing.Init( - bar.symbol, - bar.period, - i // - ); - if (!result) - { - // - swing.Clean(); - break; - } - - // - result = IsBarSwingHigh(swing); - if (result) - { - break; - } - } - - // - return result; - } - - // - // Check Swing Low ... - bool IsBarSwingLow(XOHCL &bar) - { - // - bool result = false; - - // - // Validate Content and Ignore 0 Bar - // since it is not Completed ... - result = bar.IsValid() && bar.Index() > 0; - if (!result) - { - return result; - } - - // - // Current Bar Must be Bullish ... - result = bar.IsBullish(); - if (!result) - { - return result; - } - - // - // Retrieve Prev Bar ... - XOHCL pBar; - result = bar.GetPreviousBar(pBar); - if (!result) - { - return result; - } - - // - // Prev Bar Must be Bearish ... - result = pBar.IsBearish(); - if (!result) - { - return result; - } - - // - // Retrieve Prev of Prev Bar ... - XOHCL ppBar; - result = pBar.GetPreviousBar(ppBar); - if (!result) - { - return result; - } - - // - // Prev of Prev Bar Must be Bearish ... - result = ppBar.IsBearish(); - if (!result) - { - return result; - } - - // - // Check All Lows ... - result = - // - bar.low > pBar.low && - pBar.low < ppBar.low - // - ; - - // - return result; - } - - // - // Find Simple 3 Candle Based Swing Low ... - bool IsSimpleSwingLow( - XOHCL &bar, - double thresholdInPoint = 1 // - ) - { - // - bool result = false; - - // - int index = bar.Index(); - result = index > 0; - if (!result) - { - return result; - } - - // - XOHCL nextBar; - result = bar.GetNextBar(nextBar); - if (!result) - { - return result; - } - - // - XOHCL prevBar; - result = bar.GetPreviousBar(prevBar); - if (!result) - { - return result; - } - - // - double point = GetPoints(bar.symbol); - double requiredOffset = point * thresholdInPoint; - - // - result = - bar.low < nextBar.low && - bar.low < prevBar.low && - (thresholdInPoint <= 0 - ? true - : MathAbs( - MathMax( - nextBar.low, - prevBar.low) - - bar.low) >= requiredOffset); - - // - return result; - } - - // - // Find Last Swing Low ... - bool FindLastSwingLow( - XOHCL &bar, - XOHCL &swing // - ) - { - // - bool result = false; - - // - swing.Clean(); - - // - result = bar.IsValid(); - if (!result) - { - return result; - } - - // - int totalBars = iBars( - bar.symbol, - bar.period // - ); - int maxAllowed = MathMin(100, (totalBars / 100)); - - // - int idx = bar.Index(); - for (int i = idx; i <= idx + maxAllowed; i++) - { - // - swing.Clean(); - result = swing.Init( - bar.symbol, - bar.period, - i // - ); - if (!result) - { - // - swing.Clean(); - break; - } - - // - result = IsBarSwingLow(swing); - if (result) - { - break; - } - } - - // - return result; - } - - // - // Check Bullish FVG ... - bool HasBullishFVG( - XOHCL &bar, - double &upper, - double &lower, - datetime &start, - datetime &end, - bool forceMiddleBarCheck = true, - bool forceCheckLastBarDirection = false // - ) - { - // - bool result = false; - - // - upper = 0; - lower = 0; - - // - end = NULL; - start = NULL; - - // - // Validate Content and Ignore 0 Bar - // since it is not Completed ... - result = bar.IsValid() && bar.Index() > 0; - if (!result) - { - return result; - } - - // - // Current Bar Must be Bullish ... - result = - !forceCheckLastBarDirection - ? true - : bar.IsBullish(); - if (!result) - { - return result; - } - - // - // Retrieve Prev Bar ... - XOHCL pBar; - result = bar.GetPreviousBar(pBar); - if (!result) - { - return result; - } - - // - // Prev Bar Must be Bullish ... - result = pBar.IsBullish(); - if (!result) - { - return result; - } - - // - // Retrieve Prev of Prev Bar ... - XOHCL ppBar; - result = pBar.GetPreviousBar(ppBar); - if (!result) - { - return result; - } - - // - // Prev of Prev Bar Must be Bullish ... - result = ppBar.IsBullish(); - if (!result) - { - return result; - } - - // - // Other Conditions ... - result = - // - bar.low > ppBar.high - // - ; - - // - // Check Middle Bar Range ... - if (result && forceMiddleBarCheck) - { - // - result = - // - pBar.high > bar.low && - pBar.low < ppBar.high - // - ; - - // - if (!result) - { - return result; - } - } - - // + result = isBullish || + isBearish; if (result) { // - end = bar.time; - upper = bar.low; - lower = ppBar.high; - start = ppBar.time; + dir = isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; } // - return result; - } - - // - // Check Bearish FVG ... - bool HasBearishFVG( - XOHCL &bar, - double &upper, - double &lower, - datetime &start, - datetime &end, - bool forceMiddleBarCheck = true, - bool forceCheckLastBarDirection = false // - ) - { - // - bool result = false; + // Cleanup Resources ... // - upper = 0; - lower = 0; - - // - end = NULL; - start = NULL; - - // - // Validate Content and Ignore 0 Bar - // since it is not Completed ... - result = bar.IsValid() && bar.Index() > 0; - if (!result) - { - return result; - } - - // - // Current Bar Must be Bearish ... - result = - !forceCheckLastBarDirection - ? true - : bar.IsBullish(); - if (!result) - { - return result; - } - - // - // Retrieve Prev Bar ... - XOHCL pBar; - result = bar.GetPreviousBar(pBar); - if (!result) - { - return result; - } - - // - // Prev Bar Must be Bearish ... - result = pBar.IsBearish(); - if (!result) - { - return result; - } - - // - // Retrieve Prev of Prev Bar ... - XOHCL ppBar; - result = pBar.GetPreviousBar(ppBar); - if (!result) - { - return result; - } - - // - // Prev of Prev Bar Must be Bearish ... - result = ppBar.IsBearish(); - if (!result) - { - return result; - } - - // - // Other Conditions ... - result = - // - bar.high < ppBar.low - // - ; - - // - // Check Middle Bar Range ... - if (result && forceMiddleBarCheck) - { - // - result = - // - pBar.high > bar.low && - pBar.low < ppBar.high - // - ; - - // - if (!result) - { - return result; - } - } - - // - if (result) - { - // - end = bar.time; - lower = bar.high; - upper = ppBar.low; - start = ppBar.time; - } - - // - return result; - } - - // - // Find Support ... - bool HasSupport( - XOHCL &bar, - XOHCL &dest, - ENUM_X_PRICE type = X_PRICE_CLOSE, - int _loopback = 21, - int tries = 100 // - ) - { - // - bool result = false; - - // - dest.Clean(); - - // - if (_loopback < 0) - { - _loopback = 21; - } - - // - if (tries < 0) - { - tries = 100; - } - - // - result = bar.IsValid(); - if (!result) - { - return result; - } - - // - double price = bar.GetPrice(type); - - // - for (int i = 1; i < tries; i++) - { - // - int _length = _loopback * i; - - // - int lowestIDX = bar.FindLowestIndex( - _length, - MODE_LOW // - ); - result = IsValidIndex(lowestIDX); - if (!result) - { - break; - } - - // - XOHCL iLBar; - result = iLBar.Init( - bar.symbol, - bar.period, - lowestIDX // - ); - if (!result) - { - break; - } - - // - result = - // - price > iLBar.high - // - ; - if (result) - { - // - dest = iLBar; - break; - } - } - - // - result = dest.IsValid(); - - // - return result; - } - - // - // Find Resistance ... - bool HasResistance( - XOHCL &bar, - XOHCL &dest, - ENUM_X_PRICE type = X_PRICE_CLOSE, - int _loopback = 21, - int tries = 100 // - ) - { - // - bool result = false; - - // - dest.Clean(); - - // - if (_loopback < 0) - { - _loopback = 21; - } - - // - if (tries < 0) - { - tries = 100; - } - - // - result = bar.IsValid(); - if (!result) - { - return result; - } - - // - double price = bar.GetPrice(type); - - // - for (int i = 1; i < tries; i++) - { - // - int _length = _loopback * i; - - // - int highestIDX = bar.FindHighestIndex( - _length, - MODE_LOW // - ); - result = IsValidIndex(highestIDX); - if (!result) - { - break; - } - - // - XOHCL iHBar; - result = iHBar.Init( - bar.symbol, - bar.period, - highestIDX // - ); - if (!result) - { - break; - } - - // - result = - // - price < iHBar.high - // - ; - if (result) - { - // - dest = iHBar; - break; - } - } - - // - result = dest.IsValid(); - - // - return result; - } - - // - // Trend Detection ... - - // - // Find Bullish Trend ... - bool HasBullishTrend( - XOHCL &bar, - XOHCL &highSwingBars[], - XOHCL &lowSwingBars[], - bool forceMethod2 = false, - int _loopback = 3, - int tries = 3, - ENUM_X_PRICE type = X_PRICE_CLOSE // - ) - { - // - bool result = false; - - // - Clean(lowSwingBars); - Clean(highSwingBars); - - // - result = bar.IsValid(); - if (!result) - { - return result; - } - - // - double price = bar.GetPrice(type); - - // - int lastIDX = bar.Index(); - double lastH = 0; - double lastL = 0; - for (int i = 1; i < tries + 1; i++) - { - // - // Use Regular Method ... - if (!forceMethod2) - { - // - int iHIDX = FindSwing( - bar.symbol, - bar.period, - X_SWING_HIGH, - _loopback, - lastIDX // - ); - result = IsValidIndex(iHIDX); - if (!result) - { - break; - } - - // - XOHCL iHBar; - result = iHBar.Init( - bar.symbol, - bar.period, - iHIDX // - ); - if (!result) - { - break; - } - - // - double iH = iHBar.high; - bool isIHAccepted = - // - iH > 0 && - ( - // - lastH == 0 - ? true - : iH < lastH - // - ) - // - ; - if (isIHAccepted) - { - // - AddRef( - iHBar, - highSwingBars // - ); - - // - lastH = iH; - lastIDX = iHIDX; - } - - // - int iLIDX = FindSwing( - bar.symbol, - bar.period, - X_SWING_LOW, - _loopback, - lastIDX // - ); - result = IsValidIndex(iLIDX); - if (!result) - { - break; - } - - // - XOHCL iLBar; - result = iLBar.Init( - bar.symbol, - bar.period, - iLIDX // - ); - if (!result) - { - break; - } - - // - double iL = iLBar.low; - bool isILAccepted = - // - iL > 0 && - ( - // - lastL == 0 - ? true - : iL < lastL - // - ) - // - ; - if (isILAccepted) - { - // - AddRef( - iLBar, - lowSwingBars // - ); - - // - lastL = iL; - lastIDX = iLIDX; - } - } - // - // Use Other MEthod ... - else - { - // - int _length = i * _loopback; - int start = - // - i == 1 - ? 1 - : _length - _loopback - // - ; - - // - int iHIDX = iHighest( - bar.symbol, - bar.period, - MODE_HIGH, - _loopback, - start // - ); - result = IsValidIndex(iHIDX); - if (!result) - { - break; - } - - // - XOHCL iHBar; - result = iHBar.Init( - bar.symbol, - bar.period, - iHIDX // - ); - if (!result) - { - break; - } - - // - double iH = iHBar.high; - bool isIHAccepted = - // - iH > 0 && - ( - // - lastH == 0 - ? true - : iH < lastH - // - ) - // - ; - if (isIHAccepted) - { - // - AddRef( - iHBar, - highSwingBars // - ); - - // - lastH = iH; - lastIDX = iHIDX; - } - - // - int iLIDX = iLowest( - bar.symbol, - bar.period, - MODE_LOW, - _loopback, - start // - ); - result = IsValidIndex(iLIDX); - if (!result) - { - break; - } - - // - XOHCL iLBar; - result = iLBar.Init( - bar.symbol, - bar.period, - iLIDX // - ); - if (!result) - { - break; - } - - // - double iL = iLBar.low; - bool isILAccepted = - // - iL > 0 && - ( - // - lastL == 0 - ? true - : iL < lastL - // - ) - // - ; - if (isILAccepted) - { - // - AddRef( - iLBar, - lowSwingBars // - ); - - // - lastL = iL; - lastIDX = iLIDX; - } - } - } - - // - if (result) - { - // - result = - // - ArraySize(lowSwingBars) == tries && - ArraySize(highSwingBars) == tries - // - ; - } - - // - if (!result) - { - // - Clean(lowSwingBars); - Clean(highSwingBars); - } - - // - return result; - } - - // - // Find Bearish Trend ... - bool HasBearishTrend( - XOHCL &bar, - XOHCL &highSwingBars[], - XOHCL &lowSwingBars[], - bool forceMethod2 = false, - int _loopback = 3, - int tries = 3, - ENUM_X_PRICE type = X_PRICE_CLOSE // - ) - { - // - bool result = false; - - // - Clean(lowSwingBars); - Clean(highSwingBars); - - // - result = bar.IsValid(); - if (!result) - { - return result; - } - - // - double price = bar.GetPrice(type); - - // - int lastIDX = bar.Index(); - double lastH = 0; - double lastL = 0; - for (int i = 1; i < tries + 1; i++) - { - // - // Use Regular Method ... - if (!forceMethod2) - { - // - int iHIDX = FindSwing( - bar.symbol, - bar.period, - X_SWING_HIGH, - _loopback, - lastIDX // - ); - result = IsValidIndex(iHIDX); - if (!result) - { - break; - } - - // - XOHCL iHBar; - result = iHBar.Init( - bar.symbol, - bar.period, - iHIDX // - ); - if (!result) - { - break; - } - - // - double iH = iHBar.high; - bool isIHAccepted = - // - iH > 0 && - ( - // - lastH == 0 - ? true - : iH > lastH - // - ) - // - ; - if (isIHAccepted) - { - // - AddRef( - iHBar, - highSwingBars // - ); - - // - lastH = iH; - lastIDX = iHIDX; - } - - // - int iLIDX = FindSwing( - bar.symbol, - bar.period, - X_SWING_LOW, - _loopback, - lastIDX // - ); - result = IsValidIndex(iLIDX); - if (!result) - { - break; - } - - // - XOHCL iLBar; - result = iLBar.Init( - bar.symbol, - bar.period, - iLIDX // - ); - if (!result) - { - break; - } - - // - double iL = iLBar.low; - bool isILAccepted = - // - iL > 0 && - ( - // - lastL == 0 - ? true - : iL > lastL - // - ) - // - ; - if (isILAccepted) - { - // - AddRef( - iLBar, - lowSwingBars // - ); - - // - lastL = iL; - lastIDX = iLIDX; - } - } - // - // Use Other MEthod ... - else - { - // - int _length = i * _loopback; - int start = - // - i == 1 - ? 1 - : _length - _loopback - // - ; - - // - int iHIDX = iHighest( - bar.symbol, - bar.period, - MODE_HIGH, - _loopback, - start // - ); - result = IsValidIndex(iHIDX); - if (!result) - { - break; - } - - // - XOHCL iHBar; - result = iHBar.Init( - bar.symbol, - bar.period, - iHIDX // - ); - if (!result) - { - break; - } - - // - double iH = iHBar.high; - bool isIHAccepted = - // - iH > 0 && - ( - // - lastH == 0 - ? true - : iH > lastH - // - ) - // - ; - if (isIHAccepted) - { - // - AddRef( - iHBar, - highSwingBars // - ); - - // - lastH = iH; - lastIDX = iHIDX; - } - - // - int iLIDX = iLowest( - bar.symbol, - bar.period, - MODE_LOW, - _loopback, - start // - ); - result = IsValidIndex(iLIDX); - if (!result) - { - break; - } - - // - XOHCL iLBar; - result = iLBar.Init( - bar.symbol, - bar.period, - iLIDX // - ); - if (!result) - { - break; - } - - // - double iL = iLBar.low; - bool isILAccepted = - // - iL > 0 && - ( - // - lastL == 0 - ? true - : iL > lastL - // - ) - // - ; - if (isILAccepted) - { - // - AddRef( - iLBar, - lowSwingBars // - ); - - // - lastL = iL; - lastIDX = iLIDX; - } - } - } - - // - if (result) - { - // - result = - // - ArraySize(lowSwingBars) == tries && - ArraySize(highSwingBars) == tries - // - ; - } - - // - if (!result) - { - // - Clean(lowSwingBars); - Clean(highSwingBars); - } - - // - return result; - } - - // - // Order Blocks ... - - // - // Find Bullish Order Block ... - bool HasBullishOrderBlock( - XOHCL &bar, - XOHCL &orderBlock, - int _minimumSameBars = 4 // - ) - { - // - bool result = false; - - // - orderBlock.Clean(); - - // - result = bar.IsValid(); - if (!result) - { - return result; - } - - // - if (_minimumSameBars < 0) - { - _minimumSameBars = 4; - } - - // - XOHCL cBar; - int founded = 0; - int cIDX = bar.Index(); - bool isEnough = false; - while (!isEnough) - { - // - result = cBar.Init( - bar.symbol, - bar.period, - cIDX // - ); - if (!result) - { - break; - } - - // - result = cBar.IsBullish(); - if (!result && cBar.IsBearish()) - { - break; - } - - // - cIDX++; - founded++; - } - - // - // Here we have to check founded and if it's fill - // our requirements ... - // cIDX is Order Block Index ... - result = - // - cBar.IsValid() && - bar.high > cBar.high && - founded >= _minimumSameBars - // - ; - if (!result) - { - return result; - } - - // - result = orderBlock.Init( - bar.symbol, - bar.period, - cIDX // - ); - if (!result) - { - // - orderBlock.Clean(); - return result; - } - - // - return result; - } - - // - // Find Bearish Order Block ... - bool HasBearishOrderBlock( - XOHCL &bar, - XOHCL &orderBlock, - int _minimumSameBars = 4 // - ) - { - // - bool result = false; - - // - orderBlock.Clean(); - - // - result = bar.IsValid(); - if (!result) - { - return result; - } - - // - if (_minimumSameBars < 0) - { - _minimumSameBars = 4; - } - - // - XOHCL cBar; - int founded = 0; - int cIDX = bar.Index(); - bool isEnough = false; - while (!isEnough) - { - // - bool isInited = cBar.Init( - bar.symbol, - bar.period, - cIDX // - ); - - // - result = cBar.IsBearish(); - if (!result && cBar.IsBullish()) - { - break; - } - - // - cIDX++; - founded++; - } - - // - // Here we have to check founded and if it's fill - // our requirements ... - // cIDX is Order Block Index ... - result = - // - cBar.IsValid() && - bar.high < cBar.low && - founded >= _minimumSameBars - // - ; - if (!result) - { - return result; - } - - // - result = orderBlock.Init( - bar.symbol, - bar.period, - cIDX // - ); - if (!result) - { - // - orderBlock.Clean(); - return result; - } + Clean(ranges); // return result; diff --git a/Classes/x-saherelm.x-cobject.class.mq5 b/Classes/x-saherelm.x-cobject.class.mq5 index 7645a2a4..0cac5cd9 100644 --- a/Classes/x-saherelm.x-cobject.class.mq5 +++ b/Classes/x-saherelm.x-cobject.class.mq5 @@ -2570,706 +2570,6 @@ class XCBoxObject : public XCBaseObject CChartObjectRectangle mRect; }; -class XCRRObject : public XCBaseObject -{ - // - public: - // - - /** - * Creator ... - * - * @param chart_id: Long, Specified Chart ID ... - * @param window: Integer, Specified Chart Window ID ... - * @param rr: XRR instance Reference ... - * @param prefix: String ... - * - * @return ( bool ) - */ - bool Create( - long chart_id, - int window, - XRR &rr, - string prefix = NULL // - ) - { - // - bool result = false; - - // - result = rr.IsValid(); - if (!result) - { - return result; - } - - // - string name = rr.GetTag(); - if (IsValid(prefix)) - { - name = prefix + "_" + name; - } - string nameMD5 = ToMD5(name); - - // - bool isLong = IsLong(rr.type); - - // - double price1 = rr.entry; - double price2 = rr.sl; - - // - datetime time1 = rr.time; - datetime time2 = (datetime)((int)rr.time + 5 * PeriodSeconds(rr.period)); - - // - result = mFibo.Create( - chart_id, - name, - window, - time1, - price1, - time2, - price2 // - ); - if (!result) - { - return result; - } - - // - mRR = rr; - ObjName(name); - - // - int tpsCount = ArraySize(rr.tps); - int levels = tpsCount + 2; - result = mFibo.LevelsCount(levels); - if (!result) - { - return result; - } - - // - // Set Fibo Levels ... - - // - result = mFibo.LevelValue(0, 0); - if (!result) - { - return result; - } - result = mFibo.LevelDescription(0, "SL"); - if (!result) - { - return result; - } - - // - result = mFibo.LevelValue(1, 1.0); - if (!result) - { - return result; - } - result = mFibo.LevelDescription(1, "Entry"); - if (!result) - { - return result; - } - - // - for (int i = 0; i < tpsCount; i++) - { - // - int idx = i + 2; - double level = 1.0 + rr.tps[i]; - string description = "TP " + ToString(rr.tps[i]); - - // - result = mFibo.LevelValue( - idx, - level // - ); - if (!result) - { - break; - } - - // - result = mFibo.LevelDescription( - idx, - description // - ); - if (!result) - { - break; - } - } - if (!result) - { - return result; - } - - // - return result; - } - - // - // Getter(s) / Setter(s) ... - - // - // Virtual ... - - /** - * Retrieve Object Type ... - * - * @return ( ENUM_XCHARTOBJECTS ) - */ - virtual ENUM_XCHARTOBJECTS Type() - { - return X_RR_OBJ; - } - - // - private: - // - - // - // Props ... - XRR mRR; - CChartObjectFibo mFibo; - - // - bool SetSLProps( - int width = 1, - color clr = clrRed, - ENUM_LINE_STYLE style = STYLE_SOLID, - string description = "" // - ) - { - // - bool result = false; - - // - result = SetLevelProps( - 0, - width, - clr, - style, - description // - ); - - // - return result; - } - - // - bool SetEntryProps( - int width = 1, - color clr = clrOrange, - ENUM_LINE_STYLE style = STYLE_SOLID, - string description = "" // - ) - { - // - bool result = false; - - // - result = SetLevelProps( - 0, - width, - clr, - style, - description // - ); - - // - return result; - } - - // - bool SetTPProps( - double tpValue, - int width = 1, - color clr = clrLime, - ENUM_LINE_STYLE style = STYLE_SOLID, - string description = "" // - ) - { - // - bool result = false; - - // - int tpIDX = FindIndex( - tpValue, - mRR.tps // - ); - result = IsValidIndex(tpIDX); - if (!result) - { - return result; - } - - // - tpIDX += 2; - - // - result = SetLevelProps( - tpIDX, - width, - clr, - style, - description // - ); - - // - return result; - } - - // - bool SetLevelProps( - int id, - int width = 1, - color clr = clrYellow, - ENUM_LINE_STYLE style = STYLE_SOLID, - string description = "" // - ) - { - // - bool result = false; - - // - // Color ... - result = mFibo.LevelColor( - id, - clr // - ); - if (!result) - { - return result; - } - - // - // Style ... - result = mFibo.LevelStyle( - id, - style // - ); - if (!result) - { - return result; - } - - // - // Width ... - if (width > 0) - { - // - result = mFibo.LevelWidth( - id, - width // - ); - if (!result) - { - return result; - } - } - - // - // Description ... - if (IsValid(description)) - { - // - result = mFibo.LevelDescription( - id, - description // - ); - if (!result) - { - return result; - } - } - - // - return result; - } -}; - -class XCTrendObject : public XCBaseObject -{ - // - public: - // - - /** - * Creator ... - * - * @param chart_id: Long, Specified Chart ID ... - * @param window: Integer, Specified Chart Window ID ... - * @param rr: XRR instance Reference ... - * @param prefix: String ... - * - * @return ( bool ) - */ - bool Create( - long chart_id, - int window, - XPoint &swings[], - bool useMinAsStart = true, - string prefix = NULL // - ) - { - // - bool result = false; - - // - int count = ArraySize(swings); - result = - count >= 2 && - IsValidSize(count); - if (!result) - { - return result; - } - - // - double min = 0; - datetime minAt = NULL; - - // - double max = 0; - datetime maxAt = NULL; - - // - // Etract Min/Max ... - for (int i = 0; i < count; i++) - { - // - XPoint iPoint = swings[i]; - - // - if (!iPoint.IsValid()) - { - // - iPoint.Clean(); - continue; - } - - // - bool canSetMin = - min == 0 - ? true - : min > iPoint.value; - if (canSetMin) - { - // - minAt = iPoint.at; - min = iPoint.value; - } - - // - bool canSetMax = - max == 0 - ? true - : max < iPoint.value; - if (canSetMax) - { - // - maxAt = iPoint.at; - max = iPoint.value; - } - - // - iPoint.Clean(); - } - - // - double first = - useMinAsStart - ? min - : max; - datetime firstTime = - useMinAsStart - ? minAt - : maxAt; - - // - double second = - useMinAsStart - ? max - : min; - datetime secondTime = - useMinAsStart - ? maxAt - : minAt; - - // - // Validate Points ... - result = - // - first > 0 && - second > 0 && - (useMinAsStart - ? first <= second - : first >= second) && - IsSpecifiedValid(firstTime) && - IsSpecifiedValid(secondTime) - // - ; - if (!result) - { - return result; - } - - // - ENUM_X_DIRECTION dir = - useMinAsStart - ? X_DIRECTION_BULLISH - : X_DIRECTION_BEARISH; - - // - string name = "XTRND" + ToString(dir) + "_" + ToString(first) + "_" + ToString(second); - if (IsValid(prefix)) - { - name = prefix + "_" + name; - } - string nameMD5 = ToMD5(name); - - // - result = mTrend.Create( - chart_id, - name, - window, - firstTime, - first, - secondTime, - second // - ); - if (!result) - { - return result; - } - - // - ObjName(name); - - // - return result; - } - - /** - * Creator ... - * - * @param chart_id: Long, Specified Chart ID ... - * @param window: Integer, Specified Chart Window ID ... - * @param rr: XRR instance Reference ... - * @param prefix: String ... - * - * @return ( bool ) - */ - bool Create( - long chart_id, - int window, - XSwingPoint &swings[], - string prefix = NULL // - ) - { - // - bool result = false; - - // - int count = ArraySize(swings); - result = - count >= 2 && - IsValidSize(count); - if (!result) - { - return result; - } - - // - ENUM_X_SWING_TYPE type = swings[0].type; - bool isSwingLows = type == X_SWING_LOW; - - // - double values[]; - int valuesCount = ExtractSwings( - swings, - values // - ); - result = valuesCount == count; - if (!result) - { - return result; - } - - // - int firstIDX = -1; - double first = 0; - datetime firstTime = NULL; - - // - int secondIDX = -1; - double second = 0; - datetime secondTime = NULL; - - // - if (isSwingLows) - { - // - first = GetMin( - values, - firstIDX, - 0, - 0 // - ); - if (IsValidIndex(firstIDX)) - { - // - firstTime = swings[firstIDX].time; - - // - second = FindBiggerThan( - first, - values, - true // - ); - secondIDX = FindIndex( - second, - values // - ); - if (IsValidIndex(secondIDX)) - { - secondTime = swings[secondIDX].time; - } - } - } - else - { - // - first = GetMax( - values, - firstIDX, - 0, - 0 // - ); - if (IsValidIndex(firstIDX)) - { - // - firstTime = swings[firstIDX].time; - - // - second = FindLesserThan( - first, - values, - true // - ); - secondIDX = FindIndex( - second, - values // - ); - if (IsValidIndex(secondIDX)) - { - secondTime = swings[secondIDX].time; - } - } - } - - // - // Validate Points ... - result = - // - IsValidIndex(firstIDX) && - IsValidIndex(secondIDX) && - // - IsSpecifiedValid(firstTime) && - IsSpecifiedValid(secondTime) && - // - (isSwingLows - ? first < second - : first > second) - // - ; - if (!result) - { - return result; - } - - // - string name = ToString(type) + "_" + ToString(first) + "_" + ToString(second); - if (IsValid(prefix)) - { - name = prefix + "_" + name; - } - string nameMD5 = ToMD5(name); - - // - result = mTrend.Create( - chart_id, - name, - window, - firstTime, - first, - secondTime, - second // - ); - if (!result) - { - return result; - } - - // - ObjName(name); - - // - return result; - } - - // - // Getter(s) / Setter(s) ... - - /** - * Set Trend Color ... - * - * @param value: Color ... - */ - void TrendColor(color value) - { - mTrend.Color(value); - } - - void TrendRayLeft(bool value) - { - mTrend.RayLeft(value); - } - - void TrendRayRight(bool value) - { - mTrend.RayRight(value); - } - - // - // Virtual ... - - /** - * Retrieve Object Type ... - * - * @return ( ENUM_XCHARTOBJECTS ) - */ - virtual ENUM_XCHARTOBJECTS Type() - { - return X_TREND_OBJ; - } - - // - private: - // - - // - // Props ... - CChartObjectTrend mTrend; -}; - // // Zone Ticks ... diff --git a/Classes/x-saherelm.x-poi.drawer.class.mq5 b/Classes/x-saherelm.x-poi.drawer.class.mq5 index 29c9f881..d657246b 100644 --- a/Classes/x-saherelm.x-poi.drawer.class.mq5 +++ b/Classes/x-saherelm.x-poi.drawer.class.mq5 @@ -2816,123 +2816,6 @@ class XCPOIDrawer : public XCBase return result; } - /** - * Create Trend Line Object ... - * - * @param swings: XSwingPoint instance Collection ... - * - * @return ( bool ) - */ - bool CreateTrend( - XSwingPoint &swings[], - XCTrendObject *&object // - ) - { - // - bool result = false; - - // - object = NULL; - - // - result = ArraySize(swings) >= 2 && - IsValidSize(ArraySize(swings)); - if (!result) - { - return result; - } - - // - string prefix = Prefix(); - long chartID = ChartIdentification(); - int window = SubWindowIdentification(); - - // - object = new XCTrendObject(); - result = object.Create( - chartID, - window, - swings, - prefix // - ); - - // - if (!result) - { - return result; - } - - // - color clrTrend = swings[0].type == X_SWING_LOW - ? SwingLowColor() - : SwingHighColor(); - object.TrendColor(clrTrend); - object.TrendRayRight(true); - - // - return result; - } - - /** - * Create Trend Line Object ... - * - * @param swings: XSwingPoint instance Collection ... - * @param useMinAsStart: Specified Min Value as Start ... - * - * @return ( bool ) - */ - bool CreateTrend( - XPoint &swings[], - XCTrendObject *&object, - bool useMinAsStart = true // - ) - { - // - bool result = false; - - // - object = NULL; - - // - result = ArraySize(swings) >= 2 && - IsValidSize(ArraySize(swings)); - if (!result) - { - return result; - } - - // - string prefix = Prefix(); - long chartID = ChartIdentification(); - int window = SubWindowIdentification(); - - // - object = new XCTrendObject(); - result = object.Create( - chartID, - window, - swings, - useMinAsStart, - prefix // - ); - - // - if (!result) - { - return result; - } - - // - color clrTrend = useMinAsStart - ? SwingLowColor() - : SwingHighColor(); - object.TrendColor(clrTrend); - object.TrendRayRight(true); - - // - return result; - } - /** * Create Consolidation Zone Object ... * @@ -3376,53 +3259,6 @@ class XCPOIDrawer : public XCBase return result; } - /** - * Create Specific Risk Reward (RR) on Chart ... - * - * @param rr: XRR instance Reference ... - * - * @return ( bool ) - */ - bool CreateRR( - XRR &rr, - XCRRObject *&object // - ) - { - // - bool result = false; - - // - object = NULL; - - // - result = rr.IsValid(); - if (!result) - { - return result; - } - - // - string prefix = Prefix(); - long chartID = ChartIdentification(); - int window = SubWindowIdentification(); - - // - object = new XCRRObject(); - result = object.Create( - chartID, - window, - rr, - prefix // - ); - if (!result) - { - return result; - } - - // - return result; - } - /** * Draw Specified Signal ... * diff --git a/Documents/BKP/signalling.parsers.mq5 b/Documents/BKP/signalling.parsers.mq5 new file mode 100644 index 00000000..8020ed75 --- /dev/null +++ b/Documents/BKP/signalling.parsers.mq5 @@ -0,0 +1,1563 @@ + // + bool HasSenario1Conditions( + ENUM_X_CYCLES cycle, + XBoxZone &box, + XBoxZone &holderBox, + ENUM_X_DIRECTION &dir, + X121SMCStrategySignalProviderData &provider, + ENUM_X_CYCLES holderCycle = X_CYCLE_NONE, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Fil Selected Data ... + XPOIState cState; + X121Conditions cXConditions; + XC121SMCCycleHelper *cHelper; + X121SMCCycleConditions cConditions; + result = provider.SelectCycle( + cycle, + cState, + cXConditions, + cHelper, + cConditions // + ); + if (!result) + { + // + cState.Clean(); + ZeroMemory(cHelper); + cConditions.Clean(); + cXConditions.Clean(); + + // + return result; + } + Parse(cXConditions); + + // + // Fil Selected Data ... + XPOIState chState; + X121Conditions chXConditions; + XC121SMCCycleHelper *chHelper; + X121SMCCycleConditions chConditions; + if (holderCycle != X_CYCLE_NONE) + { + // + result = provider.SelectCycle( + holderCycle, + chState, + chXConditions, + chHelper, + chConditions // + ); + if (!result) + { + // + chState.Clean(); + ZeroMemory(chHelper); + chConditions.Clean(); + chXConditions.Clean(); + + // + return result; + } + + // + Parse(chXConditions); + } + + // + // Normalize Args ... + + // + box.Clean(); + holderBox.Clean(); + dir = X_DIRECTION_NONE; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int idx = -1; + int count = 0; + bool has = false; + + // + int zIDX = barIndex; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + + // + bool isBullish = false; + bool isBearish = false; + + // + XOHCL zBar; + XOHCL cBar; + XOHCL pBar; + + // + // Initial Bars ... + result = zBar.Init( + cState.symbol, + cState.period, + barIndex // + ); + result = + result && + zBar.GetPreviousBar(cBar); + result = + result && + cBar.GetPreviousBar(pBar); + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + cState.Clean(); + chState.Clean(); + ZeroMemory(cHelper); + cConditions.Clean(); + cXConditions.Clean(); + ZeroMemory(chHelper); + chConditions.Clean(); + chXConditions.Clean(); + + // + return result; + } + + // + // + // Detecting Signal Conditions ... + + // + // Bullish Conditions ... + isBullish = + // + // Base Condition ... + cXConditions.isSMHKSwitchedToBullish && + ( + // + // Validate CBar ... + cBar.IsBullish() && + // + (cBar.low >= cXConditions.valesGoldenBuffer[cIDX] || + (cBar.low < cXConditions.valesGoldenBuffer[cIDX] && + cXConditions.isSarSwitchedToBullish)) && + // + (cBar.open == cXConditions.xhkSMOpenBuffer[cIDX] || + (cBar.low < cXConditions.xhkSMLowBuffer[cIDX] && + cBar.GetDown() > cXConditions.xhkSMHighBuffer[cIDX])) && + // + cXConditions.isSarBullish + // + ) + // + ; + + // + // Bearish Conditions ... + isBearish = + // + // Base Condition ... + cXConditions.isSMHKSwitchedToBearish && + ( + // + // Validate CBar ... + cBar.IsBearish() && + // + (cBar.high <= cXConditions.peaksGoldenBuffer[cIDX] || + (cBar.high > cXConditions.peaksGoldenBuffer[cIDX] && + cXConditions.isSarSwitchedToBearish)) && + // + (cBar.open == cXConditions.xhkSMOpenBuffer[cIDX] || + (cBar.high > cXConditions.xhkSMHighBuffer[cIDX] && + cBar.GetUp() < cXConditions.xhkSMLowBuffer[cIDX])) && + // + cXConditions.isSarBearish + // + ) + // + ; + + // + // Filling Requirements ... + result = + isBullish || + isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + box.dir = dir; + box.to = TimeCurrent(); + box.symbol = cXConditions.symbol; + box.period = cXConditions.period; + + // + int fromIDX = -1; + if (isBullish) + { + // + double vale = cXConditions.valesBuffer[cIDX]; + box.lower = vale; + box.upper = cXConditions.valesGoldenBuffer[cIDX]; + + // + int lowerValeIDX = -1; + double lowerVale = cHelper + .mX121Helper + .xpvHelper + .GetLowerVale( + lowerValeIDX, + vale, + cBar.Index() // + ); + + // + int higherValeIDX = -1; + double higherVale = cHelper + .mX121Helper + .xpvHelper + .GetHigherVale( + higherValeIDX, + vale, + cBar.Index() // + ); + + // + if (IsValidIndex(lowerValeIDX) && + IsValidIndex(higherValeIDX)) + { + // + fromIDX = + lowerValeIDX < higherValeIDX + ? lowerValeIDX + : higherValeIDX; + } + else if (IsValidIndex(lowerValeIDX) && + !IsValidIndex(higherValeIDX)) + { + // + fromIDX = lowerValeIDX; + } + else if (!IsValidIndex(lowerValeIDX) && + IsValidIndex(higherValeIDX)) + { + // + fromIDX = higherValeIDX; + } + } + else + { + // + double peak = cXConditions.peaksBuffer[cIDX]; + box.upper = peak; + + // + box.lower = cXConditions.peaksGoldenBuffer[cIDX]; + + // + int lowerPeakIDX = -1; + double lowerPeak = cHelper + .mX121Helper + .xpvHelper + .GetLowerPeak( + lowerPeakIDX, + peak, + cBar.Index() // + ); + + // + int higherPeakIDX = -1; + double higherPeak = cHelper + .mX121Helper + .xpvHelper + .GetHigherPeak( + higherPeakIDX, + peak, + cBar.Index() // + ); + + // + if (IsValidIndex(lowerPeakIDX) && + IsValidIndex(higherPeakIDX)) + { + // + fromIDX = + lowerPeakIDX < higherPeakIDX + ? lowerPeakIDX + : higherPeakIDX; + } + else if (IsValidIndex(lowerPeakIDX) && + !IsValidIndex(higherPeakIDX)) + { + // + fromIDX = lowerPeakIDX; + } + else if (!IsValidIndex(lowerPeakIDX) && + IsValidIndex(higherPeakIDX)) + { + // + fromIDX = higherPeakIDX; + } + } + + // + if (IsValidIndex(fromIDX)) + { + // + box.from = iTime( + zBar.symbol, + zBar.period, + fromIDX // + ); + } + else + { + box.from = pBar.time; + } + + // + // Detect Holder Box ... + XBoxZone tmpBoxes[]; + if (chState.IsValid()) + { + // + if (isBullish) + { + // + // Demand Zones ... + XBoxZone tmp[]; + ToBox( + chState.demandZones, + tmp // + ); + Copy( + tmp, + tmpBoxes, + false // + ); + Clean(tmp); + + // + // Bullish Order Blocks ... + ToBox( + chState.bullishOrderBlocks, + tmp // + ); + Copy( + tmp, + tmpBoxes, + false // + ); + Clean(tmp); + + // + // Bullish Fair Value Gaps ... + ToBox( + chState.bullishFairValueGaps, + tmp // + ); + Copy( + tmp, + tmpBoxes, + false // + ); + Clean(tmp); + } + else + { + // + // Supply Zones ... + XBoxZone tmp[]; + ToBox( + chState.supplyZones, + tmp // + ); + Copy( + tmp, + tmpBoxes, + false // + ); + Clean(tmp); + + // + // Bearish Order Blocks ... + ToBox( + chState.bearishOrderBlocks, + tmp // + ); + Copy( + tmp, + tmpBoxes, + false // + ); + Clean(tmp); + + // + // Bearish Fair Value Gaps ... + ToBox( + chState.bearishFairValueGaps, + tmp // + ); + Copy( + tmp, + tmpBoxes, + false // + ); + Clean(tmp); + } + } + + // + has = HasChild(tmpBoxes); + if (has) + { + // + while (HasChild(tmpBoxes)) + { + // + idx = GetOldest(tmpBoxes); + has = IsValidIndex(idx); + if (!has) + { + break; + } + + // + XBoxZone iBox = tmpBoxes[idx]; + ArrayRemove( + tmpBoxes, + idx, + 1 // + ); + + // + has = IsBoxInside( + box, + iBox // + ); + if (has) + { + // + holderBox = iBox; + holderBox.to = TimeCurrent(); + iBox.Clean(); + break; + } + + // + iBox.Clean(); + } + } + + // + Clean(tmpBoxes); + + // + // Fix Box Upper and Lower based on Strategy ... + + // + double points = GetPoints(box.symbol); + double minPointsDiff = points * 20; + + // + double prefferSL = 0; + + // + // Other SL Conditions ... + if (prefferSL <= 0) + { + // + if (isBullish) + { + // + if (zBar.open < cXConditions.valesGoldenBuffer[cIDX]) + { + prefferSL = cXConditions.valesBuffer[cIDX]; + } + else if (zBar.open > cXConditions.valesGoldenBuffer[cIDX] && + zBar.open < cXConditions.peaksGoldenBuffer[cIDX]) + { + prefferSL = cXConditions.valesGoldenBuffer[cIDX]; + } + else if (zBar.open > cXConditions.peaksGoldenBuffer[cIDX]) + { + // + if (cXConditions.sarBuffer[cIDX] > cXConditions.peaksGoldenBuffer[cIDX]) + { + prefferSL = cXConditions.sarBuffer[cIDX]; + } + else + { + prefferSL = zBar.open > cXConditions.peaksGoldenBuffer[cIDX]; + } + } + } + else + { + // + if (zBar.open > cXConditions.peaksGoldenBuffer[cIDX]) + { + prefferSL = cXConditions.peaksBuffer[cIDX]; + } + else if (zBar.open < cXConditions.peaksGoldenBuffer[cIDX] && + zBar.open > cXConditions.valesGoldenBuffer[cIDX]) + { + prefferSL = cXConditions.peaksGoldenBuffer[cIDX]; + } + else if (zBar.open < cXConditions.valesGoldenBuffer[cIDX]) + { + // + if (cXConditions.sarBuffer[cIDX] < cXConditions.valesGoldenBuffer[cIDX]) + { + prefferSL = cXConditions.sarBuffer[cIDX]; + } + else + { + prefferSL = cXConditions.valesGoldenBuffer[cIDX]; + } + } + } + } + + // + if (prefferSL > 0) + { + // + box.upper = + isBullish + ? zBar.open + : prefferSL; + + // + box.lower = + isBullish + ? prefferSL + : zBar.open; + } + + // + // Validate Conditions to Force Has Holder Box ... + + result = + result && + holderBox.IsValid() && + dir == holderBox.dir; + + // + if (!result) + { + // + isBullish = false; + isBearish = false; + } + } + + // + // Check All Conditions ... + result = + box.IsValid() && + HasDirection(dir) && + (isBullish || + isBearish); + + // + // Cleanup Resources ... + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + cState.Clean(); + chState.Clean(); + ZeroMemory(cHelper); + cConditions.Clean(); + cXConditions.Clean(); + ZeroMemory(chHelper); + chConditions.Clean(); + chXConditions.Clean(); + + // + return result; + } + + // + bool HasSenario2Conditions( + ENUM_X_CYCLES ttfCycle, + XBoxZone &breakedBoxes[], + XBoxZone &box, + ENUM_X_DIRECTION &dir, + X121SMCStrategySignalProviderData &provider, + int barIndex = 0, + bool forceBarType = false, + bool forceFiboPressure = false // + ) + { + // + bool result = false; + + // + // Validate Args ... + result = + IsValid(ttfCycle) && + HasChild(breakedBoxes); + if (!result) + { + return result; + } + + // + // TODO: Add support for Extracting Trend ... + ENUM_X_DIRECTION trend = X_DIRECTION_NONE; + bool hasBullishTrend = IsBullish(trend); + bool hasBearishTrend = IsBearish(trend); + + // + // TTF Cycle Extract ... + XPOIState ttfState; + X121Conditions ttfXConditions; + XC121SMCCycleHelper *ttfHelper; + X121SMCCycleConditions ttfConditions; + result = provider.SelectCycle( + ttfCycle, + ttfState, + ttfXConditions, + ttfHelper, + ttfConditions // + ); + if (!result) + { + // + ttfState.Clean(); + ZeroMemory(ttfHelper); + ttfConditions.Clean(); + ttfXConditions.Clean(); + + // + return result; + } + Parse(ttfXConditions); + + // + // Normalize Args ... + + // + box.Clean(); + dir = X_DIRECTION_NONE; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + // Define Resources ... + + // + int idx = -1; + int count = 0; + bool has = false; + + // + int zIDX = barIndex; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + + // + double ask = GetAsk(ttfState.symbol); + double bid = GetBid(ttfState.symbol); + + // + bool isBullish = false; + bool isBearish = false; + + // + XOHCL zBar; + XOHCL cBar; + XOHCL pBar; + + // + // Initial Bars ... + result = zBar.Init( + ttfState.symbol, + ttfState.period, + barIndex // + ); + result = + result && + zBar.GetPreviousBar(cBar); + result = + result && + cBar.GetPreviousBar(pBar); + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + ttfState.Clean(); + ZeroMemory(ttfHelper); + ttfConditions.Clean(); + ttfXConditions.Clean(); + + // + return result; + } + + // + // Conditions ... + + // + // First we Have to Detect Inside Box ... + XBoxZone insideBox; + count = ArraySize(breakedBoxes); + for (int i = 0; i < count; i++) + { + // + XBoxZone iBox = breakedBoxes[i]; + + // + bool isInside = + IsInsideBox( + zBar, + iBox // + ); + if (isInside) + { + // + // Since we have to Follow Trend based on Breaked Boxes ... + // we have to use: + // - Breaked Bullish Boxes on Bearish Trend ... + // - Breaked Bearish Boxes on Bullish Trend ... + isInside = + hasBullishTrend + ? iBox.IsBearish() + : hasBearishTrend + ? iBox.IsBullish() + : false; + + // + // Check Inside ... + if (isInside) + { + // + insideBox = iBox; + iBox.Clean(); + + // + break; + } + } + + // + iBox.Clean(); + } + + // + // Check Inside Box is Valid or not ... + result = insideBox.IsValid(); + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + ttfState.Clean(); + insideBox.Clean(); + ZeroMemory(ttfHelper); + ttfConditions.Clean(); + ttfXConditions.Clean(); + } + + // + // Update Inside Box From and To ... + // Based on Breaked ... + insideBox.from = insideBox.to; + insideBox.to = TimeCurrent(); + + // + // Detect Breaked Box Direction ... + bool isInsideBoxBullish = insideBox.IsBullish(); + bool isInsideBoxBearish = insideBox.IsBearish(); + + // + // Detect Inside Box Rejection ... + + // + bool isUpperBearishReject = + cBar.high >= insideBox.upper && + cBar.GetUp() < insideBox.upper; + + // + bool isUpperBullishReject = + cBar.low <= insideBox.upper && + cBar.GetDown() > insideBox.upper; + + // + bool isLowerBearishReject = + cBar.high >= insideBox.lower && + cBar.GetUp() < insideBox.lower; + + // + bool isLowerBullishReject = + cBar.low <= insideBox.lower && + cBar.GetDown() > insideBox.lower; + + // + // Apply Force Bar Type ... + if (forceBarType) + { + // + isUpperBearishReject = + isUpperBearishReject && + cBar.IsBearish(); + + // + isUpperBullishReject = + isUpperBullishReject && + cBar.IsBullish(); + + // + isLowerBearishReject = + isLowerBearishReject && + cBar.IsBearish(); + + // + isLowerBullishReject = + isLowerBullishReject && + cBar.IsBullish(); + } + + // + // Apply Force Fibo Pressure ... + if (forceBarType) + { + // + isUpperBearishReject = + isUpperBearishReject && + ttfHelper + .mBarAnalyser + .HasFiboPressure( + cBar, + X_DIRECTION_BEARISH, + X_FIBO_LEVEL_382 // + ); + + // + isUpperBullishReject = + isUpperBullishReject && + ttfHelper + .mBarAnalyser + .HasFiboPressure( + cBar, + X_DIRECTION_BULLISH, + X_FIBO_LEVEL_382 // + ); + + // + isLowerBearishReject = + isLowerBearishReject && + ttfHelper + .mBarAnalyser + .HasFiboPressure( + cBar, + X_DIRECTION_BEARISH, + X_FIBO_LEVEL_382 // + ); + + // + isLowerBullishReject = + isLowerBullishReject && + ttfHelper + .mBarAnalyser + .HasFiboPressure( + cBar, + X_DIRECTION_BULLISH, + X_FIBO_LEVEL_382 // + ); + } + + // + // Bullish Conditions ... + isBullish = ( + // + hasBullishTrend && + isInsideBoxBearish && + isLowerBullishReject + // + ); + + // + // Bearish Conditions ... + isBearish = ( + // + hasBearishTrend && + isInsideBoxBullish && + isUpperBearishReject + // + ); + + // + // Filling Requirements ... + result = + isBullish || + isBearish; + if (result) + { + // + box = insideBox; + + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + } + + // + // Check All Conditions ... + result = + box.IsValid() && + HasDirection(dir) && + (isBullish || + isBearish // + ); + + // + // Cleanup Resource ... + + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + + // + ttfState.Clean(); + insideBox.Clean(); + ZeroMemory(ttfHelper); + ttfConditions.Clean(); + ttfXConditions.Clean(); + + // + return result; + } + + // + bool HasSenario4Conditions( + ENUM_X_CYCLES cycle, + XBoxZone &box, + XBoxZone &holderBox, + ENUM_X_DIRECTION &dir, + X121SMCStrategySignalProviderData &provider, + ENUM_X_CYCLES holderCycle = X_CYCLE_NONE, + int barIndex = 0 // + ) + { + // + bool result = false; + + // + // Fil Selected Data ... + XPOIState cState; + X121Conditions cXConditions; + XC121SMCCycleHelper *cHelper; + X121SMCCycleConditions cConditions; + result = provider.SelectCycle( + cycle, + cState, + cXConditions, + cHelper, + cConditions // + ); + if (!result) + { + // + cState.Clean(); + ZeroMemory(cHelper); + cConditions.Clean(); + cXConditions.Clean(); + + // + return result; + } + Parse(cXConditions); + + // + // Fil Selected Data ... + XPOIState chState; + X121Conditions chXConditions; + XC121SMCCycleHelper *chHelper; + X121SMCCycleConditions chConditions; + if (holderCycle != X_CYCLE_NONE) + { + // + result = provider.SelectCycle( + holderCycle, + chState, + chXConditions, + chHelper, + chConditions // + ); + if (!result) + { + // + chState.Clean(); + ZeroMemory(chHelper); + chConditions.Clean(); + chXConditions.Clean(); + + // + return result; + } + + // + Parse(chXConditions); + } + + // + // Normalize Args ... + + // + box.Clean(); + holderBox.Clean(); + dir = X_DIRECTION_NONE; + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int idx = -1; + int count = 0; + bool has = false; + + // + int zIDX = barIndex; + int cIDX = zIDX + 1; + int pIDX = cIDX + 1; + + // + bool isBullish = false; + bool isBearish = false; + + // + XOHCL zBar; + XOHCL cBar; + XOHCL pBar; + + // + // Initial Bars ... + result = zBar.Init( + cState.symbol, + cState.period, + barIndex // + ); + result = + result && + zBar.GetPreviousBar(cBar); + result = + result && + cBar.GetPreviousBar(pBar); + if (!result) + { + // + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + cState.Clean(); + chState.Clean(); + ZeroMemory(cHelper); + cConditions.Clean(); + cXConditions.Clean(); + ZeroMemory(chHelper); + chConditions.Clean(); + chXConditions.Clean(); + + // + return result; + } + + // + // Detecting Signal Conditions ... + + // + // Bullish Conditions ... + isBullish = + // + // Base Condition ... + ( + // + cBar.IsBullish() && + zBar.open >= cBar.close && + ( + // + // Regular Reject ... + (pBar.low > cBar.low && + cBar.low < cXConditions.valesGoldenBuffer[cIDX] && + cBar.GetDown() > cXConditions.valesGoldenBuffer[cIDX]) + // + || + // + // Regular Exit ... + (pBar.low < cXConditions.valesGoldenBuffer[cIDX] && + (cBar.low > cXConditions.valesGoldenBuffer[cIDX] || + cBar.GetUp() > cXConditions.valesGoldenBuffer[cIDX])) + // + || + // + IsBarBreak( + cXConditions.valesGoldenBuffer[cIDX], + X_DIRECTION_BULLISH, + cBar // + ) + // + || + // + IsBarReject( + cXConditions.valesGoldenBuffer[cIDX], + X_DIRECTION_BULLISH, + cBar // + ) + // + ) + // + ) + // + && + // + // Checking other Conditions ... + ( + // + // XSAR ... + cXConditions.isSarBullish && + // + // XSTR ... + cXConditions.isStrSwitchedToBullish && + // + // // X3MA ... + // // XVWAP ... + // (cXConditions.isX3MaFastOverMid || + // cXConditions.isVWapFastOverMid) && + // + // XHK ... + cXConditions.isSMHKBullish && + cXConditions.isRawHKBullish && + // + // XCHE ... + cXConditions.isCheBullish && + cXConditions.le1Buffer[cIDX] < cBar.low && + cXConditions.le2Buffer[cIDX] < cBar.low + // + ) + // + ; + + // + // Bearish Conditions ... + isBearish = + // + // Base Condition ... + ( + // + cBar.IsBearish() && + zBar.open <= cBar.close && + ( + // + // Regular Reject ... + (pBar.high < cBar.high && + cBar.high > cXConditions.peaksGoldenBuffer[cIDX] && + cBar.GetUp() < cXConditions.peaksGoldenBuffer[cIDX]) + // + || + // + // Regular Exit ... + (pBar.high > cXConditions.peaksGoldenBuffer[cIDX] && + (cBar.high < cXConditions.peaksGoldenBuffer[cIDX] || + cBar.GetDown() < cXConditions.peaksGoldenBuffer[cIDX])) + // + || + // + IsBarBreak( + cXConditions.peaksGoldenBuffer[cIDX], + X_DIRECTION_BEARISH, + cBar // + ) + // + || + // + IsBarReject( + cXConditions.peaksGoldenBuffer[cIDX], + X_DIRECTION_BEARISH, + cBar // + ) + // + ) + // + ) + // + && + // + // Checking other Conditions ... + ( + // + // XSAR ... + cXConditions.isSarBearish && + // + // XSTR ... + cXConditions.isStrSwitchedToBearish && + // + // // X3MA ... + // // XVWAP ... + // (cXConditions.isX3MaFastUnderMid || + // cXConditions.isVWapFastUnderMid) && + // + // XHK ... + cXConditions.isSMHKBearish && + cXConditions.isRawHKBearish && + // + // XCHE ... + cXConditions.isCheBearish && + cXConditions.se1Buffer[cIDX] > cBar.high && + cXConditions.se2Buffer[cIDX] > cBar.high + // + ) + // + ; + + // + // Filling Requirements ... + result = + isBullish || + isBearish; + if (result) + { + // + dir = + isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + box.dir = dir; + box.to = TimeCurrent(); + box.symbol = cXConditions.symbol; + box.period = cXConditions.period; + + // + int fromIDX = -1; + if (isBullish) + { + // + double vale = cXConditions.valesBuffer[cIDX]; + box.lower = vale; + box.upper = cXConditions.valesGoldenBuffer[cIDX]; + + // + int lowerValeIDX = -1; + double lowerVale = cHelper + .mX121Helper + .xpvHelper + .GetLowerVale( + lowerValeIDX, + vale, + cBar.Index() // + ); + + // + int higherValeIDX = -1; + double higherVale = cHelper + .mX121Helper + .xpvHelper + .GetHigherVale( + higherValeIDX, + vale, + cBar.Index() // + ); + + // + if (IsValidIndex(lowerValeIDX) && + IsValidIndex(higherValeIDX)) + { + // + fromIDX = + lowerValeIDX < higherValeIDX + ? lowerValeIDX + : higherValeIDX; + } + else if (IsValidIndex(lowerValeIDX) && + !IsValidIndex(higherValeIDX)) + { + // + fromIDX = lowerValeIDX; + } + else if (!IsValidIndex(lowerValeIDX) && + IsValidIndex(higherValeIDX)) + { + // + fromIDX = higherValeIDX; + } + } + else + { + // + double peak = cXConditions.peaksBuffer[cIDX]; + box.upper = peak; + + // + box.lower = cXConditions.peaksGoldenBuffer[cIDX]; + + // + int lowerPeakIDX = -1; + double lowerPeak = cHelper + .mX121Helper + .xpvHelper + .GetLowerPeak( + lowerPeakIDX, + peak, + cBar.Index() // + ); + + // + int higherPeakIDX = -1; + double higherPeak = cHelper + .mX121Helper + .xpvHelper + .GetHigherPeak( + higherPeakIDX, + peak, + cBar.Index() // + ); + + // + if (IsValidIndex(lowerPeakIDX) && + IsValidIndex(higherPeakIDX)) + { + // + fromIDX = + lowerPeakIDX < higherPeakIDX + ? lowerPeakIDX + : higherPeakIDX; + } + else if (IsValidIndex(lowerPeakIDX) && + !IsValidIndex(higherPeakIDX)) + { + // + fromIDX = lowerPeakIDX; + } + else if (!IsValidIndex(lowerPeakIDX) && + IsValidIndex(higherPeakIDX)) + { + // + fromIDX = higherPeakIDX; + } + } + + // + if (IsValidIndex(fromIDX)) + { + // + box.from = iTime( + zBar.symbol, + zBar.period, + fromIDX // + ); + } + else + { + box.from = pBar.time; + } + + // + // Detect Holder Box ... + XBoxZone tmpBoxes[]; + if (chState.IsValid()) + { + // + if (isBullish) + { + // + // Demand Zones ... + XBoxZone tmp[]; + ToBox( + chState.demandZones, + tmp // + ); + Copy( + tmp, + tmpBoxes, + false // + ); + Clean(tmp); + + // + // Bullish Order Blocks ... + ToBox( + chState.bullishOrderBlocks, + tmp // + ); + Copy( + tmp, + tmpBoxes, + false // + ); + Clean(tmp); + + // + // Bullish Fair Value Gaps ... + ToBox( + chState.bullishFairValueGaps, + tmp // + ); + Copy( + tmp, + tmpBoxes, + false // + ); + Clean(tmp); + } + else + { + // + // Supply Zones ... + XBoxZone tmp[]; + ToBox( + chState.supplyZones, + tmp // + ); + Copy( + tmp, + tmpBoxes, + false // + ); + Clean(tmp); + + // + // Bearish Order Blocks ... + ToBox( + chState.bearishOrderBlocks, + tmp // + ); + Copy( + tmp, + tmpBoxes, + false // + ); + Clean(tmp); + + // + // Bearish Fair Value Gaps ... + ToBox( + chState.bearishFairValueGaps, + tmp // + ); + Copy( + tmp, + tmpBoxes, + false // + ); + Clean(tmp); + } + } + + // + has = HasChild(tmpBoxes); + if (has) + { + // + while (HasChild(tmpBoxes)) + { + // + idx = GetOldest(tmpBoxes); + has = IsValidIndex(idx); + if (!has) + { + break; + } + + // + XBoxZone iBox = tmpBoxes[idx]; + ArrayRemove( + tmpBoxes, + idx, + 1 // + ); + + // + has = IsBoxInside( + box, + iBox // + ); + if (has) + { + // + holderBox = iBox; + holderBox.to = TimeCurrent(); + iBox.Clean(); + break; + } + + // + iBox.Clean(); + } + } + + // + Clean(tmpBoxes); + + // + // Validate Conditions to Force Has Holder Box ... + result = + result && + holderBox.IsValid(); + if (!result) + { + // + isBullish = false; + isBearish = false; + } + } + + // + // Check All Conditions ... + result = + box.IsValid() && + HasDirection(dir) && + (isBullish || + isBearish); + + // + // Cleanup Resources ... + zBar.Clean(); + cBar.Clean(); + pBar.Clean(); + cState.Clean(); + chState.Clean(); + ZeroMemory(cHelper); + cConditions.Clean(); + cXConditions.Clean(); + ZeroMemory(chHelper); + chConditions.Clean(); + chXConditions.Clean(); + + // + return result; + } + + \ No newline at end of file diff --git a/Documents/BKP/tmp.bar.anal.mq5 b/Documents/BKP/tmp.bar.anal.mq5 new file mode 100644 index 00000000..46a05f52 --- /dev/null +++ b/Documents/BKP/tmp.bar.anal.mq5 @@ -0,0 +1,5255 @@ + /** + * Detect Price Consolidation ... + * + * @param bar: XOHCL instance Reference, Start Bar ... + * @param loopback: Integer, Consolidation Length Finder ... + * @param consolidationRange: 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, + int consolidationRange = 50, + 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; + } + + // + 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; + } + + bool HasConsolidationZone( + XOHCL &bar, + XConsolidationZone &zone, + int minLoopback = 3, + double range = 50, + ENUM_APPLIED_PRICE upperAppliedTo = PRICE_HIGH, + ENUM_APPLIED_PRICE lowerAppliedTo = PRICE_LOW // + ) + { + // + bool result = false; + + // + zone.Clean(); + + // + result = bar.IsValid() && + minLoopback > 0 && + range > 0; + if (!result) + { + return result; + } + + // + double points = GetPoints(bar.symbol); + int index = bar.Index() + 1; + int length = minLoopback; + + // + double upperPrice[]; + int upperPriceCount = FillPrice( + upperPrice, + upperAppliedTo, + bar.symbol, + bar.period, + index, + length // + ); + + // + double lowerPrice[]; + int lowerPriceCount = FillPrice( + lowerPrice, + lowerAppliedTo, + bar.symbol, + bar.period, + index, + length // + ); + + // + result = upperPriceCount == lowerPriceCount && + lowerPriceCount == length; + if (!result) + { + // + Clean(upperPrice); + Clean(lowerPrice); + + // + return result; + } + + // + double upper = upperPrice[ArrayMaximum(upperPrice)]; + double lower = lowerPrice[ArrayMinimum(lowerPrice)]; + + // + bool isBullishBreake = + bar.low > lower && + bar.high > upper && + bar.GetUp() > upper; + bool isBearishBreake = + bar.high < upper && + bar.low < lower && + bar.GetDown() < lower; + result = isBullishBreake || + isBearishBreake; + if (!result) + { + // + Clean(upperPrice); + Clean(lowerPrice); + + // + return result; + } + + // + double delta = upper - lower; + result = delta <= range * points; + if (!result) + { + // + Clean(upperPrice); + Clean(lowerPrice); + + // + return result; + } + + // + while (delta <= range * points) + { + // + length++; + + // + upperPriceCount = FillPrice( + upperPrice, + upperAppliedTo, + bar.symbol, + bar.period, + index, + length // + ); + + // + lowerPriceCount = FillPrice( + lowerPrice, + lowerAppliedTo, + bar.symbol, + bar.period, + index, + length // + ); + + // + bool isValid = upperPriceCount == lowerPriceCount && + lowerPriceCount == length; + if (!isValid) + { + break; + } + + // + double iUpper = upperPrice[ArrayMaximum(upperPrice)]; + double iLower = lowerPrice[ArrayMinimum(lowerPrice)]; + + // + delta = iUpper - iLower; + if (delta <= range * points) + { + // + upper = iUpper; + lower = iLower; + } + } + + // + Clean(upperPrice); + Clean(lowerPrice); + + // + // Filling Zone ... + zone.upper = upper; + zone.lower = lower; + zone.symbol = bar.symbol; + zone.period = bar.period; + zone.to = iTime( + bar.symbol, + bar.period, + bar.Index() + 1 // + ); + zone.from = iTime( + bar.symbol, + bar.period, + bar.Index() + length // + ); + zone.dir = isBullishBreake + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = zone.IsValid(); + if (!result) + { + zone.Clean(); + } + + // + 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 Specified Bar is Swing or not ... + * + * @param bar: XOHCL instnce ... + * @param dir: ENUM_X_DIRECTION member ... + * @param range: Integer, Specified Range ... + * + * @return ( bool ) + */ + bool IsSwing( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + int range = 2 // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + + // + bool isSwingLow = IsSwingLow(bar, range); + bool isSwingHigh = IsSwingHigh(bar, range); + + // + result = isSwingLow || + isSwingHigh; + if (result) + { + // + if (isSwingLow) + { + dir = X_DIRECTION_BULLISH; + } + else + { + dir = X_DIRECTION_BEARISH; + } + } + + // + 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); + result = rangePercent > 0; + if (!result) + { + return result; + } + + // + 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 Has Support or not ... + * + * @param bar: XOHCL instance ... + * @param supportBar: XOHCL instance Specified Support Bar ... + * @param rage: int, + * @return ( bool ) + */ + bool HasSupport( + XOHCL &bar, + XOHCL &supportBar, + int range = 21 // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int barIndex = bar.Index() + range; + result = IsValidIndex(barIndex); + if (!result) + { + // + supportBar.Clean(); + return result; + } + result = supportBar.Init( + bar.symbol, + bar.period, + barIndex // + ); + + // + result = supportBar.low < supportBar.GetDown(); + if (!result) + { + // + supportBar.Clean(); + return result; + } + + // + double selectedValue = supportBar.GetDown(); + + // + int llIDX = bar.FindLowestIndex(range - 1, MODE_LOW); + result = IsValidIndex(llIDX); + if (!result) + { + // + supportBar.Clean(); + return result; + } + + // + double llValue = iLow( + bar.symbol, + bar.period, + llIDX // + ); + + // + result = llValue >= selectedValue; + if (!result) + { + // + supportBar.Clean(); + return result; + } + + // + result = supportBar.IsValid(); + + // + 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; + } + + /** + * Check a Bar Has Resistance or not ... + * + * @param bar: XOHCL instance ... + * @param resistanceBar: XOHCL instance Specified Resistance Bar ... + * @param rage: int, + * @return ( bool ) + */ + bool HasResistance( + XOHCL &bar, + XOHCL &resistanceBar, + int range = 21 // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int barIndex = bar.Index() + range; + result = IsValidIndex(barIndex); + if (!result) + { + // + resistanceBar.Clean(); + return result; + } + result = resistanceBar.Init( + bar.symbol, + bar.period, + barIndex // + ); + + // + result = resistanceBar.low < resistanceBar.GetDown(); + if (!result) + { + // + resistanceBar.Clean(); + return result; + } + + // + double selectedValue = resistanceBar.GetUp(); + + // + int hhIDX = bar.FindHighestIndex(range - 1, MODE_HIGH); + result = IsValidIndex(hhIDX); + if (!result) + { + // + resistanceBar.Clean(); + return result; + } + + // + double hhValue = iHigh( + bar.symbol, + bar.period, + hhIDX // + ); + + // + result = hhValue >= selectedValue; + if (!result) + { + // + resistanceBar.Clean(); + return result; + } + + // + result = resistanceBar.IsValid(); + + // + 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 + 1; + 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(); + int from = + index > (to + sameBars) + ? to + sameBars + : index; + 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; + } + + // + // Tools ... + + // + bool IsStrong( + XOHCL &bar, + double percent = 50 // Percent of Body + ) + { + // + bool result = false; + + // + result = bar.IsValid() && + bar.Index() > 0; + if (!result) + { + return result; + } + + // + result = + (bar.GetRange() * percent) / 100 <= bar.GetBody(); + + // + return result; + } + + // + bool HasStrongLowShadow( + XOHCL &bar, + double percent = 50, // Percent of Body + int __loopback = 2, + double _sharpRatio = 2.5 // + ) + { + // + bool result = false; + + // + result = bar.IsValid() && + bar.Index() > 0; + if (!result) + { + return result; + } + + // + result = + (bar.GetRange() * percent) / 100 <= bar.GetLowShadow(); + if (!result) + { + return result; + } + + // + if (__loopback < 0) + { + __loopback = 2; + } + + // + if (_sharpRatio < 0) + { + _sharpRatio = 2.5; + } + + // + result = bar.Index() > __loopback; + if (!result) + { + return result; + } + + // + // Get Highest High and Lowest Low in loopback Range ... + int startIndex = bar.Index() - __loopback; + int endIndex = bar.Index() + __loopback; + int requiredBars = MathAbs(endIndex - startIndex); + + // + // Highs ... + double highs[]; + int copiedHighs = CopyHigh( + bar.symbol, + bar.period, + startIndex, + requiredBars, + highs // + ); + + // + result = copiedHighs == requiredBars; + if (!result) + { + return result; + } + + // + int highestHighIDX = ArrayMaximum(highs); + result = IsValidIndex(highestHighIDX); + if (!result) + { + return result; + } + + // + double highestHigh = highs[highestHighIDX]; + + // + // Lows ... + double lows[]; + int copiedLows = CopyLow( + bar.symbol, + bar.period, + startIndex, + requiredBars, + lows // + ); + + // + result = copiedLows == requiredBars; + if (!result) + { + return result; + } + + // + int lowestLowIDX = ArrayMinimum(lows); + result = IsValidIndex(lowestLowIDX); + if (!result) + { + return result; + } + + // + double lowestLow = lows[lowestLowIDX]; + + // + result = bar.low == lowestLow && + highestHigh > bar.high; + if (!result) + { + return result; + } + + // + // Try to Validate Sharp Ratio ... + + // + Clean(highs); + Clean(lows); + + // + // Left Side ... + startIndex = bar.Index() + 1; + endIndex = startIndex + (__loopback / 2) - 1; + requiredBars = MathAbs(endIndex - startIndex); + + // + copiedHighs = CopyHigh( + bar.symbol, + bar.period, + startIndex, + requiredBars, + highs // + ); + result = copiedHighs == requiredBars; + if (!result) + { + return result; + } + + // + highestHighIDX = ArrayMaximum(highs); + result = IsValidIndex(highestHighIDX); + if (!result) + { + return result; + } + + // + highestHigh = highs[highestHighIDX]; + + // + copiedLows = CopyLow( + bar.symbol, + bar.period, + startIndex, + requiredBars, + lows // + ); + result = copiedLows == requiredBars; + if (!result) + { + return result; + } + + // + lowestLowIDX = ArrayMinimum(lows); + result = IsValidIndex(lowestLowIDX); + if (!result) + { + return result; + } + + // + lowestLow = lows[lowestLowIDX]; + + // + double leftDiff = highestHigh - lowestLow; + + // + Clean(highs); + Clean(lows); + + // + // Right Side ... + startIndex = bar.Index() - 1; + endIndex = startIndex - (__loopback / 2) + 1; + requiredBars = MathAbs(endIndex - startIndex); + + // + copiedHighs = CopyHigh( + bar.symbol, + bar.period, + startIndex, + requiredBars, + highs // + ); + result = copiedHighs == requiredBars; + if (!result) + { + return result; + } + + // + highestHighIDX = ArrayMaximum(highs); + result = IsValidIndex(highestHighIDX); + if (!result) + { + return result; + } + + // + highestHigh = highs[highestHighIDX]; + + // + copiedLows = CopyLow( + bar.symbol, + bar.period, + startIndex, + requiredBars, + lows // + ); + result = copiedLows == requiredBars; + if (!result) + { + return result; + } + + // + lowestLowIDX = ArrayMinimum(lows); + result = IsValidIndex(lowestLowIDX); + if (!result) + { + return result; + } + + // + lowestLow = lows[lowestLowIDX]; + + // + double rightDiff = highestHigh - lowestLow; + double diff = MathMax(leftDiff, rightDiff); + result = bar.GetLowShadow() >= (diff / 100) * _sharpRatio; + + // + return result; + } + + // + bool HasStrongHighShadow( + XOHCL &bar, + double percent = 50, // Percent of Body + int __loopback = 2, + double _sharpRatio = 2.5 // + ) + { + // + bool result = false; + + // + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + result = + (bar.GetRange() * percent) / 100 <= bar.GetHighShadow(); + if (!result) + { + return result; + } + + // + if (__loopback < 0) + { + __loopback = 2; + } + + // + if (_sharpRatio < 0) + { + _sharpRatio = 2.5; + } + + // + result = bar.Index() > __loopback; + if (!result) + { + return result; + } + + // + // Get Highest High and Lowest Low in loopback Range ... + int startIndex = bar.Index() - __loopback; + int endIndex = bar.Index() + __loopback; + int requiredBars = MathAbs(endIndex - startIndex); + + // + // Highs ... + double highs[]; + int copiedHighs = CopyHigh( + bar.symbol, + bar.period, + startIndex, + requiredBars, + highs // + ); + + // + result = copiedHighs == requiredBars; + if (!result) + { + return result; + } + + // + int highestHighIDX = ArrayMaximum(highs); + result = IsValidIndex(highestHighIDX); + if (!result) + { + return result; + } + + // + double highestHigh = highs[highestHighIDX]; + + // + // Lows ... + double lows[]; + int copiedLows = CopyLow( + bar.symbol, + bar.period, + startIndex, + requiredBars, + lows // + ); + + // + result = copiedLows == requiredBars; + if (!result) + { + return result; + } + + // + int lowestLowIDX = ArrayMinimum(lows); + result = IsValidIndex(lowestLowIDX); + if (!result) + { + return result; + } + + // + double lowestLow = lows[lowestLowIDX]; + + // + result = bar.high == highestHigh && + lowestLow < bar.low; + if (!result) + { + return result; + } + + // + // Try to Validate Sharp Ratio ... + + // + Clean(highs); + Clean(lows); + + // + // Left Side ... + startIndex = bar.Index() + 1; + endIndex = startIndex + (__loopback / 2) - 1; + requiredBars = MathAbs(endIndex - startIndex); + + // + copiedHighs = CopyHigh( + bar.symbol, + bar.period, + startIndex, + requiredBars, + highs // + ); + result = copiedHighs == requiredBars; + if (!result) + { + return result; + } + + // + highestHighIDX = ArrayMaximum(highs); + result = IsValidIndex(highestHighIDX); + if (!result) + { + return result; + } + + // + highestHigh = highs[highestHighIDX]; + + // + copiedLows = CopyLow( + bar.symbol, + bar.period, + startIndex, + requiredBars, + lows // + ); + result = copiedLows == requiredBars; + if (!result) + { + return result; + } + + // + lowestLowIDX = ArrayMinimum(lows); + result = IsValidIndex(lowestLowIDX); + if (!result) + { + return result; + } + + // + lowestLow = lows[lowestLowIDX]; + + // + double leftDiff = highestHigh - lowestLow; + + // + Clean(highs); + Clean(lows); + + // + // Right Side ... + startIndex = bar.Index() - 1; + endIndex = startIndex - (__loopback / 2) + 1; + requiredBars = MathAbs(endIndex - startIndex); + + // + copiedHighs = CopyHigh( + bar.symbol, + bar.period, + startIndex, + requiredBars, + highs // + ); + result = copiedHighs == requiredBars; + if (!result) + { + return result; + } + + // + highestHighIDX = ArrayMaximum(highs); + result = IsValidIndex(highestHighIDX); + if (!result) + { + return result; + } + + // + highestHigh = highs[highestHighIDX]; + + // + copiedLows = CopyLow( + bar.symbol, + bar.period, + startIndex, + requiredBars, + lows // + ); + result = copiedLows == requiredBars; + if (!result) + { + return result; + } + + // + lowestLowIDX = ArrayMinimum(lows); + result = IsValidIndex(lowestLowIDX); + if (!result) + { + return result; + } + + // + lowestLow = lows[lowestLowIDX]; + + // + double rightDiff = highestHigh - lowestLow; + double diff = MathMax(leftDiff, rightDiff); + result = bar.GetHighShadow() >= (diff / 100) * _sharpRatio; + + // + return result; + } + + // + bool IsStrongBullish( + XOHCL &bar, + double percent = 50 // Percent of Body + ) + { + // + bool result = false; + + // + result = + bar.IsValid() && + bar.IsBullish() && + IsStrong(bar, percent); + + // + return result; + } + + // + bool IsStrongBearish( + XOHCL &bar, + double percent = 50 // Percent of Body + ) + { + // + bool result = false; + + // + result = + bar.IsValid() && + bar.IsBearish() && + IsStrong(bar, percent); + + // + return result; + } + + // + bool IsSharpBullish( + XOHCL &bar, + int __loopback = 2, + double _sharpRatio = 2.5 // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + if (__loopback < 0) + { + __loopback = 2; + } + + // + if (_sharpRatio < 0) + { + _sharpRatio = 2.5; + } + + // + int hIDX = bar.FindHighestIndex( + __loopback, + MODE_HIGH // + ); + int lIDX = bar.FindLowestIndex( + __loopback, + MODE_LOW // + ); + + // + result = + // + hIDX >= 0 && + lIDX >= 0 && + MathAbs(hIDX - bar.Index()) < 2 + // + ; + + // + if (!result) + { + return result; + } + + // + XOHCL hBar; + result = hBar.Init( + bar.symbol, + bar.period, + hIDX // + ); + if (!result) + { + return result; + } + + // + XOHCL lBar; + result = lBar.Init( + bar.symbol, + bar.period, + lIDX // + ); + if (!result) + { + return result; + } + + // + double lhDif = hBar.high - lBar.low; + + // + int hhIDX = hBar.FindHighestIndex( + __loopback, + MODE_HIGH // + ); + + // + int llIDX = lBar.FindLowestIndex( + __loopback, + MODE_LOW // + ); + + // + XOHCL hhBar; + result = hhBar.Init( + bar.symbol, + bar.period, + hhIDX + hIDX // + ); + if (!result) + { + return result; + } + + // + XOHCL llBar; + result = llBar.Init( + bar.symbol, + bar.period, + llIDX + lIDX // + ); + if (!result) + { + return result; + } + + // + double llhhDif = hhBar.high - llBar.low; + + // + result = + // + lBar.low > llBar.low && + hBar.high > hhBar.high && + lhDif >= llhhDif * _sharpRatio + // + ; + + // + return result; + } + + // + bool IsSharpBearish( + XOHCL &bar, + int __loopback = 2, + double _sharpRatio = 2.5 // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + if (__loopback < 0) + { + __loopback = 2; + } + + // + if (_sharpRatio < 0) + { + _sharpRatio = 2.5; + } + + // + int hIDX = bar.FindHighestIndex( + __loopback, + MODE_HIGH // + ); + int lIDX = bar.FindLowestIndex( + __loopback, + MODE_LOW // + ); + + // + result = + // + hIDX >= 0 && + lIDX >= 0 && + MathAbs(hIDX - bar.Index()) < 2 + // + ; + + // + if (!result) + { + return result; + } + + // + XOHCL hBar; + result = hBar.Init( + bar.symbol, + bar.period, + hIDX // + ); + if (!result) + { + return result; + } + + // + XOHCL lBar; + result = lBar.Init( + bar.symbol, + bar.period, + lIDX // + ); + if (!result) + { + return result; + } + + // + double lhDif = hBar.high - lBar.low; + + // + int hhIDX = hBar.FindHighestIndex( + __loopback, + MODE_HIGH // + ); + + // + int llIDX = lBar.FindLowestIndex( + __loopback, + MODE_LOW // + ); + + // + XOHCL hhBar; + result = hhBar.Init( + bar.symbol, + bar.period, + hhIDX + hIDX // + ); + if (!result) + { + return result; + } + + // + XOHCL llBar; + result = llBar.Init( + bar.symbol, + bar.period, + llIDX + lIDX // + ); + if (!result) + { + return result; + } + + // + double llhhDif = hhBar.high - llBar.low; + + // + result = + // + lBar.low < llBar.low && + hBar.high < hhBar.high && + lhDif >= llhhDif * _sharpRatio + // + ; + + // + return result; + } + + // + // + // + + // + // Retrieve Bullish Pressure ... + double GetBullishPressure( + XOHCL &bar, + int __loopback = 7 // + ) + { + // + double result = 0; + + // + if (!bar.IsValid()) + { + return result; + } + + // + XOHCL bars[]; + int barsCount = GetBars( + bars, + bar.symbol, + bar.period, + bar.Index(), + __loopback // + ); + if (!IsValidSize(barsCount)) + { + return result; + } + + // + for (int i = 0; i < barsCount; i++) + { + result += bars[i].GetLowShadow(); + } + + // + return result; + } + + // + // Retrieve Bearish Pressure ... + double GetBearishPressure( + XOHCL &bar, + int __loopback = 7 // + ) + { + // + double result = 0; + + // + if (!bar.IsValid()) + { + return result; + } + + // + XOHCL bars[]; + int barsCount = GetBars( + bars, + bar.symbol, + bar.period, + bar.Index(), + __loopback // + ); + if (!IsValidSize(barsCount)) + { + return result; + } + + // + for (int i = 0; i < barsCount; i++) + { + result += bars[i].GetHighShadow(); + } + + // + return result; + } + + // + bool HasBullishPressure( + XOHCL &bar, + int __loopback = 7 // + ) + { + // + bool result = false; + + // + if (__loopback < 0) + { + __loopback = 7; + } + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + double bullishPressure = GetBullishPressure(bar, __loopback); + double bearishPressure = GetBearishPressure(bar, __loopback); + + // + result = + // + bullishPressure > 0 && + bearishPressure >= 0 && + bullishPressure > bearishPressure + // + ; + + // + return result; + } + + // + bool HasBearishPressure( + XOHCL &bar, + int __loopback = 7 // + ) + { + // + bool result = false; + + // + if (__loopback < 0) + { + __loopback = 7; + } + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + double bullishPressure = GetBullishPressure(bar, __loopback); + double bearishPressure = GetBearishPressure(bar, __loopback); + + // + result = + // + bearishPressure > 0 && + bullishPressure >= 0 && + bearishPressure > bullishPressure + // + ; + + // + return result; + } + + // + // Retrieve Bullish Power ... + double GetBullishPower( + XOHCL &bar, + int __loopback = 7 // + ) + { + // + double result = 0; + + // + if (!bar.IsValid()) + { + return result; + } + + // + XOHCL bars[]; + int barsCount = GetBars( + bars, + bar.symbol, + bar.period, + bar.Index(), + __loopback // + ); + if (!IsValidSize(barsCount)) + { + return result; + } + + // + for (int i = 0; i < barsCount; i++) + { + // + if (bars[i].IsBullish()) + { + result += bars[i].GetBody(); + } + } + + // + return result; + } + + // + // Retrieve Bearish Pressure ... + double GetBearishPower( + XOHCL &bar, + int __loopback = 7 // + ) + { + // + double result = 0; + + // + if (!bar.IsValid()) + { + return result; + } + + // + XOHCL bars[]; + int barsCount = GetBars( + bars, + bar.symbol, + bar.period, + bar.Index(), + __loopback // + ); + if (!IsValidSize(barsCount)) + { + return result; + } + + // + for (int i = 0; i < barsCount; i++) + { + // + if (bars[i].IsBearish()) + { + result += bars[i].GetBody(); + } + } + + // + return result; + } + + // + bool HasBullishPower( + XOHCL &bar, + int __loopback = 7 // + ) + { + // + bool result = false; + + // + if (__loopback < 0) + { + __loopback = 7; + } + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + double bullishPressure = GetBullishPower(bar, __loopback); + double bearishPressure = GetBearishPower(bar, __loopback); + + // + result = + // + bullishPressure > 0 && + bearishPressure >= 0 && + bullishPressure > bearishPressure + // + ; + + // + return result; + } + + // + bool HasBearishPower( + XOHCL &bar, + int __loopback = 7 // + ) + { + // + bool result = false; + + // + if (__loopback < 0) + { + __loopback = 7; + } + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + double bullishPressure = GetBullishPower(bar, __loopback); + double bearishPressure = GetBearishPower(bar, __loopback); + + // + result = + // + bearishPressure > 0 && + bullishPressure >= 0 && + bearishPressure > bullishPressure + // + ; + + // + return result; + } + + // + // Decisions ... + + // + bool IsBullishDecision( + XOHCL &bar, + double percent = 70 // Percent of Body + ) + { + // + bool result = false; + + // + result = + // + bar.IsValid() && + bar.Index() > 0 && + bar.IsBullish() && + (bar.GetRange() * percent) / 100 <= bar.GetBody() + // + ; + + // + return result; + } + + // + bool IsBearishDecision( + XOHCL &bar, + double percent = 70 // Percent of Body + ) + { + // + bool result = false; + + // + result = + // + bar.IsValid() && + bar.Index() > 0 && + bar.IsBearish() && + (bar.GetRange() * percent) / 100 <= bar.GetBody() + // + ; + + // + return result; + } + + // + // Candlestic Patterns ... + + // + // Check Doji ... + bool IsDoji( + XOHCL &bar // + ) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + result = bar.open == bar.close; + + // + return result; + } + + // + // Check Hammer ... + bool IsHammer( + XOHCL &bar, + double _upShadowFactor = 0.1, + double _downShadowFactor = 0.6, + bool applyFib382Check = true, + bool applyPrevShadowCheck = true // + ) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + if (_upShadowFactor < 0) + { + _upShadowFactor = 0.1; + } + + // + if (_downShadowFactor < 0) + { + _upShadowFactor = 0.6; + } + + // + double range = bar.GetRange(); + + // + // Check Upper Shadow Must be 0 or Under 10% ... + double upShadow = bar.GetHighShadow(); + result = upShadow < range * _upShadowFactor; + if (!result) + { + return result; + } + + // + // Check Down Shadow Must at least 60% ... + double downShadow = bar.GetLowShadow(); + result = downShadow > range * _downShadowFactor; + if (!result) + { + return result; + } + + // + // Check Fib 382 ... + if (result && applyFib382Check) + { + // + double fib382 = GetFibonacciLevel( + bar.high, + bar.low, + 0.382, + -1 // + ); + result = bar.GetDown() > fib382; + } + + // + // Check Shadow Based on Prev Bar ... + if (result && applyPrevShadowCheck) + { + // + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + result = bar.low < pBar.low; + } + + // + return result; + } + + // + // Check Sgooting Star ... + // Reversal Hammer ... + bool IsShootingStar( + XOHCL &bar, + double _upShadowFactor = 0.6, + double _downShadowFactor = 0.1, + bool applyFib382Check = true, + bool applyPrevShadowCheck = true // + ) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + if (_upShadowFactor < 0) + { + _upShadowFactor = 0.6; + } + + // + if (_downShadowFactor < 0) + { + _upShadowFactor = 0.1; + } + + // + double range = bar.GetRange(); + + // + // Check Upper Shadow Must be 0 or Under 10% ... + double upShadow = bar.GetHighShadow(); + result = upShadow > range * _upShadowFactor; + if (!result) + { + return result; + } + + // + // Check Down Shadow Must at least 60% ... + double downShadow = bar.GetLowShadow(); + result = downShadow < range * _downShadowFactor; + if (!result) + { + return result; + } + + // + // Check Fib 382 ... + if (result && applyFib382Check) + { + // + double fib382 = GetFibonacciLevel( + bar.high, + bar.low, + 0.382, + 1 // + ); + result = bar.GetUp() < fib382; + } + + // + // Check Shadow Based on Prev Bar ... + if (result && applyPrevShadowCheck) + { + // + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + result = bar.high > pBar.high; + } + + // + return result; + } + + // + // Check Bullish Engulfing ... + bool IsBullishEngulfing( + XOHCL &bar, + double _engulfBarBodyFactor = 0.7 // + ) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + if (_engulfBarBodyFactor < 0) + { + _engulfBarBodyFactor = 0.7; + } + + // + // Check Bar Is Bullish ... + result = bar.IsBullish(); + if (!result) + { + return result; + } + + // + // Retrieve Previous Bar ... + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + double range = bar.GetRange(); + double body = bar.GetBody(); + + // + // Check Prev Bar Must Bearish ... + result = pBar.IsBearish(); + if (!result) + { + return result; + } + + // + // Check Shadows Engulf Prev Bar ... + result = + // + bar.high > pBar.high && + bar.low <= pBar.low + // + ; + if (!result) + { + return result; + } + + // + // Check Engulfed Bar Must Inside Engulfer Body ... + result = + // + bar.GetUp() > pBar.GetUp() && + bar.GetDown() < pBar.GetDown() + // + ; + if (!result) + { + return result; + } + + // + // Check Body of Engulfing Bar ... + if (result && _engulfBarBodyFactor > 0) + { + result = body >= range * _engulfBarBodyFactor; + } + + // + return result; + } + + // + // Check Bearish Engulfing ... + bool IsBearishEngulfing( + XOHCL &bar, + double _engulfBarBodyFactor = 0.7 // + ) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + if (_engulfBarBodyFactor < 0) + { + _engulfBarBodyFactor = 0.7; + } + + // + // Check Bar Is Bearish ... + result = bar.IsBearish(); + if (!result) + { + return result; + } + + // + // Retrieve Previous Bar ... + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + double range = bar.GetRange(); + double body = bar.GetBody(); + + // + // Check Prev Bar Must Bullish ... + result = pBar.IsBullish(); + if (!result) + { + return result; + } + + // + // Check Shadows Engulf Prev Bar ... + result = bar.high >= pBar.high && + bar.low < pBar.low; + if (!result) + { + return result; + } + + // + // Check Engulfed Bar Must Inside Engulfer Body ... + result = + // + bar.GetUp() > pBar.GetUp() && + bar.GetDown() < pBar.GetDown() + // + ; + if (!result) + { + return result; + } + + // + // Check Body of Engulfing Bar ... + if (result && _engulfBarBodyFactor > 0) + { + result = body >= range * _engulfBarBodyFactor; + } + + // + return result; + } + + // + // Check Morning Star Pattern ... + bool IsMorningStar( + XOHCL &bar, + double _middleRangeFactor = 0.3, + double _startBodyFactor = 0.6, + bool forceCheckMiddleBarDirection = true, + bool forceCheckStartBody = true // + ) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + if (_middleRangeFactor < 0) + { + _middleRangeFactor = 0.3; + } + + // + if (_startBodyFactor < 0) + { + _startBodyFactor = 0.6; + } + + // + // Current Bar Must be Bullish ... + result = bar.IsBullish(); + if (!result) + { + return result; + } + + // + // Retrieve Previous Bar ... + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + // Prev Bar must be Bearish ... + if (result && forceCheckMiddleBarDirection) + { + // + result = pBar.IsBearish(); + if (!result) + { + return result; + } + } + + // + // Retrieve Previous Bar of Prev Bar ... + XOHCL ppBar; + result = pBar.GetPreviousBar(ppBar); + if (!result) + { + return result; + } + + // + // Prev Of Prev Bar Must be Bearish ... + result = ppBar.IsBearish(); + if (!result) + { + return result; + } + + // + double range = bar.GetRange(); + double pRange = pBar.GetRange(); + double ppRange = ppBar.GetRange(); + + // + // Middle Bar must be Smaller than Ratio of other ... + result = + // + pRange < range * _middleRangeFactor && + pRange < ppRange * _middleRangeFactor + // + ; + if (!result) + { + return result; + } + + // + if (result && forceCheckStartBody) + { + // + result = ppBar.GetBody() > ppRange * _startBodyFactor; + if (!result) + { + return result; + } + } + + // + return result; + } + + // + // Check Evening Star Pattern ... + bool IsEveningStar( + XOHCL &bar, + double _middleRangeFactor = 0.3, + double _startBodyFactor = 0.6, + bool forceCheckMiddleBarDirection = true, + bool forceCheckStartBody = true // + ) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + if (_middleRangeFactor < 0) + { + _middleRangeFactor = 0.3; + } + + // + if (_startBodyFactor < 0) + { + _startBodyFactor = 0.6; + } + + // + // Current Bar Must be Bearish ... + result = bar.IsBearish(); + if (!result) + { + return result; + } + + // + // Retrieve Previous Bar ... + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + // Prev Bar must be Bullish ... + if (result && forceCheckMiddleBarDirection) + { + // + result = pBar.IsBullish(); + if (!result) + { + return result; + } + } + + // + // Retrieve Previous Bar of Prev Bar ... + XOHCL ppBar; + result = pBar.GetPreviousBar(ppBar); + if (!result) + { + return result; + } + + // + // Prev Of Prev Bar Must be Bullish ... + result = ppBar.IsBullish(); + if (!result) + { + return result; + } + + // + double range = bar.GetRange(); + double pRange = pBar.GetRange(); + double ppRange = ppBar.GetRange(); + + // + // Middle Bar must be Smaller than Ratio of other ... + result = + // + pRange < range * _middleRangeFactor && + pRange < ppRange * _middleRangeFactor + // + ; + if (!result) + { + return result; + } + + // + if (result && forceCheckStartBody) + { + // + result = ppBar.GetBody() > ppRange * _startBodyFactor; + if (!result) + { + return result; + } + } + + // + return result; + } + + // + // Bullish Marubozu ... + bool IsBullishMarubozu(XOHCL &bar) + { + // + bool result = false; + + // + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + result = bar.IsBullish(); + if (!result) + { + return result; + } + + // + result = + // + bar.GetUp() == bar.high && + bar.GetDown() == bar.low + // + ; + + // + return result; + } + + // + // Bearish Marubozu ... + bool IsBearishMarubozu(XOHCL &bar) + { + // + bool result = false; + + // + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + result = bar.IsBearish(); + if (!result) + { + return result; + } + + // + result = + // + bar.GetUp() == bar.high && + bar.GetDown() == bar.low + // + ; + + // + return result; + } + + // + // Contextual Patterns ... + + // + // Check Swing High ... + bool IsBarSwingHigh(XOHCL &bar) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + // Current Bar Must be Bearish ... + result = bar.IsBearish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev Bar ... + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + // Prev Bar Must be Bullish ... + result = pBar.IsBullish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev of Prev Bar ... + XOHCL ppBar; + result = pBar.GetPreviousBar(ppBar); + if (!result) + { + return result; + } + + // + // Prev of Prev Bar Must be Bullish ... + result = ppBar.IsBullish(); + if (!result) + { + return result; + } + + // + // Check All Highs ... + result = + // + bar.high < pBar.high && + pBar.high > ppBar.high + // + ; + + // + return result; + } + + // + // Find Simple 3 Candle Based Swing High ... + bool IsSimpleSwingHigh( + XOHCL &bar, + double thresholdInPoint = 1 // + ) + { + // + bool result = false; + + // + int index = bar.Index(); + result = index > 0; + if (!result) + { + return result; + } + + // + XOHCL nextBar; + result = bar.GetNextBar(nextBar); + if (!result) + { + return result; + } + + // + XOHCL prevBar; + result = bar.GetPreviousBar(prevBar); + if (!result) + { + return result; + } + + // + double point = GetPoints(bar.symbol); + double requiredOffset = point * thresholdInPoint; + + // + result = + bar.high > nextBar.high && + bar.high > prevBar.high && + (thresholdInPoint <= 0 + ? true + : MathAbs( + MathMax( + nextBar.high, + prevBar.high) - + bar.high) >= requiredOffset); + + // + return result; + } + + // + // Find Last Swing High ... + bool FindLastSwingHigh( + XOHCL &bar, + XOHCL &swing // + ) + { + // + bool result = false; + + // + swing.Clean(); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int totalBars = iBars( + bar.symbol, + bar.period // + ); + int maxAllowed = MathMin(100, (totalBars / 100)); + + // + int idx = bar.Index(); + for (int i = idx; i <= idx + maxAllowed; i++) + { + // + swing.Clean(); + result = swing.Init( + bar.symbol, + bar.period, + i // + ); + if (!result) + { + // + swing.Clean(); + break; + } + + // + result = IsBarSwingHigh(swing); + if (result) + { + break; + } + } + + // + return result; + } + + // + // Check Swing Low ... + bool IsBarSwingLow(XOHCL &bar) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + // Current Bar Must be Bullish ... + result = bar.IsBullish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev Bar ... + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + // Prev Bar Must be Bearish ... + result = pBar.IsBearish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev of Prev Bar ... + XOHCL ppBar; + result = pBar.GetPreviousBar(ppBar); + if (!result) + { + return result; + } + + // + // Prev of Prev Bar Must be Bearish ... + result = ppBar.IsBearish(); + if (!result) + { + return result; + } + + // + // Check All Lows ... + result = + // + bar.low > pBar.low && + pBar.low < ppBar.low + // + ; + + // + return result; + } + + // + // Find Simple 3 Candle Based Swing Low ... + bool IsSimpleSwingLow( + XOHCL &bar, + double thresholdInPoint = 1 // + ) + { + // + bool result = false; + + // + int index = bar.Index(); + result = index > 0; + if (!result) + { + return result; + } + + // + XOHCL nextBar; + result = bar.GetNextBar(nextBar); + if (!result) + { + return result; + } + + // + XOHCL prevBar; + result = bar.GetPreviousBar(prevBar); + if (!result) + { + return result; + } + + // + double point = GetPoints(bar.symbol); + double requiredOffset = point * thresholdInPoint; + + // + result = + bar.low < nextBar.low && + bar.low < prevBar.low && + (thresholdInPoint <= 0 + ? true + : MathAbs( + MathMax( + nextBar.low, + prevBar.low) - + bar.low) >= requiredOffset); + + // + return result; + } + + // + // Find Last Swing Low ... + bool FindLastSwingLow( + XOHCL &bar, + XOHCL &swing // + ) + { + // + bool result = false; + + // + swing.Clean(); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int totalBars = iBars( + bar.symbol, + bar.period // + ); + int maxAllowed = MathMin(100, (totalBars / 100)); + + // + int idx = bar.Index(); + for (int i = idx; i <= idx + maxAllowed; i++) + { + // + swing.Clean(); + result = swing.Init( + bar.symbol, + bar.period, + i // + ); + if (!result) + { + // + swing.Clean(); + break; + } + + // + result = IsBarSwingLow(swing); + if (result) + { + break; + } + } + + // + return result; + } + + // + // Check Bullish FVG ... + bool HasBullishFVG( + XOHCL &bar, + double &upper, + double &lower, + datetime &start, + datetime &end, + bool forceMiddleBarCheck = true, + bool forceCheckLastBarDirection = false // + ) + { + // + bool result = false; + + // + upper = 0; + lower = 0; + + // + end = NULL; + start = NULL; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + // Current Bar Must be Bullish ... + result = + !forceCheckLastBarDirection + ? true + : bar.IsBullish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev Bar ... + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + // Prev Bar Must be Bullish ... + result = pBar.IsBullish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev of Prev Bar ... + XOHCL ppBar; + result = pBar.GetPreviousBar(ppBar); + if (!result) + { + return result; + } + + // + // Prev of Prev Bar Must be Bullish ... + result = ppBar.IsBullish(); + if (!result) + { + return result; + } + + // + // Other Conditions ... + result = + // + bar.low > ppBar.high + // + ; + + // + // Check Middle Bar Range ... + if (result && forceMiddleBarCheck) + { + // + result = + // + pBar.high > bar.low && + pBar.low < ppBar.high + // + ; + + // + if (!result) + { + return result; + } + } + + // + if (result) + { + // + end = bar.time; + upper = bar.low; + lower = ppBar.high; + start = ppBar.time; + } + + // + return result; + } + + // + // Check Bearish FVG ... + bool HasBearishFVG( + XOHCL &bar, + double &upper, + double &lower, + datetime &start, + datetime &end, + bool forceMiddleBarCheck = true, + bool forceCheckLastBarDirection = false // + ) + { + // + bool result = false; + + // + upper = 0; + lower = 0; + + // + end = NULL; + start = NULL; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + // Current Bar Must be Bearish ... + result = + !forceCheckLastBarDirection + ? true + : bar.IsBullish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev Bar ... + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + // Prev Bar Must be Bearish ... + result = pBar.IsBearish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev of Prev Bar ... + XOHCL ppBar; + result = pBar.GetPreviousBar(ppBar); + if (!result) + { + return result; + } + + // + // Prev of Prev Bar Must be Bearish ... + result = ppBar.IsBearish(); + if (!result) + { + return result; + } + + // + // Other Conditions ... + result = + // + bar.high < ppBar.low + // + ; + + // + // Check Middle Bar Range ... + if (result && forceMiddleBarCheck) + { + // + result = + // + pBar.high > bar.low && + pBar.low < ppBar.high + // + ; + + // + if (!result) + { + return result; + } + } + + // + if (result) + { + // + end = bar.time; + lower = bar.high; + upper = ppBar.low; + start = ppBar.time; + } + + // + return result; + } + + // + // Find Support ... + bool HasSupport( + XOHCL &bar, + XOHCL &dest, + ENUM_X_PRICE type = X_PRICE_CLOSE, + int _loopback = 21, + int tries = 100 // + ) + { + // + bool result = false; + + // + dest.Clean(); + + // + if (_loopback < 0) + { + _loopback = 21; + } + + // + if (tries < 0) + { + tries = 100; + } + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + double price = bar.GetPrice(type); + + // + for (int i = 1; i < tries; i++) + { + // + int _length = _loopback * i; + + // + int lowestIDX = bar.FindLowestIndex( + _length, + MODE_LOW // + ); + result = IsValidIndex(lowestIDX); + if (!result) + { + break; + } + + // + XOHCL iLBar; + result = iLBar.Init( + bar.symbol, + bar.period, + lowestIDX // + ); + if (!result) + { + break; + } + + // + result = + // + price > iLBar.high + // + ; + if (result) + { + // + dest = iLBar; + break; + } + } + + // + result = dest.IsValid(); + + // + return result; + } + + // + // Find Resistance ... + bool HasResistance( + XOHCL &bar, + XOHCL &dest, + ENUM_X_PRICE type = X_PRICE_CLOSE, + int _loopback = 21, + int tries = 100 // + ) + { + // + bool result = false; + + // + dest.Clean(); + + // + if (_loopback < 0) + { + _loopback = 21; + } + + // + if (tries < 0) + { + tries = 100; + } + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + double price = bar.GetPrice(type); + + // + for (int i = 1; i < tries; i++) + { + // + int _length = _loopback * i; + + // + int highestIDX = bar.FindHighestIndex( + _length, + MODE_LOW // + ); + result = IsValidIndex(highestIDX); + if (!result) + { + break; + } + + // + XOHCL iHBar; + result = iHBar.Init( + bar.symbol, + bar.period, + highestIDX // + ); + if (!result) + { + break; + } + + // + result = + // + price < iHBar.high + // + ; + if (result) + { + // + dest = iHBar; + break; + } + } + + // + result = dest.IsValid(); + + // + return result; + } + + // + // Trend Detection ... + + // + // Find Bullish Trend ... + bool HasBullishTrend( + XOHCL &bar, + XOHCL &highSwingBars[], + XOHCL &lowSwingBars[], + bool forceMethod2 = false, + int _loopback = 3, + int tries = 3, + ENUM_X_PRICE type = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + Clean(lowSwingBars); + Clean(highSwingBars); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + double price = bar.GetPrice(type); + + // + int lastIDX = bar.Index(); + double lastH = 0; + double lastL = 0; + for (int i = 1; i < tries + 1; i++) + { + // + // Use Regular Method ... + if (!forceMethod2) + { + // + int iHIDX = FindSwing( + bar.symbol, + bar.period, + X_SWING_HIGH, + _loopback, + lastIDX // + ); + result = IsValidIndex(iHIDX); + if (!result) + { + break; + } + + // + XOHCL iHBar; + result = iHBar.Init( + bar.symbol, + bar.period, + iHIDX // + ); + if (!result) + { + break; + } + + // + double iH = iHBar.high; + bool isIHAccepted = + // + iH > 0 && + ( + // + lastH == 0 + ? true + : iH < lastH + // + ) + // + ; + if (isIHAccepted) + { + // + AddRef( + iHBar, + highSwingBars // + ); + + // + lastH = iH; + lastIDX = iHIDX; + } + + // + int iLIDX = FindSwing( + bar.symbol, + bar.period, + X_SWING_LOW, + _loopback, + lastIDX // + ); + result = IsValidIndex(iLIDX); + if (!result) + { + break; + } + + // + XOHCL iLBar; + result = iLBar.Init( + bar.symbol, + bar.period, + iLIDX // + ); + if (!result) + { + break; + } + + // + double iL = iLBar.low; + bool isILAccepted = + // + iL > 0 && + ( + // + lastL == 0 + ? true + : iL < lastL + // + ) + // + ; + if (isILAccepted) + { + // + AddRef( + iLBar, + lowSwingBars // + ); + + // + lastL = iL; + lastIDX = iLIDX; + } + } + // + // Use Other MEthod ... + else + { + // + int _length = i * _loopback; + int start = + // + i == 1 + ? 1 + : _length - _loopback + // + ; + + // + int iHIDX = iHighest( + bar.symbol, + bar.period, + MODE_HIGH, + _loopback, + start // + ); + result = IsValidIndex(iHIDX); + if (!result) + { + break; + } + + // + XOHCL iHBar; + result = iHBar.Init( + bar.symbol, + bar.period, + iHIDX // + ); + if (!result) + { + break; + } + + // + double iH = iHBar.high; + bool isIHAccepted = + // + iH > 0 && + ( + // + lastH == 0 + ? true + : iH < lastH + // + ) + // + ; + if (isIHAccepted) + { + // + AddRef( + iHBar, + highSwingBars // + ); + + // + lastH = iH; + lastIDX = iHIDX; + } + + // + int iLIDX = iLowest( + bar.symbol, + bar.period, + MODE_LOW, + _loopback, + start // + ); + result = IsValidIndex(iLIDX); + if (!result) + { + break; + } + + // + XOHCL iLBar; + result = iLBar.Init( + bar.symbol, + bar.period, + iLIDX // + ); + if (!result) + { + break; + } + + // + double iL = iLBar.low; + bool isILAccepted = + // + iL > 0 && + ( + // + lastL == 0 + ? true + : iL < lastL + // + ) + // + ; + if (isILAccepted) + { + // + AddRef( + iLBar, + lowSwingBars // + ); + + // + lastL = iL; + lastIDX = iLIDX; + } + } + } + + // + if (result) + { + // + result = + // + ArraySize(lowSwingBars) == tries && + ArraySize(highSwingBars) == tries + // + ; + } + + // + if (!result) + { + // + Clean(lowSwingBars); + Clean(highSwingBars); + } + + // + return result; + } + + // + // Find Bearish Trend ... + bool HasBearishTrend( + XOHCL &bar, + XOHCL &highSwingBars[], + XOHCL &lowSwingBars[], + bool forceMethod2 = false, + int _loopback = 3, + int tries = 3, + ENUM_X_PRICE type = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + Clean(lowSwingBars); + Clean(highSwingBars); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + double price = bar.GetPrice(type); + + // + int lastIDX = bar.Index(); + double lastH = 0; + double lastL = 0; + for (int i = 1; i < tries + 1; i++) + { + // + // Use Regular Method ... + if (!forceMethod2) + { + // + int iHIDX = FindSwing( + bar.symbol, + bar.period, + X_SWING_HIGH, + _loopback, + lastIDX // + ); + result = IsValidIndex(iHIDX); + if (!result) + { + break; + } + + // + XOHCL iHBar; + result = iHBar.Init( + bar.symbol, + bar.period, + iHIDX // + ); + if (!result) + { + break; + } + + // + double iH = iHBar.high; + bool isIHAccepted = + // + iH > 0 && + ( + // + lastH == 0 + ? true + : iH > lastH + // + ) + // + ; + if (isIHAccepted) + { + // + AddRef( + iHBar, + highSwingBars // + ); + + // + lastH = iH; + lastIDX = iHIDX; + } + + // + int iLIDX = FindSwing( + bar.symbol, + bar.period, + X_SWING_LOW, + _loopback, + lastIDX // + ); + result = IsValidIndex(iLIDX); + if (!result) + { + break; + } + + // + XOHCL iLBar; + result = iLBar.Init( + bar.symbol, + bar.period, + iLIDX // + ); + if (!result) + { + break; + } + + // + double iL = iLBar.low; + bool isILAccepted = + // + iL > 0 && + ( + // + lastL == 0 + ? true + : iL > lastL + // + ) + // + ; + if (isILAccepted) + { + // + AddRef( + iLBar, + lowSwingBars // + ); + + // + lastL = iL; + lastIDX = iLIDX; + } + } + // + // Use Other MEthod ... + else + { + // + int _length = i * _loopback; + int start = + // + i == 1 + ? 1 + : _length - _loopback + // + ; + + // + int iHIDX = iHighest( + bar.symbol, + bar.period, + MODE_HIGH, + _loopback, + start // + ); + result = IsValidIndex(iHIDX); + if (!result) + { + break; + } + + // + XOHCL iHBar; + result = iHBar.Init( + bar.symbol, + bar.period, + iHIDX // + ); + if (!result) + { + break; + } + + // + double iH = iHBar.high; + bool isIHAccepted = + // + iH > 0 && + ( + // + lastH == 0 + ? true + : iH > lastH + // + ) + // + ; + if (isIHAccepted) + { + // + AddRef( + iHBar, + highSwingBars // + ); + + // + lastH = iH; + lastIDX = iHIDX; + } + + // + int iLIDX = iLowest( + bar.symbol, + bar.period, + MODE_LOW, + _loopback, + start // + ); + result = IsValidIndex(iLIDX); + if (!result) + { + break; + } + + // + XOHCL iLBar; + result = iLBar.Init( + bar.symbol, + bar.period, + iLIDX // + ); + if (!result) + { + break; + } + + // + double iL = iLBar.low; + bool isILAccepted = + // + iL > 0 && + ( + // + lastL == 0 + ? true + : iL > lastL + // + ) + // + ; + if (isILAccepted) + { + // + AddRef( + iLBar, + lowSwingBars // + ); + + // + lastL = iL; + lastIDX = iLIDX; + } + } + } + + // + if (result) + { + // + result = + // + ArraySize(lowSwingBars) == tries && + ArraySize(highSwingBars) == tries + // + ; + } + + // + if (!result) + { + // + Clean(lowSwingBars); + Clean(highSwingBars); + } + + // + return result; + } + + // + // Order Blocks ... + + // + // Find Bullish Order Block ... + bool HasBullishOrderBlock( + XOHCL &bar, + XOHCL &orderBlock, + int _minimumSameBars = 4 // + ) + { + // + bool result = false; + + // + orderBlock.Clean(); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + if (_minimumSameBars < 0) + { + _minimumSameBars = 4; + } + + // + XOHCL cBar; + int founded = 0; + int cIDX = bar.Index(); + bool isEnough = false; + while (!isEnough) + { + // + result = cBar.Init( + bar.symbol, + bar.period, + cIDX // + ); + if (!result) + { + break; + } + + // + result = cBar.IsBullish(); + if (!result && cBar.IsBearish()) + { + break; + } + + // + cIDX++; + founded++; + } + + // + // Here we have to check founded and if it's fill + // our requirements ... + // cIDX is Order Block Index ... + result = + // + cBar.IsValid() && + bar.high > cBar.high && + founded >= _minimumSameBars + // + ; + if (!result) + { + return result; + } + + // + result = orderBlock.Init( + bar.symbol, + bar.period, + cIDX // + ); + if (!result) + { + // + orderBlock.Clean(); + return result; + } + + // + return result; + } + + // + // Find Bearish Order Block ... + bool HasBearishOrderBlock( + XOHCL &bar, + XOHCL &orderBlock, + int _minimumSameBars = 4 // + ) + { + // + bool result = false; + + // + orderBlock.Clean(); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + if (_minimumSameBars < 0) + { + _minimumSameBars = 4; + } + + // + XOHCL cBar; + int founded = 0; + int cIDX = bar.Index(); + bool isEnough = false; + while (!isEnough) + { + // + bool isInited = cBar.Init( + bar.symbol, + bar.period, + cIDX // + ); + + // + result = cBar.IsBearish(); + if (!result && cBar.IsBullish()) + { + break; + } + + // + cIDX++; + founded++; + } + + // + // Here we have to check founded and if it's fill + // our requirements ... + // cIDX is Order Block Index ... + result = + // + cBar.IsValid() && + bar.high < cBar.low && + founded >= _minimumSameBars + // + ; + if (!result) + { + return result; + } + + // + result = orderBlock.Init( + bar.symbol, + bar.period, + cIDX // + ); + if (!result) + { + // + orderBlock.Clean(); + return result; + } + + // + return result; + } diff --git a/Documents/BKP/workingZone.zone.box.mq5 b/Documents/BKP/workingZone.zone.box.mq5 index 5cc71c25..3b5d3ae8 100644 --- a/Documents/BKP/workingZone.zone.box.mq5 +++ b/Documents/BKP/workingZone.zone.box.mq5 @@ -2981,6 +2981,117 @@ if (useSenario1) //////////////////////////////////////////////////////////////////////// +// +// FRACTALS ... +int copiedFractalsUppers = CopyBuffer(fractalHandler, 0, UPPER_LINE, limit, fractalsUpperBuffer); +int copiedFractalsLowers = CopyBuffer(fractalHandler, 1, LOWER_LINE, limit, fractalsLowerBuffer); + +// +// FRACTALS ... +copiedFractalsUppers > 0 && +copiedFractalsLowers > 0 + +// +// FRACTALS ... +int fractalsCalculatedBars = BarsCalculated(fractalHandler); + +// +// FRACTALS ... +fractalsCalculatedBars >= maxLength + + + // + // SUPPORT and RESISTANCE ... + + // + double iHighValue = iHigh( + _Symbol, + _Period, + barIndex // + ); + double iLastHighValue = iHigh( + _Symbol, + _Period, + lastIndex // + ); + + // + double iLowValue = iLow( + _Symbol, + _Period, + barIndex // + ); + double iLastLowValue = iLow( + _Symbol, + _Period, + lastIndex // + ); + + // + // Resistance ... + // double lastResistance = + // lastIndex < barsCount + // ? resistancesBuffer[lastIndex] + // : iLastHighValue; + // double iFractalsUpper = fractalsUpperBuffer[barIndex]; + // double iResistance = + // NotEmptyZero(iFractalsUpper) + // ? iHighValue + // : lastResistance; + // resistancesBuffer[barIndex] = iResistance; + + // + // Support ... + // double lastSupport = + // lastIndex < barsCount + // ? supportsBuffer[lastIndex] + // : iLastLowValue; + // double iFractalsLower = fractalsLowerBuffer[barIndex]; + // double iSupport = + // NotEmptyZero(iFractalsLower) + // ? iLowValue + // : lastSupport; + // supportsBuffer[barIndex] = iSupport; + + // + double iFractalsUpper = fractalsUpperBuffer[barIndex]; + double iResistance = iFractalsUpper; + resistancesBuffer[barIndex] = iResistance; + + + // + double iFractalsLower = fractalsLowerBuffer[barIndex]; + double iSupport = iFractalsLower; + supportsBuffer[barIndex] = iSupport; + +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// diff --git a/Documents/BKP/x-cmn.tmp.codes.mq5 b/Documents/BKP/x-cmn.tmp.codes.mq5 new file mode 100644 index 00000000..eb04a868 --- /dev/null +++ b/Documents/BKP/x-cmn.tmp.codes.mq5 @@ -0,0 +1,1383 @@ + +// +// Calculate TP/SL for Specified Type of Positions ... +void CalculateTPSL( + double &mSL, // Hold SL + double &mTP, // Hold TP + ENUM_POSITION_TYPE mType, // Position Type Long (Buy) / Short (Sell) + double mEntry, // Entry Price + double mR2R = 1, // Provided Risk To Reward Ratio + double slPrice = 0, // Provided SL Price + double tpPrice = 0, // Provided TP Price + double priceToRisk = 0, // If Entry equal to Provided SL Price Risk Point + double priceToReward = 0 // If Entry equal to Provided TP Price Reward Point +) +{ + // + // if Both TP and SL Provided, ignore R2R and Calculate direct ... + // if SL provided, Calculate TP based on Provided R2R ... + // if TP provided, Calculate SL based on Provided R2R ... + // default R2R is set to 1 ... + + // + mSL = 0; + mTP = 0; + + // + bool isLong = IsLong(mType); + + // + // Set Default R2R ... + if (mR2R < 1) + { + mR2R = 1; + } + + // + if (mEntry <= 0 || + (tpPrice <= 0 && slPrice <= 0)) + { + return; + } + + // + double risk = 0; + double reward = 0; + + // + bool canCalculateBasedOnSL = slPrice > 0 && + (isLong + ? slPrice <= mEntry + : slPrice >= mEntry); + + // + bool canCalculateBasedOnTP = tpPrice > 0 && + (isLong + ? tpPrice >= mEntry + : tpPrice <= mEntry); + + // + if (canCalculateBasedOnSL && !canCalculateBasedOnTP) + { + // + risk = MathAbs(mEntry - slPrice); + if (risk == 0) + { + risk = priceToRisk; + } + reward = risk * mR2R; + } + else if (!canCalculateBasedOnSL && canCalculateBasedOnTP) + { + // + reward = MathAbs(mEntry - tpPrice); + if (reward == 0) + { + reward = priceToReward; + } + risk = reward / mR2R; + } + else if (!canCalculateBasedOnSL && !canCalculateBasedOnTP) + { + // + bool canSetTPPrice = isLong + ? tpPrice > mEntry + : tpPrice < mEntry; + if (canSetTPPrice) + { + mTP = tpPrice; + } + + // + bool canSetSLPrice = isLong + ? slPrice < mEntry + : slPrice > mEntry; + if (canSetSLPrice) + { + mSL = slPrice; + } + + // + return; + } + else if (canCalculateBasedOnSL && canCalculateBasedOnTP) + { + // + bool canSetTPPrice = isLong + ? tpPrice > mEntry + : tpPrice < mEntry; + if (canSetTPPrice) + { + mTP = tpPrice; + } + + // + bool canSetSLPrice = isLong + ? slPrice < mEntry + : slPrice > mEntry; + if (canSetSLPrice) + { + mSL = slPrice; + } + + // + return; + } + + // + mTP = isLong + ? mEntry + reward + : mEntry - reward; + + // + mSL = isLong + ? mEntry - risk + : mEntry + risk; +} + +// +bool CalculateTPSLByPoint( + double &mSL, // Hold SL + double &mTP, // Hold TP + ENUM_POSITION_TYPE mType, // Position Type Long (Buy) / Short (Sell) + double mEntry, // Entry Price + double mPointValue, // Point Value + double mR2R = 1, // Provided Risk To Reward Ratio + double slPoint = 0, // Provided SL Point + double tpPoint = 0 // Provided TP Point +) +{ + // + bool result = false; + + // + mSL = 0; + mTP = 0; + + // + bool isLong = IsLong(mType); + + // + // Set Default R2R ... + if (mR2R < 1) + { + mR2R = 1; + } + + // + if (mEntry <= 0 || + mPointValue <= 0 || + (slPoint <= 0 && tpPoint <= 0)) + { + return result; + } + + // + double risk = 0; + double reward = 0; + + // + bool canCalculateBasedOnSL = slPoint > 0; + + // + bool canCalculateBasedOnTP = tpPoint > 0; + + // + if (!canCalculateBasedOnSL && !canCalculateBasedOnTP) + { + return result; + } + + // + if (canCalculateBasedOnSL && canCalculateBasedOnTP) + { + // + reward = tpPoint * mPointValue; + risk = slPoint * mPointValue; + } + else if (!canCalculateBasedOnSL && canCalculateBasedOnTP) + { + // + reward = tpPoint * mPointValue; + risk = reward / mR2R; + } + else if (canCalculateBasedOnSL && !canCalculateBasedOnTP) + { + // + risk = slPoint * mPointValue; + reward = risk * mR2R; + } + + // + result = risk > 0 && reward > 0; + if (!result) + { + return result; + } + + // + mTP = isLong + ? mEntry + reward + : mEntry - reward; + + // + mSL = isLong + ? mEntry - risk + : mEntry + risk; + + // + return result; +} + +// +bool CalculateTPSLByPrice( + double &mSL, // Hold SL + double &mTP, // Hold TP + ENUM_POSITION_TYPE mType, // Position Type Long (Buy) / Short (Sell) + double mEntry, // Entry Price + double mR2R = 1 // Provided Risk To Reward Ratio +) +{ + // + bool result = false; + + // + bool isLong = IsLong(mType); + + // + // Set Default R2R ... + if (mR2R < 1) + { + mR2R = 1; + } + + // + if (mEntry <= 0 || + (mSL <= 0 && mTP <= 0)) + { + return result; + } + + // + double risk = 0; + double reward = 0; + + // + bool canCalculateBasedOnSL = mSL > 0; + bool canCalculateBasedOnTP = mTP > 0; + + // + if ( + !canCalculateBasedOnSL && + !canCalculateBasedOnTP) + { + return result; + } + + // + if (!canCalculateBasedOnSL && canCalculateBasedOnTP) + { + // + reward = MathAbs(mTP - mEntry); + risk = reward / mR2R; + } + else if (canCalculateBasedOnSL && !canCalculateBasedOnTP) + { + // + risk = MathAbs(mEntry - mSL); + reward = risk * mR2R; + } + + // + result = risk > 0 && reward > 0; + if (!result) + { + return result; + } + + // + mTP = isLong + ? mEntry + reward + : mEntry - reward; + + // + mSL = isLong + ? mEntry - risk + : mEntry + risk; + + // + return result; +} + +/** + * Calculate Momentum Changes based on Given Price + */ +double CalculateMomentum( + double currentPrice, + double previousPrice // +) +{ + // + double result = 0; + + // + return result; +} + +/** + * Detect Possible Momentum Changes + * Using MqlTick ... + */ +bool DetectMomentumChange( + ENUM_POSITION_TYPE type, + string mSymbol = NULL, + int mLength = 14 // +) +{ + // + bool result = false; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + MqlTick ticks[]; + int copied = CopyTicks( + mSymbol, + ticks, + COPY_TICKS_ALL, + 0, + mLength + 1 // + ); + + // + result = copied > mLength; + if (!result) + { + return result; + } + + // + double previousPrice = GetTickExit( + ticks[mLength], + type, + mSymbol // + ); + for (int i = mLength - 1; i >= 0; i--) + { + // + double currentPrice = GetTickExit( + ticks[i], + type, + mSymbol // + ); + + // + double momentum = CalculateMomentum( + currentPrice, + previousPrice // + ); + + // + if (fabs(momentum) > 1.0) + { + // + result = true; + break; + } + } + + // + return result; +} + + +// +// +// + +// +// Extension Methods ... + +// +// Find Swing Points ... +int FindSwing( + string mSymbol, // Trading Symbol ... + ENUM_TIMEFRAMES mPeriod, // Trading Period ... + ENUM_X_SWING_TYPE mMode, // Swing Based On Price mode ... + int mLength, // Loopback ... + int bar_index // BarIndex ... +) +{ + // + int result = -1; + + // + if (StringLen(mSymbol) == 0 || (mMode != X_SWING_HIGH && mMode != X_SWING_LOW)) + { + return result; + } + + // + int current = bar_index; + int founded = FindNextSwing( + mSymbol, + mPeriod, + mMode, + (mLength * 2) + 1, + current - mLength); + + // + while (founded != current) + { + // + current = FindNextSwing( + mSymbol, + mPeriod, + mMode, + mLength, + current + 1); + + // + founded = FindNextSwing( + mSymbol, + mPeriod, + mMode, + (mLength * 2) + 1, + current - mLength); + } + + // + result = current; + + // + return result; +} + +// +// Find Next Swing ... +int FindNextSwing( + string mSymbol, // Trading Symbol ... + ENUM_TIMEFRAMES mPeriod, // Trading Period ... + ENUM_X_SWING_TYPE mMode, // Swing Based On Price mode ... + int mLength, // Loopback ... + int bar_index // BarIndex ... +) +{ + // + int result = -1; + + // + if (bar_index < 0) + { + mLength += bar_index; + bar_index = 0; + } + + // + ENUM_SERIESMODE mSeriesMode = ToSeriesMode(mMode); + + // + result = mMode == X_SWING_HIGH + ? iHighest( + mSymbol, + mPeriod, + mSeriesMode, + mLength, + bar_index) + : iLowest( + mSymbol, + mPeriod, + mSeriesMode, + mLength, + bar_index); + + // + return result; +} + +/** + * Extract values of swings from specified Collection ... + * + * @param swings: XSwingPoint instance Collection ... + * @param values: double Collection ... + * + * @return ( int ) + */ +int ExtractSwings( + XSwingPoint &swings[], + double &values[] // +) +{ + // + int result = 0; + + // + Clean(values); + + // + int count = ArraySize(swings); + if (!IsValidSize(count)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + Add( + swings[i].swing, + values // + ); + } + + // + result = ArraySize(values); + + // + return result; +} + +// +// Functions ... + +// +// Validators ... + +// +// Validate an String has length and not NULL ... + +// +// Validate a Date ... + +// +// Validate a Period Param ... + + +// +// Validate Specific Period Mode ... + + +// +// As IS ... + +// +// Normalizers ... + + +// +// Prices ... + + + + +/** + * Calculates Price Change Percentage based on + * Several Params ... + * + * @param _symbol: Symbol ... + * @param _period: Time Frame ... + * @param _from: start Bar Index ... + * @param _length: Length of Bars ... + * + * @return ( double ) + */ +double GetPriceChanged( + string _symbol = NULL, + ENUM_TIMEFRAMES _period = NULL, + int _from = 0, + int _length = 3 // +) +{ + // + double result = 0; + + // + NormalizeSymbol(_symbol); + NormalizePeriod(_period); + + // + if (_from < 0) + { + _from = 0; + } + + // + if (_length < 2) + { + _length = 2; + } + + // + double closes[]; + int copiedCloses = CopyClose( + _symbol, + _period, + _from, + _length, + closes // + ); + if (copiedCloses < _length) + { + return result; + } + ArrayReverse(closes); + + // + double change = (closes[0] - closes[_length - 1]) / closes[_length - 1] * 100; + result = change; + + // + return result; +} + +/** + * Retrieve Current Tick ... + */ +bool GetTick( + string mSymbol, + MqlTick &tick // +) +{ + return SymbolInfoTick(mSymbol, tick); +} + +/** + * Retrieve Tick Entry ... + */ +double GetTickEntry( + MqlTick &mTick, + ENUM_POSITION_TYPE type, + string mSymbol = NULL // +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + result = + IsLong(type) + ? mTick.ask + : mTick.bid; + result = NormalizePrice(result, mSymbol); + + // + return result; +} + +/** + * Retrieve Tick Exit ... + */ +double GetTickExit( + MqlTick &mTick, + ENUM_POSITION_TYPE type, + string mSymbol = NULL // +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + result = + IsLong(type) + ? mTick.bid + : mTick.ask; + result = NormalizePrice(result, mSymbol); + + // + return result; +} + +// +// Fill Specified Applied Prices ... +int FillPrice( + double &buffer[], + ENUM_APPLIED_PRICE _mAppliedTo = PRICE_CLOSE, + string _mSymbol = NULL, + ENUM_TIMEFRAMES _mPeriod = NULL, + int _mStart = 0, + int _mLoopback = 10 // +) +{ + // + int result = 0; + + // + if (_mStart < 0) + { + _mStart = 0; + } + + // + if (_mLoopback < 1) + { + _mLoopback = 1; + } + + // + _mSymbol = NormalizeSymbol(_mSymbol); + _mPeriod = NormalizePeriod(_mPeriod); + + // + Clean(buffer); + ArraySetAsSeries(buffer, true); + + // + double open[]; + result = CopyOpen( + _mSymbol, + _mPeriod, + _mStart, + _mLoopback, + open // + ); + if (!IsValidSize(result)) + { + return result; + } + + // + double high[]; + result = CopyHigh( + _mSymbol, + _mPeriod, + _mStart, + _mLoopback, + high // + ); + if (!IsValidSize(result)) + { + return result; + } + + // + double low[]; + result = CopyLow( + _mSymbol, + _mPeriod, + _mStart, + _mLoopback, + low // + ); + if (!IsValidSize(result)) + { + return result; + } + + // + double close[]; + result = CopyClose( + _mSymbol, + _mPeriod, + _mStart, + _mLoopback, + close // + ); + if (!IsValidSize(result)) + { + return result; + } + + // + for (int i = 0; i < result; i++) + { + // + double iPrice = GetAppliedPrice( + _mAppliedTo, + open, + high, + low, + close, + i // + ); + + // + Add( + iPrice, + buffer // + ); + } + + // + result = ArraySize(buffer); + + // + return result; +} + +// +// Symbols ... + + +// +// Time / Date ... + + +// +// Retrieve Day of Week ... +ENUM_X_WEEK_DAYS GetDayOfWeek( + datetime time = NULL // +) +{ + // + ENUM_X_WEEK_DAYS result = X_WEEK_DAY_NONE; + + // + time = NormalizeTime(time); + MqlDateTime timeStruct; + bool hasDate = TimeToStruct( + time, + timeStruct // + ); + if (!hasDate) + { + return result; + } + + // + result = (ENUM_X_WEEK_DAYS)timeStruct.day_of_week; + + // + return result; +} + +// +// Representation of Time Struct ... +// struct MqlDateTime +// { +// int year; // Year +// int mon; // Month +// int day; // Day +// int hour; // Hour +// int min; // Minutes +// int sec; // Seconds +// int day_of_week; // Day of week (0-Sunday, 1-Monday, ... ,6-Saturday) +// int day_of_year; // Day number of the year (January 1st is assigned the number value of zero) +// }; + + +// +// Bar Times ... + +// +// Retrieve Specified Bar Time ... +ulong GetBarTimeAsSeconds( + string mSymbol = "", // Specify Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Specify TimeFrame + int barIndex = 0 // Specify Bar Index +) +{ + // + // Retrieve Bar Time ... + datetime time = GetBarTime( + mSymbol, + mPeriod, + barIndex); + + // + ulong result = TimeToSeconds(time); + + // + return result; +} + +// +// Retrieve Specified Bar Time ... +ulong GetBarTimeAsMilliSeconds( + string mSymbol = "", // Specify Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Specify TimeFrame + int barIndex = 0 // Specify Bar Index +) +{ + // + // Retrieve Bar Time ... + datetime time = GetBarTime( + mSymbol, + mPeriod, + barIndex); + + // + ulong result = TimeToMilliSeconds(time); + + // + return result; +} + +// +// Retrieve a Bar Time Structure ... +MqlDateTime GetBarTimeStruct( + string mSymbol = "", // Specify Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Specify TimeFrame + int barIndex = 0 // Specify Bar Index +) +{ + // + MqlDateTime result = {}; + + // + // Retrieve Bar Time ... + datetime barTime = GetBarTime( + mSymbol, + mPeriod, + barIndex); + + // + // Convert to Structure ... + TimeToStruct(barTime, result); + + // + return result; +} + +// +// Retrieve Last Available Bar Time of +// Dest Period inside Source Period ... +datetime GetLastBarTime( + ENUM_TIMEFRAMES sourcePeriod, + ENUM_TIMEFRAMES destPeriod // +) +{ + // + datetime result = NULL; + + // + if (!IsValid(sourcePeriod) || + !IsValid(destPeriod)) + { + return result; + } + + // + int sourceSeconds = PeriodSeconds(sourcePeriod); + int destSeconds = PeriodSeconds(destPeriod); + if (sourceSeconds < destSeconds) + { + return result; + } + + // + XOHCL sourceBar; + bool isInited = sourceBar.Init( + _Symbol, + sourcePeriod, + 0 // + ); + if (!isInited) + { + return result; + } + + // + result = (datetime)((((int)sourceBar.time) + sourceSeconds) - destSeconds); + + // + return result; +} + +// +// Other Tools ... + + +// +// Check Bar Reject Specified Value ... +bool IsBarReject( + double value, + ENUM_X_DIRECTION dir, + XOHCL &bar // +) +{ + // + bool result = false; + + // + result = value > 0 && + bar.IsValid() && + HasDirection(dir); + if (!result) + { + return result; + } + + // + bool isUp = IsBullish(dir); + bool isDown = IsBearish(dir); + + // + result = + // + isUp + ? bar.IsBullish() && + bar.low < value && + bar.GetDown() > value + : isDown + ? bar.IsBearish() && + bar.high > value && + bar.GetUp() < value + : false + // + ; + + // + return result; +} + +// +// Check Bar Break Specified Value ... +bool IsBarBreak( + double value, + ENUM_X_DIRECTION dir, + XOHCL &bar // +) +{ + // + bool result = false; + + // + result = value > 0 && + bar.IsValid() && + HasDirection(dir); + if (!result) + { + return result; + } + + // + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + bool isUp = IsBullish(dir); + bool isDown = IsBearish(dir); + + // + result = + isUp + ? bar.IsBullish() && + ((bar.GetDown() < value && + bar.GetUp() > value) || + (bar.close > value && + pBar.close < value)) + : isDown + ? bar.IsBearish() && + ((bar.GetUp() > value && + bar.GetDown() < value) || + (bar.close < value && + pBar.close > value)) + : false; + + // + return result; +} + +// +// Calculate Fib Level ... +double GetFibonacciLevel( + double upPrice, // Upper Bound + double downPrice, // Downer Bound + double level, // Level Multiplier Factor + int direction // From Down to Up < 0, other wise Vice Versa + // +) +{ + // + double ling = upPrice - downPrice; + double pLevel = (ling / 100) * (level * 100); + + // + double result = direction > 0 ? upPrice - pLevel : downPrice + pLevel; + + // + return result; +} + +// +double GetFibonacciLevel( + double mUp, + double mDown, + ENUM_X_FIBO_LEVELS mLevel, + ENUM_X_DIRECTION mForDir // +) +{ + // + double result = 0; + + // + double levelValue = GetFiboLevelValue(mLevel); + + // + bool isValid = + // + mUp > 0 && + mDown > 0 && + levelValue > 0 && + mUp > mDown && + HasDirection(mForDir) + // + ; + if (!isValid) + { + return result; + } + + // + bool isBullish = IsBullish(mForDir); + + // + double ling = mUp - mDown; + double pLevel = (ling / 100) * (levelValue * 100); + + // + result = + isBullish + ? mUp - pLevel + : mDown + pLevel; + + // + return result; +} + +// +// Method 1 +// Normalize between 1 and 0 ... +template +double GetNormalizedValueMethod1( + T &buffer[], // Array which required to Normalize + int mLength, // Length of Normalization + int mStart = 0, // start index + int digits = 5 // Normalization Digits +) +{ + // + double result = 0; + + // + if (digits <= 5) + { + digits = 5; + } + + // + int bufferSize = ArraySize(buffer); + if (!IsValidSize(bufferSize)) + { + return result; + } + + // + // Normalize Count ... + NormalizeCount( + mStart, + mLength, + buffer // + ); + + // + T max = 0; + T min = 0; + + // + if (bufferSize != mLength) + { + // + T tmp[]; + Copy( + mStart, + mLength, + buffer, + tmp // + ); + + // + max = GetMax(tmp); + min = GetMin(tmp); + } + + // + if (bufferSize == mLength) + { + // + max = GetMax(buffer); + min = GetMin(buffer); + } + + // + T iValue = buffer[mStart]; + + // + double minMaxDiff = (max - min); + if (minMaxDiff <= 0) + { + return result; + } + + // + result = (iValue - min) / minMaxDiff; + + // + result = NormalizeDouble(result, digits); + + // + return result; +} + +// +// Method 2 +// Normalize Between Specified Upper and Lower ... +template +double GetNormalizedValueMethod2( + T &buffer[], // Array which required to Normalize + int mLength, // Length of Normalization + int mUpper, // Specified Upper Value + int mLower, // Specified Lower Value + int mStart = 0, // start index + int digits = 5 // Normalization Digits +) +{ + // + double result = 0; + + // + if (digits <= 5) + { + digits = 5; + } + + // + int bufferSize = ArraySize(buffer); + if (!IsValidSize(bufferSize)) + { + return result; + } + + // + // Normalize Count ... + NormalizeCount( + mStart, + mLength, + buffer // + ); + + // + T max = 0; + T min = 0; + + // + if (bufferSize != mLength) + { + // + T tmp[]; + Copy( + mStart, + mLength, + buffer, + tmp // + ); + + // + max = GetMax(tmp); + min = GetMin(tmp); + } + + // + if (bufferSize == mLength) + { + // + max = GetMax(buffer); + min = GetMin(buffer); + } + + // + T iValue = buffer[mStart]; + + // + double minMaxDiff = (max - min); + double boundaryDiff = (mUpper - mLower); + if (minMaxDiff <= 0 || boundaryDiff <= 0) + { + return result; + } + + // + result = boundaryDiff / (minMaxDiff * (iValue - max) + max); + + // + result = NormalizeDouble(result, digits); + + // + return result; +} + +// +void NormalizeBuffer( + double &source[], // Source Buffer + double &dest[], // Result Buffer + double upper = 100, // Upper Value to Normalize + double lower = -100, // Lower Value to Normalize + int size = -1, // Size Of Normalization + int digits = 5 // Digits for Result +) +{ + // + if (size <= 0) + { + size = ArraySize(source); + } + + // + bool asSeriesFlag = ArrayGetAsSeries(source); + + // + ArraySetAsSeries(source, false); + ArraySetAsSeries(dest, false); + + // + double min = ArrayMinimum(source, 0, size); + double max = ArrayMaximum(source, 0, size); + + // + for (int i = 0; i < size; i++) + { + // + double iNormal = lower + ((source[i] - min) / (max - min)) * (upper - lower); + + // + if (digits > 0) + { + iNormal = NormalizeDouble(iNormal, digits); + } + + // + dest[i] = iNormal; + } + + // + ArraySetAsSeries(source, asSeriesFlag); + ArraySetAsSeries(dest, asSeriesFlag); +} + +// +// Templates ... + +// +// Bar XOHCL ... + +// +// String ... + +// +// Periods / Cycles ... + + +// +// Moving Average ... diff --git a/Documents/BKP/x-saherelm.x-bar.analyser.class.mq5 b/Documents/BKP/x-saherelm.x-bar.analyser.class.mq5 new file mode 100644 index 00000000..2b4b613f --- /dev/null +++ b/Documents/BKP/x-saherelm.x-bar.analyser.class.mq5 @@ -0,0 +1,6043 @@ +/////////////////////////////////////////////////////// +// +// 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() + 1; + 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 if (isBearish) + { + // + sameBearishBarsFounded++; + canContinueForBullish = false; + } + else + { + // + sameBullishBarsFounded = 0; + sameBearishBarsFounded = 0; + canContinueForBullish = false; + canContinueForBearish = 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; + } + + // + index--; + + // + dir = + hasBullishSameBars + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + return result; + } + + /** + * Detect Price Consolidation ... + * + * @param bar: XOHCL instance Reference, Start Bar ... + * @param loopback: Integer, Consolidation Length Finder ... + * @param consolidationRange: 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, + int consolidationRange = 50, + 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; + } + + // + 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; + } + + bool HasConsolidationZone( + XOHCL &bar, + XConsolidationZone &zone, + int minLoopback = 3, + double range = 50, + ENUM_APPLIED_PRICE upperAppliedTo = PRICE_HIGH, + ENUM_APPLIED_PRICE lowerAppliedTo = PRICE_LOW // + ) + { + // + bool result = false; + + // + zone.Clean(); + + // + result = bar.IsValid() && + minLoopback > 0 && + range > 0; + if (!result) + { + return result; + } + + // + double points = GetPoints(bar.symbol); + int index = bar.Index() + 1; + int length = minLoopback; + + // + double upperPrice[]; + int upperPriceCount = FillPrice( + upperPrice, + upperAppliedTo, + bar.symbol, + bar.period, + index, + length // + ); + + // + double lowerPrice[]; + int lowerPriceCount = FillPrice( + lowerPrice, + lowerAppliedTo, + bar.symbol, + bar.period, + index, + length // + ); + + // + result = upperPriceCount == lowerPriceCount && + lowerPriceCount == length; + if (!result) + { + // + Clean(upperPrice); + Clean(lowerPrice); + + // + return result; + } + + // + double upper = upperPrice[ArrayMaximum(upperPrice)]; + double lower = lowerPrice[ArrayMinimum(lowerPrice)]; + + // + bool isBullishBreake = + bar.low > lower && + bar.high > upper && + bar.GetUp() > upper; + bool isBearishBreake = + bar.high < upper && + bar.low < lower && + bar.GetDown() < lower; + result = isBullishBreake || + isBearishBreake; + if (!result) + { + // + Clean(upperPrice); + Clean(lowerPrice); + + // + return result; + } + + // + double delta = upper - lower; + result = delta <= range * points; + if (!result) + { + // + Clean(upperPrice); + Clean(lowerPrice); + + // + return result; + } + + // + while (delta <= range * points) + { + // + length++; + + // + upperPriceCount = FillPrice( + upperPrice, + upperAppliedTo, + bar.symbol, + bar.period, + index, + length // + ); + + // + lowerPriceCount = FillPrice( + lowerPrice, + lowerAppliedTo, + bar.symbol, + bar.period, + index, + length // + ); + + // + bool isValid = upperPriceCount == lowerPriceCount && + lowerPriceCount == length; + if (!isValid) + { + break; + } + + // + double iUpper = upperPrice[ArrayMaximum(upperPrice)]; + double iLower = lowerPrice[ArrayMinimum(lowerPrice)]; + + // + delta = iUpper - iLower; + if (delta <= range * points) + { + // + upper = iUpper; + lower = iLower; + } + } + + // + Clean(upperPrice); + Clean(lowerPrice); + + // + // Filling Zone ... + zone.upper = upper; + zone.lower = lower; + zone.symbol = bar.symbol; + zone.period = bar.period; + zone.to = iTime( + bar.symbol, + bar.period, + bar.Index() + 1 // + ); + zone.from = iTime( + bar.symbol, + bar.period, + bar.Index() + length // + ); + zone.dir = isBullishBreake + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + result = zone.IsValid(); + if (!result) + { + zone.Clean(); + } + + // + 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 = HasBullishTrend( + bar, + tmpHSW, + tmpLSW, + true // + ); + + // + bool trend2 = HasBullishTrend( + bar, + 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 = HasBearishTrend( + bar, + tmpHSW, + tmpLSW, + true // + ); + + // + bool trend2 = HasBearishTrend( + bar, + 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 + : IsHammer(iBar); + if (isHammer) + { + founded++; + } + + // + bool isMorningStar = + !checkMorningStar + ? false + : IsMorningStar(iBar); + if (isMorningStar) + { + founded++; + } + + // + bool isBullishMarubozu = + !checkBullishMarubozu + ? false + : IsBullishMarubozu(iBar); + if (isBullishMarubozu) + { + founded++; + } + + // + bool isBullishEngulfing = + !checkBullishEngulfing + ? false + : IsBullishEngulfing(iBar); + 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 + : IsShootingStar(iBar); + if (isShootingStar) + { + founded++; + } + + // + bool isEveningStar = + !checkEveningStar + ? false + : IsEveningStar(iBar); + if (isEveningStar) + { + founded++; + } + + // + bool isBearishMarubozu = + !checkBearishMarubozu + ? false + : IsBearishMarubozu(iBar); + if (isBearishMarubozu) + { + founded++; + } + + // + bool isBearishEngulfing = + !checkBearishEngulfing + ? false + : IsBearishEngulfing(iBar); + 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 Specified Bar is Swing or not ... + * + * @param bar: XOHCL instnce ... + * @param dir: ENUM_X_DIRECTION member ... + * @param range: Integer, Specified Range ... + * + * @return ( bool ) + */ + bool IsSwing( + XOHCL &bar, + ENUM_X_DIRECTION &dir, + int range = 2 // + ) + { + // + bool result = false; + + // + dir = X_DIRECTION_NONE; + + // + bool isSwingLow = IsSwingLow(bar, range); + bool isSwingHigh = IsSwingHigh(bar, range); + + // + result = isSwingLow || + isSwingHigh; + if (result) + { + // + if (isSwingLow) + { + dir = X_DIRECTION_BULLISH; + } + else + { + dir = X_DIRECTION_BEARISH; + } + } + + // + 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); + result = rangePercent > 0; + if (!result) + { + return result; + } + + // + 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; + } + + /** + * Check Fibonacci Level 382 Pressure ... + * + * @param bar: XOHCL instance ... + * @param dir: ENUM_X_DIRECTION member ... + * + * @return ( bool ) + */ + bool HasFiboPressure( + XOHCL &bar, + ENUM_X_DIRECTION forDir, + ENUM_X_FIBO_LEVELS level // + ) + { + // + bool result = false; + + // + result = bar.IsValid() && + HasDirection(forDir); + if (!result) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + bool isBearish = IsBearish(forDir); + + // + double fiboLevelValue = GetFibonacciLevel( + bar.high, + bar.low, + level, + forDir // + ); + + // + bool isBullishPressured = + isBullish && + bar.GetDown() > fiboLevelValue; + bool isBearishPressured = + isBearish && + bar.GetUp() < fiboLevelValue; + + // + result = isBullishPressured || + isBearishPressured; + + // + 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 Has Support or not ... + * + * @param bar: XOHCL instance ... + * @param supportBar: XOHCL instance Specified Support Bar ... + * @param rage: int, + * @return ( bool ) + */ + bool HasSupport( + XOHCL &bar, + XOHCL &supportBar, + int range = 21 // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int barIndex = bar.Index() + range; + result = IsValidIndex(barIndex); + if (!result) + { + // + supportBar.Clean(); + return result; + } + result = supportBar.Init( + bar.symbol, + bar.period, + barIndex // + ); + + // + result = supportBar.low < supportBar.GetDown(); + if (!result) + { + // + supportBar.Clean(); + return result; + } + + // + double selectedValue = supportBar.GetDown(); + + // + int llIDX = bar.FindLowestIndex(range - 1, MODE_LOW); + result = IsValidIndex(llIDX); + if (!result) + { + // + supportBar.Clean(); + return result; + } + + // + double llValue = iLow( + bar.symbol, + bar.period, + llIDX // + ); + + // + result = llValue >= selectedValue; + if (!result) + { + // + supportBar.Clean(); + return result; + } + + // + result = supportBar.IsValid(); + + // + 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; + } + + /** + * Check a Bar Has Resistance or not ... + * + * @param bar: XOHCL instance ... + * @param resistanceBar: XOHCL instance Specified Resistance Bar ... + * @param rage: int, + * @return ( bool ) + */ + bool HasResistance( + XOHCL &bar, + XOHCL &resistanceBar, + int range = 21 // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int barIndex = bar.Index() + range; + result = IsValidIndex(barIndex); + if (!result) + { + // + resistanceBar.Clean(); + return result; + } + result = resistanceBar.Init( + bar.symbol, + bar.period, + barIndex // + ); + + // + result = resistanceBar.low < resistanceBar.GetDown(); + if (!result) + { + // + resistanceBar.Clean(); + return result; + } + + // + double selectedValue = resistanceBar.GetUp(); + + // + int hhIDX = bar.FindHighestIndex(range - 1, MODE_HIGH); + result = IsValidIndex(hhIDX); + if (!result) + { + // + resistanceBar.Clean(); + return result; + } + + // + double hhValue = iHigh( + bar.symbol, + bar.period, + hhIDX // + ); + + // + result = hhValue >= selectedValue; + if (!result) + { + // + resistanceBar.Clean(); + return result; + } + + // + result = resistanceBar.IsValid(); + + // + 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 + 1; + 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(); + int from = + index > (to + sameBars) + ? to + sameBars + : index; + 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; + } + + // + // Tools ... + + // + bool IsStrong( + XOHCL &bar, + double percent = 50 // Percent of Body + ) + { + // + bool result = false; + + // + result = bar.IsValid() && + bar.Index() > 0; + if (!result) + { + return result; + } + + // + result = + (bar.GetRange() * percent) / 100 <= bar.GetBody(); + + // + return result; + } + + // + bool HasStrongLowShadow( + XOHCL &bar, + double percent = 50, // Percent of Body + int __loopback = 2, + double _sharpRatio = 2.5 // + ) + { + // + bool result = false; + + // + result = bar.IsValid() && + bar.Index() > 0; + if (!result) + { + return result; + } + + // + result = + (bar.GetRange() * percent) / 100 <= bar.GetLowShadow(); + if (!result) + { + return result; + } + + // + if (__loopback < 0) + { + __loopback = 2; + } + + // + if (_sharpRatio < 0) + { + _sharpRatio = 2.5; + } + + // + result = bar.Index() > __loopback; + if (!result) + { + return result; + } + + // + // Get Highest High and Lowest Low in loopback Range ... + int startIndex = bar.Index() - __loopback; + int endIndex = bar.Index() + __loopback; + int requiredBars = MathAbs(endIndex - startIndex); + + // + // Highs ... + double highs[]; + int copiedHighs = CopyHigh( + bar.symbol, + bar.period, + startIndex, + requiredBars, + highs // + ); + + // + result = copiedHighs == requiredBars; + if (!result) + { + return result; + } + + // + int highestHighIDX = ArrayMaximum(highs); + result = IsValidIndex(highestHighIDX); + if (!result) + { + return result; + } + + // + double highestHigh = highs[highestHighIDX]; + + // + // Lows ... + double lows[]; + int copiedLows = CopyLow( + bar.symbol, + bar.period, + startIndex, + requiredBars, + lows // + ); + + // + result = copiedLows == requiredBars; + if (!result) + { + return result; + } + + // + int lowestLowIDX = ArrayMinimum(lows); + result = IsValidIndex(lowestLowIDX); + if (!result) + { + return result; + } + + // + double lowestLow = lows[lowestLowIDX]; + + // + result = bar.low == lowestLow && + highestHigh > bar.high; + if (!result) + { + return result; + } + + // + // Try to Validate Sharp Ratio ... + + // + Clean(highs); + Clean(lows); + + // + // Left Side ... + startIndex = bar.Index() + 1; + endIndex = startIndex + (__loopback / 2) - 1; + requiredBars = MathAbs(endIndex - startIndex); + + // + copiedHighs = CopyHigh( + bar.symbol, + bar.period, + startIndex, + requiredBars, + highs // + ); + result = copiedHighs == requiredBars; + if (!result) + { + return result; + } + + // + highestHighIDX = ArrayMaximum(highs); + result = IsValidIndex(highestHighIDX); + if (!result) + { + return result; + } + + // + highestHigh = highs[highestHighIDX]; + + // + copiedLows = CopyLow( + bar.symbol, + bar.period, + startIndex, + requiredBars, + lows // + ); + result = copiedLows == requiredBars; + if (!result) + { + return result; + } + + // + lowestLowIDX = ArrayMinimum(lows); + result = IsValidIndex(lowestLowIDX); + if (!result) + { + return result; + } + + // + lowestLow = lows[lowestLowIDX]; + + // + double leftDiff = highestHigh - lowestLow; + + // + Clean(highs); + Clean(lows); + + // + // Right Side ... + startIndex = bar.Index() - 1; + endIndex = startIndex - (__loopback / 2) + 1; + requiredBars = MathAbs(endIndex - startIndex); + + // + copiedHighs = CopyHigh( + bar.symbol, + bar.period, + startIndex, + requiredBars, + highs // + ); + result = copiedHighs == requiredBars; + if (!result) + { + return result; + } + + // + highestHighIDX = ArrayMaximum(highs); + result = IsValidIndex(highestHighIDX); + if (!result) + { + return result; + } + + // + highestHigh = highs[highestHighIDX]; + + // + copiedLows = CopyLow( + bar.symbol, + bar.period, + startIndex, + requiredBars, + lows // + ); + result = copiedLows == requiredBars; + if (!result) + { + return result; + } + + // + lowestLowIDX = ArrayMinimum(lows); + result = IsValidIndex(lowestLowIDX); + if (!result) + { + return result; + } + + // + lowestLow = lows[lowestLowIDX]; + + // + double rightDiff = highestHigh - lowestLow; + double diff = MathMax(leftDiff, rightDiff); + result = bar.GetLowShadow() >= (diff / 100) * _sharpRatio; + + // + return result; + } + + // + bool HasStrongHighShadow( + XOHCL &bar, + double percent = 50, // Percent of Body + int __loopback = 2, + double _sharpRatio = 2.5 // + ) + { + // + bool result = false; + + // + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + result = + (bar.GetRange() * percent) / 100 <= bar.GetHighShadow(); + if (!result) + { + return result; + } + + // + if (__loopback < 0) + { + __loopback = 2; + } + + // + if (_sharpRatio < 0) + { + _sharpRatio = 2.5; + } + + // + result = bar.Index() > __loopback; + if (!result) + { + return result; + } + + // + // Get Highest High and Lowest Low in loopback Range ... + int startIndex = bar.Index() - __loopback; + int endIndex = bar.Index() + __loopback; + int requiredBars = MathAbs(endIndex - startIndex); + + // + // Highs ... + double highs[]; + int copiedHighs = CopyHigh( + bar.symbol, + bar.period, + startIndex, + requiredBars, + highs // + ); + + // + result = copiedHighs == requiredBars; + if (!result) + { + return result; + } + + // + int highestHighIDX = ArrayMaximum(highs); + result = IsValidIndex(highestHighIDX); + if (!result) + { + return result; + } + + // + double highestHigh = highs[highestHighIDX]; + + // + // Lows ... + double lows[]; + int copiedLows = CopyLow( + bar.symbol, + bar.period, + startIndex, + requiredBars, + lows // + ); + + // + result = copiedLows == requiredBars; + if (!result) + { + return result; + } + + // + int lowestLowIDX = ArrayMinimum(lows); + result = IsValidIndex(lowestLowIDX); + if (!result) + { + return result; + } + + // + double lowestLow = lows[lowestLowIDX]; + + // + result = bar.high == highestHigh && + lowestLow < bar.low; + if (!result) + { + return result; + } + + // + // Try to Validate Sharp Ratio ... + + // + Clean(highs); + Clean(lows); + + // + // Left Side ... + startIndex = bar.Index() + 1; + endIndex = startIndex + (__loopback / 2) - 1; + requiredBars = MathAbs(endIndex - startIndex); + + // + copiedHighs = CopyHigh( + bar.symbol, + bar.period, + startIndex, + requiredBars, + highs // + ); + result = copiedHighs == requiredBars; + if (!result) + { + return result; + } + + // + highestHighIDX = ArrayMaximum(highs); + result = IsValidIndex(highestHighIDX); + if (!result) + { + return result; + } + + // + highestHigh = highs[highestHighIDX]; + + // + copiedLows = CopyLow( + bar.symbol, + bar.period, + startIndex, + requiredBars, + lows // + ); + result = copiedLows == requiredBars; + if (!result) + { + return result; + } + + // + lowestLowIDX = ArrayMinimum(lows); + result = IsValidIndex(lowestLowIDX); + if (!result) + { + return result; + } + + // + lowestLow = lows[lowestLowIDX]; + + // + double leftDiff = highestHigh - lowestLow; + + // + Clean(highs); + Clean(lows); + + // + // Right Side ... + startIndex = bar.Index() - 1; + endIndex = startIndex - (__loopback / 2) + 1; + requiredBars = MathAbs(endIndex - startIndex); + + // + copiedHighs = CopyHigh( + bar.symbol, + bar.period, + startIndex, + requiredBars, + highs // + ); + result = copiedHighs == requiredBars; + if (!result) + { + return result; + } + + // + highestHighIDX = ArrayMaximum(highs); + result = IsValidIndex(highestHighIDX); + if (!result) + { + return result; + } + + // + highestHigh = highs[highestHighIDX]; + + // + copiedLows = CopyLow( + bar.symbol, + bar.period, + startIndex, + requiredBars, + lows // + ); + result = copiedLows == requiredBars; + if (!result) + { + return result; + } + + // + lowestLowIDX = ArrayMinimum(lows); + result = IsValidIndex(lowestLowIDX); + if (!result) + { + return result; + } + + // + lowestLow = lows[lowestLowIDX]; + + // + double rightDiff = highestHigh - lowestLow; + double diff = MathMax(leftDiff, rightDiff); + result = bar.GetHighShadow() >= (diff / 100) * _sharpRatio; + + // + return result; + } + + // + bool IsStrongBullish( + XOHCL &bar, + double percent = 50 // Percent of Body + ) + { + // + bool result = false; + + // + result = + bar.IsValid() && + bar.IsBullish() && + IsStrong(bar, percent); + + // + return result; + } + + // + bool IsStrongBearish( + XOHCL &bar, + double percent = 50 // Percent of Body + ) + { + // + bool result = false; + + // + result = + bar.IsValid() && + bar.IsBearish() && + IsStrong(bar, percent); + + // + return result; + } + + // + bool IsSharpBullish( + XOHCL &bar, + int __loopback = 2, + double _sharpRatio = 2.5 // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + if (__loopback < 0) + { + __loopback = 2; + } + + // + if (_sharpRatio < 0) + { + _sharpRatio = 2.5; + } + + // + int hIDX = bar.FindHighestIndex( + __loopback, + MODE_HIGH // + ); + int lIDX = bar.FindLowestIndex( + __loopback, + MODE_LOW // + ); + + // + result = + // + hIDX >= 0 && + lIDX >= 0 && + MathAbs(hIDX - bar.Index()) < 2 + // + ; + + // + if (!result) + { + return result; + } + + // + XOHCL hBar; + result = hBar.Init( + bar.symbol, + bar.period, + hIDX // + ); + if (!result) + { + return result; + } + + // + XOHCL lBar; + result = lBar.Init( + bar.symbol, + bar.period, + lIDX // + ); + if (!result) + { + return result; + } + + // + double lhDif = hBar.high - lBar.low; + + // + int hhIDX = hBar.FindHighestIndex( + __loopback, + MODE_HIGH // + ); + + // + int llIDX = lBar.FindLowestIndex( + __loopback, + MODE_LOW // + ); + + // + XOHCL hhBar; + result = hhBar.Init( + bar.symbol, + bar.period, + hhIDX + hIDX // + ); + if (!result) + { + return result; + } + + // + XOHCL llBar; + result = llBar.Init( + bar.symbol, + bar.period, + llIDX + lIDX // + ); + if (!result) + { + return result; + } + + // + double llhhDif = hhBar.high - llBar.low; + + // + result = + // + lBar.low > llBar.low && + hBar.high > hhBar.high && + lhDif >= llhhDif * _sharpRatio + // + ; + + // + return result; + } + + // + bool IsSharpBearish( + XOHCL &bar, + int __loopback = 2, + double _sharpRatio = 2.5 // + ) + { + // + bool result = false; + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + if (__loopback < 0) + { + __loopback = 2; + } + + // + if (_sharpRatio < 0) + { + _sharpRatio = 2.5; + } + + // + int hIDX = bar.FindHighestIndex( + __loopback, + MODE_HIGH // + ); + int lIDX = bar.FindLowestIndex( + __loopback, + MODE_LOW // + ); + + // + result = + // + hIDX >= 0 && + lIDX >= 0 && + MathAbs(hIDX - bar.Index()) < 2 + // + ; + + // + if (!result) + { + return result; + } + + // + XOHCL hBar; + result = hBar.Init( + bar.symbol, + bar.period, + hIDX // + ); + if (!result) + { + return result; + } + + // + XOHCL lBar; + result = lBar.Init( + bar.symbol, + bar.period, + lIDX // + ); + if (!result) + { + return result; + } + + // + double lhDif = hBar.high - lBar.low; + + // + int hhIDX = hBar.FindHighestIndex( + __loopback, + MODE_HIGH // + ); + + // + int llIDX = lBar.FindLowestIndex( + __loopback, + MODE_LOW // + ); + + // + XOHCL hhBar; + result = hhBar.Init( + bar.symbol, + bar.period, + hhIDX + hIDX // + ); + if (!result) + { + return result; + } + + // + XOHCL llBar; + result = llBar.Init( + bar.symbol, + bar.period, + llIDX + lIDX // + ); + if (!result) + { + return result; + } + + // + double llhhDif = hhBar.high - llBar.low; + + // + result = + // + lBar.low < llBar.low && + hBar.high < hhBar.high && + lhDif >= llhhDif * _sharpRatio + // + ; + + // + return result; + } + + // + // + // + + // + // Retrieve Bullish Pressure ... + double GetBullishPressure( + XOHCL &bar, + int __loopback = 7 // + ) + { + // + double result = 0; + + // + if (!bar.IsValid()) + { + return result; + } + + // + XOHCL bars[]; + int barsCount = GetBars( + bars, + bar.symbol, + bar.period, + bar.Index(), + __loopback // + ); + if (!IsValidSize(barsCount)) + { + return result; + } + + // + for (int i = 0; i < barsCount; i++) + { + result += bars[i].GetLowShadow(); + } + + // + return result; + } + + // + // Retrieve Bearish Pressure ... + double GetBearishPressure( + XOHCL &bar, + int __loopback = 7 // + ) + { + // + double result = 0; + + // + if (!bar.IsValid()) + { + return result; + } + + // + XOHCL bars[]; + int barsCount = GetBars( + bars, + bar.symbol, + bar.period, + bar.Index(), + __loopback // + ); + if (!IsValidSize(barsCount)) + { + return result; + } + + // + for (int i = 0; i < barsCount; i++) + { + result += bars[i].GetHighShadow(); + } + + // + return result; + } + + // + bool HasBullishPressure( + XOHCL &bar, + int __loopback = 7 // + ) + { + // + bool result = false; + + // + if (__loopback < 0) + { + __loopback = 7; + } + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + double bullishPressure = GetBullishPressure(bar, __loopback); + double bearishPressure = GetBearishPressure(bar, __loopback); + + // + result = + // + bullishPressure > 0 && + bearishPressure >= 0 && + bullishPressure > bearishPressure + // + ; + + // + return result; + } + + // + bool HasBearishPressure( + XOHCL &bar, + int __loopback = 7 // + ) + { + // + bool result = false; + + // + if (__loopback < 0) + { + __loopback = 7; + } + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + double bullishPressure = GetBullishPressure(bar, __loopback); + double bearishPressure = GetBearishPressure(bar, __loopback); + + // + result = + // + bearishPressure > 0 && + bullishPressure >= 0 && + bearishPressure > bullishPressure + // + ; + + // + return result; + } + + // + // Retrieve Bullish Power ... + double GetBullishPower( + XOHCL &bar, + int __loopback = 7 // + ) + { + // + double result = 0; + + // + if (!bar.IsValid()) + { + return result; + } + + // + XOHCL bars[]; + int barsCount = GetBars( + bars, + bar.symbol, + bar.period, + bar.Index(), + __loopback // + ); + if (!IsValidSize(barsCount)) + { + return result; + } + + // + for (int i = 0; i < barsCount; i++) + { + // + if (bars[i].IsBullish()) + { + result += bars[i].GetBody(); + } + } + + // + return result; + } + + // + // Retrieve Bearish Pressure ... + double GetBearishPower( + XOHCL &bar, + int __loopback = 7 // + ) + { + // + double result = 0; + + // + if (!bar.IsValid()) + { + return result; + } + + // + XOHCL bars[]; + int barsCount = GetBars( + bars, + bar.symbol, + bar.period, + bar.Index(), + __loopback // + ); + if (!IsValidSize(barsCount)) + { + return result; + } + + // + for (int i = 0; i < barsCount; i++) + { + // + if (bars[i].IsBearish()) + { + result += bars[i].GetBody(); + } + } + + // + return result; + } + + // + bool HasBullishPower( + XOHCL &bar, + int __loopback = 7 // + ) + { + // + bool result = false; + + // + if (__loopback < 0) + { + __loopback = 7; + } + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + double bullishPressure = GetBullishPower(bar, __loopback); + double bearishPressure = GetBearishPower(bar, __loopback); + + // + result = + // + bullishPressure > 0 && + bearishPressure >= 0 && + bullishPressure > bearishPressure + // + ; + + // + return result; + } + + // + bool HasBearishPower( + XOHCL &bar, + int __loopback = 7 // + ) + { + // + bool result = false; + + // + if (__loopback < 0) + { + __loopback = 7; + } + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + double bullishPressure = GetBullishPower(bar, __loopback); + double bearishPressure = GetBearishPower(bar, __loopback); + + // + result = + // + bearishPressure > 0 && + bullishPressure >= 0 && + bearishPressure > bullishPressure + // + ; + + // + return result; + } + + // + // Decisions ... + + // + bool IsBullishDecision( + XOHCL &bar, + double percent = 70 // Percent of Body + ) + { + // + bool result = false; + + // + result = + // + bar.IsValid() && + bar.Index() > 0 && + bar.IsBullish() && + (bar.GetRange() * percent) / 100 <= bar.GetBody() + // + ; + + // + return result; + } + + // + bool IsBearishDecision( + XOHCL &bar, + double percent = 70 // Percent of Body + ) + { + // + bool result = false; + + // + result = + // + bar.IsValid() && + bar.Index() > 0 && + bar.IsBearish() && + (bar.GetRange() * percent) / 100 <= bar.GetBody() + // + ; + + // + return result; + } + + // + // Candlestic Patterns ... + + // + // Check Doji ... + bool IsDoji( + XOHCL &bar // + ) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + result = bar.open == bar.close; + + // + return result; + } + + // + // Check Hammer ... + bool IsHammer( + XOHCL &bar, + double _upShadowFactor = 0.1, + double _downShadowFactor = 0.6, + bool applyFib382Check = true, + bool applyPrevShadowCheck = true // + ) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + if (_upShadowFactor < 0) + { + _upShadowFactor = 0.1; + } + + // + if (_downShadowFactor < 0) + { + _upShadowFactor = 0.6; + } + + // + double range = bar.GetRange(); + + // + // Check Upper Shadow Must be 0 or Under 10% ... + double upShadow = bar.GetHighShadow(); + result = upShadow < range * _upShadowFactor; + if (!result) + { + return result; + } + + // + // Check Down Shadow Must at least 60% ... + double downShadow = bar.GetLowShadow(); + result = downShadow > range * _downShadowFactor; + if (!result) + { + return result; + } + + // + // Check Fib 382 ... + if (result && applyFib382Check) + { + // + double fib382 = GetFibonacciLevel( + bar.high, + bar.low, + 0.382, + -1 // + ); + result = bar.GetDown() > fib382; + } + + // + // Check Shadow Based on Prev Bar ... + if (result && applyPrevShadowCheck) + { + // + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + result = bar.low < pBar.low; + } + + // + return result; + } + + // + // Check Sgooting Star ... + // Reversal Hammer ... + bool IsShootingStar( + XOHCL &bar, + double _upShadowFactor = 0.6, + double _downShadowFactor = 0.1, + bool applyFib382Check = true, + bool applyPrevShadowCheck = true // + ) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + if (_upShadowFactor < 0) + { + _upShadowFactor = 0.6; + } + + // + if (_downShadowFactor < 0) + { + _upShadowFactor = 0.1; + } + + // + double range = bar.GetRange(); + + // + // Check Upper Shadow Must be 0 or Under 10% ... + double upShadow = bar.GetHighShadow(); + result = upShadow > range * _upShadowFactor; + if (!result) + { + return result; + } + + // + // Check Down Shadow Must at least 60% ... + double downShadow = bar.GetLowShadow(); + result = downShadow < range * _downShadowFactor; + if (!result) + { + return result; + } + + // + // Check Fib 382 ... + if (result && applyFib382Check) + { + // + double fib382 = GetFibonacciLevel( + bar.high, + bar.low, + 0.382, + 1 // + ); + result = bar.GetUp() < fib382; + } + + // + // Check Shadow Based on Prev Bar ... + if (result && applyPrevShadowCheck) + { + // + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + result = bar.high > pBar.high; + } + + // + return result; + } + + // + // Check Bullish Engulfing ... + bool IsBullishEngulfing( + XOHCL &bar, + double _engulfBarBodyFactor = 0.7 // + ) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + if (_engulfBarBodyFactor < 0) + { + _engulfBarBodyFactor = 0.7; + } + + // + // Check Bar Is Bullish ... + result = bar.IsBullish(); + if (!result) + { + return result; + } + + // + // Retrieve Previous Bar ... + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + double range = bar.GetRange(); + double body = bar.GetBody(); + + // + // Check Prev Bar Must Bearish ... + result = pBar.IsBearish(); + if (!result) + { + return result; + } + + // + // Check Shadows Engulf Prev Bar ... + result = + // + bar.high > pBar.high && + bar.low <= pBar.low + // + ; + if (!result) + { + return result; + } + + // + // Check Engulfed Bar Must Inside Engulfer Body ... + result = + // + bar.GetUp() > pBar.GetUp() && + bar.GetDown() < pBar.GetDown() + // + ; + if (!result) + { + return result; + } + + // + // Check Body of Engulfing Bar ... + if (result && _engulfBarBodyFactor > 0) + { + result = body >= range * _engulfBarBodyFactor; + } + + // + return result; + } + + // + // Check Bearish Engulfing ... + bool IsBearishEngulfing( + XOHCL &bar, + double _engulfBarBodyFactor = 0.7 // + ) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + if (_engulfBarBodyFactor < 0) + { + _engulfBarBodyFactor = 0.7; + } + + // + // Check Bar Is Bearish ... + result = bar.IsBearish(); + if (!result) + { + return result; + } + + // + // Retrieve Previous Bar ... + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + double range = bar.GetRange(); + double body = bar.GetBody(); + + // + // Check Prev Bar Must Bullish ... + result = pBar.IsBullish(); + if (!result) + { + return result; + } + + // + // Check Shadows Engulf Prev Bar ... + result = bar.high >= pBar.high && + bar.low < pBar.low; + if (!result) + { + return result; + } + + // + // Check Engulfed Bar Must Inside Engulfer Body ... + result = + // + bar.GetUp() > pBar.GetUp() && + bar.GetDown() < pBar.GetDown() + // + ; + if (!result) + { + return result; + } + + // + // Check Body of Engulfing Bar ... + if (result && _engulfBarBodyFactor > 0) + { + result = body >= range * _engulfBarBodyFactor; + } + + // + return result; + } + + // + // Check Morning Star Pattern ... + bool IsMorningStar( + XOHCL &bar, + double _middleRangeFactor = 0.3, + double _startBodyFactor = 0.6, + bool forceCheckMiddleBarDirection = true, + bool forceCheckStartBody = true // + ) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + if (_middleRangeFactor < 0) + { + _middleRangeFactor = 0.3; + } + + // + if (_startBodyFactor < 0) + { + _startBodyFactor = 0.6; + } + + // + // Current Bar Must be Bullish ... + result = bar.IsBullish(); + if (!result) + { + return result; + } + + // + // Retrieve Previous Bar ... + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + // Prev Bar must be Bearish ... + if (result && forceCheckMiddleBarDirection) + { + // + result = pBar.IsBearish(); + if (!result) + { + return result; + } + } + + // + // Retrieve Previous Bar of Prev Bar ... + XOHCL ppBar; + result = pBar.GetPreviousBar(ppBar); + if (!result) + { + return result; + } + + // + // Prev Of Prev Bar Must be Bearish ... + result = ppBar.IsBearish(); + if (!result) + { + return result; + } + + // + double range = bar.GetRange(); + double pRange = pBar.GetRange(); + double ppRange = ppBar.GetRange(); + + // + // Middle Bar must be Smaller than Ratio of other ... + result = + // + pRange < range * _middleRangeFactor && + pRange < ppRange * _middleRangeFactor + // + ; + if (!result) + { + return result; + } + + // + if (result && forceCheckStartBody) + { + // + result = ppBar.GetBody() > ppRange * _startBodyFactor; + if (!result) + { + return result; + } + } + + // + return result; + } + + // + // Check Evening Star Pattern ... + bool IsEveningStar( + XOHCL &bar, + double _middleRangeFactor = 0.3, + double _startBodyFactor = 0.6, + bool forceCheckMiddleBarDirection = true, + bool forceCheckStartBody = true // + ) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + if (_middleRangeFactor < 0) + { + _middleRangeFactor = 0.3; + } + + // + if (_startBodyFactor < 0) + { + _startBodyFactor = 0.6; + } + + // + // Current Bar Must be Bearish ... + result = bar.IsBearish(); + if (!result) + { + return result; + } + + // + // Retrieve Previous Bar ... + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + // Prev Bar must be Bullish ... + if (result && forceCheckMiddleBarDirection) + { + // + result = pBar.IsBullish(); + if (!result) + { + return result; + } + } + + // + // Retrieve Previous Bar of Prev Bar ... + XOHCL ppBar; + result = pBar.GetPreviousBar(ppBar); + if (!result) + { + return result; + } + + // + // Prev Of Prev Bar Must be Bullish ... + result = ppBar.IsBullish(); + if (!result) + { + return result; + } + + // + double range = bar.GetRange(); + double pRange = pBar.GetRange(); + double ppRange = ppBar.GetRange(); + + // + // Middle Bar must be Smaller than Ratio of other ... + result = + // + pRange < range * _middleRangeFactor && + pRange < ppRange * _middleRangeFactor + // + ; + if (!result) + { + return result; + } + + // + if (result && forceCheckStartBody) + { + // + result = ppBar.GetBody() > ppRange * _startBodyFactor; + if (!result) + { + return result; + } + } + + // + return result; + } + + // + // Bullish Marubozu ... + bool IsBullishMarubozu(XOHCL &bar) + { + // + bool result = false; + + // + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + result = bar.IsBullish(); + if (!result) + { + return result; + } + + // + result = + // + bar.GetUp() == bar.high && + bar.GetDown() == bar.low + // + ; + + // + return result; + } + + // + // Bearish Marubozu ... + bool IsBearishMarubozu(XOHCL &bar) + { + // + bool result = false; + + // + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + result = bar.IsBearish(); + if (!result) + { + return result; + } + + // + result = + // + bar.GetUp() == bar.high && + bar.GetDown() == bar.low + // + ; + + // + return result; + } + + // + // Contextual Patterns ... + + // + // Check Swing High ... + bool IsBarSwingHigh(XOHCL &bar) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + // Current Bar Must be Bearish ... + result = bar.IsBearish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev Bar ... + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + // Prev Bar Must be Bullish ... + result = pBar.IsBullish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev of Prev Bar ... + XOHCL ppBar; + result = pBar.GetPreviousBar(ppBar); + if (!result) + { + return result; + } + + // + // Prev of Prev Bar Must be Bullish ... + result = ppBar.IsBullish(); + if (!result) + { + return result; + } + + // + // Check All Highs ... + result = + // + bar.high < pBar.high && + pBar.high > ppBar.high + // + ; + + // + return result; + } + + // + // Find Simple 3 Candle Based Swing High ... + bool IsSimpleSwingHigh( + XOHCL &bar, + double thresholdInPoint = 1 // + ) + { + // + bool result = false; + + // + int index = bar.Index(); + result = index > 0; + if (!result) + { + return result; + } + + // + XOHCL nextBar; + result = bar.GetNextBar(nextBar); + if (!result) + { + return result; + } + + // + XOHCL prevBar; + result = bar.GetPreviousBar(prevBar); + if (!result) + { + return result; + } + + // + double point = GetPoints(bar.symbol); + double requiredOffset = point * thresholdInPoint; + + // + result = + bar.high > nextBar.high && + bar.high > prevBar.high && + (thresholdInPoint <= 0 + ? true + : MathAbs( + MathMax( + nextBar.high, + prevBar.high) - + bar.high) >= requiredOffset); + + // + return result; + } + + // + // Find Last Swing High ... + bool FindLastSwingHigh( + XOHCL &bar, + XOHCL &swing // + ) + { + // + bool result = false; + + // + swing.Clean(); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int totalBars = iBars( + bar.symbol, + bar.period // + ); + int maxAllowed = MathMin(100, (totalBars / 100)); + + // + int idx = bar.Index(); + for (int i = idx; i <= idx + maxAllowed; i++) + { + // + swing.Clean(); + result = swing.Init( + bar.symbol, + bar.period, + i // + ); + if (!result) + { + // + swing.Clean(); + break; + } + + // + result = IsBarSwingHigh(swing); + if (result) + { + break; + } + } + + // + return result; + } + + // + // Check Swing Low ... + bool IsBarSwingLow(XOHCL &bar) + { + // + bool result = false; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + // Current Bar Must be Bullish ... + result = bar.IsBullish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev Bar ... + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + // Prev Bar Must be Bearish ... + result = pBar.IsBearish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev of Prev Bar ... + XOHCL ppBar; + result = pBar.GetPreviousBar(ppBar); + if (!result) + { + return result; + } + + // + // Prev of Prev Bar Must be Bearish ... + result = ppBar.IsBearish(); + if (!result) + { + return result; + } + + // + // Check All Lows ... + result = + // + bar.low > pBar.low && + pBar.low < ppBar.low + // + ; + + // + return result; + } + + // + // Find Simple 3 Candle Based Swing Low ... + bool IsSimpleSwingLow( + XOHCL &bar, + double thresholdInPoint = 1 // + ) + { + // + bool result = false; + + // + int index = bar.Index(); + result = index > 0; + if (!result) + { + return result; + } + + // + XOHCL nextBar; + result = bar.GetNextBar(nextBar); + if (!result) + { + return result; + } + + // + XOHCL prevBar; + result = bar.GetPreviousBar(prevBar); + if (!result) + { + return result; + } + + // + double point = GetPoints(bar.symbol); + double requiredOffset = point * thresholdInPoint; + + // + result = + bar.low < nextBar.low && + bar.low < prevBar.low && + (thresholdInPoint <= 0 + ? true + : MathAbs( + MathMax( + nextBar.low, + prevBar.low) - + bar.low) >= requiredOffset); + + // + return result; + } + + // + // Find Last Swing Low ... + bool FindLastSwingLow( + XOHCL &bar, + XOHCL &swing // + ) + { + // + bool result = false; + + // + swing.Clean(); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + int totalBars = iBars( + bar.symbol, + bar.period // + ); + int maxAllowed = MathMin(100, (totalBars / 100)); + + // + int idx = bar.Index(); + for (int i = idx; i <= idx + maxAllowed; i++) + { + // + swing.Clean(); + result = swing.Init( + bar.symbol, + bar.period, + i // + ); + if (!result) + { + // + swing.Clean(); + break; + } + + // + result = IsBarSwingLow(swing); + if (result) + { + break; + } + } + + // + return result; + } + + // + // Check Bullish FVG ... + bool HasBullishFVG( + XOHCL &bar, + double &upper, + double &lower, + datetime &start, + datetime &end, + bool forceMiddleBarCheck = true, + bool forceCheckLastBarDirection = false // + ) + { + // + bool result = false; + + // + upper = 0; + lower = 0; + + // + end = NULL; + start = NULL; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + // Current Bar Must be Bullish ... + result = + !forceCheckLastBarDirection + ? true + : bar.IsBullish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev Bar ... + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + // Prev Bar Must be Bullish ... + result = pBar.IsBullish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev of Prev Bar ... + XOHCL ppBar; + result = pBar.GetPreviousBar(ppBar); + if (!result) + { + return result; + } + + // + // Prev of Prev Bar Must be Bullish ... + result = ppBar.IsBullish(); + if (!result) + { + return result; + } + + // + // Other Conditions ... + result = + // + bar.low > ppBar.high + // + ; + + // + // Check Middle Bar Range ... + if (result && forceMiddleBarCheck) + { + // + result = + // + pBar.high > bar.low && + pBar.low < ppBar.high + // + ; + + // + if (!result) + { + return result; + } + } + + // + if (result) + { + // + end = bar.time; + upper = bar.low; + lower = ppBar.high; + start = ppBar.time; + } + + // + return result; + } + + // + // Check Bearish FVG ... + bool HasBearishFVG( + XOHCL &bar, + double &upper, + double &lower, + datetime &start, + datetime &end, + bool forceMiddleBarCheck = true, + bool forceCheckLastBarDirection = false // + ) + { + // + bool result = false; + + // + upper = 0; + lower = 0; + + // + end = NULL; + start = NULL; + + // + // Validate Content and Ignore 0 Bar + // since it is not Completed ... + result = bar.IsValid() && bar.Index() > 0; + if (!result) + { + return result; + } + + // + // Current Bar Must be Bearish ... + result = + !forceCheckLastBarDirection + ? true + : bar.IsBullish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev Bar ... + XOHCL pBar; + result = bar.GetPreviousBar(pBar); + if (!result) + { + return result; + } + + // + // Prev Bar Must be Bearish ... + result = pBar.IsBearish(); + if (!result) + { + return result; + } + + // + // Retrieve Prev of Prev Bar ... + XOHCL ppBar; + result = pBar.GetPreviousBar(ppBar); + if (!result) + { + return result; + } + + // + // Prev of Prev Bar Must be Bearish ... + result = ppBar.IsBearish(); + if (!result) + { + return result; + } + + // + // Other Conditions ... + result = + // + bar.high < ppBar.low + // + ; + + // + // Check Middle Bar Range ... + if (result && forceMiddleBarCheck) + { + // + result = + // + pBar.high > bar.low && + pBar.low < ppBar.high + // + ; + + // + if (!result) + { + return result; + } + } + + // + if (result) + { + // + end = bar.time; + lower = bar.high; + upper = ppBar.low; + start = ppBar.time; + } + + // + return result; + } + + // + // Find Support ... + bool HasSupport( + XOHCL &bar, + XOHCL &dest, + ENUM_X_PRICE type = X_PRICE_CLOSE, + int _loopback = 21, + int tries = 100 // + ) + { + // + bool result = false; + + // + dest.Clean(); + + // + if (_loopback < 0) + { + _loopback = 21; + } + + // + if (tries < 0) + { + tries = 100; + } + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + double price = bar.GetPrice(type); + + // + for (int i = 1; i < tries; i++) + { + // + int _length = _loopback * i; + + // + int lowestIDX = bar.FindLowestIndex( + _length, + MODE_LOW // + ); + result = IsValidIndex(lowestIDX); + if (!result) + { + break; + } + + // + XOHCL iLBar; + result = iLBar.Init( + bar.symbol, + bar.period, + lowestIDX // + ); + if (!result) + { + break; + } + + // + result = + // + price > iLBar.high + // + ; + if (result) + { + // + dest = iLBar; + break; + } + } + + // + result = dest.IsValid(); + + // + return result; + } + + // + // Find Resistance ... + bool HasResistance( + XOHCL &bar, + XOHCL &dest, + ENUM_X_PRICE type = X_PRICE_CLOSE, + int _loopback = 21, + int tries = 100 // + ) + { + // + bool result = false; + + // + dest.Clean(); + + // + if (_loopback < 0) + { + _loopback = 21; + } + + // + if (tries < 0) + { + tries = 100; + } + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + double price = bar.GetPrice(type); + + // + for (int i = 1; i < tries; i++) + { + // + int _length = _loopback * i; + + // + int highestIDX = bar.FindHighestIndex( + _length, + MODE_LOW // + ); + result = IsValidIndex(highestIDX); + if (!result) + { + break; + } + + // + XOHCL iHBar; + result = iHBar.Init( + bar.symbol, + bar.period, + highestIDX // + ); + if (!result) + { + break; + } + + // + result = + // + price < iHBar.high + // + ; + if (result) + { + // + dest = iHBar; + break; + } + } + + // + result = dest.IsValid(); + + // + return result; + } + + // + // Trend Detection ... + + // + // Find Bullish Trend ... + bool HasBullishTrend( + XOHCL &bar, + XOHCL &highSwingBars[], + XOHCL &lowSwingBars[], + bool forceMethod2 = false, + int _loopback = 3, + int tries = 3, + ENUM_X_PRICE type = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + Clean(lowSwingBars); + Clean(highSwingBars); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + double price = bar.GetPrice(type); + + // + int lastIDX = bar.Index(); + double lastH = 0; + double lastL = 0; + for (int i = 1; i < tries + 1; i++) + { + // + // Use Regular Method ... + if (!forceMethod2) + { + // + int iHIDX = FindSwing( + bar.symbol, + bar.period, + X_SWING_HIGH, + _loopback, + lastIDX // + ); + result = IsValidIndex(iHIDX); + if (!result) + { + break; + } + + // + XOHCL iHBar; + result = iHBar.Init( + bar.symbol, + bar.period, + iHIDX // + ); + if (!result) + { + break; + } + + // + double iH = iHBar.high; + bool isIHAccepted = + // + iH > 0 && + ( + // + lastH == 0 + ? true + : iH < lastH + // + ) + // + ; + if (isIHAccepted) + { + // + AddRef( + iHBar, + highSwingBars // + ); + + // + lastH = iH; + lastIDX = iHIDX; + } + + // + int iLIDX = FindSwing( + bar.symbol, + bar.period, + X_SWING_LOW, + _loopback, + lastIDX // + ); + result = IsValidIndex(iLIDX); + if (!result) + { + break; + } + + // + XOHCL iLBar; + result = iLBar.Init( + bar.symbol, + bar.period, + iLIDX // + ); + if (!result) + { + break; + } + + // + double iL = iLBar.low; + bool isILAccepted = + // + iL > 0 && + ( + // + lastL == 0 + ? true + : iL < lastL + // + ) + // + ; + if (isILAccepted) + { + // + AddRef( + iLBar, + lowSwingBars // + ); + + // + lastL = iL; + lastIDX = iLIDX; + } + } + // + // Use Other MEthod ... + else + { + // + int _length = i * _loopback; + int start = + // + i == 1 + ? 1 + : _length - _loopback + // + ; + + // + int iHIDX = iHighest( + bar.symbol, + bar.period, + MODE_HIGH, + _loopback, + start // + ); + result = IsValidIndex(iHIDX); + if (!result) + { + break; + } + + // + XOHCL iHBar; + result = iHBar.Init( + bar.symbol, + bar.period, + iHIDX // + ); + if (!result) + { + break; + } + + // + double iH = iHBar.high; + bool isIHAccepted = + // + iH > 0 && + ( + // + lastH == 0 + ? true + : iH < lastH + // + ) + // + ; + if (isIHAccepted) + { + // + AddRef( + iHBar, + highSwingBars // + ); + + // + lastH = iH; + lastIDX = iHIDX; + } + + // + int iLIDX = iLowest( + bar.symbol, + bar.period, + MODE_LOW, + _loopback, + start // + ); + result = IsValidIndex(iLIDX); + if (!result) + { + break; + } + + // + XOHCL iLBar; + result = iLBar.Init( + bar.symbol, + bar.period, + iLIDX // + ); + if (!result) + { + break; + } + + // + double iL = iLBar.low; + bool isILAccepted = + // + iL > 0 && + ( + // + lastL == 0 + ? true + : iL < lastL + // + ) + // + ; + if (isILAccepted) + { + // + AddRef( + iLBar, + lowSwingBars // + ); + + // + lastL = iL; + lastIDX = iLIDX; + } + } + } + + // + if (result) + { + // + result = + // + ArraySize(lowSwingBars) == tries && + ArraySize(highSwingBars) == tries + // + ; + } + + // + if (!result) + { + // + Clean(lowSwingBars); + Clean(highSwingBars); + } + + // + return result; + } + + // + // Find Bearish Trend ... + bool HasBearishTrend( + XOHCL &bar, + XOHCL &highSwingBars[], + XOHCL &lowSwingBars[], + bool forceMethod2 = false, + int _loopback = 3, + int tries = 3, + ENUM_X_PRICE type = X_PRICE_CLOSE // + ) + { + // + bool result = false; + + // + Clean(lowSwingBars); + Clean(highSwingBars); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + double price = bar.GetPrice(type); + + // + int lastIDX = bar.Index(); + double lastH = 0; + double lastL = 0; + for (int i = 1; i < tries + 1; i++) + { + // + // Use Regular Method ... + if (!forceMethod2) + { + // + int iHIDX = FindSwing( + bar.symbol, + bar.period, + X_SWING_HIGH, + _loopback, + lastIDX // + ); + result = IsValidIndex(iHIDX); + if (!result) + { + break; + } + + // + XOHCL iHBar; + result = iHBar.Init( + bar.symbol, + bar.period, + iHIDX // + ); + if (!result) + { + break; + } + + // + double iH = iHBar.high; + bool isIHAccepted = + // + iH > 0 && + ( + // + lastH == 0 + ? true + : iH > lastH + // + ) + // + ; + if (isIHAccepted) + { + // + AddRef( + iHBar, + highSwingBars // + ); + + // + lastH = iH; + lastIDX = iHIDX; + } + + // + int iLIDX = FindSwing( + bar.symbol, + bar.period, + X_SWING_LOW, + _loopback, + lastIDX // + ); + result = IsValidIndex(iLIDX); + if (!result) + { + break; + } + + // + XOHCL iLBar; + result = iLBar.Init( + bar.symbol, + bar.period, + iLIDX // + ); + if (!result) + { + break; + } + + // + double iL = iLBar.low; + bool isILAccepted = + // + iL > 0 && + ( + // + lastL == 0 + ? true + : iL > lastL + // + ) + // + ; + if (isILAccepted) + { + // + AddRef( + iLBar, + lowSwingBars // + ); + + // + lastL = iL; + lastIDX = iLIDX; + } + } + // + // Use Other MEthod ... + else + { + // + int _length = i * _loopback; + int start = + // + i == 1 + ? 1 + : _length - _loopback + // + ; + + // + int iHIDX = iHighest( + bar.symbol, + bar.period, + MODE_HIGH, + _loopback, + start // + ); + result = IsValidIndex(iHIDX); + if (!result) + { + break; + } + + // + XOHCL iHBar; + result = iHBar.Init( + bar.symbol, + bar.period, + iHIDX // + ); + if (!result) + { + break; + } + + // + double iH = iHBar.high; + bool isIHAccepted = + // + iH > 0 && + ( + // + lastH == 0 + ? true + : iH > lastH + // + ) + // + ; + if (isIHAccepted) + { + // + AddRef( + iHBar, + highSwingBars // + ); + + // + lastH = iH; + lastIDX = iHIDX; + } + + // + int iLIDX = iLowest( + bar.symbol, + bar.period, + MODE_LOW, + _loopback, + start // + ); + result = IsValidIndex(iLIDX); + if (!result) + { + break; + } + + // + XOHCL iLBar; + result = iLBar.Init( + bar.symbol, + bar.period, + iLIDX // + ); + if (!result) + { + break; + } + + // + double iL = iLBar.low; + bool isILAccepted = + // + iL > 0 && + ( + // + lastL == 0 + ? true + : iL > lastL + // + ) + // + ; + if (isILAccepted) + { + // + AddRef( + iLBar, + lowSwingBars // + ); + + // + lastL = iL; + lastIDX = iLIDX; + } + } + } + + // + if (result) + { + // + result = + // + ArraySize(lowSwingBars) == tries && + ArraySize(highSwingBars) == tries + // + ; + } + + // + if (!result) + { + // + Clean(lowSwingBars); + Clean(highSwingBars); + } + + // + return result; + } + + // + // Order Blocks ... + + // + // Find Bullish Order Block ... + bool HasBullishOrderBlock( + XOHCL &bar, + XOHCL &orderBlock, + int _minimumSameBars = 4 // + ) + { + // + bool result = false; + + // + orderBlock.Clean(); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + if (_minimumSameBars < 0) + { + _minimumSameBars = 4; + } + + // + XOHCL cBar; + int founded = 0; + int cIDX = bar.Index(); + bool isEnough = false; + while (!isEnough) + { + // + result = cBar.Init( + bar.symbol, + bar.period, + cIDX // + ); + if (!result) + { + break; + } + + // + result = cBar.IsBullish(); + if (!result && cBar.IsBearish()) + { + break; + } + + // + cIDX++; + founded++; + } + + // + // Here we have to check founded and if it's fill + // our requirements ... + // cIDX is Order Block Index ... + result = + // + cBar.IsValid() && + bar.high > cBar.high && + founded >= _minimumSameBars + // + ; + if (!result) + { + return result; + } + + // + result = orderBlock.Init( + bar.symbol, + bar.period, + cIDX // + ); + if (!result) + { + // + orderBlock.Clean(); + return result; + } + + // + return result; + } + + // + // Find Bearish Order Block ... + bool HasBearishOrderBlock( + XOHCL &bar, + XOHCL &orderBlock, + int _minimumSameBars = 4 // + ) + { + // + bool result = false; + + // + orderBlock.Clean(); + + // + result = bar.IsValid(); + if (!result) + { + return result; + } + + // + if (_minimumSameBars < 0) + { + _minimumSameBars = 4; + } + + // + XOHCL cBar; + int founded = 0; + int cIDX = bar.Index(); + bool isEnough = false; + while (!isEnough) + { + // + bool isInited = cBar.Init( + bar.symbol, + bar.period, + cIDX // + ); + + // + result = cBar.IsBearish(); + if (!result && cBar.IsBullish()) + { + break; + } + + // + cIDX++; + founded++; + } + + // + // Here we have to check founded and if it's fill + // our requirements ... + // cIDX is Order Block Index ... + result = + // + cBar.IsValid() && + bar.high < cBar.low && + founded >= _minimumSameBars + // + ; + if (!result) + { + return result; + } + + // + result = orderBlock.Init( + bar.symbol, + bar.period, + cIDX // + ); + if (!result) + { + // + orderBlock.Clean(); + return result; + } + + // + return result; + } + + // + protected: + // + + // + private: + // + + // + // Props ... + + // + // Actions ... + + // +}; + +// \ No newline at end of file diff --git a/Documents/BKP/x-tmp.structs.mq5 b/Documents/BKP/x-tmp.structs.mq5 new file mode 100644 index 00000000..f5caf9b5 --- /dev/null +++ b/Documents/BKP/x-tmp.structs.mq5 @@ -0,0 +1,2508 @@ +// +// Structs ... + +// +// Model Specified Ticks Info ... +struct XTick +{ + // + string symbol; // Symbol ... + datetime time; // Time ... + double bid; // Bid ... + double ask; // Ask ... + double spread; // Spread ... + long volume; // Volume ... + + // + // Constructor ... + void XTick() + { + Clean(); + } + + // + // Tools Functions ... + + /** + * Initial ... + * + * @param _symbol: Symbol ... + * @param _time: Time ... + * @param _bid: Bid Price ... + * @param _ask: Ask Price ... + * @param _volume: Tick Volume ... + */ + bool Init( + string _symbol, + datetime _time, + double _bid, + double _ask, + double _spread, + long _volume // + ) + { + // + bool result = false; + + // + result = IsValid(_symbol) && + IsValid(_time) && + _bid > 0 && + _ask > 0; + if (!result) + { + return result; + } + + // + bid = _bid; + ask = _ask; + time = _time; + symbol = _symbol; + spread = _spread; + + // + result = IsValid(); + + // + return result; + } + + /** + * Init Tick by Symbol ... + * + * @param _symbol: String ... + * + * @return ( bool ) + */ + bool Init( + string _symbol, + ENUM_TIMEFRAMES _volumePeriod = NULL // + ) + { + // + bool result = false; + + // + result = IsValid(_symbol); + if (!result) + { + return result; + } + + // + datetime _time = TimeCurrent(); + double _bid = GetBid(_symbol); + double _ask = GetAsk(_symbol); + double _spread = GetSpread(_symbol); + + // + long _volume = 0; + if (IsValid(_volumePeriod)) + { + _volume = iTickVolume(_symbol, _volumePeriod, 0); + } + + // + result = Init( + _symbol, + _time, + _bid, + _ask, + _spread, + _volume // + ); + + // + return result; + } + + /** + * Cleanup ... + */ + void Clean() + { + // + bid = 0; + ask = 0; + volume = 0; + time = NULL; + symbol = NULL; + + // + ZeroMemory(this); + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = IsValid(symbol) && + IsValid(time) && + bid > 0 && + ask > 0 && + volume >= 0; + + // + return result; + } + + // +}; + +// +// Model a Market Cycle ... +struct XMarketCycle +{ + // + // Props ... + + // + string prefix; // Prefix Trag ... + + // + string symbol; // Market Symbol ... + + // + ENUM_TIMEFRAMES period; // Period of Cycle ... + ENUM_X_PERIOD_METHOD method; // Period Selection Method ... + ENUM_X_MARKET_CYCLES cycle; // Cycles of MArket ... + + // + int length; // Number Of Candles per Current Time Frame ... + ENUM_TIMEFRAMES hostPeriod; // Current Time Frame ... + + // + datetime lastStart; // Last Candle Bar Time ... + + // + XBarTracker barTracker; // Bar Tracker ... + XBarRemainsTime remains; // Current Bar Remains Model ... + + // + // Constructor ... + XMarketCycle() + { + Clean(); + } + + // + // Init Cycle ... + bool Init( + string mSymbol, // Trading Symbol + ENUM_TIMEFRAMES mHostPeriod, // Host Period + ENUM_X_MARKET_CYCLES mCycle, // Init Cycle + string mPrefix = "" // Prefix + ) + { + // + bool result = false; + + // + mSymbol = NormalizeSymbol(mSymbol); + mHostPeriod = NormalizePeriod(mHostPeriod); + + // + result = IsValid(mCycle); + if (!result) + { + return result; + } + + // + this.cycle = mCycle; + + // + // Set Automatically Prefix ... + if (StringLen(mPrefix) == 0) + { + this.prefix = ToString(cycle); + } + + // + result = IsValid( + method, + period // + ); + if (!result) + { + return result; + } + + // + this.symbol = mSymbol; + this.hostPeriod = mHostPeriod; + + // + // Find Cycle Period ... + if (method == X_PERIOD_AUTO) + { + // + // Select Period ... + this.period = GetCyclePeriod( + this.cycle, + this.hostPeriod); + } + + // + // Set Prefix if Provided ... + if (StringLen(mPrefix) > 0) + { + this.prefix = mPrefix; + } + + // + // Calculate Required Info ... + + // + // Length ... + this.length = PeriodSeconds(this.period) / PeriodSeconds(this.hostPeriod); + + // + // Update Additional Data ... + result = this.Update(0); + + // + return result; + } + + // + bool Init( + string mSymbol, // Trading Symbol + ENUM_TIMEFRAMES mHostPeriod, // Host Period + ENUM_X_MARKET_CYCLES mCycle, // Init Cycle + ENUM_X_PERIOD_METHOD mMethod, // Period Selection Method + ENUM_TIMEFRAMES mPeriod, // Provided Period + string mPrefix = "" // Prefix + ) + { + // + this.period = mPeriod; + this.method = mMethod; + + // + return Init( + mSymbol, + mHostPeriod, + mCycle, + mPrefix + // + ); + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + // + length = 0; + lastStart = 0; + + // + cycle = NULL; + prefix = NULL; + symbol = NULL; + period = NULL; + method = NULL; + hostPeriod = NULL; + + // + remains.Clean(); + barTracker.Clean(); + + // + ZeroMemory(this); + } + + // + // Check Structure Valid ... + bool IsValid() + { + // + bool result = false; + + // + result = IsValid( + method, + period); + if (!result) + { + return result; + } + + // + result = + // + length > 0 && + symbol != NULL && + period != NULL && + method != NULL && + hostPeriod != NULL && + method != X_PERIOD_NONE + // + ; + + // + return result; + } + + // + // Update Market Cycle Additional Info ... + bool Update(int hostBarIndex) + { + // + bool result = false; + + // + result = this.IsValid(); + if (!result) + { + return result; + } + + // + // Init Remains ... + result = remains.Init( + this.symbol, + this.period); + if (!result) + { + return result; + } + + // + // Init Bar Tracker ... + result = barTracker.Init( + this.symbol, + this.period); + if (!result) + { + return result; + } + + // + return result; + } + + // + // Count Bars ... + int CountBars() + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = barTracker.CountBars(); + + // + return result; + } + + // + // Check New Bar ... + bool IsNewBar() + { + // + bool result = false; + + // + if (!IsValid()) + { + return result; + } + + // + result = barTracker.IsNewBar(); + + // + return result; + } + + // + // Retrieve Current Bar Index based on Host Period bar Index ... + int GetBarIndex(int barIndex) + { + // + int result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + if (barIndex < 0) + { + return result; + } + + // + int totalBars = CountBars(); + if (barIndex >= totalBars) + { + // + result = totalBars - 1; + return result; + } + + // + datetime hostBarTime = iTime( + this.symbol, + this.hostPeriod, + barIndex + // + ); + + // + result = iBarShift( + this.symbol, + this.period, + hostBarTime + // + ); + + // + return result; + } + + // + // Retrieve Current Cycles Specific Bar ... + XOHCL GetBar(int barIndex) + { + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int totalBars = CountBars(); + if (barIndex >= totalBars) + { + barIndex = totalBars - 1; + } + + // + XOHCL result; + result.Init( + this.symbol, + this.period, + barIndex + // + ); + + // + return result; + } + + // + // Extract Specific Range of Bars ... + // using Start Bar Index ... + int GetBars( + XOHCL &result[], // Hold Result + int from = 0, // Start Bar Index + int count = 1, // Number of Bars + bool forceClean = true // Clean Result Array + ) + { + // + int mResult = 0; + + // + if (from < 0) + { + from = 0; + } + + // + int total = Bars( + symbol, + period); + if (from > total - 2) + { + from = total - 2; + } + + // + if (count < 0) + { + count = 1; + } + + // + int start = from; + int end = start + count; + if (end > total - 1) + { + end = total - 1; + } + + // + if (forceClean) + { + Clean(result); + } + + // + int beforeSize = ArraySize(result); + + // + for (int i = start; i < end; i++) + { + // + XOHCL iBar; + bool isValid = iBar.Init( + symbol, + period, + i + // + ); + + // + if (isValid) + { + // + AddRef( + iBar, + result + // + ); + } + } + + // + int afterSize = ArraySize(result); + + // + mResult = afterSize - beforeSize; + + // + return mResult; + } + + // + // Extract Specific Range of Bars ... + // using Start Bar Time ... + int GetBars( + XOHCL &bars[], // Hold Result + datetime from = NULL, // Start Bar Time + int count = 1 // Number of Bars + ) + { + // + from = NormalizeTime(from); + + // + return GetBars( + bars, + symbol, + period, + from, + count // + ); + } + + // + // Retrieve Bar Time ... + datetime GetBarTime(int barIndex) + { + // + datetime result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + if (barIndex < 0) + { + barIndex = 0; + } + + // + int totalBars = CountBars(); + if (barIndex >= totalBars) + { + barIndex = totalBars - 1; + } + + // + result = iTime( + this.symbol, + this.period, + barIndex + // + ); + + // + return result; + } + + // + // Find Chart ID ... + ulong GetChartID() + { + // + ulong result = 0; + + // + long firstChart = ChartFirst(); + result = firstChart; + + // + while (result >= 0) + { + // + string chSymbol = ChartSymbol(result); + ENUM_TIMEFRAMES chPeriod = ChartPeriod(result); + + // + bool isOwnChart = + // + symbol == chSymbol && + period == chPeriod + // + ; + if (isOwnChart) + { + break; + } + + // + result = ChartNext(result); + if (result < 0) + { + break; + } + } + + // + return result; + } + + // + // Create and String Representation for Unique Taging ... + string ToString() + { + // + string result = ""; + + // + if (!IsValid()) + { + return result; + } + + // + result = + GetTypeName(this) + "(" + + "PRFX(" + this.prefix + ")" + + "SMBL(" + this.symbol + ")" + + "CYC(" + ToString(this.cycle) + ")" + + "PRD(" + ToString(this.period) + ")" + + "PRDHST(" + ToString(this.hostPeriod) + ")" + + "MTH(" + EnumToString(this.method) + ")" + + ")"; + + // + return result; + } + + // + // Here we Produce a Summary brief of + // state of Cycle ... + string GenerateSummary() + { + // + string result = ""; + + // + bool hasPrefix = + StringLen(this.prefix) > 0 && + this.prefix != ToString(this.cycle); + result += (hasPrefix ? this.prefix + "[" : "") + + ToString(this.cycle) + + (hasPrefix ? "]" : "") + "\n"; + + // + result += " - PR: " + ToString(this.period) + "\n"; + + // + XOHCL cBar = GetBar(0); + + // + result += " - State: " + (cBar.IsBullish() ? "Bullish" : cBar.IsBearish() ? "Bearish" + : "Neutural"); + + // + return result; + } +}; + +// +// Linear Regression ... + +// +struct XLinearRegressionWorkStruct +{ + // + struct sDataStruct + { + // + double value; + double sumY; + double sumXY; + }; + + // + sDataStruct data[]; + + // + int dataSize; + int period; + double sumX; + double sumXX; + double divisor; + + // + // Constructor ... + XLinearRegressionWorkStruct() + : dataSize(-1), period(-1) + { + } +}; + +// +struct XLinearRegression +{ + // + XLinearRegressionWorkStruct m_work; + + // + // Calculate Linear Regression ... + double Calculate( + double value, + int period, + double &_slope, + double &_intercept, + int r, + int bars // + ) + { + // + if (m_work.dataSize <= bars) + { + m_work.dataSize = ArrayResize(m_work.data, bars + 500, 2000); + } + + // + if (period < 1) + { + period = 1; + } + + // + if (m_work.period != (int)period) + { + // + m_work.period = (int)period; + m_work.sumX = m_work.period * (m_work.period - 1.0) / 2.0; + m_work.sumXX = m_work.period * (m_work.period - 1.0) * (2.0 * m_work.period - 1.0) / 6.0; + m_work.divisor = m_work.sumX * m_work.sumX - m_work.period * m_work.sumXX; + + // + if (m_work.divisor) + { + m_work.divisor = 1.0 / m_work.divisor; + } + } + + // + m_work.data[r].value = value; + + // + if (r >= m_work.period) + { + // + m_work.data[r].sumY = m_work.data[r - 1].sumY + value - m_work.data[r - m_work.period].value; + m_work.data[r].sumXY = m_work.data[r - 1].sumXY + m_work.data[r].sumY - m_work.data[r - m_work.period].value * (m_work.period - 1.0) - value; + } + else + { + // + m_work.data[r].sumY = value; + m_work.data[r].sumXY = 0; + + // + for (int _k = 1; _k < m_work.period && r >= _k; _k++) + { + // + m_work.data[r].sumY += m_work.data[r - _k].value; + m_work.data[r].sumXY += _k * m_work.data[r - _k].value; + } + } + + // + _slope = (m_work.period * m_work.data[r].sumXY - m_work.sumX * m_work.data[r].sumY) * m_work.divisor; + _intercept = (m_work.data[r].sumY - _slope * m_work.sumX) / (double)m_work.period; + + // + double result = (_intercept + _slope * (m_work.period - 1.0)); + + // + return result; + } + + // +}; + +// +// Use To Parse Symbols for +// Ignore Brokers Additional Suffixes ... +struct XSymbolParser +{ + // + string version; // Temp ... + + // + // Symbol Parsing ... + + // + // Forext ... + + // + bool IsEURUSD(string symbol) + { + // + string symbolIdentifiers[] = { + "EUR", + "USD" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsUSDJPY(string symbol) + { + // + string symbolIdentifiers[] = { + "USD", + "JPY" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsEURJPY(string symbol) + { + // + string symbolIdentifiers[] = { + "EUR", + "JPY" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsUSDCHF(string symbol) + { + // + string symbolIdentifiers[] = { + "USD", + "CHF" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsEURCHF(string symbol) + { + // + string symbolIdentifiers[] = { + "EUR", + "CHF" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsGBPUSD(string symbol) + { + // + string symbolIdentifiers[] = { + "GBP", + "USD" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsEURGBP(string symbol) + { + // + string symbolIdentifiers[] = { + "EUR", + "GBP" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsAUDUSD(string symbol) + { + // + string symbolIdentifiers[] = { + "AUD", + "USD" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsEURAUD(string symbol) + { + // + string symbolIdentifiers[] = { + "EUR", + "AUD" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsUSDCAD(string symbol) + { + // + string symbolIdentifiers[] = { + "USD", + "CAD" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsEURCAD(string symbol) + { + // + string symbolIdentifiers[] = { + "EUR", + "CAD" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsNZDUSD(string symbol) + { + // + string symbolIdentifiers[] = { + "NZD", + "USD" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsEURNZD(string symbol) + { + // + string symbolIdentifiers[] = { + "EUR", + "NZD" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + // Metals ... + + // + bool IsXAUUSD(string symbol) + { + // + string symbolIdentifiers[] = { + "XAU", + "USD" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + bool IsXAGUSD(string symbol) + { + // + string symbolIdentifiers[] = { + "XAG", + "USD" // + }; + + // + bool result = Contains( + symbolIdentifiers, + symbol // + ); + + // + return result; + } + + // + // Indexes ... + + // + bool IsDowJones(string symbol) + { + // + bool result = Contains( + "DowJones30", + symbol // + ); + + // + return result; + } + + // + // Oil ... + + // + bool IsBrent(string symbol) + { + // + bool result = Contains( + "BRENT", + symbol // + ); + + // + return result; + } + + // + // Symbol Finder ... + string GetEURUSDSymbol() + { + // + string result = NULL; + + // + string symbols[]; + int symbolsCount = GetAllSymbols( + symbols // + ); + if (!IsValidSize(symbolsCount)) + { + return result; + } + + // + for (int i = 0; i < symbolsCount; i++) + { + // + string iSymbol = symbols[i]; + if (IsEURUSD(iSymbol)) + { + // + result = iSymbol; + break; + } + } + + // + return result; + } +}; + +// +struct XSymbolSessionParser +{ + // + string version; // Temp ... + + // + // Check Market Is Open for Specific Symbol + // in Current Time ... + bool CanTrade( + string symbol // Trading Symbol + ) + { + // + bool result = false; + + // + result = IsValid(symbol); + if (!result) + { + return result; + } + + // + MqlDateTime timeStruct; + result = TimeCurrent(timeStruct); + if (!result) + { + return result; + } + + // + ENUM_DAY_OF_WEEK dayOfWeek = (ENUM_DAY_OF_WEEK)timeStruct.day_of_week; + + // + datetime cTime = TimeCurrent(); + + // + datetime from; + datetime to; + result = SymbolInfoSessionTrade( + symbol, + dayOfWeek, + 0, // Session Index ... + from, + to // + ); + if (!result) + { + return result; + } + + // + result = cTime > from && cTime < to; + + // + return result; + } +}; + +// +// Parsing Market Names ... +struct XMarketParser +{ + // + string _version; // Temp ... + + // + bool IsIngot(string market) + { + // + bool result = false; + + // + // result = IsValid(market) && + // market == ""; + + // + return result; + } + + // + bool IsErrante(string market) + { + // + bool result = false; + + // + // result = IsValid(market) && + // market == ""; + + // + return result; + } + + // + bool IsAMarkets(string market) + { + // + bool result = false; + + // + result = IsValid(market) && + market == "AMarkets LLC"; + + // + return result; + } + + // + bool IsIFCMarkets(string market) + { + // + bool result = false; + + // + // result = IsValid(market) && + // market == ""; + + // + return result; + } + + // + bool IsOtetMarkets(string market) + { + // + bool result = false; + + // + // result = IsValid(market) && + // market == ""; + + // + return result; + } + + // +}; + +// +struct XPoint +{ + // + // Props ... + double value; + datetime at; + + // + XPoint() + { + Clean(); + } + + // + // Tools ... + + // + void Clean() + { + // + value = 0; + at = NULL; + + // + ZeroMemory(this); + } + + // + bool IsValid() + { + // + return value > 0 && + IsValid(at); + } + + // +}; + +// +// Specified Swing Point ... +struct XSwingPoint +{ + // + // Props ... + string symbol; + ENUM_TIMEFRAMES period; + + // + double swing; + datetime time; + ENUM_X_SWING_TYPE type; + + // + // Constructor ... + XSwingPoint() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup Model ... + */ + void Clean() + { + // + swing = 0; + time = NULL; + + // + symbol = NULL; + period = NULL; + + // + type = X_NO_SWING; + } + + /** + * Validate Model ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + swing > 0 && + IsValid(time) && + IsValid(symbol) && + IsValid(period) && + type != X_NO_SWING; + + // + return result; + } + + /** + * Check Swing is Low or not ... + * + * @return ( bool ) + */ + bool IsSwingLow() + { + return type == X_SWING_LOW; + } + + /** + * Check Swing is High or not ... + * + * @return ( bool ) + */ + bool IsSwingHigh() + { + return type == X_SWING_HIGH; + } +}; + +// +// Consolidation Zone ... +struct XConsolidationZone +{ + // + // Props ... + + // + string symbol; // Symbol ... + ENUM_TIMEFRAMES period; // Period ... + + // + double upper; // Upper ... + double lower; // Lower ... + + // + datetime from; // Start Date + datetime to; // Breake Date + + // + ENUM_X_DIRECTION dir; // Break Direction ... + + // + // Constructor ... + XConsolidationZone() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleanup ... + */ + void Clean() + { + // + upper = 0; + lower = 0; + + // + to = NULL; + from = NULL; + symbol = NULL; + period = NULL; + dir = X_DIRECTION_NONE; + + // + ZeroMemory(this); + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + // + upper > 0 && + lower > 0 && + IsValid(to) && + IsValid(from) && + IsValid(symbol) && + IsValid(period) && + HasDirection(dir) + // + ; + + // + return result; + } + + bool IsSameAs( + XConsolidationZone &item // + ) + { + // + bool result = false; + + // + result = IsValid() && + item.IsValid() && + dir == item.dir && + from == item.from && + upper == item.upper && + lower == item.lower && + symbol == item.symbol && + period == item.period; + + // + return result; + } + + /** + * Retrieve Unique Identifier ... + * + * @return ( string ) + */ + string GetTag() + { + // + string result = + // + "XCZONE" + "_" + + ToString(dir) + "_" + + symbol + "_" + + ToString(period) + "_" + + ToString(upper) + "_" + + ToString(lower) + // + ; + + // + return result; + } + + // +}; + +// +// +// + +class XCRRObject : public XCBaseObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param rr: XRR instance Reference ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XRR &rr, + string prefix = NULL // + ) + { + // + bool result = false; + + // + result = rr.IsValid(); + if (!result) + { + return result; + } + + // + string name = rr.GetTag(); + if (IsValid(prefix)) + { + name = prefix + "_" + name; + } + string nameMD5 = ToMD5(name); + + // + bool isLong = IsLong(rr.type); + + // + double price1 = rr.entry; + double price2 = rr.sl; + + // + datetime time1 = rr.time; + datetime time2 = (datetime)((int)rr.time + 5 * PeriodSeconds(rr.period)); + + // + result = mFibo.Create( + chart_id, + name, + window, + time1, + price1, + time2, + price2 // + ); + if (!result) + { + return result; + } + + // + mRR = rr; + ObjName(name); + + // + int tpsCount = ArraySize(rr.tps); + int levels = tpsCount + 2; + result = mFibo.LevelsCount(levels); + if (!result) + { + return result; + } + + // + // Set Fibo Levels ... + + // + result = mFibo.LevelValue(0, 0); + if (!result) + { + return result; + } + result = mFibo.LevelDescription(0, "SL"); + if (!result) + { + return result; + } + + // + result = mFibo.LevelValue(1, 1.0); + if (!result) + { + return result; + } + result = mFibo.LevelDescription(1, "Entry"); + if (!result) + { + return result; + } + + // + for (int i = 0; i < tpsCount; i++) + { + // + int idx = i + 2; + double level = 1.0 + rr.tps[i]; + string description = "TP " + ToString(rr.tps[i]); + + // + result = mFibo.LevelValue( + idx, + level // + ); + if (!result) + { + break; + } + + // + result = mFibo.LevelDescription( + idx, + description // + ); + if (!result) + { + break; + } + } + if (!result) + { + return result; + } + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_RR_OBJ; + } + + // + private: + // + + // + // Props ... + XRR mRR; + CChartObjectFibo mFibo; + + // + bool SetSLProps( + int width = 1, + color clr = clrRed, + ENUM_LINE_STYLE style = STYLE_SOLID, + string description = "" // + ) + { + // + bool result = false; + + // + result = SetLevelProps( + 0, + width, + clr, + style, + description // + ); + + // + return result; + } + + // + bool SetEntryProps( + int width = 1, + color clr = clrOrange, + ENUM_LINE_STYLE style = STYLE_SOLID, + string description = "" // + ) + { + // + bool result = false; + + // + result = SetLevelProps( + 0, + width, + clr, + style, + description // + ); + + // + return result; + } + + // + bool SetTPProps( + double tpValue, + int width = 1, + color clr = clrLime, + ENUM_LINE_STYLE style = STYLE_SOLID, + string description = "" // + ) + { + // + bool result = false; + + // + int tpIDX = FindIndex( + tpValue, + mRR.tps // + ); + result = IsValidIndex(tpIDX); + if (!result) + { + return result; + } + + // + tpIDX += 2; + + // + result = SetLevelProps( + tpIDX, + width, + clr, + style, + description // + ); + + // + return result; + } + + // + bool SetLevelProps( + int id, + int width = 1, + color clr = clrYellow, + ENUM_LINE_STYLE style = STYLE_SOLID, + string description = "" // + ) + { + // + bool result = false; + + // + // Color ... + result = mFibo.LevelColor( + id, + clr // + ); + if (!result) + { + return result; + } + + // + // Style ... + result = mFibo.LevelStyle( + id, + style // + ); + if (!result) + { + return result; + } + + // + // Width ... + if (width > 0) + { + // + result = mFibo.LevelWidth( + id, + width // + ); + if (!result) + { + return result; + } + } + + // + // Description ... + if (IsValid(description)) + { + // + result = mFibo.LevelDescription( + id, + description // + ); + if (!result) + { + return result; + } + } + + // + return result; + } +}; + +class XCTrendObject : public XCBaseObject +{ + // + public: + // + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param rr: XRR instance Reference ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XPoint &swings[], + bool useMinAsStart = true, + string prefix = NULL // + ) + { + // + bool result = false; + + // + int count = ArraySize(swings); + result = + count >= 2 && + IsValidSize(count); + if (!result) + { + return result; + } + + // + double min = 0; + datetime minAt = NULL; + + // + double max = 0; + datetime maxAt = NULL; + + // + // Etract Min/Max ... + for (int i = 0; i < count; i++) + { + // + XPoint iPoint = swings[i]; + + // + if (!iPoint.IsValid()) + { + // + iPoint.Clean(); + continue; + } + + // + bool canSetMin = + min == 0 + ? true + : min > iPoint.value; + if (canSetMin) + { + // + minAt = iPoint.at; + min = iPoint.value; + } + + // + bool canSetMax = + max == 0 + ? true + : max < iPoint.value; + if (canSetMax) + { + // + maxAt = iPoint.at; + max = iPoint.value; + } + + // + iPoint.Clean(); + } + + // + double first = + useMinAsStart + ? min + : max; + datetime firstTime = + useMinAsStart + ? minAt + : maxAt; + + // + double second = + useMinAsStart + ? max + : min; + datetime secondTime = + useMinAsStart + ? maxAt + : minAt; + + // + // Validate Points ... + result = + // + first > 0 && + second > 0 && + (useMinAsStart + ? first <= second + : first >= second) && + IsSpecifiedValid(firstTime) && + IsSpecifiedValid(secondTime) + // + ; + if (!result) + { + return result; + } + + // + ENUM_X_DIRECTION dir = + useMinAsStart + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + string name = "XTRND" + ToString(dir) + "_" + ToString(first) + "_" + ToString(second); + if (IsValid(prefix)) + { + name = prefix + "_" + name; + } + string nameMD5 = ToMD5(name); + + // + result = mTrend.Create( + chart_id, + name, + window, + firstTime, + first, + secondTime, + second // + ); + if (!result) + { + return result; + } + + // + ObjName(name); + + // + return result; + } + + /** + * Creator ... + * + * @param chart_id: Long, Specified Chart ID ... + * @param window: Integer, Specified Chart Window ID ... + * @param rr: XRR instance Reference ... + * @param prefix: String ... + * + * @return ( bool ) + */ + bool Create( + long chart_id, + int window, + XSwingPoint &swings[], + string prefix = NULL // + ) + { + // + bool result = false; + + // + int count = ArraySize(swings); + result = + count >= 2 && + IsValidSize(count); + if (!result) + { + return result; + } + + // + ENUM_X_SWING_TYPE type = swings[0].type; + bool isSwingLows = type == X_SWING_LOW; + + // + double values[]; + int valuesCount = ExtractSwings( + swings, + values // + ); + result = valuesCount == count; + if (!result) + { + return result; + } + + // + int firstIDX = -1; + double first = 0; + datetime firstTime = NULL; + + // + int secondIDX = -1; + double second = 0; + datetime secondTime = NULL; + + // + if (isSwingLows) + { + // + first = GetMin( + values, + firstIDX, + 0, + 0 // + ); + if (IsValidIndex(firstIDX)) + { + // + firstTime = swings[firstIDX].time; + + // + second = FindBiggerThan( + first, + values, + true // + ); + secondIDX = FindIndex( + second, + values // + ); + if (IsValidIndex(secondIDX)) + { + secondTime = swings[secondIDX].time; + } + } + } + else + { + // + first = GetMax( + values, + firstIDX, + 0, + 0 // + ); + if (IsValidIndex(firstIDX)) + { + // + firstTime = swings[firstIDX].time; + + // + second = FindLesserThan( + first, + values, + true // + ); + secondIDX = FindIndex( + second, + values // + ); + if (IsValidIndex(secondIDX)) + { + secondTime = swings[secondIDX].time; + } + } + } + + // + // Validate Points ... + result = + // + IsValidIndex(firstIDX) && + IsValidIndex(secondIDX) && + // + IsSpecifiedValid(firstTime) && + IsSpecifiedValid(secondTime) && + // + (isSwingLows + ? first < second + : first > second) + // + ; + if (!result) + { + return result; + } + + // + string name = ToString(type) + "_" + ToString(first) + "_" + ToString(second); + if (IsValid(prefix)) + { + name = prefix + "_" + name; + } + string nameMD5 = ToMD5(name); + + // + result = mTrend.Create( + chart_id, + name, + window, + firstTime, + first, + secondTime, + second // + ); + if (!result) + { + return result; + } + + // + ObjName(name); + + // + return result; + } + + // + // Getter(s) / Setter(s) ... + + /** + * Set Trend Color ... + * + * @param value: Color ... + */ + void TrendColor(color value) + { + mTrend.Color(value); + } + + void TrendRayLeft(bool value) + { + mTrend.RayLeft(value); + } + + void TrendRayRight(bool value) + { + mTrend.RayRight(value); + } + + // + // Virtual ... + + /** + * Retrieve Object Type ... + * + * @return ( ENUM_XCHARTOBJECTS ) + */ + virtual ENUM_XCHARTOBJECTS Type() + { + return X_TREND_OBJ; + } + + // + private: + // + + // + // Props ... + CChartObjectTrend mTrend; +}; + +// +// +// + +/** + * Create Trend Line Object ... + * + * @param swings: XSwingPoint instance Collection ... + * + * @return ( bool ) + */ +bool CreateTrend( + XSwingPoint &swings[], + XCTrendObject *&object // +) +{ + // + bool result = false; + + // + object = NULL; + + // + result = ArraySize(swings) >= 2 && + IsValidSize(ArraySize(swings)); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + object = new XCTrendObject(); + result = object.Create( + chartID, + window, + swings, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + color clrTrend = swings[0].type == X_SWING_LOW + ? SwingLowColor() + : SwingHighColor(); + object.TrendColor(clrTrend); + object.TrendRayRight(true); + + // + return result; +} + +/** + * Create Trend Line Object ... + * + * @param swings: XSwingPoint instance Collection ... + * @param useMinAsStart: Specified Min Value as Start ... + * + * @return ( bool ) + */ +bool CreateTrend( + XPoint &swings[], + XCTrendObject *&object, + bool useMinAsStart = true // +) +{ + // + bool result = false; + + // + object = NULL; + + // + result = ArraySize(swings) >= 2 && + IsValidSize(ArraySize(swings)); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + object = new XCTrendObject(); + result = object.Create( + chartID, + window, + swings, + useMinAsStart, + prefix // + ); + + // + if (!result) + { + return result; + } + + // + color clrTrend = useMinAsStart + ? SwingLowColor() + : SwingHighColor(); + object.TrendColor(clrTrend); + object.TrendRayRight(true); + + // + return result; +} + +/** + * Create Specific Risk Reward (RR) on Chart ... + * + * @param rr: XRR instance Reference ... + * + * @return ( bool ) + */ +bool CreateRR( + XRR &rr, + XCRRObject *&object // +) +{ + // + bool result = false; + + // + object = NULL; + + // + result = rr.IsValid(); + if (!result) + { + return result; + } + + // + string prefix = Prefix(); + long chartID = ChartIdentification(); + int window = SubWindowIdentification(); + + // + object = new XCRRObject(); + result = object.Create( + chartID, + window, + rr, + prefix // + ); + if (!result) + { + return result; + } + + // + return result; +} + +// \ No newline at end of file diff --git a/Documents/BKP/x121.usin-xtrend.mq5 b/Documents/BKP/x121.usin-xtrend.mq5 new file mode 100644 index 00000000..ec2b5cae --- /dev/null +++ b/Documents/BKP/x121.usin-xtrend.mq5 @@ -0,0 +1,4637 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Helper Class Library +// ---------------------------------------------- +// Name: XCX121Helper +// Description: provides all Indicator +// Helper requirements ... +// +// +// 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 "../Helpers/x-saherelm.x121.x3ma.helper.mq5" +#include "../Helpers/x-saherelm.x121.xatr.helper.mq5" +#include "../Helpers/x-saherelm.x121.xcc.helper.mq5" +#include "../Helpers/x-saherelm.x121.xche.helper.mq5" +#include "../Helpers/x-saherelm.x121.xdon.helper.mq5" +#include "../Helpers/x-saherelm.x121.xhk.helper.mq5" +#include "../Helpers/x-saherelm.x121.xmas.helper.mq5" +#include "../Helpers/x-saherelm.x121.xpv.helper.mq5" +#include "../Helpers/x-saherelm.x121.xstr.helper.mq5" +#include "../Helpers/x-saherelm.x121.xtrend.helper.mq5" +#include "../Helpers/x-saherelm.x121.xvwap.helper.mq5" + +// +// Inputs ... +struct X121Inputs +{ + // + // Props ... + bool showRSI; + X121XCCInputs xccInputs; + X121XPVInputs xpvInputs; + X121XHKInputs xhkInputs; + X121XMASInputs xmasInputs; + X121XATRInputs xatrInputs; + X121XSTRInputs xstrInputs; + X121XCHEInputs xcheInputs; + X121XDONInputs xdonInputs; + X121X3MAInputs x3maInputs; + X121XVWAPInputs xvwapInputs; + X121XTRENDInputs xtrendInputs; + + // + // Constructor ... + X121Inputs() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + xccInputs.Clean(); + xpvInputs.Clean(); + xhkInputs.Clean(); + xmasInputs.Clean(); + xatrInputs.Clean(); + xstrInputs.Clean(); + xcheInputs.Clean(); + xdonInputs.Clean(); + xvwapInputs.Clean(); + xtrendInputs.Clean(); + + // + ZeroMemory(this); + } + + /** + * Set Default Values ... + */ + void Default() + { + // + xccInputs.Default(); + xpvInputs.Default(); + xhkInputs.Default(); + xmasInputs.Default(); + xatrInputs.Default(); + xstrInputs.Default(); + xcheInputs.Default(); + xdonInputs.Default(); + x3maInputs.Default(); + xvwapInputs.Default(); + xtrendInputs.Default(); + } + + /** + * Validate ... + * + * @return ( bool ) + */ + bool IsValid() + { + // + bool result = false; + + // + result = + // + xccInputs.IsValid() && + xpvInputs.IsValid() && + xhkInputs.IsValid() && + xmasInputs.IsValid() && + xatrInputs.IsValid() && + xstrInputs.IsValid() && + xcheInputs.IsValid() && + xdonInputs.IsValid() && + xvwapInputs.IsValid() && + xtrendInputs.IsValid() + // + ; + + // + return result; + } + + /** + * Extract Max Input Length ... + * + * @return ( int ) + */ + int Max() + { + // + int result = 0; + + // + int xpvMax = xpvInputs.Max(); + int xhkMax = xpvInputs.Max(); + int xmasMax = xpvInputs.Max(); + int xatrMax = xatrInputs.Max(); + int xstrMax = xstrInputs.Max(); + int xcheMax = xcheInputs.Max(); + int xdonMax = xdonInputs.Max(); + int xvwapMax = xvwapInputs.Max(); + int xtrendMax = xtrendInputs.Max(); + + // + result = MathMax(xpvMax, xhkMax); + result = MathMax(result, xmasMax); + result = MathMax(result, xatrMax); + result = MathMax(result, xstrMax); + result = MathMax(result, xcheMax); + result = MathMax(result, xdonMax); + result = MathMax(result, xvwapMax); + result = MathMax(result, xtrendMax); + + // + return result; + } +}; + +// +// Conditions ... +struct X121Conditions +{ + // + // Common ... + string symbol; + ENUM_TIMEFRAMES period; + datetime time; + + // + // Buffers ... + double maBuffer[]; + double rsiBuffer[]; + double atrBuffer[]; + double strBuffer[]; + double le1Buffer[]; + double se1Buffer[]; + double le2Buffer[]; + double se2Buffer[]; + double sarBuffer[]; + double cHHBuffer[]; + double cLLBuffer[]; + double sHHBuffer[]; + double sLLBuffer[]; + double mHHBuffer[]; + double mLLBuffer[]; + double lHHBuffer[]; + double lLLBuffer[]; + double hHHBuffer[]; + double hLLBuffer[]; + double upTBuffer[]; + double adxBuffer[]; + double adxPBuffer[]; + double adxMBuffer[]; + long volumeBuffer[]; + double peaksBuffer[]; + double valesBuffer[]; + double strUpBuffer[]; + double downTBuffer[]; + double masMidBuffer[]; + double masUpperBuffer[]; + double masLowerBuffer[]; + double strDownBuffer[]; + double vwapMidBuffer[]; + double upTrendBuffer[]; + double x3maMidBuffer[]; + double le1StartBuffer[]; + double se1StartBuffer[]; + double le2StartBuffer[]; + double se2StartBuffer[]; + double strPriceBuffer[]; + double atrUpperBuffer[]; + double atrLowerBuffer[]; + double strStateBuffer[]; + double vwapFastBuffer[]; + double vwapSlowBuffer[]; + double xhkSMLowBuffer[]; + double x3maFastBuffer[]; + double x3maSlowBuffer[]; + double supportsBuffer[]; + double downTrendBuffer[]; + double vwapPriceBuffer[]; + double xhkRawLowBuffer[]; + double xhkSMOpenBuffer[]; + double xhkSMHighBuffer[]; + double xhkRawOpenBuffer[]; + double xhkRawHighBuffer[]; + double xhkSMCloseBuffer[]; + double vwapVolumeBuffer[]; + double peaksGoldenBuffer[]; + double valesGoldenBuffer[]; + double xhkRawCloseBuffer[]; + double atrUpperRawBuffer[]; + double atrLowerRawBuffer[]; + double donLowUpperBuffer[]; + double donLowLowerBuffer[]; + double resistancesBuffer[]; + double vwapMidStateBuffer[]; + double donOpenUpperBuffer[]; + double donOpenLowerBuffer[]; + double donHighUpperBuffer[]; + double donHighLowerBuffer[]; + double x3maMidStateBuffer[]; + double fractalsUpperBuffer[]; + double fractalsLowerBuffer[]; + double vwapFastStateBuffer[]; + double vwapSlowStateBuffer[]; + double donCloseUpperBuffer[]; + double donCloseLowerBuffer[]; + double x3maFastStateBuffer[]; + double x3maSlowStateBuffer[]; + + // + double rsiSlope; + double strSlope; + double atrUpperSlope; + double atrLowerSlope; + double vwapFastSlope; + double vwapMidSlope; + double vwapSlowSlope; + + // + // Conditions ... + + // + // XTrend ... + + // + bool isTrendBullish; + bool isTrendBearish; + bool isTrendSwitchedToBullish; + bool isTrendSwitchedToBearish; + + // + bool isRsiSlopeBullish; + bool isStrSlopeBullish; + bool isAtrUpperSlopeBullish; + bool isAtrLowerSlopeBullish; + bool isVwapFastSlopeBullish; + bool isVwapMidSlopeBullish; + bool isVwapSlowSlopeBullish; + + // + bool isRsiSlopeBearish; + bool isStrSlopeBearish; + bool isAtrUpperSlopeBearish; + bool isAtrLowerSlopeBearish; + bool isVwapFastSlopeBearish; + bool isVwapMidSlopeBearish; + bool isVwapSlowSlopeBearish; + + // + bool isRsiOverSold; + bool isRsiOverBought; + bool isRsiCrossedOverOverSold; + bool isRsiCrossedUnderOverSold; + bool isRsiCrossedOverOverBought; + bool isRsiCrossedUnderOverBought; + + // + bool isClosedOverAtrUpper; + bool isClosedOverAtrLower; + bool isClosedUnderAtrUpper; + bool isClosedUnderAtrLower; + + // + bool isRejectedUpAtrUpper; + bool isRejectedDownAtrUpper; + + // + bool isRejectedUpAtrLower; + bool isRejectedDownAtrLower; + + // + bool isBreakedUpAtrUpper; + bool isBreakedDownAtrUpper; + + // + bool isBreakedUpAtrLower; + bool isBreakedDownAtrLower; + + // + bool isRejectedDonOpenUpper; + bool isRejectedDonHighUpper; + bool isRejectedDonLowUpper; + bool isRejectedDonCloseUpper; + + // + bool isRejectedDonOpenLower; + bool isRejectedDonHighLower; + bool isRejectedDonLowLower; + bool isRejectedDonCloseLower; + + // + bool isBreakedDonOpenUpper; + bool isBreakedDonHighUpper; + bool isBreakedDonLowUpper; + bool isBreakedDonCloseUpper; + + // + bool isBreakedDonOpenLower; + bool isBreakedDonHighLower; + bool isBreakedDonLowLower; + bool isBreakedDonCloseLower; + + // + bool isSarBullish; + bool isSarBearish; + bool isSarSwitchedToBullish; + bool isSarSwitchedToBearish; + + // + bool isNewPeak; + bool isNewPeakOverLast; + bool isNewPeakUnderLast; + bool isRejectedPrevPeak; + bool isBreakedUpPrevPeak; + + // + bool isNewVale; + bool isNewValeOverLast; + bool isNewValeUnderLast; + bool isRejectedPrevVale; + bool isBreakedDownPrevVale; + + // + bool isStrBullish; + bool isStrBearish; + bool isStrSwitchedToBullish; + bool isStrSwitchedToBearish; + + // + bool isChe1Bullish; + bool isChe1Bearish; + bool isChe1SwitchedToBullish; + bool isChe1SwitchedToBearish; + + // + bool isChe2Bullish; + bool isChe2Bearish; + bool isChe2SwitchedToBullish; + bool isChe2SwitchedToBearish; + + // + bool isCheBullish; + bool isCheBearish; + bool isCheSwitchedToBullish; + bool isCheSwitchedToBearish; + + // + bool isVWapMidBullish; + bool isVWapMidBearish; + bool isVWapFastBullish; + bool isVWapFastBearish; + bool isVWapMidNeutural; + bool isVWapSlowBullish; + bool isVWapSlowBearish; + bool isVWapFastOverMid; + bool isVWapMidOverSlow; + bool isVWapFastNeutural; + bool isVWapSlowNeutural; + bool isVWapFastUnderMid; + bool isVWapMidUnderSlow; + bool isVWapBullishState; + bool isVWapBearishState; + bool isVWapNeuturalState; + bool isVWapBullishOrdered; + bool isVWapBearishOrdered; + bool isVWapSwitchedToBullishState; + bool isVWapSwitchedToBearishState; + bool isVWapSwitchedToNeuturalState; + bool isVWapSwitchedToBullishOrdered; + bool isVWapSwitchedToBearishOrdered; + + // + bool isX3MaMidBullish; + bool isX3MaMidBearish; + bool isX3MaFastBullish; + bool isX3MaFastBearish; + bool isX3MaMidNeutural; + bool isX3MaSlowBullish; + bool isX3MaSlowBearish; + bool isX3MaFastOverMid; + bool isX3MaMidOverSlow; + bool isX3MaFastNeutural; + bool isX3MaSlowNeutural; + bool isX3MaFastUnderMid; + bool isX3MaMidUnderSlow; + bool isX3MaBullishState; + bool isX3MaBearishState; + bool isX3MaNeuturalState; + bool isX3MaBullishOrdered; + bool isX3MaBearishOrdered; + bool isX3MaSwitchedToBullishState; + bool isX3MaSwitchedToBearishState; + bool isX3MaSwitchedToNeuturalState; + bool isX3MaSwitchedToBullishOrdered; + bool isX3MaSwitchedToBearishOrdered; + + // + bool isSMHKBullish; + bool isRawHKBullish; + bool isSMHKBearish; + bool isRawHKBearish; + bool isBreakedUpSMHK; + bool isBreakedUpRawHK; + bool isRejectedUpSMHK; + bool isClosedOverSMHK; + bool isRejectedUpRawHK; + bool isBreakedDownSMHK; + bool isClosedUnderSMHK; + bool isClosedOverRawHK; + bool isClosedUnderRawHK; + bool isBreakedDownRawHK; + bool isRejectedDownSMHK; + bool isRejectedDownRawHK; + bool isRawHKBreakedUpSMHK; + bool isRawHKClosedOverSMHK; + bool isRawHKClosedUnderSMHK; + bool isRawHKBreakedDownSMHK; + bool isSMHKSwitchedToBullish; + bool isSMHKSwitchedToBearish; + bool isRawHKSwitchedToBearish; + bool isRawHKSwitchedToBullish; + + // + // Complex Conditions ... + + // + double cheMin; + double cheMax; + double x3maMin; + double x3maMax; + double vwapMin; + double vwapMax; + + // + bool isSarIncreased; + bool isSarDecreased; + bool isX3MaFatsOverMid; + bool isSarEqualsToPeak; + bool isSarEqualsToVale; + bool isStrEqualsToPeak; + bool isStrEqualsToVale; + bool isX3MaMinBreakedUp; + bool isX3MaMaxBreakedUp; + bool isX3MaFatsUnderMid; + bool isX3MaFatsOverSlow; + bool isAtrUpperOverPeak; + bool isPeakOverAtrUpper; + bool isStrUpperOverPeak; + bool isStrLowerOverVale; + bool isBreakedUpPrevSar; + bool isBreakedUpPrevStr; + bool isVWapMinBreakedUp; + bool isVWapMaxBreakedUp; + bool isClosedOverCheMin; + bool isClosedOverCheMax; + bool isX3MaFatsUnderSlow; + bool isAtrLowerUnderVale; + bool isClosedOverX3MaMin; + bool isClosedOverX3MaMax; + bool isValeUnderAtrLower; + bool isStrUpperUnderPeak; + bool isStrLowerUnderVale; + bool isClosedUnderCheMin; + bool isClosedUnderCheMax; + bool isClosedOverVWapMin; + bool isClosedOverVWapMax; + bool isX3MaMinBreakedDown; + bool isX3MaMaxBreakedDown; + bool isClosedUnderX3MaMin; + bool isClosedUnderX3MaMax; + bool isBreakedDownPrevSar; + bool isBreakedDownPrevStr; + bool isStrCrossedOverVale; + bool isSarCrossedOverVale; + bool isClosedUnderVWapMin; + bool isClosedUnderVWapMax; + bool isVWapMinBreakedDown; + bool isVWapMaxBreakedDown; + bool isX3MaFatsOverMidPrev; + bool isSarCrossedUnderPeak; + bool isStrCrossedUnderPeak; + bool isNewPeakOverAtrUpper; + bool isBreakedUpPrevCheMin; + bool isBreakedUpPrevCheMax; + bool isBreakedUpPrevCheLE1; + bool isBreakedUpPrevCheLE2; + bool isBreakedUpPrevCheSE1; + bool isBreakedUpPrevCheSE2; + bool isX3MaFatsUnderMidPrev; + bool isX3MaFatsOverSlowPrev; + bool isAtrUpperEqualsToPeak; + bool isAtrLowerEqualsToVale; + bool isStrUpperOverAtrUpper; + bool isStrLowerOverAtrLower; + bool isNewValeUnderAtrLower; + bool isAtrUpperCrossedUpPeak; + bool isAtrLowerCrossedUpVale; + bool isStrUpperUnderAtrUpper; + bool isStrLowerUnderAtrLower; + bool isX3MaFatsUnderSlowPrev; + bool isBreakedUpPrevAtrUpper; + bool isBreakedUpPrevAtrLower; + bool isBreakedDownPrevCheMin; + bool isBreakedDownPrevCheMax; + bool isBreakedDownPrevCheLE1; + bool isBreakedDownPrevCheLE2; + bool isBreakedDownPrevCheSE1; + bool isBreakedDownPrevCheSE2; + bool isX3MaFastCrossedOverMid; + bool isRejectedUpPrevAtrUpper; + bool isRejectedUpPrevAtrLower; + bool isVWapFastCrossedOverMid; + bool isX3MaFastCrossedUnderMid; + bool isX3MaFastCrossedOverSlow; + bool isAtrUpperCrossedDownPeak; + bool isAtrLowerCrossedDownVale; + bool isStrLowerOverDonLowLower; + bool isVWapFastCrossedUnderMid; + bool isBreakedDownPrevAtrUpper; + bool isBreakedDownPrevAtrLower; + bool isStrUpperCrossedOverPeak; + bool isStrLowerCrossedOverVale; + bool isDonLowLowerEqualsToVale; + bool isVWapFastCrossedOverSlow; + bool isX3MaFastCrossedUnderSlow; + bool isStrUpperOverDonHighUpper; + bool isStrLowerUnderDonLowLower; + bool isVWapFastCrossedUnderSlow; + bool isStrUpperCrossedUnderPeak; + bool isStrLowerCrossedUnderVale; + bool isDonHighUpperEqualsToPeak; + bool isRejectedDownPrevAtrUpper; + bool isRejectedDownPrevAtrLower; + bool isStrUpperUnderDonHighUpper; + bool isStrUpperCrossedOverAtrUpper; + bool isStrLowerCrossedOverAtrLower; + bool isStrUpperCrossedUnderAtrUpper; + bool isStrLowerCrossedUnderAtrLower; + bool isStrLowerCrossedOverDonLowLower; + bool isStrUpperCrossedOverDonHighUpper; + bool isStrLowerCrossedUnderDonLowLower; + bool isStrUpperCrossedUnderDonHighUpper; + + // + // Constructor ... + X121Conditions() + { + Clean(); + } + + // + // Tools ... + + /** + * Cleaning Up ... + */ + void Clean() + { + // + // Commons ... + symbol = NULL; + period = NULL; + time = NULL; + + // + // Buffers ... + + // + Clean(maBuffer); + Clean(rsiBuffer); + Clean(atrBuffer); + Clean(strBuffer); + Clean(le1Buffer); + Clean(se1Buffer); + Clean(le2Buffer); + Clean(se2Buffer); + Clean(sarBuffer); + Clean(cHHBuffer); + Clean(cLLBuffer); + Clean(sHHBuffer); + Clean(sLLBuffer); + Clean(mHHBuffer); + Clean(mLLBuffer); + Clean(lHHBuffer); + Clean(lLLBuffer); + Clean(hHHBuffer); + Clean(hLLBuffer); + Clean(upTBuffer); + Clean(adxBuffer); + Clean(adxPBuffer); + Clean(adxMBuffer); + Clean(peaksBuffer); + Clean(valesBuffer); + Clean(strUpBuffer); + Clean(downTBuffer); + Clean(volumeBuffer); + Clean(masMidBuffer); + Clean(strDownBuffer); + Clean(vwapMidBuffer); + Clean(upTrendBuffer); + Clean(x3maMidBuffer); + Clean(masUpperBuffer); + Clean(masLowerBuffer); + Clean(le1StartBuffer); + Clean(se1StartBuffer); + Clean(le2StartBuffer); + Clean(se2StartBuffer); + Clean(strPriceBuffer); + Clean(atrUpperBuffer); + Clean(atrLowerBuffer); + Clean(strStateBuffer); + Clean(vwapFastBuffer); + Clean(vwapSlowBuffer); + Clean(xhkSMLowBuffer); + Clean(x3maFastBuffer); + Clean(x3maSlowBuffer); + Clean(supportsBuffer); + Clean(downTrendBuffer); + Clean(vwapPriceBuffer); + Clean(xhkRawLowBuffer); + Clean(xhkSMOpenBuffer); + Clean(xhkSMHighBuffer); + Clean(xhkRawOpenBuffer); + Clean(xhkRawHighBuffer); + Clean(xhkSMCloseBuffer); + Clean(vwapVolumeBuffer); + Clean(peaksGoldenBuffer); + Clean(valesGoldenBuffer); + Clean(xhkRawCloseBuffer); + Clean(atrUpperRawBuffer); + Clean(atrLowerRawBuffer); + Clean(donLowUpperBuffer); + Clean(donLowLowerBuffer); + Clean(resistancesBuffer); + Clean(vwapMidStateBuffer); + Clean(donOpenUpperBuffer); + Clean(donOpenLowerBuffer); + Clean(donHighUpperBuffer); + Clean(donHighLowerBuffer); + Clean(x3maMidStateBuffer); + Clean(fractalsUpperBuffer); + Clean(fractalsLowerBuffer); + Clean(vwapFastStateBuffer); + Clean(vwapSlowStateBuffer); + Clean(donCloseUpperBuffer); + Clean(donCloseLowerBuffer); + Clean(x3maFastStateBuffer); + Clean(x3maSlowStateBuffer); + // + ArraySetAsSeries(maBuffer, true); + ArraySetAsSeries(rsiBuffer, true); + ArraySetAsSeries(atrBuffer, true); + ArraySetAsSeries(strBuffer, true); + ArraySetAsSeries(le1Buffer, true); + ArraySetAsSeries(se1Buffer, true); + ArraySetAsSeries(le2Buffer, true); + ArraySetAsSeries(se2Buffer, true); + ArraySetAsSeries(sarBuffer, true); + ArraySetAsSeries(cHHBuffer, true); + ArraySetAsSeries(cLLBuffer, true); + ArraySetAsSeries(sHHBuffer, true); + ArraySetAsSeries(sLLBuffer, true); + ArraySetAsSeries(mHHBuffer, true); + ArraySetAsSeries(mLLBuffer, true); + ArraySetAsSeries(lHHBuffer, true); + ArraySetAsSeries(lLLBuffer, true); + ArraySetAsSeries(hHHBuffer, true); + ArraySetAsSeries(hLLBuffer, true); + ArraySetAsSeries(upTBuffer, true); + ArraySetAsSeries(adxBuffer, true); + ArraySetAsSeries(adxPBuffer, true); + ArraySetAsSeries(adxMBuffer, true); + ArraySetAsSeries(peaksBuffer, true); + ArraySetAsSeries(valesBuffer, true); + ArraySetAsSeries(strUpBuffer, true); + ArraySetAsSeries(downTBuffer, true); + ArraySetAsSeries(volumeBuffer, true); + ArraySetAsSeries(masMidBuffer, true); + ArraySetAsSeries(strDownBuffer, true); + ArraySetAsSeries(vwapMidBuffer, true); + ArraySetAsSeries(upTrendBuffer, true); + ArraySetAsSeries(x3maMidBuffer, true); + ArraySetAsSeries(masUpperBuffer, true); + ArraySetAsSeries(masLowerBuffer, true); + ArraySetAsSeries(le1StartBuffer, true); + ArraySetAsSeries(se1StartBuffer, true); + ArraySetAsSeries(le2StartBuffer, true); + ArraySetAsSeries(se2StartBuffer, true); + ArraySetAsSeries(strPriceBuffer, true); + ArraySetAsSeries(atrUpperBuffer, true); + ArraySetAsSeries(atrLowerBuffer, true); + ArraySetAsSeries(strStateBuffer, true); + ArraySetAsSeries(vwapFastBuffer, true); + ArraySetAsSeries(vwapSlowBuffer, true); + ArraySetAsSeries(xhkSMLowBuffer, true); + ArraySetAsSeries(x3maFastBuffer, true); + ArraySetAsSeries(x3maSlowBuffer, true); + ArraySetAsSeries(supportsBuffer, true); + ArraySetAsSeries(downTrendBuffer, true); + ArraySetAsSeries(vwapPriceBuffer, true); + ArraySetAsSeries(xhkRawLowBuffer, true); + ArraySetAsSeries(xhkSMOpenBuffer, true); + ArraySetAsSeries(xhkSMHighBuffer, true); + ArraySetAsSeries(xhkRawOpenBuffer, true); + ArraySetAsSeries(xhkRawHighBuffer, true); + ArraySetAsSeries(xhkSMCloseBuffer, true); + ArraySetAsSeries(vwapVolumeBuffer, true); + ArraySetAsSeries(peaksGoldenBuffer, true); + ArraySetAsSeries(valesGoldenBuffer, true); + ArraySetAsSeries(xhkRawCloseBuffer, true); + ArraySetAsSeries(atrUpperRawBuffer, true); + ArraySetAsSeries(atrLowerRawBuffer, true); + ArraySetAsSeries(donLowUpperBuffer, true); + ArraySetAsSeries(donLowLowerBuffer, true); + ArraySetAsSeries(resistancesBuffer, true); + ArraySetAsSeries(vwapMidStateBuffer, true); + ArraySetAsSeries(donOpenUpperBuffer, true); + ArraySetAsSeries(donOpenLowerBuffer, true); + ArraySetAsSeries(donHighUpperBuffer, true); + ArraySetAsSeries(donHighLowerBuffer, true); + ArraySetAsSeries(x3maMidStateBuffer, true); + ArraySetAsSeries(fractalsUpperBuffer, true); + ArraySetAsSeries(fractalsLowerBuffer, true); + ArraySetAsSeries(vwapFastStateBuffer, true); + ArraySetAsSeries(vwapSlowStateBuffer, true); + ArraySetAsSeries(donCloseUpperBuffer, true); + ArraySetAsSeries(donCloseLowerBuffer, true); + ArraySetAsSeries(x3maFastStateBuffer, true); + ArraySetAsSeries(x3maSlowStateBuffer, true); + + // + cheMin = 0; + cheMax = 0; + vwapMin = 0; + vwapMax = 0; + x3maMin = 0; + x3maMax = 0; + + // + // Slopes ... + + rsiSlope = 0; + strSlope = 0; + atrUpperSlope = 0; + atrLowerSlope = 0; + vwapFastSlope = 0; + vwapMidSlope = 0; + vwapSlowSlope = 0; + + // + // Conditions ... + + // + isRsiSlopeBullish = false; + isStrSlopeBullish = false; + isAtrUpperSlopeBullish = false; + isAtrLowerSlopeBullish = false; + isVwapFastSlopeBullish = false; + isVwapMidSlopeBullish = false; + isVwapSlowSlopeBullish = false; + + // + isRsiSlopeBearish = false; + isStrSlopeBearish = false; + isAtrUpperSlopeBearish = false; + isAtrLowerSlopeBearish = false; + isVwapFastSlopeBearish = false; + isVwapMidSlopeBearish = false; + isVwapSlowSlopeBearish = false; + + // + // RSI ... + + // + isRsiOverBought = false; + isRsiCrossedOverOverBought = false; + isRsiCrossedUnderOverBought = false; + + // + isRsiOverSold = false; + isRsiCrossedUnderOverSold = false; + isRsiCrossedOverOverSold = false; + + // + // ATR ... + + // + isBreakedUpAtrUpper = false; + isBreakedUpAtrLower = false; + isClosedOverAtrUpper = false; + isClosedOverAtrLower = false; + isRejectedUpAtrUpper = false; + isRejectedUpAtrLower = false; + isClosedUnderAtrUpper = false; + isClosedUnderAtrLower = false; + isBreakedDownAtrUpper = false; + isBreakedDownAtrLower = false; + isRejectedDownAtrUpper = false; + isRejectedDownAtrLower = false; + + // + // DON ... + + // + isRejectedDonOpenUpper = false; + isRejectedDonHighUpper = false; + isRejectedDonLowUpper = false; + isRejectedDonCloseUpper = false; + isRejectedDonOpenLower = false; + isRejectedDonHighLower = false; + isRejectedDonLowLower = false; + isRejectedDonCloseLower = false; + isBreakedDonOpenUpper = false; + isBreakedDonHighUpper = false; + isBreakedDonLowUpper = false; + isBreakedDonCloseUpper = false; + isBreakedDonOpenLower = false; + isBreakedDonHighLower = false; + isBreakedDonLowLower = false; + isBreakedDonCloseLower = false; + + // + // SAR ... + + // + isSarBullish = false; + isSarBearish = false; + isSarSwitchedToBullish = false; + isSarSwitchedToBearish = false; + + // + // PV ... + + // + isNewPeak = false; + isNewPeakOverLast = false; + isNewPeakUnderLast = false; + isRejectedPrevPeak = false; + isBreakedUpPrevPeak = false; + + // + isNewVale = false; + isNewValeOverLast = false; + isNewValeUnderLast = false; + isRejectedPrevVale = false; + isBreakedDownPrevVale = false; + + // + // STR ... + + // + isStrBullish = false; + isStrBearish = false; + isStrSwitchedToBullish = false; + isStrSwitchedToBearish = false; + + // + // VWAP ... + isVWapMidBullish = false; + isVWapMidBearish = false; + isVWapMidNeutural = false; + isVWapSlowBullish = false; + isVWapSlowBearish = false; + isVWapFastBullish = false; + isVWapFastBearish = false; + isVWapFastOverMid = false; + isVWapMidOverSlow = false; + isVWapFastNeutural = false; + isVWapSlowNeutural = false; + isVWapFastUnderMid = false; + isVWapMidUnderSlow = false; + isVWapBullishState = false; + isVWapBearishState = false; + isVWapNeuturalState = false; + isVWapBullishOrdered = false; + isVWapBearishOrdered = false; + isVWapSwitchedToBullishState = false; + isVWapSwitchedToBearishState = false; + isVWapSwitchedToNeuturalState = false; + isVWapSwitchedToBullishOrdered = false; + isVWapSwitchedToBearishOrdered = false; + + // + // X3MA ... + isX3MaMidBullish = false; + isX3MaMidBearish = false; + isX3MaFastBullish = false; + isX3MaFastBearish = false; + isX3MaMidNeutural = false; + isX3MaSlowBullish = false; + isX3MaSlowBearish = false; + isX3MaFastOverMid = false; + isX3MaMidOverSlow = false; + isX3MaFastNeutural = false; + isX3MaSlowNeutural = false; + isX3MaFastUnderMid = false; + isX3MaMidUnderSlow = false; + isX3MaBullishState = false; + isX3MaBearishState = false; + isX3MaNeuturalState = false; + isX3MaBullishOrdered = false; + isX3MaBearishOrdered = false; + isX3MaSwitchedToBullishState = false; + isX3MaSwitchedToBearishState = false; + isX3MaSwitchedToNeuturalState = false; + isX3MaSwitchedToBullishOrdered = false; + isX3MaSwitchedToBearishOrdered = false; + + // + // CHE ... + + // + isCheBullish = false; + isCheBearish = false; + isChe1Bullish = false; + isChe1Bearish = false; + isChe2Bullish = false; + isChe2Bearish = false; + isClosedOverCheMin = false; + isClosedOverCheMax = false; + isClosedUnderCheMin = false; + isClosedUnderCheMax = false; + isCheSwitchedToBullish = false; + isCheSwitchedToBearish = false; + isChe1SwitchedToBullish = false; + isChe1SwitchedToBearish = false; + isChe2SwitchedToBullish = false; + isChe2SwitchedToBearish = false; + + // + // XHK ... + isSMHKBullish = false; + isRawHKBullish = false; + isSMHKBearish = false; + isRawHKBearish = false; + isBreakedUpSMHK = false; + isBreakedUpRawHK = false; + isRejectedUpSMHK = false; + isClosedOverSMHK = false; + isRejectedUpRawHK = false; + isBreakedDownSMHK = false; + isClosedUnderSMHK = false; + isClosedOverRawHK = false; + isClosedUnderRawHK = false; + isBreakedDownRawHK = false; + isRejectedDownSMHK = false; + isRejectedDownRawHK = false; + isRawHKBreakedUpSMHK = false; + isRawHKClosedOverSMHK = false; + isSMHKSwitchedToBearish = false; + isRawHKSwitchedToBearish = false; + isRawHKClosedUnderSMHK = false; + isRawHKBreakedDownSMHK = false; + isSMHKSwitchedToBullish = false; + isRawHKSwitchedToBullish = false; + + // + // Complex Conditions ... + + // + isSarIncreased = false; + isSarDecreased = false; + isX3MaFatsOverMid = false; + isSarEqualsToPeak = false; + isSarEqualsToVale = false; + isStrEqualsToPeak = false; + isStrEqualsToVale = false; + isX3MaMinBreakedUp = false; + isX3MaMaxBreakedUp = false; + isX3MaFatsUnderMid = false; + isX3MaFatsOverSlow = false; + isAtrUpperOverPeak = false; + isPeakOverAtrUpper = false; + isStrUpperOverPeak = false; + isStrLowerOverVale = false; + isBreakedUpPrevSar = false; + isBreakedUpPrevStr = false; + isVWapMinBreakedUp = false; + isVWapMaxBreakedUp = false; + isClosedOverCheMin = false; + isClosedOverCheMax = false; + isX3MaFatsUnderSlow = false; + isAtrLowerUnderVale = false; + isClosedOverX3MaMin = false; + isClosedOverX3MaMax = false; + isValeUnderAtrLower = false; + isStrUpperUnderPeak = false; + isStrLowerUnderVale = false; + isClosedUnderCheMin = false; + isClosedUnderCheMax = false; + isClosedOverVWapMin = false; + isClosedOverVWapMax = false; + isX3MaMinBreakedDown = false; + isX3MaMaxBreakedDown = false; + isClosedUnderX3MaMin = false; + isClosedUnderX3MaMax = false; + isBreakedDownPrevSar = false; + isBreakedDownPrevStr = false; + isStrCrossedOverVale = false; + isSarCrossedOverVale = false; + isClosedUnderVWapMin = false; + isClosedUnderVWapMax = false; + isVWapMinBreakedDown = false; + isVWapMaxBreakedDown = false; + isX3MaFatsOverMidPrev = false; + isSarCrossedUnderPeak = false; + isStrCrossedUnderPeak = false; + isNewPeakOverAtrUpper = false; + isBreakedUpPrevCheMin = false; + isBreakedUpPrevCheMax = false; + isBreakedUpPrevCheLE1 = false; + isBreakedUpPrevCheLE2 = false; + isBreakedUpPrevCheSE1 = false; + isBreakedUpPrevCheSE2 = false; + isX3MaFatsUnderMidPrev = false; + isX3MaFatsOverSlowPrev = false; + isAtrUpperEqualsToPeak = false; + isAtrLowerEqualsToVale = false; + isStrUpperOverAtrUpper = false; + isStrLowerOverAtrLower = false; + isNewValeUnderAtrLower = false; + isAtrUpperCrossedUpPeak = false; + isAtrLowerCrossedUpVale = false; + isStrUpperUnderAtrUpper = false; + isStrLowerUnderAtrLower = false; + isX3MaFatsUnderSlowPrev = false; + isBreakedUpPrevAtrUpper = false; + isBreakedUpPrevAtrLower = false; + isBreakedDownPrevCheMin = false; + isBreakedDownPrevCheMax = false; + isBreakedDownPrevCheLE1 = false; + isBreakedDownPrevCheLE2 = false; + isBreakedDownPrevCheSE1 = false; + isBreakedDownPrevCheSE2 = false; + isX3MaFastCrossedOverMid = false; + isRejectedUpPrevAtrUpper = false; + isRejectedUpPrevAtrLower = false; + isVWapFastCrossedOverMid = false; + isX3MaFastCrossedUnderMid = false; + isX3MaFastCrossedOverSlow = false; + isAtrUpperCrossedDownPeak = false; + isAtrLowerCrossedDownVale = false; + isStrLowerOverDonLowLower = false; + isVWapFastCrossedUnderMid = false; + isBreakedDownPrevAtrUpper = false; + isBreakedDownPrevAtrLower = false; + isStrUpperCrossedOverPeak = false; + isStrLowerCrossedOverVale = false; + isDonLowLowerEqualsToVale = false; + isVWapFastCrossedOverSlow = false; + isX3MaFastCrossedUnderSlow = false; + isStrUpperOverDonHighUpper = false; + isStrLowerUnderDonLowLower = false; + isVWapFastCrossedUnderSlow = false; + isStrUpperCrossedUnderPeak = false; + isStrLowerCrossedUnderVale = false; + isDonHighUpperEqualsToPeak = false; + isRejectedDownPrevAtrUpper = false; + isRejectedDownPrevAtrLower = false; + isStrUpperUnderDonHighUpper = false; + isStrUpperCrossedOverAtrUpper = false; + isStrLowerCrossedOverAtrLower = false; + isStrUpperCrossedUnderAtrUpper = false; + isStrLowerCrossedUnderAtrLower = false; + isStrLowerCrossedOverDonLowLower = false; + isStrUpperCrossedOverDonHighUpper = false; + isStrLowerCrossedUnderDonLowLower = false; + isStrUpperCrossedUnderDonHighUpper = false; + + // + ZeroMemory(this); + } + + /** + * Generate Conditions Scores ... + * + * @param bullishScore: Double, Directional Scores Reference ... + * @param bearishScore: Double, Directional Scores Reference ... + */ + void GenerateScore( + double &bullishScore, + double &bearishScore // + ) + { + // + bullishScore = 0; + bearishScore = 0; + + // + double score = 1; + double minScore = 0.5; + double highScore = 1.5; + + // + // SLOPES ... + + // + if (isRsiSlopeBullish) + { + bullishScore += minScore; + } + if (isStrSlopeBullish) + { + bullishScore += minScore; + } + if (isAtrUpperSlopeBullish) + { + bullishScore += minScore; + } + if (isAtrLowerSlopeBullish) + { + bullishScore += minScore; + } + if (isVwapFastSlopeBullish) + { + bullishScore += minScore; + } + if (isVwapMidSlopeBullish) + { + bullishScore += minScore; + } + if (isVwapSlowSlopeBullish) + { + bullishScore += minScore; + } + + // + if (isRsiSlopeBearish) + { + bearishScore += minScore; + } + if (isStrSlopeBearish) + { + bearishScore += minScore; + } + if (isAtrUpperSlopeBearish) + { + bearishScore += minScore; + } + if (isAtrLowerSlopeBearish) + { + bearishScore += minScore; + } + if (isVwapFastSlopeBearish) + { + bearishScore += minScore; + } + if (isVwapMidSlopeBearish) + { + bearishScore += minScore; + } + if (isVwapSlowSlopeBearish) + { + bearishScore += minScore; + } + + // + // COMPLEX ... + + // + if (isRsiOverSold) + { + bullishScore += score; + } + if (isRsiCrossedUnderOverSold) + { + bullishScore += highScore; + } + + // + if (isRsiOverBought) + { + bearishScore += score; + } + if (isRsiCrossedOverOverBought) + { + bearishScore += highScore; + } + + // + // XTREND ... + + // + if (isTrendBullish) + { + bullishScore += minScore; + } + if (isTrendSwitchedToBullish) + { + bullishScore += score; + } + + // + if (isTrendBearish) + { + bearishScore += minScore; + } + if (isTrendSwitchedToBearish) + { + bearishScore += score; + } + + // + // XSAR ... + + // + if (isSarBullish) + { + bullishScore += minScore; + } + if (isSarSwitchedToBullish) + { + bullishScore += score; + } + + // + if (isSarBearish) + { + bearishScore += minScore; + } + if (isSarSwitchedToBearish) + { + bearishScore += score; + } + + // + // XSTR ... + + // + if (isStrBullish) + { + bullishScore += minScore; + } + if (isStrSwitchedToBullish) + { + bullishScore += score; + } + + // + if (isStrBearish) + { + bearishScore += minScore; + } + if (isStrSwitchedToBearish) + { + bearishScore += score; + } + + // + // XCHE ... + + // + if (isCheBullish) + { + bullishScore += score; + } + if (isCheSwitchedToBullish) + { + bullishScore += highScore; + } + if (isChe1Bullish && + !isCheBullish && + !isCheSwitchedToBullish) + { + bullishScore += minScore; + } + if (isChe1SwitchedToBullish && + !isCheBullish && + !isCheSwitchedToBullish) + { + bullishScore += minScore; + } + + // + if (isCheBearish) + { + bearishScore += score; + } + if (isCheSwitchedToBearish) + { + bearishScore += highScore; + } + if (isChe1Bearish && + !isCheBearish && + !isCheSwitchedToBearish) + { + bearishScore += minScore; + } + if (isChe1SwitchedToBearish && + !isCheBearish && + !isCheSwitchedToBearish) + { + bearishScore += minScore; + } + + // + // XVWAP ... + + // + if (isVWapBullishState) + { + bullishScore += score; + } + if (isVWapBullishOrdered) + { + bullishScore += score; + } + if (isVWapSwitchedToBullishState) + { + bullishScore += highScore; + } + if (isVWapSwitchedToBullishOrdered) + { + bullishScore += highScore; + } + if (!isVWapBullishState && + !isVWapSwitchedToBullishState) + { + // + if (isVWapFastBullish) + { + bullishScore += minScore; + } + if (isVWapSlowBullish) + { + bullishScore += minScore; + } + } + if (!isVWapBullishOrdered && + !isVWapSwitchedToBullishOrdered) + { + // + if (isVWapFastOverMid) + { + bullishScore += minScore; + } + if (isVWapMidOverSlow) + { + bullishScore += minScore; + } + } + + // + if (isVWapBearishState) + { + bearishScore += score; + } + if (isVWapBearishOrdered) + { + bearishScore += score; + } + if (isVWapSwitchedToBearishState) + { + bearishScore += highScore; + } + if (isVWapSwitchedToBearishOrdered) + { + bearishScore += highScore; + } + if (!isVWapBearishState && + !isVWapSwitchedToBearishState) + { + // + if (isVWapFastBearish) + { + bearishScore += minScore; + } + if (isVWapSlowBearish) + { + bearishScore += minScore; + } + } + if (!isVWapBearishOrdered && + !isVWapSwitchedToBearishOrdered) + { + // + if (isVWapFastUnderMid) + { + bearishScore += minScore; + } + if (isVWapMidUnderSlow) + { + bearishScore += minScore; + } + } + + // + // X3MA ... + + // + if (isX3MaBullishState) + { + bullishScore += score; + } + if (isX3MaBullishOrdered) + { + bullishScore += score; + } + if (isX3MaSwitchedToBullishState) + { + bullishScore += highScore; + } + if (isX3MaSwitchedToBullishOrdered) + { + bullishScore += highScore; + } + if (!isX3MaBullishState && + !isX3MaSwitchedToBullishState) + { + // + if (isX3MaFastBullish) + { + bullishScore += minScore; + } + if (isX3MaSlowBullish) + { + bullishScore += minScore; + } + } + if (!isX3MaBullishOrdered && + !isX3MaSwitchedToBullishOrdered) + { + // + if (isX3MaFastOverMid) + { + bullishScore += minScore; + } + if (isX3MaMidOverSlow) + { + bullishScore += minScore; + } + } + + // + if (isX3MaBearishState) + { + bearishScore += score; + } + if (isX3MaBearishOrdered) + { + bearishScore += score; + } + if (isX3MaSwitchedToBearishState) + { + bearishScore += highScore; + } + if (isX3MaSwitchedToBearishOrdered) + { + bearishScore += highScore; + } + if (!isX3MaBearishState && + !isX3MaSwitchedToBearishState) + { + // + if (isX3MaFastBearish) + { + bearishScore += minScore; + } + if (isX3MaSlowBearish) + { + bearishScore += minScore; + } + } + if (!isX3MaBearishOrdered && + !isX3MaSwitchedToBearishOrdered) + { + // + if (isX3MaFastUnderMid) + { + bearishScore += minScore; + } + if (isX3MaMidUnderSlow) + { + bearishScore += minScore; + } + } + + // + // XSMHK ... + + // + if (isSMHKBullish) + { + bullishScore += minScore; + } + if (isRawHKBullish) + { + bullishScore += minScore; + } + if (isClosedOverSMHK) + { + bullishScore += minScore; + } + if (isClosedOverRawHK) + { + bullishScore += minScore; + } + if (isRawHKClosedOverSMHK) + { + bullishScore += minScore; + } + if (isSMHKSwitchedToBullish) + { + bullishScore += highScore; + } + if (isRawHKSwitchedToBullish) + { + bullishScore += highScore; + } + + // + if (isSMHKBearish) + { + bearishScore += minScore; + } + if (isRawHKBearish) + { + bearishScore += minScore; + } + if (isClosedUnderSMHK) + { + bearishScore += minScore; + } + if (isClosedUnderRawHK) + { + bearishScore += minScore; + } + if (isRawHKClosedUnderSMHK) + { + bearishScore += minScore; + } + if (isSMHKSwitchedToBearish) + { + bearishScore += highScore; + } + if (isRawHKSwitchedToBullish) + { + bearishScore += highScore; + } + + // + // Complex Conditions ... + + // + if (isSarIncreased) + { + bullishScore += minScore; + } + if (isSarEqualsToVale) + { + bullishScore += minScore; + } + if (isBreakedUpPrevSar) + { + bullishScore += minScore; + } + if (isSarCrossedOverVale) + { + bullishScore += score; + } + + // + if (isAtrLowerUnderVale) + { + bullishScore += minScore; + } + if (isValeUnderAtrLower) + { + bullishScore += minScore; + } + if (isNewValeUnderAtrLower) + { + bullishScore += minScore; + } + if (isAtrLowerEqualsToVale) + { + bullishScore += minScore; + } + if (isStrLowerOverAtrLower) + { + bullishScore += minScore; + } + if (isStrUpperOverAtrUpper) + { + bullishScore += minScore; + } + if (isAtrLowerCrossedUpVale) + { + bullishScore += score; + } + if (isAtrUpperCrossedUpPeak) + { + bullishScore += score; + } + if (isBreakedUpPrevAtrLower) + { + bullishScore += minScore; + } + if (isBreakedUpPrevAtrUpper) + { + bullishScore += minScore; + } + if (isRejectedUpPrevAtrUpper) + { + bullishScore += minScore; + } + if (isRejectedUpPrevAtrLower) + { + bullishScore += minScore; + } + if (isStrLowerCrossedOverAtrLower) + { + bullishScore += score; + } + if (isStrUpperCrossedOverAtrUpper) + { + bullishScore += score; + } + + // + if (isBreakedUpPrevStr) + { + bullishScore += minScore; + } + if (isStrEqualsToVale) + { + bullishScore += minScore; + } + if (isStrLowerOverVale) + { + bullishScore += minScore; + } + if (isStrLowerUnderVale) + { + bullishScore += minScore; + } + if (isStrCrossedOverVale) + { + bullishScore += score; + } + if (isStrUpperCrossedOverPeak) + { + bullishScore += score; + } + if (isStrLowerCrossedOverVale) + { + bullishScore += score; + } + if (isStrLowerUnderDonLowLower) + { + bullishScore += minScore; + } + if (isStrLowerCrossedOverDonLowLower) + { + bullishScore += score; + } + if (isStrUpperCrossedOverDonHighUpper) + { + bullishScore += score; + } + + // + if (isVWapMinBreakedUp) + { + bullishScore += minScore; + } + if (isVWapMaxBreakedUp) + { + bullishScore += minScore; + } + if (isClosedOverVWapMin) + { + bullishScore += minScore; + } + if (isClosedOverVWapMax) + { + bullishScore += minScore; + } + if (isVWapFastCrossedOverMid) + { + bullishScore += score; + } + if (isVWapFastCrossedOverSlow) + { + bullishScore += score; + } + + // + if (isX3MaMinBreakedUp) + { + bullishScore += minScore; + } + if (isX3MaMaxBreakedUp) + { + bullishScore += minScore; + } + if (isClosedOverX3MaMin) + { + bullishScore += minScore; + } + if (isClosedOverX3MaMax) + { + bullishScore += minScore; + } + if (isX3MaFastCrossedOverMid) + { + bullishScore += score; + } + if (isX3MaFastCrossedOverSlow) + { + bullishScore += score; + } + + // + if (isClosedOverCheMin) + { + bullishScore += minScore; + } + if (isClosedOverCheMax) + { + bullishScore += minScore; + } + if (isBreakedUpPrevCheMin) + { + bullishScore += minScore; + } + if (isBreakedUpPrevCheMax) + { + bullishScore += minScore; + } + if (isBreakedUpPrevCheLE1) + { + bullishScore += minScore; + } + if (isBreakedUpPrevCheLE2) + { + bullishScore += minScore; + } + if (isBreakedUpPrevCheSE1) + { + bullishScore += minScore; + } + if (isBreakedUpPrevCheSE2) + { + bullishScore += minScore; + } + if (isDonLowLowerEqualsToVale) + { + bullishScore += minScore; + } + + // + // + // + + // + if (isSarDecreased) + { + bearishScore += minScore; + } + if (isSarEqualsToPeak) + { + bearishScore += minScore; + } + if (isBreakedDownPrevSar) + { + bearishScore += minScore; + } + if (isSarCrossedUnderPeak) + { + bearishScore += score; + } + + // + if (isAtrUpperOverPeak) + { + bearishScore += minScore; + } + if (isPeakOverAtrUpper) + { + bearishScore += minScore; + } + if (isNewPeakOverAtrUpper) + { + bearishScore += minScore; + } + if (isAtrUpperEqualsToPeak) + { + bearishScore += minScore; + } + if (isStrLowerUnderAtrLower) + { + bearishScore += minScore; + } + if (isStrUpperUnderAtrUpper) + { + bearishScore += minScore; + } + if (isAtrLowerCrossedDownVale) + { + bearishScore += score; + } + if (isAtrUpperCrossedDownPeak) + { + bearishScore += score; + } + if (isBreakedDownPrevAtrUpper) + { + bearishScore += minScore; + } + if (isBreakedDownPrevAtrLower) + { + bearishScore += minScore; + } + if (isRejectedDownPrevAtrUpper) + { + bearishScore += minScore; + } + if (isRejectedDownPrevAtrLower) + { + bearishScore += minScore; + } + if (isStrLowerCrossedUnderAtrLower) + { + bearishScore += score; + } + if (isStrUpperCrossedUnderAtrUpper) + { + bearishScore += score; + } + + // + if (isStrEqualsToPeak) + { + bearishScore += minScore; + } + if (isStrUpperOverPeak) + { + bearishScore += minScore; + } + if (isStrUpperUnderPeak) + { + bearishScore += minScore; + } + if (isBreakedDownPrevStr) + { + bearishScore += minScore; + } + if (isStrCrossedUnderPeak) + { + bearishScore += score; + } + if (isStrLowerOverDonLowLower) + { + bearishScore += minScore; + } + if (isStrUpperOverDonHighUpper) + { + bearishScore += minScore; + } + if (isStrUpperCrossedUnderPeak) + { + bearishScore += score; + } + if (isStrLowerCrossedUnderVale) + { + bearishScore += score; + } + if (isStrUpperUnderDonHighUpper) + { + bearishScore += minScore; + } + if (isStrLowerCrossedUnderDonLowLower) + { + bearishScore += score; + } + if (isStrUpperCrossedUnderDonHighUpper) + { + bearishScore += score; + } + + // + if (isClosedUnderVWapMin) + { + bearishScore += minScore; + } + if (isClosedUnderVWapMax) + { + bearishScore += minScore; + } + if (isVWapMinBreakedDown) + { + bearishScore += minScore; + } + if (isVWapMaxBreakedDown) + { + bearishScore += minScore; + } + if (isVWapFastCrossedUnderMid) + { + bearishScore += score; + } + if (isVWapFastCrossedUnderSlow) + { + bearishScore += score; + } + + // + if (isX3MaMinBreakedDown) + { + bearishScore += minScore; + } + if (isX3MaMaxBreakedDown) + { + bearishScore += minScore; + } + if (isClosedUnderX3MaMin) + { + bearishScore += minScore; + } + if (isClosedUnderX3MaMax) + { + bearishScore += minScore; + } + if (isX3MaFastCrossedUnderMid) + { + bearishScore += score; + } + if (isX3MaFastCrossedUnderSlow) + { + bearishScore += score; + } + + // + if (isClosedUnderCheMin) + { + bearishScore += minScore; + } + if (isClosedUnderCheMax) + { + bearishScore += minScore; + } + if (isBreakedDownPrevCheMin) + { + bearishScore += minScore; + } + if (isBreakedDownPrevCheMax) + { + bearishScore += minScore; + } + if (isBreakedDownPrevCheLE1) + { + bearishScore += minScore; + } + if (isBreakedDownPrevCheLE2) + { + bearishScore += minScore; + } + if (isBreakedDownPrevCheSE1) + { + bearishScore += minScore; + } + if (isBreakedDownPrevCheSE2) + { + bearishScore += minScore; + } + if (isDonHighUpperEqualsToPeak) + { + bearishScore += minScore; + } + + // + // + // + } + + /** + * Generate Summary String for Represent Conditions State ... + * + * @param onlyCommons: Boolean, Just Generate Only Commons Conditions ... + * @param onlyConditions: Boolean, Just Generate Only Conditions ... + * @param includeScores: Boolean, Attach Scores Representations on Result ... + * @param ignoreFalseConditions: Boolean, Ignore False Conditions on Result ... + * @param separator: String, Separate Lines ... + * + * @return ( string ) + */ + string GenerateSummary( + bool onlyCommons = false, + bool onlyConditions = false, + bool includeScores = true, + bool ignoreFalseConditions = true, + string separator = "\n" // + ) + { + // + string result = NULL; + + // + double bullishScore = 0; + double bearishScore = 0; + GenerateScore( + bullishScore, + bearishScore // + ); + + // + string scoresStr = + // + "Scores: " + separator + + "---------------" + separator + + "Bullish: " + ToString(bullishScore) + separator + + "Bearish: " + ToString(bearishScore) + separator + + "" + // + ; + + // + string commonStr = GenerateSpecifiedCommonSummary( + this, + separator, + includeScores // + ); + + // + string conditionsStr = + // + "-----------------------" + separator + + "SAR ..." + separator + + "-----------------------" + separator + + ToString("isSarBullish", isSarBullish, ignoreFalseConditions, separator) + + ToString("isSarBearish", isSarBearish, ignoreFalseConditions, separator) + + ToString("isSarSwitchedToBullish", isSarSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isSarSwitchedToBearish", isSarSwitchedToBearish, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "Trend ..." + separator + + "-----------------------" + separator + + ToString("isTrendBullish", isTrendBullish, ignoreFalseConditions, separator) + + ToString("isTrendBearish", isTrendBearish, ignoreFalseConditions, separator) + + ToString("isTrendSwitchedToBullish", isTrendSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isTrendSwitchedToBearish", isTrendSwitchedToBearish, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "STR ..." + separator + + "-----------------------" + separator + + ToString("isStrBullish", isStrBullish, ignoreFalseConditions, separator) + + ToString("isStrBearish", isStrBearish, ignoreFalseConditions, separator) + + ToString("isStrSwitchedToBullish", isStrSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isStrSwitchedToBearish", isStrSwitchedToBearish, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "PV ..." + separator + + "-----------------------" + separator + + ToString("isNewPeak", isNewPeak, ignoreFalseConditions, separator) + + ToString("isNewPeakOverLast", isNewPeakOverLast, ignoreFalseConditions, separator) + + ToString("isNewPeakUnderLast", isNewPeakUnderLast, ignoreFalseConditions, separator) + + ToString("isRejectedPrevPeak", isRejectedPrevPeak, ignoreFalseConditions, separator) + + ToString("isBreakedUpPrevPeak", isBreakedUpPrevPeak, ignoreFalseConditions, separator) + + ToString("isNewVale", isNewVale, ignoreFalseConditions, separator) + + ToString("isNewValeOverLast", isNewValeOverLast, ignoreFalseConditions, separator) + + ToString("isNewValeUnderLast", isNewValeUnderLast, ignoreFalseConditions, separator) + + ToString("isRejectedPrevVale", isRejectedPrevVale, ignoreFalseConditions, separator) + + ToString("isBreakedDownPrevVale", isBreakedDownPrevVale, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "> RSI ..." + separator + + "-----------------------" + separator + + ToString("isRsiOverBought", isRsiOverBought, ignoreFalseConditions, separator) + + ToString("isRsiCrossedOverOverBought", isRsiCrossedOverOverBought, ignoreFalseConditions, separator) + + ToString("isRsiCrossedUnderOverBought", isRsiCrossedUnderOverBought, ignoreFalseConditions, separator) + + ToString("isRsiOverSold", isRsiOverSold, ignoreFalseConditions, separator) + + ToString("isRsiCrossedUnderOverSold", isRsiCrossedUnderOverSold, ignoreFalseConditions, separator) + + ToString("isRsiCrossedOverOverSold", isRsiCrossedOverOverSold, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "ATR ..." + separator + + "-----------------------" + separator + + ToString("isClosedOverAtrUpper", isClosedOverAtrUpper, ignoreFalseConditions, separator) + + ToString("isClosedOverAtrLower", isClosedOverAtrLower, ignoreFalseConditions, separator) + + ToString("isClosedUnderAtrUpper", isClosedUnderAtrUpper, ignoreFalseConditions, separator) + + ToString("isClosedUnderAtrLower", isClosedUnderAtrLower, ignoreFalseConditions, separator) + + ToString("isRejectedUpAtrUpper", isRejectedUpAtrUpper, ignoreFalseConditions, separator) + + ToString("isRejectedDownAtrUpper", isRejectedDownAtrUpper, ignoreFalseConditions, separator) + + ToString("isRejectedUpAtrLower", isRejectedUpAtrLower, ignoreFalseConditions, separator) + + ToString("isRejectedDownAtrLower", isRejectedDownAtrLower, ignoreFalseConditions, separator) + + ToString("isBreakedUpAtrUpper", isBreakedUpAtrUpper, ignoreFalseConditions, separator) + + ToString("isBreakedDownAtrUpper", isBreakedDownAtrUpper, ignoreFalseConditions, separator) + + ToString("isBreakedUpAtrLower", isBreakedUpAtrLower, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "DON ..." + separator + + "-----------------------" + separator + + ToString("isBreakedDownAtrLower", isBreakedDownAtrLower, ignoreFalseConditions, separator) + + ToString("isRejectedDonOpenUpper", isRejectedDonOpenUpper, ignoreFalseConditions, separator) + + ToString("isRejectedDonHighUpper", isRejectedDonHighUpper, ignoreFalseConditions, separator) + + ToString("isRejectedDonLowUpper", isRejectedDonLowUpper, ignoreFalseConditions, separator) + + ToString("isRejectedDonCloseUpper", isRejectedDonCloseUpper, ignoreFalseConditions, separator) + + ToString("isRejectedDonOpenLower", isRejectedDonOpenLower, ignoreFalseConditions, separator) + + ToString("isRejectedDonHighLower", isRejectedDonHighLower, ignoreFalseConditions, separator) + + ToString("isRejectedDonLowLower", isRejectedDonLowLower, ignoreFalseConditions, separator) + + ToString("isRejectedDonCloseLower", isRejectedDonCloseLower, ignoreFalseConditions, separator) + + ToString("isBreakedDonOpenUpper", isBreakedDonOpenUpper, ignoreFalseConditions, separator) + + ToString("isBreakedDonHighUpper", isBreakedDonHighUpper, ignoreFalseConditions, separator) + + ToString("isBreakedDonLowUpper", isBreakedDonLowUpper, ignoreFalseConditions, separator) + + ToString("isBreakedDonCloseUpper", isBreakedDonCloseUpper, ignoreFalseConditions, separator) + + ToString("isBreakedDonOpenLower", isBreakedDonOpenLower, ignoreFalseConditions, separator) + + ToString("isBreakedDonHighLower", isBreakedDonHighLower, ignoreFalseConditions, separator) + + ToString("isBreakedDonLowLower", isBreakedDonLowLower, ignoreFalseConditions, separator) + + ToString("isBreakedDonCloseLower", isBreakedDonCloseLower, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "VWAP ..." + separator + + "-----------------------" + separator + + ToString("isVWapFastBullish", isVWapFastBullish, ignoreFalseConditions, separator) + + ToString("isVWapFastBearish", isVWapFastBearish, ignoreFalseConditions, separator) + + ToString("isVWapFastNeutural", isVWapFastNeutural, ignoreFalseConditions, separator) + + ToString("isVWapMidBullish", isVWapMidBullish, ignoreFalseConditions, separator) + + ToString("isVWapMidBearish", isVWapMidBearish, ignoreFalseConditions, separator) + + ToString("isVWapMidNeutural", isVWapMidNeutural, ignoreFalseConditions, separator) + + ToString("isVWapSlowBullish", isVWapSlowBullish, ignoreFalseConditions, separator) + + ToString("isVWapSlowBearish", isVWapSlowBearish, ignoreFalseConditions, separator) + + ToString("isVWapSlowNeutural", isVWapSlowNeutural, ignoreFalseConditions, separator) + + ToString("isVWapFastOverMid", isVWapFastOverMid, ignoreFalseConditions, separator) + + ToString("isVWapMidOverSlow", isVWapMidOverSlow, ignoreFalseConditions, separator) + + ToString("isVWapFastUnderMid", isVWapFastUnderMid, ignoreFalseConditions, separator) + + ToString("isVWapMidUnderSlow", isVWapMidUnderSlow, ignoreFalseConditions, separator) + + ToString("isVWapBullishState", isVWapBullishState, ignoreFalseConditions, separator) + + ToString("isVWapBearishState", isVWapBearishState, ignoreFalseConditions, separator) + + ToString("isVWapNeuturalState", isVWapNeuturalState, ignoreFalseConditions, separator) + + ToString("isVWapBullishOrdered", isVWapBullishOrdered, ignoreFalseConditions, separator) + + ToString("isVWapBearishOrdered", isVWapBearishOrdered, ignoreFalseConditions, separator) + + ToString("isVWapSwitchedToBullishOrdered", isVWapSwitchedToBullishOrdered, ignoreFalseConditions, separator) + + ToString("isVWapSwitchedToBearishOrdered", isVWapSwitchedToBearishOrdered, ignoreFalseConditions, separator) + + ToString("isVWapSwitchedToBullishState", isVWapSwitchedToBullishState, ignoreFalseConditions, separator) + + ToString("isVWapSwitchedToBearishState", isVWapSwitchedToBearishState, ignoreFalseConditions, separator) + + ToString("isVWapSwitchedToNeuturalState", isVWapSwitchedToNeuturalState, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "X3MA ..." + separator + + "-----------------------" + separator + + ToString("isX3MaMidBullish", isX3MaMidBullish, ignoreFalseConditions, separator) + + ToString("isX3MaMidBearish", isX3MaMidBearish, ignoreFalseConditions, separator) + + ToString("isX3MaFastBullish", isX3MaFastBullish, ignoreFalseConditions, separator) + + ToString("isX3MaFastBearish", isX3MaFastBearish, ignoreFalseConditions, separator) + + ToString("isX3MaMidNeutural", isX3MaMidNeutural, ignoreFalseConditions, separator) + + ToString("isX3MaSlowBullish", isX3MaSlowBullish, ignoreFalseConditions, separator) + + ToString("isX3MaSlowBearish", isX3MaSlowBearish, ignoreFalseConditions, separator) + + ToString("isX3MaFastOverMid", isX3MaFastOverMid, ignoreFalseConditions, separator) + + ToString("isX3MaMidOverSlow", isX3MaMidOverSlow, ignoreFalseConditions, separator) + + ToString("isX3MaFastNeutural", isX3MaFastNeutural, ignoreFalseConditions, separator) + + ToString("isX3MaSlowNeutural", isX3MaSlowNeutural, ignoreFalseConditions, separator) + + ToString("isX3MaFastUnderMid", isX3MaFastUnderMid, ignoreFalseConditions, separator) + + ToString("isX3MaMidUnderSlow", isX3MaMidUnderSlow, ignoreFalseConditions, separator) + + ToString("isX3MaBullishState", isX3MaBullishState, ignoreFalseConditions, separator) + + ToString("isX3MaBearishState", isX3MaBearishState, ignoreFalseConditions, separator) + + ToString("isX3MaNeuturalState", isX3MaNeuturalState, ignoreFalseConditions, separator) + + ToString("isX3MaBullishOrdered", isX3MaBullishOrdered, ignoreFalseConditions, separator) + + ToString("isX3MaBearishOrdered", isX3MaBearishOrdered, ignoreFalseConditions, separator) + + ToString("isX3MaSwitchedToBullishState", isX3MaSwitchedToBullishState, ignoreFalseConditions, separator) + + ToString("isX3MaSwitchedToBearishState", isX3MaSwitchedToBearishState, ignoreFalseConditions, separator) + + ToString("isX3MaSwitchedToNeuturalState", isX3MaSwitchedToNeuturalState, ignoreFalseConditions, separator) + + ToString("isX3MaSwitchedToBullishOrdered", isX3MaSwitchedToBullishOrdered, ignoreFalseConditions, separator) + + ToString("isX3MaSwitchedToBearishOrdered", isX3MaSwitchedToBearishOrdered, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "CHE ..." + separator + + "-----------------------" + separator + + ToString("isChe1Bullish", isChe1Bullish, ignoreFalseConditions, separator) + + ToString("isChe1Bearish", isChe1Bearish, ignoreFalseConditions, separator) + + ToString("isChe1SwitchedToBullish", isChe1SwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isChe1SwitchedToBearish", isChe1SwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isChe2Bullish", isChe2Bullish, ignoreFalseConditions, separator) + + ToString("isChe2Bearish", isChe2Bearish, ignoreFalseConditions, separator) + + ToString("isChe2SwitchedToBullish", isChe2SwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isChe2SwitchedToBearish", isChe2SwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isCheBullish", isCheBullish, ignoreFalseConditions, separator) + + ToString("isCheBearish", isCheBearish, ignoreFalseConditions, separator) + + ToString("isCheSwitchedToBullish", isCheSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isCheSwitchedToBearish", isCheSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isClosedOverCheMin", isClosedOverCheMin, ignoreFalseConditions, separator) + + ToString("isClosedOverCheMax", isClosedOverCheMax, ignoreFalseConditions, separator) + + ToString("isClosedUnderCheMin", isClosedUnderCheMin, ignoreFalseConditions, separator) + + ToString("isClosedUnderCheMax", isClosedUnderCheMax, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "HK ..." + separator + + "-----------------------" + separator + + ToString("isSMHKBullish", isSMHKBullish, ignoreFalseConditions, separator) + + ToString("isRawHKBullish", isRawHKBullish, ignoreFalseConditions, separator) + + ToString("isSMHKBearish", isSMHKBearish, ignoreFalseConditions, separator) + + ToString("isRawHKBearish", isRawHKBearish, ignoreFalseConditions, separator) + + ToString("isBreakedUpSMHK", isBreakedUpSMHK, ignoreFalseConditions, separator) + + ToString("isBreakedUpRawHK", isBreakedUpRawHK, ignoreFalseConditions, separator) + + ToString("isRejectedUpSMHK", isRejectedUpSMHK, ignoreFalseConditions, separator) + + ToString("isClosedOverSMHK", isClosedOverSMHK, ignoreFalseConditions, separator) + + ToString("isRejectedUpRawHK", isRejectedUpRawHK, ignoreFalseConditions, separator) + + ToString("isBreakedDownSMHK", isBreakedDownSMHK, ignoreFalseConditions, separator) + + ToString("isClosedUnderSMHK", isClosedUnderSMHK, ignoreFalseConditions, separator) + + ToString("isClosedOverRawHK", isClosedOverRawHK, ignoreFalseConditions, separator) + + ToString("isClosedUnderRawHK", isClosedUnderRawHK, ignoreFalseConditions, separator) + + ToString("isBreakedDownRawHK", isBreakedDownRawHK, ignoreFalseConditions, separator) + + ToString("isRejectedDownSMHK", isRejectedDownSMHK, ignoreFalseConditions, separator) + + ToString("isRejectedDownRawHK", isRejectedDownRawHK, ignoreFalseConditions, separator) + + ToString("isRawHKBreakedUpSMHK", isRawHKBreakedUpSMHK, ignoreFalseConditions, separator) + + ToString("isRawHKClosedOverSMHK", isRawHKClosedOverSMHK, ignoreFalseConditions, separator) + + ToString("isSMHKSwitchedToBearish", isSMHKSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isRawHKSwitchedToBearish", isRawHKSwitchedToBearish, ignoreFalseConditions, separator) + + ToString("isRawHKClosedUnderSMHK", isRawHKClosedUnderSMHK, ignoreFalseConditions, separator) + + ToString("isRawHKBreakedDownSMHK", isRawHKBreakedDownSMHK, ignoreFalseConditions, separator) + + ToString("isSMHKSwitchedToBullish", isSMHKSwitchedToBullish, ignoreFalseConditions, separator) + + ToString("isRawHKSwitchedToBullish", isRawHKSwitchedToBullish, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "Slopes ..." + separator + + "-----------------------" + separator + + ToString("isRsiSlopeBullish", isRsiSlopeBullish, ignoreFalseConditions, separator) + + ToString("isStrSlopeBullish", isStrSlopeBullish, ignoreFalseConditions, separator) + + ToString("isAtrUpperSlopeBullish", isAtrUpperSlopeBullish, ignoreFalseConditions, separator) + + ToString("isAtrLowerSlopeBullish", isAtrLowerSlopeBullish, ignoreFalseConditions, separator) + + ToString("isVwapFastSlopeBullish", isVwapFastSlopeBullish, ignoreFalseConditions, separator) + + ToString("isVwapMidSlopeBullish", isVwapMidSlopeBullish, ignoreFalseConditions, separator) + + ToString("isVwapSlowSlopeBullish", isVwapSlowSlopeBullish, ignoreFalseConditions, separator) + + ToString("isRsiSlopeBearish", isRsiSlopeBearish, ignoreFalseConditions, separator) + + ToString("isStrSlopeBearish", isStrSlopeBearish, ignoreFalseConditions, separator) + + ToString("isAtrUpperSlopeBearish", isAtrUpperSlopeBearish, ignoreFalseConditions, separator) + + ToString("isAtrLowerSlopeBearish", isAtrLowerSlopeBearish, ignoreFalseConditions, separator) + + ToString("isVwapFastSlopeBearish", isVwapFastSlopeBearish, ignoreFalseConditions, separator) + + ToString("isVwapMidSlopeBearish", isVwapMidSlopeBearish, ignoreFalseConditions, separator) + + ToString("isVwapSlowSlopeBearish", isVwapSlowSlopeBearish, ignoreFalseConditions, separator) + + // + "-----------------------" + separator + + "Coplex ..." + separator + + "-----------------------" + separator + + ToString("isSarIncreased", isSarIncreased, ignoreFalseConditions, separator) + + ToString("isSarDecreased", isSarDecreased, ignoreFalseConditions, separator) + + ToString("isSarEqualsToPeak", isSarEqualsToPeak, ignoreFalseConditions, separator) + + + ToString("isStrEqualsToPeak", isStrEqualsToPeak, ignoreFalseConditions, separator) + + ToString("isStrEqualsToVale", isStrEqualsToVale, ignoreFalseConditions, separator) + + ToString("isPeakOverAtrUpper", isPeakOverAtrUpper, ignoreFalseConditions, separator) + + ToString("isBreakedUpPrevSar", isBreakedUpPrevSar, ignoreFalseConditions, separator) + + ToString("isBreakedUpPrevStr", isBreakedUpPrevStr, ignoreFalseConditions, separator) + + ToString("isVWapMinBreakedUp", isVWapMinBreakedUp, ignoreFalseConditions, separator) + + ToString("isVWapMaxBreakedUp", isVWapMaxBreakedUp, ignoreFalseConditions, separator) + + ToString("isStrUpperOverPeak", isStrUpperOverPeak, ignoreFalseConditions, separator) + + ToString("isStrLowerOverVale", isStrLowerOverVale, ignoreFalseConditions, separator) + + ToString("isAtrUpperOverPeak", isAtrUpperOverPeak, ignoreFalseConditions, separator) + + ToString("isAtrLowerUnderVale", isAtrLowerUnderVale, ignoreFalseConditions, separator) + + ToString("isClosedOverVWapMin", isClosedOverVWapMin, ignoreFalseConditions, separator) + + ToString("isClosedOverVWapMax", isClosedOverVWapMax, ignoreFalseConditions, separator) + + ToString("isStrUpperUnderPeak", isStrUpperUnderPeak, ignoreFalseConditions, separator) + + ToString("isValeUnderAtrLower", isValeUnderAtrLower, ignoreFalseConditions, separator) + + ToString("isStrLowerUnderVale", isStrLowerUnderVale, ignoreFalseConditions, separator) + + ToString("isVWapMinBreakedDown", isVWapMinBreakedDown, ignoreFalseConditions, separator) + + ToString("isVWapMaxBreakedDown", isVWapMaxBreakedDown, ignoreFalseConditions, separator) + + ToString("isClosedUnderVWapMin", isClosedUnderVWapMin, ignoreFalseConditions, separator) + + ToString("isClosedUnderVWapMax", isClosedUnderVWapMax, ignoreFalseConditions, separator) + + ToString("isBreakedDownPrevSar", isBreakedDownPrevSar, ignoreFalseConditions, separator) + + ToString("isBreakedDownPrevStr", isBreakedDownPrevStr, ignoreFalseConditions, separator) + + ToString("isSarCrossedOverVale", isSarCrossedOverVale, ignoreFalseConditions, separator) + + ToString("isStrCrossedOverVale", isStrCrossedOverVale, ignoreFalseConditions, separator) + + ToString("isBreakedUpPrevCheLE1", isBreakedUpPrevCheLE1, ignoreFalseConditions, separator) + + ToString("isBreakedUpPrevCheLE2", isBreakedUpPrevCheLE2, ignoreFalseConditions, separator) + + ToString("isBreakedUpPrevCheSE1", isBreakedUpPrevCheSE1, ignoreFalseConditions, separator) + + ToString("isBreakedUpPrevCheSE2", isBreakedUpPrevCheSE2, ignoreFalseConditions, separator) + + ToString("isSarCrossedUnderPeak", isSarCrossedUnderPeak, ignoreFalseConditions, separator) + + ToString("isStrCrossedUnderPeak", isStrCrossedUnderPeak, ignoreFalseConditions, separator) + + ToString("isNewPeakOverAtrUpper", isNewPeakOverAtrUpper, ignoreFalseConditions, separator) + + ToString("isBreakedUpPrevCheMin", isBreakedUpPrevCheMin, ignoreFalseConditions, separator) + + ToString("isBreakedUpPrevCheMax", isBreakedUpPrevCheMax, ignoreFalseConditions, separator) + + ToString("isNewValeUnderAtrLower", isNewValeUnderAtrLower, ignoreFalseConditions, separator) + + ToString("isStrUpperOverAtrUpper", isStrUpperOverAtrUpper, ignoreFalseConditions, separator) + + ToString("isStrLowerOverAtrLower", isStrLowerOverAtrLower, ignoreFalseConditions, separator) + + ToString("isAtrUpperEqualsToPeak", isAtrUpperEqualsToPeak, ignoreFalseConditions, separator) + + ToString("isAtrLowerEqualsToVale", isAtrLowerEqualsToVale, ignoreFalseConditions, separator) + + ToString("isBreakedDownPrevCheMin", isBreakedDownPrevCheMin, ignoreFalseConditions, separator) + + ToString("isBreakedDownPrevCheMax", isBreakedDownPrevCheMax, ignoreFalseConditions, separator) + + ToString("isBreakedDownPrevCheLE1", isBreakedDownPrevCheLE1, ignoreFalseConditions, separator) + + ToString("isBreakedDownPrevCheLE2", isBreakedDownPrevCheLE2, ignoreFalseConditions, separator) + + ToString("isBreakedDownPrevCheSE1", isBreakedDownPrevCheSE1, ignoreFalseConditions, separator) + + ToString("isBreakedDownPrevCheSE2", isBreakedDownPrevCheSE2, ignoreFalseConditions, separator) + + ToString("isAtrUpperCrossedUpPeak", isAtrUpperCrossedUpPeak, ignoreFalseConditions, separator) + + ToString("isAtrLowerCrossedUpVale", isAtrLowerCrossedUpVale, ignoreFalseConditions, separator) + + ToString("isStrUpperUnderAtrUpper", isStrUpperUnderAtrUpper, ignoreFalseConditions, separator) + + ToString("isStrLowerUnderAtrLower", isStrLowerUnderAtrLower, ignoreFalseConditions, separator) + + ToString("isBreakedUpPrevAtrUpper", isBreakedUpPrevAtrUpper, ignoreFalseConditions, separator) + + ToString("isBreakedUpPrevAtrLower", isBreakedUpPrevAtrLower, ignoreFalseConditions, separator) + + ToString("isVWapFastCrossedOverMid", isVWapFastCrossedOverMid, ignoreFalseConditions, separator) + + ToString("isRejectedUpPrevAtrUpper", isRejectedUpPrevAtrUpper, ignoreFalseConditions, separator) + + ToString("isRejectedUpPrevAtrLower", isRejectedUpPrevAtrLower, ignoreFalseConditions, separator) + + ToString("isAtrUpperCrossedDownPeak", isAtrUpperCrossedDownPeak, ignoreFalseConditions, separator) + + ToString("isAtrLowerCrossedDownVale", isAtrLowerCrossedDownVale, ignoreFalseConditions, separator) + + ToString("isBreakedDownPrevAtrUpper", isBreakedDownPrevAtrUpper, ignoreFalseConditions, separator) + + ToString("isBreakedDownPrevAtrLower", isBreakedDownPrevAtrLower, ignoreFalseConditions, separator) + + ToString("isVWapFastCrossedUnderMid", isVWapFastCrossedUnderMid, ignoreFalseConditions, separator) + + ToString("isVWapFastCrossedOverSlow", isVWapFastCrossedOverSlow, ignoreFalseConditions, separator) + + ToString("isStrUpperCrossedOverPeak", isStrUpperCrossedOverPeak, ignoreFalseConditions, separator) + + ToString("isStrLowerOverDonLowLower", isStrLowerOverDonLowLower, ignoreFalseConditions, separator) + + ToString("isStrLowerCrossedOverVale", isStrLowerCrossedOverVale, ignoreFalseConditions, separator) + + ToString("isDonLowLowerEqualsToVale", isDonLowLowerEqualsToVale, ignoreFalseConditions, separator) + + ToString("isRejectedDownPrevAtrUpper", isRejectedDownPrevAtrUpper, ignoreFalseConditions, separator) + + ToString("isRejectedDownPrevAtrLower", isRejectedDownPrevAtrLower, ignoreFalseConditions, separator) + + ToString("isVWapFastCrossedUnderSlow", isVWapFastCrossedUnderSlow, ignoreFalseConditions, separator) + + ToString("isStrUpperCrossedUnderPeak", isStrUpperCrossedUnderPeak, ignoreFalseConditions, separator) + + ToString("isStrLowerCrossedUnderVale", isStrLowerCrossedUnderVale, ignoreFalseConditions, separator) + + ToString("isDonHighUpperEqualsToPeak", isDonHighUpperEqualsToPeak, ignoreFalseConditions, separator) + + ToString("isStrUpperOverDonHighUpper", isStrUpperOverDonHighUpper, ignoreFalseConditions, separator) + + ToString("isStrLowerUnderDonLowLower", isStrLowerUnderDonLowLower, ignoreFalseConditions, separator) + + ToString("isStrUpperUnderDonHighUpper", isStrUpperUnderDonHighUpper, ignoreFalseConditions, separator) + + ToString("isStrUpperCrossedOverAtrUpper", isStrUpperCrossedOverAtrUpper, ignoreFalseConditions, separator) + + ToString("isStrLowerCrossedOverAtrLower", isStrLowerCrossedOverAtrLower, ignoreFalseConditions, separator) + + ToString("isStrUpperCrossedUnderAtrUpper", isStrUpperCrossedUnderAtrUpper, ignoreFalseConditions, separator) + + ToString("isStrLowerCrossedUnderAtrLower", isStrLowerCrossedUnderAtrLower, ignoreFalseConditions, separator) + + ToString("isStrLowerCrossedOverDonLowLower", isStrLowerCrossedOverDonLowLower, ignoreFalseConditions, separator) + + ToString("isStrUpperCrossedOverDonHighUpper", isStrUpperCrossedOverDonHighUpper, ignoreFalseConditions, separator) + + ToString("isStrLowerCrossedUnderDonLowLower", isStrLowerCrossedUnderDonLowLower, ignoreFalseConditions, separator) + + ToString("isStrUpperCrossedUnderDonHighUpper", isStrUpperCrossedUnderDonHighUpper, ignoreFalseConditions, separator) + + // + "" + // + ; + + // + result = + // + "[" + GetTag() + "]" + separator + + (onlyConditions + ? "" + : commonStr) + + (!includeScores + ? "" + : scoresStr) + + " " + separator + + (onlyCommons + ? "" + : conditionsStr) + + "" + // + ; + + // + return result; + } + + /** + * Retrieve nique Tag Identifier ... + * + * @return ( string ) + */ + string GetTag() + { + return GetTypeName(this); + } + + // +}; + +// +// Implementation ... +class XCX121Helper : public XCBase +{ + // + public: + // + + // + // Helpers ... + XCX121XCCHelper *xccHelper; + XCX121XPVHelper *xpvHelper; + XCX121XHKHelper *xhkHelper; + XCX121XMASHelper *xmasHelper; + XCX121XATRHelper *xatrHelper; + XCX121XSTRHelper *xstrHelper; + XCX121XCHEHelper *xcheHelper; + XCX121XDONHelper *xdonHelper; + XCX121X3MAHelper *x3maHelper; + XCX121XVWAPHelper *xvwapHelper; + XCX121XTRENDHelper *xtrendHelper; + + // + // Constructors ... + XCX121Helper() + { + } + + // + // Deconstructor ... + ~XCX121Helper() + { + // + mInputs.Clean(); + xccInputs.Clean(); + xpvInputs.Clean(); + xhkInputs.Clean(); + xmasInputs.Clean(); + xatrInputs.Clean(); + xdonInputs.Clean(); + xstrInputs.Clean(); + xcheInputs.Clean(); + x3maInputs.Clean(); + xvwapInputs.Clean(); + xtrendInputs.Clean(); + + // + delete xccHelper; + delete xpvHelper; + delete xhkHelper; + delete xmasHelper; + delete xatrHelper; + delete xstrHelper; + delete xcheHelper; + delete xdonHelper; + delete x3maHelper; + delete xvwapHelper; + delete xtrendHelper; + + // + ZeroMemory(xccHelper); + ZeroMemory(xpvHelper); + ZeroMemory(xhkHelper); + ZeroMemory(xmasHelper); + ZeroMemory(xatrHelper); + ZeroMemory(xstrHelper); + ZeroMemory(xcheHelper); + ZeroMemory(xdonHelper); + ZeroMemory(x3maHelper); + ZeroMemory(xvwapHelper); + ZeroMemory(xtrendHelper); + } + + // + string GetSymbol() + { + return mSymbol; + } + + // + ENUM_TIMEFRAMES GetPeriod() + { + return mPeriod; + } + + // + // Tools ... + + /** + * Initialize Indicator Helper ... + * + * @param symbol: String, Symbol ... + * @param period: ENUM_TIMEFRAMES member, Period ... + * @param inputs: X121Inputs instance, Indicator Inputs ... + * + * @return ( bool ) + */ + bool Init( + string symbol, // Trading Symbol + ENUM_TIMEFRAMES period, // Trading Period + X121Inputs &inputs // Inputs + ) + { + // + bool result = false; + + // + result = + IsValid(symbol) && + IsValid(period) && + inputs.IsValid(); + if (!result) + { + return result; + } + + // + mSymbol = symbol; + mPeriod = period; + + // + // Setting Inputs ... + + // + mInputs = inputs; + xccInputs = inputs.xccInputs; + xpvInputs = inputs.xpvInputs; + xhkInputs = inputs.xhkInputs; + xmasInputs = inputs.xmasInputs; + xatrInputs = inputs.xatrInputs; + xstrInputs = inputs.xstrInputs; + xcheInputs = inputs.xcheInputs; + xdonInputs = inputs.xdonInputs; + x3maInputs = inputs.x3maInputs; + xvwapInputs = inputs.xvwapInputs; + xtrendInputs = inputs.xtrendInputs; + + // + // Initial Helpers ... + + // + // XCC ... + xccHelper = new XCX121XCCHelper(); + result = xccHelper.Init( + symbol, + period, + xccInputs // + ); + if (!result) + { + return result; + } + + // + // XPV ... + xpvHelper = new XCX121XPVHelper(); + result = xpvHelper.Init( + symbol, + period, + xpvInputs // + ); + if (!result) + { + return result; + } + + // + // XHK ... + xhkHelper = new XCX121XHKHelper(); + result = xhkHelper.Init( + symbol, + period, + xhkInputs // + ); + if (!result) + { + return result; + } + + // + // XMAS ... + xmasHelper = new XCX121XMASHelper(); + result = xmasHelper.Init( + symbol, + period, + xmasInputs // + ); + if (!result) + { + return result; + } + + // + // XATR ... + xatrHelper = new XCX121XATRHelper(); + result = xatrHelper.Init( + symbol, + period, + xatrInputs // + ); + if (!result) + { + return result; + } + + // + // XSTR ... + xstrHelper = new XCX121XSTRHelper(); + result = xstrHelper.Init( + symbol, + period, + xstrInputs // + ); + if (!result) + { + return result; + } + + // + // XCHE ... + xcheHelper = new XCX121XCHEHelper(); + result = xcheHelper.Init( + symbol, + period, + xcheInputs // + ); + if (!result) + { + return result; + } + + // + // XDON ... + xdonHelper = new XCX121XDONHelper(); + result = xdonHelper.Init( + symbol, + period, + xdonInputs // + ); + if (!result) + { + return result; + } + + // + // X3MA ... + x3maHelper = new XCX121X3MAHelper(); + result = x3maHelper.Init( + symbol, + period, + x3maInputs // + ); + if (!result) + { + return result; + } + + // + // XVWAP ... + xvwapHelper = new XCX121XVWAPHelper(); + result = xvwapHelper.Init( + symbol, + period, + xvwapInputs // + ); + if (!result) + { + return result; + } + + // + // XTREND ... + xtrendHelper = new XCX121XTRENDHelper(); + result = xtrendHelper.Init( + symbol, + period, + xtrendInputs // + ); + if (!result) + { + return result; + } + + // + if (inputs.showRSI) + { + // + mRSIHandler = iRSI( + symbol, + period, + xatrInputs.rsiLength, + xatrInputs.rsiAppliedTo // + ); + + // + result = mRSIHandler != INVALID_HANDLE; + if (!result) + { + return result; + } + } + + // + return result; + } + + // + // Conditions Readers ... + + // + // XPV ... + bool GetPVConditions( + X121XPVConditions &conditions, // + int barIndex = 0, // + int loopback = 5 // + ) + { + // + bool result = false; + + // + result = xpvHelper.GetConditions( + conditions, + barIndex, + loopback // + ); + + // + return result; + } + + // + // XHK ... + bool GetHKConditions( + X121XHKConditions &conditions, // + int barIndex = 0, // + int loopback = 5 // + ) + { + // + bool result = false; + + // + result = xhkHelper.GetConditions( + conditions, + barIndex, + loopback // + ); + + // + return result; + } + + // + // XMAS ... + bool GetMASConditions( + X121XMASConditions &conditions, // + int barIndex = 0, // + int loopback = 5 // + ) + { + // + bool result = false; + + // + result = xmasHelper.GetConditions( + conditions, + barIndex, + loopback // + ); + + // + return result; + } + + // + // XATR ... + bool GetATRConditions( + X121XATRConditions &conditions, // + int barIndex = 0, // + int loopback = 5 // + ) + { + // + bool result = false; + + // + result = xatrHelper.GetConditions( + conditions, + barIndex, + loopback // + ); + + // + return result; + } + + // + // XSTR ... + bool GetSTRConditions( + X121XSTRConditions &conditions, // + int barIndex = 0, // + int loopback = 5 // + ) + { + // + bool result = false; + + // + result = xstrHelper.GetConditions( + conditions, + barIndex, + loopback // + ); + + // + return result; + } + + // + // XCHE ... + bool GetCHEConditions( + X121XCHEConditions &conditions, // + int barIndex = 0, // + int loopback = 5 // + ) + { + // + bool result = false; + + // + result = xcheHelper.GetConditions( + conditions, + barIndex, + loopback // + ); + + // + return result; + } + + // + // XDON ... + bool GetDONConditions( + X121XDONConditions &conditions, // + int barIndex = 0, // + int loopback = 5 // + ) + { + // + bool result = false; + + // + result = xdonHelper.GetConditions( + conditions, + barIndex, + loopback // + ); + + // + return result; + } + + // + // X3MA ... + bool Get3MAConditions( + X121X3MAConditions &conditions, // + int barIndex = 0, // + int loopback = 5 // + ) + { + // + bool result = false; + + // + result = x3maHelper.GetConditions( + conditions, + barIndex, + loopback // + ); + + // + return result; + } + + // + // XVWAP ... + bool GetVWAPConditions( + X121XVWAPConditions &conditions, // + int barIndex = 0, // + int loopback = 5 // + ) + { + // + bool result = false; + + // + result = xvwapHelper.GetConditions( + conditions, + barIndex, + loopback // + ); + + // + return result; + } + + // + // XTREND ... + bool GetTrendConditions( + X121XTRENDConditions &conditions, // + int barIndex = 0, // + int loopback = 5 // + ) + { + // + bool result = false; + + // + result = xtrendHelper.GetConditions( + conditions, + barIndex, + loopback // + ); + + // + return result; + } + + // + void Free() + { + // + xpvHelper.Free(); + xhkHelper.Free(); + xmasHelper.Free(); + xatrHelper.Free(); + xstrHelper.Free(); + xcheHelper.Free(); + xdonHelper.Free(); + xvwapHelper.Free(); + xtrendHelper.Free(); + } + + // + bool GetConditions( + X121Conditions &conditions, // + int barIndex = 0, // + int loopback = 5 // + ) + { + // + bool result = true; + + // + if (loopback < 5) + { + loopback = 5; + } + + // + conditions.Clean(); + + // + conditions.symbol = mSymbol; + conditions.period = mPeriod; + conditions.time = TimeCurrent(); + + // + int zIndex = barIndex; + int cIndex = zIndex + 1; + int pIndex = cIndex + 1; + int ppIndex = pIndex + 1; + + // + XOHCL zBar; + result = zBar.Init( + mSymbol, + mPeriod, + zIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL cBar; + result = cBar.Init( + mSymbol, + mPeriod, + cIndex // + ); + if (!result) + { + return result; + } + + // + XOHCL pBar; + result = pBar.Init( + mSymbol, + mPeriod, + pIndex // + ); + if (!result) + { + return result; + } + + // + // XPV ... + X121XPVConditions xpvConditions; + result = GetPVConditions( + xpvConditions, + barIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // XHK ... + X121XHKConditions xhkConditions; + result = GetHKConditions( + xhkConditions, + barIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // XMAS ... + X121XMASConditions xmasConditions; + result = GetMASConditions( + xmasConditions, + barIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // XATR ... + X121XATRConditions xatrConditions; + result = GetATRConditions( + xatrConditions, + barIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // XSTR ... + X121XSTRConditions xstrConditions; + result = GetSTRConditions( + xstrConditions, + barIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // XCHE ... + X121XCHEConditions xcheConditions; + result = GetCHEConditions( + xcheConditions, + barIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // XDON ... + X121XDONConditions xdonConditions; + result = GetDONConditions( + xdonConditions, + barIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // X3MA ... + X121X3MAConditions x3maConditions; + result = Get3MAConditions( + x3maConditions, + barIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // XVWAP ... + X121XVWAPConditions xvwapConditions; + result = GetVWAPConditions( + xvwapConditions, + barIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // XTREND ... + X121XTRENDConditions xtrendConditions; + result = GetTrendConditions( + xtrendConditions, + barIndex, + loopback // + ); + if (!result) + { + return result; + } + + // + // Fill Volume Buffer ... + for (int i = barIndex; i < barIndex + loopback; i++) + { + // + // Reading Bar Valuem ... + long iVol = iVolume( + mSymbol, + mPeriod, + i // + ); + + // + Add( + iVol, + conditions.volumeBuffer // + ); + } + + // + // Fill X121 Conditions Reference by Using + // Retrieved Conditions ... + + // + int cIDX = 1; + int pIDX = cIDX + 1; + + // + // XPV ... + + // + // Buffers ... + + // + Copy( + xpvConditions.peaksBuffer, + conditions.peaksBuffer // + ); + + // + Copy( + xpvConditions.valesBuffer, + conditions.valesBuffer // + ); + + // + Copy( + xpvConditions.supportsBuffer, + conditions.supportsBuffer // + ); + + // + Copy( + xpvConditions.resistancesBuffer, + conditions.resistancesBuffer // + ); + + // + Copy( + xpvConditions.peaksGoldenBuffer, + conditions.peaksGoldenBuffer // + ); + + // + Copy( + xpvConditions.valesGoldenBuffer, + conditions.valesGoldenBuffer // + ); + + // + Copy( + xpvConditions.sarBuffer, + conditions.sarBuffer // + ); + + // + Copy( + xpvConditions.cHHBuffer, + conditions.cHHBuffer // + ); + + // + Copy( + xpvConditions.cLLBuffer, + conditions.cLLBuffer // + ); + + // + Copy( + xpvConditions.sHHBuffer, + conditions.sHHBuffer // + ); + + // + Copy( + xpvConditions.sLLBuffer, + conditions.sLLBuffer // + ); + + // + Copy( + xpvConditions.mHHBuffer, + conditions.mHHBuffer // + ); + + // + Copy( + xpvConditions.mLLBuffer, + conditions.mLLBuffer // + ); + + // + Copy( + xpvConditions.lHHBuffer, + conditions.lHHBuffer // + ); + + // + Copy( + xpvConditions.lLLBuffer, + conditions.lLLBuffer // + ); + + // + Copy( + xpvConditions.hHHBuffer, + conditions.hHHBuffer // + ); + + // + Copy( + xpvConditions.hLLBuffer, + conditions.hLLBuffer // + ); + + // + Copy( + xpvConditions.fractalsUpperBuffer, + conditions.fractalsUpperBuffer // + ); + + // + Copy( + xpvConditions.fractalsLowerBuffer, + conditions.fractalsLowerBuffer // + ); + + // + // Conditions ... + + // + conditions.isNewPeak = xpvConditions.isNewPeak; + conditions.isNewVale = xpvConditions.isNewVale; + conditions.isSarBullish = xpvConditions.isSarBullish; + conditions.isSarBearish = xpvConditions.isSarBearish; + conditions.isNewPeakOverLast = xpvConditions.isNewPeakOverLast; + conditions.isNewValeOverLast = xpvConditions.isNewValeOverLast; + conditions.isNewPeakUnderLast = xpvConditions.isNewPeakUnderLast; + conditions.isNewValeUnderLast = xpvConditions.isNewValeUnderLast; + conditions.isRejectedPrevVale = xpvConditions.isRejectedPrevVale; + conditions.isRejectedPrevPeak = xpvConditions.isRejectedPrevPeak; + conditions.isBreakedUpPrevPeak = xpvConditions.isBreakedUpPrevPeak; + conditions.isBreakedDownPrevVale = xpvConditions.isBreakedDownPrevVale; + conditions.isSarSwitchedToBullish = xpvConditions.isSarSwitchedToBullish; + conditions.isSarSwitchedToBearish = xpvConditions.isSarSwitchedToBearish; + + // + // XHK ... + + // + // Buffers ... + + // + Copy( + xhkConditions.xhkRawOpenBuffer, + conditions.xhkRawOpenBuffer // + ); + + // + Copy( + xhkConditions.xhkRawHighBuffer, + conditions.xhkRawHighBuffer // + ); + + // + Copy( + xhkConditions.xhkRawLowBuffer, + conditions.xhkRawLowBuffer // + ); + + // + Copy( + xhkConditions.xhkRawCloseBuffer, + conditions.xhkRawCloseBuffer // + ); + + // + Copy( + xhkConditions.xhkSMOpenBuffer, + conditions.xhkSMOpenBuffer // + ); + + // + Copy( + xhkConditions.xhkSMHighBuffer, + conditions.xhkSMHighBuffer // + ); + + // + Copy( + xhkConditions.xhkSMLowBuffer, + conditions.xhkSMLowBuffer // + ); + + // + Copy( + xhkConditions.xhkSMCloseBuffer, + conditions.xhkSMCloseBuffer // + ); + + // + // Conditions ... + conditions.isSMHKBullish = xhkConditions.isSMHKBullish; + conditions.isRawHKBullish = xhkConditions.isRawHKBullish; + conditions.isSMHKBearish = xhkConditions.isSMHKBearish; + conditions.isRawHKBearish = xhkConditions.isRawHKBearish; + conditions.isBreakedUpSMHK = xhkConditions.isBreakedUpSMHK; + conditions.isBreakedUpRawHK = xhkConditions.isBreakedUpRawHK; + conditions.isRejectedUpSMHK = xhkConditions.isRejectedUpSMHK; + conditions.isClosedOverSMHK = xhkConditions.isClosedOverSMHK; + conditions.isRejectedUpRawHK = xhkConditions.isRejectedUpRawHK; + conditions.isBreakedDownSMHK = xhkConditions.isBreakedDownSMHK; + conditions.isClosedUnderSMHK = xhkConditions.isClosedUnderSMHK; + conditions.isClosedOverRawHK = xhkConditions.isClosedOverRawHK; + conditions.isClosedUnderRawHK = xhkConditions.isClosedUnderRawHK; + conditions.isBreakedDownRawHK = xhkConditions.isBreakedDownRawHK; + conditions.isRejectedDownSMHK = xhkConditions.isRejectedDownSMHK; + conditions.isRejectedDownRawHK = xhkConditions.isRejectedDownRawHK; + conditions.isRawHKBreakedUpSMHK = xhkConditions.isRawHKBreakedUpSMHK; + conditions.isRawHKClosedOverSMHK = xhkConditions.isRawHKClosedOverSMHK; + conditions.isSMHKSwitchedToBearish = xhkConditions.isSMHKSwitchedToBearish; + conditions.isRawHKSwitchedToBearish = xhkConditions.isRawHKSwitchedToBearish; + conditions.isRawHKClosedUnderSMHK = xhkConditions.isRawHKClosedUnderSMHK; + conditions.isRawHKBreakedDownSMHK = xhkConditions.isRawHKBreakedDownSMHK; + conditions.isSMHKSwitchedToBullish = xhkConditions.isSMHKSwitchedToBullish; + conditions.isRawHKSwitchedToBullish = xhkConditions.isRawHKSwitchedToBullish; + + // + // XMAS ... + + // + // Buffers ... + + // + Copy( + xmasConditions.upperBuffer, + conditions.masUpperBuffer // + ); + + // + Copy( + xmasConditions.midBuffer, + conditions.masMidBuffer // + ); + + // + Copy( + xmasConditions.lowerBuffer, + conditions.masLowerBuffer // + ); + + // + // XTREND ... + + // + // Buffers ... + + // + Copy( + xtrendConditions.upTrendBuffer, + conditions.upTrendBuffer // + ); + + // + Copy( + xtrendConditions.downTrendBuffer, + conditions.downTrendBuffer // + ); + + // + Copy( + xtrendConditions.maBuffer, + conditions.maBuffer // + ); + + // + Copy( + xtrendConditions.adxBuffer, + conditions.adxBuffer // + ); + + // + Copy( + xtrendConditions.adxPBuffer, + conditions.adxPBuffer // + ); + + // + Copy( + xtrendConditions.adxMBuffer, + conditions.adxMBuffer // + ); + + // + Copy( + xtrendConditions.upTBuffer, + conditions.upTBuffer // + ); + + // + Copy( + xtrendConditions.downTBuffer, + conditions.downTBuffer // + ); + + // + conditions.isTrendBullish = xtrendConditions.isTrendBullish; + conditions.isTrendBearish = xtrendConditions.isTrendBearish; + conditions.isTrendSwitchedToBullish = xtrendConditions.isTrendSwitchedToBullish; + conditions.isTrendSwitchedToBearish = xtrendConditions.isTrendSwitchedToBearish; + + // + // XATR ... + + // + // Buffers ... + + // + Copy( + xatrConditions.atrUpperBuffer, + conditions.atrUpperBuffer // + ); + + // + Copy( + xatrConditions.atrLowerBuffer, + conditions.atrLowerBuffer // + ); + + // + Copy( + xatrConditions.atrUpperRawBuffer, + conditions.atrUpperRawBuffer // + ); + + // + Copy( + xatrConditions.atrLowerRawBuffer, + conditions.atrLowerRawBuffer // + ); + + // + Copy( + xatrConditions.atrBuffer, + conditions.atrBuffer // + ); + + // + Copy( + xatrConditions.rsiBuffer, + conditions.rsiBuffer // + ); + + // + // Conditions ... + + // + conditions.isRsiOverSold = xatrConditions.isRsiOverSold; + conditions.isRsiOverBought = xatrConditions.isRsiOverBought; + conditions.isBreakedUpAtrUpper = xatrConditions.isBreakedUpAtrUpper; + conditions.isBreakedUpAtrLower = xatrConditions.isBreakedUpAtrLower; + conditions.isClosedOverAtrUpper = xatrConditions.isClosedOverAtrUpper; + conditions.isRejectedUpAtrUpper = xatrConditions.isRejectedUpAtrUpper; + conditions.isRejectedUpAtrLower = xatrConditions.isRejectedUpAtrLower; + conditions.isClosedOverAtrLower = xatrConditions.isClosedOverAtrLower; + conditions.isBreakedDownAtrUpper = xatrConditions.isBreakedDownAtrUpper; + conditions.isBreakedDownAtrLower = xatrConditions.isBreakedDownAtrLower; + conditions.isClosedUnderAtrUpper = xatrConditions.isClosedUnderAtrUpper; + conditions.isClosedUnderAtrLower = xatrConditions.isClosedUnderAtrLower; + conditions.isRejectedDownAtrUpper = xatrConditions.isRejectedDownAtrUpper; + conditions.isRejectedDownAtrLower = xatrConditions.isRejectedDownAtrLower; + conditions.isRsiCrossedOverOverSold = xatrConditions.isRsiCrossedOverOverSold; + conditions.isRsiCrossedUnderOverSold = xatrConditions.isRsiCrossedUnderOverSold; + conditions.isRsiCrossedOverOverBought = xatrConditions.isRsiCrossedOverOverBought; + conditions.isRsiCrossedUnderOverBought = xatrConditions.isRsiCrossedUnderOverBought; + + // + // XSTR ... + + // + // Buffers ... + + // + Copy( + xstrConditions.strBuffer, + conditions.strBuffer // + ); + + // + Copy( + xstrConditions.strPriceBuffer, + conditions.strPriceBuffer // + ); + + // + Copy( + xstrConditions.strUpBuffer, + conditions.strUpBuffer // + ); + + // + Copy( + xstrConditions.strDownBuffer, + conditions.strDownBuffer // + ); + + // + Copy( + xstrConditions.strStateBuffer, + conditions.strStateBuffer // + ); + + // + // Conditions ... + + // + conditions.isStrBullish = xstrConditions.isStrBullish; + conditions.isStrBearish = xstrConditions.isStrBearish; + conditions.isStrSwitchedToBullish = xstrConditions.isStrSwitchedToBullish; + conditions.isStrSwitchedToBearish = xstrConditions.isStrSwitchedToBearish; + + // + // XCHE ... + + // + // Buffers ... + + // + Copy( + xcheConditions.le1Buffer, + conditions.le1Buffer // + ); + + // + Copy( + xcheConditions.se1Buffer, + conditions.se1Buffer // + ); + + // + Copy( + xcheConditions.le2Buffer, + conditions.le2Buffer // + ); + + // + Copy( + xcheConditions.se2Buffer, + conditions.se2Buffer // + ); + + // + Copy( + xcheConditions.le1StartBuffer, + conditions.le1StartBuffer // + ); + + // + Copy( + xcheConditions.se1StartBuffer, + conditions.se1StartBuffer // + ); + + // + Copy( + xcheConditions.le2StartBuffer, + conditions.le2StartBuffer // + ); + + // + Copy( + xcheConditions.se2StartBuffer, + conditions.se2StartBuffer // + ); + + // + // Conditions ... + + conditions.isCheBullish = xcheConditions.isCheBullish; + conditions.isCheBearish = xcheConditions.isCheBearish; + conditions.isChe1Bullish = xcheConditions.isChe1Bullish; + conditions.isChe1Bearish = xcheConditions.isChe1Bearish; + conditions.isChe2Bullish = xcheConditions.isChe2Bullish; + conditions.isChe2Bearish = xcheConditions.isChe2Bearish; + conditions.isClosedOverCheMin = xcheConditions.isClosedOverCheMin; + conditions.isClosedOverCheMax = xcheConditions.isClosedOverCheMax; + conditions.isClosedUnderCheMin = xcheConditions.isClosedUnderCheMin; + conditions.isClosedUnderCheMax = xcheConditions.isClosedUnderCheMax; + conditions.isCheSwitchedToBullish = xcheConditions.isCheSwitchedToBullish; + conditions.isCheSwitchedToBearish = xcheConditions.isCheSwitchedToBearish; + conditions.isChe1SwitchedToBullish = xcheConditions.isChe1SwitchedToBullish; + conditions.isChe1SwitchedToBearish = xcheConditions.isChe1SwitchedToBearish; + conditions.isChe2SwitchedToBullish = xcheConditions.isChe2SwitchedToBullish; + conditions.isChe2SwitchedToBearish = xcheConditions.isChe2SwitchedToBearish; + + // + // XDON ... + + // + // Buffers ... + + // + Copy( + xdonConditions.donOpenUpperBuffer, + conditions.donOpenUpperBuffer // + ); + + // + Copy( + xdonConditions.donOpenLowerBuffer, + conditions.donOpenLowerBuffer // + ); + + // + Copy( + xdonConditions.donHighUpperBuffer, + conditions.donHighUpperBuffer // + ); + + // + Copy( + xdonConditions.donHighLowerBuffer, + conditions.donHighLowerBuffer // + ); + + // + Copy( + xdonConditions.donLowUpperBuffer, + conditions.donLowUpperBuffer // + ); + + // + Copy( + xdonConditions.donLowLowerBuffer, + conditions.donLowLowerBuffer // + ); + + // + Copy( + xdonConditions.donCloseUpperBuffer, + conditions.donCloseUpperBuffer // + ); + + // + Copy( + xdonConditions.donCloseLowerBuffer, + conditions.donCloseLowerBuffer // + ); + + // + // Conditions ... + + // + conditions.isBreakedDonLowUpper = xdonConditions.isBreakedDonLowUpper; + conditions.isBreakedDonLowLower = xdonConditions.isBreakedDonLowLower; + conditions.isRejectedDonLowUpper = xdonConditions.isRejectedDonLowUpper; + conditions.isRejectedDonLowLower = xdonConditions.isRejectedDonLowLower; + conditions.isBreakedDonOpenUpper = xdonConditions.isBreakedDonOpenUpper; + conditions.isBreakedDonHighUpper = xdonConditions.isBreakedDonHighUpper; + conditions.isBreakedDonOpenLower = xdonConditions.isBreakedDonOpenLower; + conditions.isBreakedDonHighLower = xdonConditions.isBreakedDonHighLower; + conditions.isRejectedDonOpenUpper = xdonConditions.isRejectedDonOpenUpper; + conditions.isRejectedDonHighUpper = xdonConditions.isRejectedDonHighUpper; + conditions.isRejectedDonOpenLower = xdonConditions.isRejectedDonOpenLower; + conditions.isRejectedDonHighLower = xdonConditions.isRejectedDonHighLower; + conditions.isBreakedDonCloseUpper = xdonConditions.isBreakedDonCloseUpper; + conditions.isBreakedDonCloseLower = xdonConditions.isBreakedDonCloseLower; + conditions.isRejectedDonCloseUpper = xdonConditions.isRejectedDonCloseUpper; + conditions.isRejectedDonCloseLower = xdonConditions.isRejectedDonCloseLower; + + // + // X3MA ... + + // + // Buffers ... + + // + Copy( + x3maConditions.x3maFastBuffer, + conditions.x3maFastBuffer // + ); + + // + Copy( + x3maConditions.x3maMidBuffer, + conditions.x3maMidBuffer // + ); + + // + Copy( + x3maConditions.x3maSlowBuffer, + conditions.x3maSlowBuffer // + ); + + // + Copy( + x3maConditions.x3maFastStateBuffer, + conditions.x3maFastStateBuffer // + ); + + // + Copy( + x3maConditions.x3maMidStateBuffer, + conditions.x3maMidStateBuffer // + ); + + // + Copy( + x3maConditions.x3maSlowStateBuffer, + conditions.x3maSlowStateBuffer // + ); + + // + // Conditions ... + + // + conditions.isX3MaMidBullish = x3maConditions.isX3MaMidBullish; + conditions.isX3MaMidBearish = x3maConditions.isX3MaMidBearish; + conditions.isX3MaFastBullish = x3maConditions.isX3MaFastBullish; + conditions.isX3MaFastBearish = x3maConditions.isX3MaFastBearish; + conditions.isX3MaMidNeutural = x3maConditions.isX3MaMidNeutural; + conditions.isX3MaSlowBullish = x3maConditions.isX3MaSlowBullish; + conditions.isX3MaSlowBearish = x3maConditions.isX3MaSlowBearish; + conditions.isX3MaFastOverMid = x3maConditions.isX3MaFastOverMid; + conditions.isX3MaMidOverSlow = x3maConditions.isX3MaMidOverSlow; + conditions.isX3MaFastNeutural = x3maConditions.isX3MaFastNeutural; + conditions.isX3MaSlowNeutural = x3maConditions.isX3MaSlowNeutural; + conditions.isX3MaFastUnderMid = x3maConditions.isX3MaFastUnderMid; + conditions.isX3MaMidUnderSlow = x3maConditions.isX3MaMidUnderSlow; + conditions.isX3MaBullishState = x3maConditions.isX3MaBullishState; + conditions.isX3MaBearishState = x3maConditions.isX3MaBearishState; + conditions.isX3MaNeuturalState = x3maConditions.isX3MaNeuturalState; + conditions.isX3MaBullishOrdered = x3maConditions.isX3MaBullishOrdered; + conditions.isX3MaBearishOrdered = x3maConditions.isX3MaBearishOrdered; + conditions.isX3MaSwitchedToBullishState = x3maConditions.isX3MaSwitchedToBullishState; + conditions.isX3MaSwitchedToBearishState = x3maConditions.isX3MaSwitchedToBearishState; + conditions.isX3MaSwitchedToNeuturalState = x3maConditions.isX3MaSwitchedToNeuturalState; + conditions.isX3MaSwitchedToBullishOrdered = x3maConditions.isX3MaSwitchedToBullishOrdered; + conditions.isX3MaSwitchedToBearishOrdered = x3maConditions.isX3MaSwitchedToBearishOrdered; + + // + // XVWAP ... + + // + // Buffers ... + + // + Copy( + xvwapConditions.vwapFastBuffer, + conditions.vwapFastBuffer // + ); + + // + Copy( + xvwapConditions.vwapMidBuffer, + conditions.vwapMidBuffer // + ); + + // + Copy( + xvwapConditions.vwapSlowBuffer, + conditions.vwapSlowBuffer // + ); + + // + Copy( + xvwapConditions.vwapVolumeBuffer, + conditions.vwapVolumeBuffer // + ); + + // + Copy( + xvwapConditions.vwapPriceBuffer, + conditions.vwapPriceBuffer // + ); + + // + Copy( + xvwapConditions.vwapFastStateBuffer, + conditions.vwapFastStateBuffer // + ); + + // + Copy( + xvwapConditions.vwapMidStateBuffer, + conditions.vwapMidStateBuffer // + ); + + // + Copy( + xvwapConditions.vwapSlowStateBuffer, + conditions.vwapSlowStateBuffer // + ); + + // + // Conditions ... + + // + conditions.isVWapMidBullish = xvwapConditions.isVWapMidBullish; + conditions.isVWapMidBearish = xvwapConditions.isVWapMidBearish; + conditions.isVWapFastBullish = xvwapConditions.isVWapFastBullish; + conditions.isVWapFastBearish = xvwapConditions.isVWapFastBearish; + conditions.isVWapMidNeutural = xvwapConditions.isVWapMidNeutural; + conditions.isVWapSlowBullish = xvwapConditions.isVWapSlowBullish; + conditions.isVWapSlowBearish = xvwapConditions.isVWapSlowBearish; + conditions.isVWapFastOverMid = xvwapConditions.isVWapFastOverMid; + conditions.isVWapMidOverSlow = xvwapConditions.isVWapMidOverSlow; + conditions.isVWapFastNeutural = xvwapConditions.isVWapFastNeutural; + conditions.isVWapSlowNeutural = xvwapConditions.isVWapSlowNeutural; + conditions.isVWapFastUnderMid = xvwapConditions.isVWapFastUnderMid; + conditions.isVWapMidUnderSlow = xvwapConditions.isVWapMidUnderSlow; + conditions.isVWapBullishState = xvwapConditions.isVWapBullishState; + conditions.isVWapBearishState = xvwapConditions.isVWapBearishState; + conditions.isVWapNeuturalState = xvwapConditions.isVWapNeuturalState; + conditions.isVWapBullishOrdered = xvwapConditions.isVWapBullishOrdered; + conditions.isVWapBearishOrdered = xvwapConditions.isVWapBearishOrdered; + conditions.isVWapSwitchedToBullishState = xvwapConditions.isVWapSwitchedToBullishState; + conditions.isVWapSwitchedToBearishState = xvwapConditions.isVWapSwitchedToBearishState; + conditions.isVWapSwitchedToNeuturalState = xvwapConditions.isVWapSwitchedToNeuturalState; + conditions.isVWapSwitchedToBullishOrdered = xvwapConditions.isVWapSwitchedToBullishOrdered; + conditions.isVWapSwitchedToBearishOrdered = xvwapConditions.isVWapSwitchedToBearishOrdered; + + // + // Slopes ... + + // + double rsiSlope = GetSlope(conditions.rsiBuffer, pIDX, cIDX); + double strSlope = GetSlope(conditions.strBuffer, pIDX, cIDX); + double atrUpperSlope = GetSlope(conditions.atrUpperBuffer, pIDX, cIDX); + double atrLowerSlope = GetSlope(conditions.atrLowerBuffer, pIDX, cIDX); + double vwapFastSlope = GetSlope(conditions.vwapFastBuffer, pIDX, cIDX); + double vwapMidSlope = GetSlope(conditions.vwapMidBuffer, pIDX, cIDX); + double vwapSlowSlope = GetSlope(conditions.vwapSlowBuffer, pIDX, cIDX); + + // + bool isRsiSlopeBullish = rsiSlope > 0; + bool isStrSlopeBullish = strSlope > 0; + bool isAtrUpperSlopeBullish = atrUpperSlope > 0; + bool isAtrLowerSlopeBullish = atrLowerSlope > 0; + bool isVwapFastSlopeBullish = vwapFastSlope > 0; + bool isVwapMidSlopeBullish = vwapMidSlope > 0; + bool isVwapSlowSlopeBullish = vwapSlowSlope > 0; + + // + bool isRsiSlopeBearish = rsiSlope < 0; + bool isStrSlopeBearish = strSlope < 0; + bool isAtrUpperSlopeBearish = atrUpperSlope < 0; + bool isAtrLowerSlopeBearish = atrLowerSlope < 0; + bool isVwapFastSlopeBearish = vwapFastSlope < 0; + bool isVwapMidSlopeBearish = vwapMidSlope < 0; + bool isVwapSlowSlopeBearish = vwapSlowSlope < 0; + + // + conditions.rsiSlope = rsiSlope; + conditions.strSlope = strSlope; + conditions.vwapMidSlope = vwapMidSlope; + conditions.vwapSlowSlope = vwapSlowSlope; + conditions.atrUpperSlope = atrUpperSlope; + conditions.atrLowerSlope = atrLowerSlope; + conditions.vwapFastSlope = vwapFastSlope; + conditions.isRsiSlopeBearish = isRsiSlopeBearish; + conditions.isStrSlopeBearish = isStrSlopeBearish; + conditions.isRsiSlopeBullish = isRsiSlopeBullish; + conditions.isStrSlopeBullish = isStrSlopeBullish; + conditions.isVwapMidSlopeBearish = isVwapMidSlopeBearish; + conditions.isVwapMidSlopeBullish = isVwapMidSlopeBullish; + conditions.isAtrUpperSlopeBearish = isAtrUpperSlopeBearish; + conditions.isAtrLowerSlopeBearish = isAtrLowerSlopeBearish; + conditions.isVwapFastSlopeBearish = isVwapFastSlopeBearish; + conditions.isVwapSlowSlopeBearish = isVwapSlowSlopeBearish; + conditions.isAtrUpperSlopeBullish = isAtrUpperSlopeBullish; + conditions.isAtrLowerSlopeBullish = isAtrLowerSlopeBullish; + conditions.isVwapFastSlopeBullish = isVwapFastSlopeBullish; + conditions.isVwapSlowSlopeBullish = isVwapSlowSlopeBullish; + + // + // Complex Conditions ... + + // + double x3maFast = conditions.x3maFastBuffer[cIDX]; + double x3maMid = conditions.x3maMidBuffer[cIDX]; + double x3maSlow = conditions.x3maSlowBuffer[cIDX]; + + // + double x3mas[3] = { + x3maFast, + x3maMid, + x3maSlow // + }; + + // + double x3maMin = GetMin(x3mas); + double x3maMax = GetMax(x3mas); + + // + bool isX3MaMinBreakedUp = IsBarBreak( + x3maMin, + X_DIRECTION_BULLISH, + cBar // + ); + bool isX3MaMinBreakedDown = IsBarBreak( + x3maMin, + X_DIRECTION_BEARISH, + cBar // + ); + + // + bool isX3MaMaxBreakedUp = IsBarBreak( + x3maMax, + X_DIRECTION_BULLISH, + cBar // + ); + bool isX3MaMaxBreakedDown = IsBarBreak( + x3maMax, + X_DIRECTION_BEARISH, + cBar // + ); + + // + bool isX3MaFatsOverMid = conditions.x3maFastBuffer[cIDX] > conditions.x3maMidBuffer[cIDX]; + bool isX3MaFatsOverMidPrev = conditions.x3maFastBuffer[pIDX] > conditions.x3maMidBuffer[pIDX]; + + // + bool isX3MaFatsUnderMid = conditions.x3maFastBuffer[cIDX] < conditions.x3maMidBuffer[cIDX]; + bool isX3MaFatsUnderMidPrev = conditions.x3maFastBuffer[pIDX] < conditions.x3maMidBuffer[pIDX]; + + // + bool isX3MaFatsOverSlow = conditions.x3maFastBuffer[cIDX] > conditions.x3maSlowBuffer[cIDX]; + bool isX3MaFatsOverSlowPrev = conditions.x3maFastBuffer[pIDX] > conditions.x3maSlowBuffer[pIDX]; + + // + bool isX3MaFatsUnderSlow = conditions.x3maFastBuffer[cIDX] < conditions.x3maSlowBuffer[cIDX]; + bool isX3MaFatsUnderSlowPrev = conditions.x3maFastBuffer[pIDX] < conditions.x3maSlowBuffer[pIDX]; + + // + bool isX3MaFastCrossedOverMid = isX3MaFatsOverMid && + !isX3MaFatsOverMidPrev; + bool isX3MaFastCrossedUnderMid = isX3MaFatsUnderMid && + !isX3MaFatsUnderMidPrev; + + // + bool isX3MaFastCrossedOverSlow = isX3MaFatsOverSlow && + !isX3MaFatsOverSlowPrev; + bool isX3MaFastCrossedUnderSlow = isX3MaFatsUnderSlow && + !isX3MaFatsUnderSlowPrev; + + // + bool isClosedOverX3MaMin = cBar.close > x3maMin; + bool isClosedUnderX3MaMin = cBar.close < x3maMin; + + // + bool isClosedOverX3MaMax = cBar.close > x3maMax; + bool isClosedUnderX3MaMax = cBar.close < x3maMax; + + // + // + // + + // + double vwapFast = conditions.vwapFastBuffer[cIDX]; + double vwapMid = conditions.vwapMidBuffer[cIDX]; + double vwapSlow = conditions.vwapSlowBuffer[cIDX]; + + // + double vwaps[3] = { + vwapFast, + vwapMid, + vwapSlow // + }; + + // + double vwapMin = GetMin(vwaps); + double vwapMax = GetMax(vwaps); + + // + bool isVWapMinBreakedUp = IsBarBreak( + vwapMin, + X_DIRECTION_BULLISH, + cBar // + ); + bool isVWapMinBreakedDown = IsBarBreak( + vwapMin, + X_DIRECTION_BEARISH, + cBar // + ); + + // + bool isVWapMaxBreakedUp = IsBarBreak( + vwapMax, + X_DIRECTION_BULLISH, + cBar // + ); + bool isVWapMaxBreakedDown = IsBarBreak( + vwapMax, + X_DIRECTION_BEARISH, + cBar // + ); + + // + bool isVWapFatsOverMid = conditions.vwapFastBuffer[cIDX] > conditions.vwapMidBuffer[cIDX]; + bool isVWapFatsOverMidPrev = conditions.vwapFastBuffer[pIDX] > conditions.vwapMidBuffer[pIDX]; + + // + bool isVWapFatsUnderMid = conditions.vwapFastBuffer[cIDX] < conditions.vwapMidBuffer[cIDX]; + bool isVWapFatsUnderMidPrev = conditions.vwapFastBuffer[pIDX] < conditions.vwapMidBuffer[pIDX]; + + // + bool isVWapFatsOverSlow = conditions.vwapFastBuffer[cIDX] > conditions.vwapSlowBuffer[cIDX]; + bool isVWapFatsOverSlowPrev = conditions.vwapFastBuffer[pIDX] > conditions.vwapSlowBuffer[pIDX]; + + // + bool isVWapFatsUnderSlow = conditions.vwapFastBuffer[cIDX] < conditions.vwapSlowBuffer[cIDX]; + bool isVWapFatsUnderSlowPrev = conditions.vwapFastBuffer[pIDX] < conditions.vwapSlowBuffer[pIDX]; + + // + bool isVWapFastCrossedOverMid = isVWapFatsOverMid && + !isVWapFatsOverMidPrev; + bool isVWapFastCrossedUnderMid = isVWapFatsUnderMid && + !isVWapFatsUnderMidPrev; + + // + bool isVWapFastCrossedOverSlow = isVWapFatsOverSlow && + !isVWapFatsOverSlowPrev; + bool isVWapFastCrossedUnderSlow = isVWapFatsUnderSlow && + !isVWapFatsUnderSlowPrev; + + // + bool isClosedOverVWapMin = cBar.close > vwapMin; + bool isClosedUnderVWapMin = cBar.close < vwapMin; + + // + bool isClosedOverVWapMax = cBar.close > vwapMax; + bool isClosedUnderVWapMax = cBar.close < vwapMax; + + // + bool isSarEqualsToPeak = + conditions.sarBuffer[cIDX] == conditions.peaksBuffer[cIDX]; + bool isSarEqualsToVale = + conditions.sarBuffer[cIDX] == conditions.valesBuffer[cIDX]; + + // + bool isSarIncreased = conditions.sarBuffer[cIDX] > conditions.sarBuffer[pIDX]; + bool isSarDecreased = conditions.sarBuffer[cIDX] < conditions.sarBuffer[pIDX]; + + // + double prevSar = conditions.sarBuffer[pIDX]; + double prevStr = conditions.strBuffer[pIDX]; + double prevCheLE1 = conditions.le1Buffer[pIDX]; + double prevCheLE2 = conditions.le2Buffer[pIDX]; + double prevCheSE1 = conditions.se1Buffer[pIDX]; + double prevCheSE2 = conditions.se2Buffer[pIDX]; + double prevAtrUpper = conditions.atrUpperBuffer[pIDX]; + double prevAtrLower = conditions.atrLowerBuffer[pIDX]; + + // + double ches[]; + if (prevCheLE1 != EMPTY_VALUE) + { + // + Add( + prevCheLE1, + ches // + ); + } + if (prevCheLE2 != EMPTY_VALUE) + { + // + Add( + prevCheLE2, + ches // + ); + } + if (prevCheSE1 != EMPTY_VALUE) + { + // + Add( + prevCheSE1, + ches // + ); + } + if (prevCheSE2 != EMPTY_VALUE) + { + // + Add( + prevCheSE2, + ches // + ); + } + + // + double cheMin = GetMin(ches); + double cheMax = GetMax(ches); + + // + bool isBreakedUpPrevSar = IsBarBreak( + prevSar, + X_DIRECTION_BULLISH, + cBar // + ); + bool isBreakedDownPrevSar = IsBarBreak( + prevSar, + X_DIRECTION_BEARISH, + cBar // + ); + + // + bool isBreakedUpPrevStr = IsBarBreak( + prevStr, + X_DIRECTION_BULLISH, + cBar // + ); + bool isBreakedDownPrevStr = IsBarBreak( + prevStr, + X_DIRECTION_BEARISH, + cBar // + ); + + // + bool isRejectedUpPrevAtrUpper = IsBarReject( + prevAtrUpper, + X_DIRECTION_BULLISH, + cBar // + ); + + // + bool isRejectedDownPrevAtrUpper = IsBarReject( + prevAtrUpper, + X_DIRECTION_BEARISH, + cBar // + ); + + // + bool isRejectedUpPrevAtrLower = IsBarReject( + prevAtrLower, + X_DIRECTION_BULLISH, + cBar // + ); + + // + bool isRejectedDownPrevAtrLower = IsBarReject( + prevAtrLower, + X_DIRECTION_BEARISH, + cBar // + ); + + // + bool isBreakedUpPrevAtrUpper = IsBarBreak( + prevAtrUpper, + X_DIRECTION_BULLISH, + cBar // + ); + bool isBreakedDownPrevAtrUpper = IsBarBreak( + prevAtrUpper, + X_DIRECTION_BEARISH, + cBar // + ); + + // + bool isBreakedUpPrevAtrLower = IsBarBreak( + prevAtrLower, + X_DIRECTION_BULLISH, + cBar // + ); + bool isBreakedDownPrevAtrLower = IsBarBreak( + prevAtrLower, + X_DIRECTION_BEARISH, + cBar // + ); + + // + bool isBreakedUpPrevCheLE1 = IsBarBreak( + prevCheLE1, + X_DIRECTION_BULLISH, + cBar // + ); + bool isBreakedUpPrevCheLE2 = IsBarBreak( + prevCheLE2, + X_DIRECTION_BULLISH, + cBar // + ); + bool isBreakedUpPrevCheSE1 = IsBarBreak( + prevCheSE1, + X_DIRECTION_BULLISH, + cBar // + ); + bool isBreakedUpPrevCheSE2 = IsBarBreak( + prevCheSE2, + X_DIRECTION_BULLISH, + cBar // + ); + + // + bool isBreakedDownPrevCheLE1 = IsBarBreak( + prevCheLE1, + X_DIRECTION_BEARISH, + cBar // + ); + bool isBreakedDownPrevCheLE2 = IsBarBreak( + prevCheLE2, + X_DIRECTION_BEARISH, + cBar // + ); + bool isBreakedDownPrevCheSE1 = IsBarBreak( + prevCheSE1, + X_DIRECTION_BEARISH, + cBar // + ); + bool isBreakedDownPrevCheSE2 = IsBarBreak( + prevCheSE2, + X_DIRECTION_BEARISH, + cBar // + ); + + // + bool isBreakedUpPrevCheMin = IsBarBreak( + cheMin, + X_DIRECTION_BULLISH, + cBar // + ); + bool isBreakedDownPrevCheMin = IsBarBreak( + cheMin, + X_DIRECTION_BEARISH, + cBar // + ); + + // + bool isBreakedUpPrevCheMax = IsBarBreak( + cheMax, + X_DIRECTION_BULLISH, + cBar // + ); + bool isBreakedDownPrevCheMax = IsBarBreak( + cheMax, + X_DIRECTION_BEARISH, + cBar // + ); + + // + bool isSarCrossedUnderPeak = + conditions.sarBuffer[cIDX] < conditions.peaksBuffer[cIDX] && + !(conditions.sarBuffer[pIDX] < conditions.peaksBuffer[pIDX]); + bool isSarCrossedOverVale = + conditions.sarBuffer[cIDX] > conditions.valesBuffer[cIDX] && + !(conditions.sarBuffer[pIDX] > conditions.valesBuffer[pIDX]); + + // + bool isStrEqualsToPeak = + conditions.strBuffer[cIDX] == conditions.peaksBuffer[cIDX]; + bool isStrEqualsToVale = + conditions.strBuffer[cIDX] == conditions.valesBuffer[cIDX]; + + // + bool isStrCrossedUnderPeak = + conditions.strBuffer[cIDX] < conditions.peaksBuffer[cIDX] && + !(conditions.strBuffer[pIDX] < conditions.peaksBuffer[pIDX]); + bool isStrCrossedOverVale = + conditions.strBuffer[cIDX] > conditions.valesBuffer[cIDX] && + !(conditions.strBuffer[pIDX] > conditions.valesBuffer[pIDX]); + + // + bool isPeakOverAtrUpper = + conditions.peaksBuffer[cIDX] > conditions.atrUpperBuffer[cIDX]; + bool isValeUnderAtrLower = + conditions.valesBuffer[cIDX] > conditions.atrLowerBuffer[cIDX]; + + // + bool isNewPeakOverAtrUpper = + isPeakOverAtrUpper && + conditions.isNewPeak; + bool isNewValeUnderAtrLower = + isValeUnderAtrLower && + conditions.isNewVale; + + // + bool isStrUpperOverPeak = + conditions.strBuffer[cIDX] > conditions.peaksBuffer[cIDX]; + bool isStrUpperOverPeakPrev = + conditions.strBuffer[pIDX] > conditions.peaksBuffer[pIDX]; + + // + bool isStrUpperUnderPeak = + conditions.strBuffer[cIDX] < conditions.peaksBuffer[cIDX]; + bool isStrUpperUnderPeakPrev = + conditions.strBuffer[pIDX] < conditions.peaksBuffer[pIDX]; + + // + bool isStrUpperCrossedOverPeak = isStrUpperOverPeak && + !isStrUpperOverPeakPrev; + bool isStrUpperCrossedUnderPeak = isStrUpperUnderPeak && + !isStrUpperUnderPeakPrev; + + // + bool isStrLowerOverVale = + conditions.strBuffer[cIDX] > conditions.valesBuffer[cIDX]; + bool isStrLowerOverValePrev = + conditions.strBuffer[pIDX] > conditions.valesBuffer[pIDX]; + + // + bool isStrLowerUnderVale = + conditions.strBuffer[cIDX] < conditions.valesBuffer[cIDX]; + bool isStrLowerUnderValePrev = + conditions.strBuffer[pIDX] < conditions.valesBuffer[pIDX]; + + // + bool isStrLowerCrossedOverVale = isStrLowerOverVale && + !isStrLowerOverValePrev; + bool isStrLowerCrossedUnderVale = isStrLowerUnderVale && + !isStrLowerUnderValePrev; + + // + bool isDonHighUpperEqualsToPeak = + conditions.donHighUpperBuffer[cIDX] == conditions.peaksBuffer[cIDX]; + bool isDonLowLowerEqualsToVale = + conditions.donLowLowerBuffer[cIDX] == conditions.valesBuffer[cIDX]; + + // + bool isStrUpperOverAtrUpper = + conditions.strUpBuffer[cIDX] > conditions.atrUpperBuffer[cIDX]; + bool isStrUpperOverAtrUpperPrev = + conditions.strUpBuffer[pIDX] > conditions.atrUpperBuffer[pIDX]; + bool isStrUpperCrossedOverAtrUpper = isStrUpperOverAtrUpper && + !isStrUpperOverAtrUpperPrev; + + // + bool isStrUpperUnderAtrUpper = + conditions.strUpBuffer[cIDX] < conditions.atrUpperBuffer[cIDX]; + bool isStrUpperUnderAtrUpperPrev = + conditions.strUpBuffer[pIDX] < conditions.atrUpperBuffer[pIDX]; + bool isStrUpperCrossedUnderAtrUpper = isStrUpperUnderAtrUpper && + !isStrUpperUnderAtrUpperPrev; + + // + bool isStrLowerOverAtrLower = + conditions.strDownBuffer[cIDX] > conditions.atrLowerBuffer[cIDX]; + bool isStrLowerOverAtrLowerPrev = + conditions.strDownBuffer[pIDX] > conditions.atrLowerBuffer[pIDX]; + bool isStrLowerCrossedOverAtrLower = isStrLowerOverAtrLower && + !isStrLowerOverAtrLowerPrev; + + // + bool isStrLowerUnderAtrLower = + conditions.strDownBuffer[cIDX] < conditions.atrLowerBuffer[cIDX]; + bool isStrLowerUnderAtrLowerPrev = + conditions.strDownBuffer[pIDX] < conditions.atrLowerBuffer[pIDX]; + bool isStrLowerCrossedUnderAtrLower = isStrLowerUnderAtrLower && + !isStrLowerUnderAtrLowerPrev; + + // + bool isStrUpperOverDonHighUpper = + conditions.strUpBuffer[cIDX] > conditions.donHighUpperBuffer[cIDX]; + bool isStrUpperOverDonHighUpperPrev = + conditions.strUpBuffer[pIDX] > conditions.donHighUpperBuffer[pIDX]; + bool isStrUpperCrossedOverDonHighUpper = isStrUpperOverDonHighUpper && + !isStrUpperOverDonHighUpperPrev; + + // + bool isStrUpperUnderDonHighUpper = + conditions.strUpBuffer[cIDX] < conditions.donHighUpperBuffer[cIDX]; + bool isStrUpperUnderDonHighUpperPrev = + conditions.strUpBuffer[pIDX] < conditions.donHighUpperBuffer[pIDX]; + bool isStrUpperCrossedUnderDonHighUpper = isStrUpperUnderDonHighUpper && + !isStrUpperUnderDonHighUpperPrev; + + // + bool isStrLowerOverDonLowLower = + conditions.strDownBuffer[cIDX] > conditions.donLowLowerBuffer[cIDX]; + bool isStrLowerOverDonLowLowerPrev = + conditions.strDownBuffer[pIDX] > conditions.donLowLowerBuffer[pIDX]; + bool isStrLowerCrossedOverDonLowLower = isStrLowerOverDonLowLower && + !isStrLowerOverDonLowLowerPrev; + + // + bool isStrLowerUnderDonLowLower = + conditions.strDownBuffer[cIDX] < conditions.donLowLowerBuffer[cIDX]; + bool isStrLowerUnderDonLowLowerPrev = + conditions.strDownBuffer[pIDX] < conditions.donLowLowerBuffer[pIDX]; + bool isStrLowerCrossedUnderDonLowLower = isStrLowerUnderDonLowLower && + !isStrLowerUnderDonLowLowerPrev; + + // + bool isAtrUpperOverPeak = conditions.atrUpperBuffer[cIDX] > conditions.peaksBuffer[cIDX]; + bool isAtrUpperEqualsToPeak = conditions.atrUpperBuffer[cIDX] == conditions.peaksBuffer[cIDX]; + + // + bool isAtrUpperCrossedUpPeak = conditions.atrUpperBuffer[cIDX] > conditions.peaksBuffer[cIDX] && + !(conditions.atrUpperBuffer[cIDX] > conditions.peaksBuffer[cIDX]); + bool isAtrUpperCrossedDownPeak = conditions.atrUpperBuffer[cIDX] < conditions.peaksBuffer[cIDX] && + !(conditions.atrUpperBuffer[cIDX] < conditions.peaksBuffer[cIDX]); + + // + bool isAtrLowerUnderVale = conditions.atrUpperBuffer[cIDX] < conditions.valesBuffer[cIDX]; + bool isAtrLowerEqualsToVale = conditions.atrUpperBuffer[cIDX] == conditions.valesBuffer[cIDX]; + + // + bool isAtrLowerCrossedUpVale = conditions.atrUpperBuffer[cIDX] > conditions.valesBuffer[cIDX] && + !(conditions.atrUpperBuffer[cIDX] > conditions.valesBuffer[cIDX]); + bool isAtrLowerCrossedDownVale = conditions.atrUpperBuffer[cIDX] < conditions.valesBuffer[cIDX] && + !(conditions.atrUpperBuffer[cIDX] < conditions.valesBuffer[cIDX]); + + // + conditions.cheMin = cheMin; + conditions.cheMax = cheMax; + conditions.x3maMin = x3maMin; + conditions.x3maMax = x3maMax; + conditions.vwapMin = vwapMin; + conditions.vwapMax = vwapMax; + + // + conditions.isSarIncreased = isSarIncreased; + conditions.isSarDecreased = isSarDecreased; + conditions.isSarEqualsToPeak = isSarEqualsToPeak; + conditions.isSarEqualsToVale = isSarEqualsToVale; + conditions.isStrEqualsToPeak = isStrEqualsToPeak; + conditions.isStrEqualsToVale = isStrEqualsToVale; + conditions.isX3MaFatsOverMid = isX3MaFatsOverMid; + conditions.isX3MaMinBreakedUp = isX3MaMinBreakedUp; + conditions.isX3MaMaxBreakedUp = isX3MaMaxBreakedUp; + conditions.isX3MaFatsUnderMid = isX3MaFatsUnderMid; + conditions.isX3MaFatsOverSlow = isX3MaFatsOverSlow; + conditions.isStrUpperOverPeak = isStrUpperOverPeak; + conditions.isPeakOverAtrUpper = isPeakOverAtrUpper; + conditions.isStrLowerOverVale = isStrLowerOverVale; + conditions.isVWapMinBreakedUp = isVWapMinBreakedUp; + conditions.isVWapMaxBreakedUp = isVWapMaxBreakedUp; + conditions.isBreakedUpPrevSar = isBreakedUpPrevSar; + conditions.isBreakedUpPrevStr = isBreakedUpPrevStr; + conditions.isAtrUpperOverPeak = isAtrUpperOverPeak; + conditions.isClosedOverX3MaMin = isClosedOverX3MaMin; + conditions.isClosedOverX3MaMax = isClosedOverX3MaMax; + conditions.isX3MaFatsUnderSlow = isX3MaFatsUnderSlow; + conditions.isAtrLowerUnderVale = isAtrLowerUnderVale; + conditions.isStrLowerUnderVale = isStrLowerUnderVale; + conditions.isStrUpperUnderPeak = isStrUpperUnderPeak; + conditions.isValeUnderAtrLower = isValeUnderAtrLower; + conditions.isClosedOverVWapMin = isClosedOverVWapMin; + conditions.isClosedOverVWapMax = isClosedOverVWapMax; + conditions.isClosedUnderX3MaMin = isClosedUnderX3MaMin; + conditions.isClosedUnderX3MaMax = isClosedUnderX3MaMax; + conditions.isX3MaMinBreakedDown = isX3MaMinBreakedDown; + conditions.isX3MaMaxBreakedDown = isX3MaMaxBreakedDown; + conditions.isClosedUnderVWapMin = isClosedUnderVWapMin; + conditions.isClosedUnderVWapMax = isClosedUnderVWapMax; + conditions.isVWapMinBreakedDown = isVWapMinBreakedDown; + conditions.isVWapMaxBreakedDown = isVWapMaxBreakedDown; + conditions.isSarCrossedOverVale = isSarCrossedOverVale; + conditions.isStrCrossedOverVale = isStrCrossedOverVale; + conditions.isBreakedDownPrevStr = isBreakedDownPrevStr; + conditions.isBreakedDownPrevSar = isBreakedDownPrevSar; + conditions.isX3MaFatsOverMidPrev = isX3MaFatsOverMidPrev; + conditions.isSarCrossedUnderPeak = isSarCrossedUnderPeak; + conditions.isStrCrossedUnderPeak = isStrCrossedUnderPeak; + conditions.isNewPeakOverAtrUpper = isNewPeakOverAtrUpper; + conditions.isBreakedUpPrevCheLE1 = isBreakedUpPrevCheLE1; + conditions.isBreakedUpPrevCheLE2 = isBreakedUpPrevCheLE2; + conditions.isBreakedUpPrevCheSE1 = isBreakedUpPrevCheSE1; + conditions.isBreakedUpPrevCheSE2 = isBreakedUpPrevCheSE2; + conditions.isBreakedUpPrevCheMin = isBreakedUpPrevCheMin; + conditions.isBreakedUpPrevCheMax = isBreakedUpPrevCheMax; + conditions.isX3MaFatsUnderMidPrev = isX3MaFatsUnderMidPrev; + conditions.isX3MaFatsOverSlowPrev = isX3MaFatsOverSlowPrev; + conditions.isAtrUpperEqualsToPeak = isAtrUpperEqualsToPeak; + conditions.isAtrLowerEqualsToVale = isAtrLowerEqualsToVale; + conditions.isNewValeUnderAtrLower = isNewValeUnderAtrLower; + conditions.isStrUpperOverAtrUpper = isStrUpperOverAtrUpper; + conditions.isStrLowerOverAtrLower = isStrLowerOverAtrLower; + conditions.isX3MaFatsUnderSlowPrev = isX3MaFatsUnderSlowPrev; + conditions.isBreakedDownPrevCheMin = isBreakedDownPrevCheMin; + conditions.isBreakedDownPrevCheMax = isBreakedDownPrevCheMax; + conditions.isBreakedDownPrevCheLE1 = isBreakedDownPrevCheLE1; + conditions.isBreakedDownPrevCheLE2 = isBreakedDownPrevCheLE2; + conditions.isBreakedDownPrevCheSE1 = isBreakedDownPrevCheSE1; + conditions.isBreakedDownPrevCheSE2 = isBreakedDownPrevCheSE2; + conditions.isStrUpperUnderAtrUpper = isStrUpperUnderAtrUpper; + conditions.isStrLowerUnderAtrLower = isStrLowerUnderAtrLower; + conditions.isBreakedUpPrevAtrUpper = isBreakedUpPrevAtrUpper; + conditions.isBreakedUpPrevAtrLower = isBreakedUpPrevAtrLower; + conditions.isAtrUpperCrossedUpPeak = isAtrUpperCrossedUpPeak; + conditions.isAtrLowerCrossedUpVale = isAtrLowerCrossedUpVale; + conditions.isX3MaFastCrossedOverMid = isX3MaFastCrossedOverMid; + conditions.isVWapFastCrossedOverMid = isVWapFastCrossedOverMid; + conditions.isRejectedUpPrevAtrUpper = isRejectedUpPrevAtrUpper; + conditions.isRejectedUpPrevAtrLower = isRejectedUpPrevAtrLower; + conditions.isX3MaFastCrossedUnderMid = isX3MaFastCrossedUnderMid; + conditions.isX3MaFastCrossedOverSlow = isX3MaFastCrossedOverSlow; + conditions.isAtrUpperCrossedDownPeak = isAtrUpperCrossedDownPeak; + conditions.isAtrLowerCrossedDownVale = isAtrLowerCrossedDownVale; + conditions.isBreakedDownPrevAtrUpper = isBreakedDownPrevAtrUpper; + conditions.isBreakedDownPrevAtrLower = isBreakedDownPrevAtrLower; + conditions.isVWapFastCrossedUnderMid = isVWapFastCrossedUnderMid; + conditions.isDonLowLowerEqualsToVale = isDonLowLowerEqualsToVale; + conditions.isStrUpperCrossedOverPeak = isStrUpperCrossedOverPeak; + conditions.isStrLowerCrossedOverVale = isStrLowerCrossedOverVale; + conditions.isStrLowerOverDonLowLower = isStrLowerOverDonLowLower; + conditions.isVWapFastCrossedOverSlow = isVWapFastCrossedOverSlow; + conditions.isX3MaFastCrossedUnderSlow = isX3MaFastCrossedUnderSlow; + conditions.isRejectedDownPrevAtrUpper = isRejectedDownPrevAtrUpper; + conditions.isRejectedDownPrevAtrLower = isRejectedDownPrevAtrLower; + conditions.isVWapFastCrossedUnderSlow = isVWapFastCrossedUnderSlow; + conditions.isStrUpperOverDonHighUpper = isStrUpperOverDonHighUpper; + conditions.isStrLowerUnderDonLowLower = isStrLowerUnderDonLowLower; + conditions.isDonHighUpperEqualsToPeak = isDonHighUpperEqualsToPeak; + conditions.isStrUpperCrossedUnderPeak = isStrUpperCrossedUnderPeak; + conditions.isStrLowerCrossedUnderVale = isStrLowerCrossedUnderVale; + conditions.isStrUpperUnderDonHighUpper = isStrUpperUnderDonHighUpper; + conditions.isStrLowerCrossedOverAtrLower = isStrLowerCrossedOverAtrLower; + conditions.isStrUpperCrossedOverAtrUpper = isStrUpperCrossedOverAtrUpper; + conditions.isStrUpperCrossedUnderAtrUpper = isStrUpperCrossedUnderAtrUpper; + conditions.isStrLowerCrossedUnderAtrLower = isStrLowerCrossedUnderAtrLower; + conditions.isStrLowerCrossedOverDonLowLower = isStrLowerCrossedOverDonLowLower; + conditions.isStrUpperCrossedOverDonHighUpper = isStrUpperCrossedOverDonHighUpper; + conditions.isStrLowerCrossedUnderDonLowLower = isStrLowerCrossedUnderDonLowLower; + conditions.isStrUpperCrossedUnderDonHighUpper = isStrUpperCrossedUnderDonHighUpper; + + // + xpvConditions.Clean(); + xhkConditions.Clean(); + xmasConditions.Clean(); + xatrConditions.Clean(); + xstrConditions.Clean(); + xcheConditions.Clean(); + xdonConditions.Clean(); + x3maConditions.Clean(); + xvwapConditions.Clean(); + xtrendConditions.Clean(); + + // + Free(); + + // + return result; + } + + // + protected: + // + + // + private: + // + + // + string mSymbol; // Trading Symbol + ENUM_TIMEFRAMES mPeriod; // Trading Period + + // + // Inputs ... + X121Inputs mInputs; + X121XCCInputs xccInputs; + X121XPVInputs xpvInputs; + X121XHKInputs xhkInputs; + X121XMASInputs xmasInputs; + X121XATRInputs xatrInputs; + X121XDONInputs xdonInputs; + X121XSTRInputs xstrInputs; + X121XCHEInputs xcheInputs; + X121X3MAInputs x3maInputs; + X121XVWAPInputs xvwapInputs; + X121XTRENDInputs xtrendInputs; + + // + int mRSIHandler; +}; + +// \ No newline at end of file diff --git a/Experts/x-saherelm.xpoi.test.ea.mq5 b/Experts/x-saherelm.xpoi.test.ea.mq5 new file mode 100644 index 00000000..af5285ee --- /dev/null +++ b/Experts/x-saherelm.xpoi.test.ea.mq5 @@ -0,0 +1,129 @@ +//+------------------------------------------------------------------+ +//| x-saherelm.xpoi.test.ea.mq5 | +//| SaherElm IT Center | +//| https://www.saherelm.ir | +//+------------------------------------------------------------------+ +#property copyright "SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" + +// +// #include "../Classes/x-saherelm.x-poi.class.mq5" +// #include "../Classes/x-saherelm.x-poi.drawer.class.mq5" +// #include "../Libraries/x-saherelm.x-poi.extensions.lib.mq5" +// #include "../Libraries/x-saherelm.x-poi.state.lib.mq5" + +// +#include "../Classes/x-saherelm.x-bar.analyser.class.mq5" + +// +// Global Variables ... + +// +// XCPOIDrawer *mPOIDrawer; + +// +// XCPOIDetector *mPOIDetector; +XCBarAnalyser *mBarAnalyser; + +// +bool useDetector = false; +bool useBarAnalyser = true; + +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() +{ + // + // mPOIDetector = new XCPOIDetector( + // _Symbol, + // _Period // + // ); + + // + // mPOIDrawer = new XCPOIDrawer(); + + // + mBarAnalyser = new XCBarAnalyser(); + + // + return (INIT_SUCCEEDED); +} + +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) +{ + // + // ZeroMemory(mPOIDrawer); + // ZeroMemory(mPOIDetector); + ZeroMemory(mBarAnalyser); +} + +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() +{ + // + DetectBarAnalyser(); + + // + DetectPOIState(); +} + +//+------------------------------------------------------------------+ +//| Custom Functions | +//+------------------------------------------------------------------+ + +/** + * Detect POI(s) Using Bar Analyser Class ... + */ +void DetectBarAnalyser() +{ + // + if (!useBarAnalyser) + { + return; + } + + // + XOHCL zBar; + bool isInited = zBar.Init( + _Symbol, + _Period, + 0 // + ); + + // + XOHCL toBar; + XOHCL fromBar; + ENUM_X_DIRECTION dir; + bool isSpike = mBarAnalyser.IsSpike( + zBar, + fromBar, + toBar, + dir // + ); + if (isSpike) + { + Print("Spike Detected ..."); + } +} + +/** + * Detect POI(s) Using POIDetector Class ... + */ +void DetectPOIState() +{ + // + if (!useDetector) + { + return; + } +} + +// +//+------------------------------------------------------------------+ diff --git a/Helpers/x-saherelm.x121.helper.mq5 b/Helpers/x-saherelm.x121.helper.mq5 index ec2b5cae..167c0205 100644 --- a/Helpers/x-saherelm.x121.helper.mq5 +++ b/Helpers/x-saherelm.x121.helper.mq5 @@ -31,7 +31,6 @@ #include "../Helpers/x-saherelm.x121.xmas.helper.mq5" #include "../Helpers/x-saherelm.x121.xpv.helper.mq5" #include "../Helpers/x-saherelm.x121.xstr.helper.mq5" -#include "../Helpers/x-saherelm.x121.xtrend.helper.mq5" #include "../Helpers/x-saherelm.x121.xvwap.helper.mq5" // @@ -51,7 +50,6 @@ struct X121Inputs X121XDONInputs xdonInputs; X121X3MAInputs x3maInputs; X121XVWAPInputs xvwapInputs; - X121XTRENDInputs xtrendInputs; // // Constructor ... @@ -78,7 +76,6 @@ struct X121Inputs xcheInputs.Clean(); xdonInputs.Clean(); xvwapInputs.Clean(); - xtrendInputs.Clean(); // ZeroMemory(this); @@ -100,7 +97,6 @@ struct X121Inputs xdonInputs.Default(); x3maInputs.Default(); xvwapInputs.Default(); - xtrendInputs.Default(); } /** @@ -124,8 +120,7 @@ struct X121Inputs xstrInputs.IsValid() && xcheInputs.IsValid() && xdonInputs.IsValid() && - xvwapInputs.IsValid() && - xtrendInputs.IsValid() + xvwapInputs.IsValid() // ; @@ -152,7 +147,6 @@ struct X121Inputs int xcheMax = xcheInputs.Max(); int xdonMax = xdonInputs.Max(); int xvwapMax = xvwapInputs.Max(); - int xtrendMax = xtrendInputs.Max(); // result = MathMax(xpvMax, xhkMax); @@ -162,7 +156,6 @@ struct X121Inputs result = MathMax(result, xcheMax); result = MathMax(result, xdonMax); result = MathMax(result, xvwapMax); - result = MathMax(result, xtrendMax); // return result; @@ -2431,7 +2424,6 @@ class XCX121Helper : public XCBase XCX121XDONHelper *xdonHelper; XCX121X3MAHelper *x3maHelper; XCX121XVWAPHelper *xvwapHelper; - XCX121XTRENDHelper *xtrendHelper; // // Constructors ... @@ -2455,7 +2447,6 @@ class XCX121Helper : public XCBase xcheInputs.Clean(); x3maInputs.Clean(); xvwapInputs.Clean(); - xtrendInputs.Clean(); // delete xccHelper; @@ -2468,7 +2459,6 @@ class XCX121Helper : public XCBase delete xdonHelper; delete x3maHelper; delete xvwapHelper; - delete xtrendHelper; // ZeroMemory(xccHelper); @@ -2481,7 +2471,6 @@ class XCX121Helper : public XCBase ZeroMemory(xdonHelper); ZeroMemory(x3maHelper); ZeroMemory(xvwapHelper); - ZeroMemory(xtrendHelper); } // @@ -2546,7 +2535,6 @@ class XCX121Helper : public XCBase xdonInputs = inputs.xdonInputs; x3maInputs = inputs.x3maInputs; xvwapInputs = inputs.xvwapInputs; - xtrendInputs = inputs.xtrendInputs; // // Initial Helpers ... @@ -2681,19 +2669,6 @@ class XCX121Helper : public XCBase return result; } - // - // XTREND ... - xtrendHelper = new XCX121XTRENDHelper(); - result = xtrendHelper.Init( - symbol, - period, - xtrendInputs // - ); - if (!result) - { - return result; - } - // if (inputs.showRSI) { @@ -2918,28 +2893,6 @@ class XCX121Helper : public XCBase return result; } - // - // XTREND ... - bool GetTrendConditions( - X121XTRENDConditions &conditions, // - int barIndex = 0, // - int loopback = 5 // - ) - { - // - bool result = false; - - // - result = xtrendHelper.GetConditions( - conditions, - barIndex, - loopback // - ); - - // - return result; - } - // void Free() { @@ -2952,7 +2905,6 @@ class XCX121Helper : public XCBase xcheHelper.Free(); xdonHelper.Free(); xvwapHelper.Free(); - xtrendHelper.Free(); } // @@ -3138,19 +3090,6 @@ class XCX121Helper : public XCBase return result; } - // - // XTREND ... - X121XTRENDConditions xtrendConditions; - result = GetTrendConditions( - xtrendConditions, - barIndex, - loopback // - ); - if (!result) - { - return result; - } - // // Fill Volume Buffer ... for (int i = barIndex; i < barIndex + loopback; i++) @@ -3422,66 +3361,6 @@ class XCX121Helper : public XCBase conditions.masLowerBuffer // ); - // - // XTREND ... - - // - // Buffers ... - - // - Copy( - xtrendConditions.upTrendBuffer, - conditions.upTrendBuffer // - ); - - // - Copy( - xtrendConditions.downTrendBuffer, - conditions.downTrendBuffer // - ); - - // - Copy( - xtrendConditions.maBuffer, - conditions.maBuffer // - ); - - // - Copy( - xtrendConditions.adxBuffer, - conditions.adxBuffer // - ); - - // - Copy( - xtrendConditions.adxPBuffer, - conditions.adxPBuffer // - ); - - // - Copy( - xtrendConditions.adxMBuffer, - conditions.adxMBuffer // - ); - - // - Copy( - xtrendConditions.upTBuffer, - conditions.upTBuffer // - ); - - // - Copy( - xtrendConditions.downTBuffer, - conditions.downTBuffer // - ); - - // - conditions.isTrendBullish = xtrendConditions.isTrendBullish; - conditions.isTrendBearish = xtrendConditions.isTrendBearish; - conditions.isTrendSwitchedToBullish = xtrendConditions.isTrendSwitchedToBullish; - conditions.isTrendSwitchedToBearish = xtrendConditions.isTrendSwitchedToBearish; - // // XATR ... @@ -4594,7 +4473,6 @@ class XCX121Helper : public XCBase xdonConditions.Clean(); x3maConditions.Clean(); xvwapConditions.Clean(); - xtrendConditions.Clean(); // Free(); @@ -4628,7 +4506,6 @@ class XCX121Helper : public XCBase X121XCHEInputs xcheInputs; X121X3MAInputs x3maInputs; X121XVWAPInputs xvwapInputs; - X121XTRENDInputs xtrendInputs; // int mRSIHandler; diff --git a/Helpers/x-saherelm.x121.xpv.helper.mq5 b/Helpers/x-saherelm.x121.xpv.helper.mq5 index 5d2f2fe9..b694a71f 100644 --- a/Helpers/x-saherelm.x121.xpv.helper.mq5 +++ b/Helpers/x-saherelm.x121.xpv.helper.mq5 @@ -126,22 +126,22 @@ struct X121XPVInputs { // // Short ... - scMethod = X_PERIOD_NOTHING; + scMethod = X_PERIOD_NONE; scPeriod = NULL; // // Medium ... - mcMethod = X_PERIOD_NOTHING; + mcMethod = X_PERIOD_NONE; mcPeriod = NULL; // // Long ... - lcMethod = X_PERIOD_NOTHING; + lcMethod = X_PERIOD_NONE; lcPeriod = NULL; // // Hind ... - hcMethod = X_PERIOD_NOTHING; + hcMethod = X_PERIOD_NONE; hcPeriod = NULL; // diff --git a/Indicators/x-saherelm.x121.xsessions.mq5 b/Indicators/x-saherelm.x121.xsessions.mq5 new file mode 100644 index 00000000..c2660db9 --- /dev/null +++ b/Indicators/x-saherelm.x121.xsessions.mq5 @@ -0,0 +1,197 @@ +//+------------------------------------------------------------------+ +//| Forex Sessions and Day Range Indicator | +//+------------------------------------------------------------------+ +#property copyright "Your Name" +#property link "https://www.example.com" +#property version "1.00" +#property indicator_chart_window + +#include + +struct SessionInfo { + string name; + int startHour; // Standard start hour (GMT) + int startMinute; + int endHour; // Standard end hour (GMT) + int endMinute; + bool *isDST(datetime); // DST check function + int dstAdjustment; // Hours to add during DST +}; + +SessionInfo sessions[] = { + {"Sydney", 21, 0, 5, 0, IsSydneyDST, 1}, + {"Tokyo", 23, 0, 8, 0, IsTokyoDST, 0}, + {"London", 7, 0, 15, 0, IsLondonDST, 1}, + {"New York", 12, 0, 17, 0, IsNewYorkDST, 1} +}; + +bool sessionActive[]; +double sessionHigh[]; +double sessionLow[]; +datetime sessionStartTime[]; +datetime sessionEndTime[]; + +double dayHigh = 0; +double dayLow = 0; +datetime dayStartTime; + +//+------------------------------------------------------------------+ +//| Custom indicator initialization function | +//+------------------------------------------------------------------+ +int OnInit() { + ArrayResize(sessionActive, ArraySize(sessions)); + ArrayResize(sessionHigh, ArraySize(sessions)); + ArrayResize(sessionLow, ArraySize(sessions)); + ArrayResize(sessionStartTime, ArraySize(sessions)); + ArrayResize(sessionEndTime, ArraySize(sessions)); + + for(int i=0; i= todayStart && currentTime < todayEnd) { + if(!sessionActive[i]) { + sessionActive[i] = true; + sessionStartTime[i] = todayStart; + sessionEndTime[i] = todayEnd; + sessionHigh[i] = Bid; + sessionLow[i] = Ask; + } else { + if(Bid > sessionHigh[i]) sessionHigh[i] = Bid; + if(Ask < sessionLow[i]) sessionLow[i] = Ask; + } + } else { + sessionActive[i] = false; + } + } + + // Check day range + bool dstActiveNY = IsNewYorkDST(currentTime); + int dayStartHour = dstActiveNY ? 21 : 22; + datetime todayDayStart = StringToTime(TimeToString(currentTime, TIME_DATE) + " " + + IntegerToString(dayStartHour) + ":00"); + + if(currentTime < todayDayStart) { + todayDayStart -= 24 * 3600; + } + + if(dayStartTime != todayDayStart) { + dayStartTime = todayDayStart; + dayHigh = Bid; + dayLow = Ask; + } else { + if(Bid > dayHigh) dayHigh = Bid; + if(Ask < dayLow) dayLow = Ask; + } + + // Display information on chart + string comment = "Active Forex Sessions:\n"; + for(int i=0; i= dstStart && time < dstEnd; +} + +bool IsNewYorkDST(datetime time) { + int year = TimeYear(time); + datetime march1 = StringToTime(year + ".03.01 00:00"); + int dayOfWeekMarch1 = TimeDayOfWeek(march1); + int secondSundayMarch = 1 + (7 - dayOfWeekMarch1) % 7 + 7; + datetime dstStart = StringToTime(year + ".03." + IntegerToString(secondSundayMarch) + " 07:00"); + + datetime nov1 = StringToTime(year + ".11.01 00:00"); + int dayOfWeekNov1 = TimeDayOfWeek(nov1); + int firstSundayNov = 1 + (7 - dayOfWeekNov1) % 7; + datetime dstEnd = StringToTime(year + ".11." + IntegerToString(firstSundayNov) + " 06:00"); + + return time >= dstStart && time < dstEnd; +} + +bool IsSydneyDST(datetime time) { + int year = TimeYear(time); + datetime oct1 = StringToTime(year + ".10.01 00:00"); + int dayOfWeekOct1 = TimeDayOfWeek(oct1); + int firstSundayOct = 1 + (7 - dayOfWeekOct1) % 7; + datetime dstStart = StringToTime(year + ".10." + IntegerToString(firstSundayOct) + " 13:00"); + + datetime apr1 = StringToTime(year + ".04.01 00:00"); + int dayOfWeekApr1 = TimeDayOfWeek(apr1); + int firstSundayApr = 1 + (7 - dayOfWeekApr1) % 7; + datetime dstEnd = StringToTime(year + ".04." + IntegerToString(firstSundayApr) + " 15:00"); + + return time >= dstStart && time < dstEnd; +} + +bool IsTokyoDST(datetime time) { + return false; +} \ No newline at end of file diff --git a/Libraries/x-saherelm.common.extensions.lib.mq5 b/Libraries/x-saherelm.common.extensions.lib.mq5 new file mode 100644 index 00000000..2eba7f47 --- /dev/null +++ b/Libraries/x-saherelm.common.extensions.lib.mq5 @@ -0,0 +1,5956 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Common Library +// -------------------------------------- +// Name: XCommonExtensionsLib +// Description: provide all commonly used functions ... +// +// +// 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 + +// +#include "../Classes/x-saherelm.x-md5.class.mq5" +#include "../Libraries/x-saherelm.x-enums.lib.mq5" + +// +#include + +// +// Constants ... +#define X_MIN_SIZE 0 +#define X_INVALID_INDEX -1 + +// +// START Value Checkers ... +// + +// +// Check a Value Not Empty ... +template +bool NotEmpty(T value) +{ + return value != EMPTY_VALUE; +} + +// +// Check a Value Not Empty and Zero ... +template +bool NotEmptyZero(T value) +{ + return value != 0 && + value != EMPTY_VALUE; +} + +// +// END Value Checkers ... +// + +// +// START Validators ... +// + +/** + * Validate Strings ... + * + * @param value: string + * + * @return ( bool ) + */ +bool IsValid(string value) +{ + // + bool result = false; + + // + result = + // + value != NULL && + StringLen(value) > 0 + // + ; + + // + return result; +} +bool IsSpecifiedValid(string value) +{ + return IsValid(value); +} + +/** + * Validate Date ... + * + * @param value: datetime + * + * @return ( bool ) + */ +bool IsValid(datetime value) +{ + // + bool result = false; + + // + result = NotEmpty(value) && value != NULL; + + // + return result; +} +bool IsSpecifiedValid(datetime value) +{ + return IsValid(value); +} + +/** + * Validate Time Frame ... + * + * @param value: ENUM_TIMEFRAMES member ... + * + * @return ( bool ) + */ +bool IsValid(ENUM_TIMEFRAMES value) +{ + // + bool result = false; + + // + result = + // + value != NULL + // + ; + + // + return result; +} +bool IsSpecifiedValid(ENUM_TIMEFRAMES value) +{ + // + return IsValid(value); +} + +/** + * Validate Specific Period Mode ... + * + * @param mMethod: ENUM_X_PERIOD_METHOD member, Period Select Method ... + * @param mPeriod: ENUM_TIMEFRAMES member, Selected Period ... + * + * @return ( bool ) + */ +bool IsValid( + ENUM_X_PERIOD_METHOD mMethod, + ENUM_TIMEFRAMES mPeriod // +) +{ + // + bool result = false; + + // + result = + // + mMethod == X_PERIOD_NONE + ? false + : mMethod == X_PERIOD_MANUALLY + ? mPeriod != NULL + : mMethod == X_PERIOD_AUTO + ? true + : false + // + ; + + // + return result; +} +bool IsSpecifiedValid( + ENUM_X_PERIOD_METHOD mMethod, + ENUM_TIMEFRAMES mPeriod // +) +{ + return IsValid( + mMethod, + mPeriod // + ); +} + +/** + * Validate a Size Value ... + * + * @param value: int, Provided Size ... + * + * @return ( bool ) + */ +bool IsValidSize(int value) +{ + // + bool result = value > X_MIN_SIZE; + + // + return result; +} + +/** + * Check a Given Index is Valid or not ... + * + * @param value: int, Provided Index ... + * + * @return ( bool ) + */ +bool IsValidIndex(int value) +{ + return value >= X_MIN_SIZE; +} + +// +// END Validators ... +// + +// +// START Normalizations ... +// + +/** + * Normalize Symbol ... + * + * @param value: string, Provided Symbols ... + * + * @return ( string ) + */ +string NormalizeSymbol(string value) +{ + // + string result = value; + + // + if (!IsValid(result)) + { + result = _Symbol; + } + + // + return result; +} + +/** + * Normalize Time ... + * + * @param value: datetime, Provided Time ... + * + * @return ( datetime ) + */ +datetime NormalizeTime(datetime value) +{ + // + datetime result = value; + + // + if (!IsValid(result)) + { + result = TimeCurrent(); + } + + // + return result; +} + +/** + * Normalize Period ... + * + * @param value: ENUM_TIMEFRAMES member, Provided Period ... + * + * @return ( ENUM_TIMEFRAMES ) + */ +ENUM_TIMEFRAMES NormalizePeriod(ENUM_TIMEFRAMES value) +{ + // + ENUM_TIMEFRAMES result = value; + + // + if (!IsValid(value)) + { + result = _Period; + } + + // + return result; +} + +/** + * Normalize Market Cycle ... + * + * @param value: ENUM_X_MARKET_CYCLES, Provided Cycle ... + * + * @return ( ENUM_X_MARKET_CYCLES ) + */ +ENUM_X_MARKET_CYCLES NormalizeCycle(ENUM_X_MARKET_CYCLES value) +{ + // + ENUM_X_MARKET_CYCLES result = value; + + // + if (!IsValid(result)) + { + result = X_MARKET_CYCLE_SHORT; + } + + // + return value; +} + +/** + * Normalize Integer Value ... + * + * @param value: int, Provided Value ... + * @param min: int, Minimum Allowed Value ... + * @param max: int, Maximum Allowed Value ... + * + * @return ( int ) + */ +int NormalizeInt( + int value, + int min = 0, + int max = INT_MAX // +) +{ + // + if (value < min) + { + value = min; + } + + // + if (value > max) + { + value = max; + } + + // + return value; +} + +/** + * Normalize Double Value ... + * + * @param value: double, Provided Value ... + * @param min: double, Minimum Allowed Value ... + * @param max: double, Maximum Allowed Value ... + * + * @return ( double ) + */ +double NormalizeDouble( + double value, + double min = 0, + double max = DBL_MAX // +) +{ + // + if (value < min) + { + value = min; + } + + // + if (value > max) + { + value = max; + } + + // + return value; +} + +/** + * Normalize Index based on Collection ... + * + * @param index: int, Provided Index ... + * @param buffer: Collection Reference ... + */ +template +bool NormalizeIndex( + int &index, + T &buffer[] // +) +{ + // + bool result = false; + + // + int size = ArraySize(buffer); + result = IsValidSize(size); + if (!result) + { + return result; + } + + // + if (!IsValidIndex(index)) + { + index = X_MIN_SIZE; + } + + // + if (index > size - 1) + { + index = size - 1; + } + + // + result = IsValidIndex(index) && + index >= X_MIN_SIZE && + index < size; + + // + return result; +} + +/** + * Normalize Start and Count based on Specified Buffer ... + * + * @param start: int, Provided Start index ... + * @param count: int, Provided Number of Iteration ... + * @param buffer: Collection instance ... + */ +template +void NormalizeCount( + int &start, + int &count, + T &buffer[] // +) +{ + // + // Validate Buffer Size ... + int bufferSize = ArraySize(buffer); + if (!IsValidSize(bufferSize)) + { + return; + } + + // + // Normalization Start ... + NormalizeIndex( + start, + buffer // + ); + + // + if (count < start) + { + count = (start - count); + } + + // + // Normalization Count ... + + // + if (count < 0) + { + count = start; + } + + // + if (count > bufferSize - start) + { + count = bufferSize - start; + } +} + +/** + * Normalize a Volume ... + * + * @param mVolume: double, Provided Volume ... + * @param mSymbol: string, Specified Symbol ... + * @param mLength: int, Provided Default floating Length ... + * + * @return ( double ) + */ +double NormalizeVolume( + double mVolume, + string mSymbol = NULL, + int mLength = 2 // +) +{ + // + double result = mVolume; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double maxAvailableVolume = SymbolInfoDouble(mSymbol, SYMBOL_VOLUME_MAX); + double minAvailableVolume = SymbolInfoDouble(mSymbol, SYMBOL_VOLUME_MIN); + + // + // Normalize Digits ... + int digits = GetDigits(minAvailableVolume); + + // + mLength = + mLength == 0 || mLength > digits + ? digits + : MathMin(mLength, digits); + + // + // Normalize Volume ... + result = NormalizeDouble(result, mLength); + + // + // Validate Result ... + if (result > maxAvailableVolume) + { + result = maxAvailableVolume; + } + else if (result < minAvailableVolume) + { + result = minAvailableVolume; + } + + // + return result; +} + +/** + * Normalize a Price Value ... + * + * @param mPrice: double, Provided Price ... + * @param mSymbol: string, Provided Symbol ... + * + * @return ( double ) + */ +double NormalizePrice( + double mPrice, + string mSymbol = NULL // +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double tickSize = 0; + result = SymbolInfoDouble(mSymbol, SYMBOL_TRADE_TICK_SIZE, tickSize); + + // + int digits = GetDigits(mSymbol); + result = NormalizeDouble(MathRound(mPrice / tickSize) * tickSize, digits); + + // + return result; +} + +// +// END Normalizations ... +// + +// +// START Position ... +// + +/** + * Determine a Position type is Long or not ... + * + * @param value: ENUM_POSITION_TYPE member, Specified Type ... + * + * @return ( bool ) + */ +bool IsLong(ENUM_POSITION_TYPE value) +{ + // + bool result = value == POSITION_TYPE_BUY; + + // + return result; +} + +/** + * Determine a Position type is Long or not ... + * + * @param value: ENUM_ORDER_TYPE member, Specified Type ... + * + * @return ( bool ) + */ +bool IsLong(ENUM_ORDER_TYPE value) +{ + // + bool result = value == ORDER_TYPE_BUY; + + // + return result; +} + +/** + * Determine a Position type is Long or not ... + * + * @param value: ENUM_X_DIRECTION member, Specified Type ... + * + * @return ( bool ) + */ +bool IsLong(ENUM_X_DIRECTION value) +{ + // + bool result = value == X_DIRECTION_BULLISH; + + // + return result; +} + +/** + * Determine a Position type is Short or not ... + * + * @param value: ENUM_POSITION_TYPE member, Specified Type ... + * + * @return ( bool ) + */ +bool IsShort(ENUM_POSITION_TYPE value) +{ + // + bool result = value == POSITION_TYPE_SELL; + + // + return result; +} + +/** + * Determine a Position type is Short or not ... + * + * @param value: ENUM_ORDER_TYPE member, Specified Type ... + * + * @return ( bool ) + */ +bool IsShort(ENUM_ORDER_TYPE value) +{ + // + bool result = value == ORDER_TYPE_SELL; + + // + return result; +} + +/** + * Determine a Position type is Short or not ... + * + * @param value: ENUM_X_DIRECTION member, Specified Type ... + * + * @return ( bool ) + */ +bool IsShort(ENUM_X_DIRECTION value) +{ + // + bool result = value == X_DIRECTION_BEARISH; + + // + return result; +} + +/** + * Converts Opposit Direction Type ... + * + * @param value: ENUM_POSITION_TYPE member, Specified Type ... + * + * @return ( ENUM_POSITION_TYPE ) + */ +ENUM_POSITION_TYPE Opposit(ENUM_POSITION_TYPE value) +{ + // + ENUM_POSITION_TYPE result = NULL; + + // + bool isLong = IsLong(value); + result = isLong + ? POSITION_TYPE_SELL + : POSITION_TYPE_BUY; + + // + return result; +} + +/** + * Converts Opposit Direction Type ... + * + * @param value: ENUM_ORDER_TYPE member, Specified Type ... + * + * @return ( ENUM_ORDER_TYPE ) + */ +ENUM_ORDER_TYPE Opposit(ENUM_ORDER_TYPE value) +{ + // + ENUM_ORDER_TYPE result = NULL; + + // + bool isLong = IsLong(value); + result = isLong + ? ORDER_TYPE_SELL + : ORDER_TYPE_BUY; + + // + return result; +} + +/** + * Converts To String ... + * + * @param value: ENUM_POSITION_TYPE member ... + * + * @return ( string ) + */ +string ToString(ENUM_POSITION_TYPE value) +{ + // + string result = NULL; + + // + result = + // + IsLong(value) + ? "Long" + : "Short" + // + ; + + // + return result; +} + +/** + * Converts To String ... + * + * @param value: ENUM_ORDER_TYPE member ... + * + * @return ( string ) + */ +string ToString(ENUM_ORDER_TYPE value) +{ + // + string result = NULL; + + // + result = + // + IsLong(value) + ? "Long" + : "Short" + // + ; + + // + return result; +} + +/** + * Get Ask Price ... + * + * @param mSymbol: string, Provided Symbol ... + * + * @return ( double ) + */ +double GetAsk( + string mSymbol = NULL // +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double result = SymbolInfoDouble(mSymbol, SYMBOL_ASK); + + // + return result; +} + +/** + * Get Bid Price ... + * + * @param mSymbol: string, Provided Symbol ... + * + * @return ( double ) + */ +double GetBid( + string mSymbol = NULL // +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double result = SymbolInfoDouble(mSymbol, SYMBOL_BID); + + // + return result; +} + +/** + * Get Spread Price ... + * + * @param mSymbol: string, Provided Symbol ... + * + * @return ( double ) + */ +double GetSpread( + string mSymbol = NULL // +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double ask = GetAsk(mSymbol); + double bid = GetBid(mSymbol); + + // + double result = MathAbs(ask - bid); + + // + return result; +} + +/** + * Get Point Price ... + * + * @param mSymbol: string, Provided Symbol ... + * + * @return ( double ) + */ +double GetPoints( + string mSymbol = NULL // Trading Symbol +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double result = SymbolInfoDouble(mSymbol, SYMBOL_POINT); + + // + return result; +} + +/** + * Get Digits Length ... + * + * @param mSymbol: string, Provided Symbol ... + * + * @return ( double ) + */ +int GetDigits( + string mSymbol = NULL // Trading Symbol +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + int result = (int)SymbolInfoInteger(mSymbol, SYMBOL_DIGITS); + + // + return result; +} + +/** + * Get Entry Price ... + * + * @param mSymbol: string, Provided Symbol ... + * @param type: ENUM_POSITION_TYPE member, Specified Entry type ... + * + * @return ( double ) + */ +double GetEntry( + string mSymbol = NULL, + ENUM_POSITION_TYPE type = POSITION_TYPE_BUY // +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + result = + IsLong(type) + ? GetAsk(mSymbol) + : GetBid(mSymbol); + result = NormalizePrice(result, mSymbol); + + // + return result; +} + +/** + * Get Entry Price ... + * + * @param mSymbol: string, Provided Symbol ... + * @param type: ENUM_X_DIRECTION member, Specified Entry type ... + * + * @return ( double ) + */ +double GetEntry( + string mSymbol = NULL, + ENUM_X_DIRECTION type = X_DIRECTION_BULLISH // +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + result = + IsBullish(type) + ? GetAsk(mSymbol) + : GetBid(mSymbol); + result = NormalizePrice(result, mSymbol); + + // + return result; +} + +/** + * Get Exit Price ... + * + * @param mSymbol: string, Provided Symbol ... + * @param type: ENUM_POSITION_TYPE member, Specified Exit type ... + * + * @return ( double ) + */ +double GetExit( + string mSymbol = NULL, + ENUM_POSITION_TYPE type = POSITION_TYPE_BUY // +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + result = + IsLong(type) + ? GetBid(mSymbol) + : GetAsk(mSymbol); + result = NormalizePrice(result, mSymbol); + + // + return result; +} + +/** + * Get Exit Price ... + * + * @param mSymbol: string, Provided Symbol ... + * @param type: ENUM_X_DIRECTION member, Specified Exit type ... + * + * @return ( double ) + */ +double GetExit( + string mSymbol = NULL, + ENUM_X_DIRECTION type = X_DIRECTION_BULLISH // +) +{ + // + double result = 0; + + // + mSymbol = NormalizeSymbol(mSymbol); + + // + result = + IsBullish(type) + ? GetBid(mSymbol) + : GetAsk(mSymbol); + result = NormalizePrice(result, mSymbol); + + // + return result; +} + +// +// END Position ... +// + +// +// START Tools ... +// + +/** + * Check Expert Running in Testing Mode or not ... + * + * @return ( bool ) + */ +bool IsRunningOnTestMode() +{ + // + bool result = false; + + // + // check programm mode ... + result = MQL5InfoInteger(MQL5_TESTING); + + // + return result; +} + +/** + * Find Chart ID ... + * + * @param mSymbol: string, Specified Symbol ... + * @param mPeriod: ENUM_TIMEFRAMES member, Specified Period ... + * + * @return ( long ) + */ +long FindChartID( + string mSymbol = NULL, + ENUM_TIMEFRAMES mPeriod = NULL // +) +{ + // + long result = ChartFirst(); + long first = result; + + // + while (result > 0) + { + // + string chSymbol = ChartSymbol(result); + ENUM_TIMEFRAMES chPeriod = ChartPeriod(result); + + // + bool isOwn = + // + chSymbol == mSymbol && + chPeriod == mPeriod + // + ; + if (isOwn) + { + break; + } + + // + result = ChartNext(result); + } + + // + return result; +} + +/** + * Retrieve Available Symbols ... + * + * @param symbols: string Collection reference to Hold Symbols ... + * @param onlyInWatchList: bool, Force Extracts only Watch List Symbols ... + * + * @return ( int ) + */ +int GetAllSymbols( + string &symbols[], // Hold Result + bool onlyInWatchList = false // Specified Retrieve only Symbols which in Watch List +) +{ + // + int result = 0; + + // + Clean(symbols); + + // + int count = SymbolsTotal(onlyInWatchList); + if (!IsValidSize(count)) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + string iSymbol = SymbolName( + i, + onlyInWatchList // + ); + if (!IsValid(iSymbol)) + { + continue; + } + + // + Add( + iSymbol, + symbols // + ); + } + + // + result = ArraySize(symbols); + + // + return result; +} + +/** + * Filter Symbols Collections ... + * + * @param query: string, Provided Query to Search Symbols ... + * @param symbols: string, Collection resources to Hold's Filtered results ... + * @param onlyInWatchList: bool, Specified Apply Filter only on Watch List Symbols ... + * @param ignoreCase: bool, Ignore Case Sesitive ... + * @param querySeparator: string, Provided Separator of Query ... + * + * @return ( int ) + */ +int FilterSymbols( + string query, + string &symbols[], + bool onlyInWatchList = false, + bool ignoreCase = true, + string querySeparator = "," // If Provided means query is a Collection of Queries and need to be Splitted +) +{ + // + int result = 0; + + // + Clean(symbols); + + // + if (!IsValid(query)) + { + return result; + } + + // + // Check Query is an String array or not ... + string mQueries[]; + int queriesCount = 0; + if (IsValid(querySeparator) && Contains(querySeparator, query, true)) + { + // + queriesCount = SplitContent( + mQueries, + query, + querySeparator // + ); + } + + // + string allSymbols[]; + int allSymbolsCount = GetAllSymbols( + allSymbols, + onlyInWatchList // + ); + if (allSymbolsCount <= 0) + { + return result; + } + + // + // Loop Through all Symbols ... + for (int i = 0; i < allSymbolsCount; i++) + { + // + string iSymbol = allSymbols[i]; + + // + bool isFilterPassed = false; + if (queriesCount == 0) + { + // + isFilterPassed = Contains( + query, + iSymbol, + ignoreCase // + ); + } + else if (queriesCount > 0) + { + // + isFilterPassed = Contains( + mQueries, + iSymbol, + ignoreCase // + ); + } + + // + if (isFilterPassed) + { + // + Add( + iSymbol, + symbols // + ); + } + } + + // + result = ArraySize(symbols); + + // + return result; +} + +/** + * Extract Symbols to Find Only USD Side Assets ... + * + * @param symbols: string, Collection resources to Hold's Filtered results ... + * @param onlyInWatchList: bool, Specified Apply Filter only on Watch List Symbols ... + * @param ignoreCase: bool, Ignore Case Sesitive ... + * @param querySeparator: string, Provided Separator of Query ... + * + * @return ( int ) + */ +int FilterUSDSymbols( + string &symbols[], + bool onlyInWatchList = false, + bool ignoreCase = true, + string querySeparator = "," // +) +{ + // + return FilterSymbols( + "USD", + symbols, + onlyInWatchList, + ignoreCase, + querySeparator // + ); +} + +/** + * Get Digits Length of Specified Double Value ... + * + * @param value: double, Provided Value ... + * + * @return ( int ) + */ +int GetDigits(double value) +{ + // + int d = 0; + double p = 1; + while (MathRound(value * p) / p != value) + { + p = MathPow(10, ++d); + } + + // + return d; +} + +/** + * Retrieve Specific Object Types Name ... + * + * @param t: T object reference ... + * + * @return ( string ) + * + */ +template +string GetTypeName(const T &t) +{ + return typename(T); +} + +/** + * Get Specified Types Token ... + * + * @param item: T, object reference ... + * + * @return ( string ) + */ +template +string GetToken(T &item) +{ + // + string mType = GetTypeName(item); + + // + string result = mType; + + // + string parts[]; + int partsCount = SplitContent( + parts, + result, + " " // + ); + if (partsCount <= 0) + { + // + result = mType; + return result; + } + + // + bool hasLastPart = GetLastItem( + result, + parts // + ); + if (!hasLastPart) + { + // + result = mType; + return result; + } + + // + return result; +} +template +string GetSpecificToken(T &item) +{ + return GetToken(item); +} + +/** + * Generate Unique Tags ... + * + * @param model: T, object reference ... + * + * @return ( string ) + */ +template +string GenerateTag(T &model) +{ + // + string result = ""; + + // + string tag = model.ToString(); + if (StringLen(tag) == 0) + { + return result; + } + + // + XSCMD5 *md5; + md5 = new XCMD5(); + + // + result = md5.Hash(tag); + + // + ZeroMemory(md5); + + // + return result; +} + +/** + * Hash Specified Content ... + * + * @param content: T, Proveded Content ... + * + * @return ( string ) + */ +template +string ToMD5(T content) +{ + // + string result = ""; + + // + string strContent = ToString(content); + if (StringLen(strContent) == 0) + { + return result; + } + + // + XCMD5 *md5; + md5 = new XCMD5(); + + // + result = md5.Hash(strContent); + + // + ZeroMemory(md5); + + // + return result; +} + +/** + * Calculate Fibo Level ... + * + * @param mUp: double, Specified Upper Price ... + * @param mDown: double, Specified Lower Price ... + * @param mLevel: ENUM_X_FIBO_LEVELS member, Specified Fibo Level ... + * @param mForDir: ENUM_X_DIRECTION member, Specified Calculation Direction ... + * + * @return ( double ) + */ +double GetFibonacciLevel( + double mUp, + double mDown, + ENUM_X_FIBO_LEVELS mLevel, + ENUM_X_DIRECTION mForDir // +) +{ + // + double result = 0; + + // + double levelValue = GetFiboLevelValue(mLevel); + + // + bool isValid = + // + mUp > 0 && + mDown > 0 && + levelValue > 0 && + mUp > mDown && + HasDirection(mForDir) + // + ; + if (!isValid) + { + return result; + } + + // + bool isBullish = IsBullish(mForDir); + + // + double ling = mUp - mDown; + double pLevel = (ling / 100) * (levelValue * 100); + + // + result = + isBullish + ? mUp - pLevel + : mDown + pLevel; + + // + return result; +} + +/** + * Calculate Sspecified Buffer's Moving Averages ... + * + * @param rates_total: Integer, number of items ... + * @param prev_calculated: Integer, Previous Calculate Items ... + * @param begin: Integer, Bar Index ... + * @param period: Integer, Moving Average Length ... + * @param source: Double Array, Specified Array for Calculating Moving Averages ... + * @param buffer: Double Array, Specified Array to Apply Calculated Moving Average on it ... + * @param method: ENUM_MA_METHOD member Specified Moving Average Calculation Method ... + * + * @return ( int ) + */ +int iMAOnBuffer( + const int _rates_total, + const int _prev_calculated, + const int _begin, + const int _period, + const double &_source[], + double &_buffer[], + ENUM_X_MA_METHOD _method = X_MA_MODE_SMA // +) +{ + // + int result = 0; + + // + if ( + _period < 0 || + _rates_total <= 0 || + _prev_calculated < 0 || + _method == X_MA_MODE_NONE || + _prev_calculated > _rates_total) + { + return result; + } + + // + switch (_method) + { + // + case X_MA_MODE_SMA: + result = SimpleMAOnBuffer( + _rates_total, + _prev_calculated, + _begin, + _period, + _source, + _buffer // + ); + break; + + // + case X_MA_MODE_EMA: + result = ExponentialMAOnBuffer( + _rates_total, + _prev_calculated, + _begin, + _period, + _source, + _buffer // + ); + break; + + // + case X_MA_MODE_LWMA: + result = LinearWeightedMAOnBuffer( + _rates_total, + _prev_calculated, + _begin, + _period, + _source, + _buffer // + ); + break; + + // + case X_MA_MODE_SMMA: + result = SmoothedMAOnBuffer( + _rates_total, + _prev_calculated, + _begin, + _period, + _source, + _buffer // + ); + break; + } + + // + return result; +} + +// +// END Tools ... +// + +// +// START String ... +// + +/** + * Search a Content Contains Specific String or not ... + * + * @param mQuery: string, Search Query ... + * @param mContent: string, Search Content ... + * @param ignoreCase: bool, Force Ignore Case Sensitive ... + * + * @return ( bool ) + */ +bool Contains( + string mQuery, + string mContent, + bool ignoreCase = true // +) +{ + // + bool result = false; + + // + // Validate Query ... + result = IsValid(mQuery); + if (!result) + { + return result; + } + + // + // Validate Content ... + result = IsValid(mContent); + if (!result) + { + return result; + } + + // + // Normalize Inputs ... + string query = mQuery; + string content = mContent; + if (ignoreCase) + { + // + StringToLower(query); + StringToLower(content); + } + + // + int queryIdx = StringFind( + content, + query); + + // + result = queryIdx >= 0; + + // + return result; +} + +/** + * Search a Content Contains Specifics Query or not ... + * + * @param mQueries: string collection, Search Queries ... + * @param mContent: string, Search Content ... + * @param ignoreCase: bool, Force Ignore Case Sensitive ... + * + * @return ( bool ) + */ +bool Contains( + string &mQueries[], + string mContent, + bool ignoreCase = true // +) +{ + // + bool result = false; + + // + // Validate Queries ... + int queriesCount = ArraySize(mQueries); + result = queriesCount > 0; + if (!result) + { + return result; + } + + // + // Validate Content ... + result = IsValid(mContent); + if (!result) + { + return result; + } + + // + int containsCount = 0; + for (int i = 0; i < queriesCount; i++) + { + // + bool isContains = Contains( + mQueries[i], + mContent, + ignoreCase); + + // + if (!isContains) + { + // + result = false; + break; + } + + // + containsCount++; + } + + // + result = containsCount == queriesCount; + + // + return result; +} + +/** + * Search a Content and Extract Occuranse Indexes ... + * + * @param mQuery: string, Search Query ... + * @param mContent: string, Search Content ... + * @param result: int collection reference, Holds Founded Indexes ... + * @param ignoreCase: bool, Force Ignore Case Sensitive ... + * + * @return ( int ) + */ +int FindIndexes( + string mQuery, + string mContent, + int &result[], + bool ignoreCase = false // +) +{ + // + int mResult = 0; + + // + Clean(result); + + // + // Validate Inputs ... + if (!IsValid(mQuery) || + !IsValid(mContent)) + { + return mResult; + } + + // + // Apply Ignore Case if Provided ... + if (ignoreCase) + { + // + bool isConverted = StringToLower(mQuery); + if (!isConverted) + { + return mResult; + } + + // + isConverted = StringToLower(mContent); + if (!isConverted) + { + return mResult; + } + } + + // + // Search First Index ... + int lastPos = 0; + int idx = StringFind( + mContent, + mQuery, + lastPos // + ); + while (idx >= 0) + { + // + // Add Position to Result ... + Add( + idx, + result // + ); + + // + lastPos = idx + StringLen(mQuery); + idx = StringFind( + mContent, + mQuery, + lastPos // + ); + } + + // + mResult = ArraySize(result); + + // + return mResult; +} + +/** + * Convert From String ... + * + * @param value: string, Provided Value ... + * + * @return ( T ) + */ +template +T FromString(string value) +{ + // + T result = NULL; + + // + if (!IsValid(value)) + { + return result; + } + + // + result = (T)value; + + // + return result; +} + +/** + * Converts to String ... + * + * @param value: T, Provided Value ... + * + * @return ( string ) + */ +template +string ToString(T value) +{ + return (string)value; +} + +// +// Used In Report or Summary Generators ... +string ToString( + string prefix, // Title + bool value, // Value + bool ignoreFalseConditions = true, // Ignore False Conditions + string lineSeparator = "\n", // Line Separator + string prefixSeparator = ":" // Title Separator +) +{ + // + string result = NULL; + + // + result = (value || !ignoreFalseConditions) + ? prefix + + prefixSeparator + " " + + ToString(value) + + lineSeparator + : ""; + + // + return result; +} + +// +template +string ToString( + string prefix, // Title + T value, // Value + string lineSeparator = "\n", // Line Separator + string prefixSeparator = ":" // Title Separator +) +{ + // + string result = NULL; + + // + result = prefix + + prefixSeparator + " " + + ToString(value) + + lineSeparator; + + // + return result; +} + +// +string SetLabel( + string mLabel, // Provided Label ... + string value, // Source Value ... + string separator = "\n", // Line Separator + bool addTopEmptyLine = true // Add Empty Line On top +) +{ + // + string result = value; + + // + if (StringLen(mLabel) <= 0) + { + return result; + } + + // + result = (StringLen(value) > 0) + ? (addTopEmptyLine ? separator : "") + + mLabel + + separator + + "-----------------------------" + + separator + + value + : value; + + // + return result; +} + +// +// Converts a Buffer to String Representation ... +template +string ToString( + const T &buffer[], // Specified Buffer + string separator = ",", // Specified Separator + bool addIndex = false, // Specified Add Items Indexes or Not + string indexLabel = "i:", // Specified Index Label + string indexSeparator = ">" // Specified Index Separator +) +{ + // + string result = ""; + + // + int bufferSize = ArraySize(buffer); + if (bufferSize <= 0) + { + return result; + } + + // + for (int i = 0; i < bufferSize; i++) + { + // + if (addIndex) + { + // + if (StringLen(indexLabel) > 0) + { + result += indexLabel + " "; + } + + // + result += (string)i + " "; + + // + if (StringLen(indexSeparator) > 0) + { + result += indexSeparator + " "; + } + } + + // + string iItemString = (string)buffer[i]; + + // + result += iItemString; + + // + if (i < bufferSize - 1) + { + result += separator; + } + } + + // + return result; +} + +/** + * Converts String to boolean ... + * + * @param value: string, Provided Value ... + * + * @return ( bool ) + */ +bool ToBoolean(string value) +{ + // + bool result = false; + + // + if (StringLen(value) <= 0) + { + return result; + } + + // + StringToLower(value); + result = value == "true"; + + // + return result; +} + +// +// Split an String Representation of an Array ... +int SplitContent( + string &result[], // Hold Result ... + string content, // Source ... + string separator = ",", // Separator ... + bool forceCleanResult = true // Clean Result ... +) +{ + // + int mResult = 0; + + // + if (forceCleanResult) + { + Clean(result); + } + + // + int before = ArraySize(result); + + // + if (separator == NULL || StringLen(separator) == 0) + { + separator = ","; + } + + // + if (StringLen(content) == 0) + { + return mResult; + } + + // + StringSplit( + content, + StringGetCharacter( + separator, + 0), + result); + + // + int after = ArraySize(result); + + // + mResult = after - before; + + // + return mResult; +} + +// +// Extract Data from String ... +string ExtractString( + const string source, // Source String used for Extracting + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + string result = ""; + + // + // Validate String ... + if ( + StringLen(source) == 0 || + StringLen(endString) == 0 || + StringLen(startString) == 0) + { + return result; + } + + // + // Find Start String Position ... + int sPos = StringFind( + source, + startString); + if (sPos < 0) + { + return result; + } + + // + // Find End String Position after Start String ... + int searchEndFromPos = sPos + StringLen(startString); + int ePos = StringFind( + source, + endString, + searchEndFromPos); + if (ePos < 0) + { + return result; + } + + // + // Extract Data from Source ... + int dLength = ePos - searchEndFromPos; + result = StringSubstr( + source, + searchEndFromPos, + dLength); + + // + return result; +} + +// +// Extract an Array of Contents ... +int ExtractStrings( + string &result[], // Hold Result + const string source, // Source String used for Extracting + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + int mResult = 0; + + // + Clean(result); + + // + // Validate Args ... + int sourceLength = StringLen(source); + int startLength = StringLen(startString); + int endLength = StringLen(endString); + + // + int minRequiredLength = startLength + endLength; + + // + if ( + endLength <= 0 || + startLength <= 0 || + sourceLength <= 0 || + sourceLength < minRequiredLength) + { + return mResult; + } + + // + // Make a Copy of Source for Manipulating ... + string workStr = source; + + // + // Define a Loop ... + while (StringLen(workStr) > minRequiredLength) + { + // + // Find Item ... + string item = ExtractString( + workStr, + startString, + endString); + + // + // Breakout when couldn't find anymore item ... + int itemLength = StringLen(item); + if (itemLength <= 0) + { + break; + } + + // + // Prepare Item Source String for Replacing in Work String ... + string itemSource = startString + item + endString; + + // + // Add Item to Result Array ... + Add( + item, + result); + + // + // Replace Item Soure in Work String ... + StringReplace( + workStr, + itemSource, + ""); + } + + // + // Calculate Size of Array ... + mResult = ArraySize(result); + + // + return mResult; +} + +// +string ExtractSurrounded( + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + return ExtractString( + surrounded, + mToken + startString, + endString + // + ); +} + +// +int ParseIntSurrounded( + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + int result = NULL; + + // + string strContent = ExtractSurrounded( + surrounded, + mToken, + startString, + endString + // + ); + if (!IsValid(strContent)) + { + return result; + } + + // + result = (int)strContent; + + // + return result; +} + +long ParseLongSurrounded( + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + long result = NULL; + + // + string strContent = ExtractSurrounded( + surrounded, + mToken, + startString, + endString + // + ); + if (!IsValid(strContent)) + { + return result; + } + + // + result = (long)strContent; + + // + return result; +} + +string ParseStringSurrounded( + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + string result = NULL; + + // + string strContent = ExtractSurrounded( + surrounded, + mToken, + startString, + endString + // + ); + if (!IsValid(strContent)) + { + return result; + } + + // + result = (string)strContent; + + // + return result; +} + +double ParseDoubleSurrounded( + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + double result = NULL; + + // + string strContent = ExtractSurrounded( + surrounded, + mToken, + startString, + endString + // + ); + if (!IsValid(strContent)) + { + return result; + } + + // + result = (double)strContent; + + // + return result; +} + +datetime ParseTimeSurrounded( + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + const string startString = "(", // Expression Start String must be Unique + const string endString = ")" // Where to End Extraction, usually a Sign +) +{ + // + datetime result = NULL; + + // + string strContent = ExtractSurrounded( + surrounded, + mToken, + startString, + endString + // + ); + if (!IsValid(strContent)) + { + return result; + } + + // + result = (datetime)strContent; + + // + return result; +} + +// +int ParseIntArraySurrounded( + int &result[], // Holds Result + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + string separator = ",", // Separator ... + const string startString = "(", // Expression Start String must be Unique + const string endString = ")", // Where to End Extraction, usually a Sign + bool forceClean = true // Clean Result ... +) +{ + // + int count = 0; + + // + if (forceClean) + { + Clean(result); + } + + // + int before = ArraySize(result); + + // + string contentStr = ParseStringSurrounded(surrounded, mToken); + if (!IsValid(contentStr)) + { + return count; + } + + // + string tmps[]; + int tmpsCount = SplitContent( + tmps, + contentStr + // + ); + if (tmpsCount <= 0) + { + return count; + } + + // + for (int i = 0; i < tmpsCount; i++) + { + // + string iTMP = tmps[i]; + if (!IsValid(iTMP)) + { + continue; + } + + // + int iValue = (int)iTMP; + + // + Add( + iValue, + result + // + ); + } + + // + int after = ArraySize(result); + + // + count = after - before; + + // + return count; +} + +int ParseLongArraySurrounded( + long &result[], // Holds Result + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + string separator = ",", // Separator ... + const string startString = "(", // Expression Start String must be Unique + const string endString = ")", // Where to End Extraction, usually a Sign + bool forceClean = true // Clean Result ... +) +{ + // + int count = 0; + + // + if (forceClean) + { + Clean(result); + } + + // + int before = ArraySize(result); + + // + string contentStr = ParseStringSurrounded(surrounded, mToken); + if (!IsValid(contentStr)) + { + return count; + } + + // + string tmps[]; + int tmpsCount = SplitContent( + tmps, + contentStr + // + ); + if (tmpsCount <= 0) + { + return count; + } + + // + for (int i = 0; i < tmpsCount; i++) + { + // + string iTMP = tmps[i]; + if (!IsValid(iTMP)) + { + continue; + } + + // + long iValue = (long)iTMP; + + // + Add( + iValue, + result + // + ); + } + + // + int after = ArraySize(result); + + // + count = after - before; + + // + return count; +} + +int ParseDoubleArraySurrounded( + double &result[], // Holds Result + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + string separator = ",", // Separator ... + const string startString = "(", // Expression Start String must be Unique + const string endString = ")", // Where to End Extraction, usually a Sign + bool forceClean = true // Clean Result ... +) +{ + // + int count = 0; + + // + if (forceClean) + { + Clean(result); + } + + // + int before = ArraySize(result); + + // + string contentStr = ParseStringSurrounded(surrounded, mToken); + if (!IsValid(contentStr)) + { + return count; + } + + // + string tmps[]; + int tmpsCount = SplitContent( + tmps, + contentStr + // + ); + if (tmpsCount <= 0) + { + return count; + } + + // + for (int i = 0; i < tmpsCount; i++) + { + // + string iTMP = tmps[i]; + if (!IsValid(iTMP)) + { + continue; + } + + // + double iValue = (double)iTMP; + + // + Add( + iValue, + result + // + ); + } + + // + int after = ArraySize(result); + + // + count = after - before; + + // + return count; +} + +int ParseTimeArraySurrounded( + datetime &result[], // Holds Result + const string surrounded, // Surrounded Content + const string mToken, // Specified Token + string separator = ",", // Separator ... + const string startString = "(", // Expression Start String must be Unique + const string endString = ")", // Where to End Extraction, usually a Sign + bool forceClean = true // Clean Result ... +) +{ + // + int count = 0; + + // + if (forceClean) + { + Clean(result); + } + + // + int before = ArraySize(result); + + // + string contentStr = ParseStringSurrounded(surrounded, mToken); + if (!IsValid(contentStr)) + { + return count; + } + + // + string tmps[]; + int tmpsCount = SplitContent( + tmps, + contentStr + // + ); + if (tmpsCount <= 0) + { + return count; + } + + // + for (int i = 0; i < tmpsCount; i++) + { + // + string iTMP = tmps[i]; + if (!IsValid(iTMP)) + { + continue; + } + + // + datetime iValue = (datetime)iTMP; + + // + Add( + iValue, + result + // + ); + } + + // + int after = ArraySize(result); + + // + count = after - before; + + // + return count; +} + +// +// Surround an String by Specific Token ... +template +string Surround( + string mToken, // an String which used to Tokenize + T &value, // a Value for Tokenize it + string startString = "(", // Token Start Content + string endString = ")" // Token End Content +) +{ + // + string result = NULL; + + // + string strValue = ToString(value); + if (!IsValid(strValue)) + { + return result; + } + + // + result = + // + (IsValid(mToken) + ? mToken + : "") + + // + startString + + strValue + + endString + // + ; + + // + return result; +} + +// +template +string SurroundArray( + string mToken, + T &value[], + string startString = "(", // Token Start Content + string endString = ")" // Token End Content +) +{ + // + string result = NULL; + + // + string valueStr = ToString(value); + if (!IsValid(valueStr)) + { + return result; + } + + // + result = Surround( + mToken, + valueStr, + startString, + endString + // + ); + + // + return result; +} + +// +// END String ... +// + +// +// START Cycles ... +// + +/** + * Converts String To Period ... + * + * @param value: string ... + * + * @return ( ENUM_TIMEFRAMES ) + */ +ENUM_TIMEFRAMES ToPeriod(string value) +{ + // + if (StringLen(value) == 0) + { + return _Period; + } + + // + StringTrimLeft(value); + StringTrimRight(value); + + // + ENUM_TIMEFRAMES result = _Period; + + // + if (value == "M1") + { + result = PERIOD_M1; + } + else if (value == "M2") + { + result = PERIOD_M2; + } + else if (value == "M3") + { + result = PERIOD_M3; + } + else if (value == "M4") + { + result = PERIOD_M4; + } + else if (value == "M5") + { + result = PERIOD_M5; + } + else if (value == "M6") + { + result = PERIOD_M6; + } + else if (value == "M10") + { + result = PERIOD_M10; + } + else if (value == "M12") + { + result = PERIOD_M12; + } + else if (value == "M15") + { + result = PERIOD_M15; + } + else if (value == "M20") + { + result = PERIOD_M20; + } + else if (value == "M30") + { + result = PERIOD_M30; + } + else if (value == "H1") + { + result = PERIOD_H1; + } + else if (value == "H2") + { + result = PERIOD_H2; + } + else if (value == "H3") + { + result = PERIOD_H3; + } + else if (value == "H4") + { + result = PERIOD_H4; + } + else if (value == "H6") + { + result = PERIOD_H6; + } + else if (value == "H8") + { + result = PERIOD_H8; + } + else if (value == "H12") + { + result = PERIOD_H12; + } + else if (value == "D1") + { + result = PERIOD_D1; + } + else if (value == "W1") + { + result = PERIOD_W1; + } + else if (value == "MN1") + { + result = PERIOD_MN1; + } + + // + return result; +} + +/** + * Converts To String ... + * + * @param value: ENUM_TIMEFRAMES member ... + * + * @return ( string ) + */ +string ToString(ENUM_TIMEFRAMES value) +{ + // + string result = ""; + + // + string mPStr = EnumToString(value); + + string mPStrParts[]; + int partsCount = StringSplit( + mPStr, + StringGetCharacter("_", 0), + mPStrParts); + if (partsCount <= 0) + { + return result; + } + + // + result = mPStrParts[1]; + + // + return result; +} + +// +// Retrieve All Available Period as an Array ...s +int GetAllAvailablePeriods( + ENUM_TIMEFRAMES &result[] // Holds Result ... +) +{ + // + Clean(result); + + // + Add( + PERIOD_M1, + result + // + ); + + // + Add( + PERIOD_M2, + result + // + ); + + // + Add( + PERIOD_M3, + result + // + ); + + // + Add( + PERIOD_M4, + result + // + ); + + // + Add( + PERIOD_M5, + result + // + ); + + // + Add( + PERIOD_M6, + result + // + ); + + // + Add( + PERIOD_M10, + result + // + ); + + // + Add( + PERIOD_M12, + result + // + ); + + // + Add( + PERIOD_M15, + result + // + ); + + // + Add( + PERIOD_M20, + result + // + ); + + // + Add( + PERIOD_M30, + result + // + ); + + // + Add( + PERIOD_H1, + result + // + ); + + // + Add( + PERIOD_H2, + result + // + ); + + // + Add( + PERIOD_H3, + result + // + ); + + // + Add( + PERIOD_H4, + result + // + ); + + // + Add( + PERIOD_H6, + result + // + ); + + // + Add( + PERIOD_H8, + result + // + ); + + // + Add( + PERIOD_H12, + result + // + ); + + // + Add( + PERIOD_D1, + result + // + ); + + // + Add( + PERIOD_W1, + result + // + ); + + // + Add( + PERIOD_MN1, + result + // + ); + + // + int mResult = ArraySize(result); + + // + return mResult; +} + +// +// Get Specific Time Frame Start Candle Time ... +datetime GetPeriodStartTime( + string mSymbol = NULL, // Specified Symbol ... + ENUM_TIMEFRAMES mPeriod = NULL, // Specified Period ... + datetime mTime = NULL // Specified Bar Time of Host Period ... +) +{ + // + // Normalize Arg ... + mTime = NormalizeTime(mTime); + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + int barIndex = iBarShift( + mSymbol, + mPeriod, + mTime, + false // + ); + + // + datetime result = GetBarTime( + mSymbol, + mPeriod, + barIndex // + ); + + // + return result; +} + +// +// Retrieve Nearest Period base on Given Period ... +ENUM_TIMEFRAMES GetNearestPeriod(ENUM_TIMEFRAMES mPeriod) +{ + // + ENUM_TIMEFRAMES result = _Period; + + // + mPeriod = NormalizePeriod(mPeriod); + + // + switch (mPeriod) + { + // + case PERIOD_M1: + case PERIOD_M2: + case PERIOD_M3: + result = PERIOD_M5; + break; + + // + case PERIOD_M4: + case PERIOD_M5: + case PERIOD_M6: + result = PERIOD_M10; + break; + + // + case PERIOD_M10: + case PERIOD_M12: + case PERIOD_M15: + result = PERIOD_M20; + break; + + // + case PERIOD_M20: + case PERIOD_M30: + result = PERIOD_H1; + break; + + // + case PERIOD_H1: + case PERIOD_H2: + result = PERIOD_H3; + break; + + // + case PERIOD_H3: + result = PERIOD_H4; + break; + + // + case PERIOD_H4: + result = PERIOD_H6; + break; + + // + case PERIOD_H6: + result = PERIOD_H8; + break; + + // + case PERIOD_H8: + result = PERIOD_H12; + break; + + // + default: + result = mPeriod; + break; + } + + // + return result; +} + +// +// Retrieve Mediest Period base on Given Period ... +ENUM_TIMEFRAMES GetMediestPeriod(ENUM_TIMEFRAMES mPeriod) +{ + // + ENUM_TIMEFRAMES result = _Period; + + // + mPeriod = NormalizePeriod(mPeriod); + + // + switch (mPeriod) + { + // + case PERIOD_M1: + case PERIOD_M2: + case PERIOD_M3: + result = PERIOD_M10; + break; + + // + case PERIOD_M4: + case PERIOD_M5: + case PERIOD_M6: + result = PERIOD_M15; + break; + + // + case PERIOD_M10: + case PERIOD_M12: + case PERIOD_M15: + result = PERIOD_M30; + break; + + // + case PERIOD_M20: + case PERIOD_M30: + result = PERIOD_H2; + break; + + // + case PERIOD_H1: + case PERIOD_H2: + result = PERIOD_H4; + break; + + // + case PERIOD_H3: + result = PERIOD_H6; + break; + + // + case PERIOD_H4: + result = PERIOD_H8; + break; + + // + case PERIOD_H6: + result = PERIOD_H12; + break; + + // + case PERIOD_H8: + result = PERIOD_D1; + break; + + // + default: + result = mPeriod; + break; + } + + // + return result; +} + +// +// Retrieve Longest Period base on Given Period ... +ENUM_TIMEFRAMES GetLongestPeriod(ENUM_TIMEFRAMES mPeriod) +{ + // + ENUM_TIMEFRAMES result = _Period; + + // + mPeriod = NormalizePeriod(mPeriod); + + // + switch (mPeriod) + { + // + case PERIOD_M1: + case PERIOD_M2: + case PERIOD_M3: + result = PERIOD_M30; + break; + + // + case PERIOD_M4: + case PERIOD_M5: + case PERIOD_M6: + result = PERIOD_H1; + break; + + // + case PERIOD_M10: + case PERIOD_M12: + case PERIOD_M15: + result = PERIOD_H2; + break; + + // + case PERIOD_M20: + case PERIOD_M30: + result = PERIOD_H4; + break; + + // + case PERIOD_H1: + case PERIOD_H2: + result = PERIOD_H6; + break; + + // + case PERIOD_H3: + result = PERIOD_H8; + break; + + // + case PERIOD_H4: + result = PERIOD_H12; + break; + + // + case PERIOD_H6: + result = PERIOD_D1; + break; + + // + case PERIOD_H8: + result = PERIOD_W1; + break; + + // + default: + result = mPeriod; + break; + } + + // + return result; +} + +// +// Retrieve Hindmost Period base on Given Period ... +ENUM_TIMEFRAMES GetHindMostPeriod(ENUM_TIMEFRAMES mPeriod) +{ + // + ENUM_TIMEFRAMES result = _Period; + + // + mPeriod = NormalizePeriod(mPeriod); + + // + switch (mPeriod) + { + // + case PERIOD_M1: + case PERIOD_M2: + case PERIOD_M3: + result = PERIOD_H1; + break; + + // + case PERIOD_M4: + case PERIOD_M5: + case PERIOD_M6: + result = PERIOD_H2; + break; + + // + case PERIOD_M10: + case PERIOD_M12: + case PERIOD_M15: + result = PERIOD_H4; + break; + + // + case PERIOD_M20: + case PERIOD_M30: + result = PERIOD_H6; + break; + + // + case PERIOD_H1: + case PERIOD_H2: + result = PERIOD_H8; + break; + + // + case PERIOD_H3: + result = PERIOD_H12; + break; + + // + case PERIOD_H4: + result = PERIOD_D1; + break; + + // + case PERIOD_H6: + result = PERIOD_W1; + break; + + // + case PERIOD_H8: + result = PERIOD_MN1; + break; + + // + default: + result = mPeriod; + break; + } + + // + return result; +} + +// +// Retrieve Specified Cycles Period related to Host Period ... +ENUM_TIMEFRAMES GetCyclePeriod( + ENUM_X_MARKET_CYCLES mCycle = NULL, // Specified Cycle + ENUM_TIMEFRAMES mPeriod = NULL // Host Period +) +{ + // + ENUM_TIMEFRAMES result = NULL; + + // + mPeriod = NormalizePeriod(mPeriod); + mCycle = NormalizeCycle(mCycle); + + // + switch (mCycle) + { + // + // Short ... + case X_MARKET_CYCLE_SHORT: + result = GetNearestPeriod(mPeriod); + break; + + // + // Medium ... + case X_MARKET_CYCLE_MEDIUM: + result = GetMediestPeriod(mPeriod); + break; + + // + // Long ... + case X_MARKET_CYCLE_LONG: + result = GetLongestPeriod(mPeriod); + break; + + // + // Hind ... + case X_MARKET_CYCLE_HIND: + result = GetHindMostPeriod(mPeriod); + break; + } + + // + return result; +} + +// +// Calculate a Cycle Length based on Host Period ... +int GetCycleLengthOn( + ENUM_TIMEFRAMES _hostPeriod, + ENUM_X_MARKET_CYCLES _cycle, + ENUM_X_PERIOD_METHOD _method, + ENUM_TIMEFRAMES _period // +) +{ + // + int result = 0; + + // + // Validate ... + bool isValid = + // + IsValid(_hostPeriod) && + IsValid(_method, _Period) + // + ; + if (!isValid) + { + return result; + } + + // + // Calculate Period ... + isValid = + _method != X_PERIOD_NONE && + _cycle != X_MARKET_CYCLE_UNKNOWN; + if (!isValid) + { + return result; + } + + // + if (_method == X_PERIOD_AUTO) + { + // + _period = GetCyclePeriod( + _cycle, + _hostPeriod // + ); + } + isValid = IsValid(_period); + if (!isValid) + { + return result; + } + + // + int _hostPeriodSeconds = PeriodSeconds(_hostPeriod); + int _periodSeconds = PeriodSeconds(_period); + + // + isValid = _periodSeconds >= _hostPeriodSeconds; + if (!isValid) + { + return result; + } + + // + result = _periodSeconds / _hostPeriodSeconds; + + // + return result; +} + +// +// END Cycles ... +// + +// +// START Collections ... +// + +// +// Add Specified Item to Array ... +template +int Add( + T item, // item want to add + T &buffer[] // Destination buffer +) +{ + // + int result = 0; + + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; + + // + result = ArraySize(buffer); + + // + return result; +} +template +int AddSpecific( + T item, // item want to add + T &buffer[] // Destination buffer +) +{ + // + return Add( + item, + buffer // + ); +} +template +int AddRef( + T &item, // item want to add + T &buffer[] // Destination buffer +) +{ + // + int result = 0; + + // + ArrayResize( + buffer, + ArraySize(buffer) + 1); + + // + buffer[ArraySize(buffer) - 1] = item; + + // + result = ArraySize(buffer); + + // + return result; +} + +// +// Check Specified Array Has Childs or not ... +template +bool HasChild(T &buffer[]) +{ + return IsValidSize(ArraySize(buffer)); +} +template +bool SpecificHasChild(T &buffer[]) +{ + return HasChild(buffer); +} + +// +// Remove Specified Item from an Array ... +template +bool Remove( + T item, + T &buffer[]) +{ + // + bool result = false; + + // + int itemIndex = FindIndex( + item, + buffer); + if (itemIndex < 0) + { + return result; + } + + // + result = ArrayRemove( + buffer, + itemIndex, + 1); + + // + return result; +} + +// +// Clean Specified Array ... +template +void Clean(T &buffer[]) +{ + // + ArrayResize(buffer, 0); + ArrayFree(buffer); + ZeroMemory(buffer); +} +template +void SpecificClean(T &buffer[]) +{ + Clean(buffer); +} + +// +// Copy Whole Content of Source to Dest array ... +template +void Copy( + T &source[], // Source Buffer ... + T &dest[], // Dest Buffer ... + bool cleanDest = true // Force Clen Dest Buffer ... +) +{ + // + if (cleanDest) + { + Clean(dest); + } + + // + int sourceCount = ArraySize(source); + if (sourceCount <= 0) + { + return; + } + + // + for (int i = 0; i < sourceCount; i++) + { + // + T iSource = source[i]; + + // + AddRef( + iSource, + dest); + } +} + +// +// Copy Items from a Buffer ... +template +int Copy( + int start, // Start + int count, // Number of Items for read + T &source[], // Source Buffer + T &dest[], // Dest Buffer + bool forceClean = true, // Force To Clean buffer + bool forceStart = true // Force To Clean buffer +) +{ + // + int result = 0; + + // + if (forceClean) + { + Clean(dest); + } + + // + if (start < 0 && forceStart) + { + start = 0; + } + + // + if (start >= ArraySize(source)) + { + start = ArraySize(source) - 1; + } + + // + if (count == 0) + { + count = ArraySize(source) - 1 - start; + } + + // + if (start + count > ArraySize(source)) + { + return result; + } + + // + int beforeSize = ArraySize(dest); + + // + bool asSeriesDest = ArrayGetAsSeries(dest); + bool asSeriesSource = ArrayGetAsSeries(source); + + // + ArraySetAsSeries(dest, true); + ArraySetAsSeries(source, true); + + // + ArrayCopy( + dest, + source, + 0, + start, + count + // + ); + + // + int afterSize = ArraySize(dest); + + // + result = afterSize - beforeSize; + + // + ArraySetAsSeries(dest, asSeriesDest); + ArraySetAsSeries(source, asSeriesSource); + + // + return result; +} + +// +// Copy Items from a Buffer ... +template +int CopyRef( + int start, // Start + int count, // Number of Items for read + T &source[], // Source Buffer + T &dest[], // Dest Buffer + bool forceClean = true // Force To Clean buffer +) +{ + // + int result = 0; + + // + if (forceClean) + { + Clean(dest); + } + + // + if (start < 0) + { + start = 0; + } + + // + if (start >= ArraySize(source)) + { + start = ArraySize(source) - 1; + } + + // + int beforeSize = ArraySize(dest); + + // + bool asSeriesDest = ArrayGetAsSeries(dest); + bool asSeriesSource = ArrayGetAsSeries(source); + + // + ArraySetAsSeries(dest, true); + ArraySetAsSeries(source, true); + + // + for (int i = start; i < start + count; i++) + { + // + AddRef( + source[i], + dest + // + ); + } + + // + int afterSize = ArraySize(dest); + + // + result = afterSize - beforeSize; + + // + ArraySetAsSeries(dest, asSeriesDest); + ArraySetAsSeries(source, asSeriesSource); + + // + return result; +} + +// +// Retrive Last Item of Specified Buffer ... +template +bool GetLastItem( + T &item, // Holds Result + T &buffer[] // Specified Buffer +) +{ + // + bool result = false; + + // + int bufferSize = ArraySize(buffer); + if (bufferSize <= 0) + { + return result; + } + + // + item = buffer[bufferSize - 1]; + + // + result = true; + return result; +} + +// +// Remove Last Item of Specified Buffer ... +template +bool RemoveLastItem( + T &buffer[] // Specified Buffer +) +{ + // + bool result = false; + + // + int count = ArraySize(buffer); + result = IsValidSize(count); + if (!result) + { + return result; + } + + // + ArrayRemove( + buffer, + count - 1, + 1 // + ); + + // + return result; +} + +template +void CleanupArray( + T &buffer[], // Buffer to Cleanup ... + int maxAllowed = 0 // Max Allowed Number of items ... +) +{ + // + if (maxAllowed <= 0) + { + return; + } + + // + int count = ArraySize(buffer); + if (!IsValidSize(count) || + count <= maxAllowed) + { + return; + } + + // + int mustRemove = count - maxAllowed; + if (!IsValidSize(mustRemove)) + { + return; + } + + // + ArrayRemove( + buffer, + 0, + mustRemove // + ); +} + +template +void CleanupArray( + int &removedIndexes[], + T &buffer[] // Buffer to Cleanup ... +) +{ + // + bool isValid = HasChild(buffer) && + HasChild(removedIndexes); + if (!isValid) + { + return; + } + + // + for (int i = 0; i < ArraySize(removedIndexes); i++) + { + // + int idx = removedIndexes[i]; + if (IsValidIndex(idx) && ArraySize(buffer) > idx) + { + // + ArrayRemove( + buffer, + idx, + 1 // + ); + } + } + + // + Clean(removedIndexes); +} + +// +// Search Array For Specific Item ... +template +int FindIndex( + T item, // What is Search ... + T &buffer[] // Search in ... +) +{ + // + int result = -1; + + // + int count = ArraySize(buffer); + if (count <= 0) + { + return result; + } + + // + for (int i = 0; i < count; i++) + { + // + T iT = buffer[i]; + + // + if (iT == item) + { + // + result = i; + break; + } + } + + // + return result; +} +// +// Find Specific Item Index inside a Collection ... +template +int FindIndex( + T &item, // Item to Find + const T &items[] // Items for Search +) +{ + // + int result = -1; + + // + // Check Item Validation ... + if (!item.IsValid()) + { + return result; + } + + // + int itemsCount = ArraySize(items); + if (itemsCount <= 0) + { + return result; + } + + // + for (int i = 0; i < itemsCount; i++) + { + // + T iItem = items[i]; + + // + // Validate Item ... + if (!iItem.IsValid()) + { + continue; + } + + // + bool isSame = item.IsSameAs(iItem); + if (isSame && result <= -1) + { + // + result = i; + break; + } + } + + // + return result; +} + +// +// Check an Array Contains Specified Value ... +template +bool Contains( + T item, // What is Search ... + T &buffer[] // Search in ... +) +{ + // + bool result = false; + + // + int idx = FindIndex( + item, + buffer); + result = idx > -1; + + // + return result; +} + +// +// Calculate a Buffer's Sum ... +template +double GetSum( + T &buffer[], // the Buffer which required to search + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + // + double result = 0; + + // + T tmp[]; + int tmpCount = Copy( + start, + count, + buffer, + tmp + // + ); + if (tmpCount <= 0) + { + return result; + } + + // + // Calculate Summary ... + for (int i = 0; i < tmpCount; i++) + { + result += buffer[i]; + } + + // + return result; +} + +// +// Calculate a Buffer's Average ... +template +double GetAverage( + T &buffer[], // the Buffer which required to search + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + // + double result = 0; + + // + T tmp[]; + int tmpCount = Copy( + start, + count, + buffer, + tmp + // + ); + if (tmpCount <= 0) + { + return result; + } + + // + // Calculate Summary ... + for (int i = 0; i < tmpCount; i++) + { + result += buffer[i]; + } + + // + // Calculate Average ... + result = result / tmpCount; + + // + return result; +} + +// +// Get Max of Specific Loopback of a Buffer ... +template +T GetMax( + T &buffer[], // the Buffer which required to search + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + // + T result = 0; + + // + if (count <= 0) + { + count = ArraySize(buffer); + } + + // + T tmp[]; + int tmpCount = Copy( + start, + count, + buffer, + tmp + // + ); + if (tmpCount <= 0) + { + return result; + } + + // + // Loop Through LoopBack ... + for (int i = 0; i < tmpCount; i++) + { + // + T iValue = tmp[i]; + + // + result = + // + result == 0 || result < iValue + // + ? iValue + // + : result + // + ; + } + + // + return result; +} +template +T GetMax( + T &buffer[], // the Buffer which required to search + int &index, // Item Index ... + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + // + T result = 0; + index = -1; + + // + if (count <= 0) + { + count = ArraySize(buffer); + } + + // + T tmp[]; + int tmpCount = Copy( + start, + count, + buffer, + tmp + // + ); + if (tmpCount <= 0) + { + return result; + } + + // + // Loop Through LoopBack ... + for (int i = 0; i < tmpCount; i++) + { + // + T iValue = tmp[i]; + + // + bool isNew = result == 0; + bool canSet = isNew || + (!isNew && + result < iValue); + if (canSet) + { + // + index = i; + result = iValue; + } + } + + // + return result; +} +template +T GetSpecifiedMax( + T &buffer[], // the Buffer which required to search + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + return GetMax( + buffer, + start, + count // + ); +} +template +T GetSpecifiedMax( + T &buffer[], // the Buffer which required to search + int &index, // Item Index ... + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + return GetMax( + buffer, + index, + start, + count // + ); +} + +// +// Get Min of Specific Loopback of a Buffer ... +template +T GetMin( + T &buffer[], // the Buffer which required to search + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + // + T result = 0; + + // + if (count <= 0) + { + count = ArraySize(buffer); + } + + // + T tmp[]; + int tmpCount = Copy( + start, + count, + buffer, + tmp + // + ); + if (tmpCount <= 0) + { + return result; + } + + // + // Loop Through LoopBack ... + for (int i = 0; i < tmpCount; i++) + { + // + T iValue = tmp[i]; + + // + result = + // + result == 0 || result > iValue + // + ? iValue + // + : result + // + ; + } + + // + return result; +} +template +T GetMin( + T &buffer[], // the Buffer which required to search + int &index, // Item Index ... + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + // + T result = 0; + index = -1; + + // + if (count <= 0) + { + count = ArraySize(buffer); + } + + // + T tmp[]; + int tmpCount = Copy( + start, + count, + buffer, + tmp + // + ); + if (tmpCount <= 0) + { + return result; + } + + // + // Loop Through LoopBack ... + for (int i = 0; i < tmpCount; i++) + { + // + T iValue = tmp[i]; + + // + bool isNew = result == 0; + bool canSet = isNew || + (!isNew && + result > iValue); + if (canSet) + { + // + index = i; + result = iValue; + } + } + + // + return result; +} +template +T GetSpecifiedMin( + T &buffer[], // the Buffer which required to search + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + return GetMin( + buffer, + start, + count // + ); +} +template +T GetSpecifiedMin( + T &buffer[], // the Buffer which required to search + int &index, // Item Index ... + int start = 0, // Start Index + int count = 0 // Count for Search +) +{ + return GetMin( + buffer, + index, + start, + count // + ); +} + +// +// Find a Value less than Specified ... +template +T FindLesserThan( + T value, // Specified Value ... + const T &source[], // Source ... + bool isDescend = false // Find Biggest Lesser Value ... +) +{ + // + T result = -1; + + // + int itemsCount = ArraySize(source); + if (itemsCount <= 0) + { + return result; + } + + // + // Make a Copy of source ... + T tmp[]; + + // + ArrayResize( + tmp, + ArraySize(source) // + ); + + // + ArrayCopy( + tmp, + source // + ); + + // + // Sort Temp Buffer ... + ArraySort(tmp); + if (isDescend) + { + ArrayReverse(tmp); + } + + // + int tmpCount = ArraySize(tmp); + for (int i = 0; i < tmpCount; i++) + { + // + T iValue = tmp[i]; + + // + if (iValue < value) + { + // + result = iValue; + break; + } + } + + // + return result; +} +template +T FindLesserThan( + T value, // Specified Value ... + int &index, // Item Index ... + const T &source[], // Source ... + bool isDescend = false // Find Biggest Lesser Value ... +) +{ + // + T result = -1; + index = -1; + + // + int itemsCount = ArraySize(source); + if (itemsCount <= 0) + { + return result; + } + + // + // Make a Copy of source ... + T tmp[]; + + // + ArrayResize( + tmp, + ArraySize(source) // + ); + + // + ArrayCopy( + tmp, + source // + ); + + // + // Sort Temp Buffer ... + ArraySort(tmp); + if (isDescend) + { + ArrayReverse(tmp); + } + + // + int tmpCount = ArraySize(tmp); + for (int i = 0; i < tmpCount; i++) + { + // + T iValue = tmp[i]; + + // + if (iValue < value) + { + // + index = i; + result = iValue; + break; + } + } + + // + return result; +} + +// +// Find a Value less than Specified ... +template +T FindBiggerThan( + T value, // Specified Value ... + const T &source[], // Source ... + bool isDescend = false // Find Smallest Bigger Value ... +) +{ + // + T result = -1; + + // + int itemsCount = ArraySize(source); + if (itemsCount <= 0) + { + return result; + } + + // + // Make a Copy of source ... + T tmp[]; + + // + ArrayResize( + tmp, + ArraySize(source) // + ); + + // + ArrayCopy( + tmp, + source // + ); + + // + // Sort Temp Buffer ... + ArraySort(tmp); + if (!isDescend) + { + ArrayReverse(tmp); + } + + // + int tmpCount = ArraySize(tmp); + for (int i = 0; i < tmpCount; i++) + { + // + T iValue = tmp[i]; + + // + if (iValue > value) + { + // + result = iValue; + break; + } + } + + // + return result; +} +template +T FindBiggerThan( + T value, // Specified Value ... + int &index, // Item Index ... + const T &source[], // Source ... + bool isDescend = false // Find Smallest Bigger Value ... +) +{ + // + T result = -1; + index = -1; + + // + int itemsCount = ArraySize(source); + if (itemsCount <= 0) + { + return result; + } + + // + // Make a Copy of source ... + T tmp[]; + + // + ArrayResize( + tmp, + ArraySize(source) // + ); + + // + ArrayCopy( + tmp, + source // + ); + + // + // Sort Temp Buffer ... + ArraySort(tmp); + if (!isDescend) + { + ArrayReverse(tmp); + } + + // + int tmpCount = ArraySize(tmp); + for (int i = 0; i < tmpCount; i++) + { + // + T iValue = tmp[i]; + + // + if (iValue > value) + { + // + index = i; + result = iValue; + break; + } + } + + // + return result; +} + +// +// Find Same Values in Array ... +template +void FindSames( + T &result[], // Holds Result ... + T &source[], // Source ... + int verifications = 3 // Number of Consequence Repeat ... +) +{ + // + Clean(result); + + // + // TenkanSen Flats ... + int sourceCount = ArraySize(source); + if (sourceCount > verifications) + { + // + T mLast = 0; + int mVerified = 0; + for (int i = 0; i < sourceCount; i++) + { + // + T iVal = source[i]; + if (mLast == 0) + { + mLast = iVal; + } + else if (mLast == iVal) + { + mVerified++; + } + else + { + mLast = iVal; + mVerified = 0; + } + + // + if (iVal == mLast && mVerified >= verifications) + { + // + Add( + iVal, + result); + + // + mLast = 0; + mVerified = 0; + } + } + } +} + +// +// Add an Item to a Buffer if not Exists ... +void AddIfNotExists( + double value, + double &values[], + double smoothingPoint = 3 // +) +{ + // + double smoothingValue = smoothingPoint * GetPoints(_Symbol); + + // + int valuesCount = ArraySize(values); + if (valuesCount <= 0) + { + // + Add(value, + values); + } + else + { + // + bool isExists = false; + for (int i = 0; i < valuesCount; i++) + { + // + double iVal = values[i]; + + // + double diff = MathAbs(iVal - value); + + // + if (iVal == value || diff < smoothingValue) + { + // + isExists = true; + break; + } + } + + // + if (!isExists) + { + // + Add(value, + values); + } + } +} + +// +// Add a Buffers Child to another Buffer +// if it's not Contains them ... +void AddsIfNotExists( + double &source[], + double &dest[], + double smoothingPoint = 3) +{ + // + double smoothingValue = smoothingPoint * GetPoints(_Symbol); + + // + int sourceCount = ArraySize(source); + if (sourceCount <= 0) + { + return; + } + + // + for (int i = 0; i < sourceCount; i++) + { + // + double iSource = source[i]; + + // + AddIfNotExists( + iSource, + dest, + smoothingPoint); + } +} + +// +// END Collections ... +// + +// +// START Buffers ... +// + +// +template +bool IsSame( + T &buffer[], // Search Buffer + int count = 5, // Number of Searchs + int start = 0 // Start ... +) +{ + // + bool result = false; + + // + int bufferSize = ArraySize(buffer); + result = bufferSize > 0; + if (!result) + { + return result; + } + + // + // Validate Count ... + result = start + count < bufferSize; + if (!result) + { + return result; + } + + // + T iTem = buffer[start]; + for (int i = start; i < start + count; i++) + { + // + if (iTem != buffer[i]) + { + result = false; + break; + } + + // + if (!result) + { + result = true; + } + } + + // + return result; +} + +// +// Check first Cross Over second at index ... +bool IsCrossedOver( + const double &first[], // the buffer which check crossing over second buffer + const double &second[], // first buffer checks based on this buffer + const int index = 0 // check crosses in specific index +) +{ + // + bool result = false; + + // + // Validate Args ... + if (ArraySize(first) < index + 1 || ArraySize(second) < index + 1) + { + return result; + } + + // + result = first[index] > second[index] && + !(first[index + 1] > second[index + 1]); + + // + return result; +} + +// +// Check first is Over second at index ... +bool IsOver( + const double &first[], // the buffer which check over second buffer + const double &second[], // first buffer checks based on this buffer + const int index = 0 // check crosses in specific index +) +{ + // + bool result = false; + + // + // Validate Args ... + if (ArraySize(first) < index + 1 || ArraySize(second) < index + 1) + { + return result; + } + + // + result = first[index] > second[index] && + first[index + 1] > second[index + 1]; + + // + return result; +} + +// +// Check first Cross Under second at index ... +bool IsCrossedUnder( + const double &first[], // the buffer which check crossing under second buffer + const double &second[], // first buffer checks based on this buffer + const int index = 0 // check crosses in specific index +) +{ + // + bool result = false; + + // + // Validate Args ... + if (ArraySize(first) < index + 1 || ArraySize(second) < index + 1) + { + return result; + } + + // + result = first[index] < second[index] && + !(first[index + 1] < second[index + 1]); + + // + return result; +} + +// +// Check first is Under second at index ... +bool IsUnder( + const double &first[], // the buffer which check under second buffer + const double &second[], // first buffer checks based on this buffer + const int index = 0 // check crosses in specific index +) +{ + // + bool result = false; + + // + // Validate Args ... + if (ArraySize(first) < index + 1 || ArraySize(second) < index + 1) + { + return result; + } + + // + result = first[index] < second[index] && + first[index + 1] < second[index + 1]; + + // + return result; +} + +// +// Check if a Value Increasing in Loopback ... +bool IsIncreasing( + const double &buffer[], // the Buffer which required to search + int from = -1, // Last Time Index + int to = -1 // Fisrs Tima Index +) +{ + // + bool result = false; + + // + if (from == -1) + { + from = ArraySize(buffer) - 1; + } + + // + if (to == -1) + { + to = 0; + } + + // + // Validate Args ... + if ( + from <= to || + ArraySize(buffer) < from + 1) + { + return result; + } + + // + // Loop through Items ... + double toValue = buffer[to]; + double fromValue = buffer[from]; + result = toValue >= fromValue; + for (int i = to + 1; i <= from - 1; i++) + { + // + double iValue = buffer[i]; + bool isPassed = toValue >= iValue; + + // + bool isIIncreasing = IsIncreasing( + buffer, + from, + i // + ); + + // + // Check Result ... + result = result && isPassed && isIIncreasing; + if (!result) + { + break; + } + } + + // + return result; +} + +// +// Check if a Value Decreasing in Loopback ... +bool IsDecreasing( + const double &buffer[], // the Buffer which required to search + int from = -1, // Last Time Index + int to = -1 // Fisrs Tima Index +) +{ + // + bool result = false; + + // + if (from == -1) + { + from = ArraySize(buffer) - 1; + } + + // + if (to == -1) + { + to = 0; + } + + // + // Validate Args ... + if ( + from <= to || + ArraySize(buffer) < from + 1) + { + return result; + } + + // + // Loop through Items ... + double toValue = buffer[to]; + double fromValue = buffer[from]; + result = toValue <= fromValue; + for (int i = to + 1; i <= from - 1; i++) + { + // + double iValue = buffer[i]; + bool isPassed = toValue <= iValue; + + // + bool isIDecreasing = IsDecreasing( + buffer, + from, + i // + ); + + // + // Check Result ... + result = result && isPassed && isIDecreasing; + if (!result) + { + break; + } + } + + // + return result; +} + +// +bool IsTrendingUp( + const double &buffer1[], // First Buffer + const double &buffer2[] // Seccend Buffer +) +{ + // + bool result = false; + + // + int buffer1Count = ArraySize(buffer1); + int buffer2Count = ArraySize(buffer2); + if (buffer1Count <= 0 || buffer2Count <= 0) + { + return result; + } + + // + int count = MathMin(buffer1Count, buffer2Count); + if (count <= 1) + { + return result; + } + + // + int upCounts = 0; + int downCounts = 0; + double value = MathAbs(buffer1[0] - buffer2[0]); + for (int i = 1; i < count; i++) + { + // + double iValue = MathAbs(buffer1[i] - buffer2[i]); + + // + if (value > iValue) + { + upCounts++; + } + + // + if (value < iValue) + { + downCounts++; + } + } + + // + result = upCounts > 1 && upCounts > downCounts; + + // + return result; +} + +// +bool IsTrendingDown( + const double &buffer1[], // First Buffer + const double &buffer2[] // Seccend Buffer +) +{ + // + bool result = false; + + // + int buffer1Count = ArraySize(buffer1); + int buffer2Count = ArraySize(buffer2); + if (buffer1Count <= 0 || buffer2Count <= 0) + { + return result; + } + + // + int count = MathMin(buffer1Count, buffer2Count); + if (count <= 1) + { + return result; + } + + // + int upCounts = 0; + int downCounts = 0; + double value = MathAbs(buffer1[0] - buffer2[0]); + for (int i = 1; i < count; i++) + { + // + double iValue = MathAbs(buffer1[i] - buffer2[i]); + + // + if (value > iValue) + { + upCounts++; + } + + // + if (value < iValue) + { + downCounts++; + } + } + + // + result = downCounts > 1 && downCounts > upCounts; + + // + return result; +} + +// +// Calculate Slope of Specified Buffer at Specified Index ... +double GetSlope( + const double &buffer[], // Buffer + int from, // In Past Index ... + int to // In Past Index ... +) +{ + // + double result = 0; + + // + if (from > ArraySize(buffer) || to > ArraySize(buffer)) + { + return result; + } + + // + double toValue = buffer[to]; + double fromValue = buffer[from]; + double deltaValue = toValue - fromValue; + double deltaTime = from - to; + + // + result = deltaValue / deltaTime; + + // + return result; +} + +// +// END Buffers ... +// + +// +// START Time ... +// + +// +// Converts Time to Seconds ... +ulong TimeToSeconds( + datetime time // Specify time to Convert ... +) +{ + // + ulong result = (ulong)time; + + // + return result; +} +ulong TimeToSeconds( + MqlDateTime &time // Specify time to Convert ... +) +{ + // + datetime dTime = StructToTime(time); + + // + ulong result = TimeToSeconds(dTime); + + // + return result; +} + +// +// Converts Seconds To Time ... +datetime SecondsToTime( + ulong seconds // Specify Seconds to Convert ... +) +{ + // + datetime result = (datetime)seconds; + + // + return result; +} +MqlDateTime SecondsToStruct( + ulong seconds // Specify Seconds to Convert ... +) +{ + // + datetime dTime = SecondsToTime(seconds); + + // + MqlDateTime result = {}; + TimeToStruct( + dTime, + result); + + // + return result; +} + +// +// Converts Time to MilliSeconds ... +ulong TimeToMilliSeconds( + datetime time // Specify time to Convert ... +) +{ + // + ulong result = TimeToSeconds(time) * 1000; + + // + return result; +} +ulong TimeToMilliSeconds( + MqlDateTime &time // Specify time to Convert ... +) +{ + // + datetime dTime = StructToTime(time); + + // + ulong result = TimeToMilliSeconds(dTime); + + // + return result; +} + +// +// Converts MillisSeconds to Time ... +datetime MilliSecondsToTiem( + ulong milliSeconds // Specify MilliSeconds to Convert ... +) +{ + // + ulong seconds = milliSeconds / 1000; + + // + datetime result = SecondsToTime(seconds); + + // + return result; +} +MqlDateTime MilliSecondsToStruct( + ulong milliSeconds // Specify MilliSeconds to Convert ... +) +{ + // + datetime dTime = MilliSecondsToTiem(milliSeconds); + + // + MqlDateTime result = {}; + TimeToStruct( + dTime, + result); + + // + return result; +} + +// +// Converts Hours to Seconds ... +int HoursToSeconds(int value) +{ + // + int result = 0; + + // + if (value < 0) + { + value = 0; + } + + // + if (value == 0) + { + return result; + } + + // + result = value * 60 * 60; + + // + return result; +} + +// +// Retrieve DateTime Structure ... +MqlDateTime GetCurrentTime() +{ + // + MqlDateTime result = {}; + + // + datetime cTime = TimeCurrent(); + TimeToStruct(cTime, result); + + // + return result; +} + +// +// Retrieve Current Time as Seconds ... +ulong GetCurrentTimeAsSeconds() +{ + // + datetime time = TimeCurrent(); + + // + ulong result = TimeToSeconds(time); + + // + return result; +} + +// +// Retrieve Current Time as MilliSeconds ... +ulong GetCurrentTimeAsMilliSeconds() +{ + // + datetime time = TimeCurrent(); + + // + ulong result = TimeToMilliSeconds(time); + + // + return result; +} + +// +int GetLocalOffset() +{ + // + MqlDateTime cTimeStruct; + datetime cTime = TimeCurrent(cTimeStruct); + + // + MqlDateTime cLTimeStruct; + datetime cLTime = TimeLocal(cLTimeStruct); + + // + cTimeStruct.sec = 0; + cTime = StructToTime(cTimeStruct); + + // + cLTimeStruct.sec = 0; + cLTime = StructToTime(cLTimeStruct); + + // + int result = ((int)cLTime - (int)cTime); + + // + return result; +} + +// +int GetUTCRequiredTimeOffset() +{ + // + int utcOffset = TimeGMTOffset(); + int localOffset = GetLocalOffset(); + + // + int result = utcOffset + localOffset; + + // + return result; +} + +// +datetime GetUTCTime( + datetime time = NULL, + bool applyTradeServerTime = false // +) +{ + // + datetime result = NULL; + + // + NormalizeTime(time); + + // + datetime cTime = TimeCurrent(); + datetime cTimeLocal = TimeLocal(); + + // + int cLocalOffset = ((int)cTimeLocal - (int)cTime); + int gmtOffset = TimeGMTOffset(); + int offsetDelte = gmtOffset + cLocalOffset; + int requiredUTCOffset = GetUTCRequiredTimeOffset(); + if (requiredUTCOffset > 0) + { + requiredUTCOffset = -1 * requiredUTCOffset; + } + + // + int timeSeconds = (int)time; + int resultSeconds = timeSeconds + requiredUTCOffset; + + // + result = (datetime)(resultSeconds); + + // + return result; +} + +// +// Retrieve only Hour and Minute as String ... +string GetTimeString( + datetime time = NULL // +) +{ + // + NormalizeTime(time); + + // + string result = NULL; + + // + MqlDateTime tStruct; + bool isStructed = TimeToStruct(time, tStruct); + if (!isStructed) + { + return result; + } + + // + string hour = ToString(tStruct.hour); + hour = + StringLen(hour) == 1 + ? "0" + hour + : hour; + + // + string minute = ToString(tStruct.min); + minute = + StringLen(minute) == 1 + ? "0" + minute + : minute; + + // + result = hour + ":" + minute; + + // + return result; +} + +// +// Converts a Date time to File Format ... +string ToFormatString( + datetime mTime, + string separator = "_" // +) +{ + // + string result = NULL; + + // + if (!IsValid(mTime)) + { + return result; + } + + // + MqlDateTime timeStruct; + bool isConverts = TimeToStruct( + mTime, + timeStruct // + ); + if (!isConverts) + { + return result; + } + + // + string year = ToString(timeStruct.year); + string month = ToString(timeStruct.mon); + string day = ToString(timeStruct.day); + string hour = ToString(timeStruct.hour); + string minute = ToString(timeStruct.min); + string second = ToString(timeStruct.sec); + + // + result = + // + // Year ... + year + separator + + // + // Month ... + (StringLen(month) == 1 + ? "0" + month + : month) + + separator + + // + // Day ... + (StringLen(day) == 1 + ? "0" + day + : day) + + separator + + // + // Hour ... + (StringLen(hour) == 1 + ? "0" + hour + : hour) + + separator + + // + // Minute ... + (StringLen(minute) == 1 + ? "0" + minute + : minute) + + separator + + // + // Seconds ... + (StringLen(second) == 1 + ? "0" + second + : second) + + separator + + // + "" + // + ; + + // + return result; +} + +/** + * Converts an String Represetation of Time (00:00) to Date Time .. + * + * @param value: String ... + * + * @return ( datetime ) + */ +datetime ParseDateTimeFromTimeString(string value) +{ + // + datetime result = NULL; + + // + if (!IsValid(value)) + { + return result; + } + + // + // Check Signalling Time ... + MqlDateTime cTime; + bool isTimeRecieved = TimeCurrent(cTime); + if (!isTimeRecieved) + { + return result; + } + + // + // Split ... + string parts[]; + int partsCount = SplitContent( + parts, + value, + ":" + // + ); + if (!IsValidSize(partsCount)) + { + return result; + } + + // + int hour = 0; + int minute = 0; + if (partsCount >= 1) + { + hour = (int)(parts[0]); + } + if (partsCount >= 2) + { + minute = (int)(parts[1]); + } + + // + cTime.day_of_week = 0; + cTime.day_of_year = 0; + + // + cTime.hour = hour; + cTime.min = minute; + + // + result = StructToTime(cTime); + + // + return result; +} + +// +// Check Specific Time in Range of another Time ... +bool IsTimeInRange( + datetime currentTime = NULL, + datetime startTime = NULL, + datetime stopTime = NULL // +) +{ + // + bool result = false; + + // + // Normallize Current Time ... + currentTime = NormalizeTime(currentTime); + + // + result = !IsValid(startTime) && + !IsValid(stopTime); + if (result) + { + return result; + } + + // + result = IsValid(startTime) && + IsValid(stopTime); + if (!result) + { + // + result = IsValid(startTime) && + currentTime >= startTime; + + // + return result; + } + + // + result = currentTime >= startTime && + currentTime < stopTime; + + // + return result; +} +bool IsTimeInRange( + datetime currentTime, + string startTime, + string endTime // +) +{ + // + bool result = false; + + // + result = IsValid(startTime) && + IsValid(endTime); + if (!result) + { + // + // Here Since there isnot provide any + // data source we pass result as true ... + result = true; + return result; + } + + // + // Converts String Representation to Time ... + datetime st = ParseDateTimeFromTimeString(startTime); + datetime et = ParseDateTimeFromTimeString(endTime); + + // + result = IsTimeInRange( + currentTime, + st, + et // + ); + + // + return result; +} + +// +// END Time ... +// + +// +// START Price ... +// + +// +// Get 1 Pip in Price Value ... +double GetPipPrice( + string mSymbol = NULL // Trading Symbol +) +{ + // + mSymbol = NormalizeSymbol(mSymbol); + + // + double symbolPoint = GetPoints(mSymbol); + int symbolDigits = GetDigits(mSymbol); + + // + double result = symbolPoint; + if (symbolDigits == 3 || symbolDigits == 5) + { + result *= 10; + } + + // + return result; +} + +/** + * Calculate Applied Price ... + * + * @param mType: ENUM_X_PRICE member, Price Type ... + * @param mOpen: double collection, Open Prices ... + * @param mHigh: double collection, High Prices ... + * @param mLow: double collection, Low Prices ... + * @param mClose: double collection, Close Prices ... + * @param barIndex: int, Index ... + * + * @return ( double ) + */ +double GetAppliedPrice( + ENUM_X_PRICE mType, // Type of Price Selection + double &mOpen[], // Open Prices + double &mHigh[], // High Preices + double &mLow[], // Low Prices + double &mClose[], // Close Prices + int barIndex // Bar Index +) +{ + // + double result = 0; + + // + switch (mType) + { + // + case X_PRICE_NONE: + result = 0; + break; + + // + case X_PRICE_HIGH: + result = mHigh[barIndex]; + break; + + // + case X_PRICE_OPEN: + result = mOpen[barIndex]; + break; + + // + case X_PRICE_CLOSE: + result = mClose[barIndex]; + break; + + // + case X_PRICE_LOW: + result = mLow[barIndex]; + break; + + // + case X_PRICE_UP: + result = MathMax(mOpen[barIndex], mClose[barIndex]); + break; + + // + case X_PRICE_DOWN: + result = MathMin(mOpen[barIndex], mClose[barIndex]); + break; + + // + case X_PRICE_MEDIAN: + result = ((mHigh[barIndex] + mLow[barIndex]) / 2.0); + break; + + // + case X_PRICE_BODY_MEDIAN: + result = ((mOpen[barIndex] + mClose[barIndex]) / 2.0); + break; + + // + case X_PRICE_TYPICAL: + result = ((mHigh[barIndex] + mLow[barIndex] + mClose[barIndex]) / 3.0); + break; + + // + case X_PRICE_WEIGHTED: + result = (((mHigh[barIndex] + mLow[barIndex] + mClose[barIndex] + mClose[barIndex]) / 4.0)); + break; + } + + // + return result; +} + +/** + * Calculate Applied Price ... + * + * @param mType: ENUM_X_PRICE member, Price Type ... + * @param mOpen: double, Open Price ... + * @param mHigh: double, High Price ... + * @param mLow: double, Low Price ... + * @param mClose: double, Close Price ... + * @param barIndex: int, Index ... + * + * @return ( double ) + */ +double GetAppliedPrice( + ENUM_X_PRICE mType, // Type of Price Selection + double mOpen, // Open Prices + double mHigh, // High Preices + double mLow, // Low Prices + double mClose // Close Prices +) +{ + // + double result = 0; + + // + switch (mType) + { + // + case X_PRICE_NONE: + result = 0; + break; + + // + case X_PRICE_HIGH: + result = mHigh; + break; + + // + case X_PRICE_OPEN: + result = mOpen; + break; + + // + case X_PRICE_CLOSE: + result = mClose; + break; + + // + case X_PRICE_LOW: + result = mLow; + break; + + // + case X_PRICE_UP: + result = MathMax(mOpen, mClose); + break; + + // + case X_PRICE_DOWN: + result = MathMin(mOpen, mClose); + break; + + // + case X_PRICE_MEDIAN: + result = ((mHigh + mLow) / 2.0); + break; + + // + case X_PRICE_BODY_MEDIAN: + result = ((mOpen + mClose) / 2.0); + break; + + // + case X_PRICE_TYPICAL: + result = ((mHigh + mLow + mClose) / 3.0); + break; + + // + case X_PRICE_WEIGHTED: + result = (((mHigh + mLow + mClose + mClose) / 4.0)); + break; + } + + // + return result; +} + +// +// END Price ... +// + +// +// START Bar ... +// + +/** + * Retrieve Specific Bar's Time ... + * + * @param mSymbol: string, Provided Symbol ... + * @param mPeriod: ENUM_TIMEFRAMES member, Provided Period ... + * @param barIndex: int, Provided Bar Index ... + * + * @return ( datetime ) + */ +datetime GetBarTime( + string mSymbol = NULL, // Specify Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Specify TimeFrame + int barIndex = 0 // Specify Bar Index +) +{ + // + // Validate and Normalize Args ... + + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + // Retrieve Bar Time ... + datetime result = iTime( + mSymbol, + mPeriod, + barIndex // + ); + + // + return result; +} + +/** + * Retrieve Specific Bar's Index ... + * + * @param mSymbol: string, Provided Symbol ... + * @param mPeriod: ENUM_TIMEFRAMES member, Provided Period ... + * @param barTime: datetime, Provided Bar Time ... + * + * @return ( datetime ) + */ +int GetBarIndex( + string mSymbol = NULL, // Specify Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Specify TimeFrame + datetime barTime = NULL // Specify Bar Time +) +{ + // + // Validate and Normalize Args ... + + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + // Retrieve Bar Time ... + int result = iBarShift( + mSymbol, + mPeriod, + barTime // + ); + + // + return result; +} + +// +// EN Bar ... +// + +// diff --git a/Libraries/x-saherelm.common.lib.mq5 b/Libraries/x-saherelm.common.lib.mq5 index 5dc4e86d..cad150f6 100644 --- a/Libraries/x-saherelm.common.lib.mq5 +++ b/Libraries/x-saherelm.common.lib.mq5 @@ -21,3739 +21,13 @@ // // Imports ... -#include "../Classes/x-saherelm.x-md5.class.mq5" - -// -#include +#include "../Libraries/x-saherelm.common.extensions.lib.mq5" +#include "../Libraries/x-saherelm.common.models.lib.mq5" +#include "../Libraries/x-saherelm.x-ohcl.lib.mq5" // // Models ... -// -// Specified Price Type ... -enum ENUM_X_PRICE -{ - X_PRICE_HIGH, - X_PRICE_OPEN, - X_PRICE_CLOSE, - X_PRICE_LOW, - X_PRICE_UP, - X_PRICE_DOWN -}; - -// -enum ENUM_X_DIRECTION -{ - X_DIRECTION_ALL, // All - X_DIRECTION_NONE, // None - X_DIRECTION_BULLISH, // Bullish - X_DIRECTION_BEARISH, // Bearish -}; - -// -enum ENUM_X_FIBO_LEVELS -{ - X_FIBO_LEVEL_236, - X_FIBO_LEVEL_382, - X_FIBO_LEVEL_500, - X_FIBO_LEVEL_618, - X_FIBO_LEVEL_764, -}; - -// -double GetFiboLevelValue(ENUM_X_FIBO_LEVELS value) -{ - // - double result = 0; - - // - switch (value) - { - // - case X_FIBO_LEVEL_236: - result = 0.236; - break; - - // - case X_FIBO_LEVEL_382: - result = 0.382; - break; - - // - case X_FIBO_LEVEL_500: - result = 0.500; - break; - - // - case X_FIBO_LEVEL_618: - result = 0.618; - break; - - // - case X_FIBO_LEVEL_764: - result = 0.764; - break; - } - - // - return result; -} - -// -string ToString(ENUM_X_DIRECTION value) -{ - // - string result = NULL; - - // - switch (value) - { - case X_DIRECTION_ALL: - result = "ALL"; - break; - case X_DIRECTION_NONE: - result = "NONE"; - break; - case X_DIRECTION_BULLISH: - result = "BULLISH"; - break; - case X_DIRECTION_BEARISH: - result = "BEARISH"; - break; - } - - // - return result; -} - -// -// Swing Types Enum ... -enum ENUM_X_SWING_TYPE -{ - X_NO_SWING = 0, - X_SWING_HIGH = 1, - X_SWING_LOW = -1, -}; - -// -string ToString(ENUM_X_SWING_TYPE value) -{ - // - string result = NULL; - - // - switch (value) - { - // - case X_NO_SWING: - result = "NO_SWING"; - break; - - // - case X_SWING_LOW: - result = "SWING_LOW"; - break; - - // - case X_SWING_HIGH: - result = "SWING_HIGH"; - break; - } - - // - return result; -} - -// -ENUM_SERIESMODE ToSeriesMode(ENUM_X_SWING_TYPE value) -{ - // - ENUM_SERIESMODE result = MODE_HIGH; - - // - switch (value) - { - // - case X_SWING_HIGH: - result = MODE_HIGH; - break; - - // - case X_SWING_LOW: - result = MODE_LOW; - break; - } - - // - return result; -} - -// -// Find Swing Points ... -int FindSwing( - string mSymbol, // Trading Symbol ... - ENUM_TIMEFRAMES mPeriod, // Trading Period ... - ENUM_X_SWING_TYPE mMode, // Swing Based On Price mode ... - int mLength, // Loopback ... - int bar_index // BarIndex ... -) -{ - // - int result = -1; - - // - if (StringLen(mSymbol) == 0 || (mMode != X_SWING_HIGH && mMode != X_SWING_LOW)) - { - return result; - } - - // - int current = bar_index; - int founded = FindNextSwing( - mSymbol, - mPeriod, - mMode, - (mLength * 2) + 1, - current - mLength); - - // - while (founded != current) - { - // - current = FindNextSwing( - mSymbol, - mPeriod, - mMode, - mLength, - current + 1); - - // - founded = FindNextSwing( - mSymbol, - mPeriod, - mMode, - (mLength * 2) + 1, - current - mLength); - } - - // - result = current; - - // - return result; -} - -// -// Find Next Swing ... -int FindNextSwing( - string mSymbol, // Trading Symbol ... - ENUM_TIMEFRAMES mPeriod, // Trading Period ... - ENUM_X_SWING_TYPE mMode, // Swing Based On Price mode ... - int mLength, // Loopback ... - int bar_index // BarIndex ... -) -{ - // - int result = -1; - - // - if (bar_index < 0) - { - mLength += bar_index; - bar_index = 0; - } - - // - ENUM_SERIESMODE mSeriesMode = ToSeriesMode(mMode); - - // - result = mMode == X_SWING_HIGH - ? iHighest( - mSymbol, - mPeriod, - mSeriesMode, - mLength, - bar_index) - : iLowest( - mSymbol, - mPeriod, - mSeriesMode, - mLength, - bar_index); - - // - return result; -} - -// -// XPERIOD Calculation Method ... -enum ENUM_X_PERIOD_METHOD -{ - // - X_PERIOD_NOTHING, // Nothing - X_PERIOD_AUTO, // Auto Select - X_PERIOD_MANUALLY // Manually -}; - -// -// Available Market Cycles ... -enum ENUM_X_MARKET_CYCLES -{ - // - X_MARKET_CYCLE_UNKNOWN, // Unknown Cycle - X_MARKET_CYCLE_SHORT, // Short Cycle - X_MARKET_CYCLE_MEDIUM, // Medium Cycle - X_MARKET_CYCLE_LONG, // Long Cycle - X_MARKET_CYCLE_HIND, // Hind Cycle -}; - -// -// Structs ... - -// -// Model Specified Ticks Info ... -struct XTick -{ - // - string symbol; // Symbol ... - datetime time; // Time ... - double bid; // Bid ... - double ask; // Ask ... - double spread; // Spread ... - long volume; // Volume ... - - // - // Constructor ... - void XTick() - { - Clean(); - } - - // - // Tools Functions ... - - /** - * Initial ... - * - * @param _symbol: Symbol ... - * @param _time: Time ... - * @param _bid: Bid Price ... - * @param _ask: Ask Price ... - * @param _volume: Tick Volume ... - */ - bool Init( - string _symbol, - datetime _time, - double _bid, - double _ask, - double _spread, - long _volume // - ) - { - // - bool result = false; - - // - result = IsValid(_symbol) && - IsValid(_time) && - _bid > 0 && - _ask > 0; - if (!result) - { - return result; - } - - // - bid = _bid; - ask = _ask; - time = _time; - symbol = _symbol; - spread = _spread; - - // - result = IsValid(); - - // - return result; - } - - /** - * Init Tick by Symbol ... - * - * @param _symbol: String ... - * - * @return ( bool ) - */ - bool Init( - string _symbol, - ENUM_TIMEFRAMES _volumePeriod = NULL // - ) - { - // - bool result = false; - - // - result = IsValid(_symbol); - if (!result) - { - return result; - } - - // - datetime _time = TimeCurrent(); - double _bid = GetBid(_symbol); - double _ask = GetAsk(_symbol); - double _spread = GetSpread(_symbol); - - // - long _volume = 0; - if (IsValid(_volumePeriod)) - { - _volume = iTickVolume(_symbol, _volumePeriod, 0); - } - - // - result = Init( - _symbol, - _time, - _bid, - _ask, - _spread, - _volume // - ); - - // - return result; - } - - /** - * Cleanup ... - */ - void Clean() - { - // - bid = 0; - ask = 0; - volume = 0; - time = NULL; - symbol = NULL; - - // - ZeroMemory(this); - } - - /** - * Validate ... - * - * @return ( bool ) - */ - bool IsValid() - { - // - bool result = false; - - // - result = IsValid(symbol) && - IsValid(time) && - bid > 0 && - ask > 0 && - volume >= 0; - - // - return result; - } - - // -}; - -// -// Model a Bar Remains Time ... -struct XBarRemainsTime -{ - // - int days; - int hours; - int minutes; - int seconds; - - // - // Constructor ... - XBarRemainsTime() - { - Clean(); - } - - // - // Always Calculate Current 0 Bar Timing ... - bool Init( - string mSymbol = NULL, // Trading Symbol - ENUM_TIMEFRAMES mPeriod = NULL // Trading Period - ) - { - // - bool result = false; - - // - mSymbol = NormalizeSymbol(mSymbol); - mPeriod = NormalizePeriod(mPeriod); - - // - int minuteSecoonds = 60; - int hourSeconds = minuteSecoonds * 60; - int daySeconds = 24 * hourSeconds; - - // - int periodSeconds = PeriodSeconds( - mPeriod); - datetime startTime = GetBarTime( - mSymbol, - mPeriod, - 0 - // - ); - - // - int secondsDiff = (int)startTime + periodSeconds - (int)TimeCurrent(); - - // - int mWorkingSecondsDiff = secondsDiff; - if (mWorkingSecondsDiff > daySeconds) - { - // - days = mWorkingSecondsDiff / daySeconds; - mWorkingSecondsDiff -= days * daySeconds; - } - if (mWorkingSecondsDiff > hourSeconds) - { - // - hours = mWorkingSecondsDiff / hourSeconds; - mWorkingSecondsDiff -= hours * hourSeconds; - } - if (mWorkingSecondsDiff > minuteSecoonds) - { - // - minutes = mWorkingSecondsDiff / minuteSecoonds; - mWorkingSecondsDiff -= minutes * minuteSecoonds; - } - seconds = mWorkingSecondsDiff; - - // - result = true; - - // - return result; - } - - // - // Tools ... - - // - // Cleanup ... - void Clean() - { - days = 0; - hours = 0; - minutes = 0; - seconds = 0; - - // - ZeroMemory(this); - } - - // - // To String Representation ... - string ToString( - string dayId = "d", - string hourId = "h", - string minuteId = "m", - string secondId = "s", - string idSeparator = ": ", - string separator = ", ", - bool ignoreZeroValues = true - // - ) - { - // - string result = ""; - - // - // Days ... - if (!ignoreZeroValues || days > 0) - { - result += dayId + idSeparator + (string)days + separator; - } - - // - // Hours ... - if (!ignoreZeroValues || hours > 0) - { - // - string strHour = ToString(hours); - if (StringLen(strHour) == 1) - { - strHour = "0" + strHour; - } - - // - result += hourId + idSeparator + strHour + separator; - } - - // - // Minutes ... - if (!ignoreZeroValues || minutes > 0) - { - // - string strMinute = ToString(minutes); - if (StringLen(strMinute) == 1) - { - strMinute = "0" + strMinute; - } - - // - result += minuteId + idSeparator + strMinute + separator; - } - - // - // Seconds ... - if (!ignoreZeroValues || seconds > 0) - { - // - string strSec = ToString(seconds); - if (StringLen(strSec) == 1) - { - strSec = "0" + strSec; - } - - // - result += secondId + idSeparator + strSec; - } - - // - return result; - } -}; - -// -// Describe an Specific Candle ... -struct XOHCL -{ - // - // Props ... - - // - double high; - double open; - double close; - double low; - - // - string symbol; - datetime time; - ENUM_TIMEFRAMES period; - - // - // Constructor ... - XOHCL() - { - Clean(); - } - - // - // Init a Bar ... - // Using Bar Index ... - bool Init( - string mSymbol = NULL, // Trading Symbol - ENUM_TIMEFRAMES mPeriod = NULL, // Trading Period - int barIndex = 0 // Bar Index - ) - { - // - mSymbol = NormalizeSymbol(mSymbol); - mPeriod = NormalizePeriod(mPeriod); - - // - symbol = mSymbol; - period = mPeriod; - - // - time = iTime( - mSymbol, - mPeriod, - barIndex // - ); - - // - open = iOpen( - mSymbol, - mPeriod, - barIndex // - ); - open = NormalizePrice(open, mSymbol); - - // - close = iClose( - mSymbol, - mPeriod, - barIndex // - ); - close = NormalizePrice(close, mSymbol); - - // - high = iHigh( - mSymbol, - mPeriod, - barIndex // - ); - high = NormalizePrice(high, mSymbol); - - // - low = iLow( - mSymbol, - mPeriod, - barIndex // - ); - low = NormalizePrice(low, mSymbol); - - // - bool result = IsValid(); - - // - return result; - } - - // - // Init a Bar ... - // Using Bar Time ... - bool Init( - string mSymbol = NULL, // Trading Symbol - ENUM_TIMEFRAMES mPeriod = NULL, // Trading Period - datetime mTime = NULL // Bar Time - ) - { - // - mTime = NormalizeTime(mTime); - - // - int barIndex = iBarShift( - mSymbol, - mPeriod, - mTime, - false // - ); - - // - bool result = Init( - mSymbol, - mPeriod, - barIndex - // - ); - - // - return result; - } - - // - bool Init( - string mSymbol = NULL, // Trading Symbol - ENUM_TIMEFRAMES mPeriod = NULL, // Trading Period - double mOpen = 0, // Open - double mHigh = 0, // High - double mClose = 0, // Close - double mLow = 0, // Low - int barIndex = 0 // Bar Index - ) - { - // - mSymbol = NormalizeSymbol(mSymbol); - mPeriod = NormalizePeriod(mPeriod); - - // - symbol = mSymbol; - period = mPeriod; - - // - time = iTime( - mSymbol, - mPeriod, - barIndex - // - ); - - // - open = mOpen; - high = mHigh; - close = mClose; - low = mLow; - - // - return IsValid(); - } - - // - bool Init( - string mSymbol = NULL, // Trading Symbol - ENUM_TIMEFRAMES mPeriod = NULL, // Trading Period - double mOpen = 0, // Open - double mHigh = 0, // High - double mClose = 0, // Close - double mLow = 0, // Low - datetime mTime = NULL // Bar Time - ) - { - // - mSymbol = NormalizeSymbol(mSymbol); - mPeriod = NormalizePeriod(mPeriod); - - // - symbol = mSymbol; - period = mPeriod; - - // - int barIndex = iBarShift( - symbol, - period, - mTime); - - // - time = iTime( - mSymbol, - mPeriod, - barIndex - // - ); - - // - open = mOpen; - high = mHigh; - close = mClose; - low = mLow; - - // - return IsValid(); - } - - // - // Tools ... - - // - void Clean() - { - // - high = 0; - open = 0; - close = 0; - low = 0; - - // - time = NULL; - symbol = NULL; - period = NULL; - - // - ZeroMemory(this); - } - - // - // Validate Bar ... - bool IsValid() - { - // - bool result = false; - - // - result = - // - high > 0 && - open > 0 && - close > 0 && - low > 0 - // - ; - - // - return result; - } - - // - int TotalBars() - { - // - int result = 0; - - // - result = iBars( - symbol, - period // - ); - - // - return result; - } - - // - // Calculate X_PRICE Specified Type ... - double GetPrice(ENUM_X_PRICE mPType) - { - // - double result = 0; - - // - if (!IsValid()) - { - return result; - } - - // - switch (mPType) - { - // - case X_PRICE_OPEN: - result = open; - break; - // - case X_PRICE_HIGH: - result = high; - break; - // - case X_PRICE_CLOSE: - result = close; - break; - // - case X_PRICE_LOW: - result = low; - break; - // - case X_PRICE_UP: - result = GetUp(); - break; - // - case X_PRICE_DOWN: - result = GetDown(); - break; - } - - // - return result; - } - - // - // Retrieve Price base On Series Mode ... - double GetPrice(ENUM_SERIESMODE mMode) - { - // - ENUM_X_PRICE mXMode = ToPrice(mMode); - - // - return GetPrice(mXMode); - } - - // - // Calculate Applied Price ... - double GetPrice( - ENUM_APPLIED_PRICE mAppliedTo // Select Application Method - ) - { - // - double result = 0; - - // - // Calculate Applied Price ... - switch (mAppliedTo) - { - // - case PRICE_CLOSE: - result = close; - break; - - // - case PRICE_OPEN: - result = open; - break; - - // - case PRICE_HIGH: - result = high; - break; - - // - case PRICE_LOW: - result = low; - break; - - // - case PRICE_MEDIAN: - result = (high + low) / 2; - break; - - // - case PRICE_TYPICAL: - result = (high + low + close) / 3; - break; - - // - case PRICE_WEIGHTED: - result = (high + low + close + close) / 4; - break; - } - - // - return result; - } - - // - // Find Specific Price ... - bool FindHigherPriceBar( - XOHCL &bar, - double price, - ENUM_X_PRICE _type = X_PRICE_HIGH // - ) - { - // - bool result = false; - - // - result = IsValid(); - if (!result) - { - return result; - } - - // - int totalBars = TotalBars(); - result = IsValidSize(totalBars); - if (!result) - { - return result; - } - - // - int start = Index(); - int maxAllowedLoopback = totalBars / 5; - for (int i = start; i < maxAllowedLoopback; i++) - { - // - result = bar.Init( - symbol, - period, - i // - ); - - // - if (!result) - { - break; - } - - // - double iPrice = bar.GetPrice(_type); - - // - result = - // - iPrice > 0 && - iPrice > price - // - ; - if (result) - { - break; - } - } - - // - if (!result) - { - bar.Clean(); - } - - // - return result; - } - - // - // Find Specific Price ... - bool FindLowerPriceBar( - XOHCL &bar, - double price, - ENUM_X_PRICE _type = X_PRICE_HIGH // - ) - { - // - bool result = false; - - // - result = IsValid(); - if (!result) - { - return result; - } - - // - int totalBars = TotalBars(); - result = IsValidSize(totalBars); - if (!result) - { - return result; - } - - // - int start = Index(); - int maxAllowedLoopback = totalBars / 5; - for (int i = start; i < maxAllowedLoopback; i++) - { - // - result = bar.Init( - symbol, - period, - i // - ); - - // - if (!result) - { - break; - } - - // - double iPrice = bar.GetPrice(_type); - - // - result = - // - iPrice > 0 && - iPrice < price - // - ; - if (result) - { - break; - } - } - - // - if (!result) - { - bar.Clean(); - } - - // - return result; - } - - // - // Calculate Bar Mid Line ... - double GetMid() - { - // - double result = 0; - - // - if (!IsValid()) - { - return result; - } - - // - result = (high + low) / 2; - - // - return result; - } - - // - // Calculate up Price ... - double GetUp() - { - // - double result = 0; - - // - if (!IsValid()) - { - return result; - } - - // - result = MathMax(open, close); - - // - return result; - } - - // - // Calculate Down Price ... - double GetDown() - { - // - double result = 0; - - // - if (!IsValid()) - { - return result; - } - - // - result = MathMin(open, close); - - // - return result; - } - - // - // Retrieve Required Price for Zone Checking ... - // For Bullish Zones => low; - // For Bearish Zones => high; - double GetZoneCheckValue(ENUM_X_DIRECTION forDir) - { - // - double result = 0; - - // - if (!IsValid() || - !HasDirection(forDir)) - { - return result; - } - - // - bool isBullish = IsBullish(forDir); - - // - result = - isBullish - ? low - : high; - - return result; - } - - // - // Calculate Bar Body ... - double GetBody() - { - // - double result = 0; - - // - if (!IsValid()) - { - return result; - } - - // - result = GetUp() - GetDown(); - - // - return result; - } - - // - // Calculate Bar Range ... - double GetRange() - { - // - double result = 0; - - // - if (!IsValid()) - { - return result; - } - - // - result = high - low; - - // - return result; - } - - // - // Calculate Bar Shadows ... - double GetShadows() - { - // - double result = 0; - - // - if (!IsValid()) - { - return result; - } - - // - result = GetRange() - GetBody(); - - // - return result; - } - - // - // Calculate Bar High Shadow ... - double GetHighShadow() - { - // - double result = 0; - - // - if (!IsValid()) - { - return result; - } - - // - result = - // - high - GetUp() - // - ; - - // - return result; - } - - // - // Calculate Bar Low Shadow ... - double GetLowShadow() - { - // - double result = 0; - - // - if (!IsValid()) - { - return result; - } - - // - result = - // - GetDown() - low; - // - ; - - // - return result; - } - - // - // Check Bar is Bullish ... - bool IsBullish() - { - // - bool result = false; - - // - if (!IsValid()) - { - return result; - } - - // - result = open < close; - - // - return result; - } - - // - // Check Bar is Bearish ... - bool IsBearish() - { - // - bool result = false; - - // - if (!IsValid()) - { - return result; - } - - // - result = open > close; - - // - return result; - } - - // - // Get Direction of Bar ... - ENUM_X_DIRECTION GetDirection() - { - // - ENUM_X_DIRECTION result = X_DIRECTION_NONE; - - // - bool isBullish = IsBullish(); - bool isBearish = IsBearish(); - - // - result = - isBullish && isBearish - ? X_DIRECTION_ALL - : !isBullish && !isBearish - ? X_DIRECTION_NONE - : isBullish - ? X_DIRECTION_BULLISH - : X_DIRECTION_BEARISH; - - // - return result; - } - - // - // Find Next Bar Time ... - datetime NextAt() - { - // - datetime result = NULL; - - // - if (!IsValid()) - { - return result; - } - - // - int prSeconds = PeriodSeconds(period); - - // - result = time + prSeconds; - - // - return result; - } - - // - // Find Prev Bar Time ... - datetime BeforeOn() - { - // - datetime result = NULL; - - // - if (!IsValid()) - { - return result; - } - - // - int prSeconds = PeriodSeconds(period); - - // - result = time - prSeconds; - - // - return result; - } - - // - // Calculate Last Bar Open Time in Smaller Period ... - datetime GetLastBarTimeOfPeriod( - ENUM_TIMEFRAMES smallerPeriod // - ) - { - // - datetime result = NULL; - - // - if (!IsValid()) - { - return result; - } - - // - int sourceSeconds = PeriodSeconds(period); - int destSeconds = PeriodSeconds(smallerPeriod); - if (destSeconds >= sourceSeconds) - { - // - result = time; - return result; - } - - // - result = (datetime)((((int)time) + sourceSeconds) - destSeconds); - - // - return result; - } - - // - // Calculate Close Time ... - datetime GetCloseTime() - { - // - datetime result = NULL; - - // - if (!IsValid()) - { - return result; - } - - // - int seconds = PeriodSeconds(period); - - // - result = (datetime)(((int)time) + seconds); - - // - return result; - } - - // - bool BarAt( - int index, - XOHCL &bar // - ) - { - // - bool result = false; - - // - bar.Clean(); - - // - result = IsValid(); - if (!result) - { - return result; - } - - // - if (index < 0) - { - index = 0; - } - - // - result = bar.Init( - symbol, - period, - index // - ); - - // - return result; - } - - // - bool BarIn( - ENUM_TIMEFRAMES _period, - XOHCL &bar // - ) - { - // - bool result = false; - - // - bar.Clean(); - - // - result = IsValid() && - IsSpecifiedValid(_period); - if (!result) - { - return result; - } - - // - int index = Index(_period); - result = bar.Init( - symbol, - _period, - index // - ); - - // - return result; - } - - // - // Find Current Bar Index on Chart ... - int Index() - { - // - int result = -1; - - // - if (!IsValid()) - { - return result; - } - - // - result = iBarShift( - symbol, - period, - time - // - ); - - // - return result; - } - - // - int Index(datetime value) - { - // - int result = -1; - - // - value = NormalizeTime(value); - - // - result = IsValid(); - if (!result) - { - return result; - } - - // - result = iBarShift( - symbol, - period, - value // - ); - - // - return result; - } - - // - int Index(ENUM_TIMEFRAMES value) - { - // - int result = -1; - - // - result = IsValid() && - IsSpecifiedValid(value); - if (!result) - { - return result; - } - - // - result = iBarShift( - symbol, - value, - time // - ); - - // - return result; - } - - // - bool GetNextBar(XOHCL &bar) - { - // - bool result = false; - - // - result = IsValid(); - if (!result) - { - return result; - } - - // - int idx = Index(); - result = idx > 0; - if (!result) - { - return result; - } - - // - result = bar.Init( - this.symbol, - this.period, - idx - 1 // - ); - - // - if (!result) - { - bar.Clean(); - } - - // - return result; - } - - // - bool GetPreviousBar(XOHCL &bar) - { - // - bool result = false; - - // - result = IsValid(); - if (!result) - { - return result; - } - - // - int idx = Index(); - - // - result = bar.Init( - this.symbol, - this.period, - idx + 1 // - ); - - // - if (!result) - { - bar.Clean(); - } - - // - return result; - } - - // - // Find Highest Bar Index ... - int FindHighestIndex( - int mLength, // Loopback ... - ENUM_SERIESMODE mMode // Calculation mode - ) - { - // - int result = -1; - - // - if (!IsValid()) - { - return result; - } - - // - if (mLength < 2) - { - mLength = 2; - } - - // - result = iHighest( - symbol, - period, - mMode, - mLength, - Index()); - - // - return result; - } - - // - // Find Highest ... - double FindHighest( - int mLength, // Loopback ... - ENUM_SERIESMODE mMode // Calculation mode - ) - { - // - double result = 0; - - // - if (!IsValid()) - { - return result; - } - - // - int idx = FindHighestIndex( - mLength, - mMode); - if (idx <= -1) - { - return result; - } - - // - XOHCL iH; - result = iH.Init( - symbol, - period, - idx - // - ); - if (!result) - { - return result; - } - - // - result = iH.GetPrice(mMode); - - // - return result; - } - - // - // Find Highest ... - double FindHighestUp( - int mLength // Loopback ... - ) - { - // - double result = 0; - - // - if (!IsValid()) - { - return result; - } - - // - result = FindHighest(mLength, MODE_OPEN); - result = MathMax(mLength, FindHighest(mLength, MODE_CLOSE)); - - // - return result; - } - - // - // Find Lowest Bar Index ... - int FindLowestIndex( - int mLength, // Loopback ... - ENUM_SERIESMODE mMode // Calculation mode - ) - { - // - int result = -1; - - // - if (!IsValid()) - { - return result; - } - - // - if (mLength < 2) - { - mLength = 2; - } - - // - result = iLowest( - symbol, - period, - mMode, - mLength, - Index()); - - // - return result; - } - - // - // Find Lowest ... - double FindLowest( - int mLength, // Loopback ... - ENUM_SERIESMODE mMode // Calculation mode - ) - { - // - double result = 0; - - // - if (!IsValid()) - { - return result; - } - - // - int idx = FindLowestIndex( - mLength, - mMode); - if (idx <= -1) - { - return result; - } - - // - XOHCL iL; - result = iL.Init( - symbol, - period, - idx - // - ); - if (!result) - { - return result; - } - - // - result = iL.GetPrice(mMode); - - // - return result; - } - - // - // Find Lowest ... - double FindLowesttDown( - int mLength // Loopback ... - ) - { - // - double result = 0; - - // - if (!IsValid()) - { - return result; - } - - // - result = FindLowest(mLength, MODE_OPEN); - result = MathMax(mLength, FindLowest(mLength, MODE_CLOSE)); - - // - return result; - } - - // - // Other ... - string GetTag(string prefix = "") - { - // - string result = NULL; - - // - result = - (IsValid(prefix) - ? prefix + "_" - : "") + - "XOHCL_" + symbol + "_" + ToString(period) + "_" + ToFormatString(time); - - // - return result; - } - - // - // Convert to String Representation ... - string ToString() - { - // - string result = ""; - - // - result = GetTypeName(this) + - "(O(" + ToString(open) + "),H(" + ToString(high) + "),C(" + ToString(close) + "),L(" + ToString(low) + "))"; - - // - return result; - } -}; - -// -// Tracking Times ... -struct XTimeTracker -{ - // - // Props ... - int xMonth; - int xDayOfWeek; - int xForWeekDay; - int xDay; - int xHour; - int xMinute; - - // - // Constructor ... - XTimeTracker() - { - Clean(); - } - - // - // Tools ... - - // - void Clean() - { - // - xDay = -1; - xHour = -1; - xMonth = -1; - xMinute = -1; - xDayOfWeek = -1; - xForWeekDay = -1; - - // - ZeroMemory(this); - } - - // - // Detecting New Minute ... - bool IsNewMinute() - { - // - bool result = false; - - // - // Retrieve Current Time as Struct ... - MqlDateTime timeStruct = GetCurrentTime(); - - // - // Check Houre ... - result = timeStruct.min != xMinute; - if (result) - { - xMinute = timeStruct.min; - } - - // - return result; - } - - // - // Detecting New Houre ... - bool IsNewHour() - { - // - bool result = false; - - // - // Retrieve Current Time as Struct ... - MqlDateTime timeStruct = GetCurrentTime(); - - // - // Check Houre ... - result = timeStruct.hour != xHour; - if (result) - { - xHour = timeStruct.hour; - } - - // - return result; - } - - // - // Detecting New Day ... - bool IsNewDay() - { - // - bool result = false; - - // - // Retrieve Current Time as Struct ... - MqlDateTime timeStruct = GetCurrentTime(); - - // - // Check Houre ... - result = timeStruct.day_of_year != xDay; - if (result) - { - xDay = timeStruct.day_of_year; - } - - // - return result; - } - - // - // Detecting New Week ... - bool IsNewWeek() - { - // - bool result = false; - - // - // Retrieve Current Time as Struct ... - MqlDateTime timeStruct = GetCurrentTime(); - - // - // Check Week ... - // Since Week Starts From Monday in Forex World ... - // we Calculate Start of Week by 1-Monday ... - result = - xDayOfWeek == -1 && - xForWeekDay == -1 - ? true - : timeStruct.day_of_week == 1 && - timeStruct.day_of_year > xForWeekDay; - - // - xForWeekDay = timeStruct.day_of_year; - xDayOfWeek = timeStruct.day_of_week; - - // - return result; - } - - // - // Detecting End Of Week ... - bool IsWeekEnd() - { - // - bool result = false; - - // - // Retrieve Current Time as Struct ... - MqlDateTime timeStruct = GetCurrentTime(); - - // - // Check WeekEnd ... - // Since Week Starts From Monday in Forex World ... - // we Calculate End of Week by 5-Friday ... - result = - xDayOfWeek != -1 && - timeStruct.day_of_week == 5 && - timeStruct.hour == 23 && - timeStruct.min == 59 && - timeStruct.sec == 59; - - // - return result; - } - - // - // Detecting New Month ... - bool IsNewMonth() - { - // - bool result = false; - - // - // Retrieve Current Time as Struct ... - MqlDateTime timeStruct = GetCurrentTime(); - - // - // Check Houre ... - result = timeStruct.mon != xMonth; - if (result) - { - xMonth = timeStruct.mon; - } - - // - return result; - } -}; - -// -// Tracking Bars on Specified Environment ... -struct XBarTracker -{ - // - string symbol; // Tracking Symbol - ENUM_TIMEFRAMES period; // Tracking Time Frame - - // - int lastTrackedBar; // Last Tracked Bar ... - - // - bool waitsUntilNext; // Waits Until Next Bar ... - - // - // Constructor ... - XBarTracker() - { - Clean(); - } - - // - // Initializer ... - bool Init( - string mSymbol = NULL, // Trading Symbol - ENUM_TIMEFRAMES mPeriod = NULL // Trading Period - ) - { - // - bool result = false; - - // - mSymbol = NormalizeSymbol(mSymbol); - mPeriod = NormalizePeriod(mPeriod); - - // - this.symbol = mSymbol; - this.period = mPeriod; - - // - this.lastTrackedBar = 0; - - // - result = true; - - // - return result; - } - - // - // Retrieve all Bars ... - int CountBars() - { - // - return iBars( - symbol, - period - // - ); - } - - // - // Check if it's New Bar ... - bool IsNewBar() - { - // - bool result = false; - - // - int currentBars = CountBars(); - - // - result = currentBars > lastTrackedBar; - if (result) - { - lastTrackedBar = currentBars; - } - - // - return result; - } - - // - bool CanProcessBar() - { - // - bool _isInTestMode = IsRunningOnTestMode(); - - // - bool isNewBar = IsNewBar(); - - // - bool result = - _isInTestMode - ? isNewBar - : !waitsUntilNext - ? true - : isNewBar; - if (result && waitsUntilNext) - { - waitsUntilNext = false; - } - - // - return result; - } - - // - void Waits() - { - this.waitsUntilNext = true; - } - - // - // Tools ... - void Clean() - { - // - symbol = NormalizeSymbol(NULL); - period = NormalizePeriod(NULL); - - // - ZeroMemory(this); - } - - // - bool GetBar( - XOHCL &bar, - int index = 0 // - ) - { - // - bool result = false; - - // - result = bar.Init( - symbol, - period, - index // - ); - - // - return result; - } - - // - bool GetBar( - XOHCL &bar, - datetime time = NULL // - ) - { - // - bool result = false; - - // - NormalizeTime(time); - - // - int barIndex = iBarShift( - symbol, - period, - time, - false // - ); - - // - result = barIndex >= 0; - if (!result) - { - return result; - } - - // - result = bar.Init( - symbol, - period, - barIndex // - ); - - // - return result; - } - - // - int Index(datetime time = NULL) - { - // - int result = 0; - - // - NormalizeTime(time); - - // - result = iBarShift( - symbol, - period, - time, - false // - ); - - // - return result; - } -}; - -// -// Model a Market Cycle ... -struct XMarketCycle -{ - // - // Props ... - - // - string prefix; // Prefix Trag ... - - // - string symbol; // Market Symbol ... - - // - ENUM_TIMEFRAMES period; // Period of Cycle ... - ENUM_X_PERIOD_METHOD method; // Period Selection Method ... - ENUM_X_MARKET_CYCLES cycle; // Cycles of MArket ... - - // - int length; // Number Of Candles per Current Time Frame ... - ENUM_TIMEFRAMES hostPeriod; // Current Time Frame ... - - // - datetime lastStart; // Last Candle Bar Time ... - - // - XBarTracker barTracker; // Bar Tracker ... - XBarRemainsTime remains; // Current Bar Remains Model ... - - // - // Constructor ... - XMarketCycle() - { - Clean(); - } - - // - // Init Cycle ... - bool Init( - string mSymbol, // Trading Symbol - ENUM_TIMEFRAMES mHostPeriod, // Host Period - ENUM_X_MARKET_CYCLES mCycle, // Init Cycle - string mPrefix = "" // Prefix - ) - { - // - bool result = false; - - // - mSymbol = NormalizeSymbol(mSymbol); - mHostPeriod = NormalizePeriod(mHostPeriod); - - // - result = IsValid(mCycle); - if (!result) - { - return result; - } - - // - this.cycle = mCycle; - - // - // Set Automatically Prefix ... - if (StringLen(mPrefix) == 0) - { - this.prefix = ToString(cycle); - } - - // - result = IsValid( - method, - period // - ); - if (!result) - { - return result; - } - - // - this.symbol = mSymbol; - this.hostPeriod = mHostPeriod; - - // - // Find Cycle Period ... - if (method == X_PERIOD_AUTO) - { - // - // Select Period ... - this.period = GetCyclePeriod( - this.cycle, - this.hostPeriod); - } - - // - // Set Prefix if Provided ... - if (StringLen(mPrefix) > 0) - { - this.prefix = mPrefix; - } - - // - // Calculate Required Info ... - - // - // Length ... - this.length = PeriodSeconds(this.period) / PeriodSeconds(this.hostPeriod); - - // - // Update Additional Data ... - result = this.Update(0); - - // - return result; - } - - // - bool Init( - string mSymbol, // Trading Symbol - ENUM_TIMEFRAMES mHostPeriod, // Host Period - ENUM_X_MARKET_CYCLES mCycle, // Init Cycle - ENUM_X_PERIOD_METHOD mMethod, // Period Selection Method - ENUM_TIMEFRAMES mPeriod, // Provided Period - string mPrefix = "" // Prefix - ) - { - // - this.period = mPeriod; - this.method = mMethod; - - // - return Init( - mSymbol, - mHostPeriod, - mCycle, - mPrefix - // - ); - } - - // - // Tools ... - - // - // Cleanup ... - void Clean() - { - // - length = 0; - lastStart = 0; - - // - cycle = NULL; - prefix = NULL; - symbol = NULL; - period = NULL; - method = NULL; - hostPeriod = NULL; - - // - remains.Clean(); - barTracker.Clean(); - - // - ZeroMemory(this); - } - - // - // Check Structure Valid ... - bool IsValid() - { - // - bool result = false; - - // - result = IsValid( - method, - period); - if (!result) - { - return result; - } - - // - result = - // - length > 0 && - symbol != NULL && - period != NULL && - method != NULL && - hostPeriod != NULL && - method != X_PERIOD_NOTHING - // - ; - - // - return result; - } - - // - // Update Market Cycle Additional Info ... - bool Update(int hostBarIndex) - { - // - bool result = false; - - // - result = this.IsValid(); - if (!result) - { - return result; - } - - // - // Init Remains ... - result = remains.Init( - this.symbol, - this.period); - if (!result) - { - return result; - } - - // - // Init Bar Tracker ... - result = barTracker.Init( - this.symbol, - this.period); - if (!result) - { - return result; - } - - // - return result; - } - - // - // Count Bars ... - int CountBars() - { - // - int result = 0; - - // - if (!IsValid()) - { - return result; - } - - // - result = barTracker.CountBars(); - - // - return result; - } - - // - // Check New Bar ... - bool IsNewBar() - { - // - bool result = false; - - // - if (!IsValid()) - { - return result; - } - - // - result = barTracker.IsNewBar(); - - // - return result; - } - - // - // Retrieve Current Bar Index based on Host Period bar Index ... - int GetBarIndex(int barIndex) - { - // - int result = 0; - - // - if (!IsValid()) - { - return result; - } - - // - if (barIndex < 0) - { - return result; - } - - // - int totalBars = CountBars(); - if (barIndex >= totalBars) - { - // - result = totalBars - 1; - return result; - } - - // - datetime hostBarTime = iTime( - this.symbol, - this.hostPeriod, - barIndex - // - ); - - // - result = iBarShift( - this.symbol, - this.period, - hostBarTime - // - ); - - // - return result; - } - - // - // Retrieve Current Cycles Specific Bar ... - XOHCL GetBar(int barIndex) - { - // - if (barIndex < 0) - { - barIndex = 0; - } - - // - int totalBars = CountBars(); - if (barIndex >= totalBars) - { - barIndex = totalBars - 1; - } - - // - XOHCL result; - result.Init( - this.symbol, - this.period, - barIndex - // - ); - - // - return result; - } - - // - // Extract Specific Range of Bars ... - // using Start Bar Index ... - int GetBars( - XOHCL &result[], // Hold Result - int from = 0, // Start Bar Index - int count = 1, // Number of Bars - bool forceClean = true // Clean Result Array - ) - { - // - int mResult = 0; - - // - if (from < 0) - { - from = 0; - } - - // - int total = Bars( - symbol, - period); - if (from > total - 2) - { - from = total - 2; - } - - // - if (count < 0) - { - count = 1; - } - - // - int start = from; - int end = start + count; - if (end > total - 1) - { - end = total - 1; - } - - // - if (forceClean) - { - Clean(result); - } - - // - int beforeSize = ArraySize(result); - - // - for (int i = start; i < end; i++) - { - // - XOHCL iBar; - bool isValid = iBar.Init( - symbol, - period, - i - // - ); - - // - if (isValid) - { - // - AddRef( - iBar, - result - // - ); - } - } - - // - int afterSize = ArraySize(result); - - // - mResult = afterSize - beforeSize; - - // - return mResult; - } - - // - // Extract Specific Range of Bars ... - // using Start Bar Time ... - int GetBars( - XOHCL &result[], // Hold Result - datetime from = NULL, // Start Bar Time - int count = 1, // Number of Bars - bool forceClean = true // Clean Result Array - ) - { - // - from = NormalizeTime(from); - - // - int barIndex = iBarShift( - symbol, - period, - from, - false - // - ); - - // - return GetBars( - result, - symbol, - period, - barIndex, - count, - forceClean - // - ); - } - - // - // Retrieve Bar Time ... - datetime GetBarTime(int barIndex) - { - // - datetime result = NULL; - - // - if (!IsValid()) - { - return result; - } - - // - if (barIndex < 0) - { - barIndex = 0; - } - - // - int totalBars = CountBars(); - if (barIndex >= totalBars) - { - barIndex = totalBars - 1; - } - - // - result = iTime( - this.symbol, - this.period, - barIndex - // - ); - - // - return result; - } - - // - // Find Chart ID ... - ulong GetChartID() - { - // - ulong result = 0; - - // - long firstChart = ChartFirst(); - result = firstChart; - - // - while (result >= 0) - { - // - string chSymbol = ChartSymbol(result); - ENUM_TIMEFRAMES chPeriod = ChartPeriod(result); - - // - bool isOwnChart = - // - symbol == chSymbol && - period == chPeriod - // - ; - if (isOwnChart) - { - break; - } - - // - result = ChartNext(result); - if (result < 0) - { - break; - } - } - - // - return result; - } - - // - // Create and String Representation for Unique Taging ... - string ToString() - { - // - string result = ""; - - // - if (!IsValid()) - { - return result; - } - - // - result = - GetTypeName(this) + "(" + - "PRFX(" + this.prefix + ")" + - "SMBL(" + this.symbol + ")" + - "CYC(" + ToString(this.cycle) + ")" + - "PRD(" + ToString(this.period) + ")" + - "PRDHST(" + ToString(this.hostPeriod) + ")" + - "MTH(" + EnumToString(this.method) + ")" + - ")"; - - // - return result; - } - - // - // Here we Produce a Summary brief of - // state of Cycle ... - string GenerateSummary() - { - // - string result = ""; - - // - bool hasPrefix = - StringLen(this.prefix) > 0 && - this.prefix != ToString(this.cycle); - result += (hasPrefix ? this.prefix + "[" : "") + - ToString(this.cycle) + - (hasPrefix ? "]" : "") + "\n"; - - // - result += " - PR: " + ToString(this.period) + "\n"; - - // - XOHCL cBar = GetBar(0); - - // - result += " - State: " + (cBar.IsBullish() ? "Bullish" : cBar.IsBearish() ? "Bearish" - : "Neutural"); - - // - return result; - } -}; - -// -// Linear Regression ... - -// -struct XLinearRegressionWorkStruct -{ - // - struct sDataStruct - { - // - double value; - double sumY; - double sumXY; - }; - - // - sDataStruct data[]; - - // - int dataSize; - int period; - double sumX; - double sumXX; - double divisor; - - // - // Constructor ... - XLinearRegressionWorkStruct() - : dataSize(-1), period(-1) - { - } -}; - -// -struct XLinearRegression -{ - // - XLinearRegressionWorkStruct m_work; - - // - // Calculate Linear Regression ... - double Calculate( - double value, - int period, - double &_slope, - double &_intercept, - int r, - int bars // - ) - { - // - if (m_work.dataSize <= bars) - { - m_work.dataSize = ArrayResize(m_work.data, bars + 500, 2000); - } - - // - if (period < 1) - { - period = 1; - } - - // - if (m_work.period != (int)period) - { - // - m_work.period = (int)period; - m_work.sumX = m_work.period * (m_work.period - 1.0) / 2.0; - m_work.sumXX = m_work.period * (m_work.period - 1.0) * (2.0 * m_work.period - 1.0) / 6.0; - m_work.divisor = m_work.sumX * m_work.sumX - m_work.period * m_work.sumXX; - - // - if (m_work.divisor) - { - m_work.divisor = 1.0 / m_work.divisor; - } - } - - // - m_work.data[r].value = value; - - // - if (r >= m_work.period) - { - // - m_work.data[r].sumY = m_work.data[r - 1].sumY + value - m_work.data[r - m_work.period].value; - m_work.data[r].sumXY = m_work.data[r - 1].sumXY + m_work.data[r].sumY - m_work.data[r - m_work.period].value * (m_work.period - 1.0) - value; - } - else - { - // - m_work.data[r].sumY = value; - m_work.data[r].sumXY = 0; - - // - for (int _k = 1; _k < m_work.period && r >= _k; _k++) - { - // - m_work.data[r].sumY += m_work.data[r - _k].value; - m_work.data[r].sumXY += _k * m_work.data[r - _k].value; - } - } - - // - _slope = (m_work.period * m_work.data[r].sumXY - m_work.sumX * m_work.data[r].sumY) * m_work.divisor; - _intercept = (m_work.data[r].sumY - _slope * m_work.sumX) / (double)m_work.period; - - // - double result = (_intercept + _slope * (m_work.period - 1.0)); - - // - return result; - } - - // -}; - -// -// Use To Parse Symbols for -// Ignore Brokers Additional Suffixes ... -struct XSymbolParser -{ - // - string version; // Temp ... - - // - // Symbol Parsing ... - - // - // Forext ... - - // - bool IsEURUSD(string symbol) - { - // - string symbolIdentifiers[] = { - "EUR", - "USD" // - }; - - // - bool result = Contains( - symbolIdentifiers, - symbol // - ); - - // - return result; - } - - // - bool IsUSDJPY(string symbol) - { - // - string symbolIdentifiers[] = { - "USD", - "JPY" // - }; - - // - bool result = Contains( - symbolIdentifiers, - symbol // - ); - - // - return result; - } - - // - bool IsEURJPY(string symbol) - { - // - string symbolIdentifiers[] = { - "EUR", - "JPY" // - }; - - // - bool result = Contains( - symbolIdentifiers, - symbol // - ); - - // - return result; - } - - // - bool IsUSDCHF(string symbol) - { - // - string symbolIdentifiers[] = { - "USD", - "CHF" // - }; - - // - bool result = Contains( - symbolIdentifiers, - symbol // - ); - - // - return result; - } - - // - bool IsEURCHF(string symbol) - { - // - string symbolIdentifiers[] = { - "EUR", - "CHF" // - }; - - // - bool result = Contains( - symbolIdentifiers, - symbol // - ); - - // - return result; - } - - // - bool IsGBPUSD(string symbol) - { - // - string symbolIdentifiers[] = { - "GBP", - "USD" // - }; - - // - bool result = Contains( - symbolIdentifiers, - symbol // - ); - - // - return result; - } - - // - bool IsEURGBP(string symbol) - { - // - string symbolIdentifiers[] = { - "EUR", - "GBP" // - }; - - // - bool result = Contains( - symbolIdentifiers, - symbol // - ); - - // - return result; - } - - // - bool IsAUDUSD(string symbol) - { - // - string symbolIdentifiers[] = { - "AUD", - "USD" // - }; - - // - bool result = Contains( - symbolIdentifiers, - symbol // - ); - - // - return result; - } - - // - bool IsEURAUD(string symbol) - { - // - string symbolIdentifiers[] = { - "EUR", - "AUD" // - }; - - // - bool result = Contains( - symbolIdentifiers, - symbol // - ); - - // - return result; - } - - // - bool IsUSDCAD(string symbol) - { - // - string symbolIdentifiers[] = { - "USD", - "CAD" // - }; - - // - bool result = Contains( - symbolIdentifiers, - symbol // - ); - - // - return result; - } - - // - bool IsEURCAD(string symbol) - { - // - string symbolIdentifiers[] = { - "EUR", - "CAD" // - }; - - // - bool result = Contains( - symbolIdentifiers, - symbol // - ); - - // - return result; - } - - // - bool IsNZDUSD(string symbol) - { - // - string symbolIdentifiers[] = { - "NZD", - "USD" // - }; - - // - bool result = Contains( - symbolIdentifiers, - symbol // - ); - - // - return result; - } - - // - bool IsEURNZD(string symbol) - { - // - string symbolIdentifiers[] = { - "EUR", - "NZD" // - }; - - // - bool result = Contains( - symbolIdentifiers, - symbol // - ); - - // - return result; - } - - // - // Metals ... - - // - bool IsXAUUSD(string symbol) - { - // - string symbolIdentifiers[] = { - "XAU", - "USD" // - }; - - // - bool result = Contains( - symbolIdentifiers, - symbol // - ); - - // - return result; - } - - // - bool IsXAGUSD(string symbol) - { - // - string symbolIdentifiers[] = { - "XAG", - "USD" // - }; - - // - bool result = Contains( - symbolIdentifiers, - symbol // - ); - - // - return result; - } - - // - // Indexes ... - - // - bool IsDowJones(string symbol) - { - // - bool result = Contains( - "DowJones30", - symbol // - ); - - // - return result; - } - - // - // Oil ... - - // - bool IsBrent(string symbol) - { - // - bool result = Contains( - "BRENT", - symbol // - ); - - // - return result; - } - - // - // Symbol Finder ... - string GetEURUSDSymbol() - { - // - string result = NULL; - - // - string symbols[]; - int symbolsCount = GetAllSymbols( - symbols // - ); - if (!IsValidSize(symbolsCount)) - { - return result; - } - - // - for (int i = 0; i < symbolsCount; i++) - { - // - string iSymbol = symbols[i]; - if (IsEURUSD(iSymbol)) - { - // - result = iSymbol; - break; - } - } - - // - return result; - } -}; - -// -struct XSymbolSessionParser -{ - // - string version; // Temp ... - - // - // Check Market Is Open for Specific Symbol - // in Current Time ... - bool CanTrade( - string symbol // Trading Symbol - ) - { - // - bool result = false; - - // - result = IsValid(symbol); - if (!result) - { - return result; - } - - // - MqlDateTime timeStruct; - result = TimeCurrent(timeStruct); - if (!result) - { - return result; - } - - // - ENUM_DAY_OF_WEEK dayOfWeek = (ENUM_DAY_OF_WEEK)timeStruct.day_of_week; - - // - datetime cTime = TimeCurrent(); - - // - datetime from; - datetime to; - result = SymbolInfoSessionTrade( - symbol, - dayOfWeek, - 0, // Session Index ... - from, - to // - ); - if (!result) - { - return result; - } - - // - result = cTime > from && cTime < to; - - // - return result; - } -}; - -// -// Parsing Market Names ... -struct XMarketParser -{ - // - string _version; // Temp ... - - // - bool IsIngot(string market) - { - // - bool result = false; - - // - // result = IsValid(market) && - // market == ""; - - // - return result; - } - - // - bool IsErrante(string market) - { - // - bool result = false; - - // - // result = IsValid(market) && - // market == ""; - - // - return result; - } - - // - bool IsAMarkets(string market) - { - // - bool result = false; - - // - result = IsValid(market) && - market == "AMarkets LLC"; - - // - return result; - } - - // - bool IsIFCMarkets(string market) - { - // - bool result = false; - - // - // result = IsValid(market) && - // market == ""; - - // - return result; - } - - // - bool IsOtetMarkets(string market) - { - // - bool result = false; - - // - // result = IsValid(market) && - // market == ""; - - // - return result; - } - - // -}; - -// -struct XPoint -{ - // - // Props ... - double value; - datetime at; - - // - XPoint() - { - Clean(); - } - - // - // Tools ... - - // - void Clean() - { - // - value = 0; - at = NULL; - - // - ZeroMemory(this); - } - - // - bool IsValid() - { - // - return value > 0 && - IsValid(at); - } - - // -}; - -// -// Specified Swing Point ... -struct XSwingPoint -{ - // - // Props ... - string symbol; - ENUM_TIMEFRAMES period; - - // - double swing; - datetime time; - ENUM_X_SWING_TYPE type; - - // - // Constructor ... - XSwingPoint() - { - Clean(); - } - - // - // Tools ... - - /** - * Cleanup Model ... - */ - void Clean() - { - // - swing = 0; - time = NULL; - - // - symbol = NULL; - period = NULL; - - // - type = X_NO_SWING; - } - - /** - * Validate Model ... - * - * @return ( bool ) - */ - bool IsValid() - { - // - bool result = false; - - // - result = - swing > 0 && - IsValid(time) && - IsValid(symbol) && - IsValid(period) && - type != X_NO_SWING; - - // - return result; - } - - /** - * Check Swing is Low or not ... - * - * @return ( bool ) - */ - bool IsSwingLow() - { - return type == X_SWING_LOW; - } - - /** - * Check Swing is High or not ... - * - * @return ( bool ) - */ - bool IsSwingHigh() - { - return type == X_SWING_HIGH; - } -}; - -/** - * Extract values of swings from specified Collection ... - * - * @param swings: XSwingPoint instance Collection ... - * @param values: double Collection ... - * - * @return ( int ) - */ -int ExtractSwings( - XSwingPoint &swings[], - double &values[] // -) -{ - // - int result = 0; - - // - Clean(values); - - // - int count = ArraySize(swings); - if (!IsValidSize(count)) - { - return result; - } - - // - for (int i = 0; i < count; i++) - { - // - Add( - swings[i].swing, - values // - ); - } - - // - result = ArraySize(values); - - // - return result; -} - // // Consolidation Zone ... struct XConsolidationZone @@ -3880,7030 +154,4 @@ struct XConsolidationZone // }; -// -// Functions ... - -// -// Validators ... - -// -// Validate an String has length and not NULL ... -bool IsValid(string value) -{ - // - bool result = false; - - // - result = - // - value != NULL && - StringLen(value) > 0 - // - ; - - // - return result; -} -bool IsSpecifiedValid(string value) -{ - return IsValid(value); -} - -// -// Validate a Date ... -bool IsValid(datetime value) -{ - // - bool result = false; - - // - result = NotEmpty(value) && value != NULL; - - // - return result; -} -bool IsSpecifiedValid(datetime value) -{ - return IsValid(value); -} - -// -// Validate a Period Param ... -bool IsValid(ENUM_TIMEFRAMES value) -{ - // - bool result = false; - - // - result = - // - value != NULL - // - ; - - // - return result; -} -bool IsSpecifiedValid(ENUM_TIMEFRAMES value) -{ - // - return IsValid(value); -} - -// -// Validate Specified Cycle ... -bool IsValid(ENUM_X_MARKET_CYCLES value) -{ - // - bool result = false; - - // - result = - // - value != NULL && - value != X_MARKET_CYCLE_UNKNOWN - // - ; - - // - return result; -} - -// -// Validate Specific Period Mode ... -bool IsValid( - ENUM_X_PERIOD_METHOD mMethod, // Period Select Method - ENUM_TIMEFRAMES mPeriod // Selected Period -) -{ - // - bool result = false; - - // - result = - // - mMethod == X_PERIOD_NOTHING - ? false - : mMethod == X_PERIOD_MANUALLY - ? mPeriod != NULL - : mMethod == X_PERIOD_AUTO - ? true - : false - // - ; - - // - return result; -} - -// -bool IsSpecifiedValid( - ENUM_X_PERIOD_METHOD mMethod, // Period Select Method - ENUM_TIMEFRAMES mPeriod // Selected Period -) -{ - return IsValid(mMethod, - mPeriod // - ); -} - -// -// Validate Swing Mode ... -bool IsValid(ENUM_X_SWING_TYPE value) -{ - // - bool result = false; - - // - result = - // - value == X_SWING_HIGH || - value == X_SWING_LOW - // - ; - - // - return result; -} - -// -// As IS ... - -// -// Determine a Position type is Long or not ... -bool IsLong(ENUM_POSITION_TYPE type) -{ - // - bool result = type == POSITION_TYPE_BUY; - - // - return result; -} -bool IsLong(ENUM_ORDER_TYPE type) -{ - // - bool result = type == ORDER_TYPE_BUY; - - // - return result; -} - -// -// Determine a Position type is Short or not ... -bool IsShort(ENUM_POSITION_TYPE type) -{ - // - bool result = type == POSITION_TYPE_SELL; - - // - return result; -} -bool IsShort(ENUM_ORDER_TYPE type) -{ - // - bool result = type == ORDER_TYPE_SELL; - - // - return result; -} - -// -// Retrieve Opposit Direction Type ... -ENUM_POSITION_TYPE GetOpposit(ENUM_POSITION_TYPE type) -{ - // - ENUM_POSITION_TYPE result = NULL; - - // - bool isLong = IsLong(type); - result = isLong - ? POSITION_TYPE_SELL - : POSITION_TYPE_BUY; - - // - return result; -} -ENUM_ORDER_TYPE GetOpposit(ENUM_ORDER_TYPE type) -{ - // - ENUM_ORDER_TYPE result = NULL; - - // - bool isLong = IsLong(type); - result = isLong - ? ORDER_TYPE_SELL - : ORDER_TYPE_BUY; - - // - return result; -} - -// -string ToString(ENUM_POSITION_TYPE value) -{ - // - string result = NULL; - - // - result = - // - IsLong(value) - ? "Long" - : "Short" - // - ; - - // - return result; -} -string ToString(ENUM_ORDER_TYPE value) -{ - // - string result = NULL; - - // - result = - // - IsLong(value) - ? "Long" - : "Short" - // - ; - - // - return result; -} - -// -// Check Expert Running in Testing Mode or not ... -bool IsRunningOnTestMode() -{ - // - bool result = false; - - // - // check programm mode ... - result = MQL5InfoInteger(MQL5_TESTING); - - // - return result; -} - -// -// Find Chart ID ... -long FindChartID( - string mSymbol = NULL, // Trading Symbol - ENUM_TIMEFRAMES mPeriod = NULL // Trading Period -) -{ - // - long result = ChartFirst(); - long first = result; - - // - while (result > 0) - { - // - string chSymbol = ChartSymbol(result); - ENUM_TIMEFRAMES chPeriod = ChartPeriod(result); - - // - bool isOwn = - // - chSymbol == mSymbol && - chPeriod == mPeriod - // - ; - if (isOwn) - { - break; - } - - // - result = ChartNext(result); - } - - // - return result; -} - -// -// Normalizers ... - -// -// Check a Symbol provided or not ... -// if not use Default ... -string NormalizeSymbol(string value) -{ - // - string result = value; - - // - if (!IsValid(result)) - { - result = _Symbol; - } - - // - return result; -} - -// -// Check a Datetime provided or not ... -// if not use Current ... -datetime NormalizeTime(datetime value) -{ - // - datetime result = value; - - // - if (!IsValid(result)) - { - result = TimeCurrent(); - } - - // - return result; -} - -// -// Check a Period provided or not ... -// if not use Default ... -ENUM_TIMEFRAMES NormalizePeriod(ENUM_TIMEFRAMES value) -{ - // - ENUM_TIMEFRAMES result = value; - - // - if (!IsValid(value)) - { - result = _Period; - } - - // - return result; -} - -// -// Normalize Cycle ... -ENUM_X_MARKET_CYCLES NormalizeCycle(ENUM_X_MARKET_CYCLES value) -{ - // - ENUM_X_MARKET_CYCLES result = value; - - // - if (!IsValid(result)) - { - result = X_MARKET_CYCLE_SHORT; - } - - // - return value; -} - -// -// Validate a Buffer Size for Looping or etc ... -bool IsValidSize(int size) -{ - // - bool result = size > 0; - - // - return result; -} - -template -bool IsValidSize(T &buffer[]) -{ - // - bool result = false; - - // - result = - // - IsValidSize(ArraySize(buffer)) - // - ; - - // - return result; -} - -// -// Check a Given Index is Valid or not ... -bool IsValidIndex(int index) -{ - return index >= 0; -} - -// -// Normalize Index Based On Specified Buffer ... -template -void NormalizeIndex( - int &index, - T &buffer[] // -) -{ - // - int bufferSize = ArraySize(buffer); - - // - if (bufferSize <= 0) - { - index = 0; - } - - // - if (index <= 0) - { - index = 0; - } - - // - if (index > bufferSize - 1) - { - index = bufferSize - 1; - } -} - -// -// Normalize Start and Count based on Specified Buffer ... -template -void NormalizeCount( - int &start, - int &count, - T &buffer[] // -) -{ - // - // Validate Buffer Size ... - int bufferSize = ArraySize(buffer); - if (!IsValidSize(bufferSize)) - { - return; - } - - // - // Normalization Start ... - NormalizeIndex( - start, - buffer // - ); - - // - if (count < start) - { - count = (start - count); - } - - // - // Normalization Count ... - - // - if (count < 0) - { - count = start; - } - - // - if (count > bufferSize) - { - count = bufferSize; - } -} - -// -// Normalize a give Volume ... -double NormalizeVolume( - double mVolume, // desired volume to normalize - string mSymbol = NULL, // Trading Symbol - int mLength = 2 // Length of Digits -) -{ - // - double result = mVolume; - - // - mSymbol = NormalizeSymbol(mSymbol); - - // - // Normalize Digits ... - int digits = GetDigits(mSymbol); - - // - mLength = - mLength == 0 || mLength > digits - ? digits - : MathMin(mLength, digits); - - // - // Normalize Volume ... - result = NormalizeDouble(result, mLength); - - // - double maxAvailableVolume = SymbolInfoDouble(mSymbol, SYMBOL_VOLUME_MAX); - double minAvailableVolume = SymbolInfoDouble(mSymbol, SYMBOL_VOLUME_MIN); - - // - // Validate Result ... - if (result > maxAvailableVolume) - { - result = maxAvailableVolume; - } - else if (result < minAvailableVolume) - { - result = minAvailableVolume; - } - - // - return result; -} - -// -// Normallize Price ... -double NormalizePrice( - double mPrice, // desired Price for normalization - string mSymbol = NULL // Trading Symbol -) -{ - // - double result = 0; - - // - mSymbol = NormalizeSymbol(mSymbol); - - // - double tickSize = 0; - result = SymbolInfoDouble(mSymbol, SYMBOL_TRADE_TICK_SIZE, tickSize); - - // - int digits = GetDigits(mSymbol); - result = NormalizeDouble(MathRound(mPrice / tickSize) * tickSize, digits); - - // - return result; -} - -// -// Prices ... - -// -// Retrieve Ask Price ... -double GetAsk( - string mSymbol = NULL // Trading Symbol -) -{ - // - mSymbol = NormalizeSymbol(mSymbol); - - // - double result = SymbolInfoDouble(mSymbol, SYMBOL_ASK); - - // - return result; -} - -// -// Retrieve Bid Price ... -double GetBid( - string mSymbol = NULL // Trading Symbol -) -{ - // - mSymbol = NormalizeSymbol(mSymbol); - - // - double result = SymbolInfoDouble(mSymbol, SYMBOL_BID); - - // - return result; -} - -// -// Retrieve Spread Price ... -double GetSpread( - string mSymbol = NULL // Trading Symbol -) -{ - // - mSymbol = NormalizeSymbol(mSymbol); - - // - double ask = GetAsk(mSymbol); - double bid = GetBid(mSymbol); - - // - double result = MathAbs(ask - bid); - - // - return result; -} - -// -// Retrieve Point Value ... -double GetPoints( - string mSymbol = NULL // Trading Symbol -) -{ - // - mSymbol = NormalizeSymbol(mSymbol); - - // - double result = SymbolInfoDouble(mSymbol, SYMBOL_POINT); - - // - return result; -} - -// -// Retrieve Point Digits ... -int GetDigits( - string mSymbol = NULL // Trading Symbol -) -{ - // - mSymbol = NormalizeSymbol(mSymbol); - - // - int result = (int)SymbolInfoInteger(mSymbol, SYMBOL_DIGITS); - - // - return result; -} - -// -// Get Digits of Specified Double Value ... -int GetDigits(double num) -{ - // - int d = 0; - double p = 1; - while (MathRound(num * p) / p != num) - { - p = MathPow(10, ++d); - } - - // - return d; -} - -// -// Retrieve Entry Price ... -double GetEntry( - string mSymbol = NULL, // Trading Symbol - ENUM_POSITION_TYPE type = POSITION_TYPE_BUY // Get entry price for Which direction trade ... -) -{ - // - double result = 0; - - // - mSymbol = NormalizeSymbol(mSymbol); - - // - result = - IsLong(type) - ? GetAsk(mSymbol) - : GetBid(mSymbol); - result = NormalizePrice(result, mSymbol); - - // - return result; -} -double GetEntry( - string mSymbol = NULL, // Trading Symbol - ENUM_X_DIRECTION type = X_DIRECTION_BULLISH // Get entry price for Which direction trade ... -) -{ - // - double result = 0; - - // - mSymbol = NormalizeSymbol(mSymbol); - - // - result = - IsBullish(type) - ? GetAsk(mSymbol) - : GetBid(mSymbol); - result = NormalizePrice(result, mSymbol); - - // - return result; -} - -// -// Retrieve Exit Price ... -double GetExit( - string mSymbol = NULL, // Trading Symbol - ENUM_POSITION_TYPE type = POSITION_TYPE_BUY // Get entry price for Which direction trade ... -) -{ - // - double result = 0; - - // - mSymbol = NormalizeSymbol(mSymbol); - - // - result = - IsLong(type) - ? GetBid(mSymbol) - : GetAsk(mSymbol); - result = NormalizePrice(result, mSymbol); - - // - return result; -} -double GetExit( - string mSymbol = NULL, // Trading Symbol - ENUM_X_DIRECTION type = X_DIRECTION_BULLISH // Get entry price for Which direction trade ... -) -{ - // - double result = 0; - - // - mSymbol = NormalizeSymbol(mSymbol); - - // - result = - IsBullish(type) - ? GetBid(mSymbol) - : GetAsk(mSymbol); - result = NormalizePrice(result, mSymbol); - - // - return result; -} - -// -// Get 1 Pip in Price Value ... -double GetPipPrice( - string mSymbol = NULL // Trading Symbol -) -{ - // - mSymbol = NormalizeSymbol(mSymbol); - - // - double symbolPoint = GetPoints(mSymbol); - int symbolDigits = GetDigits(mSymbol); - - // - double result = symbolPoint; - if (symbolDigits == 3 || symbolDigits == 5) - { - result *= 10; - } - - // - return result; -} - -// -// Converts Pips To Price ... -double PipsToPrice( - double mPips, // pips amount - string mSymbol = NULL // Trading Symbol -) -{ - // - mSymbol = NormalizeSymbol(mSymbol); - - // - int digits = GetDigits(mSymbol); - double pipValue = GetPipPrice(mSymbol); - double result = mPips * pipValue; - - // - result = NormalizePrice(result, mSymbol); - - // - return result; -} - -// -// Converts Price to Pips ... -double PriceToPips( - double mPrice, // the price amount which required to calculate - string mSymbol = NULL // Trading Symbol -) -{ - // - mSymbol = NormalizeSymbol(mSymbol); - mPrice = NormalizePrice(mPrice, mSymbol); - - // - int digits = GetDigits(mSymbol); - double pipPrice = GetPipPrice(mSymbol); - - // - double result = mPrice / pipPrice; - - // - result = NormalizeDouble(result, digits); - - // - return result; -} - -// -// Convert Price to Point ... -double PriceToPoint( - double price, // the price amount which required to calculate - string mSymbol = NULL // Trading Symbol -) -{ - // - double result = 0; - - // - mSymbol = NormalizeSymbol(mSymbol); - price = NormalizePrice(price, mSymbol); - - // - double point = GetPoints(mSymbol); - result = price / point; - - // - return result; -} - -// -// Converts Point to Price ... -double PointToPrice( - double points, // Points Amount - string mSymbol = NULL // Trading Symbol -) -{ - // - double result = 0; - - // - mSymbol = NormalizeSymbol(mSymbol); - - // - double point = GetPoints(mSymbol); - result = points * point; - - // - result = NormalizePrice(result, mSymbol); - - // - return result; -} - -// -// Converts Series Mode to XPRICE ... -ENUM_X_PRICE ToPrice( - ENUM_SERIESMODE mMode // Specified Series Mode ... -) -{ - // - ENUM_X_PRICE result = X_PRICE_CLOSE; - - // - switch (mMode) - { - // - // High ... - case MODE_HIGH: - result = X_PRICE_HIGH; - break; - - // - // Open ... - case MODE_OPEN: - result = X_PRICE_OPEN; - break; - - // - // Low ... - case MODE_LOW: - result = X_PRICE_LOW; - break; - - // - // Close ... - // Default ... - case MODE_CLOSE: - default: - result = X_PRICE_CLOSE; - break; - } - - // - return result; -} - -// -// Retrieve Applied Price ... -template -double GetAppliedPrice( - ENUM_APPLIED_PRICE tprice, // Type of Price Selection - T &open[], // Open Prices - T &high[], // High Preices - T &low[], // Low Prices - T &close[], // Close Prices - int i // Bar Index -) -{ - switch (tprice) - { - case PRICE_CLOSE: - return (close[i]); - case PRICE_OPEN: - return (open[i]); - case PRICE_HIGH: - return (high[i]); - case PRICE_LOW: - return (low[i]); - case PRICE_MEDIAN: - return ((high[i] + low[i]) / 2.0); - case PRICE_TYPICAL: - return ((high[i] + low[i] + close[i]) / 3.0); - case PRICE_WEIGHTED: - return ((high[i] + low[i] + close[i] + close[i]) / 4.0); - } - return (0); -} - -// -double iGetPrice( - int tprice, - double open, - double high, - const double low, - const double close // -) -{ - // - switch (tprice) - { - case PRICE_CLOSE: - return (close); - case PRICE_OPEN: - return (open); - case PRICE_HIGH: - return (high); - case PRICE_LOW: - return (low); - case PRICE_MEDIAN: - return ((high + low) / 2.0); - case PRICE_TYPICAL: - return ((high + low + close) / 3.0); - case PRICE_WEIGHTED: - return ((high + low + close + close) / 4.0); - } - - // - return (0); -} - -/** - * Calculates Price Change Percentage based on - * Several Params ... - * - * @param _symbol: Symbol ... - * @param _period: Time Frame ... - * @param _from: start Bar Index ... - * @param _length: Length of Bars ... - * - * @return ( double ) - */ -double GetPriceChanged( - string _symbol = NULL, - ENUM_TIMEFRAMES _period = NULL, - int _from = 0, - int _length = 3 // -) -{ - // - double result = 0; - - // - NormalizeSymbol(_symbol); - NormalizePeriod(_period); - - // - if (_from < 0) - { - _from = 0; - } - - // - if (_length < 2) - { - _length = 2; - } - - // - double closes[]; - int copiedCloses = CopyClose( - _symbol, - _period, - _from, - _length, - closes // - ); - if (copiedCloses < _length) - { - return result; - } - ArrayReverse(closes); - - // - double change = (closes[0] - closes[_length - 1]) / closes[_length - 1] * 100; - result = change; - - // - return result; -} - -// -// Calculate TP/SL for Specified Type of Positions ... -void CalculateTPSL( - double &mSL, // Hold SL - double &mTP, // Hold TP - ENUM_POSITION_TYPE mType, // Position Type Long (Buy) / Short (Sell) - double mEntry, // Entry Price - double mR2R = 1, // Provided Risk To Reward Ratio - double slPrice = 0, // Provided SL Price - double tpPrice = 0, // Provided TP Price - double priceToRisk = 0, // If Entry equal to Provided SL Price Risk Point - double priceToReward = 0 // If Entry equal to Provided TP Price Reward Point -) -{ - // - // if Both TP and SL Provided, ignore R2R and Calculate direct ... - // if SL provided, Calculate TP based on Provided R2R ... - // if TP provided, Calculate SL based on Provided R2R ... - // default R2R is set to 1 ... - - // - mSL = 0; - mTP = 0; - - // - bool isLong = IsLong(mType); - - // - // Set Default R2R ... - if (mR2R < 1) - { - mR2R = 1; - } - - // - if (mEntry <= 0 || - (tpPrice <= 0 && slPrice <= 0)) - { - return; - } - - // - double risk = 0; - double reward = 0; - - // - bool canCalculateBasedOnSL = slPrice > 0 && - (isLong - ? slPrice <= mEntry - : slPrice >= mEntry); - - // - bool canCalculateBasedOnTP = tpPrice > 0 && - (isLong - ? tpPrice >= mEntry - : tpPrice <= mEntry); - - // - if (canCalculateBasedOnSL && !canCalculateBasedOnTP) - { - // - risk = MathAbs(mEntry - slPrice); - if (risk == 0) - { - risk = priceToRisk; - } - reward = risk * mR2R; - } - else if (!canCalculateBasedOnSL && canCalculateBasedOnTP) - { - // - reward = MathAbs(mEntry - tpPrice); - if (reward == 0) - { - reward = priceToReward; - } - risk = reward / mR2R; - } - else if (!canCalculateBasedOnSL && !canCalculateBasedOnTP) - { - // - bool canSetTPPrice = isLong - ? tpPrice > mEntry - : tpPrice < mEntry; - if (canSetTPPrice) - { - mTP = tpPrice; - } - - // - bool canSetSLPrice = isLong - ? slPrice < mEntry - : slPrice > mEntry; - if (canSetSLPrice) - { - mSL = slPrice; - } - - // - return; - } - else if (canCalculateBasedOnSL && canCalculateBasedOnTP) - { - // - bool canSetTPPrice = isLong - ? tpPrice > mEntry - : tpPrice < mEntry; - if (canSetTPPrice) - { - mTP = tpPrice; - } - - // - bool canSetSLPrice = isLong - ? slPrice < mEntry - : slPrice > mEntry; - if (canSetSLPrice) - { - mSL = slPrice; - } - - // - return; - } - - // - mTP = isLong - ? mEntry + reward - : mEntry - reward; - - // - mSL = isLong - ? mEntry - risk - : mEntry + risk; -} - -// -bool CalculateTPSLByPoint( - double &mSL, // Hold SL - double &mTP, // Hold TP - ENUM_POSITION_TYPE mType, // Position Type Long (Buy) / Short (Sell) - double mEntry, // Entry Price - double mPointValue, // Point Value - double mR2R = 1, // Provided Risk To Reward Ratio - double slPoint = 0, // Provided SL Point - double tpPoint = 0 // Provided TP Point -) -{ - // - bool result = false; - - // - mSL = 0; - mTP = 0; - - // - bool isLong = IsLong(mType); - - // - // Set Default R2R ... - if (mR2R < 1) - { - mR2R = 1; - } - - // - if (mEntry <= 0 || - mPointValue <= 0 || - (slPoint <= 0 && tpPoint <= 0)) - { - return result; - } - - // - double risk = 0; - double reward = 0; - - // - bool canCalculateBasedOnSL = slPoint > 0; - - // - bool canCalculateBasedOnTP = tpPoint > 0; - - // - if (!canCalculateBasedOnSL && !canCalculateBasedOnTP) - { - return result; - } - - // - if (canCalculateBasedOnSL && canCalculateBasedOnTP) - { - // - reward = tpPoint * mPointValue; - risk = slPoint * mPointValue; - } - else if (!canCalculateBasedOnSL && canCalculateBasedOnTP) - { - // - reward = tpPoint * mPointValue; - risk = reward / mR2R; - } - else if (canCalculateBasedOnSL && !canCalculateBasedOnTP) - { - // - risk = slPoint * mPointValue; - reward = risk * mR2R; - } - - // - result = risk > 0 && reward > 0; - if (!result) - { - return result; - } - - // - mTP = isLong - ? mEntry + reward - : mEntry - reward; - - // - mSL = isLong - ? mEntry - risk - : mEntry + risk; - - // - return result; -} - -// -bool CalculateTPSLByPrice( - double &mSL, // Hold SL - double &mTP, // Hold TP - ENUM_POSITION_TYPE mType, // Position Type Long (Buy) / Short (Sell) - double mEntry, // Entry Price - double mR2R = 1 // Provided Risk To Reward Ratio -) -{ - // - bool result = false; - - // - bool isLong = IsLong(mType); - - // - // Set Default R2R ... - if (mR2R < 1) - { - mR2R = 1; - } - - // - if (mEntry <= 0 || - (mSL <= 0 && mTP <= 0)) - { - return result; - } - - // - double risk = 0; - double reward = 0; - - // - bool canCalculateBasedOnSL = mSL > 0; - bool canCalculateBasedOnTP = mTP > 0; - - // - if ( - !canCalculateBasedOnSL && - !canCalculateBasedOnTP) - { - return result; - } - - // - if (!canCalculateBasedOnSL && canCalculateBasedOnTP) - { - // - reward = MathAbs(mTP - mEntry); - risk = reward / mR2R; - } - else if (canCalculateBasedOnSL && !canCalculateBasedOnTP) - { - // - risk = MathAbs(mEntry - mSL); - reward = risk * mR2R; - } - - // - result = risk > 0 && reward > 0; - if (!result) - { - return result; - } - - // - mTP = isLong - ? mEntry + reward - : mEntry - reward; - - // - mSL = isLong - ? mEntry - risk - : mEntry + risk; - - // - return result; -} - -/** - * Retrieve Current Tick ... - */ -bool GetTick( - string mSymbol, - MqlTick &tick // -) -{ - return SymbolInfoTick(mSymbol, tick); -} - -/** - * Retrieve Tick Entry ... - */ -double GetTickEntry( - MqlTick &mTick, - ENUM_POSITION_TYPE type, - string mSymbol = NULL // -) -{ - // - double result = 0; - - // - mSymbol = NormalizeSymbol(mSymbol); - - // - result = - IsLong(type) - ? mTick.ask - : mTick.bid; - result = NormalizePrice(result, mSymbol); - - // - return result; -} - -/** - * Retrieve Tick Exit ... - */ -double GetTickExit( - MqlTick &mTick, - ENUM_POSITION_TYPE type, - string mSymbol = NULL // -) -{ - // - double result = 0; - - // - mSymbol = NormalizeSymbol(mSymbol); - - // - result = - IsLong(type) - ? mTick.bid - : mTick.ask; - result = NormalizePrice(result, mSymbol); - - // - return result; -} - -/** - * Calculate Momentum Changes based on Given Price - */ -double CalculateMomentum( - double currentPrice, - double previousPrice // -) -{ - // - double result = 0; - - // - return result; -} - -/** - * Detect Possible Momentum Changes - * Using MqlTick ... - */ -bool DetectMomentumChange( - ENUM_POSITION_TYPE type, - string mSymbol = NULL, - int mLength = 14 // -) -{ - // - bool result = false; - - // - mSymbol = NormalizeSymbol(mSymbol); - - // - MqlTick ticks[]; - int copied = CopyTicks( - mSymbol, - ticks, - COPY_TICKS_ALL, - 0, - mLength + 1 // - ); - - // - result = copied > mLength; - if (!result) - { - return result; - } - - // - double previousPrice = GetTickExit( - ticks[mLength], - type, - mSymbol // - ); - for (int i = mLength - 1; i >= 0; i--) - { - // - double currentPrice = GetTickExit( - ticks[i], - type, - mSymbol // - ); - - // - double momentum = CalculateMomentum( - currentPrice, - previousPrice // - ); - - // - if (fabs(momentum) > 1.0) - { - // - result = true; - break; - } - } - - // - return result; -} - -// -// Fill Specified Applied Prices ... -int FillPrice( - double &buffer[], - ENUM_APPLIED_PRICE _mAppliedTo = PRICE_CLOSE, - string _mSymbol = NULL, - ENUM_TIMEFRAMES _mPeriod = NULL, - int _mStart = 0, - int _mLoopback = 10 // -) -{ - // - int result = 0; - - // - if (_mStart < 0) - { - _mStart = 0; - } - - // - if (_mLoopback < 1) - { - _mLoopback = 1; - } - - // - _mSymbol = NormalizeSymbol(_mSymbol); - _mPeriod = NormalizePeriod(_mPeriod); - - // - Clean(buffer); - ArraySetAsSeries(buffer, true); - - // - double open[]; - result = CopyOpen( - _mSymbol, - _mPeriod, - _mStart, - _mLoopback, - open // - ); - if (!IsValidSize(result)) - { - return result; - } - - // - double high[]; - result = CopyHigh( - _mSymbol, - _mPeriod, - _mStart, - _mLoopback, - high // - ); - if (!IsValidSize(result)) - { - return result; - } - - // - double low[]; - result = CopyLow( - _mSymbol, - _mPeriod, - _mStart, - _mLoopback, - low // - ); - if (!IsValidSize(result)) - { - return result; - } - - // - double close[]; - result = CopyClose( - _mSymbol, - _mPeriod, - _mStart, - _mLoopback, - close // - ); - if (!IsValidSize(result)) - { - return result; - } - - // - for (int i = 0; i < result; i++) - { - // - double iPrice = GetAppliedPrice( - _mAppliedTo, - open, - high, - low, - close, - i // - ); - - // - Add( - iPrice, - buffer // - ); - } - - // - result = ArraySize(buffer); - - // - return result; -} - -// -// Symbols ... - -// -// Retrieve Available Symbols ... -int GetAllSymbols( - string &symbols[], // Hold Result - bool onlyInWatchList = false, // Specified Retrieve only Symbols which in Watch List - bool forceClean = true // Force To Clean Result Array -) -{ - // - int result = 0; - - // - if (forceClean) - { - Clean(symbols); - } - - // - int beforeSize = ArraySize(symbols); - - // - int symbolsCount = SymbolsTotal(onlyInWatchList); - if (symbolsCount <= 0) - { - return result; - } - - // - for (int i = 0; i < symbolsCount; i++) - { - // - string iSymbol = SymbolName( - i, - onlyInWatchList - // - ); - if (!IsValid(iSymbol)) - { - continue; - } - - // - Add( - iSymbol, - symbols - // - ); - } - - // - int afterSize = ArraySize(symbols); - - // - result = afterSize - beforeSize; - - // - return result; -} - -// -// This is a Global Way to Filter Symbols -// you can pass Specific string as Query or a List String for Filtering ... -int FilterSymbols( - string query, // Which Query to Search Symbol - string &symbols[], // Hold Result - bool onlyInWatchList = false, // Specified Retrieve only Symbols which in Watch List - bool forceClean = true, // Force To Clean Result Array - bool ignoreCase = true, // Ignore Case - string querySeparator = "," // If Provided means query is a COllection of Queries and need to be Splitted -) -{ - // - int result = 0; - - // - if (forceClean) - { - Clean(symbols); - } - - // - if (!IsValid(query)) - { - return result; - } - - // - // Check Query is an String array or not ... - string mQueries[]; - int queriesCount = 0; - if (IsValid(querySeparator) && Contains(querySeparator, query, true)) - { - // - queriesCount = SplitContent( - mQueries, - query, - querySeparator - // - ); - } - - // - int beforeSize = ArraySize(symbols); - - // - string allSymbols[]; - int allSymbolsCount = GetAllSymbols( - allSymbols, - onlyInWatchList, - forceClean); - if (allSymbolsCount <= 0) - { - return result; - } - - // - // Loop Through all Symbols ... - for (int i = 0; i < allSymbolsCount; i++) - { - // - string iSymbol = allSymbols[i]; - - // - bool isFilterPassed = false; - if (queriesCount == 0) - { - // - isFilterPassed = Contains( - query, - iSymbol, - ignoreCase - // - ); - } - else if (queriesCount > 0) - { - // - isFilterPassed = Contains( - mQueries, - iSymbol, - ignoreCase - // - ); - } - - // - if (isFilterPassed) - { - // - Add( - iSymbol, - symbols - // - ); - } - } - - // - int afterSize = ArraySize(symbols); - - // - result = afterSize - beforeSize; - - // - return result; -} - -// -int FilterUSDSymbols( - string &symbols[], // Hold Result - bool onlyInWatchList = false, // Specified Retrieve only Symbols which in Watch List - bool forceClean = true, // Force To Clean Result Array - bool ignoreCase = true, // Ignore Case - string querySeparator = "," // If Provided means query is a COllection of Queries and need to be Splitted -) -{ - // - return FilterSymbols( - "USD", - symbols, - onlyInWatchList, - forceClean, - ignoreCase, - querySeparator - // - ); -} - -// -// Time / Date ... - -// -// 0 => Sunday -// 1 => Monday -// 2 => Tuesday -// 3 => Wednesday -// 4 => Thursday -// 5 => Friday -// 6 => Saturday -enum ENUM_X_WEEK_DAYS -{ - X_WEEK_DAY_NONE = -1, - X_WEEK_DAY_SUNDAY = 0, - X_WEEK_DAY_MONDAY = 1, - X_WEEK_DAY_TUESDAY = 2, - X_WEEK_DAY_WEDNESDAY = 3, - X_WEEK_DAY_THURSDAY = 4, - X_WEEK_DAY_FRIDAY = 5, - X_WEEK_DAY_SATURDAY = 6, -}; - -// -// Retrieve Day of Week ... -ENUM_X_WEEK_DAYS GetDayOfWeek( - datetime time = NULL // -) -{ - // - ENUM_X_WEEK_DAYS result = X_WEEK_DAY_NONE; - - // - time = NormalizeTime(time); - MqlDateTime timeStruct; - bool hasDate = TimeToStruct( - time, - timeStruct // - ); - if (!hasDate) - { - return result; - } - - // - result = (ENUM_X_WEEK_DAYS)timeStruct.day_of_week; - - // - return result; -} - -// -// Representation of Time Struct ... -// struct MqlDateTime -// { -// int year; // Year -// int mon; // Month -// int day; // Day -// int hour; // Hour -// int min; // Minutes -// int sec; // Seconds -// int day_of_week; // Day of week (0-Sunday, 1-Monday, ... ,6-Saturday) -// int day_of_year; // Day number of the year (January 1st is assigned the number value of zero) -// }; - -// -// Converts Time to Seconds ... -ulong TimeToSeconds( - datetime time // Specify time to Convert ... -) -{ - // - ulong result = (ulong)time; - - // - return result; -} -ulong TimeToSeconds( - MqlDateTime &time // Specify time to Convert ... -) -{ - // - datetime dTime = StructToTime(time); - - // - ulong result = TimeToSeconds(dTime); - - // - return result; -} - -// -// Converts Seconds To Time ... -datetime SecondsToTime( - ulong seconds // Specify Seconds to Convert ... -) -{ - // - datetime result = (datetime)seconds; - - // - return result; -} -MqlDateTime SecondsToStruct( - ulong seconds // Specify Seconds to Convert ... -) -{ - // - datetime dTime = SecondsToTime(seconds); - - // - MqlDateTime result = {}; - TimeToStruct( - dTime, - result); - - // - return result; -} - -// -// Converts Time to MilliSeconds ... -ulong TimeToMilliSeconds( - datetime time // Specify time to Convert ... -) -{ - // - ulong result = TimeToSeconds(time) * 1000; - - // - return result; -} -ulong TimeToMilliSeconds( - MqlDateTime &time // Specify time to Convert ... -) -{ - // - datetime dTime = StructToTime(time); - - // - ulong result = TimeToMilliSeconds(dTime); - - // - return result; -} - -// -// Converts MillisSeconds to Time ... -datetime MilliSecondsToTiem( - ulong milliSeconds // Specify MilliSeconds to Convert ... -) -{ - // - ulong seconds = milliSeconds / 1000; - - // - datetime result = SecondsToTime(seconds); - - // - return result; -} -MqlDateTime MilliSecondsToStruct( - ulong milliSeconds // Specify MilliSeconds to Convert ... -) -{ - // - datetime dTime = MilliSecondsToTiem(milliSeconds); - - // - MqlDateTime result = {}; - TimeToStruct( - dTime, - result); - - // - return result; -} - -// -// Converts Hours to Seconds ... -int HoursToSeconds(int value) -{ - // - int result = 0; - - // - if (value < 0) - { - value = 0; - } - - // - if (value == 0) - { - return result; - } - - // - result = value * 60 * 60; - - // - return result; -} - -// -// Retrieve DateTime Structure ... -MqlDateTime GetCurrentTime() -{ - // - MqlDateTime result = {}; - - // - datetime cTime = TimeCurrent(); - TimeToStruct(cTime, result); - - // - return result; -} - -// -// Retrieve Current Time as Seconds ... -ulong GetCurrentTimeAsSeconds() -{ - // - datetime time = TimeCurrent(); - - // - ulong result = TimeToSeconds(time); - - // - return result; -} - -// -// Retrieve Current Time as MilliSeconds ... -ulong GetCurrentTimeAsMilliSeconds() -{ - // - datetime time = TimeCurrent(); - - // - ulong result = TimeToMilliSeconds(time); - - // - return result; -} - -// -int GetLocalOffset() -{ - // - MqlDateTime cTimeStruct; - datetime cTime = TimeCurrent(cTimeStruct); - - // - MqlDateTime cLTimeStruct; - datetime cLTime = TimeLocal(cLTimeStruct); - - // - cTimeStruct.sec = 0; - cTime = StructToTime(cTimeStruct); - - // - cLTimeStruct.sec = 0; - cLTime = StructToTime(cLTimeStruct); - - // - int result = ((int)cLTime - (int)cTime); - - // - return result; -} - -// -int GetUTCRequiredTimeOffset() -{ - // - int utcOffset = TimeGMTOffset(); - int localOffset = GetLocalOffset(); - - // - int result = utcOffset + localOffset; - - // - return result; -} - -// -datetime GetUTCTime( - datetime time = NULL, - bool applyTradeServerTime = false // -) -{ - // - datetime result = NULL; - - // - NormalizeTime(time); - - // - datetime cTime = TimeCurrent(); - datetime cTimeLocal = TimeLocal(); - - // - int cLocalOffset = ((int)cTimeLocal - (int)cTime); - int gmtOffset = TimeGMTOffset(); - int offsetDelte = gmtOffset + cLocalOffset; - int requiredUTCOffset = GetUTCRequiredTimeOffset(); - if (requiredUTCOffset > 0) - { - requiredUTCOffset = -1 * requiredUTCOffset; - } - - // - int timeSeconds = (int)time; - int resultSeconds = timeSeconds + requiredUTCOffset; - - // - result = (datetime)(resultSeconds); - - // - return result; -} - -// -// Retrieve only Hour and Minute as String ... -string GetTimeString( - datetime time = NULL // -) -{ - // - NormalizeTime(time); - - // - string result = NULL; - - // - MqlDateTime tStruct; - bool isStructed = TimeToStruct(time, tStruct); - if (!isStructed) - { - return result; - } - - // - string hour = ToString(tStruct.hour); - hour = - StringLen(hour) == 1 - ? "0" + hour - : hour; - - // - string minute = ToString(tStruct.min); - minute = - StringLen(minute) == 1 - ? "0" + minute - : minute; - - // - result = hour + ":" + minute; - - // - return result; -} - -// -// Converts a Date time to File Format ... -string ToFormatString( - datetime mTime, - string separator = "_" // -) -{ - // - string result = NULL; - - // - if (!IsValid(mTime)) - { - return result; - } - - // - MqlDateTime timeStruct; - bool isConverts = TimeToStruct( - mTime, - timeStruct // - ); - if (!isConverts) - { - return result; - } - - // - string year = ToString(timeStruct.year); - string month = ToString(timeStruct.mon); - string day = ToString(timeStruct.day); - string hour = ToString(timeStruct.hour); - string minute = ToString(timeStruct.min); - string second = ToString(timeStruct.sec); - - // - result = - // - // Year ... - year + separator + - // - // Month ... - (StringLen(month) == 1 - ? "0" + month - : month) + - separator + - // - // Day ... - (StringLen(day) == 1 - ? "0" + day - : day) + - separator + - // - // Hour ... - (StringLen(hour) == 1 - ? "0" + hour - : hour) + - separator + - // - // Minute ... - (StringLen(minute) == 1 - ? "0" + minute - : minute) + - separator + - // - // Seconds ... - (StringLen(second) == 1 - ? "0" + second - : second) + - separator + - // - "" - // - ; - - // - return result; -} - -/** - * Converts an String Represetation of Time (00:00) to Date Time .. - * - * @param value: String ... - * - * @return ( datetime ) - */ -datetime ParseDateTimeFromTimeString(string value) -{ - // - datetime result = NULL; - - // - if (!IsValid(value)) - { - return result; - } - - // - // Check Signalling Time ... - MqlDateTime cTime; - bool isTimeRecieved = TimeCurrent(cTime); - if (!isTimeRecieved) - { - return result; - } - - // - // Split ... - string parts[]; - int partsCount = SplitContent( - parts, - value, - ":" - // - ); - if (!IsValidSize(partsCount)) - { - return result; - } - - // - int hour = 0; - int minute = 0; - if (partsCount >= 1) - { - hour = (int)(parts[0]); - } - if (partsCount >= 2) - { - minute = (int)(parts[1]); - } - - // - cTime.day_of_week = 0; - cTime.day_of_year = 0; - - // - cTime.hour = hour; - cTime.min = minute; - - // - result = StructToTime(cTime); - - // - return result; -} - -// -// Check Specific Time in Range of another Time ... -bool IsTimeInRange( - datetime currentTime = NULL, - datetime startTime = NULL, - datetime stopTime = NULL // -) -{ - // - bool result = false; - - // - // Normallize Current Time ... - currentTime = NormalizeTime(currentTime); - - // - result = !IsValid(startTime) && - !IsValid(stopTime); - if (result) - { - return result; - } - - // - result = IsValid(startTime) && - IsValid(stopTime); - if (!result) - { - // - result = IsValid(startTime) && - currentTime >= startTime; - - // - return result; - } - - // - result = currentTime >= startTime && - currentTime < stopTime; - - // - return result; -} -bool IsTimeInRange( - datetime currentTime, - string startTime, - string endTime // -) -{ - // - bool result = false; - - // - result = IsValid(startTime) && - IsValid(endTime); - if (!result) - { - // - // Here Since there isnot provide any - // data source we pass result as true ... - result = true; - return result; - } - - // - // Converts String Representation to Time ... - datetime st = ParseDateTimeFromTimeString(startTime); - datetime et = ParseDateTimeFromTimeString(endTime); - - // - result = IsTimeInRange( - currentTime, - st, - et // - ); - - // - return result; -} - -// -// Bar Times ... - -// -// Retrieve Specified Bar Time ... -datetime GetBarTime( - string mSymbol = "", // Specify Symbol - ENUM_TIMEFRAMES mPeriod = NULL, // Specify TimeFrame - int barIndex = 0 // Specify Bar Index -) -{ - // - // Validate and Normalize Args ... - - // - mSymbol = NormalizeSymbol(mSymbol); - mPeriod = NormalizePeriod(mPeriod); - - // - // Retrieve Bar Time ... - datetime result = iTime( - mSymbol, - mPeriod, - barIndex); - - // - return result; -} - -// -// Retrieve Specified Bar Time ... -ulong GetBarTimeAsSeconds( - string mSymbol = "", // Specify Symbol - ENUM_TIMEFRAMES mPeriod = NULL, // Specify TimeFrame - int barIndex = 0 // Specify Bar Index -) -{ - // - // Retrieve Bar Time ... - datetime time = GetBarTime( - mSymbol, - mPeriod, - barIndex); - - // - ulong result = TimeToSeconds(time); - - // - return result; -} - -// -// Retrieve Specified Bar Time ... -ulong GetBarTimeAsMilliSeconds( - string mSymbol = "", // Specify Symbol - ENUM_TIMEFRAMES mPeriod = NULL, // Specify TimeFrame - int barIndex = 0 // Specify Bar Index -) -{ - // - // Retrieve Bar Time ... - datetime time = GetBarTime( - mSymbol, - mPeriod, - barIndex); - - // - ulong result = TimeToMilliSeconds(time); - - // - return result; -} - -// -// Retrieve a Bar Time Structure ... -MqlDateTime GetBarTimeStruct( - string mSymbol = "", // Specify Symbol - ENUM_TIMEFRAMES mPeriod = NULL, // Specify TimeFrame - int barIndex = 0 // Specify Bar Index -) -{ - // - MqlDateTime result = {}; - - // - // Retrieve Bar Time ... - datetime barTime = GetBarTime( - mSymbol, - mPeriod, - barIndex); - - // - // Convert to Structure ... - TimeToStruct(barTime, result); - - // - return result; -} - -// -// Retrieve Last Available Bar Time of -// Dest Period inside Source Period ... -datetime GetLastBarTime( - ENUM_TIMEFRAMES sourcePeriod, - ENUM_TIMEFRAMES destPeriod // -) -{ - // - datetime result = NULL; - - // - if (!IsValid(sourcePeriod) || - !IsValid(destPeriod)) - { - return result; - } - - // - int sourceSeconds = PeriodSeconds(sourcePeriod); - int destSeconds = PeriodSeconds(destPeriod); - if (sourceSeconds < destSeconds) - { - return result; - } - - // - XOHCL sourceBar; - bool isInited = sourceBar.Init( - _Symbol, - sourcePeriod, - 0 // - ); - if (!isInited) - { - return result; - } - - // - result = (datetime)((((int)sourceBar.time) + sourceSeconds) - destSeconds); - - // - return result; -} - -// -// Other Tools ... - -// -template -bool IsSame( - T &buffer[], // Search Buffer - int count = 5, // Number of Searchs - int start = 0 // Start ... -) -{ - // - bool result = false; - - // - int bufferSize = ArraySize(buffer); - result = bufferSize > 0; - if (!result) - { - return result; - } - - // - // Validate Count ... - result = start + count < bufferSize; - if (!result) - { - return result; - } - - // - T iTem = buffer[start]; - for (int i = start; i < start + count; i++) - { - // - if (iTem != buffer[i]) - { - result = false; - break; - } - - // - if (!result) - { - result = true; - } - } - - // - return result; -} - -// -// Check first Cross Over second at index ... -bool IsCrossedOver( - const double &first[], // the buffer which check crossing over second buffer - const double &second[], // first buffer checks based on this buffer - const int index = 0 // check crosses in specific index -) -{ - // - bool result = false; - - // - // Validate Args ... - if (ArraySize(first) < index + 1 || ArraySize(second) < index + 1) - { - return result; - } - - // - result = first[index] > second[index] && - !(first[index + 1] > second[index + 1]); - - // - return result; -} - -// -// Check first is Over second at index ... -bool IsOver( - const double &first[], // the buffer which check over second buffer - const double &second[], // first buffer checks based on this buffer - const int index = 0 // check crosses in specific index -) -{ - // - bool result = false; - - // - // Validate Args ... - if (ArraySize(first) < index + 1 || ArraySize(second) < index + 1) - { - return result; - } - - // - result = first[index] > second[index] && - first[index + 1] > second[index + 1]; - - // - return result; -} - -// -// Check first Cross Under second at index ... -bool IsCrossedUnder( - const double &first[], // the buffer which check crossing under second buffer - const double &second[], // first buffer checks based on this buffer - const int index = 0 // check crosses in specific index -) -{ - // - bool result = false; - - // - // Validate Args ... - if (ArraySize(first) < index + 1 || ArraySize(second) < index + 1) - { - return result; - } - - // - result = first[index] < second[index] && - !(first[index + 1] < second[index + 1]); - - // - return result; -} - -// -// Check first is Under second at index ... -bool IsUnder( - const double &first[], // the buffer which check under second buffer - const double &second[], // first buffer checks based on this buffer - const int index = 0 // check crosses in specific index -) -{ - // - bool result = false; - - // - // Validate Args ... - if (ArraySize(first) < index + 1 || ArraySize(second) < index + 1) - { - return result; - } - - // - result = first[index] < second[index] && - first[index + 1] < second[index + 1]; - - // - return result; -} - -// -// Check if a Value Increasing in Loopback ... -bool IsIncreasing( - const double &buffer[], // the Buffer which required to search - int from = -1, // Last Time Index - int to = -1 // Fisrs Tima Index -) -{ - // - bool result = false; - - // - if (from == -1) - { - from = ArraySize(buffer) - 1; - } - - // - if (to == -1) - { - to = 0; - } - - // - // Validate Args ... - if ( - from <= to || - ArraySize(buffer) < from + 1) - { - return result; - } - - // - // Loop through Items ... - double toValue = buffer[to]; - double fromValue = buffer[from]; - result = toValue >= fromValue; - for (int i = to + 1; i <= from - 1; i++) - { - // - double iValue = buffer[i]; - bool isPassed = toValue >= iValue; - - // - bool isIIncreasing = IsIncreasing( - buffer, - from, - i // - ); - - // - // Check Result ... - result = result && isPassed && isIIncreasing; - if (!result) - { - break; - } - } - - // - return result; -} - -// -// Check if a Value Decreasing in Loopback ... -bool IsDecreasing( - const double &buffer[], // the Buffer which required to search - int from = -1, // Last Time Index - int to = -1 // Fisrs Tima Index -) -{ - // - bool result = false; - - // - if (from == -1) - { - from = ArraySize(buffer) - 1; - } - - // - if (to == -1) - { - to = 0; - } - - // - // Validate Args ... - if ( - from <= to || - ArraySize(buffer) < from + 1) - { - return result; - } - - // - // Loop through Items ... - double toValue = buffer[to]; - double fromValue = buffer[from]; - result = toValue <= fromValue; - for (int i = to + 1; i <= from - 1; i++) - { - // - double iValue = buffer[i]; - bool isPassed = toValue <= iValue; - - // - bool isIDecreasing = IsDecreasing( - buffer, - from, - i // - ); - - // - // Check Result ... - result = result && isPassed && isIDecreasing; - if (!result) - { - break; - } - } - - // - return result; -} - -// -bool IsTrendingUp( - const double &buffer1[], // First Buffer - const double &buffer2[] // Seccend Buffer -) -{ - // - bool result = false; - - // - int buffer1Count = ArraySize(buffer1); - int buffer2Count = ArraySize(buffer2); - if (buffer1Count <= 0 || buffer2Count <= 0) - { - return result; - } - - // - int count = MathMin(buffer1Count, buffer2Count); - if (count <= 1) - { - return result; - } - - // - int upCounts = 0; - int downCounts = 0; - double value = MathAbs(buffer1[0] - buffer2[0]); - for (int i = 1; i < count; i++) - { - // - double iValue = MathAbs(buffer1[i] - buffer2[i]); - - // - if (value > iValue) - { - upCounts++; - } - - // - if (value < iValue) - { - downCounts++; - } - } - - // - result = upCounts > 1 && upCounts > downCounts; - - // - return result; -} - -// -bool IsTrendingDown( - const double &buffer1[], // First Buffer - const double &buffer2[] // Seccend Buffer -) -{ - // - bool result = false; - - // - int buffer1Count = ArraySize(buffer1); - int buffer2Count = ArraySize(buffer2); - if (buffer1Count <= 0 || buffer2Count <= 0) - { - return result; - } - - // - int count = MathMin(buffer1Count, buffer2Count); - if (count <= 1) - { - return result; - } - - // - int upCounts = 0; - int downCounts = 0; - double value = MathAbs(buffer1[0] - buffer2[0]); - for (int i = 1; i < count; i++) - { - // - double iValue = MathAbs(buffer1[i] - buffer2[i]); - - // - if (value > iValue) - { - upCounts++; - } - - // - if (value < iValue) - { - downCounts++; - } - } - - // - result = downCounts > 1 && downCounts > upCounts; - - // - return result; -} - -// -// Calculate Slope of Specified Buffer at Specified Index ... -double GetSlope( - const double &buffer[], // Buffer - int from, // In Past Index ... - int to // In Past Index ... -) -{ - // - double result = 0; - - // - if (from > ArraySize(buffer) || to > ArraySize(buffer)) - { - return result; - } - - // - double toValue = buffer[to]; - double fromValue = buffer[from]; - double deltaValue = toValue - fromValue; - double deltaTime = from - to; - - // - result = deltaValue / deltaTime; - - // - return result; -} - -// -// Check Bar Reject Specified Value ... -bool IsBarReject( - double value, - ENUM_X_DIRECTION dir, - XOHCL &bar // -) -{ - // - bool result = false; - - // - result = value > 0 && - bar.IsValid() && - HasDirection(dir); - if (!result) - { - return result; - } - - // - bool isUp = IsBullish(dir); - bool isDown = IsBearish(dir); - - // - result = - // - isUp - ? bar.IsBullish() && - bar.low < value && - bar.GetDown() > value - : isDown - ? bar.IsBearish() && - bar.high > value && - bar.GetUp() < value - : false - // - ; - - // - return result; -} - -// -// Check Bar Break Specified Value ... -bool IsBarBreak( - double value, - ENUM_X_DIRECTION dir, - XOHCL &bar // -) -{ - // - bool result = false; - - // - result = value > 0 && - bar.IsValid() && - HasDirection(dir); - if (!result) - { - return result; - } - - // - XOHCL pBar; - result = bar.GetPreviousBar(pBar); - if (!result) - { - return result; - } - - // - bool isUp = IsBullish(dir); - bool isDown = IsBearish(dir); - - // - result = - isUp - ? bar.IsBullish() && - ((bar.GetDown() < value && - bar.GetUp() > value) || - (bar.close > value && - pBar.close < value)) - : isDown - ? bar.IsBearish() && - ((bar.GetUp() > value && - bar.GetDown() < value) || - (bar.close < value && - pBar.close > value)) - : false; - - // - return result; -} - -// -// Calculate Fib Level ... -double GetFibonacciLevel( - double upPrice, // Upper Bound - double downPrice, // Downer Bound - double level, // Level Multiplier Factor - int direction // From Down to Up < 0, other wise Vice Versa - // -) -{ - // - double ling = upPrice - downPrice; - double pLevel = (ling / 100) * (level * 100); - - // - double result = direction > 0 ? upPrice - pLevel : downPrice + pLevel; - - // - return result; -} - -// -double GetFibonacciLevel( - double mUp, - double mDown, - ENUM_X_FIBO_LEVELS mLevel, - ENUM_X_DIRECTION mForDir // -) -{ - // - double result = 0; - - // - double levelValue = GetFiboLevelValue(mLevel); - - // - bool isValid = - // - mUp > 0 && - mDown > 0 && - levelValue > 0 && - mUp > mDown && - HasDirection(mForDir) - // - ; - if (!isValid) - { - return result; - } - - // - bool isBullish = IsBullish(mForDir); - - // - double ling = mUp - mDown; - double pLevel = (ling / 100) * (levelValue * 100); - - // - result = - isBullish - ? mUp - pLevel - : mDown + pLevel; - - // - return result; -} - -// -// Method 1 -// Normalize between 1 and 0 ... -template -double GetNormalizedValueMethod1( - T &buffer[], // Array which required to Normalize - int mLength, // Length of Normalization - int mStart = 0, // start index - int digits = 5 // Normalization Digits -) -{ - // - double result = 0; - - // - if (digits <= 5) - { - digits = 5; - } - - // - int bufferSize = ArraySize(buffer); - if (!IsValidSize(bufferSize)) - { - return result; - } - - // - // Normalize Count ... - NormalizeCount( - mStart, - mLength, - buffer // - ); - - // - T max = 0; - T min = 0; - - // - if (bufferSize != mLength) - { - // - T tmp[]; - Copy( - mStart, - mLength, - buffer, - tmp // - ); - - // - max = GetMax(tmp); - min = GetMin(tmp); - } - - // - if (bufferSize == mLength) - { - // - max = GetMax(buffer); - min = GetMin(buffer); - } - - // - T iValue = buffer[mStart]; - - // - double minMaxDiff = (max - min); - if (minMaxDiff <= 0) - { - return result; - } - - // - result = (iValue - min) / minMaxDiff; - - // - result = NormalizeDouble(result, digits); - - // - return result; -} - -// -// Method 2 -// Normalize Between Specified Upper and Lower ... -template -double GetNormalizedValueMethod2( - T &buffer[], // Array which required to Normalize - int mLength, // Length of Normalization - int mUpper, // Specified Upper Value - int mLower, // Specified Lower Value - int mStart = 0, // start index - int digits = 5 // Normalization Digits -) -{ - // - double result = 0; - - // - if (digits <= 5) - { - digits = 5; - } - - // - int bufferSize = ArraySize(buffer); - if (!IsValidSize(bufferSize)) - { - return result; - } - - // - // Normalize Count ... - NormalizeCount( - mStart, - mLength, - buffer // - ); - - // - T max = 0; - T min = 0; - - // - if (bufferSize != mLength) - { - // - T tmp[]; - Copy( - mStart, - mLength, - buffer, - tmp // - ); - - // - max = GetMax(tmp); - min = GetMin(tmp); - } - - // - if (bufferSize == mLength) - { - // - max = GetMax(buffer); - min = GetMin(buffer); - } - - // - T iValue = buffer[mStart]; - - // - double minMaxDiff = (max - min); - double boundaryDiff = (mUpper - mLower); - if (minMaxDiff <= 0 || boundaryDiff <= 0) - { - return result; - } - - // - result = boundaryDiff / (minMaxDiff * (iValue - max) + max); - - // - result = NormalizeDouble(result, digits); - - // - return result; -} - -// -void NormalizeBuffer( - double &source[], // Source Buffer - double &dest[], // Result Buffer - double upper = 100, // Upper Value to Normalize - double lower = -100, // Lower Value to Normalize - int size = -1, // Size Of Normalization - int digits = 5 // Digits for Result -) -{ - // - if (size <= 0) - { - size = ArraySize(source); - } - - // - bool asSeriesFlag = ArrayGetAsSeries(source); - - // - ArraySetAsSeries(source, false); - ArraySetAsSeries(dest, false); - - // - double min = ArrayMinimum(source, 0, size); - double max = ArrayMaximum(source, 0, size); - - // - for (int i = 0; i < size; i++) - { - // - double iNormal = lower + ((source[i] - min) / (max - min)) * (upper - lower); - - // - if (digits > 0) - { - iNormal = NormalizeDouble(iNormal, digits); - } - - // - dest[i] = iNormal; - } - - // - ArraySetAsSeries(source, asSeriesFlag); - ArraySetAsSeries(dest, asSeriesFlag); -} - -// -// Templates ... - -// -// Retrieve Specific Object Types Name ... -template -string GetTypeName(const T &t) -{ - return typename(T); -} - -// -template -string GetToken(T &item) -{ - // - string mType = GetTypeName(item); - - // - string result = mType; - - // - string parts[]; - int partsCount = SplitContent( - parts, - result, - " " - // - ); - if (partsCount <= 0) - { - // - result = mType; - return result; - } - - // - bool hasLastPart = GetLastItem( - result, - parts - // - ); - if (!hasLastPart) - { - // - result = mType; - return result; - } - - // - return result; -} - -// -// Same as Get Token for Use in Classes ... -template -string GetSpecificToken(T &item) -{ - // - string mType = GetTypeName(item); - - // - string result = mType; - - // - string parts[]; - int partsCount = SplitContent( - parts, - result, - " " - // - ); - if (partsCount <= 0) - { - // - result = mType; - return result; - } - - // - bool hasLastPart = GetLastItem( - result, - parts - // - ); - if (!hasLastPart) - { - // - result = mType; - return result; - } - - // - return result; -} - -// -// Generate Unique Tags ... -template -string GenerateTag(T &model) -{ - // - string result = ""; - - // - string tag = model.ToString(); - if (StringLen(tag) == 0) - { - return result; - } - - // - static XSCMD5 md5; - - // - result = md5.Hash(tag); - - // - return result; -} - -// -// Hash Specified Content ... -template -string ToMD5(T content) -{ - // - string result = ""; - - // - string strContent = ToString(content); - if (StringLen(strContent) == 0) - { - return result; - } - - // - static XCMD5 md5; - - // - result = md5.Hash(strContent); - - // - return result; -} - -// -// Check a Value Not Empty ... -template -bool NotEmpty(T value) -{ - return value != EMPTY_VALUE; -} - -// -// Check a Value Not Empty and Zero ... -template -bool NotEmptyZero(T value) -{ - return value != EMPTY_VALUE && value != 0; -} - -// -// Add Specified Item to Array ... -template -int Add( - T item, // item want to add - T &buffer[] // Destination buffer -) -{ - // - int result = 0; - - // - ArrayResize( - buffer, - ArraySize(buffer) + 1); - - // - buffer[ArraySize(buffer) - 1] = item; - - // - result = ArraySize(buffer); - - // - return result; -} -template -int AddSpecific( - T item, // item want to add - T &buffer[] // Destination buffer -) -{ - // - return Add( - item, - buffer // - ); -} -template -int AddRef( - T &item, // item want to add - T &buffer[] // Destination buffer -) -{ - // - int result = 0; - - // - ArrayResize( - buffer, - ArraySize(buffer) + 1); - - // - buffer[ArraySize(buffer) - 1] = item; - - // - result = ArraySize(buffer); - - // - return result; -} - -// -// Check Specified Array Has Childs or not ... -template -bool HasChild(T &buffer[]) -{ - return IsValidSize(ArraySize(buffer)); -} -template -bool SpecificHasChild(T &buffer[]) -{ - return HasChild(buffer); -} - -// -// Remove Specified Item from an Array ... -template -bool Remove( - T item, - T &buffer[]) -{ - // - bool result = false; - - // - int itemIndex = FindIndex( - item, - buffer); - if (itemIndex < 0) - { - return result; - } - - // - result = ArrayRemove( - buffer, - itemIndex, - 1); - - // - return result; -} - -// -// Clean Specified Array ... -template -void Clean(T &buffer[]) -{ - // - ArrayResize(buffer, 0); - ArrayFree(buffer); - ZeroMemory(buffer); -} -template -void SpecificClean(T &buffer[]) -{ - Clean(buffer); -} - -// -// Copy Whole Content of Source to Dest array ... -template -void Copy( - T &source[], // Source Buffer ... - T &dest[], // Dest Buffer ... - bool cleanDest = true // Force Clen Dest Buffer ... -) -{ - // - if (cleanDest) - { - Clean(dest); - } - - // - int sourceCount = ArraySize(source); - if (sourceCount <= 0) - { - return; - } - - // - for (int i = 0; i < sourceCount; i++) - { - // - T iSource = source[i]; - - // - AddRef( - iSource, - dest); - } -} - -// -// Copy Items from a Buffer ... -template -int Copy( - int start, // Start - int count, // Number of Items for read - T &source[], // Source Buffer - T &dest[], // Dest Buffer - bool forceClean = true, // Force To Clean buffer - bool forceStart = true // Force To Clean buffer -) -{ - // - int result = 0; - - // - if (forceClean) - { - Clean(dest); - } - - // - if (start < 0 && forceStart) - { - start = 0; - } - - // - if (start >= ArraySize(source)) - { - start = ArraySize(source) - 1; - } - - // - if (count == 0) - { - count = ArraySize(source) - 1 - start; - } - - // - if (start + count > ArraySize(source)) - { - return result; - } - - // - int beforeSize = ArraySize(dest); - - // - bool asSeriesDest = ArrayGetAsSeries(dest); - bool asSeriesSource = ArrayGetAsSeries(source); - - // - ArraySetAsSeries(dest, true); - ArraySetAsSeries(source, true); - - // - ArrayCopy( - dest, - source, - 0, - start, - count - // - ); - - // - int afterSize = ArraySize(dest); - - // - result = afterSize - beforeSize; - - // - ArraySetAsSeries(dest, asSeriesDest); - ArraySetAsSeries(source, asSeriesSource); - - // - return result; -} - -// -// Copy Items from a Buffer ... -template -int CopyRef( - int start, // Start - int count, // Number of Items for read - T &source[], // Source Buffer - T &dest[], // Dest Buffer - bool forceClean = true // Force To Clean buffer -) -{ - // - int result = 0; - - // - if (forceClean) - { - Clean(dest); - } - - // - if (start < 0) - { - start = 0; - } - - // - if (start >= ArraySize(source)) - { - start = ArraySize(source) - 1; - } - - // - int beforeSize = ArraySize(dest); - - // - bool asSeriesDest = ArrayGetAsSeries(dest); - bool asSeriesSource = ArrayGetAsSeries(source); - - // - ArraySetAsSeries(dest, true); - ArraySetAsSeries(source, true); - - // - for (int i = start; i < start + count; i++) - { - // - AddRef( - source[i], - dest - // - ); - } - - // - int afterSize = ArraySize(dest); - - // - result = afterSize - beforeSize; - - // - ArraySetAsSeries(dest, asSeriesDest); - ArraySetAsSeries(source, asSeriesSource); - - // - return result; -} - -// -// Retrive Last Item of Specified Buffer ... -template -bool GetLastItem( - T &item, // Holds Result - T &buffer[] // Specified Buffer -) -{ - // - bool result = false; - - // - int bufferSize = ArraySize(buffer); - if (bufferSize <= 0) - { - return result; - } - - // - item = buffer[bufferSize - 1]; - - // - result = true; - return result; -} - -// -// Remove Last Item of Specified Buffer ... -template -bool RemoveLastItem( - T &buffer[] // Specified Buffer -) -{ - // - bool result = false; - - // - int count = ArraySize(buffer); - result = IsValidSize(count); - if (!result) - { - return result; - } - - // - ArrayRemove( - buffer, - count - 1, - 1 // - ); - - // - return result; -} - -template -void CleanupArray( - T &buffer[], // Buffer to Cleanup ... - int maxAllowed = 0 // Max Allowed Number of items ... -) -{ - // - if (maxAllowed <= 0) - { - return; - } - - // - int count = ArraySize(buffer); - if (!IsValidSize(count) || - count <= maxAllowed) - { - return; - } - - // - int mustRemove = count - maxAllowed; - if (!IsValidSize(mustRemove)) - { - return; - } - - // - ArrayRemove( - buffer, - 0, - mustRemove // - ); -} - -template -void CleanupArray( - int &removedIndexes[], - T &buffer[] // Buffer to Cleanup ... -) -{ - // - bool isValid = HasChild(buffer) && - HasChild(removedIndexes); - if (!isValid) - { - return; - } - - // - for (int i = 0; i < ArraySize(removedIndexes); i++) - { - // - int idx = removedIndexes[i]; - if (IsValidIndex(idx) && ArraySize(buffer) > idx) - { - // - ArrayRemove( - buffer, - idx, - 1 // - ); - } - } - - // - Clean(removedIndexes); -} - -// -// Search Array For Specific Item ... -template -int FindIndex( - T item, // What is Search ... - T &buffer[] // Search in ... -) -{ - // - int result = -1; - - // - int count = ArraySize(buffer); - if (count <= 0) - { - return result; - } - - // - for (int i = 0; i < count; i++) - { - // - T iT = buffer[i]; - - // - if (iT == item) - { - // - result = i; - break; - } - } - - // - return result; -} -// -// Find Specific Item Index inside a Collection ... -template -int FindIndex( - T &item, // Item to Find - const T &items[] // Items for Search -) -{ - // - int result = -1; - - // - // Check Item Validation ... - if (!item.IsValid()) - { - return result; - } - - // - int itemsCount = ArraySize(items); - if (itemsCount <= 0) - { - return result; - } - - // - for (int i = 0; i < itemsCount; i++) - { - // - T iItem = items[i]; - - // - // Validate Item ... - if (!iItem.IsValid()) - { - continue; - } - - // - bool isSame = item.IsSameAs(iItem); - if (isSame && result <= -1) - { - // - result = i; - break; - } - } - - // - return result; -} - -// -// Check an Array Contains Specified Value ... -template -bool Contains( - T item, // What is Search ... - T &buffer[] // Search in ... -) -{ - // - bool result = false; - - // - int idx = FindIndex( - item, - buffer); - result = idx > -1; - - // - return result; -} - -// -// Calculate a Buffer's Sum ... -template -double GetSum( - T &buffer[], // the Buffer which required to search - int start = 0, // Start Index - int count = 0 // Count for Search -) -{ - // - double result = 0; - - // - T tmp[]; - int tmpCount = Copy( - start, - count, - buffer, - tmp - // - ); - if (tmpCount <= 0) - { - return result; - } - - // - // Calculate Summary ... - for (int i = 0; i < tmpCount; i++) - { - result += buffer[i]; - } - - // - return result; -} - -// -// Calculate a Buffer's Average ... -template -double GetAverage( - T &buffer[], // the Buffer which required to search - int start = 0, // Start Index - int count = 0 // Count for Search -) -{ - // - double result = 0; - - // - T tmp[]; - int tmpCount = Copy( - start, - count, - buffer, - tmp - // - ); - if (tmpCount <= 0) - { - return result; - } - - // - // Calculate Summary ... - for (int i = 0; i < tmpCount; i++) - { - result += buffer[i]; - } - - // - // Calculate Average ... - result = result / tmpCount; - - // - return result; -} - -// -// Get Max of Specific Loopback of a Buffer ... -template -T GetMax( - T &buffer[], // the Buffer which required to search - int start = 0, // Start Index - int count = 0 // Count for Search -) -{ - // - T result = 0; - - // - if (count <= 0) - { - count = ArraySize(buffer); - } - - // - T tmp[]; - int tmpCount = Copy( - start, - count, - buffer, - tmp - // - ); - if (tmpCount <= 0) - { - return result; - } - - // - // Loop Through LoopBack ... - for (int i = 0; i < tmpCount; i++) - { - // - T iValue = tmp[i]; - - // - result = - // - result == 0 || result < iValue - // - ? iValue - // - : result - // - ; - } - - // - return result; -} -template -T GetMax( - T &buffer[], // the Buffer which required to search - int &index, // Item Index ... - int start = 0, // Start Index - int count = 0 // Count for Search -) -{ - // - T result = 0; - index = -1; - - // - if (count <= 0) - { - count = ArraySize(buffer); - } - - // - T tmp[]; - int tmpCount = Copy( - start, - count, - buffer, - tmp - // - ); - if (tmpCount <= 0) - { - return result; - } - - // - // Loop Through LoopBack ... - for (int i = 0; i < tmpCount; i++) - { - // - T iValue = tmp[i]; - - // - bool isNew = result == 0; - bool canSet = isNew || - (!isNew && - result < iValue); - if (canSet) - { - // - index = i; - result = iValue; - } - } - - // - return result; -} -template -T GetSpecifiedMax( - T &buffer[], // the Buffer which required to search - int start = 0, // Start Index - int count = 0 // Count for Search -) -{ - return GetMax( - buffer, - start, - count // - ); -} -template -T GetSpecifiedMax( - T &buffer[], // the Buffer which required to search - int &index, // Item Index ... - int start = 0, // Start Index - int count = 0 // Count for Search -) -{ - return GetMax( - buffer, - index, - start, - count // - ); -} - -// -// Get Min of Specific Loopback of a Buffer ... -template -T GetMin( - T &buffer[], // the Buffer which required to search - int start = 0, // Start Index - int count = 0 // Count for Search -) -{ - // - T result = 0; - - // - if (count <= 0) - { - count = ArraySize(buffer); - } - - // - T tmp[]; - int tmpCount = Copy( - start, - count, - buffer, - tmp - // - ); - if (tmpCount <= 0) - { - return result; - } - - // - // Loop Through LoopBack ... - for (int i = 0; i < tmpCount; i++) - { - // - T iValue = tmp[i]; - - // - result = - // - result == 0 || result > iValue - // - ? iValue - // - : result - // - ; - } - - // - return result; -} -template -T GetMin( - T &buffer[], // the Buffer which required to search - int &index, // Item Index ... - int start = 0, // Start Index - int count = 0 // Count for Search -) -{ - // - T result = 0; - index = -1; - - // - if (count <= 0) - { - count = ArraySize(buffer); - } - - // - T tmp[]; - int tmpCount = Copy( - start, - count, - buffer, - tmp - // - ); - if (tmpCount <= 0) - { - return result; - } - - // - // Loop Through LoopBack ... - for (int i = 0; i < tmpCount; i++) - { - // - T iValue = tmp[i]; - - // - bool isNew = result == 0; - bool canSet = isNew || - (!isNew && - result > iValue); - if (canSet) - { - // - index = i; - result = iValue; - } - } - - // - return result; -} -template -T GetSpecifiedMin( - T &buffer[], // the Buffer which required to search - int start = 0, // Start Index - int count = 0 // Count for Search -) -{ - return GetMin( - buffer, - start, - count // - ); -} -template -T GetSpecifiedMin( - T &buffer[], // the Buffer which required to search - int &index, // Item Index ... - int start = 0, // Start Index - int count = 0 // Count for Search -) -{ - return GetMin( - buffer, - index, - start, - count // - ); -} - -// -// Find a Value less than Specified ... -template -T FindLesserThan( - T value, // Specified Value ... - const T &source[], // Source ... - bool isDescend = false // Find Biggest Lesser Value ... -) -{ - // - T result = -1; - - // - int itemsCount = ArraySize(source); - if (itemsCount <= 0) - { - return result; - } - - // - // Make a Copy of source ... - T tmp[]; - - // - ArrayResize( - tmp, - ArraySize(source) // - ); - - // - ArrayCopy( - tmp, - source // - ); - - // - // Sort Temp Buffer ... - ArraySort(tmp); - if (isDescend) - { - ArrayReverse(tmp); - } - - // - int tmpCount = ArraySize(tmp); - for (int i = 0; i < tmpCount; i++) - { - // - T iValue = tmp[i]; - - // - if (iValue < value) - { - // - result = iValue; - break; - } - } - - // - return result; -} -template -T FindLesserThan( - T value, // Specified Value ... - int &index, // Item Index ... - const T &source[], // Source ... - bool isDescend = false // Find Biggest Lesser Value ... -) -{ - // - T result = -1; - index = -1; - - // - int itemsCount = ArraySize(source); - if (itemsCount <= 0) - { - return result; - } - - // - // Make a Copy of source ... - T tmp[]; - - // - ArrayResize( - tmp, - ArraySize(source) // - ); - - // - ArrayCopy( - tmp, - source // - ); - - // - // Sort Temp Buffer ... - ArraySort(tmp); - if (isDescend) - { - ArrayReverse(tmp); - } - - // - int tmpCount = ArraySize(tmp); - for (int i = 0; i < tmpCount; i++) - { - // - T iValue = tmp[i]; - - // - if (iValue < value) - { - // - index = i; - result = iValue; - break; - } - } - - // - return result; -} - -// -// Find a Value less than Specified ... -template -T FindBiggerThan( - T value, // Specified Value ... - const T &source[], // Source ... - bool isDescend = false // Find Smallest Bigger Value ... -) -{ - // - T result = -1; - - // - int itemsCount = ArraySize(source); - if (itemsCount <= 0) - { - return result; - } - - // - // Make a Copy of source ... - T tmp[]; - - // - ArrayResize( - tmp, - ArraySize(source) // - ); - - // - ArrayCopy( - tmp, - source // - ); - - // - // Sort Temp Buffer ... - ArraySort(tmp); - if (!isDescend) - { - ArrayReverse(tmp); - } - - // - int tmpCount = ArraySize(tmp); - for (int i = 0; i < tmpCount; i++) - { - // - T iValue = tmp[i]; - - // - if (iValue > value) - { - // - result = iValue; - break; - } - } - - // - return result; -} -template -T FindBiggerThan( - T value, // Specified Value ... - int &index, // Item Index ... - const T &source[], // Source ... - bool isDescend = false // Find Smallest Bigger Value ... -) -{ - // - T result = -1; - index = -1; - - // - int itemsCount = ArraySize(source); - if (itemsCount <= 0) - { - return result; - } - - // - // Make a Copy of source ... - T tmp[]; - - // - ArrayResize( - tmp, - ArraySize(source) // - ); - - // - ArrayCopy( - tmp, - source // - ); - - // - // Sort Temp Buffer ... - ArraySort(tmp); - if (!isDescend) - { - ArrayReverse(tmp); - } - - // - int tmpCount = ArraySize(tmp); - for (int i = 0; i < tmpCount; i++) - { - // - T iValue = tmp[i]; - - // - if (iValue > value) - { - // - index = i; - result = iValue; - break; - } - } - - // - return result; -} - -// -// Find Same Values in Array ... -template -void FindSames( - T &result[], // Holds Result ... - T &source[], // Source ... - int verifications = 3 // Number of Consequence Repeat ... -) -{ - // - Clean(result); - - // - // TenkanSen Flats ... - int sourceCount = ArraySize(source); - if (sourceCount > verifications) - { - // - T mLast = 0; - int mVerified = 0; - for (int i = 0; i < sourceCount; i++) - { - // - T iVal = source[i]; - if (mLast == 0) - { - mLast = iVal; - } - else if (mLast == iVal) - { - mVerified++; - } - else - { - mLast = iVal; - mVerified = 0; - } - - // - if (iVal == mLast && mVerified >= verifications) - { - // - Add( - iVal, - result); - - // - mLast = 0; - mVerified = 0; - } - } - } -} - -// -// Add an Item to a Buffer if not Exists ... -void AddIfNotExists( - double value, - double &values[], - double smoothingPoint = 3 // -) -{ - // - double smoothingValue = smoothingPoint * GetPoints(_Symbol); - - // - int valuesCount = ArraySize(values); - if (valuesCount <= 0) - { - // - Add(value, - values); - } - else - { - // - bool isExists = false; - for (int i = 0; i < valuesCount; i++) - { - // - double iVal = values[i]; - - // - double diff = MathAbs(iVal - value); - - // - if (iVal == value || diff < smoothingValue) - { - // - isExists = true; - break; - } - } - - // - if (!isExists) - { - // - Add(value, - values); - } - } -} - -// -// Add a Buffers Child to another Buffer -// if it's not Contains them ... -void AddsIfNotExists( - double &source[], - double &dest[], - double smoothingPoint = 3) -{ - // - double smoothingValue = smoothingPoint * GetPoints(_Symbol); - - // - int sourceCount = ArraySize(source); - if (sourceCount <= 0) - { - return; - } - - // - for (int i = 0; i < sourceCount; i++) - { - // - double iSource = source[i]; - - // - AddIfNotExists( - iSource, - dest, - smoothingPoint); - } -} - -// -// Bar XOHCL ... - -// -// Extract Specific Range of Bars ... -// using Start Bar Index ... -int GetBars( - XOHCL &result[], // Hold Result - string mSymbol = NULL, // Trading Symbol - ENUM_TIMEFRAMES mPeriod = NULL, // Trading Time Frame - int from = 0, // Start Bar Index - int count = 1, // Number of Bars - bool forceClean = true // Clean Result Array -) -{ - // - int mResult = 0; - - // - if (from < 0) - { - from = 0; - } - - // - mSymbol = NormalizeSymbol(mSymbol); - mPeriod = NormalizePeriod(mPeriod); - - // - int total = Bars( - mSymbol, - mPeriod); - if (from > total - 2) - { - from = total - 2; - } - - // - if (count < 0) - { - count = 1; - } - - // - int start = from; - int end = start + count; - if (end > total - 1) - { - end = total - 1; - } - - // - if (forceClean) - { - Clean(result); - } - - // - int beforeSize = ArraySize(result); - - // - for (int i = start; i < end; i++) - { - // - XOHCL iBar; - bool isValid = iBar.Init( - mSymbol, - mPeriod, - i - // - ); - - // - if (isValid) - { - // - AddRef( - iBar, - result - // - ); - } - } - - // - int afterSize = ArraySize(result); - - // - mResult = afterSize - beforeSize; - - // - return mResult; -} - -// -// Extract Specific Range of Bars ... -// using Start Bar Time ... -int GetBars( - XOHCL &result[], // Hold Result - string mSymbol = NULL, // Trading Symbol - ENUM_TIMEFRAMES mPeriod = NULL, // Trading Time Frame - datetime from = NULL, // Start Bar Time - int count = 1, // Number of Bars - bool forceClean = true // Clean Result Array -) -{ - // - mSymbol = NormalizeSymbol(mSymbol); - mPeriod = NormalizePeriod(mPeriod); - - // - from = NormalizeTime(from); - - // - int barIndex = iBarShift( - mSymbol, - mPeriod, - from, - false - // - ); - - // - return GetBars( - result, - mSymbol, - mPeriod, - barIndex, - count, - forceClean - // - ); -} - -// -// String ... - -// -// Search a Content Contains Specific String or not ... -bool Contains( - string mQuery, // Search String - string mContent, // Search Content - bool ignoreCase = true // Ignore Case -) -{ - // - bool result = false; - - // - // Validate Query ... - result = IsValid(mQuery); - if (!result) - { - return result; - } - - // - // Validate Content ... - result = IsValid(mContent); - if (!result) - { - return result; - } - - // - // Normalize Inputs ... - string query = mQuery; - string content = mContent; - if (ignoreCase) - { - // - StringToLower(query); - StringToLower(content); - } - - // - int queryIdx = StringFind( - content, - query); - - // - result = queryIdx >= 0; - - // - return result; -} - -// -bool Contains( - string &mQueries[], // Search Strings - string mContent, // Search Content - bool ignoreCase = true // Ignore Case -) -{ - // - bool result = false; - - // - // Validate Queries ... - int queriesCount = ArraySize(mQueries); - result = queriesCount > 0; - if (!result) - { - return result; - } - - // - // Validate Content ... - result = IsValid(mContent); - if (!result) - { - return result; - } - - // - int containsCount = 0; - for (int i = 0; i < queriesCount; i++) - { - // - bool isContains = Contains( - mQueries[i], - mContent, - ignoreCase); - - // - if (!isContains) - { - // - result = false; - break; - } - - // - containsCount++; - } - - // - result = containsCount == queriesCount; - - // - return result; -} - -// -int FindIndexes( - string mQuery, // Search String - string mContent, // Search Content - int &result[], // Holding Results - bool ignoreCase = false // Ignore Case -) -{ - // - int mResult = 0; - - // - Clean(result); - - // - // Validate Inputs ... - if (!IsValid(mQuery) || - !IsValid(mContent)) - { - return mResult; - } - - // - // Apply Ignore Case if Provided ... - if (ignoreCase) - { - // - bool isConverted = StringToLower(mQuery); - if (!isConverted) - { - return mResult; - } - - // - isConverted = StringToLower(mContent); - if (!isConverted) - { - return mResult; - } - } - - // - // Search First Index ... - int lastPos = 0; - int idx = StringFind( - mContent, - mQuery, - lastPos // - ); - while (idx >= 0) - { - // - // Add Position to Result ... - Add( - idx, - result // - ); - - // - lastPos = idx + StringLen(mQuery); - idx = StringFind( - mContent, - mQuery, - lastPos // - ); - } - - // - mResult = ArraySize(result); - - // - return mResult; -} - -// -// Convert From String ... -template -T FromString(string value) -{ - // - T result = NULL; - - // - if (!IsValid(value)) - { - return result; - } - - // - result = (T)value; - - // - return result; -} - -// -// Converts an item to String ... -template -string ToString(T value) -{ - return (string)value; -} - -// -// Used In Report or Summary Generators ... -string ToString( - string prefix, // Title - bool value, // Value - bool ignoreFalseConditions = true, // Ignore False Conditions - string lineSeparator = "\n", // Line Separator - string prefixSeparator = ":" // Title Separator -) -{ - // - string result = NULL; - - // - result = (value || !ignoreFalseConditions) - ? prefix + - prefixSeparator + " " + - ToString(value) + - lineSeparator - : ""; - - // - return result; -} - -// -template -string ToString( - string prefix, // Title - T value, // Value - string lineSeparator = "\n", // Line Separator - string prefixSeparator = ":" // Title Separator -) -{ - // - string result = NULL; - - // - result = prefix + - prefixSeparator + " " + - ToString(value) + - lineSeparator; - - // - return result; -} - -// -string SetLabel( - string mLabel, // Provided Label ... - string value, // Source Value ... - string separator = "\n", // Line Separator - bool addTopEmptyLine = true // Add Empty Line On top -) -{ - // - string result = value; - - // - if (StringLen(mLabel) <= 0) - { - return result; - } - - // - result = (StringLen(value) > 0) - ? (addTopEmptyLine ? separator : "") + - mLabel + - separator + - "-----------------------------" + - separator + - value - : value; - - // - return result; -} - -// -// Converts a Buffer to String Representation ... -template -string ToString( - const T &buffer[], // Specified Buffer - string separator = ",", // Specified Separator - bool addIndex = false, // Specified Add Items Indexes or Not - string indexLabel = "i:", // Specified Index Label - string indexSeparator = ">" // Specified Index Separator -) -{ - // - string result = ""; - - // - int bufferSize = ArraySize(buffer); - if (bufferSize <= 0) - { - return result; - } - - // - for (int i = 0; i < bufferSize; i++) - { - // - if (addIndex) - { - // - if (StringLen(indexLabel) > 0) - { - result += indexLabel + " "; - } - - // - result += (string)i + " "; - - // - if (StringLen(indexSeparator) > 0) - { - result += indexSeparator + " "; - } - } - - // - string iItemString = (string)buffer[i]; - - // - result += iItemString; - - // - if (i < bufferSize - 1) - { - result += separator; - } - } - - // - return result; -} - -// -// Converts String to boolean ... -bool ToBoolean(string value) -{ - // - bool result = false; - - // - if (StringLen(value) <= 0) - { - return result; - } - - // - StringToLower(value); - result = value == "true"; - - // - return result; -} - -// -// Split an String Representation of an Array ... -int SplitContent( - string &result[], // Hold Result ... - string content, // Source ... - string separator = ",", // Separator ... - bool forceCleanResult = true // Clean Result ... -) -{ - // - int mResult = 0; - - // - if (forceCleanResult) - { - Clean(result); - } - - // - int before = ArraySize(result); - - // - if (separator == NULL || StringLen(separator) == 0) - { - separator = ","; - } - - // - if (StringLen(content) == 0) - { - return mResult; - } - - // - StringSplit( - content, - StringGetCharacter( - separator, - 0), - result); - - // - int after = ArraySize(result); - - // - mResult = after - before; - - // - return mResult; -} - -// -// Extract Data from String ... -string ExtractString( - const string source, // Source String used for Extracting - const string startString = "(", // Expression Start String must be Unique - const string endString = ")" // Where to End Extraction, usually a Sign -) -{ - // - string result = ""; - - // - // Validate String ... - if ( - StringLen(source) == 0 || - StringLen(endString) == 0 || - StringLen(startString) == 0) - { - return result; - } - - // - // Find Start String Position ... - int sPos = StringFind( - source, - startString); - if (sPos < 0) - { - return result; - } - - // - // Find End String Position after Start String ... - int searchEndFromPos = sPos + StringLen(startString); - int ePos = StringFind( - source, - endString, - searchEndFromPos); - if (ePos < 0) - { - return result; - } - - // - // Extract Data from Source ... - int dLength = ePos - searchEndFromPos; - result = StringSubstr( - source, - searchEndFromPos, - dLength); - - // - return result; -} - -// -// Extract an Array of Contents ... -int ExtractStrings( - string &result[], // Hold Result - const string source, // Source String used for Extracting - const string startString = "(", // Expression Start String must be Unique - const string endString = ")" // Where to End Extraction, usually a Sign -) -{ - // - int mResult = 0; - - // - Clean(result); - - // - // Validate Args ... - int sourceLength = StringLen(source); - int startLength = StringLen(startString); - int endLength = StringLen(endString); - - // - int minRequiredLength = startLength + endLength; - - // - if ( - endLength <= 0 || - startLength <= 0 || - sourceLength <= 0 || - sourceLength < minRequiredLength) - { - return mResult; - } - - // - // Make a Copy of Source for Manipulating ... - string workStr = source; - - // - // Define a Loop ... - while (StringLen(workStr) > minRequiredLength) - { - // - // Find Item ... - string item = ExtractString( - workStr, - startString, - endString); - - // - // Breakout when couldn't find anymore item ... - int itemLength = StringLen(item); - if (itemLength <= 0) - { - break; - } - - // - // Prepare Item Source String for Replacing in Work String ... - string itemSource = startString + item + endString; - - // - // Add Item to Result Array ... - Add( - item, - result); - - // - // Replace Item Soure in Work String ... - StringReplace( - workStr, - itemSource, - ""); - } - - // - // Calculate Size of Array ... - mResult = ArraySize(result); - - // - return mResult; -} - -// -string ExtractSurrounded( - const string surrounded, // Surrounded Content - const string mToken, // Specified Token - const string startString = "(", // Expression Start String must be Unique - const string endString = ")" // Where to End Extraction, usually a Sign -) -{ - // - return ExtractString( - surrounded, - mToken + startString, - endString - // - ); -} - -// -int ParseIntSurrounded( - const string surrounded, // Surrounded Content - const string mToken, // Specified Token - const string startString = "(", // Expression Start String must be Unique - const string endString = ")" // Where to End Extraction, usually a Sign -) -{ - // - int result = NULL; - - // - string strContent = ExtractSurrounded( - surrounded, - mToken, - startString, - endString - // - ); - if (!IsValid(strContent)) - { - return result; - } - - // - result = (int)strContent; - - // - return result; -} -long ParseLongSurrounded( - const string surrounded, // Surrounded Content - const string mToken, // Specified Token - const string startString = "(", // Expression Start String must be Unique - const string endString = ")" // Where to End Extraction, usually a Sign -) -{ - // - long result = NULL; - - // - string strContent = ExtractSurrounded( - surrounded, - mToken, - startString, - endString - // - ); - if (!IsValid(strContent)) - { - return result; - } - - // - result = (long)strContent; - - // - return result; -} -string ParseStringSurrounded( - const string surrounded, // Surrounded Content - const string mToken, // Specified Token - const string startString = "(", // Expression Start String must be Unique - const string endString = ")" // Where to End Extraction, usually a Sign -) -{ - // - string result = NULL; - - // - string strContent = ExtractSurrounded( - surrounded, - mToken, - startString, - endString - // - ); - if (!IsValid(strContent)) - { - return result; - } - - // - result = (string)strContent; - - // - return result; -} -double ParseDoubleSurrounded( - const string surrounded, // Surrounded Content - const string mToken, // Specified Token - const string startString = "(", // Expression Start String must be Unique - const string endString = ")" // Where to End Extraction, usually a Sign -) -{ - // - double result = NULL; - - // - string strContent = ExtractSurrounded( - surrounded, - mToken, - startString, - endString - // - ); - if (!IsValid(strContent)) - { - return result; - } - - // - result = (double)strContent; - - // - return result; -} -datetime ParseTimeSurrounded( - const string surrounded, // Surrounded Content - const string mToken, // Specified Token - const string startString = "(", // Expression Start String must be Unique - const string endString = ")" // Where to End Extraction, usually a Sign -) -{ - // - datetime result = NULL; - - // - string strContent = ExtractSurrounded( - surrounded, - mToken, - startString, - endString - // - ); - if (!IsValid(strContent)) - { - return result; - } - - // - result = (datetime)strContent; - - // - return result; -} - -// -int ParseIntArraySurrounded( - int &result[], // Holds Result - const string surrounded, // Surrounded Content - const string mToken, // Specified Token - string separator = ",", // Separator ... - const string startString = "(", // Expression Start String must be Unique - const string endString = ")", // Where to End Extraction, usually a Sign - bool forceClean = true // Clean Result ... -) -{ - // - int count = 0; - - // - if (forceClean) - { - Clean(result); - } - - // - int before = ArraySize(result); - - // - string contentStr = ParseStringSurrounded(surrounded, mToken); - if (!IsValid(contentStr)) - { - return count; - } - - // - string tmps[]; - int tmpsCount = SplitContent( - tmps, - contentStr - // - ); - if (tmpsCount <= 0) - { - return count; - } - - // - for (int i = 0; i < tmpsCount; i++) - { - // - string iTMP = tmps[i]; - if (!IsValid(iTMP)) - { - continue; - } - - // - int iValue = (int)iTMP; - - // - Add( - iValue, - result - // - ); - } - - // - int after = ArraySize(result); - - // - count = after - before; - - // - return count; -} -int ParseLongArraySurrounded( - long &result[], // Holds Result - const string surrounded, // Surrounded Content - const string mToken, // Specified Token - string separator = ",", // Separator ... - const string startString = "(", // Expression Start String must be Unique - const string endString = ")", // Where to End Extraction, usually a Sign - bool forceClean = true // Clean Result ... -) -{ - // - int count = 0; - - // - if (forceClean) - { - Clean(result); - } - - // - int before = ArraySize(result); - - // - string contentStr = ParseStringSurrounded(surrounded, mToken); - if (!IsValid(contentStr)) - { - return count; - } - - // - string tmps[]; - int tmpsCount = SplitContent( - tmps, - contentStr - // - ); - if (tmpsCount <= 0) - { - return count; - } - - // - for (int i = 0; i < tmpsCount; i++) - { - // - string iTMP = tmps[i]; - if (!IsValid(iTMP)) - { - continue; - } - - // - long iValue = (long)iTMP; - - // - Add( - iValue, - result - // - ); - } - - // - int after = ArraySize(result); - - // - count = after - before; - - // - return count; -} -int ParseDoubleArraySurrounded( - double &result[], // Holds Result - const string surrounded, // Surrounded Content - const string mToken, // Specified Token - string separator = ",", // Separator ... - const string startString = "(", // Expression Start String must be Unique - const string endString = ")", // Where to End Extraction, usually a Sign - bool forceClean = true // Clean Result ... -) -{ - // - int count = 0; - - // - if (forceClean) - { - Clean(result); - } - - // - int before = ArraySize(result); - - // - string contentStr = ParseStringSurrounded(surrounded, mToken); - if (!IsValid(contentStr)) - { - return count; - } - - // - string tmps[]; - int tmpsCount = SplitContent( - tmps, - contentStr - // - ); - if (tmpsCount <= 0) - { - return count; - } - - // - for (int i = 0; i < tmpsCount; i++) - { - // - string iTMP = tmps[i]; - if (!IsValid(iTMP)) - { - continue; - } - - // - double iValue = (double)iTMP; - - // - Add( - iValue, - result - // - ); - } - - // - int after = ArraySize(result); - - // - count = after - before; - - // - return count; -} -int ParseTimeArraySurrounded( - datetime &result[], // Holds Result - const string surrounded, // Surrounded Content - const string mToken, // Specified Token - string separator = ",", // Separator ... - const string startString = "(", // Expression Start String must be Unique - const string endString = ")", // Where to End Extraction, usually a Sign - bool forceClean = true // Clean Result ... -) -{ - // - int count = 0; - - // - if (forceClean) - { - Clean(result); - } - - // - int before = ArraySize(result); - - // - string contentStr = ParseStringSurrounded(surrounded, mToken); - if (!IsValid(contentStr)) - { - return count; - } - - // - string tmps[]; - int tmpsCount = SplitContent( - tmps, - contentStr - // - ); - if (tmpsCount <= 0) - { - return count; - } - - // - for (int i = 0; i < tmpsCount; i++) - { - // - string iTMP = tmps[i]; - if (!IsValid(iTMP)) - { - continue; - } - - // - datetime iValue = (datetime)iTMP; - - // - Add( - iValue, - result - // - ); - } - - // - int after = ArraySize(result); - - // - count = after - before; - - // - return count; -} - -// -// Surround an String by Specific Token ... -template -string Surround( - string mToken, // an String which used to Tokenize - T &value, // a Value for Tokenize it - string startString = "(", // Token Start Content - string endString = ")" // Token End Content -) -{ - // - string result = NULL; - - // - string strValue = ToString(value); - if (!IsValid(strValue)) - { - return result; - } - - // - result = - // - (IsValid(mToken) - ? mToken - : "") + - // - startString + - strValue + - endString - // - ; - - // - return result; -} - -// -template -string SurroundArray( - string mToken, - T &value[], - string startString = "(", // Token Start Content - string endString = ")" // Token End Content -) -{ - // - string result = NULL; - - // - string valueStr = ToString(value); - if (!IsValid(valueStr)) - { - return result; - } - - // - result = Surround( - mToken, - valueStr, - startString, - endString - // - ); - - // - return result; -} - -// -// Periods / Cycles ... - -// -// Converts an String to TimeFrame ... -ENUM_TIMEFRAMES ToPeriod(string value) -{ - // - if (StringLen(value) == 0) - { - return _Period; - } - - // - StringTrimLeft(value); - StringTrimRight(value); - - // - ENUM_TIMEFRAMES result = _Period; - - // - if (value == "M1") - { - result = PERIOD_M1; - } - else if (value == "M2") - { - result = PERIOD_M2; - } - else if (value == "M3") - { - result = PERIOD_M3; - } - else if (value == "M4") - { - result = PERIOD_M4; - } - else if (value == "M5") - { - result = PERIOD_M5; - } - else if (value == "M6") - { - result = PERIOD_M6; - } - else if (value == "M10") - { - result = PERIOD_M10; - } - else if (value == "M12") - { - result = PERIOD_M12; - } - else if (value == "M15") - { - result = PERIOD_M15; - } - else if (value == "M20") - { - result = PERIOD_M20; - } - else if (value == "M30") - { - result = PERIOD_M30; - } - else if (value == "H1") - { - result = PERIOD_H1; - } - else if (value == "H2") - { - result = PERIOD_H2; - } - else if (value == "H3") - { - result = PERIOD_H3; - } - else if (value == "H4") - { - result = PERIOD_H4; - } - else if (value == "H6") - { - result = PERIOD_H6; - } - else if (value == "H8") - { - result = PERIOD_H8; - } - else if (value == "H12") - { - result = PERIOD_H12; - } - else if (value == "D1") - { - result = PERIOD_D1; - } - else if (value == "W1") - { - result = PERIOD_W1; - } - else if (value == "MN1") - { - result = PERIOD_MN1; - } - - // - return result; -} - -// -// Converts Period to String ... -string ToString(ENUM_TIMEFRAMES mPeriod) -{ - // - string result = ""; - - // - string mPStr = EnumToString(mPeriod); - - string mPStrParts[]; - int partsCount = StringSplit( - mPStr, - StringGetCharacter("_", 0), - mPStrParts); - if (partsCount <= 0) - { - return result; - } - - // - result = mPStrParts[1]; - - // - return result; -} - -// -// Retrieve All Available Period as an Array ...s -int GetAllAvailablePeriods( - ENUM_TIMEFRAMES &result[] // Holds Result ... -) -{ - // - Clean(result); - - // - Add( - PERIOD_M1, - result - // - ); - - // - Add( - PERIOD_M2, - result - // - ); - - // - Add( - PERIOD_M3, - result - // - ); - - // - Add( - PERIOD_M4, - result - // - ); - - // - Add( - PERIOD_M5, - result - // - ); - - // - Add( - PERIOD_M6, - result - // - ); - - // - Add( - PERIOD_M10, - result - // - ); - - // - Add( - PERIOD_M12, - result - // - ); - - // - Add( - PERIOD_M15, - result - // - ); - - // - Add( - PERIOD_M20, - result - // - ); - - // - Add( - PERIOD_M30, - result - // - ); - - // - Add( - PERIOD_H1, - result - // - ); - - // - Add( - PERIOD_H2, - result - // - ); - - // - Add( - PERIOD_H3, - result - // - ); - - // - Add( - PERIOD_H4, - result - // - ); - - // - Add( - PERIOD_H6, - result - // - ); - - // - Add( - PERIOD_H8, - result - // - ); - - // - Add( - PERIOD_H12, - result - // - ); - - // - Add( - PERIOD_D1, - result - // - ); - - // - Add( - PERIOD_W1, - result - // - ); - - // - Add( - PERIOD_MN1, - result - // - ); - - // - int mResult = ArraySize(result); - - // - return mResult; -} - -// -// Get Specific Time Frame Start Candle Time ... -datetime GetPeriodStartTime( - string mSymbol = NULL, // Specified Symbol ... - ENUM_TIMEFRAMES mPeriod = NULL, // Specified Period ... - datetime mTime = NULL // Specified Bar Time of Host Period ... -) -{ - // - // Normalize Arg ... - mTime = NormalizeTime(mTime); - mSymbol = NormalizeSymbol(mSymbol); - mPeriod = NormalizePeriod(mPeriod); - - // - int barIndex = iBarShift( - mSymbol, - mPeriod, - mTime, - false - // - ); - - // - datetime result = GetBarTime( - mSymbol, - mPeriod, - barIndex - // - ); - - // - return result; -} - -// -// Converts an String to it's related Market Cycle ... -ENUM_X_MARKET_CYCLES ToCycle(string value) -{ - // - ENUM_X_MARKET_CYCLES result = X_MARKET_CYCLE_UNKNOWN; - - // - ENUM_X_MARKET_CYCLES cycles[]; - int count = GetAllMarketCycles(cycles); - for (int i = 0; i < count; i++) - { - // - ENUM_X_MARKET_CYCLES iCycle = cycles[i]; - string iStr = ToString(iCycle); - - // - if (value == iStr) - { - // - result = iCycle; - break; - } - } - - // - return result; -} - -// -// Converts a Cycle to it's String Representation ... -string ToString(ENUM_X_MARKET_CYCLES cycle) -{ - // - string result = ""; - - // - string mPStr = EnumToString(cycle); - - string mPStrParts[]; - int partsCount = StringSplit( - mPStr, - StringGetCharacter("_", 0), - mPStrParts); - if (partsCount <= 0) - { - return result; - } - - // - result = mPStrParts[3]; - - // - return result; -} - -// -// Retrieve all Available Cycles ... -int GetAllMarketCycles(ENUM_X_MARKET_CYCLES &result[]) -{ - // - int mResult = 0; - - // - Clean(result); - - // - ENUM_X_MARKET_CYCLES tmp[] = { - X_MARKET_CYCLE_UNKNOWN, - X_MARKET_CYCLE_SHORT, - X_MARKET_CYCLE_MEDIUM, - X_MARKET_CYCLE_LONG, - X_MARKET_CYCLE_HIND}; - - // - Copy( - tmp, - result // - ); - - // - Clean(tmp); - - // - mResult = ArraySize(result); - - // - return mResult; -} - -// -// Retrieve Nearest Period base on Given Period ... -ENUM_TIMEFRAMES GetNearestPeriod(ENUM_TIMEFRAMES mPeriod) -{ - // - ENUM_TIMEFRAMES result = _Period; - - // - mPeriod = NormalizePeriod(mPeriod); - - // - switch (mPeriod) - { - // - case PERIOD_M1: - case PERIOD_M2: - case PERIOD_M3: - result = PERIOD_M5; - break; - - // - case PERIOD_M4: - case PERIOD_M5: - case PERIOD_M6: - result = PERIOD_M10; - break; - - // - case PERIOD_M10: - case PERIOD_M12: - case PERIOD_M15: - result = PERIOD_M20; - break; - - // - case PERIOD_M20: - case PERIOD_M30: - result = PERIOD_H1; - break; - - // - case PERIOD_H1: - case PERIOD_H2: - result = PERIOD_H3; - break; - - // - case PERIOD_H3: - result = PERIOD_H4; - break; - - // - case PERIOD_H4: - result = PERIOD_H6; - break; - - // - case PERIOD_H6: - result = PERIOD_H8; - break; - - // - case PERIOD_H8: - result = PERIOD_H12; - break; - - // - default: - result = mPeriod; - break; - } - - // - return result; -} - -// -// Retrieve Mediest Period base on Given Period ... -ENUM_TIMEFRAMES GetMediestPeriod(ENUM_TIMEFRAMES mPeriod) -{ - // - ENUM_TIMEFRAMES result = _Period; - - // - mPeriod = NormalizePeriod(mPeriod); - - // - switch (mPeriod) - { - // - case PERIOD_M1: - case PERIOD_M2: - case PERIOD_M3: - result = PERIOD_M10; - break; - - // - case PERIOD_M4: - case PERIOD_M5: - case PERIOD_M6: - result = PERIOD_M15; - break; - - // - case PERIOD_M10: - case PERIOD_M12: - case PERIOD_M15: - result = PERIOD_M30; - break; - - // - case PERIOD_M20: - case PERIOD_M30: - result = PERIOD_H2; - break; - - // - case PERIOD_H1: - case PERIOD_H2: - result = PERIOD_H4; - break; - - // - case PERIOD_H3: - result = PERIOD_H6; - break; - - // - case PERIOD_H4: - result = PERIOD_H8; - break; - - // - case PERIOD_H6: - result = PERIOD_H12; - break; - - // - case PERIOD_H8: - result = PERIOD_D1; - break; - - // - default: - result = mPeriod; - break; - } - - // - return result; -} - -// -// Retrieve Longest Period base on Given Period ... -ENUM_TIMEFRAMES GetLongestPeriod(ENUM_TIMEFRAMES mPeriod) -{ - // - ENUM_TIMEFRAMES result = _Period; - - // - mPeriod = NormalizePeriod(mPeriod); - - // - switch (mPeriod) - { - // - case PERIOD_M1: - case PERIOD_M2: - case PERIOD_M3: - result = PERIOD_M30; - break; - - // - case PERIOD_M4: - case PERIOD_M5: - case PERIOD_M6: - result = PERIOD_H1; - break; - - // - case PERIOD_M10: - case PERIOD_M12: - case PERIOD_M15: - result = PERIOD_H2; - break; - - // - case PERIOD_M20: - case PERIOD_M30: - result = PERIOD_H4; - break; - - // - case PERIOD_H1: - case PERIOD_H2: - result = PERIOD_H6; - break; - - // - case PERIOD_H3: - result = PERIOD_H8; - break; - - // - case PERIOD_H4: - result = PERIOD_H12; - break; - - // - case PERIOD_H6: - result = PERIOD_D1; - break; - - // - case PERIOD_H8: - result = PERIOD_W1; - break; - - // - default: - result = mPeriod; - break; - } - - // - return result; -} - -// -// Retrieve Hindmost Period base on Given Period ... -ENUM_TIMEFRAMES GetHindMostPeriod(ENUM_TIMEFRAMES mPeriod) -{ - // - ENUM_TIMEFRAMES result = _Period; - - // - mPeriod = NormalizePeriod(mPeriod); - - // - switch (mPeriod) - { - // - case PERIOD_M1: - case PERIOD_M2: - case PERIOD_M3: - result = PERIOD_H1; - break; - - // - case PERIOD_M4: - case PERIOD_M5: - case PERIOD_M6: - result = PERIOD_H2; - break; - - // - case PERIOD_M10: - case PERIOD_M12: - case PERIOD_M15: - result = PERIOD_H4; - break; - - // - case PERIOD_M20: - case PERIOD_M30: - result = PERIOD_H6; - break; - - // - case PERIOD_H1: - case PERIOD_H2: - result = PERIOD_H8; - break; - - // - case PERIOD_H3: - result = PERIOD_H12; - break; - - // - case PERIOD_H4: - result = PERIOD_D1; - break; - - // - case PERIOD_H6: - result = PERIOD_W1; - break; - - // - case PERIOD_H8: - result = PERIOD_MN1; - break; - - // - default: - result = mPeriod; - break; - } - - // - return result; -} - -// -// Retrieve Specified Cycles Period related to Host Period ... -ENUM_TIMEFRAMES GetCyclePeriod( - ENUM_X_MARKET_CYCLES mCycle = NULL, // Specified Cycle - ENUM_TIMEFRAMES mPeriod = NULL // Host Period -) -{ - // - ENUM_TIMEFRAMES result = NULL; - - // - mPeriod = NormalizePeriod(mPeriod); - mCycle = NormalizeCycle(mCycle); - - // - switch (mCycle) - { - // - // Short ... - case X_MARKET_CYCLE_SHORT: - result = GetNearestPeriod(mPeriod); - break; - - // - // Medium ... - case X_MARKET_CYCLE_MEDIUM: - result = GetMediestPeriod(mPeriod); - break; - - // - // Long ... - case X_MARKET_CYCLE_LONG: - result = GetLongestPeriod(mPeriod); - break; - - // - // Hind ... - case X_MARKET_CYCLE_HIND: - result = GetHindMostPeriod(mPeriod); - break; - } - - // - return result; -} - -// -// Calculate a Cycle Length based on Host Period ... -int GetCycleLengthOn( - ENUM_TIMEFRAMES _hostPeriod, - ENUM_X_MARKET_CYCLES _cycle, - ENUM_X_PERIOD_METHOD _method, - ENUM_TIMEFRAMES _period // -) -{ - // - int result = 0; - - // - // Validate ... - bool isValid = - // - IsValid(_hostPeriod) && - IsValid(_method, _Period) - // - ; - if (!isValid) - { - return result; - } - - // - // Calculate Period ... - isValid = - _method != X_PERIOD_NOTHING && - _cycle != X_MARKET_CYCLE_UNKNOWN; - if (!isValid) - { - return result; - } - - // - if (_method == X_PERIOD_AUTO) - { - // - _period = GetCyclePeriod( - _cycle, - _hostPeriod // - ); - } - isValid = IsValid(_period); - if (!isValid) - { - return result; - } - - // - int _hostPeriodSeconds = PeriodSeconds(_hostPeriod); - int _periodSeconds = PeriodSeconds(_period); - - // - isValid = _periodSeconds >= _hostPeriodSeconds; - if (!isValid) - { - return result; - } - - // - result = _periodSeconds / _hostPeriodSeconds; - - // - return result; -} - -// -// Direction ... - -// -bool HasDirection(ENUM_X_DIRECTION value) -{ - // - bool result = false; - - // - result = value != X_DIRECTION_NONE && - value != X_DIRECTION_ALL; - - // - return result; -} - -// -bool IsBullish(ENUM_X_DIRECTION value) -{ - // - bool result = false; - - // - result = value == X_DIRECTION_BULLISH; - - // - return result; -} -bool IsSpecifiedBullish(ENUM_X_DIRECTION value) -{ - // - bool result = false; - - // - result = value == X_DIRECTION_BULLISH; - - // - return result; -} - -// -bool IsBearish(ENUM_X_DIRECTION value) -{ - // - bool result = false; - - // - result = value == X_DIRECTION_BEARISH; - - // - return result; -} -bool IsSpecifiedBearish(ENUM_X_DIRECTION value) -{ - // - bool result = false; - - // - result = value == X_DIRECTION_BEARISH; - - // - return result; -} - -// -ENUM_X_DIRECTION Opposit(ENUM_X_DIRECTION value) -{ - // - ENUM_X_DIRECTION result = X_DIRECTION_NONE; - - // - if (!HasDirection(value)) - { - return result; - } - - // - result = - IsBullish(value) - ? X_DIRECTION_BEARISH - : X_DIRECTION_BULLISH; - - // - return result; -} - -// -// Moving Average ... - -enum ENUM_X_MA_METHOD -{ - X_MA_MODE_NONE, // None - X_MA_MODE_SMA, // SMA - X_MA_MODE_EMA, // EMA - X_MA_MODE_LWMA, // LWMA - X_MA_MODE_SMMA, // SMMA -}; - -/** - * Calculate Sspecified Buffer's Moving Averages ... - * - * @param rates_total: Integer, number of items ... - * @param prev_calculated: Integer, Previous Calculate Items ... - * @param begin: Integer, Bar Index ... - * @param period: Integer, Moving Average Length ... - * @param source: Double Array, Specified Array for Calculating Moving Averages ... - * @param buffer: Double Array, Specified Array to Apply Calculated Moving Average on it ... - * @param method: ENUM_MA_METHOD member Specified Moving Average Calculation Method ... - * - * @return ( int ) - */ -int iMAOnBuffer( - const int _rates_total, - const int _prev_calculated, - const int _begin, - const int _period, - const double &_source[], - double &_buffer[], - ENUM_X_MA_METHOD _method = X_MA_MODE_SMA // -) -{ - // - int result = 0; - - // - if ( - _period < 0 || - _rates_total <= 0 || - _prev_calculated < 0 || - _method == X_MA_MODE_NONE || - _prev_calculated > _rates_total) - { - return result; - } - - // - switch (_method) - { - // - case X_MA_MODE_SMA: - result = SimpleMAOnBuffer( - _rates_total, - _prev_calculated, - _begin, - _period, - _source, - _buffer // - ); - break; - - // - case X_MA_MODE_EMA: - result = ExponentialMAOnBuffer( - _rates_total, - _prev_calculated, - _begin, - _period, - _source, - _buffer // - ); - break; - - // - case X_MA_MODE_LWMA: - result = LinearWeightedMAOnBuffer( - _rates_total, - _prev_calculated, - _begin, - _period, - _source, - _buffer // - ); - break; - - // - case X_MA_MODE_SMMA: - result = SmoothedMAOnBuffer( - _rates_total, - _prev_calculated, - _begin, - _period, - _source, - _buffer // - ); - break; - } - - // - return result; -} - // \ No newline at end of file diff --git a/Libraries/x-saherelm.common.models.lib.mq5 b/Libraries/x-saherelm.common.models.lib.mq5 new file mode 100644 index 00000000..4cd05ace --- /dev/null +++ b/Libraries/x-saherelm.common.models.lib.mq5 @@ -0,0 +1,24 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Common Library +// -------------------------------------- +// Name: XModelsLib +// Description: provide all commonly used functions ... +// +// +// 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 + +// +#include "../Libraries/x-saherelm.common.extensions.lib.mq5" + diff --git a/Libraries/x-saherelm.x-enums.lib.mq5 b/Libraries/x-saherelm.x-enums.lib.mq5 new file mode 100644 index 00000000..64b18aef --- /dev/null +++ b/Libraries/x-saherelm.x-enums.lib.mq5 @@ -0,0 +1,1166 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Common Library +// -------------------------------------- +// Name: XEnumsLib +// Description: provide all commonly used functions ... +// +// +// 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 + +// +// START Price Type ... +// + +// +// Availables Price Types ... +enum ENUM_X_PRICE +{ + X_PRICE_NONE, // None + X_PRICE_HIGH, // High + X_PRICE_OPEN, // Open + X_PRICE_CLOSE, // Close + X_PRICE_LOW, // Low + X_PRICE_UP, // Body Up + X_PRICE_DOWN, // Body Down + X_PRICE_MEDIAN, // Median + X_PRICE_BODY_MEDIAN, // Body Median + X_PRICE_TYPICAL, // Typical + X_PRICE_WEIGHTED // Weighted +}; + +// +// Extensions ... + +/** + * Validate ... + * + * @param value: ENUM_X_PRICE member ... + * + * @return ( bool ) + */ +bool IsValid(ENUM_X_PRICE value) +{ + // + bool result = false; + + // + result = + value != NULL && + value != X_PRICE_NONE; + + // + return result; +} + +/** + * Converts Series Mode to ENUM_X_PRICE ... + * + * @param value: ENUM_SERIESMODE member ... + * + * @return ( ENUM_X_PRICE ) + */ +ENUM_X_PRICE ToXPrice(ENUM_SERIESMODE value) +{ + // + ENUM_X_PRICE result = X_PRICE_CLOSE; + + // + switch (value) + { + // + // High ... + case MODE_HIGH: + result = X_PRICE_HIGH; + break; + + // + // Open ... + case MODE_OPEN: + result = X_PRICE_OPEN; + break; + + // + // Low ... + case MODE_LOW: + result = X_PRICE_LOW; + break; + + // + // Close ... + // Default ... + case MODE_CLOSE: + default: + result = X_PRICE_CLOSE; + break; + } + + // + return result; +} + +/** + * Converts Applied Price to ENUM_X_PRICE ... + * + * @param value: ENUM_APPLIED_PRICE member ... + * + * @return ( ENUM_X_PRICE ) + */ +ENUM_X_PRICE ToXPrice(ENUM_APPLIED_PRICE value) +{ + // + ENUM_X_PRICE result = X_PRICE_NONE; + + // + switch (value) + { + // + case PRICE_HIGH: + result = X_PRICE_HIGH; + break; + + // + case PRICE_OPEN: + result = X_PRICE_OPEN; + break; + + // + case PRICE_CLOSE: + result = X_PRICE_CLOSE; + break; + + // + case PRICE_LOW: + result = X_PRICE_LOW; + break; + + // + case PRICE_MEDIAN: + result = X_PRICE_MEDIAN; + break; + + // + case PRICE_TYPICAL: + result = X_PRICE_TYPICAL; + break; + + // + case PRICE_WEIGHTED: + result = X_PRICE_WEIGHTED; + break; + } + + // + return result; +} + +/** + * Converts Price Type to Applied Price ... + * + * @param value: ENUM_X_PRICE member ... + * + * @return ( ENUM_APPLIED_PRICE ) + */ +ENUM_APPLIED_PRICE ToAppliedPrice(ENUM_X_PRICE value) +{ + // + // Default ... + ENUM_APPLIED_PRICE result = PRICE_CLOSE; + + // + if (!IsValid(value) || + value == X_PRICE_UP || + value == X_PRICE_DOWN || + value == X_PRICE_BODY_MEDIAN) + { + return result; + } + + // + switch (value) + { + // + case X_PRICE_HIGH: + result = PRICE_HIGH; + break; + + // + case X_PRICE_OPEN: + result = PRICE_OPEN; + break; + + // + case X_PRICE_CLOSE: + result = PRICE_CLOSE; + break; + + // + case X_PRICE_LOW: + result = PRICE_LOW; + break; + + // + case X_PRICE_MEDIAN: + result = PRICE_MEDIAN; + break; + + // + case X_PRICE_TYPICAL: + result = PRICE_TYPICAL; + break; + + // + case X_PRICE_WEIGHTED: + result = PRICE_WEIGHTED; + break; + } + + // + return result; +} + +/** + * Converts To String ... + * + * @param value: ENUM_X_PRICE member ... + * + * @return ( string ) + */ +string ToString(ENUM_X_PRICE value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_PRICE_NONE: + result = "None"; + break; + + // + case X_PRICE_HIGH: + result = "High"; + break; + + // + case X_PRICE_OPEN: + result = "Open"; + break; + + // + case X_PRICE_CLOSE: + result = "Close"; + break; + + // + case X_PRICE_LOW: + result = "Low"; + break; + + // + case X_PRICE_UP: + result = "Body Up"; + break; + + // + case X_PRICE_DOWN: + result = "Body Down"; + break; + + // + case X_PRICE_MEDIAN: + result = "Median"; + break; + + // + case X_PRICE_BODY_MEDIAN: + result = "Body Median"; + break; + + // + case X_PRICE_TYPICAL: + result = "Typical"; + break; + + // + case X_PRICE_WEIGHTED: + result = "Weighted"; + break; + } + + // + return result; +} + +// +// END Price Type ... +// + +// +// START Direction ... +// + +// +// Directions ... +enum ENUM_X_DIRECTION +{ + X_DIRECTION_ALL, // All + X_DIRECTION_NONE, // None + X_DIRECTION_BULLISH, // Bullish + X_DIRECTION_BEARISH, // Bearish +}; + +// +// Extensions ... + +/** + * Validate ... + * + * @param value: ENUM_X_DIRECTION member ... + * + * @return ( bool ) + */ +bool IsValid(ENUM_X_DIRECTION value) +{ + // + bool result = false; + + // + result = + value != NULL && + value != X_DIRECTION_NONE; + + // + return result; +} + +/** + * Validate value Has Specified Direction ... + * + * @param value: ENUM_X_DIRECTION member ... + * + * @return ( bool ) + */ +bool HasDirection(ENUM_X_DIRECTION value) +{ + // + bool result = false; + + // + result = IsValid(value) && + value != X_DIRECTION_ALL; + + // + return result; +} + +/** + * Check a Direction is Bullish or not ... + * + * @param value: ENUM_X_DIRECTION member ... + * + * @return ( bool ) + */ +bool IsBullish(ENUM_X_DIRECTION value) +{ + // + bool result = false; + + // + result = value == X_DIRECTION_BULLISH; + + // + return result; +} +bool IsSpecifiedBullish(ENUM_X_DIRECTION value) +{ + // + bool result = false; + + // + result = value == X_DIRECTION_BULLISH; + + // + return result; +} + +/** + * Check a Direction is Bearish or not ... + * + * @param value: ENUM_X_DIRECTION member ... + * + * @return ( bool ) + */ +bool IsBearish(ENUM_X_DIRECTION value) +{ + // + bool result = false; + + // + result = value == X_DIRECTION_BEARISH; + + // + return result; +} +bool IsSpecifiedBearish(ENUM_X_DIRECTION value) +{ + // + bool result = false; + + // + result = value == X_DIRECTION_BEARISH; + + // + return result; +} + +/** + * Converts Specified Direction to Opposit ... + * + * @param value: ENUM_X_DIRECTION member ... + * + * @return ( ENUM_X_DIRECTION ) + */ +ENUM_X_DIRECTION Opposit(ENUM_X_DIRECTION value) +{ + // + ENUM_X_DIRECTION result = X_DIRECTION_NONE; + + // + if (!HasDirection(value)) + { + return result; + } + + // + result = + IsBullish(value) + ? X_DIRECTION_BEARISH + : X_DIRECTION_BULLISH; + + // + return result; +} + +/** + * Converts To String ... + * + * @param value: ENUM_X_DIRECTION member ... + * + * @return ( string ) + */ +string ToString(ENUM_X_DIRECTION value) +{ + // + string result = NULL; + + // + switch (value) + { + case X_DIRECTION_ALL: + result = "ALL"; + break; + case X_DIRECTION_NONE: + result = "NONE"; + break; + case X_DIRECTION_BULLISH: + result = "BULLISH"; + break; + case X_DIRECTION_BEARISH: + result = "BEARISH"; + break; + } + + // + return result; +} + +// +// END Direction ... +// + +// +// START Fibo Level ... +// + +// +// Fibonacci Levels ... +enum ENUM_X_FIBO_LEVELS +{ + X_FIBO_LEVEL_236, // 0.236 + X_FIBO_LEVEL_270, // 0.27 + X_FIBO_LEVEL_382, // 0.382 + X_FIBO_LEVEL_500, // 0.5 + X_FIBO_LEVEL_618, // 0.618 + X_FIBO_LEVEL_786, // 0.786 +}; + +// +// Extensions ... + +/** + * Converts To String ... + * + * @param value: ENUM_X_FIBO_LEVELS member ... + * + * @return ( string ) + */ +string ToString(ENUM_X_FIBO_LEVELS value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_FIBO_LEVEL_236: + result = "0.236"; + break; + + // + case X_FIBO_LEVEL_270: + result = "0.270"; + break; + + // + case X_FIBO_LEVEL_382: + result = "0.382"; + break; + + // + case X_FIBO_LEVEL_500: + result = "0.500"; + break; + + // + case X_FIBO_LEVEL_618: + result = "0.618"; + break; + + // + case X_FIBO_LEVEL_786: + result = "0.786"; + break; + } + + // + return result; +} + +/** + * Converts To String ... + * + * @param value: ENUM_X_FIBO_LEVELS member ... + * + * @return ( double ) + */ +double GetFiboLevelValue(ENUM_X_FIBO_LEVELS value) +{ + // + double result = 0; + + // + switch (value) + { + // + case X_FIBO_LEVEL_236: + result = 0.236; + break; + + // + case X_FIBO_LEVEL_270: + result = 0.270; + break; + + // + case X_FIBO_LEVEL_382: + result = 0.382; + break; + + // + case X_FIBO_LEVEL_500: + result = 0.500; + break; + + // + case X_FIBO_LEVEL_618: + result = 0.618; + break; + + // + case X_FIBO_LEVEL_786: + result = 0.786; + break; + } + + // + return result; +} + +// +// END Fibo Level ... +// + +// +// START Swing Types ... +// + +// +// Swing Types ... +enum ENUM_X_SWING_TYPE +{ + X_SWING_NONE, // None + X_SWING_LOW, // Swing Low + X_SWING_HIGH, // Swing High +}; + +// +// Extensions ... + +/** + * Validate ... + * + * @param value: ENUM_X_DIRECTION member ... + * + * @return ( bool ) + */ +bool IsValid(ENUM_X_SWING_TYPE value) +{ + // + bool result = false; + + // + result = + value != NULL && + value != X_SWING_NONE; + + // + return result; +} + +/** + * Converts To String ... + * + * @param value: ENUM_X_SWING_TYPE member ... + * + * @return ( string ) + */ +string ToString(ENUM_X_SWING_TYPE value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_SWING_NONE: + result = "None"; + break; + + // + case X_SWING_LOW: + result = "Swing Low"; + break; + + // + case X_SWING_HIGH: + result = "Swing High"; + break; + } + + // + return result; +} + +/** + * Converts To ENUM_SERIESMODE ... + * + * @param value: ENUM_X_SWING_TYPE member ... + * + * @return ( ENUM_SERIESMODE ) + */ +ENUM_SERIESMODE ToSeriesMode(ENUM_X_SWING_TYPE value) +{ + // + ENUM_SERIESMODE result = MODE_HIGH; + + // + switch (value) + { + // + case X_SWING_HIGH: + result = MODE_HIGH; + break; + + // + case X_SWING_LOW: + default: + result = MODE_LOW; + break; + } + + // + return result; +} + +// +// END Swing Types ... +// + +// +// START Period Method ... +// + +// +// Period Calculation Method ... +enum ENUM_X_PERIOD_METHOD +{ + X_PERIOD_NONE, // None + X_PERIOD_AUTO, // Auto Select + X_PERIOD_MANUALLY // Manually +}; + +// +// Extensions ... + +/** + * Validate ... + * + * @param value: ENUM_X_PERIOD_METHOD member ... + * + * @return ( bool ) + */ +bool IsValid(ENUM_X_PERIOD_METHOD value) +{ + // + bool result = false; + + // + result = + value != NULL && + value != X_PERIOD_NONE; + + // + return result; +} + +/** + * Converts To String ... + * + * @param value: ENUM_X_PERIOD_METHOD member ... + * + * @return ( string ) + */ +string ToString(ENUM_X_PERIOD_METHOD value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_PERIOD_NONE: + result = "None"; + break; + + // + case X_PERIOD_AUTO: + result = "Auto Select"; + break; + + // + case X_PERIOD_MANUALLY: + result = "Manually"; + break; + } + + // + return result; +} + +// +// END Period Method ... +// + +// +// START Market Cycles ... +// + +// +// Market Cycles ... +enum ENUM_X_MARKET_CYCLES +{ + X_MARKET_CYCLE_UNKNOWN, // Unknown Cycle + X_MARKET_CYCLE_SHORT, // Short Cycle + X_MARKET_CYCLE_MEDIUM, // Medium Cycle + X_MARKET_CYCLE_LONG, // Long Cycle + X_MARKET_CYCLE_HIND, // Hind Cycle +}; + +// +// Extensions ... + +/** + * Validate ... + * + * @param value: ENUM_X_MARKET_CYCLES member ... + * + * @return ( bool ) + */ +bool IsValid(ENUM_X_MARKET_CYCLES value) +{ + // + bool result = false; + + // + result = + // + value != NULL && + value != X_MARKET_CYCLE_UNKNOWN + // + ; + + // + return result; +} + +/** + * Converts an String to it's related Market Cycle ... + * + * @param value: string ... + * + * @return ( ENUM_X_MARKET_CYCLES ) + */ +ENUM_X_MARKET_CYCLES ToCycle(string value) +{ + // + ENUM_X_MARKET_CYCLES result = X_MARKET_CYCLE_UNKNOWN; + + // + ENUM_X_MARKET_CYCLES cycles[]; + int count = GetAllMarketCycles(cycles); + for (int i = 0; i < count; i++) + { + // + ENUM_X_MARKET_CYCLES iCycle = cycles[i]; + string iStr = ToString(iCycle); + + // + if (value == iStr) + { + // + result = iCycle; + break; + } + } + + // + return result; +} + +/** + * Converts To String ... + * + * @param value: ENUM_X_MARKET_CYCLES member ... + * + * @return ( string ) + */ +string ToString(ENUM_X_MARKET_CYCLES value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_MARKET_CYCLE_UNKNOWN: + result = "Unknown Cycle"; + break; + + // + case X_MARKET_CYCLE_SHORT: + result = "Short Cycle"; + break; + + // + case X_MARKET_CYCLE_MEDIUM: + result = "Medium Cycle"; + break; + + // + case X_MARKET_CYCLE_LONG: + result = "Long Cycle"; + break; + + // + case X_MARKET_CYCLE_HIND: + result = "Hind Cycle"; + break; + } + + // + return result; +} + +/** + * Retrieve All Availabled Market Cycles ... + * + * @param cycles: ENUM_X_MARKET_CYCLES member collection ... + * + * @return ( int ) + */ +int GetAllMarketCycles(ENUM_X_MARKET_CYCLES &cycles[]) +{ + // + ZeroMemory(cycles); + ArrayResize(cycles, 0); + + // + ArrayResize(cycles, ArraySize(cycles) + 1); + cycles[ArraySize(cycles) - 1] = X_MARKET_CYCLE_UNKNOWN; + + // + ArrayResize(cycles, ArraySize(cycles) + 1); + cycles[ArraySize(cycles) - 1] = X_MARKET_CYCLE_SHORT; + + // + ArrayResize(cycles, ArraySize(cycles) + 1); + cycles[ArraySize(cycles) - 1] = X_MARKET_CYCLE_MEDIUM; + + // + ArrayResize(cycles, ArraySize(cycles) + 1); + cycles[ArraySize(cycles) - 1] = X_MARKET_CYCLE_LONG; + + // + ArrayResize(cycles, ArraySize(cycles) + 1); + cycles[ArraySize(cycles) - 1] = X_MARKET_CYCLE_HIND; + + // + int result = ArraySize(cycles); + + // + return result; +} + +// +// END Market Cycles ... +// + +// +// START Week Days ... +// + +// +// Week Days ... +enum ENUM_X_WEEK_DAYS +{ + X_WEEK_DAY_NONE = -1, // None + X_WEEK_DAY_SUNDAY = 0, // Sunday + X_WEEK_DAY_MONDAY = 1, // Monday + X_WEEK_DAY_TUESDAY = 2, // Tuesday + X_WEEK_DAY_WEDNESDAY = 3, // Wednesday + X_WEEK_DAY_THURSDAY = 4, // Thursday + X_WEEK_DAY_FRIDAY = 5, // Friday + X_WEEK_DAY_SATURDAY = 6, // Saturday +}; + +// +// Extensions ... + +/** + * Validate ... + * + * @param value: ENUM_X_WEEK_DAYS member ... + * + * @return ( bool ) + */ +bool IsValid(ENUM_X_WEEK_DAYS value) +{ + // + bool result = false; + + // + result = + // + value != NULL && + value != X_WEEK_DAY_NONE + // + ; + + // + return result; +} + +/** + * Converts To String ... + * + * @param value: ENUM_X_WEEK_DAYS member ... + * + * @return ( string ) + */ +string ToString(ENUM_X_WEEK_DAYS value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_WEEK_DAY_NONE: + result = "None"; + break; + + // + case X_WEEK_DAY_SUNDAY: + result = "Sunday"; + break; + + // + case X_WEEK_DAY_MONDAY: + result = "Monday"; + break; + + // + case X_WEEK_DAY_TUESDAY: + result = "Tuesday"; + break; + + // + case X_WEEK_DAY_WEDNESDAY: + result = "Wednesday"; + break; + + // + case X_WEEK_DAY_THURSDAY: + result = "Thursday"; + break; + + // + case X_WEEK_DAY_FRIDAY: + result = "Friday"; + break; + + // + case X_WEEK_DAY_SATURDAY: + result = "Saturday"; + break; + } + + // + return result; +} + +// +// END Week Days ... +// + +// +// START Ma Methods ... +// + +// +// Ma Methods ... +enum ENUM_X_MA_METHOD +{ + X_MA_MODE_NONE, // None + X_MA_MODE_SMA, // SMA + X_MA_MODE_EMA, // EMA + X_MA_MODE_LWMA, // LWMA + X_MA_MODE_SMMA, // SMMA +}; + +// +// Extensions ... + +/** + * Validate ... + * + * @param value: ENUM_X_MA_METHOD member ... + * + * @return ( bool ) + */ +bool IsValid(ENUM_X_MA_METHOD value) +{ + // + bool result = false; + + // + result = + // + value != NULL && + value != X_MA_MODE_NONE + // + ; + + // + return result; +} + +/** + * Converts To String ... + * + * @param value: ENUM_X_MA_METHOD member ... + * + * @return ( string ) + */ +string ToString(ENUM_X_MA_METHOD value) +{ + // + string result = NULL; + + // + switch (value) + { + // + case X_MA_MODE_NONE: + result = "None"; + break; + + // + case X_MA_MODE_SMA: + result = "SMA"; + break; + + // + case X_MA_MODE_EMA: + result = "EMA"; + break; + + // + case X_MA_MODE_LWMA: + result = "LWMA"; + break; + + // + case X_MA_MODE_SMMA: + result = "SMMA"; + break; + } + + // + return result; +} + +// +// END Ma Methods ... +// + +// \ No newline at end of file diff --git a/Libraries/x-saherelm.x-ohcl.lib.mq5 b/Libraries/x-saherelm.x-ohcl.lib.mq5 new file mode 100644 index 00000000..2403460c --- /dev/null +++ b/Libraries/x-saherelm.x-ohcl.lib.mq5 @@ -0,0 +1,1874 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Common Library +// -------------------------------------- +// Name: XOHCLLib +// Description: provide all commonly used functions ... +// +// +// 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 + +// +#include "../Libraries/x-saherelm.common.extensions.lib.mq5" + +// +// Describe an Specific Candle ... +struct XOHCL +{ + // + // Props ... + + // + double high; + double open; + double close; + double low; + double spread; + + // + string symbol; + datetime time; + ENUM_TIMEFRAMES period; + + // + // Constructor ... + XOHCL() + { + Clean(); + } + + // + // Init a Bar ... + // Using Bar Index ... + bool Init( + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Period + int barIndex = 0 // Bar Index + ) + { + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + symbol = mSymbol; + period = mPeriod; + + // + time = iTime( + mSymbol, + mPeriod, + barIndex // + ); + + // + open = iOpen( + mSymbol, + mPeriod, + barIndex // + ); + open = NormalizePrice(open, mSymbol); + + // + close = iClose( + mSymbol, + mPeriod, + barIndex // + ); + close = NormalizePrice(close, mSymbol); + + // + high = iHigh( + mSymbol, + mPeriod, + barIndex // + ); + high = NormalizePrice(high, mSymbol); + + // + low = iLow( + mSymbol, + mPeriod, + barIndex // + ); + low = NormalizePrice(low, mSymbol); + + // + spread = iSpread( + mSymbol, + mPeriod, + barIndex // + ); + spread = NormalizePrice(spread, mSymbol); + + // + bool result = IsValid(); + + // + return result; + } + + // + // Init a Bar ... + // Using Bar Time ... + bool Init( + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Period + datetime mTime = NULL // Bar Time + ) + { + // + mTime = NormalizeTime(mTime); + + // + int barIndex = iBarShift( + mSymbol, + mPeriod, + mTime, + false // + ); + + // + bool result = Init( + mSymbol, + mPeriod, + barIndex + // + ); + + // + return result; + } + + // + bool Init( + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Period + double mOpen = 0, // Open + double mHigh = 0, // High + double mClose = 0, // Close + double mLow = 0, // Low + datetime mTime = NULL // Bar Time + ) + { + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + symbol = mSymbol; + period = mPeriod; + + // + int barIndex = GetBarIndex( + symbol, + period, + mTime // + ); + + // + return Init( + mSymbol, + mPeriod, + barIndex // + ); + } + + // + // Tools ... + + // + void Clean() + { + // + low = 0; + high = 0; + open = 0; + close = 0; + spread = 0; + + // + time = NULL; + symbol = NULL; + period = NULL; + + // + ZeroMemory(this); + } + + // + // Validate Bar ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + low > 0 && + high > 0 && + open > 0 && + close > 0 && + spread > 0 + // + ; + + // + return result; + } + + // + int TotalBars() + { + // + int result = 0; + + // + result = iBars( + symbol, + period // + ); + + // + return result; + } + + // + // Calculate X_PRICE Specified Type ... + double GetPrice(ENUM_X_PRICE mPType) + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + return GetAppliedPrice( + mPType, + open, + high, + low, + close // + ); + } + + // + // Retrieve Price base On Series Mode ... + double GetPrice(ENUM_SERIESMODE mMode) + { + // + ENUM_X_PRICE mType = ToXPrice(mMode); + + // + return GetPrice(mType); + } + + // + // Calculate Applied Price ... + double GetPrice(ENUM_APPLIED_PRICE mPType) + { + // + ENUM_X_PRICE mType = ToXPrice(mPType); + + // + return GetPrice(mType); + } + + // + // Find Specific Price ... + bool FindHigherPriceBar( + XOHCL &bar, + double price, + ENUM_X_PRICE _type = X_PRICE_HIGH // + ) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int totalBars = TotalBars(); + result = IsValidSize(totalBars); + if (!result) + { + return result; + } + + // + int start = Index(); + int maxAllowedLoopback = totalBars / 5; + for (int i = start; i < maxAllowedLoopback; i++) + { + // + result = bar.Init( + symbol, + period, + i // + ); + + // + if (!result) + { + break; + } + + // + double iPrice = bar.GetPrice(_type); + + // + result = + // + iPrice > 0 && + iPrice > price + // + ; + if (result) + { + break; + } + } + + // + if (!result) + { + bar.Clean(); + } + + // + return result; + } + + // + // Find Specific Price ... + bool FindLowerPriceBar( + XOHCL &bar, + double price, + ENUM_X_PRICE _type = X_PRICE_HIGH // + ) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int totalBars = TotalBars(); + result = IsValidSize(totalBars); + if (!result) + { + return result; + } + + // + int start = Index(); + int maxAllowedLoopback = totalBars / 5; + for (int i = start; i < maxAllowedLoopback; i++) + { + // + result = bar.Init( + symbol, + period, + i // + ); + + // + if (!result) + { + break; + } + + // + double iPrice = bar.GetPrice(_type); + + // + result = + // + iPrice > 0 && + iPrice < price + // + ; + if (result) + { + break; + } + } + + // + if (!result) + { + bar.Clean(); + } + + // + return result; + } + + // + // Calculate up Price ... + double GetUp() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = MathMax(open, close); + + // + return result; + } + + // + // Calculate Down Price ... + double GetDown() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = MathMin(open, close); + + // + return result; + } + + // + // Calculate Bar Body ... + double GetBody() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetUp() - GetDown(); + + // + return result; + } + + // + // Calculate Bar Range ... + double GetRange() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = high - low; + + // + return result; + } + + // + // Calculate Bar Shadows ... + double GetShadows() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetRange() - GetBody(); + + // + return result; + } + + // + // Calculate Bar High Shadow ... + double GetHighShadow() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = + // + high - GetUp() + // + ; + + // + return result; + } + + // + // Calculate Bar Low Shadow ... + double GetLowShadow() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = + // + GetDown() - low; + // + ; + + // + return result; + } + + // + // Check Bar is Bullish ... + bool IsBullish() + { + // + bool result = false; + + // + if (!IsValid()) + { + return result; + } + + // + result = open < close; + + // + return result; + } + + // + // Check Bar is Bearish ... + bool IsBearish() + { + // + bool result = false; + + // + if (!IsValid()) + { + return result; + } + + // + result = open > close; + + // + return result; + } + + // + // Get Direction of Bar ... + ENUM_X_DIRECTION GetDirection() + { + // + ENUM_X_DIRECTION result = X_DIRECTION_NONE; + + // + bool isBullish = IsBullish(); + bool isBearish = IsBearish(); + + // + result = + isBullish && isBearish + ? X_DIRECTION_ALL + : !isBullish && !isBearish + ? X_DIRECTION_NONE + : isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + return result; + } + + // + // Find Next Bar Time ... + datetime NextAt() + { + // + datetime result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + int prSeconds = PeriodSeconds(period); + + // + result = time + prSeconds; + + // + return result; + } + + // + // Find Prev Bar Time ... + datetime BeforeOn() + { + // + datetime result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + int prSeconds = PeriodSeconds(period); + + // + result = time - prSeconds; + + // + return result; + } + + // + // Calculate Last Bar Open Time in Smaller Period ... + datetime GetLastBarTimeOfPeriod( + ENUM_TIMEFRAMES smallerPeriod // + ) + { + // + datetime result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + int sourceSeconds = PeriodSeconds(period); + int destSeconds = PeriodSeconds(smallerPeriod); + if (destSeconds >= sourceSeconds) + { + // + result = time; + return result; + } + + // + result = (datetime)((((int)time) + sourceSeconds) - destSeconds); + + // + return result; + } + + // + // Calculate Close Time ... + datetime GetCloseTime() + { + // + datetime result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + int seconds = PeriodSeconds(period); + + // + result = (datetime)(((int)time) + seconds); + + // + return result; + } + + // + bool BarAt( + int index, + XOHCL &bar // + ) + { + // + bool result = false; + + // + bar.Clean(); + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + if (index < 0) + { + index = 0; + } + + // + result = bar.Init( + symbol, + period, + index // + ); + + // + return result; + } + + // + bool BarIn( + ENUM_TIMEFRAMES _period, + XOHCL &bar // + ) + { + // + bool result = false; + + // + bar.Clean(); + + // + result = IsValid() && + IsSpecifiedValid(_period); + if (!result) + { + return result; + } + + // + int index = Index(_period); + result = bar.Init( + symbol, + _period, + index // + ); + + // + return result; + } + + // + // Find Current Bar Index on Chart ... + int Index() + { + // + int result = -1; + + // + if (!IsValid()) + { + return result; + } + + // + result = iBarShift( + symbol, + period, + time + // + ); + + // + return result; + } + + // + int Index(datetime value) + { + // + int result = -1; + + // + value = NormalizeTime(value); + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + result = iBarShift( + symbol, + period, + value // + ); + + // + return result; + } + + // + int Index(ENUM_TIMEFRAMES value) + { + // + int result = -1; + + // + result = IsValid() && + IsSpecifiedValid(value); + if (!result) + { + return result; + } + + // + result = iBarShift( + symbol, + value, + time // + ); + + // + return result; + } + + // + bool GetNextBar(XOHCL &bar) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int idx = Index(); + result = idx > 0; + if (!result) + { + return result; + } + + // + result = bar.Init( + this.symbol, + this.period, + idx - 1 // + ); + + // + if (!result) + { + bar.Clean(); + } + + // + return result; + } + + // + bool GetPreviousBar(XOHCL &bar) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int idx = Index(); + + // + result = bar.Init( + this.symbol, + this.period, + idx + 1 // + ); + + // + if (!result) + { + bar.Clean(); + } + + // + return result; + } + + // + // Find Highest Bar Index ... + int FindHighestIndex( + int mLength, // Loopback ... + ENUM_SERIESMODE mMode // Calculation mode + ) + { + // + int result = -1; + + // + if (!IsValid()) + { + return result; + } + + // + if (mLength < 2) + { + mLength = 2; + } + + // + result = iHighest( + symbol, + period, + mMode, + mLength, + Index()); + + // + return result; + } + + // + // Find Highest ... + double FindHighest( + int mLength, // Loopback ... + ENUM_SERIESMODE mMode // Calculation mode + ) + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + int idx = FindHighestIndex( + mLength, + mMode); + if (idx <= -1) + { + return result; + } + + // + XOHCL iH; + result = iH.Init( + symbol, + period, + idx + // + ); + if (!result) + { + return result; + } + + // + result = iH.GetPrice(mMode); + + // + return result; + } + + // + // Find Highest ... + double FindHighestUp( + int mLength // Loopback ... + ) + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = FindHighest(mLength, MODE_OPEN); + result = MathMax(mLength, FindHighest(mLength, MODE_CLOSE)); + + // + return result; + } + + // + // Find Lowest Bar Index ... + int FindLowestIndex( + int mLength, // Loopback ... + ENUM_SERIESMODE mMode // Calculation mode + ) + { + // + int result = -1; + + // + if (!IsValid()) + { + return result; + } + + // + if (mLength < 2) + { + mLength = 2; + } + + // + result = iLowest( + symbol, + period, + mMode, + mLength, + Index()); + + // + return result; + } + + // + // Find Lowest ... + double FindLowest( + int mLength, // Loopback ... + ENUM_SERIESMODE mMode // Calculation mode + ) + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + int idx = FindLowestIndex( + mLength, + mMode); + if (idx <= -1) + { + return result; + } + + // + XOHCL iL; + result = iL.Init( + symbol, + period, + idx + // + ); + if (!result) + { + return result; + } + + // + result = iL.GetPrice(mMode); + + // + return result; + } + + // + // Find Lowest ... + double FindLowesttDown( + int mLength // Loopback ... + ) + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = FindLowest(mLength, MODE_OPEN); + result = MathMax(mLength, FindLowest(mLength, MODE_CLOSE)); + + // + return result; + } + + // + // Other ... + string GetTag(string prefix = "") + { + // + string result = NULL; + + // + result = + (IsValid(prefix) + ? prefix + "_" + : "") + + "XOHCL_" + symbol + "_" + ToString(period) + "_" + ToFormatString(time); + + // + return result; + } + + // + // Convert to String Representation ... + string ToString() + { + // + string result = ""; + + // + result = GetTypeName(this) + + "(O(" + ToString(open) + "),H(" + ToString(high) + "),C(" + ToString(close) + "),L(" + ToString(low) + "))"; + + // + return result; + } +}; + +// +// Models ... + +// +// Model a Bar Remains Time ... +struct XBarRemainsTime +{ + // + int days; + int hours; + int minutes; + int seconds; + + // + // Constructor ... + XBarRemainsTime() + { + Clean(); + } + + // + // Always Calculate Current 0 Bar Timing ... + bool Init( + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL // Trading Period + ) + { + // + bool result = false; + + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + int minuteSecoonds = 60; + int hourSeconds = minuteSecoonds * 60; + int daySeconds = 24 * hourSeconds; + + // + int periodSeconds = PeriodSeconds( + mPeriod); + datetime startTime = GetBarTime( + mSymbol, + mPeriod, + 0 + // + ); + + // + int secondsDiff = (int)startTime + periodSeconds - (int)TimeCurrent(); + + // + int mWorkingSecondsDiff = secondsDiff; + if (mWorkingSecondsDiff > daySeconds) + { + // + days = mWorkingSecondsDiff / daySeconds; + mWorkingSecondsDiff -= days * daySeconds; + } + if (mWorkingSecondsDiff > hourSeconds) + { + // + hours = mWorkingSecondsDiff / hourSeconds; + mWorkingSecondsDiff -= hours * hourSeconds; + } + if (mWorkingSecondsDiff > minuteSecoonds) + { + // + minutes = mWorkingSecondsDiff / minuteSecoonds; + mWorkingSecondsDiff -= minutes * minuteSecoonds; + } + seconds = mWorkingSecondsDiff; + + // + result = true; + + // + return result; + } + + // + // Tools ... + + // + // Cleanup ... + void Clean() + { + days = 0; + hours = 0; + minutes = 0; + seconds = 0; + + // + ZeroMemory(this); + } + + // + // To String Representation ... + string ToString( + string dayId = "d", + string hourId = "h", + string minuteId = "m", + string secondId = "s", + string idSeparator = ": ", + string separator = ", ", + bool ignoreZeroValues = true + // + ) + { + // + string result = ""; + + // + // Days ... + if (!ignoreZeroValues || days > 0) + { + result += dayId + idSeparator + (string)days + separator; + } + + // + // Hours ... + if (!ignoreZeroValues || hours > 0) + { + // + string strHour = ToString(hours); + if (StringLen(strHour) == 1) + { + strHour = "0" + strHour; + } + + // + result += hourId + idSeparator + strHour + separator; + } + + // + // Minutes ... + if (!ignoreZeroValues || minutes > 0) + { + // + string strMinute = ToString(minutes); + if (StringLen(strMinute) == 1) + { + strMinute = "0" + strMinute; + } + + // + result += minuteId + idSeparator + strMinute + separator; + } + + // + // Seconds ... + if (!ignoreZeroValues || seconds > 0) + { + // + string strSec = ToString(seconds); + if (StringLen(strSec) == 1) + { + strSec = "0" + strSec; + } + + // + result += secondId + idSeparator + strSec; + } + + // + return result; + } +}; + +// +// Tracking Times ... +struct XTimeTracker +{ + // + // Props ... + int xMonth; + int xDayOfWeek; + int xForWeekDay; + int xDay; + int xHour; + int xMinute; + + // + // Constructor ... + XTimeTracker() + { + Clean(); + } + + // + // Tools ... + + // + void Clean() + { + // + xDay = -1; + xHour = -1; + xMonth = -1; + xMinute = -1; + xDayOfWeek = -1; + xForWeekDay = -1; + + // + ZeroMemory(this); + } + + // + // Detecting New Minute ... + bool IsNewMinute() + { + // + bool result = false; + + // + // Retrieve Current Time as Struct ... + MqlDateTime timeStruct = GetCurrentTime(); + + // + // Check Houre ... + result = timeStruct.min != xMinute; + if (result) + { + xMinute = timeStruct.min; + } + + // + return result; + } + + // + // Detecting New Houre ... + bool IsNewHour() + { + // + bool result = false; + + // + // Retrieve Current Time as Struct ... + MqlDateTime timeStruct = GetCurrentTime(); + + // + // Check Houre ... + result = timeStruct.hour != xHour; + if (result) + { + xHour = timeStruct.hour; + } + + // + return result; + } + + // + // Detecting New Day ... + bool IsNewDay() + { + // + bool result = false; + + // + // Retrieve Current Time as Struct ... + MqlDateTime timeStruct = GetCurrentTime(); + + // + // Check Houre ... + result = timeStruct.day_of_year != xDay; + if (result) + { + xDay = timeStruct.day_of_year; + } + + // + return result; + } + + // + // Detecting New Week ... + bool IsNewWeek() + { + // + bool result = false; + + // + // Retrieve Current Time as Struct ... + MqlDateTime timeStruct = GetCurrentTime(); + + // + // Check Week ... + // Since Week Starts From Monday in Forex World ... + // we Calculate Start of Week by 1-Monday ... + result = + xDayOfWeek == -1 && + xForWeekDay == -1 + ? true + : timeStruct.day_of_week == 1 && + timeStruct.day_of_year > xForWeekDay; + + // + xForWeekDay = timeStruct.day_of_year; + xDayOfWeek = timeStruct.day_of_week; + + // + return result; + } + + // + // Detecting End Of Week ... + bool IsWeekEnd() + { + // + bool result = false; + + // + // Retrieve Current Time as Struct ... + MqlDateTime timeStruct = GetCurrentTime(); + + // + // Check WeekEnd ... + // Since Week Starts From Monday in Forex World ... + // we Calculate End of Week by 5-Friday ... + result = + xDayOfWeek != -1 && + timeStruct.day_of_week == 5 && + timeStruct.hour == 23 && + timeStruct.min == 59 && + timeStruct.sec == 59; + + // + return result; + } + + // + // Detecting New Month ... + bool IsNewMonth() + { + // + bool result = false; + + // + // Retrieve Current Time as Struct ... + MqlDateTime timeStruct = GetCurrentTime(); + + // + // Check Houre ... + result = timeStruct.mon != xMonth; + if (result) + { + xMonth = timeStruct.mon; + } + + // + return result; + } +}; + +// +// Tracking Bars on Specified Environment ... +struct XBarTracker +{ + // + string symbol; // Tracking Symbol + ENUM_TIMEFRAMES period; // Tracking Time Frame + + // + int lastTrackedBar; // Last Tracked Bar ... + + // + bool waitsUntilNext; // Waits Until Next Bar ... + + // + // Constructor ... + XBarTracker() + { + Clean(); + } + + // + // Initializer ... + bool Init( + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL // Trading Period + ) + { + // + bool result = false; + + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + this.symbol = mSymbol; + this.period = mPeriod; + + // + this.lastTrackedBar = 0; + + // + result = true; + + // + return result; + } + + // + // Retrieve all Bars ... + int CountBars() + { + // + return iBars( + symbol, + period + // + ); + } + + // + // Check if it's New Bar ... + bool IsNewBar() + { + // + bool result = false; + + // + int currentBars = CountBars(); + + // + result = currentBars > lastTrackedBar; + if (result) + { + lastTrackedBar = currentBars; + } + + // + return result; + } + + // + bool CanProcessBar() + { + // + bool _isInTestMode = IsRunningOnTestMode(); + + // + bool isNewBar = IsNewBar(); + + // + bool result = + _isInTestMode + ? isNewBar + : !waitsUntilNext + ? true + : isNewBar; + if (result && waitsUntilNext) + { + waitsUntilNext = false; + } + + // + return result; + } + + // + void Waits() + { + this.waitsUntilNext = true; + } + + // + // Tools ... + void Clean() + { + // + symbol = NormalizeSymbol(NULL); + period = NormalizePeriod(NULL); + + // + ZeroMemory(this); + } + + // + bool GetBar( + XOHCL &bar, + int index = 0 // + ) + { + // + bool result = false; + + // + result = bar.Init( + symbol, + period, + index // + ); + + // + return result; + } + + // + bool GetBar( + XOHCL &bar, + datetime time = NULL // + ) + { + // + bool result = false; + + // + NormalizeTime(time); + + // + int barIndex = iBarShift( + symbol, + period, + time, + false // + ); + + // + result = barIndex >= 0; + if (!result) + { + return result; + } + + // + result = bar.Init( + symbol, + period, + barIndex // + ); + + // + return result; + } + + // + int Index(datetime time = NULL) + { + // + int result = 0; + + // + NormalizeTime(time); + + // + result = iBarShift( + symbol, + period, + time, + false // + ); + + // + return result; + } +}; + +// +// Extensions ... + +// +// Extract Specific Range of Bars ... +// using Start Bar Index ... +int GetBars( + XOHCL &bars[], // Hold Result + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Time Frame + int from = 0, // Start Bar Index + int count = 1 // Number of Bars +) +{ + // + int result = 0; + + // + from = NormalizeInt(from); + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + int total = Bars( + mSymbol, + mPeriod // + ); + if (from > total - 2) + { + from = total - 2; + } + + // + if (count < 0) + { + count = 1; + } + + // + int start = from; + int end = start + count; + if (end > total - 1) + { + end = total - 1; + } + + // + Clean(bars); + + // + for (int i = start; i < end; i++) + { + // + XOHCL iBar; + bool isValid = iBar.Init( + mSymbol, + mPeriod, + i // + ); + + // + if (isValid) + { + // + AddRef( + iBar, + bars // + ); + } + } + + // + result = ArraySize(bars); + + // + return result; +} + +// +// Extract Specific Range of Bars ... +// using Start Bar Time ... +int GetBars( + XOHCL &bars[], // Hold Result + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Time Frame + datetime from = NULL, // Start Bar Time + int count = 1 // Number of Bars +) +{ + // + from = NormalizeTime(from); + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + int barIndex = GetBarIndex( + mSymbol, + mPeriod, + from // + ); + + // + return GetBars( + bars, + mSymbol, + mPeriod, + barIndex, + count // + ); +} + +// \ No newline at end of file diff --git a/Libraries/x-saherelm.x-trade.lib.mq5 b/Libraries/x-saherelm.x-trade.lib.mq5 index 0c515c8b..0b6b1078 100644 --- a/Libraries/x-saherelm.x-trade.lib.mq5 +++ b/Libraries/x-saherelm.x-trade.lib.mq5 @@ -239,7 +239,7 @@ ENUM_X_POSITION_TYPES ToPositionType(ENUM_POSITION_TYPE value) } // -ENUM_X_POSITION_TYPES GetOppositPositionType(ENUM_POSITION_TYPE type) +ENUM_X_POSITION_TYPES OppositPositionType(ENUM_POSITION_TYPE type) { // ENUM_X_POSITION_TYPES result = X_POSITION_TYPE_NONE; @@ -1567,7 +1567,7 @@ struct XSignal } // - ENUM_POSITION_TYPE mType = GetOpposit(this.type); + ENUM_POSITION_TYPE mType = Opposit(this.type); double mEntry = GetExit(this.symbol, mType); // @@ -1615,7 +1615,7 @@ struct XSignal bool result = false; // - ENUM_POSITION_TYPE mType = GetOpposit(source.type); + ENUM_POSITION_TYPE mType = Opposit(source.type); double mEntry = GetEntry(source.symbol, mType); // diff --git a/Libraries/x-saherelm.xohcl.lib.mq5 b/Libraries/x-saherelm.xohcl.lib.mq5 new file mode 100644 index 00000000..03a6d0b2 --- /dev/null +++ b/Libraries/x-saherelm.xohcl.lib.mq5 @@ -0,0 +1,1352 @@ +/////////////////////////////////////////////////////// +// +// SaherElm IT Center MQL5 Common Library +// -------------------------------------- +// Name: XOHCLLib +// Description: provide all commonly used functions ... +// +// +// 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 + +// +// Describe an Specific Candle ... +struct XOHCL +{ + // + // Props ... + + // + double high; + double open; + double close; + double low; + + // + string symbol; + datetime time; + ENUM_TIMEFRAMES period; + + // + // Constructor ... + XOHCL() + { + Clean(); + } + + // + // Init a Bar ... + // Using Bar Index ... + bool Init( + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Period + int barIndex = 0 // Bar Index + ) + { + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + symbol = mSymbol; + period = mPeriod; + + // + time = iTime( + mSymbol, + mPeriod, + barIndex // + ); + + // + open = iOpen( + mSymbol, + mPeriod, + barIndex // + ); + open = NormalizePrice(open, mSymbol); + + // + close = iClose( + mSymbol, + mPeriod, + barIndex // + ); + close = NormalizePrice(close, mSymbol); + + // + high = iHigh( + mSymbol, + mPeriod, + barIndex // + ); + high = NormalizePrice(high, mSymbol); + + // + low = iLow( + mSymbol, + mPeriod, + barIndex // + ); + low = NormalizePrice(low, mSymbol); + + // + bool result = IsValid(); + + // + return result; + } + + // + // Init a Bar ... + // Using Bar Time ... + bool Init( + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Period + datetime mTime = NULL // Bar Time + ) + { + // + mTime = NormalizeTime(mTime); + + // + int barIndex = iBarShift( + mSymbol, + mPeriod, + mTime, + false // + ); + + // + bool result = Init( + mSymbol, + mPeriod, + barIndex + // + ); + + // + return result; + } + + // + bool Init( + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Period + double mOpen = 0, // Open + double mHigh = 0, // High + double mClose = 0, // Close + double mLow = 0, // Low + int barIndex = 0 // Bar Index + ) + { + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + symbol = mSymbol; + period = mPeriod; + + // + time = iTime( + mSymbol, + mPeriod, + barIndex + // + ); + + // + open = mOpen; + high = mHigh; + close = mClose; + low = mLow; + + // + return IsValid(); + } + + // + bool Init( + string mSymbol = NULL, // Trading Symbol + ENUM_TIMEFRAMES mPeriod = NULL, // Trading Period + double mOpen = 0, // Open + double mHigh = 0, // High + double mClose = 0, // Close + double mLow = 0, // Low + datetime mTime = NULL // Bar Time + ) + { + // + mSymbol = NormalizeSymbol(mSymbol); + mPeriod = NormalizePeriod(mPeriod); + + // + symbol = mSymbol; + period = mPeriod; + + // + int barIndex = iBarShift( + symbol, + period, + mTime); + + // + time = iTime( + mSymbol, + mPeriod, + barIndex + // + ); + + // + open = mOpen; + high = mHigh; + close = mClose; + low = mLow; + + // + return IsValid(); + } + + // + // Tools ... + + // + void Clean() + { + // + high = 0; + open = 0; + close = 0; + low = 0; + + // + time = NULL; + symbol = NULL; + period = NULL; + + // + ZeroMemory(this); + } + + // + // Validate Bar ... + bool IsValid() + { + // + bool result = false; + + // + result = + // + high > 0 && + open > 0 && + close > 0 && + low > 0 + // + ; + + // + return result; + } + + // + int TotalBars() + { + // + int result = 0; + + // + result = iBars( + symbol, + period // + ); + + // + return result; + } + + // + // Calculate X_PRICE Specified Type ... + double GetPrice(ENUM_X_PRICE mPType) + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + switch (mPType) + { + // + case X_PRICE_OPEN: + result = open; + break; + // + case X_PRICE_HIGH: + result = high; + break; + // + case X_PRICE_CLOSE: + result = close; + break; + // + case X_PRICE_LOW: + result = low; + break; + // + case X_PRICE_UP: + result = GetUp(); + break; + // + case X_PRICE_DOWN: + result = GetDown(); + break; + } + // case PRICE_MEDIAN: + // return ((high[i] + low[i]) / 2.0); + // case PRICE_TYPICAL: + // return ((high[i] + low[i] + close[i]) / 3.0); + // case PRICE_WEIGHTED: + // return ((high[i] + low[i] + close[i] + close[i]) / 4.0); + + // + return result; + } + + // + // Retrieve Price base On Series Mode ... + double GetPrice(ENUM_SERIESMODE mMode) + { + // + ENUM_X_PRICE mXMode = ToPrice(mMode); + + // + return GetPrice(mXMode); + } + + // + // Calculate Applied Price ... + double GetPrice( + ENUM_APPLIED_PRICE mAppliedTo // Select Application Method + ) + { + // + double result = 0; + + // + // Calculate Applied Price ... + switch (mAppliedTo) + { + // + case PRICE_CLOSE: + result = close; + break; + + // + case PRICE_OPEN: + result = open; + break; + + // + case PRICE_HIGH: + result = high; + break; + + // + case PRICE_LOW: + result = low; + break; + + // + case PRICE_MEDIAN: + result = (high + low) / 2; + break; + + // + case PRICE_TYPICAL: + result = (high + low + close) / 3; + break; + + // + case PRICE_WEIGHTED: + result = (high + low + close + close) / 4; + break; + } + + // + return result; + } + + // + // Find Specific Price ... + bool FindHigherPriceBar( + XOHCL &bar, + double price, + ENUM_X_PRICE _type = X_PRICE_HIGH // + ) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int totalBars = TotalBars(); + result = IsValidSize(totalBars); + if (!result) + { + return result; + } + + // + int start = Index(); + int maxAllowedLoopback = totalBars / 5; + for (int i = start; i < maxAllowedLoopback; i++) + { + // + result = bar.Init( + symbol, + period, + i // + ); + + // + if (!result) + { + break; + } + + // + double iPrice = bar.GetPrice(_type); + + // + result = + // + iPrice > 0 && + iPrice > price + // + ; + if (result) + { + break; + } + } + + // + if (!result) + { + bar.Clean(); + } + + // + return result; + } + + // + // Find Specific Price ... + bool FindLowerPriceBar( + XOHCL &bar, + double price, + ENUM_X_PRICE _type = X_PRICE_HIGH // + ) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int totalBars = TotalBars(); + result = IsValidSize(totalBars); + if (!result) + { + return result; + } + + // + int start = Index(); + int maxAllowedLoopback = totalBars / 5; + for (int i = start; i < maxAllowedLoopback; i++) + { + // + result = bar.Init( + symbol, + period, + i // + ); + + // + if (!result) + { + break; + } + + // + double iPrice = bar.GetPrice(_type); + + // + result = + // + iPrice > 0 && + iPrice < price + // + ; + if (result) + { + break; + } + } + + // + if (!result) + { + bar.Clean(); + } + + // + return result; + } + + // + // Calculate Bar Mid Line ... + double GetMid() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = (high + low) / 2; + + // + return result; + } + + // + // Calculate up Price ... + double GetUp() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = MathMax(open, close); + + // + return result; + } + + // + // Calculate Down Price ... + double GetDown() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = MathMin(open, close); + + // + return result; + } + + // + // Retrieve Required Price for Zone Checking ... + // For Bullish Zones => low; + // For Bearish Zones => high; + double GetZoneCheckValue(ENUM_X_DIRECTION forDir) + { + // + double result = 0; + + // + if (!IsValid() || + !HasDirection(forDir)) + { + return result; + } + + // + bool isBullish = IsBullish(forDir); + + // + result = + isBullish + ? low + : high; + + return result; + } + + // + // Calculate Bar Body ... + double GetBody() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetUp() - GetDown(); + + // + return result; + } + + // + // Calculate Bar Range ... + double GetRange() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = high - low; + + // + return result; + } + + // + // Calculate Bar Shadows ... + double GetShadows() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = GetRange() - GetBody(); + + // + return result; + } + + // + // Calculate Bar High Shadow ... + double GetHighShadow() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = + // + high - GetUp() + // + ; + + // + return result; + } + + // + // Calculate Bar Low Shadow ... + double GetLowShadow() + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = + // + GetDown() - low; + // + ; + + // + return result; + } + + // + // Check Bar is Bullish ... + bool IsBullish() + { + // + bool result = false; + + // + if (!IsValid()) + { + return result; + } + + // + result = open < close; + + // + return result; + } + + // + // Check Bar is Bearish ... + bool IsBearish() + { + // + bool result = false; + + // + if (!IsValid()) + { + return result; + } + + // + result = open > close; + + // + return result; + } + + // + // Get Direction of Bar ... + ENUM_X_DIRECTION GetDirection() + { + // + ENUM_X_DIRECTION result = X_DIRECTION_NONE; + + // + bool isBullish = IsBullish(); + bool isBearish = IsBearish(); + + // + result = + isBullish && isBearish + ? X_DIRECTION_ALL + : !isBullish && !isBearish + ? X_DIRECTION_NONE + : isBullish + ? X_DIRECTION_BULLISH + : X_DIRECTION_BEARISH; + + // + return result; + } + + // + // Find Next Bar Time ... + datetime NextAt() + { + // + datetime result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + int prSeconds = PeriodSeconds(period); + + // + result = time + prSeconds; + + // + return result; + } + + // + // Find Prev Bar Time ... + datetime BeforeOn() + { + // + datetime result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + int prSeconds = PeriodSeconds(period); + + // + result = time - prSeconds; + + // + return result; + } + + // + // Calculate Last Bar Open Time in Smaller Period ... + datetime GetLastBarTimeOfPeriod( + ENUM_TIMEFRAMES smallerPeriod // + ) + { + // + datetime result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + int sourceSeconds = PeriodSeconds(period); + int destSeconds = PeriodSeconds(smallerPeriod); + if (destSeconds >= sourceSeconds) + { + // + result = time; + return result; + } + + // + result = (datetime)((((int)time) + sourceSeconds) - destSeconds); + + // + return result; + } + + // + // Calculate Close Time ... + datetime GetCloseTime() + { + // + datetime result = NULL; + + // + if (!IsValid()) + { + return result; + } + + // + int seconds = PeriodSeconds(period); + + // + result = (datetime)(((int)time) + seconds); + + // + return result; + } + + // + bool BarAt( + int index, + XOHCL &bar // + ) + { + // + bool result = false; + + // + bar.Clean(); + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + if (index < 0) + { + index = 0; + } + + // + result = bar.Init( + symbol, + period, + index // + ); + + // + return result; + } + + // + bool BarIn( + ENUM_TIMEFRAMES _period, + XOHCL &bar // + ) + { + // + bool result = false; + + // + bar.Clean(); + + // + result = IsValid() && + IsSpecifiedValid(_period); + if (!result) + { + return result; + } + + // + int index = Index(_period); + result = bar.Init( + symbol, + _period, + index // + ); + + // + return result; + } + + // + // Find Current Bar Index on Chart ... + int Index() + { + // + int result = -1; + + // + if (!IsValid()) + { + return result; + } + + // + result = iBarShift( + symbol, + period, + time + // + ); + + // + return result; + } + + // + int Index(datetime value) + { + // + int result = -1; + + // + value = NormalizeTime(value); + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + result = iBarShift( + symbol, + period, + value // + ); + + // + return result; + } + + // + int Index(ENUM_TIMEFRAMES value) + { + // + int result = -1; + + // + result = IsValid() && + IsSpecifiedValid(value); + if (!result) + { + return result; + } + + // + result = iBarShift( + symbol, + value, + time // + ); + + // + return result; + } + + // + bool GetNextBar(XOHCL &bar) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int idx = Index(); + result = idx > 0; + if (!result) + { + return result; + } + + // + result = bar.Init( + this.symbol, + this.period, + idx - 1 // + ); + + // + if (!result) + { + bar.Clean(); + } + + // + return result; + } + + // + bool GetPreviousBar(XOHCL &bar) + { + // + bool result = false; + + // + result = IsValid(); + if (!result) + { + return result; + } + + // + int idx = Index(); + + // + result = bar.Init( + this.symbol, + this.period, + idx + 1 // + ); + + // + if (!result) + { + bar.Clean(); + } + + // + return result; + } + + // + // Find Highest Bar Index ... + int FindHighestIndex( + int mLength, // Loopback ... + ENUM_SERIESMODE mMode // Calculation mode + ) + { + // + int result = -1; + + // + if (!IsValid()) + { + return result; + } + + // + if (mLength < 2) + { + mLength = 2; + } + + // + result = iHighest( + symbol, + period, + mMode, + mLength, + Index()); + + // + return result; + } + + // + // Find Highest ... + double FindHighest( + int mLength, // Loopback ... + ENUM_SERIESMODE mMode // Calculation mode + ) + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + int idx = FindHighestIndex( + mLength, + mMode); + if (idx <= -1) + { + return result; + } + + // + XOHCL iH; + result = iH.Init( + symbol, + period, + idx + // + ); + if (!result) + { + return result; + } + + // + result = iH.GetPrice(mMode); + + // + return result; + } + + // + // Find Highest ... + double FindHighestUp( + int mLength // Loopback ... + ) + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = FindHighest(mLength, MODE_OPEN); + result = MathMax(mLength, FindHighest(mLength, MODE_CLOSE)); + + // + return result; + } + + // + // Find Lowest Bar Index ... + int FindLowestIndex( + int mLength, // Loopback ... + ENUM_SERIESMODE mMode // Calculation mode + ) + { + // + int result = -1; + + // + if (!IsValid()) + { + return result; + } + + // + if (mLength < 2) + { + mLength = 2; + } + + // + result = iLowest( + symbol, + period, + mMode, + mLength, + Index()); + + // + return result; + } + + // + // Find Lowest ... + double FindLowest( + int mLength, // Loopback ... + ENUM_SERIESMODE mMode // Calculation mode + ) + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + int idx = FindLowestIndex( + mLength, + mMode); + if (idx <= -1) + { + return result; + } + + // + XOHCL iL; + result = iL.Init( + symbol, + period, + idx + // + ); + if (!result) + { + return result; + } + + // + result = iL.GetPrice(mMode); + + // + return result; + } + + // + // Find Lowest ... + double FindLowesttDown( + int mLength // Loopback ... + ) + { + // + double result = 0; + + // + if (!IsValid()) + { + return result; + } + + // + result = FindLowest(mLength, MODE_OPEN); + result = MathMax(mLength, FindLowest(mLength, MODE_CLOSE)); + + // + return result; + } + + // + // Other ... + string GetTag(string prefix = "") + { + // + string result = NULL; + + // + result = + (IsValid(prefix) + ? prefix + "_" + : "") + + "XOHCL_" + symbol + "_" + ToString(period) + "_" + ToFormatString(time); + + // + return result; + } + + // + // Convert to String Representation ... + string ToString() + { + // + string result = ""; + + // + result = GetTypeName(this) + + "(O(" + ToString(open) + "),H(" + ToString(high) + "),C(" + ToString(close) + "),L(" + ToString(low) + "))"; + + // + return result; + } +}; + +// \ No newline at end of file diff --git a/X121SMCEA/Classes/x-121.smc.market.cycle.helper.class.mq5 b/X121SMCEA/Classes/x-121.smc.market.cycle.helper.class.mq5 index fd046e86..3d8f8ed2 100644 --- a/X121SMCEA/Classes/x-121.smc.market.cycle.helper.class.mq5 +++ b/X121SMCEA/Classes/x-121.smc.market.cycle.helper.class.mq5 @@ -1159,7 +1159,13 @@ struct X121SMCStrategySignalProviderData // Prepare all ... bool Prepare( int barIndex = 0, - int loopback = 10 // + int loopback = 10, + bool trigger = false, + bool decision = true, + bool analyse = true, + bool verification = false, + bool consolidation = true, + bool vision = true // ) { // @@ -1186,169 +1192,192 @@ struct X121SMCStrategySignalProviderData // // Trigger ... - result = triggerCycleHelper.GetConditions( - triggerCycleEvents, - triggerPoiEvents, - triggerConditions, - barIndex, - loopback // - ); - if (!result) + if (trigger) { // - Clean(triggerPoiEvents); - Clean(triggerCycleEvents); + result = triggerCycleHelper.GetConditions( + triggerCycleEvents, + triggerPoiEvents, + triggerConditions, + barIndex, + loopback // + ); + if (!result) + { + // + Clean(triggerPoiEvents); + Clean(triggerCycleEvents); - // - triggerConditions.Clean(); + // + triggerConditions.Clean(); - // - return result; + // + return result; + } } // // Decision ... - result = decisionCycleHelper.GetConditions( - decisionCycleEvents, - decisionPoiEvents, - decisionConditions, - barIndex, - loopback // - ); - if (!result) + if (decision) { // - Clean(triggerPoiEvents); - Clean(decisionPoiEvents); - Clean(triggerCycleEvents); - triggerConditions.Clean(); - Clean(decisionCycleEvents); - decisionConditions.Clean(); + result = decisionCycleHelper.GetConditions( + decisionCycleEvents, + decisionPoiEvents, + decisionConditions, + barIndex, + loopback // + ); + if (!result) + { + // + Clean(triggerPoiEvents); + Clean(decisionPoiEvents); + Clean(triggerCycleEvents); + triggerConditions.Clean(); + Clean(decisionCycleEvents); + decisionConditions.Clean(); - // - return result; + // + return result; + } } // // Analyse ... - result = analyseCycleHelper.GetConditions( - analyseCycleEvents, - analysePoiEvents, - analyseConditions, - barIndex, - loopback // - ); - if (!result) + if (analyse) { // - Clean(triggerPoiEvents); - Clean(analysePoiEvents); - Clean(decisionPoiEvents); - Clean(triggerCycleEvents); - Clean(analyseCycleEvents); - triggerConditions.Clean(); - analyseConditions.Clean(); - Clean(decisionCycleEvents); - decisionConditions.Clean(); + result = analyseCycleHelper.GetConditions( + analyseCycleEvents, + analysePoiEvents, + analyseConditions, + barIndex, + loopback // + ); + if (!result) + { + // + Clean(triggerPoiEvents); + Clean(analysePoiEvents); + Clean(decisionPoiEvents); + Clean(triggerCycleEvents); + Clean(analyseCycleEvents); + triggerConditions.Clean(); + analyseConditions.Clean(); + Clean(decisionCycleEvents); + decisionConditions.Clean(); - // - return result; + // + return result; + } } // // Verification ... - result = verificationCycleHelper.GetConditions( - verificationCycleEvents, - verificationPoiEvents, - verificationConditions, - barIndex, - loopback // - ); - if (!result) + if (verification) { // - Clean(triggerPoiEvents); - Clean(analysePoiEvents); - Clean(decisionPoiEvents); - Clean(triggerCycleEvents); - Clean(analyseCycleEvents); - triggerConditions.Clean(); - analyseConditions.Clean(); - Clean(decisionCycleEvents); - decisionConditions.Clean(); - Clean(verificationPoiEvents); - Clean(verificationCycleEvents); - verificationConditions.Clean(); + result = verificationCycleHelper.GetConditions( + verificationCycleEvents, + verificationPoiEvents, + verificationConditions, + barIndex, + loopback // + ); + if (!result) + { + // + Clean(triggerPoiEvents); + Clean(analysePoiEvents); + Clean(decisionPoiEvents); + Clean(triggerCycleEvents); + Clean(analyseCycleEvents); + triggerConditions.Clean(); + analyseConditions.Clean(); + Clean(decisionCycleEvents); + decisionConditions.Clean(); + Clean(verificationPoiEvents); + Clean(verificationCycleEvents); + verificationConditions.Clean(); - // - return result; + // + return result; + } } // // Consolidation ... - result = consolidationCycleHelper.GetConditions( - consolidationCycleEvents, - consolidationPoiEvents, - consolidationConditions, - barIndex, - loopback // - ); - if (!result) + if (consolidation) { // - Clean(triggerPoiEvents); - Clean(analysePoiEvents); - Clean(decisionPoiEvents); - Clean(triggerCycleEvents); - Clean(analyseCycleEvents); - triggerConditions.Clean(); - analyseConditions.Clean(); - Clean(decisionCycleEvents); - decisionConditions.Clean(); - Clean(verificationPoiEvents); - Clean(consolidationPoiEvents); - Clean(verificationCycleEvents); - verificationConditions.Clean(); - Clean(consolidationCycleEvents); - consolidationConditions.Clean(); + result = consolidationCycleHelper.GetConditions( + consolidationCycleEvents, + consolidationPoiEvents, + consolidationConditions, + barIndex, + loopback // + ); + if (!result) + { + // + Clean(triggerPoiEvents); + Clean(analysePoiEvents); + Clean(decisionPoiEvents); + Clean(triggerCycleEvents); + Clean(analyseCycleEvents); + triggerConditions.Clean(); + analyseConditions.Clean(); + Clean(decisionCycleEvents); + decisionConditions.Clean(); + Clean(verificationPoiEvents); + Clean(consolidationPoiEvents); + Clean(verificationCycleEvents); + verificationConditions.Clean(); + Clean(consolidationCycleEvents); + consolidationConditions.Clean(); - // - return result; + // + return result; + } } // // Vision ... - result = visionCycleHelper.GetConditions( - visionCycleEvents, - visionPoiEvents, - visionConditions, - barIndex, - loopback // - ); - if (!result) + if (vision) { - // - Clean(visionPoiEvents); - Clean(triggerPoiEvents); - Clean(analysePoiEvents); - Clean(visionCycleEvents); - visionConditions.Clean(); - Clean(decisionPoiEvents); - Clean(triggerCycleEvents); - Clean(analyseCycleEvents); - triggerConditions.Clean(); - analyseConditions.Clean(); - Clean(decisionCycleEvents); - decisionConditions.Clean(); - Clean(verificationPoiEvents); - Clean(consolidationPoiEvents); - Clean(verificationCycleEvents); - verificationConditions.Clean(); - Clean(consolidationCycleEvents); - consolidationConditions.Clean(); + result = visionCycleHelper.GetConditions( + visionCycleEvents, + visionPoiEvents, + visionConditions, + barIndex, + loopback // + ); + if (!result) + { + // + Clean(visionPoiEvents); + Clean(triggerPoiEvents); + Clean(analysePoiEvents); + Clean(visionCycleEvents); + visionConditions.Clean(); + Clean(decisionPoiEvents); + Clean(triggerCycleEvents); + Clean(analyseCycleEvents); + triggerConditions.Clean(); + analyseConditions.Clean(); + Clean(decisionCycleEvents); + decisionConditions.Clean(); + Clean(verificationPoiEvents); + Clean(consolidationPoiEvents); + Clean(verificationCycleEvents); + verificationConditions.Clean(); + Clean(consolidationCycleEvents); + consolidationConditions.Clean(); - // - return result; + // + return result; + } } // @@ -2593,7 +2622,6 @@ struct X121SMCStrategyConditionParser return result; } - // // // Detecting Signal Conditions ... @@ -2602,21 +2630,16 @@ struct X121SMCStrategyConditionParser isBullish = // // Base Condition ... - cXConditions.isSMHKSwitchedToBullish && ( // - // Validate CBar ... - cBar.IsBullish() && + cXConditions.supportsBuffer[cIDX] == cXConditions.valesBuffer[zIDX] // - (cBar.low >= cXConditions.valesGoldenBuffer[cIDX] || - (cBar.low < cXConditions.valesGoldenBuffer[cIDX] && - cXConditions.isSarSwitchedToBullish)) && - // - (cBar.open == cXConditions.xhkSMOpenBuffer[cIDX] || - (cBar.low < cXConditions.xhkSMLowBuffer[cIDX] && - cBar.GetDown() > cXConditions.xhkSMHighBuffer[cIDX])) && - // - cXConditions.isSarBullish + // cXConditions.isSarSwitchedToBullish && + // cXConditions.isSMHKSwitchedToBullish && + // cBar.low < cXConditions.masLowerBuffer[cIDX] && + // cBar.low < cXConditions.valesGoldenBuffer[cIDX] && + // zBar.close < cXConditions.valesGoldenBuffer[cIDX] && + // cXConditions.xhkSMCloseBuffer[cIDX] < cXConditions.valesGoldenBuffer[cIDX] // ) // @@ -2627,21 +2650,9 @@ struct X121SMCStrategyConditionParser isBearish = // // Base Condition ... - cXConditions.isSMHKSwitchedToBearish && ( // - // Validate CBar ... - cBar.IsBearish() && - // - (cBar.high <= cXConditions.peaksGoldenBuffer[cIDX] || - (cBar.high > cXConditions.peaksGoldenBuffer[cIDX] && - cXConditions.isSarSwitchedToBearish)) && - // - (cBar.open == cXConditions.xhkSMOpenBuffer[cIDX] || - (cBar.high > cXConditions.xhkSMHighBuffer[cIDX] && - cBar.GetUp() < cXConditions.xhkSMLowBuffer[cIDX])) && - // - cXConditions.isSarBearish + false // ) // diff --git a/X121SMCEA/Signals/x-121.smc.xwz.signal.class.mq5 b/X121SMCEA/Signals/x-121.smc.xwz.signal.class.mq5 index cef23bdf..512971c4 100644 --- a/X121SMCEA/Signals/x-121.smc.xwz.signal.class.mq5 +++ b/X121SMCEA/Signals/x-121.smc.xwz.signal.class.mq5 @@ -117,7 +117,13 @@ class XCX121SMCXWZSignalDetector : public XCBase // Cycles Conditions ... result = provider.Prepare( zIndex, - loopback // + loopback, + false, // Trigger ... + true, // Decision ... + true, // Analyse ... + true, // Verification ... + true, // Consolidation ... + true // Vision ... ); if (!result) { diff --git a/X121SMCEA/Signals/x-121.smc.xwz.signal.lib.mq5 b/X121SMCEA/Signals/x-121.smc.xwz.signal.lib.mq5 index f02fbae0..ee8e93dd 100644 --- a/X121SMCEA/Signals/x-121.smc.xwz.signal.lib.mq5 +++ b/X121SMCEA/Signals/x-121.smc.xwz.signal.lib.mq5 @@ -1002,7 +1002,7 @@ struct X121SMCStrategyXWZWorkingZone // --------------------------------------------- // XPVHK Conditions ... // --------------------------------------------- - bool useSenario1 = false; + bool useSenario1 = true; bool isSenario1Happend = false; bool isSenario1Bullish = false; bool isSenario1Bearish = false; diff --git a/X121SMCEA/Strategy/x-121.smc.strategy.class.mq5 b/X121SMCEA/Strategy/x-121.smc.strategy.class.mq5 index 780f2934..1a556429 100644 --- a/X121SMCEA/Strategy/x-121.smc.strategy.class.mq5 +++ b/X121SMCEA/Strategy/x-121.smc.strategy.class.mq5 @@ -784,12 +784,6 @@ class XCX121SMCStrategy : public XCX121SMCBaseStrategy // XCC ... x121Inputs.xccInputs.showCandles = showAll || true; - // - // XTREND ... - x121Inputs.xtrendInputs.showUpTrend = showAll || false; - x121Inputs.xtrendInputs.showDownTrend = showAll || false; - x121Inputs.xtrendInputs.showOnlyTrendStart = showAll || false; - // // XPV ... x121Inputs.xpvInputs.showSar = showAll || true;