/////////////////////////////////////////////////////// // // 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 // ); } //