Histograms

 

I have been trying to make an indicator that uses 4 MA lines to calculate direction then uses that direction to decide which of three buffers to use for drawing a macd histogram, so the end result I was looking for would be a macd histogram with three colours, I looked at the code for the awesome oscillator as a guide for how to do this and I believe I coded my indicator in the same way but it is not working out, if i map the 3 histogram buffers to the macd buffer the indicator window is left empty, but if i map them to one of the MA lines buffers it draws the three colored histogram, but the histogram is not what i expected as the lines are all the same length can anyone see where I am going wrong with this ? The result I am looking for would look simalar to the awesome oscillator but should have three colors.

Below is the code when the 3 histogram buffers are mapped to one of the MA lines in my switch, i wanted to map them to buffer4 - the macd line buffer but that doesnt work

//---- indicator settings
#property indicator_separate_window
#property indicator_buffers 8
#property indicator_color1 EMPTY
#property indicator_color2 EMPTY
#property indicator_color3 EMPTY
#property indicator_color4 EMPTY
#property indicator_color5 Black
#property indicator_color6 Lime
#property indicator_color7 Red
#property indicator_color8 Magenta
//---- input parameters
extern int       LinePeriods=3;
extern int       Shift=0;
//---- buffers
double ExtMapBuffer0[];
double ExtMapBuffer1[];
double ExtMapBuffer2[];
double ExtMapBuffer3[];
double ExtMapBuffer4[];
double ExtMapBuffer5[];
double ExtMapBuffer6[];
double ExtMapBuffer7[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
//---- indicators
   SetIndexStyle(0,DRAW_NONE);
   SetIndexStyle(1,DRAW_NONE);
   SetIndexStyle(2,DRAW_NONE);
   SetIndexStyle(3,DRAW_NONE);
   SetIndexStyle(4,DRAW_NONE);
   SetIndexStyle(5,DRAW_HISTOGRAM);
   SetIndexStyle(6,DRAW_HISTOGRAM);
   SetIndexStyle(7,DRAW_HISTOGRAM);
   IndicatorDigits(Digits+1);
//----   
   SetIndexBuffer(0,ExtMapBuffer0);
   SetIndexBuffer(1,ExtMapBuffer1);
   SetIndexBuffer(2,ExtMapBuffer2);
   SetIndexBuffer(3,ExtMapBuffer3);
   SetIndexBuffer(4,ExtMapBuffer4);
   SetIndexBuffer(5,ExtMapBuffer5);
   SetIndexBuffer(6,ExtMapBuffer6);
   SetIndexBuffer(7,ExtMapBuffer7);
//----
   SetIndexDrawBegin(0,LinePeriods);
   SetIndexDrawBegin(1,LinePeriods);
   SetIndexDrawBegin(2,LinePeriods);
   SetIndexDrawBegin(3,LinePeriods);
   SetIndexDrawBegin(4,34);
   SetIndexDrawBegin(5,34);
   SetIndexDrawBegin(6,34);
   SetIndexDrawBegin(7,34);  
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
//----
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
   int    limit=500,idf,mdf;
   int    i, counted_bars=IndicatorCounted();
   
//----
   i=Bars-counted_bars-1;
   if(i>limit-1) i=limit-1;
   while(i>=0)
    {
     ExtMapBuffer0[i]=iMA(NULL,0,LinePeriods,Shift,MODE_LWMA,PRICE_HIGH,i);
     ExtMapBuffer1[i]=iMA(NULL,0,LinePeriods,Shift,MODE_LWMA,PRICE_LOW,i);
     ExtMapBuffer2[i]=iMA(NULL,0,LinePeriods,Shift,MODE_LWMA,PRICE_MEDIAN,i);
     ExtMapBuffer3[i]=iMA(NULL,0,LinePeriods,Shift,MODE_LWMA,PRICE_CLOSE,i);
     ExtMapBuffer4[i]=iMA(NULL,0,5,0,MODE_SMA,PRICE_MEDIAN,i)-iMA(NULL,0,34,0,MODE_SMA,PRICE_MEDIAN,i);
     
//---- compare current and previous line values

     idf=0;
     if(ExtMapBuffer0[i]>ExtMapBuffer0[i+1]) idf++;
     if(ExtMapBuffer1[i]>ExtMapBuffer1[i+1]) idf++;
     if(ExtMapBuffer2[i]>ExtMapBuffer2[i+1]) idf++;
     if(ExtMapBuffer3[i]>ExtMapBuffer3[i+1]) idf++;
     if(ExtMapBuffer0[i]<ExtMapBuffer0[i+1]) idf--;
     if(ExtMapBuffer1[i]<ExtMapBuffer1[i+1]) idf--;
     if(ExtMapBuffer2[i]<ExtMapBuffer2[i+1]) idf--;
     if(ExtMapBuffer3[i]<ExtMapBuffer3[i+1]) idf--;
     
//---- calculate direction
     if(idf==4 || idf==3) mdf=0;
     if(idf==-4 || idf ==-3) mdf=1;
     if(idf<=2 && idf>=-2) mdf=2;
//----    

     switch(mdf)
      {
       case 0:  ExtMapBuffer5[i]=ExtMapBuffer1[i];
                ExtMapBuffer6[i]=0.0;
                ExtMapBuffer7[i]=0.0;  break;
                
       case 1:  ExtMapBuffer6[i]=ExtMapBuffer1[i];
                ExtMapBuffer5[i]=0.0;
                ExtMapBuffer7[i]=0.0;  break;
                
       case 2:  ExtMapBuffer7[i]=ExtMapBuffer1[i];
                ExtMapBuffer5[i]=0.0;
                ExtMapBuffer6[i]=0.0;  break;
                         
       default: Alert("error: invalid switch. mdf= ",mdf);
      }
     i--;
    } 
   return(0);
  }
