Help please, why 2 bars shift when send bar[index] to indicator class !!!

 

Dear Fellow

I am having challenge to figure out why there is 2 bar shift when I send bar[index] to Indicator class.

Even after two days for debugging I have failed to find the reason for it. The code and screen shot is attached for ready reference herewith.

You will also notice that Hammer/Shooting Star values are plotted 2 bars away from actual bar position. (marked on the screen shot)

I have also noticed one thing, if I LogPrint for current bar i.e. index[0] it returns index of MaxBars on the Chart!!!

Indicator Code

#include  "CPTest.mqh"
//#include  "..\\..\\..\\Experts\\AlgoBulls\\Includes\\CPatterns\\CPTest.mqh"
CCPTest                                                                                                                                 *cCPTest;
#property indicator_chart_window
#property indicator_buffers                                             2
#property indicator_plots                                               2

#define                         _OffSet                                                                         (int)(500 * Point())

// Entry Points LONG
#define                         _Hammer                                                                         0
#define                         _SStar                                                                          1
        datetime                mPrevTime;
        double  Hammer[];                                                                                                                                                                                                                               double  SStar[];

        string  mIndexTime;
        bool            DoPrint;

        int             SkipBars;                                                                                                                                                                                                                       // how many of the oldest bars of the indicator to skip
int OnInit() {

                SkipBars  = 21;                                                                                                                                                                                                                         // Averaging period used in iBand and iNVOL
                mPrevTime = WRONG_VALUE;
                IndicatorSetString(INDICATOR_SHORTNAME,"iVSA CPatterns");
                IndicatorSetInteger(INDICATOR_DIGITS,_Digits);
                SetIndexBuffer(_Hammer,Hammer,INDICATOR_DATA);                                                                                                  ArraySetAsSeries(Hammer,true);
                SetIndexBuffer(_SStar,SStar,INDICATOR_DATA);                                                                                                            ArraySetAsSeries(SStar,true);

    PlotIndexSetString(_Hammer,PLOT_LABEL,"Hammer");
    PlotIndexSetInteger(_Hammer,PLOT_DRAW_TYPE,DRAW_ARROW);
    PlotIndexSetInteger(_Hammer,PLOT_ARROW,225);
    PlotIndexSetInteger(_Hammer,PLOT_LINE_COLOR,clrGreen);
                PlotIndexSetInteger(_Hammer,PLOT_ARROW_SHIFT,+_OffSet);
    PlotIndexSetInteger(_Hammer,PLOT_LINE_WIDTH,2);
    PlotIndexSetDouble(_Hammer,PLOT_EMPTY_VALUE,EMPTY_VALUE);
                PlotIndexSetInteger(_Hammer,PLOT_DRAW_BEGIN,SkipBars);
    PlotIndexSetInteger(_Hammer,PLOT_SHOW_DATA,true);                                                   // 'true' Show in DataWindow

    PlotIndexSetString(_SStar,PLOT_LABEL,"Shootin Star");
    PlotIndexSetInteger(_SStar,PLOT_DRAW_TYPE,DRAW_ARROW);
    PlotIndexSetInteger(_SStar,PLOT_ARROW,226);
    PlotIndexSetInteger(_SStar,PLOT_LINE_COLOR,clrRed);
                PlotIndexSetInteger(_SStar,PLOT_ARROW_SHIFT,-_OffSet);
    PlotIndexSetInteger(_SStar,PLOT_LINE_WIDTH,2);
    PlotIndexSetDouble(_SStar,PLOT_EMPTY_VALUE,EMPTY_VALUE);
                PlotIndexSetInteger(_SStar,PLOT_DRAW_BEGIN,SkipBars);
    PlotIndexSetInteger(_SStar,PLOT_SHOW_DATA,true);                                                    // 'true' Show in DataWindow

                cCPTest = new CCPTest(_Symbol,_Period);
                ResetLastError();
                if(CheckPointer(cCPTest) == POINTER_INVALID) {
        string vMethod = "[" + _Symbol + "," + EnumToString(_Period) + "] " + __FUNCTION__;
            PrintFormat("%s LogError[#%i] Creating pointer for cCPTest",vMethod,GetLastError());
                        return(INIT_FAILED);
                }
        //+---------------------------------------------------------------------------------------------------------------------------+
                return(INIT_SUCCEEDED);

} // End of function OnInit()

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[]) {

        // INDICATOR START TIME
        //ulong startTime = GetMicrosecondCount();

                // Check if there are enough bars for calculation
                if(rates_total < SkipBars)                                                                                                                                                                                                                                                                                                                                                              return(0);

                // Set indexing of elements in arrays as in timeseries  
                ArraySetAsSeries(open,true);
                ArraySetAsSeries(high,true);
                ArraySetAsSeries(low,true);
                ArraySetAsSeries(close,true);

                /*
                int limit = rates_total - prev_calculated - SkipBars;
                for(int bar = limit; bar >= 0; bar--) {
                */

                // Declare local variables 
                int limit,bar;

                // Calculate the 'first' starting number for the bars recalculation cycle
                if(prev_calculated > rates_total || prev_calculated <= 0)               // Check for the first indicator start
                        limit = rates_total - SkipBars;                                                                 // Starting index for calculating all bars
                else
                        limit = rates_total - prev_calculated;                                  // Starting index for calculating new bars
                // Main indicator calculation loop
                for(bar = limit; bar >= 0 && IsNewBar(); bar--) {


                        // Update calculation data at index[bar] from CScanVSACPatterns
                        cCPTest.UpdateData(open,high,low,close,bar);

                        Hammer[bar] = cCPTest.IsHammer()                                                                ? low[bar]  : EMPTY_VALUE;
                        SStar[bar]      = cCPTest.IsSStar()                                                                     ? high[bar] : EMPTY_VALUE;
                }

          // INDICATOR END TIME AND INDICATOR TIME CALCULATION IN MILI SECONDS
                //ulong finishTime = GetMicrosecondCount();  
                //PrintFormat("%s in %s took %.1f ms",__FUNCTION__,__FILE__,(finishTime-startTime)/1000);

                // Return value for next bar
                return(rates_total);

} // End of function OnCalculate()

