//+------------------------------------------------------------------+
//|                                           Damiani Volatmeter.mq5 |
//|                                        Copyright @ 2022, Centaur |
//|                           https://www.mql5.com/en/users/centaur/ |
//+------------------------------------------------------------------+
#property copyright "Copyright @ 2022, Centaur"
#property link      "https://www.mql5.com/en/users/centaur/"
#property version   "1.00"
#property indicator_separate_window
#property indicator_buffers 8
#property indicator_plots   3
//--- plot Threshold
#property indicator_label1  "Threshold"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrSilver
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- plot Vol M
#property indicator_label2  "Vol M"
#property indicator_type2   DRAW_SECTION
#property indicator_color2  clrFireBrick
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1
//--- plot Vol T
#property indicator_label3  "Vol T"
#property indicator_type3   DRAW_LINE
#property indicator_color3  clrLime
#property indicator_style3  STYLE_SOLID
#property indicator_width3  1
//--- enumerations
enum ENUM_YES_NO
  {
   Yes,
   No
  };
//--- input parameters
input int            inp_viscosity           = 7;        // Viscosity
input int            inp_sedimentation       = 40;       // Sedimentation
input double         inp_threshold_level     = 1.40;     // Threshold Level
input ENUM_YES_NO    inp_lag_suppression     = Yes;      // Lag Suppression ?
//--- indicator plot buffers
double               Threshold[];
double               Vol_M[];
double               Vol_T[];
//--- indicator calculation buffers
double               ind_c[];
double               ATR_Vis[];
double               ATR_Sed[];
double               StdDev_Vis[];
double               StdDev_Sed[];
//--- indicator variables
int                  viscosity;
int                  sedimentation;
double               threshold_level;
double               lag_s_K;
int                  ATR_Vis_Handle;
int                  ATR_Sed_Handle;
int                  StdDev_Vis_Handle;
int                  StdDev_Sed_Handle;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- check input parameters
   viscosity = inp_viscosity < 1 ? 1 : inp_viscosity;
   sedimentation = inp_sedimentation < 1 ? 1 : inp_sedimentation;
   threshold_level = inp_threshold_level < 0.01 ? 0.01 : NormalizeDouble(inp_threshold_level, 2);
   lag_s_K = 0.5;
//--- indicator buffers mapping
   SetIndexBuffer(0, Threshold, INDICATOR_DATA);
   SetIndexBuffer(1, Vol_M, INDICATOR_DATA);
   SetIndexBuffer(2, Vol_T, INDICATOR_DATA);
   SetIndexBuffer(3, ind_c, INDICATOR_CALCULATIONS);
   SetIndexBuffer(4, ATR_Vis, INDICATOR_CALCULATIONS);
   SetIndexBuffer(5, ATR_Sed, INDICATOR_CALCULATIONS);
   SetIndexBuffer(6, StdDev_Vis, INDICATOR_CALCULATIONS);
   SetIndexBuffer(7, StdDev_Sed, INDICATOR_CALCULATIONS);
//--- set indicator accuracy
   IndicatorSetInteger(INDICATOR_DIGITS, 2);
//--- set indicator name display
   string short_name = "Damiani Volatmeter (" + IntegerToString(viscosity) + ", " + IntegerToString(sedimentation) + ", " + DoubleToString(threshold_level, 2) + ", " + EnumToString(inp_lag_suppression) + ")";
   IndicatorSetString(INDICATOR_SHORTNAME, short_name);
//--- sets drawing lines to empty value
   PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   PlotIndexSetDouble(2, PLOT_EMPTY_VALUE, EMPTY_VALUE);
//--- initialize buffers
   ArrayInitialize(Threshold, EMPTY_VALUE);
   ArrayInitialize(Vol_M, EMPTY_VALUE);
   ArrayInitialize(Vol_T, EMPTY_VALUE);
   ArrayInitialize(ind_c, 0.0);
   ArrayInitialize(ATR_Vis, 0.0);
   ArrayInitialize(ATR_Sed, 0.0);
   ArrayInitialize(StdDev_Vis, 0.0);
   ArrayInitialize(StdDev_Sed, 0.0);
//--- create handles
   ATR_Vis_Handle = iATR(_Symbol, _Period, viscosity);
   ATR_Sed_Handle = iATR(_Symbol, _Period, sedimentation);
   StdDev_Vis_Handle = iStdDev(_Symbol, _Period, viscosity, 0, MODE_LWMA, PRICE_TYPICAL);
   StdDev_Sed_Handle = iStdDev(_Symbol, _Period, sedimentation, 0, MODE_LWMA, PRICE_TYPICAL);
//--- initialization succeeded
   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[])
  {
//--- check period
   if(fmax(viscosity, sedimentation) <= 1 || fmax(viscosity, sedimentation) > rates_total)
      return(0);
//--- latest data copy
   int copy;
   if(prev_calculated > rates_total || prev_calculated <= 0)
      copy = rates_total;
   else
     {
      copy = rates_total - prev_calculated;
      //--- last value is always copied
      copy++;
     }
//--- populate buffers
   if(CopyBuffer(ATR_Vis_Handle, 0, 0, copy, ATR_Vis) <= 0)
      return(0);
   if(CopyBuffer(ATR_Sed_Handle, 0, 0, copy, ATR_Sed) <= 0)
      return(0);
   if(CopyBuffer(StdDev_Vis_Handle, 0, 0, copy, StdDev_Vis) <= 0)
      return(0);
   if(CopyBuffer(StdDev_Sed_Handle, 0, 0, copy, StdDev_Sed) <= 0)
      return(0);
//--- calculate start position
   int bar;
   if(prev_calculated == 0)
      bar = 0;
   else
      bar = prev_calculated - 1;
//--- main loop
   double vol = 0.0;
   for(int i = bar; i < rates_total && !_StopFlag; i++)
     {
      if(i > fmax(viscosity, sedimentation))
        {
         double sa = ATR_Vis[i];
         double s1 = ind_c[i - 1];
         double s3 = ind_c[i - 3];
         double atr = NormalizeDouble(sa, _Digits);
         vol = inp_lag_suppression == Yes ? sa / ATR_Sed[i] + lag_s_K * (s1 - s3) : sa / ATR_Sed[i];
         double anti_thres = StdDev_Vis[i];
         anti_thres = anti_thres / StdDev_Sed[i];
         double t = threshold_level;
         t = t - anti_thres;
         Vol_M[i] = vol > t ? vol : EMPTY_VALUE;
         Vol_T[i] = vol > t ? vol : vol;
         ind_c[i] = vol;
         Threshold[i] = t;
        }
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
