iBarShift() returns -1 - multiple timeframes - page 2

 

I created this solution for my problem.. I required the analysis of the previous H1 bar/candle relative to the current M15 bar/candle (within the current H1 candle).


//-------------------------------

      // get the current chart timeframe
      ENUM_TIMEFRAMES period = Period();

      if(period == PERIOD_M15)
        {

         /*
         Find the open time of any M15 bar.
         Remove the minutes and use the hour detail to get the H1 opening time (of the H1 bar that contains the M15 bar).
         There are x4 M15 bars in each H1 bar.
         The opening time of the first M15 bar (within each hour bar) will match the opening time of the H1 bar.
         */

         // Search bar by time. The function returns the index of the bar corresponding to the specified time.
         int M15_bar = iBarShift(Symbol(),PERIOD_M15,time[i]);

         // Returns the opening time of the bar (indicated by the 'shift' parameter) on the corresponding chart.
         datetime open_time_of_M15_bar = iTime(Symbol(),PERIOD_M15,M15_bar);

         // Convert datetime to seconds.
         ulong open_time_of_M15_bar_in_seconds = (ulong)open_time_of_M15_bar;

         // Round down to the nearest 3600 seconds (1 hour).
         ulong open_time_of_H1_bar_in_seconds = (ulong)(MathFloor(open_time_of_M15_bar_in_seconds / 3600.0) * 3600.0);

         // Get the open time of the previous H1 bar.
         ulong open_time_of_PREVIOUS_H1_bar_in_seconds = open_time_of_H1_bar_in_seconds-(60*60); //1hr

         // M15 bars within the H1 bar.
         int M15_bar1_of_H1_bar = iBarShift(Symbol(),PERIOD_M15,open_time_of_PREVIOUS_H1_bar_in_seconds);
         int M15_bar2_of_H1_bar = iBarShift(Symbol(),PERIOD_M15,open_time_of_PREVIOUS_H1_bar_in_seconds+(60*15)); //15min
         int M15_bar3_of_H1_bar = iBarShift(Symbol(),PERIOD_M15,open_time_of_PREVIOUS_H1_bar_in_seconds+(60*30)); //30min
         int M15_bar4_of_H1_bar = iBarShift(Symbol(),PERIOD_M15,open_time_of_PREVIOUS_H1_bar_in_seconds+(60*45)); //45min


         // Get H1 bar data.
         double h1_high, h1_low, h1_open, H1_close;

         //
         double M15_bar1_of_H1_bar_high, M15_bar2_of_H1_bar_high, M15_bar3_of_H1_bar_high, M15_bar4_of_H1_bar_high;

         M15_bar1_of_H1_bar_high = iHigh(_Symbol,PERIOD_M15,M15_bar1_of_H1_bar);
         M15_bar2_of_H1_bar_high = iHigh(_Symbol,PERIOD_M15,M15_bar2_of_H1_bar);
         M15_bar3_of_H1_bar_high = iHigh(_Symbol,PERIOD_M15,M15_bar3_of_H1_bar);
         M15_bar4_of_H1_bar_high = iHigh(_Symbol,PERIOD_M15,M15_bar4_of_H1_bar);

         h1_high =  MathMax(M15_bar1_of_H1_bar_high, MathMax(M15_bar2_of_H1_bar_high, MathMax(M15_bar3_of_H1_bar_high, M15_bar4_of_H1_bar_high)));


         //
         double M15_bar1_of_H1_bar_low, M15_bar2_of_H1_bar_low, M15_bar3_of_H1_bar_low, M15_bar4_of_H1_bar_low;

         M15_bar1_of_H1_bar_low = iLow(_Symbol,PERIOD_M15,M15_bar1_of_H1_bar);
         M15_bar2_of_H1_bar_low = iLow(_Symbol,PERIOD_M15,M15_bar2_of_H1_bar);
         M15_bar3_of_H1_bar_low = iLow(_Symbol,PERIOD_M15,M15_bar3_of_H1_bar);
         M15_bar4_of_H1_bar_low = iLow(_Symbol,PERIOD_M15,M15_bar4_of_H1_bar);


         h1_low = MathMin(M15_bar1_of_H1_bar_low, MathMin(M15_bar2_of_H1_bar_low, MathMin(M15_bar3_of_H1_bar_low, M15_bar4_of_H1_bar_low)));

         h1_open = iOpen(_Symbol,PERIOD_M15,M15_bar1_of_H1_bar);
         H1_close = iClose(_Symbol,PERIOD_M15,M15_bar4_of_H1_bar);

         //testing...
         Print("h1_open ", h1_open); //working
         Print("h1_high ", h1_high); //working
         Print("h1_low ", h1_low); //working
         Print("H1_close ", H1_close); //working

        }

      //-------------------------------
 
G Toner #:

I created this solution for my problem.. I required the analysis of the previous H1 bar/candle relative to the current M15 bar/candle (within the current H1 candle).


Why so complicated?

Just compute the bar from the indicator arrays

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int32_t rates_total,
                const int32_t 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[])
  {
//---

    // Get previous 1H bar (Assuming chart timeframe is 15Mins)
    MqlRates prev_1h_bar[1];
    prev_1h_bar[0] = get_bar_by_timeframe(PERIOD_H1, time[rates_total - 4], time, open, high, low, close, tick_volume, volume, spread);
    ArrayPrint(prev_1h_bar);
    
   
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+




const MqlRates get_bar_by_timeframe(const ENUM_TIMEFRAMES   target_timeframe, 
                                    const datetime          _target_time, 
                                    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[],
                                    const long              offset = NULL)
{
    // Local init
    
        const int       src_period_seconds  = ::PeriodSeconds(_Period);
        const int       dst_period_seconds  = ::PeriodSeconds(target_timeframe);
        const datetime  eod_time            = time[::ArraySize(time) - 1];
        const datetime  target_time         = _target_time - (_target_time % dst_period_seconds) - offset;
        int             src_ptr             = ::ArrayBsearch(time, target_time);
        MqlRates        retval              = {};


    // Error handling
    
        if( (src_ptr < NULL) 
         || (src_period_seconds > dst_period_seconds) 
         || (time[0] > (target_time)) )
        { return(retval); }


    // Init retval
    
        retval.low      = DBL_MAX;
        retval.spread   = INT_MAX;


    // Accumulate target-bar

        const datetime limit = ::MathMin(eod_time + 1, target_time + dst_period_seconds);
        while(time[src_ptr] < limit)
        {
            retval.close    = close[src_ptr];
            retval.time     = (retval.time == NULL)             ? time[src_ptr]     : retval.time;
            retval.open     = (retval.open == NULL)             ? open[src_ptr]     : retval.open;
            retval.high     = (retval.high < high[src_ptr])     ? high[src_ptr]     : retval.high;
            retval.low      = (retval.low > low[src_ptr])       ? low[src_ptr]      : retval.low;
            retval.spread   = (retval.spread > spread[src_ptr]) ? spread[src_ptr]   : retval.spread;

            retval.tick_volume += tick_volume[src_ptr];
            retval.real_volume += volume[src_ptr];
        
            // Loop control
            src_ptr++;
        }

    // Return
    return(retval);    
}

Just typed, not tested.