MACD histogram direction change help

 


I am trying to create indicator which displays up arrow when MACD histogram changes direction to go up, and down arrow when change to down. I run with no errors but it giving incorrect arrows on chart and missing out many changes...

 

Any help much appreciated! :) 

 

//+------------------------------------------------------------------+
//|                                                        19151.mq4 |
//|                                                                  |
//|                                                                  |
//+------------------------------------------------------------------+
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 LawnGreen
#property indicator_color2 Red
//MACD Settings
extern int Fast_EMA = 12;
extern int Slow_EMA = 26;
extern int Signal_Period = 9;
extern int price = PRICE_CLOSE;

//MACD for calculations
double MACD1;
double MACD2;
double MACD3;

double CrossUp[];
double CrossDown[];

//plot state can be 1 of: UP,DOWN
#define PLOTUP 1
#define PLOTDOWN -1
int iWaitFor = PLOTUP;  //initial value

//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
  //---- indicators/ Arrows
  SetIndexBuffer(0, CrossUp);
  SetIndexStyle(0, DRAW_ARROW, EMPTY);
  SetIndexArrow(0, 225);
  SetIndexBuffer(1, CrossDown);
  SetIndexStyle(1, DRAW_ARROW, EMPTY);
  SetIndexArrow(1, 226);
  

  return(0);
}
//+------------------------------------------------------------------+
//| script program start function |
//+------------------------------------------------------------------+
int start()
{
  MACD1 =0;
  MACD2 =0;
  MACD3 =0;
  int counted_bars = IndicatorCounted();
  int i;
  int limit;
  if(counted_bars < 0)
  return(-1);
  if(counted_bars > 0)
  counted_bars--;
  limit = Bars - counted_bars;
  for(i=0; i<=limit; i++)
  {
    MACD1 = iMACD(NULL,0,Fast_EMA,Slow_EMA,Signal_Period,price,MODE_MAIN,i);  
    MACD2 = iMACD(NULL,0,Fast_EMA,Slow_EMA,Signal_Period,price,MODE_MAIN,i + 1);
    MACD3 = iMACD(NULL,0,Fast_EMA,Slow_EMA,Signal_Period,price,MODE_MAIN,i + 2);
  
    if ((MACD1<MACD2  &&  MACD2>MACD3) && iWaitFor==PLOTUP)  //
    {
      iWaitFor = PLOTDOWN;
      CrossUp[i]=Low[i] - 0.0005;
    }
    if ((MACD1>MACD2  &&  MACD2<MACD3) && iWaitFor==PLOTDOWN)
    {
      iWaitFor = PLOTUP;
      CrossDown[i]=High[i] + 0.0005;
    }
  }
  return(0);
}


 

 
 
fabian waldo:

I am trying to create indicator which displays up arrow when MACD histogram changes direction to go up, and down arrow when change to down. I run with no errors but it giving incorrect arrows on chart and missing out many changes...

 

Any help much appreciated! :) 

Post the code ...
 


Mladen Rakic
:

Post the code ...

Sorry I dont know why it didnt insert properly the first time... 

//+------------------------------------------------------------------+
//|                                                        19151.mq4 |
//|                                                                  |
//|                                                                  |
//+------------------------------------------------------------------+
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 LawnGreen
#property indicator_color2 Red
//MACD Settings
extern int Fast_EMA = 12;
extern int Slow_EMA = 26;
extern int Signal_Period = 9;
extern int price = PRICE_CLOSE;

//MACD for calculations
double MACD1;
double MACD2;
double MACD3;

double CrossUp[];
double CrossDown[];

//plot state can be 1 of: UP,DOWN
#define PLOTUP 1
#define PLOTDOWN -1
int iWaitFor = PLOTUP;  //initial value

