//+------------------------------------------------------------------+
//|                                                           VQ.mq4 |
//|                                               Volatility Quality |
//|                                     original   by raff1410@o2.pl |
//|                                     arranged   by k-matsu        |
//|                            ( http://www.age.jp/~k-matsu/FX/MT4/ )|
//+------------------------------------------------------------------+

// histgram version 1.00  2010/03/27
//                  1.01  2010/03/31 auto set level(Filter)

#property  indicator_separate_window
#property  indicator_buffers 4
#property  indicator_color1  Green
#property  indicator_color2  Red
#property  indicator_color3  Green
#property  indicator_color4  Red
#property  indicator_width1  1
#property  indicator_width2  1
#property  indicator_width3  2
#property  indicator_width4  2

extern   bool     Crash = false;

extern   int      TimeFrame = 0;
extern   int      Length = 5;
extern   int      Method = 3;
extern   int      Smoothing = 1;
extern   int      Filter = 5;

extern   bool     RealTime = true;
extern   bool     Steady  = false;
/*
extern   bool     Alerts = true;
extern   bool     EmailON = false;
extern   bool     SignalPrice = true;
extern   color    SignalPriceBUY = Yellow;
extern   color    SignalPriceSELL = Aqua;
*/

extern   int      CountBarLimit = 9000;

double   VQ[];
double   VQ_MTF[];
double   DIR[];
double   UpBuffer[];
double   DnBuffer[];
double   UpBufferFiltered[];
double   DnBufferFiltered[];

datetime timeprev1=0;
datetime timeprev2=0;
double filteredVQ;
int p=0;

string short_name;
//+------------------------------------------------------------------+

int init()
{
IndicatorBuffers(7);
SetIndexStyle(0,DRAW_HISTOGRAM,STYLE_SOLID);
SetIndexBuffer(0, UpBuffer);
SetIndexStyle(1,DRAW_HISTOGRAM,STYLE_SOLID);
SetIndexBuffer(1, DnBuffer);
SetIndexStyle(2,DRAW_HISTOGRAM,STYLE_SOLID);
SetIndexBuffer(2, UpBufferFiltered);
SetIndexStyle(3,DRAW_HISTOGRAM,STYLE_SOLID);
SetIndexBuffer(3, DnBufferFiltered);
SetIndexBuffer(4,DIR);
SetIndexBuffer(5,VQ);
SetIndexBuffer(6,VQ_MTF);

if (Length < 2) Length = 2;
if (Method < 0) Method = 0;
if (Method > 3) Method = 3;
if (Smoothing < 0) Smoothing = 0;
if (Filter < 0) Filter = 0;

if ((TimeFrame < Period()) && (TimeFrame != 0)) TimeFrame = Period();
switch(TimeFrame)
   {
   case 1:     string TimeFrameStr = "M1"; break;
   case 5:            TimeFrameStr = "M5"; break;
   case 15:           TimeFrameStr = "M15"; break;
   case 30:           TimeFrameStr = "M30"; break;
   case 60:           TimeFrameStr = "H1"; break;
   case 240:          TimeFrameStr = "H4"; break;
   case 1440:         TimeFrameStr = "D1"; break;
   case 10080:        TimeFrameStr = "W1"; break;
   case 43200:        TimeFrameStr = "MN1"; break;
   default:           TimeFrameStr = "";
   }

   short_name = "VQhist" + TimeFrameStr + " |  " + Length + " , " + Method + " , " + Smoothing + " , " + Filter + "  | ";
   IndicatorShortName(short_name);

   if (Filter > 0) {
     double FilterPoint = Filter * Point;
     SetLevelStyle(STYLE_DOT, 1, Gray);
     SetLevelValue(0, FilterPoint);
     SetLevelValue(1, -FilterPoint);
   }

return(0);
}

//+------------------------------------------------------------------+

