How to overlay Histogram plots in DRAW_HISTOGRAM2 - page 3

Vladimir Karputov
Moderator
306178

Code:

//+------------------------------------------------------------------+
//|                                               Temp Indicator.mq5 |
//|                              Copyright © 2022, Vladimir Karputov |
//|                      https://www.mql5.com/en/users/barabashkakvn |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2022, Vladimir Karputov"
#property link      "https://www.mql5.com/en/users/barabashkakvn"
#property version   "1.000"
#property indicator_separate_window
#property indicator_buffers 4
#property indicator_plots   2
//--- plot Label1
#property indicator_label1  "Label1"
#property indicator_type1   DRAW_HISTOGRAM2
#property indicator_color1  clrBlue
#property indicator_style1  STYLE_SOLID
#property indicator_width1  3
//--- plot Label2
#property indicator_label2  "Label2"
#property indicator_type2   DRAW_HISTOGRAM2
#property indicator_color2  clrRed
#property indicator_style2  STYLE_SOLID
#property indicator_width2  3
//--- input parameters
input int      Input1=1;
//--- indicator buffers
double         Label1Buffer1[];
double         Label1Buffer2[];
double         Label2Buffer1[];
double         Label2Buffer2[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,Label1Buffer1,INDICATOR_DATA);
   SetIndexBuffer(1,Label1Buffer2,INDICATOR_DATA);
   SetIndexBuffer(2,Label2Buffer1,INDICATOR_DATA);
   SetIndexBuffer(3,Label2Buffer2,INDICATOR_DATA);
//---
   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[])
  {
//---
   int limit=prev_calculated-1;
   if(prev_calculated==0)
      limit=0;
   for(int i=0; i<rates_total; i++)
     {
      double up=3.0,medium=2.0,down=1.0;
      int rnd=MathRand();
      if(rnd>32767/2)
        {
         up=3.0;
         medium=2.0;
         down=1.0;
        }
      else
        {
         up=1.0;medium=2.0;down=3.0;
        }
      //---
      Label1Buffer1[i]=up;
      Label1Buffer2[i]=medium;
      Label2Buffer1[i]=medium;
      Label2Buffer2[i]=down;
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+


Result:

Files:
salitos
47
salitos  

Thank you so much @Fernando I think my one of my main problems was not understanding that I needed to specify 2 plots in the compiler directives when I used 2 histograms, MT4 let me get away with specifying one plot and then indirectly creating 2 histogram plots in directive by specifying indicator color 1 and indicator color 2 directives, so I carried this over to mql5. Also of course I had thought that histogram 2 would handle 2 plots.


On the mixing of intermediate/calculation buffers part, could you please clarify on something please, do you mean that the assignment of values should be done from a variable that got its data independently of the buffer ie. that another buffer should not be somewhere in the pipeline of data you want to assign to another buffer? Also, If the above is true, should I then create a normal array instead of a calculation  buffer to pass on values for the ADX and Awesome Osc handle that i retrieve in calls to handleValuesToBuffer() in my code?

Edit Thank yout too @Vladimir , I would also appreciate if you could shed light on the buffer values mixing.
Fernando Carreiro
11039

salitos #: Thank you so much @Fernando I think my one of my main problems was not understanding that I needed to specify 2 plots in the compiler directives when I used 2 histograms, MT4 let me get away with specifying one plot and then indirectly creating 2 histogram plots in directive by specifying indicator color 1 and indicator color 2 directives, so I carried this over to mql5. Also of course I had thought that histogram 2 would handle 2 plots.

On the mixing of intermediate/calculation buffers part, could you please clarify on something please, do you mean that the assignment of values should be done from a variable that got its data independently of the buffer ie. that another buffer should not be somewhere in the pipeline of data you want to assign to another buffer? Also, If the above is true, should I then create a normal array instead of a calculation  data to pass on values for the ADX and Awesome Osc handle that i retrieve in calls to handleValuesToBuffer() in my code?

I had already stated that you had to define 2 plots ... "So, yes, just as you do on MT4 you can have 2 separate plots, each one being a histogram but with different display properties."

However, even in MT4 you also require 2 "plots", and you just stated that you were defining 2 colours, and therefore 2 plots (MT4 does not have "plots", only buffers). You were just being lucky that it was using valid default values for the other properties instead of you specifying them explicitly. In other words you were programming it incorrectly, but you were getting away with it by pure luck on MT4.

As for the "mixing", calculation buffers are not "plots", so they should be registered at the end of the buffer list ...

// Valid registration list of buffers
SetIndexBuffer( 0, ..., INDICATOR_DATA         );
SetIndexBuffer( 1, ..., INDICATOR_DATA         );
SetIndexBuffer( 2, ..., INDICATOR_DATA         );
SetIndexBuffer( 3, ..., INDICATOR_DATA         );
SetIndexBuffer( 4, ..., INDICATOR_CALCULATIONS );
SetIndexBuffer( 5, ..., INDICATOR_CALCULATIONS );
SetIndexBuffer( 6, ..., INDICATOR_CALCULATIONS );

and not as you have done it ...

// Invalid registration of buffers (do not mix)
SetIndexBuffer( 0, ..., INDICATOR_DATA         );
SetIndexBuffer( 1, ..., INDICATOR_CALCULATIONS );
SetIndexBuffer( 2, ..., INDICATOR_DATA         );
SetIndexBuffer( 3, ..., INDICATOR_DATA         );
SetIndexBuffer( 4, ..., INDICATOR_CALCULATIONS );
SetIndexBuffer( 5, ..., INDICATOR_DATA         );
SetIndexBuffer( 6, ..., INDICATOR_CALCULATIONS );
salitos
47
salitos  
Absoloutely, much obliged on the second point I see why now, In the Docs it was stated that compiler directive N will map to indexBuffer N-1 so putting the calculations in between was actually causing the properties specified in the compiler directives to map erroneously, right? Incidentally I had placed the calculationBuffers in my mql4 code at the end, not because I understood this but just by the coincidence that I had thought to add them last when developing the indicator. :)
Fernando Carreiro
11039
salitos #: Absoloutely, much obliged on the second point I see why now, In the Docs it was stated that compiler directive N will map to indexBuffer N-1 so putting the calculations in between was actually causing the properties specified in the compiler directives to map erroneously, right? Incidentally I had placed the calculationBuffers in my mql4 code at the end, not because I understood this but just by the coincidence that I had thought to add them last when developing the indicator. :)

On MT4 there are no calculation buffers. It accepts the classification without an error but they are treated as normal data buffers. The distinction is just in the order they are indexed when comparing the buffer count in the compiler directive and the buffer count defined by the function, meaning that they have to be at the end.

On MT5, you can actually mix them (only to a degree), but you have to be VERY careful if you don't know what you are doing, so to prevent such problems, ALWAYS put them at the end and you will save yourself a lot of hassles.

salitos
47
salitos  
Thank you this was a life saver.
Fernando Carreiro
11039
salitos #: Thank you this was a life saver.
You are welcome!