//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
  //---- indicators/ Arrows
  SetIndexBuffer(0, CrossUp);
  SetIndexStyle(0, DRAW_ARROW, EMPTY);
  SetIndexArrow(0, 225);
  SetIndexBuffer(1, CrossDown);
  SetIndexStyle(1, DRAW_ARROW, EMPTY);
  SetIndexArrow(1, 226);
  

  return(0);
}
//+------------------------------------------------------------------+
//| script program start function |
//+------------------------------------------------------------------+
int start()
{
  MACD1 =0;
  MACD2 =0;
  MACD3 =0;
  int counted_bars = IndicatorCounted();
  int i;
  int limit;
  if(counted_bars < 0)
  return(-1);
  if(counted_bars > 0)
  counted_bars--;
  limit = Bars - counted_bars;
  for(i=0; i<=limit; i++)
  {
    MACD1 = iMACD(NULL,0,Fast_EMA,Slow_EMA,Signal_Period,price,MODE_MAIN,i);  
    MACD2 = iMACD(NULL,0,Fast_EMA,Slow_EMA,Signal_Period,price,MODE_MAIN,i + 1);
    MACD3 = iMACD(NULL,0,Fast_EMA,Slow_EMA,Signal_Period,price,MODE_MAIN,i + 2);
  
    if ((MACD1<MACD2  &&  MACD2>MACD3) && iWaitFor==PLOTUP)  //
    {
      iWaitFor = PLOTDOWN;
      CrossUp[i]=Low[i] - 0.0005;
    }
    if ((MACD1>MACD2  &&  MACD2<MACD3) && iWaitFor==PLOTDOWN)
    {
      iWaitFor = PLOTUP;
      CrossDown[i]=High[i] + 0.0005;
    }
  }
  return(0);
}

 
fabian waldo:

Sorry I dont know why it didnt insert properly the first time... 

//+------------------------------------------------------------------+
//|                                                        19151.mq4 |
//|                                                                  |
//|                                                                  |
//+------------------------------------------------------------------+
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 LawnGreen
#property indicator_color2 Red
//MACD Settings
extern int Fast_EMA = 12;
extern int Slow_EMA = 26;
extern int Signal_Period = 9;
extern int price = PRICE_CLOSE;

//MACD for calculations
double MACD1;
double MACD2;
double MACD3;

double CrossUp[];
double CrossDown[];

//plot state can be 1 of: UP,DOWN
#define PLOTUP 1
#define PLOTDOWN -1
int iWaitFor = PLOTUP;  //initial value

//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
  //---- indicators/ Arrows
  SetIndexBuffer(0, CrossUp);
  SetIndexStyle(0, DRAW_ARROW, EMPTY);
  SetIndexArrow(0, 225);
  SetIndexBuffer(1, CrossDown);
  SetIndexStyle(1, DRAW_ARROW, EMPTY);
  SetIndexArrow(1, 226);
  

  return(0);
}
//+------------------------------------------------------------------+
//| script program start function |
//+------------------------------------------------------------------+
int start()
{
  MACD1 =0;
  MACD2 =0;
  MACD3 =0;
  int counted_bars = IndicatorCounted();
  int i;
  int limit;
  if(counted_bars < 0)
  return(-1);
  if(counted_bars > 0)
  counted_bars--;
  limit = Bars - counted_bars;
  for(i=0; i<=limit; i++)
  {
    MACD1 = iMACD(NULL,0,Fast_EMA,Slow_EMA,Signal_Period,price,MODE_MAIN,i);  
    MACD2 = iMACD(NULL,0,Fast_EMA,Slow_EMA,Signal_Period,price,MODE_MAIN,i + 1);
    MACD3 = iMACD(NULL,0,Fast_EMA,Slow_EMA,Signal_Period,price,MODE_MAIN,i + 2);
  
    if ((MACD1<MACD2  &&  MACD2>MACD3) && iWaitFor==PLOTUP)  //
    {
      iWaitFor = PLOTDOWN;
      CrossUp[i]=Low[i] - 0.0005;
    }
    if ((MACD1>MACD2  &&  MACD2<MACD3) && iWaitFor==PLOTDOWN)
    {
      iWaitFor = PLOTUP;
      CrossDown[i]=High[i] + 0.0005;
    }
  }
  return(0);
}

Use this (it plots an arrow on a bar where the macd slope changes up or down). Since you did not use the signal line for anything, in this version there is no signal calculated (or parameter used for that)
//------------------------------------------------------------------
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 clrLawnGreen
#property indicator_color2 clrRed
#property strict
//------------------------------------------------------------------
extern int                Fast_EMA = 12;          // Fast ema period
extern int                Slow_EMA = 26;          // Slow ema period
extern ENUM_APPLIED_PRICE price    = PRICE_CLOSE; // Price

