Custom Enum time frames

 

In Ninja traders 8 platform one can customize time frames when getting the return value for the OHLC by adding a data series which one square bracket would say how many bars ago, and the other square bracket would give the time frame value calculated in minutes. Is the same thing possible with Meta5? I am looking to create a 16 hour, 18 hour and 20 hour time frame. I do now it is possible using a 'loop' to get the opening and closing prices of these time frames, but I don't believe with this 'loop' it would be possible to get the high and low price. Has anyone created a custom Enum time frame and what technique did you use?

 

From the 1 hour timeframe, you can achieve any X hour timeframe with a condition using modulus. Take all data from 1 hour timeframe to make OHLC update at X hour timeframe.

I just coded this indicator for you as an example:

//+------------------------------------------------------------------+
//|                                                   Xhour Bars.mq5 |
//|                                  Copyright 2023, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_separate_window
#property indicator_buffers 5
#property indicator_plots 1

#property indicator_type1   DRAW_COLOR_CANDLES
#property indicator_color1  clrDodgerBlue, clrRed
#property indicator_width1  1

double opens[], closes[], highs[], lows[], candleColor[];

input int xHour = 1; // Custom hour timeframe

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
{
   //--- indicator buffers mapping
   SetIndexBuffer(0, opens, INDICATOR_DATA);
   SetIndexBuffer(1, highs, INDICATOR_DATA);
   SetIndexBuffer(2, lows, INDICATOR_DATA);
   SetIndexBuffer(3, closes, INDICATOR_DATA);
   SetIndexBuffer(4, candleColor, INDICATOR_COLOR_INDEX);

   //--- Set series order
   ArraySetAsSeries(opens, true);
   ArraySetAsSeries(closes, true);
   ArraySetAsSeries(highs, true);
   ArraySetAsSeries(lows, true);
   ArraySetAsSeries(candleColor, true);

   return (INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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[])
{
   CreateXHourTimeframe(xHour);  // Create custom 16-hour bars

   return (rates_total);
}


//+------------------------------------------------------------------+
//| Function to construct custom X-hour bars                         |
//+------------------------------------------------------------------+
void CreateXHourTimeframe(int xHours)
{
   MqlRates rates[];
   
   int count = 500;
   
   int copied = CopyRates(Symbol(), PERIOD_H1, 0, count, rates);
   if (copied <= 0)
   {
      Print("Failed to get rates!");
      return;
   }

   int index = 0;  // map X-hour candle index

   for (int i = copied - 1; i >= 0; i--)
   {
      datetime barTime = rates[i].time;
      int hour = TimeHour(barTime);

      // detect start of a new X-hour bar
      if (hour % xHours == 0)
      {
         opens[index] = rates[i].open;
         closes[index] = rates[i].close;
         highs[index] = rates[i].high;
         lows[index] = rates[i].low;
         
         candleColor[index] = (opens[index] < closes[index]) ? 0 : 1;

         index++;
      }
   }
}

//+------------------------------------------------------------------+
//| Custom function to extract hour from datetime                    |
//+------------------------------------------------------------------+
int TimeHour(datetime timeValue)
{
   return (int)((timeValue % 86400) / 3600); // Extract hours from timestamp
}
 
To get the customized OHLC data in an expert advisor, just use iCustom to gather the buffer data from the auxiliary open, high, low and close. Do the processing in the indicator, and use that custom indicator in the EA.
 
Conor Mcnamara #:
To get the customized OHLC data in an expert advisor, just use iCustom to gather the buffer data from the auxiliary open, high, low and close. Do the processing in the indicator, and use that custom indicator in the EA.

Thank you for the wsidom!

 

here's an optimized version of that function:

void CreateXHourTimeframe(int xHours)
{
   MqlRates rates[];
   int count = 500;

   int copied = CopyRates(Symbol(), PERIOD_H1, 0, count, rates);
   if (copied <= 0)
   {
      Print("Failed to get rates!");
      return;
   }

   int index = 0;  // X-hour candle index
   bool newBar = true;

   for (int i = copied - 1; i >= 0; i--)
   {
      datetime barTime = rates[i].time;
      int hour = TimeHour(barTime);

      // update current auxiliary bar high, low, and close
      if (!newBar)
      {
         closes[index] = rates[i].close;       // Save the last closing price
         highs[index] = rates[i].high;       // Save the highest price
         lows[index] = rates[i].low;           // Save the lowest price
      }
         
      // Check for the start of a new X-hour bar
      if (newBar || hour % xHours == 0)
      {
         // set up the new bar
         opens[index] = rates[i].open;
         highs[index] = rates[i].high;
         lows[index] = rates[i].low;
         closes[index] = rates[i].close;
         candleColor[index] = (opens[index] < closes[index]) ? 0 : 1;
         
         index++; 
         
         newBar = false;
      }
   }
}
 
Conor Mcnamara #:

here's an optimized version of that function:

Thank you!