bool IsNewBar() {

  datetime vCurrTime = (datetime)SeriesInfoInteger(_Symbol,PERIOD_CURRENT,SERIES_LASTBAR_DATE);

  if(mPrevTime != vCurrTime) {
                 mPrevTime      = vCurrTime;
        return(true);
        }

  return(false);

} // End of method IsNewBar()
//+-----------------------------------------------------------------------------------------------------------------------------+

Indicator Class Code

#include "BaseIndicator.mqh"
//#include "..\\CBase\\BaseIndicator.mqh"
#define         fillSize                                6                                                                                                                       // Six Bars including Idx[0], in BreakOut we lookback 5 bars!!!
#define         periodBands                     21                                                                                                              // iBands averaging period

#define         objectDraw                      true
#define         objectDelete            true
#define         offSet                                  (450 * Point())

class CCPTest final : public CBaseIndicator {

public:
    CCPTest() : CBaseIndicator(_Symbol,_Period) { }

                // NOW USE 'new' OPERATOR FOR PARAMETRIC CONSTRUCTOR TO SET CORRECT PARAMETERS
          CCPTest(string pSymbol,ENUM_TIMEFRAMES pTimeFrame);
         ~CCPTest(void);

        public:
                void                                                    UpdateData(const double &pOpen[],const double &pHigh[],const double &pLow[],const double &pClose[],int pIdxCB);
                void                                                    ReleaseDataArrays(void);

                bool                                                    IsSStar(int pIndex);                                                                                                                                    bool    IsHammer(int pIndex);
private:
                int                                                             mIdxCB;                                                                                                                                                                                         // Passed in pIdxCBTF, saved as global variable
                struct SiOHLC {
                        double                          open;
                        double                          high;
                        double                          low;
                        double                          close;
                };
                SiOHLC                                          OHLC[fillSize];
                bool                                                    isBullish[fillSize];                                                                                                                                    bool    isBearish[fillSize];

                struct SLongWick {
                        bool            upper;
                        bool            lower;
                };
                SLongWick                                       LongWick[fillSize];

}; // END Of Class Definition

