scale candlewidth for overlays (DRAW_HISTOGRAM)

 

As laid out by @whroeder1 in https://www.mql5.com/en/forum/158597 I have added some code to scale overlays I am drawing on top of candles. Unfortunately I can't seem to get it overlaid as I would like.

I have tried the original code, and I have tried tweaking the width for SetIndexStyle() based on the CHART_SCALE, but the cwidth I am setting for various CHART_SCALEs doesn't seem to allow for "perfectly" overlaying the entire body of the candle on different zoom levels.

Would very much appreciate pointers to what I'm missing here. Thanks.

Code:


//+------------------------------------------------------------------+
//|                                                 orangecandles.mq4 |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, bb"
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
#property indicator_chart_window

#property indicator_buffers 2

double BodyLow[], BodyHigh[];

int cwidth = 0;
int chwidth = 0;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   cwidth = (int) ChartGetInteger(0, CHART_SCALE);
   
   if (chwidth == 0) cwidth = 1;
   else if (chwidth == 1) cwidth = 1;
   else if (chwidth == 2) cwidth = 1;
   else if (chwidth == 3) cwidth = 1;
   else if (chwidth == 4) cwidth = 1;
   else if (chwidth == 5) cwidth = 1;  
   //we should never get here. 
   else cwidth = 1;   

   //Print(cwidth);
   
   SetIndexBuffer(0, BodyLow);
   SetIndexBuffer(1, BodyHigh);
   SetIndexStyle(0, DRAW_HISTOGRAM, EMPTY, cwidth, clrOrange);
   SetIndexStyle(1, DRAW_HISTOGRAM, EMPTY, cwidth, clrOrange);
   
//---
   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[])
  {
//---
   if(ChartGetInteger(0,CHART_SCALE) != chwidth)  OnInit();
   int limit;

   if (rates_total<=9)
      return(0);
   
   limit = rates_total - prev_calculated;
   if (prev_calculated > 0)
      limit++;
      
   //count backwards from most recent bar
   for (int i = limit-1; i >= 0; i--)
   {      
      double bopen=open[i], bclose=close[i];
      double bodyhigh=MathMax(bopen,bclose);
      double bodylow=MathMin(bopen,bclose);
      
      BodyHigh[i] = bodyhigh;
      BodyLow[i] = bodylow;
      
   }
   
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

Change Candle Size automatically when zooming in or out
Change Candle Size automatically when zooming in or out
  • 2016.03.11
  • www.mql5.com
Hi Is it possible to automatically change the Candle Size when i zoom out or zoom in...
 
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0, BodyLow);
   SetIndexBuffer(1, BodyHigh);
   Candle_Width();
   
//---
   return(INIT_SUCCEEDED);
  }
void Candle_Width()
  {
//---
   chwidth = (int)ChartGetInteger(0, CHART_SCALE);
   
   if (chwidth == 0) cwidth = 0;
   else if (chwidth == 1) cwidth = 1;
   else if (chwidth == 2) cwidth = 2;
   else if (chwidth == 3) cwidth = 3;
   else if (chwidth == 4) cwidth = 4;
   else if (chwidth == 5) cwidth = 5;  
   //we should never get here. 
   else cwidth = 1;   

   //Print(cwidth);
   
   SetIndexStyle(0, DRAW_HISTOGRAM, EMPTY, cwidth, clrOrange);
   SetIndexStyle(1, DRAW_HISTOGRAM, EMPTY, cwidth, clrOrange);
   
//---
  }
//if(ChartGetInteger(0,CHART_SCALE) != chwidth)  OnInit();
if(ChartGetInteger(0,CHART_SCALE) != chwidth)  Candle_With();
 

The problem is you should not be calling OnInit after initialization. Instead you need to use the chart event handler. Also, see correct pixels per scale ratios. 


//+------------------------------------------------------------------+
//|                                                 orangecandles.mq4 |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, bb"
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
#property indicator_chart_window

#property indicator_buffers 2

double BodyLow[], BodyHigh[];

int get_width()
{
   switch((int)ChartGetInteger(0, CHART_SCALE)){
      case 2: return 2;
      case 3: return 3;
      case 4: return 6;
      case 5: return 13;
   }
   return 1;
}
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0, BodyLow);
   SetIndexBuffer(1, BodyHigh);
   int w = get_width();
   SetIndexStyle(0, DRAW_HISTOGRAM, EMPTY, w, clrOrange);
   SetIndexStyle(1, DRAW_HISTOGRAM, EMPTY, w, clrOrange);
//---
   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 = rates_total - prev_calculated;
   if(limit < 1)
      limit = 1;
   for(int i=limit-1; i>=0; i--)
   {            
      BodyHigh[i] = fmax(open[i], close[i]);
      BodyLow[i]  = fmin(open[i], close[i]);
   }
   return(rates_total);
  }
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
{
   if(id == CHARTEVENT_CHART_CHANGE)
   {
      int w = get_width();
      SetIndexStyle(0, DRAW_HISTOGRAM, EMPTY, w, clrOrange);
      SetIndexStyle(1, DRAW_HISTOGRAM, EMPTY, w, clrOrange);
      ChartRedraw();
   }
}