double CrossUp[],CrossDown[],direction[],macd[];
int OnInit()
{
   IndicatorBuffers(4);
   SetIndexBuffer(0, CrossUp);   SetIndexStyle(0, DRAW_ARROW); SetIndexArrow(0, 225);
   SetIndexBuffer(1, CrossDown); SetIndexStyle(1, DRAW_ARROW); SetIndexArrow(1, 226);
   SetIndexBuffer(2, direction);
   SetIndexBuffer(3, macd);
  return(0);
}
int OnCalculate (const int       rates_total,
                 const int       prev_calculated,
                 const datetime& btime[],
                 const double&   open[],
                 const double&   high[],
                 const double&   low[],
                 const double&   close[],
                 const long&     tick_volume[],
                 const long&     volume[],
                 const int&      spread[] )
{
   int counted_bars = prev_calculated;
      if(counted_bars < 0) return(-1);
      if(counted_bars > 0) counted_bars--;
            int limit=MathMin(rates_total-counted_bars,rates_total-1);

      for(int i=limit; i>-0; i--)
      {
         macd[i]      = iMA(NULL,0,Fast_EMA,0,MODE_EMA,price,i)-iMA(NULL,0,Slow_EMA,0,MODE_EMA,price,i);
         direction[i] = (i<Bars-1) ? (macd[i]>macd[i+1]) ? 1 : (macd[i]<macd[i+1]) ? -1 : 0 : 0;
         CrossUp[i]   = EMPTY_VALUE;
         CrossDown[i] = EMPTY_VALUE;
         if (i<Bars-1 && direction[i]!=direction[i+1])
         {
               if (direction[i]== 1) CrossUp[i]   = Low[i]  - iATR(NULL,0,10,i);
               if (direction[i]==-1) CrossDown[i] = High[i] + iATR(NULL,0,10,i);
         }
  }
  return(rates_total);
}
 
Mladen Rakic:
Use this (it plots an arrow on a bar where the macd slope changes up or down). Since you did not use the signal line for anything, in this version there is no signal calculated (or parameter used for that)
//------------------------------------------------------------------
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 clrLawnGreen
#property indicator_color2 clrRed
#property strict
//------------------------------------------------------------------
extern int                Fast_EMA = 12;          // Fast ema period
extern int                Slow_EMA = 26;          // Slow ema period
extern ENUM_APPLIED_PRICE price    = PRICE_CLOSE; // Price

double CrossUp[],CrossDown[],direction[],macd[];
int OnInit()
{
   IndicatorBuffers(4);
   SetIndexBuffer(0, CrossUp);   SetIndexStyle(0, DRAW_ARROW); SetIndexArrow(0, 225);
   SetIndexBuffer(1, CrossDown); SetIndexStyle(1, DRAW_ARROW); SetIndexArrow(1, 226);
   SetIndexBuffer(2, direction);
   SetIndexBuffer(3, macd);
  return(0);
}
int OnCalculate (const int       rates_total,
                 const int       prev_calculated,
                 const datetime& btime[],
                 const double&   open[],
                 const double&   high[],
                 const double&   low[],
                 const double&   close[],
                 const long&     tick_volume[],
                 const long&     volume[],
                 const int&      spread[] )
{
   int counted_bars = prev_calculated;
      if(counted_bars < 0) return(-1);
      if(counted_bars > 0) counted_bars--;
            int limit=MathMin(rates_total-counted_bars,rates_total-1);

      for(int i=limit; i>-0; i--)
      {
         macd[i]      = iMA(NULL,0,Fast_EMA,0,MODE_EMA,price,i)-iMA(NULL,0,Slow_EMA,0,MODE_EMA,price,i);
         direction[i] = (i<Bars-1) ? (macd[i]>macd[i+1]) ? 1 : (macd[i]<macd[i+1]) ? -1 : 0 : 0;
         CrossUp[i]   = EMPTY_VALUE;
         CrossDown[i] = EMPTY_VALUE;
         if (i<Bars-1 && direction[i]!=direction[i+1])
         {
               if (direction[i]== 1) CrossUp[i]   = Low[i]  - iATR(NULL,0,10,i);
               if (direction[i]==-1) CrossDown[i] = High[i] + iATR(NULL,0,10,i);
         }
  }
  return(rates_total);
}