int start()
{
if (Bars < 100) {IndicatorShortName("Bars less than 100"); return(0);}

if(timeprev1<iTime(NULL,TimeFrame,0)) {timeprev1=iTime(NULL,TimeFrame,0);}

if (!RealTime)
{
   if(timeprev2==iTime(NULL,TimeFrame,0)) return(0);
   timeprev2=iTime(NULL,TimeFrame,0);
   p=TimeFrame/Period()+1; if (p==0) p=1;
}

double TR = 0, MH = 0, ML = 0, MO = 0, MC = 0, MC1 = 0;
int i, limit, limitbase, counted_bars=IndicatorCounted();
//---- check for possible errors
if(counted_bars<0) return(-1);
//---- last counted bar will be recounted
if(counted_bars>0) counted_bars--;

if(counted_bars<1) limitbase=Bars-Length-1;
else limitbase=Bars-counted_bars;
if (limitbase>CountBarLimit) limitbase=CountBarLimit;

if (TimeFrame>Period()) i=limitbase*Period()/TimeFrame;
else i=limitbase;
while (i >= 0)
   {
   MH = iMA(NULL,TimeFrame,Length,0,Method,PRICE_HIGH,i);
   ML = iMA(NULL,TimeFrame,Length,0,Method,PRICE_LOW,i);
   MO = iMA(NULL,TimeFrame,Length,0,Method,PRICE_OPEN,i);
   if (Steady==true) {
     MC=iMA(NULL,TimeFrame,Length,0,Method,PRICE_MEDIAN,i);
     MC1=iMA(NULL,TimeFrame,Length,0,Method,PRICE_MEDIAN,i+Smoothing);
   } else {
     MC = iMA(NULL,TimeFrame,Length,0,Method,PRICE_CLOSE,i);
     MC1 = iMA(NULL,TimeFrame,Length,0,Method,PRICE_CLOSE,i + Smoothing);
   }
   VQ[i] = MathAbs(((MC - MC1) / MathMax(MH - ML,MathMax(MH - MC1,MC1 - ML)) + (MC - MO) / (MH - ML)) * 0.5) * ((MC - MC1 + (MC - MO)) * 0.5);
   if (TimeFrame > Period()) VQ_MTF[i] = VQ[i];
   i--;
   }

   if (TimeFrame>Period())
   {
     datetime TimeArray1[]; 
     ArrayCopySeries(TimeArray1,MODE_TIME,Symbol(),TimeFrame); 
     limit=limitbase+TimeFrame/Period();
     for(i=0, int y=0;i<limit;i++) {
       if (Time[i]<TimeArray1[y]) {
         y++;
       }
       VQ[i]=VQ_MTF[y];
     }
   }

limit=limitbase+TimeFrame/Period();
for (i = limit; i >= 0; i--)
   {
   filteredVQ = VQ[i];
   if (MathAbs(VQ[i]) < Filter * Point) filteredVQ=0;
   if (TimeFrame > Period()) VQ_MTF[i] = VQ[i];

   if (VQ[i] > 0)
     {
     UpBuffer[i]=VQ[i];
     DnBuffer[i]=0;
     }
   if (VQ[i] == 0)
     {
     UpBuffer[i]=0;
     DnBuffer[i]=0;
     }
   if (VQ[i] < 0)
     {
     UpBuffer[i]=0;
     DnBuffer[i]=VQ[i];
     }

   if (filteredVQ > 0)
     {
     DIR[i] = 1;
     UpBufferFiltered[i]=VQ[i];
     DnBufferFiltered[i]=0;
     }
   if (filteredVQ == 0)
     {
     DIR[i] = DIR[i + 1];
     UpBufferFiltered[i]=0;
     DnBufferFiltered[i]=0;
     }
   if (filteredVQ < 0)
     {
     DIR[i] = -1;
     UpBufferFiltered[i]=0;
     DnBufferFiltered[i]=VQ[i];
     }

   }


return(0);
}