//+------------------------------------------------------------------+
 

Does anyone have any ideas about this ? Histograms seems to be a bit of a grey area on this forum I found some information but its hard to find any proper documentation I'm going to continue experimenting untill I get this to work then i'll write a thread describing exactly how to use them. I'm about to try something different. I was looking at other indicators with histograms it appears it is neccessary to make two separate loops the first one for calculating and filling buffers with the data to be used in the histogram, then a second loop to draw the histogram of that data so I'm going to try that.

 

Im finaly getting somewhere with this, it definately needs a separate loop for the histogram, I dont know why it wont take the data from the other buffer as the buffer is getting filled, i thought if the non drawing buffer[i] has been assigned a value in the loop before that same buffer value is called to be assigned to histogram_buffer[i] then it should work but for some reason it doesnt. I hope someone would explain why that is, but anyway the way to make a multicolored histogram is to fill a non drawing buffer with the data to be used for the histogram in the first loop then in the second loop use a buffer for each color, map those buffers to the previously filled buffer with the data for the histogram, switching between them according to the criteria for changing the color AND at the same time assigning the non used color buffers the value of zero so only only one of the buffers at a time can be used to draw.

I guess if all the buffers are at zero because the real value is a zero nothing gets drawn because they cancel each other out but in that case nothing is supposed to be drawn at zero so that works fine.

 

SDC:

I guess if all the buffers are at zero because the real value is a zero nothing gets drawn because they cancel each other out but in that case nothing is supposed to be drawn at zero so that works fine.

You should be setting them to EMPTY_VALUE not zero since you didn't call SetIndexEmptyValue()
 
WHRoeder:
You should be setting them to EMPTY_VALUE not zero since you didn't call SetIndexEmptyValue()

OK thanks WHR I tried that it works great thats a better solution than setting them to zero. I got the idea for using zero from other multicolored histogram indicators but it didnt really look like the best way to do it
 

I found theres a problem with using EMPTY_VALUE it changes the whole histogram. I assume this is because EMPTY_VALUE actually has a value i cant remember what that value is but I do remember comming across an issue related to that before, i tried using SetIndexEmptyValue to zero but that didnt work properly either so I went back to setting the unused buffers to zero in the change color part.

Other issues I have found are, for some reason if there are any other buffers in the indicator, drawing or non drawing they mess up the histogram I have no idea why this is, it makes no difference if the extra buffer is in the first loop, the second loop or even in a third counting loop of its own, it somehow interferes with the histogram maybe someone might be able to explain why this is. This means I wont be able to use any other counting buffers in the indicator for establishing direction which was my original intention I will have to do that another way.

 

Histograms behave different if you use them in chart_window or separate_window.