Wow thank you so much Rakic, very much appreciated!!! :)

Out of interest do you know what was wrong with the approach I used to code this and why it didnt work, as opposed to what you have done?

 
fabian waldo:

Wow thank you so much Rakic, very much appreciated!!! :)

Out of interest do you know what was wrong with the approach I used to code this and why it didnt work, as opposed to what you have done?

A couple of things :
  • you were checking conditions (and "inheriting" previous state) from right to left - from future to past. That is a bad practice and should be avoided (that is one of the most common causes for repainting - not necessarily, but coupled with variables values "inheriting", that directly leads to repainting)
  • conditions were not clear (you were looking for places where the macd made an extreme on previous bar, not on current, and then marked it a if it was the current)
  • your arrow buffers were not cleaned - that was another cause for repainting that needed to be solved
 
Mladen Rakic:
A couple of things :
  • you were checking conditions (and "inheriting" previous state) from right to left - from future to past. That is a bad practice and should be avoided (that is one of the most common causes for repainting - not necessarily, but coupled with variables values "inheriting", that directly leads to repainting)
  • conditions were not clear (you were looking for places where the macd made an extreme on previous bar, not on current, and then marked it a if it was the current)
  • your arrow buffers were not cleaned - that was another cause for repainting that needed to be solved

Thankyou again Rakic very helpful!

 

I am trying to understand your code so I can work with it but I am struggling with a few parts, specifically the use of 0:0:,  EmptyValue, and the if statement (below only).. any guidance on this I would be very greatful for!

 Also I am trying to get the arrow to display on the current candle '0', ( so after close of previous rather than on it) - I have tried changing CrossUp[i] to CrossUp[i-1] but had no luck... any thoughts on how I could do this... 

 

Many Thanks! 

       direction[i] = (i<Bars-1) ? (macd[i]>macd[i+1]) ? 1 : (macd[i]<macd[i+1]) ? -1 : 0 : 0;
         CrossUp[i]   = EMPTY_VALUE;
         CrossDown[i] = EMPTY_VALUE;
         if (i<Bars-1 && direction[i]!=direction[i+1])


 

 
fabian waldo:

...

       direction[i] = (i<Bars-1) ? (macd[i]>macd[i+1]) ? 1 : (macd[i]<macd[i+1]) ? -1 : 0 : 0;
 ...

This line is equivalent to :

if(i<Bars-1)
  {
   if(macd[i]>macd[i+1])
     {
      direction[i]=1;
     }
   else if(macd[i]<macd[i+1])
     {
      direction[i]=-1;
     }
   else
     {
      direction[i]=0;
     }
  }
else
  {
   direction[i]=0;
  }


 

 
fabian waldo:

Thankyou again Rakic very helpful!

 

I am trying to understand your code so I can work with it but I am struggling with a few parts, specifically the use of 0:0:,  EmptyValue, and the if statement (below only).. any guidance on this I would be very greatful for!

 Also I am trying to get the arrow to display on the current candle '0', ( so after close of previous rather than on it) - I have tried changing CrossUp[i] to CrossUp[i-1] but had no luck... any thoughts on how I could do this... 

 

Many Thanks! 

       direction[i] = (i<Bars-1) ? (macd[i]>macd[i+1]) ? 1 : (macd[i]<macd[i+1]) ? -1 : 0 : 0;
         CrossUp[i]   = EMPTY_VALUE;
         CrossDown[i] = EMPTY_VALUE;
         if (i<Bars-1 && direction[i]!=direction[i+1])


Hi Radic, 

 

Do you know how I can get arrow to display on current candle - I have tried changing  "for(int i=limit; i>-0; i--)" to "for(int i=limit; i>=0; i--)" but this did not work... any thoughts please...? :)

 

Thanks 

 
fabian waldo:
Please don't answer inside quote.
Reason: