diff --git a/Documents/BKP/TestRegresser.mq5 b/Documents/BKP/TestRegresser.mq5 new file mode 100644 index 00000000..5b14ef61 --- /dev/null +++ b/Documents/BKP/TestRegresser.mq5 @@ -0,0 +1,344 @@ +//+------------------------------------------------------------------+ +//| 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 "../Libraries/x-saherelm.common.lib.mq5" +#include + +// +// Inputs ... +input int mLoopbackLength = 200; +input ENUM_X_PRICE mPriceType = X_PRICE_HIGH; + +// +// Calculation ... +input group "Calculation"; +input int zigzagDepth = 12; // Depth +input int zigzagDeviation = 5; // Deviation +input int zigzagBackStep = 3; // Back Step + +// +// Variables ... + +// +int mZigZagHandler = INVALID_HANDLE; + +// +// double mSumX = 0; +// double mSumY = 0; +// double mSumXY = 0; +// double mSumX2 = 0; + +//+------------------------------------------------------------------+ +//| Expert initialization function | +//+------------------------------------------------------------------+ +int OnInit() +{ + // + double xData[]; + double yData[]; + int xDataCount = CollectData( + xData, + yData // + ); + + // + // Initialize ZigZag Handler ... + mZigZagHandler = iCustom( + _Symbol, + _Period, + "ZigZagColor", + zigzagDepth, + zigzagDeviation, + zigzagBackStep // + ); + if (mZigZagHandler == INVALID_HANDLE) + { + Print("Error creating ZigZag handle"); + return (INIT_FAILED); + } + + // // + // for (int i = 0; i < mLoopbackLength; i++) + // { + // // + // double iY = yData[i]; + // double iX = xData[i]; + + // // + // mSumX += iX; + // mSumY += iY; + // mSumXY += (iX * iY); + // mSumX2 += (iX * iX); + // } + + // // + // for (int i = 0; i < mLoopbackLength; i++) + // { + // // + // double iY = GetAppliedPrice( + // _Symbol, + // _Period, + // i, + // mPriceType // + // ); + // double iX = i + 1; + + // // + // mSumX += iX; + // mSumY += iY; + // mSumXY += (iX * iY); + // mSumX2 += (iX * iX); + // } + + // + // int n = mLoopbackLength; + // double slope = (n * mSumXY - mSumX * mSumY) / (n * mSumX2 - mSumX * mSumX); + // double intercept = (mSumY - slope * mSumX) / n; + + // // + // double xData[]; + // double yData[]; + // int xDataCount = CollectData( + // xData, + // yData // + // ); + double _cSlope; + double _cIntercept; + int calculatedCount = CalculateSlopeandIntercept( + _cSlope, + _cIntercept, + xData, + yData // + ); + + // + datetime time1 = iTime(_Symbol, _Period, mLoopbackLength); + datetime time2 = iTime(_Symbol, _Period, 0); + + // // + // double price1 = (intercept + slope * mLoopbackLength); + // double price2 = (intercept + slope); + + // + double cPrice1 = PredictValue( + _cSlope, + _cIntercept, + time1 // + ); + double cPrice2 = PredictValue( + _cSlope, + _cIntercept, + time2 // + ); + + // + string name = "TrendLine"; + string cName = "cTrendLine"; + + // + // CChartObjectTrend *iTrend = new CChartObjectTrend(); + // bool isCreated = iTrend.Create( + // ChartID(), + // name, + // 0, + // time1, + // price1, + // time2, + // price2 // + // ); + // if (isCreated) + // { + // // + // // Styling Trend Line ... + // } + + // + CChartObjectTrend *iCTrend = new CChartObjectTrend(); + bool isCreated = iCTrend.Create( + ChartID(), + cName, + 0, + time1, + cPrice1, + time2, + cPrice2 // + ); + if (isCreated) + { + // + // Styling Trend Line ... + } + + // + return (INIT_SUCCEEDED); +} +//+------------------------------------------------------------------+ +//| Expert deinitialization function | +//+------------------------------------------------------------------+ +void OnDeinit(const int reason) +{ + //--- +} +//+------------------------------------------------------------------+ +//| Expert tick function | +//+------------------------------------------------------------------+ +void OnTick() +{ + //--- +} +//+------------------------------------------------------------------+ + +// +int CollectData( + double &xData[], + double &yData[], + int barIndex = 0 // +) +{ + // + int result = false; + + // + SpecifiedClean(xData); + SpecifiedClean(yData); + + // + barIndex = NormalizeInt(barIndex, 0); + + // + int start = barIndex; + int end = start + mLoopbackLength; + for (int i = start; i < end; i++) + { + // + double iY = GetAppliedPrice( + _Symbol, + _Period, + i // + ); + + // + datetime iTime = iTime( + _Symbol, + _Period, + i // + ); + double iX = i + 1; // (double)TimeToSeconds(iTime); + + // + Add( + iX, + xData // + ); + + // + Add( + iY, + yData // + ); + } + + // + result = ArraySize(xData); + + // + return result; +} + +// +int CalculateSlopeandIntercept( + double &_slope, + double &_intercept, + double &xData[], + double &yData[] // +) +{ + // + int result = 0; + + // + bool has = false; + + // + _slope = 0; + _intercept = 0; + + // + if (!HasChild(xData) || + !HasChild(yData)) + { + return result; + } + + // + double sumX = 0; + double sumY = 0; + double sumXY = 0; + double sumX2 = 0; + + // + double x = 0; + double y = 0; + int end = MathMin(ArraySize(xData), ArraySize(yData)); + for (int i = 0; i < end; i++) + { + // + double x = xData[i]; + double y = yData[i]; + + // + sumX += x; + sumY += y; + sumXY += x * y; + sumX2 += x * x; + } + + // + int n = end; + _slope = (n * sumXY - sumX * sumY) / (n * sumX2 - sumX * sumX); + _intercept = (sumY - _slope * sumX) / n; + + // + result = n; + + // + return result; +} + +// +double PredictValue( + double &_slope, + double &_intercept, + datetime forTime // +) +{ + // + double result = 0; + + // + if (!IsSpecifiedValid(forTime)) + { + return result; + } + + // + double forX = iBarShift( + _Symbol, + _Period, + forTime // + ); // (double)TimeToSeconds(forTime); + result = (_intercept + _slope * forX); + + // + return result; +} + +// \ No newline at end of file diff --git a/Experts/TestRegresser.mq5 b/Experts/TestRegresser.mq5 index af399abe..e0ae56fb 100644 --- a/Experts/TestRegresser.mq5 +++ b/Experts/TestRegresser.mq5 @@ -14,15 +14,44 @@ // // Inputs ... + +// +// Calculation ... +input int zigzagDepth = 12; // Depth +input int zigzagDeviation = 5; // Deviation +input int zigzagBackStep = 3; // Back Step + +// input int mLoopbackLength = 200; -input ENUM_X_PRICE mPriceType = X_PRICE_HIGH; +input int mExtendFutureLength = 100; // Bars to extend trendlines into the future // // Variables ... -double mSumX = 0; -double mSumY = 0; -double mSumXY = 0; -double mSumX2 = 0; + +// +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[]; //+------------------------------------------------------------------+ //| Expert initialization function | @@ -30,28 +59,11 @@ double mSumX2 = 0; int OnInit() { // - for (int i = 0; i < mLoopbackLength; i++) - { - // - double iY = GetAppliedPrice( - _Symbol, - _Period, - i, - mPriceType // - ); - double iX = i + 1; - - // - mSumX += iX; - mSumY += iY; - mSumXY += (iX * iY); - mSumX2 += (iX * iX); - } - - // - int n = mLoopbackLength; - double slope = (n * mSumXY - mSumX * mSumY) / (n * mSumX2 - mSumX * mSumX); - double intercept = (mSumY - slope * mSumX) / n; + // Initialize Bar Tracker ... + mBarTracker.Init( + _Symbol, + _Period // + ); // double xData[]; @@ -60,71 +72,21 @@ int OnInit() xData, yData // ); - double _cSlope; - double _cIntercept; - int calculatedCount = CalculateSlopeandIntercept( - _cSlope, - _cIntercept, - xData, - yData // + + // + // Initialize ZigZag Handler ... + mZigZagHandler = iCustom( + _Symbol, + _Period, + "ZigZag", + zigzagDepth, + zigzagDeviation, + zigzagBackStep // ); - - // - datetime time1 = iTime(_Symbol, _Period, mLoopbackLength); - datetime time2 = iTime(_Symbol, _Period, 0); - - // - double price1 = (intercept + slope * mLoopbackLength); - double price2 = (intercept + slope); - - // - double cPrice1 = PredictValue( - _cSlope, - _cIntercept, - time1 // - ); - double cPrice2 = PredictValue( - _cSlope, - _cIntercept, - time2 // - ); - - // - string name = "TrendLine"; - string cName = "cTrendLine"; - - // - CChartObjectTrend *iTrend = new CChartObjectTrend(); - bool isCreated = iTrend.Create( - ChartID(), - name, - 0, - time1, - price1, - time2, - price2 // - ); - if (isCreated) + if (mZigZagHandler == INVALID_HANDLE) { - // - // Styling Trend Line ... - } - - // - CChartObjectTrend *iCTrend = new CChartObjectTrend(); - isCreated = iCTrend.Create( - ChartID(), - cName, - 0, - time1, - cPrice1, - time2, - cPrice2 // - ); - if (isCreated) - { - // - // Styling Trend Line ... + Print("Error creating ZigZag handle"); + return (INIT_FAILED); } // @@ -135,14 +97,35 @@ int OnInit() //+------------------------------------------------------------------+ void OnDeinit(const int reason) { - //--- + // + IndicatorRelease(mZigZagHandler); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { - //--- + // + if (!mBarTracker.IsNewBar()) + { + return; + } + + // + int readedZigZagsCount = ReadZigZagValues(); + if (readedZigZagsCount <= 0) + { + return; + } + ProcessZigZagsPeaksAndVales(); + CalculateZigZagLinearRegressionParameters(); + DrawZigZagPredictedTrendLines(); + + // + // Process ZigZag Values ... + Print(""); + + // } //+------------------------------------------------------------------+ @@ -204,91 +187,351 @@ int CollectData( } // -int CalculateSlopeandIntercept( - double &_slope, - double &_intercept, - double &xData[], - double &yData[] // -) +int ReadZigZagValues(int barIndex = 0) { // int result = 0; // - bool has = false; + // Normalize ... + barIndex = NormalizeInt(barIndex, 0); // - _slope = 0; - _intercept = 0; - - // - if (!HasChild(xData) || - !HasChild(yData)) + // Validate ... + if (mZigZagHandler == INVALID_HANDLE) { return result; } // - double sumX = 0; - double sumY = 0; - double sumXY = 0; - double sumX2 = 0; + // Copy ZigZag Values to Buffers ... + result = CopyBuffer(mZigZagHandler, MAIN_LINE, 0, mLoopbackLength, mZigZagBuffer); // - double x = 0; - double y = 0; - int end = MathMin(ArraySize(xData), ArraySize(yData)); - for (int i = 0; i < end; i++) - { - // - double x = xData[i]; - double y = yData[i]; - - // - sumX += x; - sumY += y; - sumXY += x * y; - sumX2 += x * x; - } - - // - int n = end; - _slope = (n * sumXY - sumX * sumY) / (n * sumX2 - sumX * sumX); - _intercept = (sumY - _slope * sumX) / n; - - // - result = n; + // Set ZigZag Buffers as Series ... + ArraySetAsSeries(mZigZagBuffer, true); // return result; } // -double PredictValue( - double &_slope, - double &_intercept, - datetime forTime // -) +void ProcessZigZagsPeaksAndVales() { // - double result = 0; + // Here we Parse ZigZag Values to Detect Peak or Vale ... // - if (!IsSpecifiedValid(forTime)) + // 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++) { - return result; + // + // 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(); } // - double forX = iBarShift( - _Symbol, - _Period, - forTime // - ); // (double)TimeToSeconds(forTime); - result = (_intercept + _slope * forX); + // 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; + } // - return result; + double iZigZagIDX = -1; + 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 // + ); + } + } + + // + // TODO: + // - [] Add Support for Reading Specified Number of Swings instead of Specified Loopback ... +} + +// +void CalculateZigZagLinearRegressionParameters() +{ + // + // Peaks ... + CalculateSlopeAndIntercept( + mPeakSlope, + mPeakIntercept, + mZigZagPeakIndexes, + mZigZagPeaks // + ); + + // + // Vales ... + CalculateSlopeAndIntercept( + mValeSlope, + mValeIntercept, + mZigZagValeIndexes, + mZigZagVales // + ); +} + +// +void DrawZigZagPredictedTrendLines() +{ + // + // This Variables are Same in Peaks and Vales ... + + // + // TODO: + // - [] Add Support for Extending Lines betwen Oldest and Youngest Pivots ... + // - [] Add Support for Styling Lines ... + + // + // FromTime ... + datetime fromTime = iTime( + _Symbol, + _Period, + mLoopbackLength - 1 // + ); + int fromIDX = iBarShift( + _Symbol, + _Period, + fromTime // + ); + + // + // To Time ... + // this time Calculated using From Time and mExtendFutureLength ... + datetime toTime = fromTime + (mExtendFutureLength * PeriodSeconds(_Period)); + int toIDX = iBarShift( + _Symbol, + _Period, + toTime // + ); + + // + // Predict Values ... + + // + // Peak ... + double mPeakTo = PredictValue( + mPeakSlope, + mPeakIntercept, + toIDX // + ); + double mPeakFrom = PredictValue( + mPeakSlope, + mPeakIntercept, + fromIDX // + ); + + // + // Vale ... + double mValeTo = PredictValue( + mValeSlope, + mValeIntercept, + toIDX // + ); + double mValeFrom = PredictValue( + mValeSlope, + mValeIntercept, + fromIDX // + ); + + // + // Draw Predicted Lines ... + + // + 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, + fromTime, + mPeakFrom, + toTime, + mPeakTo // + ); + if (isCreated) + { + // + // Apply Styles ... + + // + mUpperTrend.Width(2); + mUpperTrend.RayRight(true); + mUpperTrend.Color(clrAqua); + } + + // + // Vale ... + + // + // Cleanup Lower Object ... + if (mLowerTrend != NULL) + { + // + mLowerTrend.Delete(); + mLowerTrend.Detach(); + delete mLowerTrend; + ZeroMemory(mLowerTrend); + } + + // + mLowerTrend = new CChartObjectTrend(); + isCreated = mLowerTrend.Create( + ChartID(), + "LowerTrend", + 0, + fromTime, + mValeFrom, + toTime, + mValeTo // + ); + if (isCreated) + { + // + // Apply Styles ... + + // + mLowerTrend.Width(2); + mLowerTrend.RayRight(true); + mLowerTrend.Color(clrMagenta); + } } // \ No newline at end of file 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/Indicators/ZigZagColor.mq5 b/Indicators/ZigZagColor.mq5 new file mode 100644 index 00000000..ed3448af --- /dev/null +++ b/Indicators/ZigZagColor.mq5 @@ -0,0 +1,288 @@ +//+------------------------------------------------------------------+ +//| ZigzagColor.mq5 | +//| Copyright 2000-2025, MetaQuotes Ltd. | +//| https://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "Copyright 2000-2025, MetaQuotes Ltd." +#property link "https://www.mql5.com" +//--- indicator settings +#property indicator_chart_window +#property indicator_buffers 5 +#property indicator_plots 1 +#property indicator_type1 DRAW_COLOR_ZIGZAG +#property indicator_width1 3 +#property indicator_color1 clrAqua, clrMagenta +//--- input parameters +input int InpDepth =12; // Depth +input int InpDeviation=5; // Deviation +input int InpBackstep =3; // Back Step +//--- indicator buffers +double ZigzagPeakBuffer[]; +double ZigzagBottomBuffer[]; +double HighMapBuffer[]; +double LowMapBuffer[]; +double ColorBuffer[]; + +int ExtRecalc=3; // recounting's depth + +enum EnSearchMode + { + Extremum=0, // searching for the first extremum + Peak=1, // searching for the next ZigZag peak + Bottom=-1 // searching for the next ZigZag bottom + }; +//+------------------------------------------------------------------+ +//| Custom indicator initialization function | +//+------------------------------------------------------------------+ +void OnInit() + { +//--- indicator buffers mapping + SetIndexBuffer(0,ZigzagPeakBuffer,INDICATOR_DATA); + SetIndexBuffer(1,ZigzagBottomBuffer,INDICATOR_DATA); + SetIndexBuffer(2,ColorBuffer,INDICATOR_COLOR_INDEX); + SetIndexBuffer(3,HighMapBuffer,INDICATOR_CALCULATIONS); + SetIndexBuffer(4,LowMapBuffer,INDICATOR_CALCULATIONS); +//--- set accuracy + IndicatorSetInteger(INDICATOR_DIGITS,_Digits); +//--- name for DataWindow and indicator subwindow label + string short_name=StringFormat("ZigZagColor(%d,%d,%d)",InpDepth,InpDeviation,InpBackstep); + IndicatorSetString(INDICATOR_SHORTNAME,short_name); + PlotIndexSetString(0,PLOT_LABEL,short_name); +//--- set an empty value + PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0); + } +//+------------------------------------------------------------------+ +//| ZigZag calculation | +//+------------------------------------------------------------------+ +int OnCalculate(const int rates_total, + const int prev_calculated, + const datetime &time[], + const double &open[], + const double &high[], + const double &low[], + const double &close[], + const long &tick_volume[], + const long &volume[], + const int &spread[]) + { + if(rates_total<100) + return(0); +//--- + int i,start=0; + int extreme_counter=0,extreme_search=Extremum; + int shift,back=0,last_high_pos=0,last_low_pos=0; + double val=0,res=0; + double cur_low=0,cur_high=0,last_high=0,last_low=0; +//--- initializing + if(prev_calculated==0) + { + ArrayInitialize(ZigzagPeakBuffer,0.0); + ArrayInitialize(ZigzagBottomBuffer,0.0); + ArrayInitialize(HighMapBuffer,0.0); + ArrayInitialize(LowMapBuffer,0.0); + //--- start calculation from bar number InpDepth + start=InpDepth-1; + } +//--- ZigZag was already calculated before + if(prev_calculated>0) + { + i=rates_total-1; + //--- searching for the third extremum from the last uncompleted bar + while(extreme_counterrates_total -100) + { + res=(ZigzagPeakBuffer[i]+ZigzagBottomBuffer[i]); + //--- + if(res!=0) + extreme_counter++; + i--; + } + i++; + start=i; + //--- what type of exremum we search for + if(LowMapBuffer[i]!=0) + { + cur_low=LowMapBuffer[i]; + extreme_search=Peak; + } + else + { + cur_high=HighMapBuffer[i]; + extreme_search=Bottom; + } + //--- clear indicator values + for(i=start+1; i(InpDeviation*_Point)) + val=0.0; + else + { + for(back=InpBackstep; back>=1; back--) + { + res=LowMapBuffer[shift-back]; + //--- + if((res!=0) && (res>val)) + LowMapBuffer[shift-back]=0.0; + } + } + } + if(low[shift]==val) + LowMapBuffer[shift]=val; + else + LowMapBuffer[shift]=0.0; + //--- high + val=Highest(high,InpDepth,shift); + if(val==last_high) + val=0.0; + else + { + last_high=val; + if((val-high[shift])>(InpDeviation*_Point)) + val=0.0; + else + { + for(back=InpBackstep; back>=1; back--) + { + res=HighMapBuffer[shift-back]; + //--- + if((res!=0) && (reslast_high && + LowMapBuffer[shift]==0.0) + { + ZigzagPeakBuffer[last_high_pos]=0.0; + last_high_pos=shift; + last_high=HighMapBuffer[shift]; + ZigzagPeakBuffer[shift]=last_high; + ColorBuffer[shift]=0; + } + if(LowMapBuffer[shift]!=0.0 && HighMapBuffer[shift]==0.0) + { + last_low=LowMapBuffer[shift]; + last_low_pos=shift; + ZigzagBottomBuffer[shift]=last_low; + ColorBuffer[shift]=1; + extreme_search=Peak; + } + break; + default: + return(rates_total); + } + } + +//--- return value of prev_calculated for next call + return(rates_total); + } +//+------------------------------------------------------------------+ +//| Get highest value for range | +//+------------------------------------------------------------------+ +double Highest(const double&array[],int count,int start) + { + double res=array[start]; +//--- + for(int i=start-1; i>start-count && i>=0; i--) + if(resstart-count && i>=0; i--) + if(res>array[i]) + res=array[i]; +//--- + return(res); + } +//+------------------------------------------------------------------+ diff --git a/Libraries/x-saherelm.common.extensions.lib.mq5 b/Libraries/x-saherelm.common.extensions.lib.mq5 index afca0c1c..a5cf9639 100644 --- a/Libraries/x-saherelm.common.extensions.lib.mq5 +++ b/Libraries/x-saherelm.common.extensions.lib.mq5 @@ -7065,67 +7065,54 @@ bool SetChartVolumesColor( // /** - * Linear Regression Based Calculate Data ... - * int this Senario X Axis is Buffer Index ... + * Calculate Slope and Intercept for Linear Regression Predictions ... * - * @param _slope: double, refrence for Calculated Slope ... - * @param _intercept: double, reference for Calculated Intercept ... - * @param _source: double, Y Axis Valus Collection ... - * @param _start: int, start Index ... - * @param _count: int, number of Calculations ... + * @param _slope: double, refrence to Hold Calculated Slope ... + * @param _intercept: double, reference to Hold Calculated Intercept ... + * @param xData: double, reference Collection to Provides X-Axis Data for Calculations ... + * @param yData: double, reference Collection to Provides Y-Axis Data for Calculations ... * - * @return ( bool ) + * @return ( int ) */ -bool CalculateLinearRegression( +int CalculateSlopeAndIntercept( double &_slope, double &_intercept, - double &_source[], - int _start = 0, - int _count = 0 // + double &xData[], + double &yData[] // ) { // - bool result = false; + int result = 0; // - // Prepare ... - _slope = EMPTY_VALUE; - _intercept = EMPTY_VALUE; + bool has = false; // - // Validate ... - int count = ArraySize(_source); - result = IsValidSize(count); - if (!result) + _slope = 0; + _intercept = 0; + + // + if (!HasChild(xData) || + !HasChild(yData)) { return result; } // - // Normalize ... - _start = NormalizeInt(_start, 0, count - 1); - if (_count == 0 || _count + _start >= count) - { - // - // Get Whole Array ... - _count = count - 1 - _start; - } - int _end = _start + _count; - - // - // Define Requirements ... double sumX = 0; double sumY = 0; double sumXY = 0; double sumX2 = 0; // - // Looping Through Source Buffer to Cellect Data ... - for (int i = _start; i < _end; i++) + double x = 0; + double y = 0; + int end = MathMin(ArraySize(xData), ArraySize(yData)); + for (int i = 0; i < end; i++) { // - double x = i + 1; - double y = _source[i]; + double x = xData[i]; + double y = yData[i]; // sumX += x; @@ -7135,54 +7122,46 @@ bool CalculateLinearRegression( } // - // Calculate Slope and Intercept ... - int n = _count; - _slope = ((n * sumXY) - (sumX * sumY)) / ((n * sumX2) - (sumX * sumX)); - _intercept = ((sumY - _slope) * sumX) / n; + int n = end; + _slope = (n * sumXY - sumX * sumY) / (n * sumX2 - sumX * sumX); + _intercept = (sumY - _slope * sumX) / n; // - result = sumX > 0 && - sumY > 0 && - sumXY > 0 && - sumX2 > 0 && - NotEmpty(_slope) && - NotEmpty(_intercept); - if (!result) - { - // - _slope = EMPTY_VALUE; - _intercept = EMPTY_VALUE; - } + result = n; // return result; } -double CalculateValueBySlopeIntercept( +/** + * Predict Value for Specified X ... + * + * @param _sllope: double, Provided Slope ... + * @param _intercept: double, Provided Intercept ... + * @param _forX: double, Specified XValue ... + * + * @return ( double ) + */ +double PredictValue( double _slope, double _intercept, - int _index // + double _forX // ) { // - double result = EMPTY_VALUE; - - // - // Normalize Index ... - _index = NormalizeInt(_index, 1); + double result = 0; // // Validate ... - if ( + if (!NotEmpty(_forX) || !NotEmpty(_slope) || - !NotEmpty(_intercept) || - !IsValidIndex(_index)) + !NotEmpty(_intercept)) { return result; } // - result = (_intercept + _slope * _index); + result = (_intercept + (_slope * _forX)); // return result;