diff --git a/Documents/Notes/ZigZag Linear Regression Result Test.txt b/Documents/Notes/ZigZag Linear Regression Result Test.txt new file mode 100644 index 00000000..2c2b3115 --- /dev/null +++ b/Documents/Notes/ZigZag Linear Regression Result Test.txt @@ -0,0 +1,33 @@ +========== +Test: +========== +TO: D'2024.12.31 21:15:00' +From: D'2024.12.26 19:45:00' + +Support: +========= +Minor: 1.0371600000000001 +Major: 1.0343800000000001 + +Resistance: +============ +Minor: 1.0443899999999999 +Major: 1.04582 + +Slope: +============= +Peak: 0.000003537255859231 +Vale: 0.000004208223277701 + +Intercept: +============== +Peak: 1.0404296187948323 +Vale: 1.0385336052465912 + +Values: +==================== +Peak From: 1.0436237608357177 +Peak To: 1.0405074384237354 + +Vale From: 1.0423336308663556 +Vale To: 1.0386261861587007 diff --git a/Documents/Notes/ZigZag Linear Regression Result XFIMA.txt b/Documents/Notes/ZigZag Linear Regression Result XFIMA.txt new file mode 100644 index 00000000..4b6e1a81 --- /dev/null +++ b/Documents/Notes/ZigZag Linear Regression Result XFIMA.txt @@ -0,0 +1,33 @@ +========== +Test: +========== +TO: D'2024.12.31 21:15:00' O +From: D'2024.12.26 18:55:00' X + +Support: +========= +Minor: 1.0371600000000001 O +Major: 1.0343800000000001 O + +Resistance: +============ +Minor: 1.0443899999999999 O +Major: 1.04582 O + +Slope: +============= +Peak: 0.000003194109764736 X +Vale: 0.000004351756566922 X + +Intercept: +============== +Peak: 1.0405539031901065 X +Vale: 1.0383562942289146 X + +Values: +==================== +Peak From: 1.0434701254053103 X +Peak To: 1.0406241736049306 X + +Vale From: 1.0423294479745144 X +Vale To: 1.0384520328733868 X diff --git a/Experts/TestRegresser.mq5 b/Experts/TestRegresser.mq5 new file mode 100644 index 00000000..cd880162 --- /dev/null +++ b/Experts/TestRegresser.mq5 @@ -0,0 +1,1108 @@ +//+------------------------------------------------------------------+ +//| TestRegresser.mq5 | +//| SaherElm IT Center | +//| https://www.saherelm.ir | +//+------------------------------------------------------------------+ +#property copyright "SaherElm IT Center" +#property link "https://www.saherelm.ir" +#property version "1.00" + +// +// Imports ... +#include "../Classes/x-saherelm.x-cobject.class.mq5" +#include "../Libraries/x-saherelm.common.lib.mq5" +#include "../Libraries/x-saherelm.x-poi.lib.mq5" +#include + +// +// Inputs ... + +// +// Calculation ... +input int zigzagDepth = 12; // Depth +input int zigzagDeviation = 5; // Deviation +input int zigzagBackStep = 3; // Back Step +input int mLoopbackLength = 200; // Loopback Length for Calculation +input int mRequiredPivots = 50; // Required Peaks for Calculation (0 > use loopback ) + +// +// Variables ... + +// +double mZigZagBuffer[]; // ZigZag Values Buffer ... +XBarTracker mBarTracker; // Bar Tracker ... +bool mZigZagPivotIsPeaks[]; // Check ZigZag Pivot Peak or Vale ... +double mZigZagPivotPrices[]; // ZigZag Pivot Prices ... +double mZigZagPivotIndexes[]; // ZigZag Pivot Indexes ... +datetime mZigZagPivotTimes[]; // ZigZag Pivot Times ... +CChartObjectTrend *mUpperTrend; // Trend Line Upper ... +CChartObjectTrend *mLowerTrend; // Trend Line Lower ... +int mZigZagHandler = INVALID_HANDLE; // ZigZag Indicator Handler ... + +// +double mPeakSlope; +double mPeakIntercept; +double mZigZagPeaks[]; +double mZigZagPeakIndexes[]; +datetime mZigZagPeakTimes[]; + +// +double mValeSlope; +double mValeIntercept; +double mZigZagVales[]; +double mZigZagValeIndexes[]; +datetime mZigZagValeTimes[]; + +// +datetime mToTime; +datetime mFromTime; + +// +// Predictions ... + +// +double mPeakTo; +double mValeTo; +double mPeakFrom; +double mValeFrom; + +// +ENUM_X_DIRECTION mUpperTrendDir; +ENUM_X_DIRECTION mLowerTrendDir; + +// +// Support and Resistances ... + +// +XBoxZone mSupportBox; +double mMinorSupport; +double mMajorSupport; +XCBoxObject *mSupportObj; + +// +XBoxZone mResistanceBox; +double mMinorResistance; +double mMajorResistance; +XCBoxObject *mResistanceObj; + +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() +{ + // + // Initialize Bar Tracker ... + mBarTracker.Init( + _Symbol, + _Period // + ); + + // + // Initialize ZigZag Handler ... + mZigZagHandler = iCustom( + _Symbol, + _Period, + "ZigZag", + zigzagDepth, + zigzagDeviation, + zigzagBackStep // + ); + if (mZigZagHandler == INVALID_HANDLE) + { + Print("Error creating ZigZag handle"); + return (INIT_FAILED); + } + + // + return (INIT_SUCCEEDED); +} +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) +{ + // + IndicatorRelease(mZigZagHandler); +} +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() +{ + // + if (!mBarTracker.IsNewBar()) + { + return; + } + + // + int readedZigZagsCount = 0; + bool readZigZagsBasedOnPivots = mRequiredPivots > 0; + + // + // Reading ZigZag Values Based on Loopback Length ... + if (!readZigZagsBasedOnPivots) + { + readedZigZagsCount = ReadZigZagValues(); + } + // + // Reading ZigZag Pivots based on required Pivots ... + else + { + // + readedZigZagsCount = ReadingZigZagPivots( + 0, // BarIndex ... + mRequiredPivots + 1, // Required Pivots ... + 1500 // Max Allowed Loopback Length ... + ); + } + + // + // Validate Reading Succeed ... + if (readedZigZagsCount <= 0) + { + return; + } + + // + // Try to Detect ZigZag Peaks and Vales ... + ProcessZigZagsPeaksAndVales(); + + // + // Try to Calculate ZigZag Supports and Resistances ... + ProcessZigZagsSupportsAnsResistances(); + + // + // Try to Calculate Peaks and Vales Linear Regression Based + // Slope and Intercept (s) and also Detect From and To Times then + // Predict Peaks and Vales Values for them then ... + // Prepare Support and Resistance Boxes based on Calculated Support + // and Resistances ... + if (!CalculateZigZagLinearRegressionParameters()) + { + return; + } + + // + // Draw Peaks and Vales Based Trend Lines ... + DrawAnalysis(); + + // + // Process ZigZag Values ... + Print(""); + + // +} +//+------------------------------------------------------------------+ + +// +int ReadZigZagValues(int barIndex = 0) +{ + // + int result = 0; + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + + // + // Validate ... + if (mZigZagHandler == INVALID_HANDLE) + { + return result; + } + + // + // Copy ZigZag Values to Buffers ... + result = CopyBuffer(mZigZagHandler, MAIN_LINE, 0, mLoopbackLength, mZigZagBuffer); + + // + // Set ZigZag Buffers as Series ... + ArraySetAsSeries(mZigZagBuffer, true); + + // + if (result <= 0) + { + return result; + } + + // + // Filling ZigZag Pivots ... + + // + // Clean Buffers ... + SpecifiedClean(mZigZagPivotTimes); + SpecifiedClean(mZigZagPivotPrices); + SpecifiedClean(mZigZagPivotIsPeaks); + SpecifiedClean(mZigZagPivotIndexes); + + // + // Looping Through ZigZag Buffers ... + XOHCL iBar; + bool has = false; + double iZigZag = 0; + bool isIZigZagPeak = false; + int count = ArraySize(mZigZagBuffer); + for (int i = 0; i < count; i++) + { + // + // Reading ZigZag Value ... + iZigZag = mZigZagBuffer[i]; + + // + // Validate ZigZag Values ... + if (!NotEmptyZero(iZigZag)) + { + continue; + } + + // + // Check ZigZag Value Is Peak or Vale ... + + // + // Initialize iBar ... + has = iBar.Init( + _Symbol, + _Period, + i // + ); + + // + // Validate Bar and also Exclude Most Recent Swing ... + if (!has || iBar.Index() == 0) + { + // + iBar.Clean(); + continue; + } + + // + isIZigZagPeak = iZigZag == iBar.high; + + // + // Filling Buffers ... + Add( + iBar.time, + mZigZagPivotTimes // + ); + Add( + iZigZag, + mZigZagPivotPrices // + ); + Add( + isIZigZagPeak, + mZigZagPivotIsPeaks // + ); + Add( + (double)iBar.Index(), + mZigZagPivotIndexes // + ); + + // + // Cleanup Resources ... + iBar.Clean(); + } + + // + return result; +} + +// +int ReadingZigZagPivots( + int barIndex = 0, + int requiredPivots = 15, + int maxAllowedLoopback = 1500 // +) +{ + // + int result = 0; + + // + // Cleanup Resources ... + SpecifiedClean(mZigZagPivotTimes); + SpecifiedClean(mZigZagPivotPrices); + SpecifiedClean(mZigZagPivotIsPeaks); + SpecifiedClean(mZigZagPivotIndexes); + + // + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); + requiredPivots = NormalizeInt(requiredPivots, 2); + maxAllowedLoopback = NormalizeInt(maxAllowedLoopback, 100); + + // + XOHCL iBar; + bool has = false; + double iZigZag = 0; + bool isPeak = false; + int idx = barIndex - 1; + double tmpZigZagBuffer[]; + int maxAllowed = barIndex + maxAllowedLoopback; + while (idx < maxAllowed && + ArraySize(mZigZagPivotPrices) < requiredPivots) + { + // + idx++; + + // + // Initializing Bar ... + has = iBar.Init( + _Symbol, + _Period, + idx // + ); + if (!has) + { + continue; + } + + // + // Reading ZigZag Value ... + if (CopyBuffer(mZigZagHandler, MAIN_LINE, idx, 1, tmpZigZagBuffer) < 1) + { + // + iBar.Clean(); + continue; + } + + // + // Read ZigZag Value and Validate it ... + iZigZag = tmpZigZagBuffer[0]; + has = NotEmptyZero(iZigZag); + if (!has) + { + // + iBar.Clean(); + SpecifiedClean(tmpZigZagBuffer); + + // + continue; + } + + // + isPeak = iZigZag == iBar.high; + + // + // Validate ZigZag Value for Ignore Zero ... + if (iBar.Index() == barIndex) + { + // + iBar.Clean(); + SpecifiedClean(tmpZigZagBuffer); + + // + continue; + } + + // + // Filling Pivots ... + + // + Add( + iZigZag, + mZigZagPivotPrices // + ); + + // + Add( + isPeak, + mZigZagPivotIsPeaks // + ); + + // + Add( + iBar.time, + mZigZagPivotTimes // + ); + + // + Add( + (double)iBar.Index(), + mZigZagPivotIndexes // + ); + + // + // Cleanup Resources ... + iBar.Clean(); + SpecifiedClean(tmpZigZagBuffer); + + // + // Check Can Break Loop ... + has = idx >= maxAllowed || + ArraySize(mZigZagPivotPrices) == requiredPivots; + if (has) + { + break; + } + } + + // + // Cleanup Resources ... + SpecifiedClean(tmpZigZagBuffer); + + // + result = ArraySize(mZigZagPivotPrices); + + // + return result; +} + +// +void ProcessZigZagsPeaksAndVales() +{ + // + // Here we Parse ZigZag Values to Detect Peak or Vale ... + + // + int count = 0; + bool has = false; + + // + // Extract mZigZag Peaks and Vales ... + SpecifiedClean(mZigZagPeaks); + SpecifiedClean(mZigZagVales); + SpecifiedClean(mZigZagPeakTimes); + SpecifiedClean(mZigZagValeTimes); + SpecifiedClean(mZigZagPeakIndexes); + SpecifiedClean(mZigZagValeIndexes); + count = ArraySize(mZigZagPivotPrices); + has = IsValidSize(count); + if (!has) + { + return; + } + + // + double iZigZag = 0; + double iZigZagIDX = -1; + bool isIZigZagPeak = false; + datetime iZigZagTime = NULL; + for (int i = 0; i < count; i++) + { + // + // Reading Required Values ... + iZigZag = mZigZagPivotPrices[i]; + iZigZagTime = mZigZagPivotTimes[i]; + iZigZagIDX = mZigZagPivotIndexes[i]; + isIZigZagPeak = mZigZagPivotIsPeaks[i]; + + // + if (isIZigZagPeak) + { + // + Add( + iZigZag, + mZigZagPeaks // + ); + + // + Add( + iZigZagTime, + mZigZagPeakTimes // + ); + + // + Add( + iZigZagIDX, + mZigZagPeakIndexes // + ); + } + else + { + // + Add( + iZigZag, + mZigZagVales // + ); + + // + Add( + iZigZagTime, + mZigZagValeTimes // + ); + + // + Add( + iZigZagIDX, + mZigZagValeIndexes // + ); + } + } +} + +// +void ProcessZigZagsSupportsAnsResistances() +{ + // + int count = 0; + bool has = false; + double iValue = EMPTY_VALUE; + double tmpValue = EMPTY_VALUE; + + // + // Support ... + // Supports Calculated based on Vales ... + + // + tmpValue = EMPTY_VALUE; + mMinorSupport = EMPTY_VALUE; + mMajorSupport = EMPTY_VALUE; + count = ArraySize(mZigZagVales); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + // Reading Indexed Value ... + iValue = mZigZagVales[i]; + + // + // Check Can Change Major Support ... + has = !NotEmpty(mMajorSupport) || + mMajorSupport > iValue; + if (has) + { + // + tmpValue = mMajorSupport; + mMajorSupport = iValue; + } + else + { + // + // Check Minor Support ... + has = !NotEmpty(tmpValue) || + tmpValue > iValue; + if (has) + { + tmpValue = iValue; + } + } + } + + // + has = NotEmpty(tmpValue); + if (has) + { + mMinorSupport = tmpValue; + } + } + + // + // Resistance ... + // Resistances Calculated based on Peaks ... + + // + tmpValue = EMPTY_VALUE; + mMinorResistance = EMPTY_VALUE; + mMajorResistance = EMPTY_VALUE; + count = ArraySize(mZigZagPeaks); + has = IsValidSize(count); + if (has) + { + // + for (int i = 0; i < count; i++) + { + // + // Reading Indexed Value ... + iValue = mZigZagPeaks[i]; + + // + // Check Can Change Major Resistance ... + has = !NotEmpty(mMajorResistance) || + mMajorResistance < iValue; + if (has) + { + // + tmpValue = mMajorResistance; + mMajorResistance = iValue; + } + else + { + // + // Check Minor Resistance ... + has = !NotEmpty(tmpValue) || + tmpValue < iValue; + if (has) + { + tmpValue = iValue; + } + } + } + + // + has = NotEmpty(tmpValue); + if (has) + { + mMinorResistance = tmpValue; + } + } +} + +// +bool CalculateZigZagLinearRegressionParameters() +{ + // + bool result = false; + mUpperTrendDir = X_DIRECTION_NONE; + mLowerTrendDir = X_DIRECTION_NONE; + + // + // Peaks ... + CalculateSlopeAndIntercept( + mPeakSlope, + mPeakIntercept, + mZigZagPeakIndexes, + mZigZagPeaks // + ); + + // + // Vales ... + CalculateSlopeAndIntercept( + mValeSlope, + mValeIntercept, + mZigZagValeIndexes, + mZigZagVales // + ); + + // + result = + (NotEmpty(mPeakSlope) && + NotEmpty(mPeakIntercept)) || + (NotEmpty(mValeSlope) && + NotEmpty(mValeIntercept)); + if (!result) + { + return result; + } + + // + // Detect Oldest and Youngest Time of Pivots ... + + // + int idx = -1; + bool has = false; + + // + // Oldest ... + has = FindOldestIndex( + idx, + mZigZagPivotTimes // + ); + if (has) + { + mFromTime = mZigZagPivotTimes[idx]; + } + + // + // Youngest ... + has = FindYoungesttIndex( + idx, + mZigZagPivotTimes // + ); + if (has) + { + mToTime = mZigZagPivotTimes[idx]; + } + + // + // Validate Extracted Times ... + result = + IsSpecifiedValid(mToTime) && + IsSpecifiedValid(mFromTime); + if (!result) + { + return result; + } + + // + // Detect Extracted Times Bar Indexes ... + + // + int mToIDX = iBarShift( + _Symbol, + _Period, + mToTime // + ); + int mFromIDX = iBarShift( + _Symbol, + _Period, + mFromTime // + ); + + // + // Validate Detected Bar Indexes ... + result = + IsValidIndex(mToIDX) && + IsValidIndex(mFromIDX); + if (!result) + { + return result; + } + + // + // Calculate Predictions ... + + // + // Peak ... + mPeakTo = PredictValue( + mPeakSlope, + mPeakIntercept, + mToIDX // + ); + mPeakFrom = PredictValue( + mPeakSlope, + mPeakIntercept, + mFromIDX // + ); + + // + // Vale ... + mValeTo = PredictValue( + mValeSlope, + mValeIntercept, + mToIDX // + ); + mValeFrom = PredictValue( + mValeSlope, + mValeIntercept, + mFromIDX // + ); + + // + mUpperTrendDir = + mPeakFrom < mPeakTo + ? X_DIRECTION_BULLISH + : mPeakFrom > mPeakTo + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + mLowerTrendDir = + mValeFrom < mValeTo + ? X_DIRECTION_BULLISH + : mValeFrom > mValeTo + ? X_DIRECTION_BEARISH + : X_DIRECTION_NONE; + + // + // Prepare Support and Resistance Boxes ... + + // + // Support ... + + // + mSupportBox.Clean(); + has = NotEmptyZero(mMinorSupport) && + NotEmptyZero(mMajorSupport); + if (has) + { + // + mSupportBox.to = mToTime; + mSupportBox.from = mFromTime; + mSupportBox.symbol = _Symbol; + mSupportBox.period = _Period; + mSupportBox.type = "Support"; + mSupportBox.upper = mMinorSupport; + mSupportBox.lower = mMajorSupport; + mSupportBox.dir = X_DIRECTION_BULLISH; + } + + // + // Resistance ... + + // + mResistanceBox.Clean(); + has = NotEmptyZero(mMinorResistance) && + NotEmptyZero(mMajorResistance); + if (has) + { + // + mResistanceBox.to = mToTime; + mResistanceBox.from = mFromTime; + mResistanceBox.symbol = _Symbol; + mResistanceBox.period = _Period; + mResistanceBox.type = "Resistance"; + mResistanceBox.upper = mMajorResistance; + mResistanceBox.lower = mMinorResistance; + mResistanceBox.dir = X_DIRECTION_BEARISH; + } + + // + result = + mSupportBox.IsValid() || + mResistanceBox.IsValid(); + + // + return result; +} + +// +void DrawAnalysis() +{ + // + bool isCreated = false; + + // + // Peak ... + + // + // Cleanup Upper Object ... + if (mUpperTrend != NULL) + { + // + mUpperTrend.Delete(); + mUpperTrend.Detach(); + delete mUpperTrend; + ZeroMemory(mUpperTrend); + } + + // + mUpperTrend = new CChartObjectTrend(); + isCreated = mUpperTrend.Create( + ChartID(), + "UpperTrend", + 0, + mFromTime, + mPeakFrom, + mToTime, + mPeakTo // + ); + if (isCreated) + { + // + // Apply Styles ... + + // + color upperColor = + IsSpecifiedBullish(mUpperTrendDir) + ? clrAqua + : IsSpecifiedBearish(mUpperTrendDir) + ? clrMagenta + : clrGray; // Neutural ... + + // + mUpperTrend.Width(2); + mUpperTrend.RayRight(true); + mUpperTrend.Color(upperColor); + } + + // + // Vale ... + + // + // Cleanup Lower Object ... + if (mLowerTrend != NULL) + { + // + mLowerTrend.Delete(); + mLowerTrend.Detach(); + delete mLowerTrend; + ZeroMemory(mLowerTrend); + } + + // + mLowerTrend = new CChartObjectTrend(); + isCreated = mLowerTrend.Create( + ChartID(), + "LowerTrend", + 0, + mFromTime, + mValeFrom, + mToTime, + mValeTo // + ); + if (isCreated) + { + // + // Apply Styles ... + + // + color lowerColor = + IsSpecifiedBullish(mLowerTrendDir) + ? clrAqua + : IsSpecifiedBearish(mLowerTrendDir) + ? clrMagenta + : clrGray; // Neutural ... + + // + mLowerTrend.Width(2); + mLowerTrend.RayRight(true); + mLowerTrend.Color(lowerColor); + } + + // + // Support ... + + // + // Cleanup Support Object ... + if (mSupportObj != NULL) + { + // + mSupportObj.Delete(); + mSupportObj.Detach(); + delete mSupportObj; + ZeroMemory(mSupportObj); + } + + // + isCreated = mSupportBox.IsValid(); + if (isCreated) + { + // + datetime to = TimeCurrent(); + mSupportObj = new XCBoxObject(); + isCreated = mSupportObj.Create( + ChartID(), + 0, + "Support", + mSupportBox.upper, + mSupportBox.lower, + mSupportBox.from, + to // + ); + if (isCreated) + { + // + // Apply Style ... + mSupportObj.BoxWidth(2); + mSupportObj.BoxColor(clrAqua); + } + } + + // + // Resistance ... + + // + // Cleanup Resistance Object ... + if (mResistanceObj != NULL) + { + // + mResistanceObj.Delete(); + mResistanceObj.Detach(); + delete mResistanceObj; + ZeroMemory(mResistanceObj); + } + + // + isCreated = mResistanceBox.IsValid(); + if (isCreated) + { + // + datetime to = TimeCurrent(); + mResistanceObj = new XCBoxObject(); + isCreated = mResistanceObj.Create( + ChartID(), + 0, + "Resistance", + mResistanceBox.upper, + mResistanceBox.lower, + mResistanceBox.from, + to // + ); + if (isCreated) + { + // + // Apply Style ... + mResistanceObj.BoxWidth(2); + mResistanceObj.BoxColor(clrMagenta); + } + } +} + +// +int FindOldestIndex( + int &index, + datetime ×[] // +) +{ + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Validate ... + if (!HasChild(times)) + { + return result; + } + + // + bool has = false; + datetime tmpTime = NULL; + for (int i = 0; i < ArraySize(times); i++) + { + // + has = + !IsSpecifiedValid(tmpTime) + ? true + : tmpTime > times[i]; + if (has) + { + // + index = i; + tmpTime = times[i]; + } + } + + // + // Validate result ... + result = + IsValidIndex(index) && + IsSpecifiedValid(tmpTime); + + // + return result; +} + +// +int FindYoungesttIndex( + int &index, + datetime ×[] // +) +{ + // + bool result = false; + + // + // Prepare ... + index = -1; + + // + // Validate ... + if (!HasChild(times)) + { + return result; + } + + // + bool has = false; + datetime tmpTime = NULL; + for (int i = 0; i < ArraySize(times); i++) + { + // + has = + !IsSpecifiedValid(tmpTime) + ? true + : tmpTime < times[i]; + if (has) + { + // + index = i; + tmpTime = times[i]; + } + } + + // + // Validate result ... + result = + IsValidIndex(index) && + IsSpecifiedValid(tmpTime); + + // + return result; +} + +// \ No newline at end of file diff --git a/Experts/x-saherelm.xfima.backtester.ea.mq5 b/Experts/x-saherelm.xfima.backtester.ea.mq5 index 2ef22f26..608afdbe 100644 --- a/Experts/x-saherelm.xfima.backtester.ea.mq5 +++ b/Experts/x-saherelm.xfima.backtester.ea.mq5 @@ -1367,10 +1367,10 @@ void DetectPatterns() // XPivotAnalysis analysis; has = fima2Signaller.poiDetector.AnalyseZigZagPivots( - analysis, // Result ... - cBar.Index(), // Bar Index ... - 50, // Required Number of Pivots ... - 1500 // Max Allowed Loopback ... + analysis, // Result ... + 0, // Bar Index ... + 50, // Required Number of Pivots ... + 1500 // Max Allowed Loopback ... ); if (has) { diff --git a/Helpers/x-saherelm.xfima.helper.mq5 b/Helpers/x-saherelm.xfima.helper.mq5 index 50255726..f12f1980 100644 --- a/Helpers/x-saherelm.xfima.helper.mq5 +++ b/Helpers/x-saherelm.xfima.helper.mq5 @@ -1808,6 +1808,7 @@ class XCXFIMAHelper : public XCBaseHelper { // iBar.Clean(); + SpecifiedClean(tmpZigZagBuffer); continue; } @@ -1824,6 +1825,7 @@ class XCXFIMAHelper : public XCBaseHelper { // iBar.Clean(); + SpecifiedClean(tmpZigZagBuffer); continue; } @@ -1840,6 +1842,7 @@ class XCXFIMAHelper : public XCBaseHelper { // iBar.Clean(); + SpecifiedClean(tmpZigZagBuffer); continue; } diff --git a/Indicators/ZigZag.mq5 b/Indicators/ZigZag.mq5 new file mode 100644 index 00000000..3863bd7a Binary files /dev/null and b/Indicators/ZigZag.mq5 differ diff --git a/Libraries/x-saherelm.x-poi.extensions.lib.mq5 b/Libraries/x-saherelm.x-poi.extensions.lib.mq5 index 90944d7e..41e2b5c2 100644 --- a/Libraries/x-saherelm.x-poi.extensions.lib.mq5 +++ b/Libraries/x-saherelm.x-poi.extensions.lib.mq5 @@ -1109,12 +1109,22 @@ int ExtractPivotsData( } // + XOHCL iBar; + bool has = false; double iX = EMPTY_VALUE; double iY = EMPTY_VALUE; for (int i = 0; i < count; i++) { // - iX = i + 1; + // Get Pivot Bar ... + has = source[i].GetBar(iBar); + if (!has) + { + continue; + } + + // + iX = iBar.Index(); iY = source[i].value; // @@ -1128,8 +1138,14 @@ int ExtractPivotsData( iY, yData // ); + + // + iBar.Clean(); } + // + iBar.Clean(); + // result = MathMin(ArraySize(xData), ArraySize(yData));