/////////////////////////////////////////////////////// // // 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; long volume; 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); // volume = iTickVolume( mSymbol, mPeriod, barIndex // ); // 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; } // // Tools ... // void Clean() { // low = 0; high = 0; open = 0; close = 0; spread = 0; volume = 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 && volume > 0 // // TODO: Fix in Some Cases for Zero Spread ... // 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 BarAt( datetime _time, XOHCL &bar // ) { // bool result = false; // bar.Clean(); // result = IsValid(); if (!result) { return result; } // _time = NormalizeTime(_time); // result = bar.Init( symbol, period, _time // ); // 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; } // bool HasFiboPressure( ENUM_X_DIRECTION forDir, ENUM_X_FIBO_LEVELS level = X_FIBO_LEVEL_382 // ) { // bool result = false; // result = IsValid() && HasDirection(forDir); if (!result) { return result; } // bool isBullish = IsSpecifiedBullish(forDir); bool isBearish = IsSpecifiedBearish(forDir); // double fiboLevelValue = GetFibonacciLevel( high, low, level, forDir // ); // isBullish = isBullish && GetDown() > fiboLevelValue; isBearish = isBearish && GetUp() < fiboLevelValue; // result = isBullish || isBearish; // return result; } // bool IsRejected( double price, ENUM_X_DIRECTION forDir, bool forceType = false, bool forcePressure = false // ) { // bool result = false; // result = IsValid() && price > 0 && HasDirection(forDir); if (!result) { return result; } // bool isBullish = IsSpecifiedBullish(forDir) && low < price && GetDown() > price; // bool isBearish = IsSpecifiedBearish(forDir) && high > price && GetUp() < price; // if (forceType) { // isBullish = isBullish && IsBullish(); // isBearish = isBearish && IsBearish(); } // if (forcePressure) { // isBullish = isBullish && HasFiboPressure(forDir); // isBearish = isBearish && HasFiboPressure(forDir); } // result = isBullish || isBearish; // return result; } // bool IsBreaked( double price, ENUM_X_DIRECTION forDir, ENUM_X_FIBO_LEVELS fibLevel = X_FIBO_LEVEL_500, ENUM_X_BOUNDARY_PRICE boundaryType = X_BOUNDARY_PRICE_UP_DOWN // ) { // bool result = false; // result = IsValid() && price > 0 && HasDirection(forDir) && IsSpecifiedValid(boundaryType); if (!result) { return result; } // bool isUpDownPriceType = boundaryType == X_BOUNDARY_PRICE_UP_DOWN; // bool isBullish = IsBullish() && low < price && high > price && IsSpecifiedBullish(forDir); // bool isBearish = IsBearish() && low < price && high > price && IsSpecifiedBearish(forDir); // result = isBullish || isBearish; if (result) { // // Calculate Range ... double range = isUpDownPriceType ? GetBody() : GetRange(); // // Apply Edge Range ... double iReqRange = (range / 100) * (GetFiboLevelValue(fibLevel) * 100); // // Calculate Boundary Price ... double iBoundary = isUpDownPriceType ? isBullish ? GetUp() : GetDown() : isBullish ? high : low; // // Detect Breaked Value ... // double breakedPrice = isBullish ? (high - price) : (price - low); // result = breakedPrice >= iReqRange; } // 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; } /** * Detect Highest of Specified Price type in Market ... * * @param index: souble, reference to hold detected Value Bar index ... * @param mLength: int, Specified Loopback Length ... * @param mPriceType: ENUM_X_PRICE, Specified Price type to Detect ... * * @return ( double ) */ double FindHighest( int &index, // Index ... int mLength, // Loopback ... ENUM_X_PRICE mPriceType // Price Type ... ) { // double result = EMPTY_VALUE; // // Prepare ... index = -1; // // Normalize ... mLength = NormalizeInt(mLength, 1); // // Validate ... bool has = IsValid() && IsXValid(mPriceType); if (!has) { return result; } // XOHCL iBar; int start = Index(); int end = start + mLength; double iValue = EMPTY_VALUE; for (int i = start; i < end; i++) { // iBar.Clean(); has = BarAt(i, iBar); if (!has) { continue; } // // Calculate Price ... iValue = iBar.GetPrice(mPriceType); // // Compare Price With Prev Detected ... has = !NotEmptyZero(result) ? true : iValue > result; if (has) { // index = i; result = iValue; } } // // Cleanup Resources ... iBar.Clean(); // 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; } /** * Detect Lowest of Specified Price type in Market ... * * @param index: souble, reference to hold detected Value Bar index ... * @param mLength: int, Specified Loopback Length ... * @param mPriceType: ENUM_X_PRICE, Specified Price type to Detect ... * * @return ( double ) */ double FindLowest( int &index, // Index ... int mLength, // Loopback ... ENUM_X_PRICE mPriceType // Price Type ... ) { // double result = EMPTY_VALUE; // // Prepare ... index = -1; // // Normalize ... mLength = NormalizeInt(mLength, 1); // // Validate ... bool has = IsValid() && IsXValid(mPriceType); if (!has) { return result; } // XOHCL iBar; int start = Index(); int end = start + mLength; double iValue = EMPTY_VALUE; for (int i = start; i < end; i++) { // iBar.Clean(); has = BarAt(i, iBar); if (!has) { continue; } // // Calculate Price ... iValue = iBar.GetPrice(mPriceType); // // Compare Price With Prev Detected ... has = !NotEmptyZero(result) ? true : iValue < result; if (has) { // index = i; result = iValue; } } // // Cleanup Resources ... iBar.Clean(); // 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; } // // Swing Detection ... // int FindSwing( ENUM_X_SWING_TYPE type, int shoulders = 3 // ) { // int result = -1; // // Validate ... bool isValid = IsValid() && IsXValid(type); if (!isValid) { return result; } // // Find Next Swing ... result = FindXSwing( type, symbol, period, Index(), shoulders // ); // return result; } // int FindNextSwing( ENUM_X_SWING_TYPE type, int shoulders = 3 // ) { // int result = -1; // // Validate ... bool isValid = IsValid() && IsXValid(type); if (!isValid) { return result; } // // Find Next Swing ... result = FindXSwing( type, symbol, period, Index() + 1, shoulders // ); // return result; } // bool FindSwingBar( ENUM_X_SWING_TYPE type, XOHCL &swingBar, int shoulders = 3 // ) { // bool result = false; // // Prepare ... swingBar.Clean(); // // Validate ... result = IsValid() && IsXValid(type); if (!result) { return result; } // // Find Next Swing ... int idx = FindXSwing( type, symbol, period, Index(), shoulders // ); result = IsValidIndex(idx); if (!result) { return result; } // result = swingBar.Init( symbol, period, idx // ); // return result; } // bool FindNextSwingBar( ENUM_X_SWING_TYPE type, XOHCL &swingBar, int shoulders = 3 // ) { // bool result = false; // // Prepare ... swingBar.Clean(); // // Validate ... result = IsValid() && IsXValid(type); if (!result) { return result; } // // Find Next Swing ... int idx = FindXSwing( type, symbol, period, Index() + 1, shoulders // ); result = IsValidIndex(idx); if (!result) { return result; } // result = swingBar.Init( symbol, period, idx // ); // return result; } // // Same Checkers ... // bool IsSameAs(XOHCL &item) { // bool result = false; // result = IsValid() && item.IsValid() && IsSameTime(item) && IsSameMarket(item); // return result; } // bool IsSameTime(XOHCL &item) { // bool result = false; // result = IsValid() && item.IsValid() && time == item.time; // return result; } // bool IsSameSymbol(XOHCL &item) { // bool result = false; // result = IsValid() && item.IsValid() && symbol == item.symbol; // return result; } // bool IsSamePeriod(XOHCL &item) { // bool result = false; // result = IsValid() && item.IsValid() && period == item.period; // return result; } // bool IsSameMarket(XOHCL &item) { // bool result = false; // result = IsValid() && item.IsValid() && IsSameSymbol(item) && IsSamePeriod(item); // return result; } // // Other ... string GetTag(string prefix = "") { // string result = NULL; // result = (IsSpecifiedValid(prefix) ? prefix + "_" : "") + "XOHCL_" + symbol + "_" + ToXString(period) + "_" + ToFormatString(time); // return result; } // // Convert to String Representation ... string ToString() { // string result = ""; // result = GetTypeName(this) + "(O(" + ToXString(open) + "),H(" + ToXString(high) + "),C(" + ToXString(close) + "),L(" + ToXString(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 = ToXString(hours); if (StringLen(strHour) == 1) { strHour = "0" + strHour; } // result += hourId + idSeparator + strHour + separator; } // // Minutes ... if (!ignoreZeroValues || minutes > 0) { // string strMinute = ToXString(minutes); if (StringLen(strMinute) == 1) { strMinute = "0" + strMinute; } // result += minuteId + idSeparator + strMinute + separator; } // // Seconds ... if (!ignoreZeroValues || seconds > 0) { // string strSec = ToXString(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 // ); } /** * Remove Specified Item from a Collection ... * * @param item: Specified Item ... * @param source: Specified Collection for Remove item from it ... * * @return ( bool ) */ bool Remove( XOHCL &item, XOHCL &source[] // ) { // bool result = false; // result = item.IsValid() && HasChild(source); if (!result) { return result; } // int idx = -1; result = FindIndex( idx, item, source // ); if (!result) { return result; } // result = ArrayRemove( source, idx, 1 // ); // return result; } /** * Remove Specified items from a Collection ... * * @param items: Specified Items to Remove ... * @param sources: Sepcified Collection for Removing items from it ... * * @return ( int ) */ int Removes( XOHCL &items[], XOHCL &sources[] // ) { // int result = 0; // bool has = HasChild(items) && HasChild(sources); if (!has) { return result; } // int idx = -1; has = false; int count = ArraySize(items); for (int i = 0; i < count; i++) { // // Detect Item Index in Collection ... has = FindIndex( idx, items[i], sources // ); if (has) { // // Remove Detected Index from Collection ... has = ArrayRemove( sources, idx, 1 // ); // if (has) { // // Count Removed Items ... result++; } } } // return result; } /** * Find Specified Item index in a Collection ... * * @param index: int, reference to Hold Index if Exists ... * @param item: Specified item to Detect ... * @param source: Collection to Search for item ... * * @return ( bool ) */ bool FindIndex( int &index, XOHCL &item, XOHCL &source[] // ) { // bool result = false; // index = -1; // int count = ArraySize(source); result = item.IsValid() && IsValidSize(count); if (!result) { return result; } // for (int i = 0; i < count; i++) { // bool isSame = item.IsSameAs(source[i]); if (isSame) { // index = i; break; } } // result = IsValidIndex(index); // return result; } /** * Add Specified Item to Specified Collection, if not Exists ... * * @param item: Item to Add ... * @param sources: Collection to Add item ... * @param maxAllowed: int, Max Allowed Collection Size ... * * @return ( bool ) */ bool AddIfNotExists( XOHCL &item, XOHCL &sources[], int maxAllowed = 0 // ) { // bool result = false; // // Validate Args ... result = item.IsValid(); if (!result) { return result; } // // Check Item Exists or not ... int idx = -1; bool isExists = FindIndex( idx, item, sources // ); result = !isExists; if (!result) { return result; } // AddRef( item, sources // ); // // Handle Cleanup Collection // if Max Reached ... if (result && maxAllowed > 0) { // CleanupArray( sources, maxAllowed // ); } // return result; } /** * Get Oldest Index of Specified Collection ... * * @param source: Specified Collection ... * * @return ( int ) */ int GetOldest( XOHCL &source[] // ) { // int result = -1; // int count = ArraySize(source); if (!IsValidSize(count)) { return result; } // XOHCL selected; for (int i = 0; i < count; i++) { // bool canSet = !selected.IsValid() ? true : selected.time > source[i].time; if (canSet) { // result = i; selected = source[i]; } } // selected.Clean(); // return result; } /** * Get Youngest Index of Specified Collection ... * * @param source: Specified Collection ... * * @return ( int ) */ int GetYoungest( XOHCL &source[] // ) { // int result = -1; // int count = ArraySize(source); if (!IsValidSize(count)) { return result; } // XOHCL selected; for (int i = 0; i < count; i++) { // bool canSet = !selected.IsValid() ? true : selected.time < source[i].time; if (canSet) { // result = i; selected = source[i]; } } // selected.Clean(); // return result; } /** * Get Lowest Index of Specified Collection ... * * @param source: Specified Collection ... * * @return ( int ) */ int GetLowest( XOHCL &source[], ENUM_X_PRICE _priceType = X_PRICE_LOW // ) { // int result = -1; // if (!IsXValid(_priceType)) { _priceType = X_PRICE_LOW; } // int count = ArraySize(source); if (!IsValidSize(count)) { return result; } // XOHCL selected; double iPrice = EMPTY_VALUE; double selectedPrice = EMPTY_VALUE; for (int i = 0; i < count; i++) { // iPrice = source[i].GetPrice(_priceType); selectedPrice = selected.GetPrice(_priceType); // bool canSet = !selected.IsValid() ? true : selectedPrice > iPrice; if (canSet) { // result = i; selected = source[i]; } } // selected.Clean(); // return result; } /** * Get Highest Index of Specified Collection ... * * @param source: Specified Collection ... * @param _priceType: Specified Price type ... * * @return ( int ) */ int GetHighest( XOHCL &source[], ENUM_X_PRICE _priceType = X_PRICE_HIGH // ) { // int result = -1; // if (!IsXValid(_priceType)) { _priceType = X_PRICE_HIGH; } // int count = ArraySize(source); if (!IsValidSize(count)) { return result; } // XOHCL selected; double iPrice = EMPTY_VALUE; double selectedPrice = EMPTY_VALUE; for (int i = 0; i < count; i++) { // iPrice = source[i].GetPrice(_priceType); selectedPrice = selected.GetPrice(_priceType); // bool canSet = !selected.IsValid() ? true : selectedPrice < iPrice; if (canSet) { // result = i; selected = source[i]; } } // selected.Clean(); // return result; } /** * Get Nearest Directional Bar ... * * @param bar: XOHCL, reference to Specified Start Bar ... * @param directionalBar: XOHCL, reference to hold Detected Bar ... * @param forDir: ENUM_X_DIRECTION, Specified Which Directional Bar looking for ... * @param loopback: int, Loopback Length ... * * @return ( bool ) */ bool GetDirectionalBar( XOHCL &bar, XOHCL &directionalBar, ENUM_X_DIRECTION forDir, int loopback = 1500 // ) { // bool result = false; // // Prepare ... directionalBar.Clean(); // // Normalize ... loopback = NormalizeInt(loopback, 1); // // Validate ... result = bar.IsValid() && HasDirection(forDir); if (!result) { return result; } // int start = bar.Index() + 1; int end = start + loopback; for (int i = start; i < end; i++) { // directionalBar.Clean(); result = bar.BarAt(i, directionalBar); result = result && directionalBar.GetDirection() == forDir; if (result) { break; } // directionalBar.Clean(); } // result = directionalBar.IsValid() && forDir == directionalBar.GetDirection(); // // Cleanup Resources ... if (!result) { directionalBar.Clean(); } // return result; } /** * Get Nearest Breaker Bar of Specified Bar's Price ... * * @param bar: XOHCL, reference to Specified Bar ... * @param breaker: XOHCL, reference to hold Detected Breaker Bar ... * @param priceType: ENUM_X_PRICE, which price type of Bar to Check to Break ... * @param breakType: ENUM_X_PRICE, which price of Breaker Bar must Breke price ... * @param breakDir: ENUM_X_DIRECTION, Specified Break Direction ... * @param loopback: int, Max Allowed Loopback to Detect Breaker Bar ... * * @return ( bool ) */ bool GetBreakerBar( XOHCL &bar, XOHCL &breaker, ENUM_X_PRICE priceType, ENUM_X_PRICE breakType, ENUM_X_DIRECTION breakDir, int loopback = 1500 // ) { // // PriceType: which Applied Price of Specified Bar must to Check for Break ... // // BreakType: which Applied Price of breakerBar must Break price ... // // BreakDir: // ----------- // Bullish: Price Must Break Applied Price from Down to Top ... // Bearish: Price must Break Applied Price from Top to Down ... // bool result = false; // // Prepare ... breaker.Clean(); // // Normalize ... loopback = NormalizeInt(loopback, 1); // // Validate ... result = bar.IsValid() && IsXValid(priceType) && IsXValid(breakType) && HasDirection(breakDir); if (!result) { return result; } // double iPrice = EMPTY_VALUE; bool isBullish = IsXBullish(breakDir); double price = bar.GetPrice(priceType); // int start = bar.Index(); int end = start + loopback; for (int i = start; i < end; i++) { // breaker.Clean(); iPrice = EMPTY_VALUE; // // Initialize Indexed Bar ... result = bar.BarAt(i, breaker); if (!result) { breaker.Clean(); break; } // // Check Breake ... iPrice = breaker.GetPrice(breakType); result = isBullish ? iPrice > price : iPrice < price; if (result) { break; } } // result = breaker.IsValid(); // // Cleanup Resources ... if (!result) { breaker.Clean(); } // return result; } //