Unfortunately this is not documented well.

separate_window:

  • you can draw up to eight different histograms, each one is starting from the 0 line and goes to the value set in the buffer
chart_window:

  • you can draw up to 4 different histograms simultaneously
  • each buffer automatically pairs with the next buffer (buffer1 and buffer2),( buffer3 and buffer4)....
  • buffers color is choosen automatically depending on which of the 2 (from each pair) buffer values is higher

i hope that make something clear. if not just ask...

Histograms are pain in the beginning..

 

btw, how should the indikator look?

this is what i get, (i have modified the histogrames, to witdh 5)

 

Ah,i think i understood what you want. after rereading your first post.

The problem with linking to macd buffer is that the ma buffers are much bigger so your windows will zoom out, and the small macd values are only displayed as straight line.

two solutions:

1) use indicator_minimum, indicator_maximum.

2)use internal variables and not buffers for the ma values.

voila:


#property indicator_separate_window
#property indicator_buffers 4
#property indicator_color1 Red
#property indicator_color2 Lime
#property indicator_color3 Magenta
#property indicator_color4 Red
//---- buffers
double do[];
double up[];
double no[];
double macd[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
//---- indicators
   SetIndexStyle(0,DRAW_HISTOGRAM,STYLE_SOLID,5);
   SetIndexBuffer(0,do);
   SetIndexStyle(1,DRAW_HISTOGRAM,STYLE_SOLID,5);
   SetIndexBuffer(1,up);
   SetIndexStyle(2,DRAW_HISTOGRAM,STYLE_SOLID,5);
   SetIndexBuffer(2,no);
   SetIndexStyle(3,DRAW_LINE,STYLE_SOLID,5);
   SetIndexBuffer(3,macd);
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
extern int       LinePeriods=3;
extern int       Shift=0;
int start()
  {
   int    counted_bars=IndicatorCounted();
//----
   double ma_values[2][4];
   double idf;
   int j=0;
   for(int i=Bars-counted_bars-1;i>=0;i--){
     for(j=0;j<2;j++){
     ma_values[j][0]=iMA(NULL,0,LinePeriods,Shift,MODE_LWMA,PRICE_HIGH,i+j);
     ma_values[j][1]=iMA(NULL,0,LinePeriods,Shift,MODE_LWMA,PRICE_LOW,i+j);
     ma_values[j][2]=iMA(NULL,0,LinePeriods,Shift,MODE_LWMA,PRICE_MEDIAN,i+j);
     ma_values[j][3]=iMA(NULL,0,LinePeriods,Shift,MODE_LWMA,PRICE_CLOSE,i+j);
     }
     macd[i]=iMA(NULL,0,5,0,MODE_SMA,PRICE_MEDIAN,i)-iMA(NULL,0,34,0,MODE_SMA,PRICE_MEDIAN,i);
     idf=0;
     for(j=0;j<4;j++){
         if(ma_values[0][j]<ma_values[1][j]) idf--;
         if(ma_values[0][j]>ma_values[1][j]) idf++;         
     }

     if(idf>=3){
      up[i]=macd[i];do[i]=0;no[i]=0;
     }else{
     if(idf<=-3){
      do[i]=macd[i];up[i]=0;no[i]=0;
     }else{
      no[i]=macd[i];up[i]=0;do[i]=0;
     }
     }    
   }
//----
   return(0);
  }
//+------------------------------------------------------------------+
 

Yes !! the last histogram you have displayed is what I was trying to do thanks zzuegg thats exactly what I was struggling with,you make it look so easy lol, I see how you're using internal variables to avoid the extra buffers, is there any reason why you used ifs instead of switch like i did in my first attempt at this ?

 
SDC:

Yes !! the last histogram you have displayed is what I was trying to do thanks zzuegg thats exactly what I was struggling with,you make it look so easy lol, I see how you're using internal variables to avoid the extra buffers, is there any reason why you used ifs instead of switch like i did in my first attempt at this ?

no big deal, you made a if tree to set the value to mdf, and i set there immediately the buffers. so no need for the mdf variable and no need for the switch.

i assume also that a if()else tree like this one is a bit faster then a switch construct.

but honestly if switch would support things like

case >3 : {}

i probably would have taken the switch();

Reason: