/////////////////////////////////////////////////////// // // SaherElm IT Center MQL5 Tools Library // -------------------------------------- // Name: XToolsLib // Description: provide all commonly used Tools ... // // // 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 "../Libraries/x-saherelm.draw.lib.mq5" #include "../Libraries/x-saherelm.common.lib.mq5" // // Definitions ... // // a Pivot Point ... struct XPivot { // string symbol; // Trading Symbol ... ENUM_TIMEFRAMES period; // Trading TimeFrame ... // double price; // Price ... datetime time; // Time ... // int breakedAsSupport; // Number of Breaked As Support ... int rejectedAsSupport; // Number of Rejected As Support ... // int breakedAsResistance; // Number of Breaked As Resistance ... int rejectedAsResistance; // Number of Rejected As Resistance ... // bool isSupport; datetime supportTime; // bool isResistance; datetime resistanceTime; // int _lastCalculatedBar; int _loopbackForSupportAndResistance; // Number of LoopBacks for Support or Resistance ... // // Constructor ... XPivot() { Clean(); } // // Initialization ... bool Init( string _symbol, ENUM_TIMEFRAMES _period, double _price, int barIndex = 0, int _supResVerificationsStep = 21 // ) { // bool result = false; // if (barIndex < 0) { barIndex = 0; } // if (_supResVerificationsStep < 0) { _supResVerificationsStep = 21; } // result = // _price > 0 && IsValid(_symbol) && IsValid(_period) && IsValidSize(_supResVerificationsStep) // ; if (!result) { return result; } // symbol = _symbol; period = _period; price = _price; // _loopbackForSupportAndResistance = _supResVerificationsStep; // Calculate( barIndex // ); // result = IsValid(); // return result; } // // Find Last Support for Market and // Initialize Pivot Based On it ... bool FindLastSupport( string _symbol, ENUM_TIMEFRAMES _period, int barIndex = 0, int _supResVerificationsStep = 21 // ) { // bool result = false; // if (barIndex < 0) { barIndex = 0; } // if (_supResVerificationsStep < 0) { _supResVerificationsStep = 21; } // result = // IsValid(_symbol) && IsValid(_period) && IsValidSize(_supResVerificationsStep) // ; if (!result) { return result; } // // Find Resistance ... // // Retrieve Current Bar ... XOHCL cBar; result = cBar.Init( _symbol, _period, barIndex // ); if (!result) { return result; } // // Calculate Available Bars ... // int bars = iBars( _symbol, _period // ); int maxAllowedBars = bars - 500; int currentLength = _supResVerificationsStep; // // Find Highest High ... for (int i = barIndex; i < maxAllowedBars; i++) { // // Validate and Regenrate Current Length ... if (i > 1) { // currentLength = _supResVerificationsStep * i; // if (currentLength > maxAllowedBars) { currentLength = maxAllowedBars; } } // // Clean ... Clean(); // int llIndex = cBar.FindLowestIndex( currentLength, MODE_LOW // ); XOHCL llBar; result = llBar.Init( _Symbol, _Period, llIndex // ); if (!result) { continue; } // result = Init( _symbol, _period, llBar.low, barIndex // ); if (!result) { // Clean(); continue; } // result = isSupport; if (result) { // supportTime = llBar.time; break; } } // result = IsValid() && isSupport; // return result; } // // Find Last Resistance for Market and // Initialized Pivot Based On it ... bool FindLastResistance( string _symbol, ENUM_TIMEFRAMES _period, int barIndex = 0, int _supResVerificationsStep = 21 // ) { // bool result = false; // if (barIndex < 0) { barIndex = 0; } // if (_supResVerificationsStep < 0) { _supResVerificationsStep = 21; } // result = // IsValid(_symbol) && IsValid(_period) && IsValidSize(_supResVerificationsStep) // ; if (!result) { return result; } // // Find Resistance ... // // Retrieve Current Bar ... XOHCL cBar; result = cBar.Init( _symbol, _period, barIndex // ); if (!result) { return result; } // // Calculate Available Bars ... // int bars = iBars( _symbol, _period // ); int maxAllowedBars = bars - 500; int currentLength = _supResVerificationsStep; // // Find Highest High ... for (int i = barIndex; i < maxAllowedBars; i++) { // // Validate and Regenrate Current Length ... if (i > 1) { // currentLength = _supResVerificationsStep * i; // if (currentLength > maxAllowedBars) { currentLength = maxAllowedBars; } } // // Clean ... Clean(); // int hhIndex = cBar.FindHighestIndex( currentLength, MODE_HIGH // ); XOHCL hhBar; result = hhBar.Init( _Symbol, _Period, hhIndex // ); if (!result) { continue; } // result = Init( _symbol, _period, hhBar.high, barIndex // ); if (!result) { // Clean(); continue; } // result = isResistance; if (result) { // resistanceTime = hhBar.time; break; } } // result = IsValid() && isResistance; // return result; } // // Check Rejection Based On Pivot Type ... bool IsRejected() { // bool result = false; // result = // IsValid() && ( // isSupport || isResistance // ) // ; if (!result) { return result; } // result = // isSupport ? IsSupportRejected() : IsResistanceRejected() // ; // return result; } // // Check Breake Based On Pivot Type ... bool IsBreaked() { // bool result = false; // result = // IsValid() && ( // isSupport || isResistance // ) // ; if (!result) { return result; } // result = // isSupport ? IsSupportBreaked() : IsResistanceBreaked() // ; // return result; } // // Tools ... // // Check Support Rejected ... bool IsSupportRejected() { // bool result = false; // result = isSupport; if (!result) { return result; } // // Initialize Required Bars ... // XOHCL cBar; result = cBar.Init( symbol, period, 1 // ); if (!result) { return result; } // XOHCL pBar; result = pBar.Init( symbol, period, 2 // ); if (!result) { return result; } // result = // // Check Support Touch or Fake Break ... pBar.low < price // && // // Check Rejection ... cBar.low > price // ; // return result; } // // Check Support Breaked ... bool IsSupportBreaked() { // bool result = false; // result = isSupport; if (!result) { return result; } // // Initialize Required Bars ... // XOHCL cBar; result = cBar.Init( symbol, period, 1 // ); if (!result) { return result; } // XOHCL pBar; result = pBar.Init( symbol, period, 2 // ); if (!result) { return result; } // result = // // Check Support Breaks ... pBar.close < price // && // // Check 50% ... (price - pBar.close) > (pBar.GetBody() / 100) * 50 // && // // Also Next Bar must Closed Below Support ... cBar.high < price // && // cBar.close < price // && // cBar.IsBullish() // ; // return result; } // // Check Resistance Rejected ... bool IsResistanceRejected() { // bool result = false; // result = isResistance; if (!result) { return result; } // // Initialize Required Bars ... // XOHCL cBar; result = cBar.Init( symbol, period, 1 // ); if (!result) { return result; } // XOHCL pBar; result = pBar.Init( symbol, period, 2 // ); if (!result) { return result; } // result = // // Check Resistance Touch or Fake Break ... pBar.high > price // && // // Check Rejection ... cBar.high < price // ; // return result; } // // Check Resistance Breaked ... bool IsResistanceBreaked() { // bool result = false; // result = isResistance; if (!result) { return result; } // // Initialize Required Bars ... // XOHCL cBar; result = cBar.Init( symbol, period, 1 // ); if (!result) { return result; } // XOHCL pBar; result = pBar.Init( symbol, period, 2 // ); if (!result) { return result; } // result = // // Check Resistance Breaks ... pBar.close > price // && // // Check 50% ... (pBar.close - price) > (pBar.GetBody() / 100) * 50 // && // // Also Next Bar Must Closed Above Resistance ... cBar.low > price // && // cBar.close > price // && // cBar.IsBullish() // ; // return result; } // // Cleanup ... void Clean() { // time = NULL; symbol = NULL; period = NULL; supportTime = NULL; resistanceTime = NULL; // price = 0; // breakedAsSupport = 0; rejectedAsSupport = 0; breakedAsResistance = 0; rejectedAsResistance = 0; // _lastCalculatedBar = -1; // isSupport = false; isResistance = false; // _objName = NULL; } // // Validate Model ... bool IsValid() { // bool result = false; // result = // IsValid(symbol) && IsValid(period) && price > 0 // ; // return result; } // // Calculate Required Data ... void Calculate( int barIndex, int loopback = 288 // ) { // if (isSupport || isResistance) { return; } // int bars = iBars( symbol, period // ); // loopback += barIndex; // // Normalizing Loopback ... if (loopback > bars) { loopback = bars - 2 - _loopbackForSupportAndResistance; } // // Check Previous Calculation ... if (bars == _lastCalculatedBar) { return; } // _lastCalculatedBar = bars; // // First Get Current State of Pivot ... // Means Use Zero Index ... XOHCL pBar; bool isInited = pBar.Init( symbol, period, barIndex + 1 // ); if (!isInited) { return; } // // Retrieve Highest High and Lowest Low of SupRes Loopback ... double hhValue = pBar .FindHighest( _loopbackForSupportAndResistance, MODE_HIGH // ); // double llValue = pBar .FindLowest( _loopbackForSupportAndResistance, MODE_LOW // ); // isSupport = llValue > price; isResistance = hhValue < price; // // Prevent Moving Forward if it isn't Support or Resistance ... if (!isSupport && !isResistance) { return; } // time = TimeCurrent(); // for (int i = 2; i < loopback; i++) { // XOHCL iBar; isInited = iBar.Init( symbol, period, i // ); if (!isInited) { continue; } // XOHCL iPBar; isInited = iPBar.Init( symbol, period, i + 1 // ); if (!isInited) { continue; } // XOHCL iPPBar; isInited = iPPBar.Init( symbol, period, i + 2 // ); if (!isInited) { continue; } // bool isBreaked = false; bool isRejected = false; // if (isSupport) { // // Count Support Rejects // and Support Breaks ... // // Support Rejected ... isRejected = // // Check Support Touch or Fake Break ... iPBar.low < price // && // // Check Rejection ... iBar.low > price // ; if (isRejected) { rejectedAsSupport++; } // // Support Breaked ... isBreaked = // // Check Support Breaks ... iPBar.close < price // && // // Check 50% ... (price - iPBar.close) > (iPBar.GetBody() / 100) * 50 // && // // Also Next Bar must Closed Below Support ... iBar.high < price // && // iBar.close < price // && // iBar.IsBullish() // ; if (isBreaked) { breakedAsSupport++; } } else if (isResistance) { // // Count Resistance Reject // or Resistance Breaks ... // // Resistance Rejected ... isRejected = // // Check Resistance Touch or Fake Break ... iPBar.high > price // && // // Check Rejection ... iBar.high < price // ; if (isRejected) { rejectedAsResistance++; } // // Resistance Breaked ... isBreaked = // // Check Resistance Breaks ... iPBar.close > price // && // // Check 50% ... (iPBar.close - price) > (iPBar.GetBody() / 100) * 50 // && // // Also Next Bar Must Closed Above Resistance ... iBar.low > price // && // iBar.close > price // && // iBar.IsBullish() // ; if (isBreaked) { breakedAsResistance++; } } } } // string GetTag() { return "XPivot"; } // // Draw Functions ... // // Last Draw Object Name ... string _objName; // // Draw ... bool Draw( long _chartId, string _prefix = "", color _color = clrYellow, ENUM_LINE_STYLE _style = STYLE_DOT, bool _ray = true, int _width = 1, int _subWindow = 0, bool forcePrefix = false // ) { // bool result = false; // if (!isSupport && !isResistance) { return result; } // _objName = (IsValid(_prefix) && forcePrefix) ? _prefix : GetTag() + "_" + (IsValid(_prefix) ? _prefix + "_" : "") + ToString(NormalizeDouble(price, 2)); // int timeBarIndex = iBarShift( symbol, period, time, false // ); datetime time1 = // isSupport ? supportTime : resistanceTime // ; // result = DrawTrendLine( _chartId, _objName, _subWindow, time1, price, time, price, _color, _style, _width, false, false, _ray // ); // return result; } // // Remove Draw ... void Remove() { // if (!IsValid(_objName)) { return; } // RemoveDraws(_objName); } }; // // a Zone Modeling ... // enum ENUM_XZONE_STATE { XZONE_STATE_INVALID = 0, // Invalid Zone ... XZONE_STATE_FULL_SUPPORT = 1, // Full Support (up / down) are Support ... XZONE_STATE_FULL_RESISTANCE = 2, // Full Resistance (up / down) are Resistaence ... XZONE_STATE_CONSOLIDATE = 3, // Down are Support and Up are Resistance ... }; // // a Zone Consists an Area of // an Upper Pivot and a Lower Pivot ... struct XZone { // string symbol; // Trading Symbol ... ENUM_TIMEFRAMES period; // Trading TimeFrame ... // datetime time; // XPivot up; // Up pivot ... XPivot down; // Down Pivot ... // // Constructor ... XZone() { Clean(); } // // Initialize a Zone ... bool Init( string _symbol, ENUM_TIMEFRAMES _period, double _upPrice, double _downPrice, int barIndex = 0, int pivotVerificationStep = 21 // ) { // bool result = false; // result = // IsValid(_symbol) && IsValid(_period) && _upPrice > 0 && _downPrice > 0 && _downPrice < _upPrice // ; if (!result) { return result; } // symbol = _symbol; period = _period; // result = up.Init( symbol, period, _upPrice, barIndex, pivotVerificationStep // ); if (!result) { return result; } // result = down.Init( symbol, period, _downPrice, barIndex, pivotVerificationStep // ); if (!result) { return result; } // result = IsValid(); // if (result) { time = TimeCurrent(); } // return result; } // // Find Last Support Zone ... bool FindLastSupportZone( string _symbol, ENUM_TIMEFRAMES _period, int barIndex = 0, int pivotVerificationStep = 21 // ) { // bool result = false; // // Since Support Pivots Used Target Bar's Low price // Last Resistance Set in Down Line of Zone ... result = down.FindLastSupport( _symbol, _Period, barIndex, pivotVerificationStep // ); if (!result) { return result; } // // Since Support Pivots Used Target Bar's Low price // we can Set it's High as Up Zone ... XOHCL tBar; result = tBar.Init( _symbol, _period, down.supportTime // ); if (!result) { return result; } // // Now we Have Target Bar ... // Set it's High as Up Line of Zone ... result = up.Init( _symbol, _period, tBar.high, barIndex, pivotVerificationStep // ); if (!result) { return result; } // up.supportTime = down.supportTime; // if (result) { // symbol = _symbol; period = _period; // time = TimeCurrent(); } // return result; } // // Find Last Resistance Zone ... bool FindLastResistanceZone( string _symbol, ENUM_TIMEFRAMES _period, int barIndex = 0, int pivotVerificationStep = 21 // ) { // bool result = false; // // Since Resistance Pivots Used Target Bar's High price // Last Resistance Set in Up Line of Zone ... result = up.FindLastResistance( _symbol, _Period, barIndex, pivotVerificationStep // ); if (!result) { return result; } // // Since Resistance Pivots Used Target Bar's High price // we can Set it's Low as Down Zone ... XOHCL tBar; result = tBar.Init( _symbol, _period, up.resistanceTime // ); if (!result) { return result; } // // Now we Have Target Bar ... // Set it's Low as Down Line of Zone ... result = down.Init( _symbol, _period, tBar.low, barIndex, pivotVerificationStep // ); if (!result) { return result; } // down.resistanceTime = up.resistanceTime; // if (result) { // symbol = _symbol; period = _period; // time = TimeCurrent(); } // return result; } // // Tools ... // // Check XZone State ... ENUM_XZONE_STATE GetState() { // ENUM_XZONE_STATE result = XZONE_STATE_INVALID; if (!IsValid()) { return result; } // if (up.isSupport && down.isSupport) { result = XZONE_STATE_FULL_SUPPORT; } else if (up.isResistance && down.isResistance) { result = XZONE_STATE_FULL_RESISTANCE; } else if (up.isSupport && down.isResistance) { result = XZONE_STATE_CONSOLIDATE; } // return result; } // // Zone Tools ... double _threshold; double GetThresholdPoints() { // double result = 0; // if (!IsValid()) { return result; } // double _points = GetPoints(symbol); result = // _points && _threshold // ; // return result; } // // Check Zone Rejected ... bool IsSupportRejected() { // bool result = false; // // Check is Full Support or Not ... ENUM_XZONE_STATE state = GetState(); result = state == XZONE_STATE_FULL_SUPPORT; if (!result) { return result; } // // First Check Price Rejection Above Upper Line ... // return result; } // // Check Zone Breaked ... // // Cleanup ... void Clean() { // symbol = NULL; period = NULL; time = NULL; // up.Clean(); down.Clean(); // _threshold = 15; // _objName = NULL; } // // Validate ... bool IsValid() { // bool result = false; // result = // IsValid(symbol) && IsValid(period) && up.IsValid() && down.IsValid() && _threshold > 0 // ; // return result; } // string GetTag() { return "XZone"; } // // Draw Functions ... // // Last Draw Object Name ... string _objName; // // Draw ... bool Draw( long _chartId, string _prefix = "", color _color = clrYellow, ENUM_LINE_STYLE _style = STYLE_DOT, bool _ray = true, int _width = 1, int _subWindow = 0 // ) { // bool result = false; // ENUM_XZONE_STATE state = GetState(); // result = // IsValid() && state != XZONE_STATE_INVALID // ; if (!result) { return result; } // _objName = GetTag() + "_" + (IsValid(_prefix) ? _prefix + "_" : "") + ToString(NormalizeDouble(up.price, 2)) + "," + ToString(NormalizeDouble(down.price, 2)); // datetime time1 = // down.isSupport ? down.supportTime : down.resistanceTime // ; // result = down.Draw( _chartId, _objName + "_DOWN", _color, _style, _ray, _width, _subWindow, true // Force PRefix ... ); if (!result) { return result; } // result = up.Draw( _chartId, _objName + "_UP", _color, _style, _ray, _width, _subWindow, true // Force PRefix ... ); // return result; } // // Remove Draw ... void Remove() { // if (!IsValid(_objName)) { return; } // RemoveDraws(_objName); } }; // // a Range Box Model ... // struct XRBox // { // // // string symbol; // ENUM_TIMEFRAMES period; // // // datetime time; // datetime expiration; // // // XZone up; // Up Zone ... // XZone down; // Down Zone ... // // // // Constructor ... // XRBox() // { // Clean(); // } // // // // Initialization ... // bool Init( // string _symbol, // ENUM_TIMEFRAMES _period, // double _upZoneUpperPrice, // double _upZoneLowerPrice, // double _downZoneUpperPrice, // double _downZoneLowerPrice, // datetime _expiration = NULL // // ) // { // // // bool result = false; // // // result = // // // IsValid(_symbol) && // IsValid(_period) && // _upZoneUpperPrice > 0 && // _upZoneLowerPrice > 0 && // _upZoneLowerPrice < _upZoneUpperPrice && // _downZoneUpperPrice > 0 && // _downZoneLowerPrice > 0 && // _downZoneLowerPrice < _downZoneUpperPrice // // // ; // // // if (!result) // { // return result; // } // // // result = IsValid(); // // // if (result) // { // // // time = TimeCurrent(); // } // // // return result; // } // // // // Tools ... // // // // Cleanup ... // void Clean() // { // // // time = NULL; // symbol = NULL; // period = NULL; // expiration = NULL; // // // up.Clean(); // down.Clean(); // } // // // // Validation ... // bool IsValid() // { // // // bool result = false; // // // result = // // // IsValid(symbol) && // IsValid(period) && // up.IsValid() && // down.IsValid() // // // ; // // // return result; // } // }; // // // // Detect Trends ... // struct XTrendDetector // { // // // string symbol; // ENUM_TIMEFRAMES period; // // // double higherHighs[]; // datetime higherHighTimes[]; // // // double higherLows[]; // datetime higherLowTimes[]; // // // double lowerHighs[]; // datetime lowerHighTimes[]; // // // double lowerLows[]; // datetime lowerLowTimes[]; // // // int _numberOfPivots; // int _pivotShoulders; // // // // Constructor ... // XTrendDetector() // { // Clean(); // } // // // // Tools ... // // // // Cleanup ... // void Clean() // { // // // symbol = NULL; // period = NULL; // // // _numberOfPivots = 0; // _pivotShoulders = 0; // // // Clean(higherHighs); // Clean(higherHighTimes); // // // Clean(higherLows); // Clean(higherLowTimes); // // // Clean(lowerHighs); // Clean(lowerHighTimes); // // // Clean(lowerLows); // Clean(lowerLowTimes); // } // // // // Validate ... // bool IsValid() // { // // // bool result = false; // // // result = // // // IsValid(symbol) && // IsValid(period) // // // ; // // // return result; // } // };