Please Help me to make MultiTimeframe indicator

 
Hi there,

My name is Revazi, I am trying to made MultiTimeframe indicator based on Custom indicator called  Traditional MACD from MQL5 Market(https://www.mql5.com/en/market/product/2593).
I am using this indicators main line and as soon as line crosses above 0 level I want to make blue arrow(ArrowCode=116) and make reversal for below cross of 0 level with red dot.
Everything works fine till I am using Curreent_Timeframe but when I change it to different timeframe then indicator doesn't draw anything. Below is full source code:

//+------------------------------------------------------------------+
//|                                                    MACD Test.mq5 |
//+------------------------------------------------------------------+
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 4
#property indicator_plots 4

input int                  MACDH4FastEMAPeriod                 =  12;
input int                  MACDH4SlowEMAPeriod                 =  26;
input int                  MACDH4SignalEMAPeriod               =  9;
input ENUM_APPLIED_PRICE   MACDH4AppliedPrice                  =  PRICE_CLOSE;
input int                  MACDH4DotsWidth                     =  1;
input color                MACDH4UpDotsColor                   =  clrBlue;
input color                MACDH4DnDotsColor                   =  clrRed;

input int                  MACDD1FastEMAPeriod                 =  12;
input int                  MACDD1SlowEMAPeriod                 =  26;
input int                  MACDD1SignalEMAPeriod               =  9;
input ENUM_APPLIED_PRICE   MACDD1AppliedPrice                  =  PRICE_CLOSE;
input int                  MACDD1DotsWidth                     =  1;
input color                MACDD1UpDotsColor                   =  clrBlue;
input color                MACDD1DnDotsColor                   =  clrRed;

int View = 1;

int macdArrowCode = 116;

double   macdD1UpperBuffer[], macdD1LowerBuffer[],
         macdH4UpperBuffer[], macdH4LowerBuffer[];

int macdD1Direction = 0;
int macdH4Direction = 0;

int macdD1Handle = INVALID_HANDLE;
int macdH4Handle = INVALID_HANDLE;
//+------------------------------------------------------------------+
void DrawArrowBuffers(int       functonIndex,
                      double&   functonBuffer[],
                      int       functonArrowCode,
                      int       functonView,
                      color     functonDotsColor,
                      int       functionDotsWidth,
                      string    functionLabel)
{
   SetIndexBuffer(functonIndex, functonBuffer, INDICATOR_DATA);
   PlotIndexSetInteger(functonIndex, PLOT_DRAW_TYPE, DRAW_ARROW);
   PlotIndexSetInteger(functonIndex, PLOT_ARROW, functonArrowCode);
   PlotIndexSetInteger(functonIndex, PLOT_LINE_STYLE, STYLE_SOLID);
   PlotIndexSetInteger(functonIndex, PLOT_LINE_COLOR, functonView > 0 ? functonDotsColor : clrNONE);
   PlotIndexSetInteger(functonIndex, PLOT_LINE_WIDTH, functionDotsWidth);
   PlotIndexSetDouble(functonIndex, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   PlotIndexSetString(functonIndex, PLOT_LABEL, functionLabel);
}
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
{
//--- indicator buffers mapping
//--- macd d1 buffers
   DrawArrowBuffers(0, macdD1UpperBuffer, macdArrowCode, View, MACDD1UpDotsColor, MACDD1DotsWidth, "macdD1UpperBuffer");
   DrawArrowBuffers(1, macdD1LowerBuffer, macdArrowCode, View, MACDD1DnDotsColor, MACDD1DotsWidth, "macdD1LowerBuffer");
//--- macd h4 buffers
   DrawArrowBuffers(2, macdH4UpperBuffer, macdArrowCode, View, MACDH4UpDotsColor, MACDH4DotsWidth, "macdH4UpperBuffer");
   DrawArrowBuffers(3, macdH4LowerBuffer, macdArrowCode, View, MACDH4DnDotsColor, MACDH4DotsWidth, "macdH4LowerBuffer");
   //---
   macdD1Handle = iCustom(Symbol(), PERIOD_D1, "Market\\Traditional MACD", "", MACDD1FastEMAPeriod, MACDD1SlowEMAPeriod,
                        MACDD1SignalEMAPeriod, MACDD1AppliedPrice, true, false, "", 5000, false, clrRed, clrDarkGreen,
                        STYLE_SOLID, 2, false, STYLE_DOT, 1, false, clrSalmon, clrLawnGreen, STYLE_SOLID, 2, false,
                        STYLE_DOT, 1, "", false, false, false, "alert.wav", false, false);
   if(macdD1Handle < 0)
   {
      Print("The creation of iMACD has failed: macdD1Handle = ", INVALID_HANDLE, "\n",
            "Runtime error = ", GetLastError());
   }
   //---
   macdH4Handle = iCustom(Symbol(), PERIOD_H4, "Market\\Traditional MACD", "", MACDH4FastEMAPeriod, MACDH4SlowEMAPeriod,
                        MACDH4SignalEMAPeriod, MACDH4AppliedPrice, true, false, "", 5000, false, clrRed, clrDarkGreen,
                        STYLE_SOLID, 2, false, STYLE_DOT, 1, false, clrSalmon, clrLawnGreen, STYLE_SOLID, 2, false,
                        STYLE_DOT, 1, "", false, false, false, "alert.wav", false, false);
   if(macdH4Handle < 0)
   {
      Print("The creation of iMACD has failed: macdH4Handle = ", INVALID_HANDLE, "\n",
            "Runtime error = ", GetLastError());
   }
//---
   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[])
{
//---
   CalculateMACD(rates_total, prev_calculated, macdD1Handle, Symbol(), PERIOD_D1, MACDD1FastEMAPeriod, MACDD1SlowEMAPeriod, MACDD1SignalEMAPeriod, MACDD1AppliedPrice, macdD1UpperBuffer, macdD1LowerBuffer, macdD1Direction);
   CalculateMACD(rates_total, prev_calculated, macdH4Handle, Symbol(), PERIOD_H4, MACDH4FastEMAPeriod, MACDH4SlowEMAPeriod, MACDH4SignalEMAPeriod, MACDH4AppliedPrice, macdH4UpperBuffer, macdH4LowerBuffer, macdH4Direction);
//--- return value of prev_calculated for next call
   return(rates_total);
}
//+------------------------------------------------------------------+
void CalculateMACD(int                 macdRatesTotal,
                   int                 macdPervCalculated,
                   int                 macdHandle,
                   string              macdSymbol,
                   ENUM_TIMEFRAMES     macdTimeframe,
                   int                 macdFastEMAPeriod,
                   int                 macdSlowEMAPeriod,
                   int                 macdSignalEMAPeriod,
                   ENUM_APPLIED_PRICE  macdAppliedPrice,
                   double&             macdUpperArray[],
                   double&             macdLowerArray[],
                   int&                macdDirection)
{
   int limit = macdRatesTotal - macdPervCalculated;
   //--- counting from 0 to rates_total
   ArraySetAsSeries(macdUpperArray, true);
   ArraySetAsSeries(macdLowerArray, true);
   //--- initial zero
   if(macdPervCalculated < 1)
   {
      ArrayInitialize(macdUpperArray, EMPTY_VALUE);
      ArrayInitialize(macdLowerArray, EMPTY_VALUE);
   }
   else
   {
      limit++;
   }
   //---
   double macdLineArray[];
   if(CopyBuffer(macdHandle, 0, 0, macdRatesTotal, macdLineArray) <= 0) return;//return(macdRatesTotal);
   ArraySetAsSeries(macdLineArray, true);
   double High[];
   if(CopyHigh(macdSymbol, macdTimeframe, 0, macdRatesTotal, High) <= 0) return;//return(macdRatesTotal);
   ArraySetAsSeries(High, true);
   double Low[];
   if(CopyLow(macdSymbol, macdTimeframe, 0, macdRatesTotal, Low) <= 0) return;//return(macdRatesTotal);
   ArraySetAsSeries(Low, true);
   //--- main loop
   for(int i = limit - 1; i >= 0; i--)
   {
      if (i >= MathMin(5000 - 1, macdRatesTotal - 1 - 50)) continue; //omit some old rates to prevent "Array out of range" or slow calculation
      if(macdLineArray[i] > 0 && macdLineArray[i + 1] < 0)
      {
         macdUpperArray[i] = Low[i]; //Set indicator value at Candlestick Low
      }
      else
      {
         macdUpperArray[i] = EMPTY_VALUE;
      }
      if(macdLineArray[i] < 0 && macdLineArray[i + 1] > 0)
      {
         macdLowerArray[i] = Low[i]; //Set indicator value at Candlestick Low
      }
      else
      {
         macdLowerArray[i] = EMPTY_VALUE;
      }
   }
   //--- direction finding loop
   for(int i = 0; i < limit - 1; i++)
   {
      if(macdUpperArray[i] != 0)
      {
         //macdDirection = 1; // Buy
         macdDirection = -1; // Sell
         break;
      }
      else if(macdLowerArray[i] != 0)
      {
         macdDirection = 1; // Buy
         //macdDirection = -1; // Sell
         break;
      }
   }
}
//+------------------------------------------------------------------+

I have check lots of articles and posts but unfortunately couldn't fixed this indicator still so if someone can help me I will be very very grateful.

Thanks to all in advanced.
Download the 'Traditional MACD' Technical Indicator for MetaTrader 5 in MetaTrader Market
Download the 'Traditional MACD' Technical Indicator for MetaTrader 5 in MetaTrader Market
  • www.mql5.com
The MACD indicator in MetaTrader 4/5 looks different than the MACD indicator in most other charting software. That's because the MetaTrader 4/5 - English
 

This is probably because the original rates_total is too high for CopyBuffer on the higher timeframe. You need to 'translate' rates_total and prev_calculated.

But if you only intend to use Macd there's an easier solution - instead of calculating it for the higher timeframe you can multiply its periods. A Macd(12,26,9) on D1 is roughly the same as Macd(12*6,26*6,9*6) on H4.

So instead of working with MTF history data you could just adapt the Macd periods and stick with the current timeframe.

 
lippmaje:

This is probably because the original rates_total is too high for CopyBuffer on the higher timeframe. You need to 'translate' rates_total and prev_calculated.

But if you only intend to use Macd there's an easier solution - instead of calculating it for the higher timeframe you can multiply its periods. A Macd(12,26,9) on D1 is roughly the same as Macd(12*6,26*6,9*6) on H4.

So instead of working with MTF history data you could just adapt the Macd periods and stick with the current timeframe.

Thanks for reply.
Can you please help me and give more details how to 'translate' rates_total and prev_calculated?
That was max what I could do so if you will able to help me and edit code I will be very very grateful. Thanks in advanced.

 
   int D1factor=PeriodSeconds(PERIOD_D1)/PeriodSeconds();
   if(D1factor==0)
     {
       ...bad timeframe message
      return INIT_FAILED;
     }
   macdD1Handle = iCustom(_Symbol, _Period, "Market\\Traditional MACD", "", MACDD1FastEMAPeriod*D1factor, MACDD1SlowEMAPeriod*D1factor,
                        MACDD1SignalEMAPeriod*D1factor, MACDD1AppliedPrice, true, false, "", 5000, false, clrRed, clrDarkGreen,
                        STYLE_SOLID, 2, false, STYLE_DOT, 1, false, clrSalmon, clrLawnGreen, STYLE_SOLID, 2, false,
                        STYLE_DOT, 1, "", false, false, false, "alert.wav", false, false);

Like so maybe.

 
lippmaje:
Like so maybe.

No this is not helping. I want to get correct points. I have download many MTF indicators and all has this problem error:4806. Even code provided by MetaQuote itself has this problem when I use different timeframe then current. link for MetaQuote code: https://www.mql5.com/en/docs/indicators/imacd

So if you can and it will be easier for you just help me with this demo from MetaQuote and then I will do rest in my code.

Documentation on MQL5: Technical Indicators / iMACD
Documentation on MQL5: Technical Indicators / iMACD
  • www.mql5.com
//|                                                   Demo_iMACD.mq5 | //|                        Copyright 2011, MetaQuotes Software Corp. | //|                                             https://www.mql5.com | "The method of creation of the handle is set through the 'type' parameter (function type...
 
Dealing with MTF buffer data is complex. I'd go with the 'period' translation, much less headache and also it looks smoother on the chart.
Reason: