//+------------------------------------------------------------------+
//|                                             Value area lines.mq4 |
//|                                                                  |
//| © 2019 hanover, calculation method from:                         |
//| https://www.linnsoft.com/techind/value-area-indicator-vau-vad    |
//|                                                                  |
//+------------------------------------------------------------------+

#property indicator_chart_window

#include <hanover --- function header (np).mqh>

extern   string   RectangleSignature     = "+val";
extern   double   StandardDeviations     = 1;
extern   bool     PriceRangeBased        = false;
extern   color    LineColor              = Gray;
extern   int      LineWidth              = 2;
extern   int      LineStyle              = STYLE_SOLID;
extern   string   RefreshPeriod          = "M1";
extern   bool     AutoAdjustRectangles   = false;

datetime   prev_time;
string     arr[20], IndiName;
int        vis, RefreshEveryXMins;
bool       FirstTime;

//+------------------------------------------------------------------+
int init() {
//+------------------------------------------------------------------+
  IndiName = "##val";
  IndicatorShortName(IndiName);
  RefreshEveryXMins = StrToTF(RefreshPeriod);
  prev_time = -9999;
  del_obj();
  plot_obj();
  return(0);
}

//+------------------------------------------------------------------+
int deinit()   {
//+------------------------------------------------------------------+
  del_obj();
  return(0);
}

//+------------------------------------------------------------------+
void del_obj()  {
//+------------------------------------------------------------------+
  int k=0;
  while (k<ObjectsTotal())   {
    string objname = ObjectName(k);
    if (StringSubstr(objname,0,StringLen(IndiName)) == IndiName)  
      ObjectDelete(objname);
    else
      k++;
  }    
  return(0);
}

//+------------------------------------------------------------------+
int start()  {
//+------------------------------------------------------------------+
  del_obj();
  plot_obj();
  return(0);
  if (RefreshEveryXMins < 0)  {
    if (FirstTime)  {
      del_obj();
      plot_obj();
    }
    FirstTime = false;      
    return(0);
  }  
  if (RefreshEveryXMins == 0) {
    del_obj();
    plot_obj();    
  } else {
    if (prev_time != iTime(Symbol(),RefreshEveryXMins,0))  {
      del_obj();
      plot_obj();
      prev_time = iTime(Symbol(),RefreshEveryXMins,0);
  } }      
  return(0);
}

//+------------------------------------------------------------------+
int plot_obj()  {
//+------------------------------------------------------------------+
  int tf    = Period();
  int total = ObjectsTotal()+10;
  for (int i=total; i>=0; i--)  {
    string objname = ObjectName(i);
    if (StringFind(objname, RectangleSignature) < 0)   continue;
    if (ObjectType(objname) != OBJ_RECTANGLE)          continue;
    int    start_bar = iBarShift(Symbol(),tf,ObjectGet(objname,OBJPROP_TIME2));
    int    end_bar   = iBarShift(Symbol(),tf,ObjectGet(objname,OBJPROP_TIME1));
    int    n=0;
    double sum_p=0, sum_p2 = 0, sum_v=0, sum_pv=0, hi=0, lo=999999;  
    for (int j=start_bar; j<=end_bar; j++)  {
      double price = iClose(Symbol(),tf,j);
      if (PriceRangeBased)
        price   = (iLow(Symbol(),tf,j)+iHigh(Symbol(),tf,j))/2;
      n++;
      sum_p    += price;
      sum_v    += iVolume(Symbol(),tf,j);
      hi        = MathMax(hi,iHigh(Symbol(),tf,j));
      lo        = MathMin(lo,iLow(Symbol(),tf,j));
//      hi        = MathMax(hi,price);
//      lo        = MathMin(lo,price);
    }
    double mean_v = DivZero(sum_v,n);

    for (j=start_bar; j<=end_bar; j++)  {
      price     = iClose(Symbol(),tf,j);
      if (PriceRangeBased)
        price   = (iLow(Symbol(),tf,j)+iHigh(Symbol(),tf,j))/2;
      sum_pv   += DivZero(price*iVolume(Symbol(),tf,j),mean_v);
    }
    double mean_p = DivZero(sum_pv,n);

    for (j=start_bar; j<=end_bar; j++)  {
      price     = iClose(Symbol(),tf,j);
      if (PriceRangeBased)
        price   = (iLow(Symbol(),tf,j)+iHigh(Symbol(),tf,j))/2;
      sum_p2   += MathPow(price-mean_p,2)*iVolume(Symbol(),tf,j);
    }
    double stddev = MathSqrt(DivZero(sum_p2,mean_v*n));
    double vau    = mean_p + stddev*StandardDeviations;
    double vad    = mean_p - stddev*StandardDeviations;
    PlotTL    (IndiName+NumberToStr(i,"'-'Z6'u'"), false, 0, Time[end_bar], vau,    Time[start_bar], vau,    LineColor, LineWidth, LineStyle, false, false, 0, "vau");       // Plot trendline
    PlotTL    (IndiName+NumberToStr(i,"'-'Z6'm'"), false, 0, Time[end_bar], mean_p, Time[start_bar], mean_p, LineColor, LineWidth, LineStyle, false, false, 0, "mean");      // Plot trendline
    PlotTL    (IndiName+NumberToStr(i,"'-'Z6'd'"), false, 0, Time[end_bar], vad,    Time[start_bar], vad,    LineColor, LineWidth, LineStyle, false, false, 0, "vad");       // Plot trendline
    if (AutoAdjustRectangles)  {
      ObjectSet(objname,OBJPROP_PRICE2,hi);
      ObjectSet(objname,OBJPROP_PRICE1,lo);
    }      
    i+=3;
  }
  return(0);
}

//+------------------------------------------------------------------+
#include <hanover --- extensible functions (np).mqh>