void CCPTest::UpdateData(const double &pOpen[],const double &pHigh[],const double &pLow[],const double &pClose[],int pIdxCB) {

        string vMethod = "[" + mSymbol + "," + EnumToString(mTimeFrame) + "] " + __FUNCTION__;
                mIndexTime = TimeToString(iTime(mSymbol,mTimeFrame,mIdxCB),TIME_DATE|TIME_MINUTES);
                DoPrint = (mIndexTime == "2023.10.02 14:00");                                                                                                                                                                   // ... pIdxCB is Index[0] bar on chart

                if(DoPrint)     PrintFormat("%s [%s] pIdxCB[%i] > (Bars[%i]-21) Exit",vMethod,mIndexTime,pIdxCB,Bars(mSymbol,mTimeFrame));
                if(pIdxCB > (Bars(mSymbol,mTimeFrame)-21))                                                                                                                                                                                                                                                                                                      return;

                mIdxCB   = pIdxCB;                                                                                                                                                                                      // Saved as global varible to be called from different methods

                int idxLoop = mIdxCB + fillSize;                                                                                                                                // Bar Shift for Index[0]
                for(int j = fillSize-1; j >= 0 && pIdxCB > 0; j--) {                                            // Static array element number 5 to 0

                        OHLC[j].open = pOpen[idxLoop];                                                                                                                          OHLC[j].high  = pHigh[idxLoop];
                        OHLC[j].low  = pLow[idxLoop];                                                                                                                                   OHLC[j].close = pClose[idxLoop];
                if(DoPrint)     PrintFormat("%s [%s] mIdxCB[%i] idxLoop[%i] idxJ[%i] Close[%.1f] Open[%.1f]",vMethod,mIndexTime,mIdxCB,idxLoop,j,OHLC[j].close,OHLC[j].open);

                        isBullish[j]    = OHLC[j].close >= OHLC[j].open ? true : false;
                        isBearish[j]    = OHLC[j].close <  OHLC[j].open ? true : false;
                        idxLoop--;
                }

} // END Of method UpdateData()

bool CCPTest::IsSStar(int pIndex=1) {

                int i = pIndex;

                double lowerThird = OHLC[i].low + ((OHLC[i].high - OHLC[i].low) / 3);
                if(OHLC[i].open < lowerThird && OHLC[i].close < lowerThird)                                                                                                                                                                                                     return(true);

                return(false);

} // END of method IsSStar()

bool CCPTest::IsHammer(int pIndex=1) {

                int i = pIndex;

                double upperThird = OHLC[i].high - ((OHLC[i].high - OHLC[i].low) / 3);
                if(OHLC[i].open > upperThird && OHLC[i].close > upperThird)                                                                                                                                                                                                     return(true);

                return(false);

} // END of method IsHammer()k forward to experts to help me out and enable me to continue work on my indicator, which primarily uses this bar[index] data for further calculation.

Thanks in advance and regards.

Files:
CPTest.mqh  17 kb
iCPTest.mq5  17 kb
CPTest_001.png  536 kb
 
I don't mean to sound rude, but I don't think anybody has time to look deeply into someone else's project!
 
Conor Mcnamara #:
I don't mean to sound rude, but I don't think anybody has time to look deeply into someone else's project!

Hi @Conor Mcnamara

May be that's what you think.

But my experience is different and most of the time I am being assisted by 'kind hearted people' on the forum.

 
What is the purpose of this fillSize ?
It might cause the chart shift you"re experiencing.
(Just guessing without further detail testing)

    int idxLoop = mIdxCB + fillSize;                                                                                                                                // Bar Shift for Index[0]
           
 
Soewono Effendi #:
What is the purpose of this fillSize ?
It might cause the chart shift you"re experiencing.
(Just guessing with further detail testing)

Thanks for reply @Soewono Effendi

The purpose is to collect previous 5 bars data as some candle pattern can take into account three+ bars (e.g. Three White Soldiers).

mIdxCB is current bar on which pattern is searched. OHLC[fillSize] = OHLC[6] static array where OHLC[1] have data for mIdxCB.

Hope this clarify matter and help you for further detail testing.

Regards.

 
my guess is, that variable caused your bar shift.
Good luck
 
Soewono Effendi #:
my guess is, that variable caused your bar shift.
Good luck

@Soewono Effendi Thanks for you time man :)

Reason: