//
// "00-ESV_v100.mq4" -- Exponential Smoothed Volatility
//
//    Ver. 1.00  2009/09/13(Sun)  initial version
// 
// 
#property  copyright "00"
#property  link      "http://www.mql4.com/"

//---- defines

//---- indicator settings
#property  indicator_separate_window

#property  indicator_buffers  1

#property  indicator_color1  Violet

#property  indicator_width1  1

#property  indicator_style1  STYLE_SOLID

#property indicator_level1  0.0

//---- indicator parameters
extern int  timeFrame    = 0;            // time frame
extern int  period       = 10;           // ESV period
extern int  appliedPrice = PRICE_CLOSE;  // 0:CLOSE 1:OPEN 2:HIGH 3:LOW 4:MEDIAN 5:TYPICAL 6:WEIGHTED
extern int  nMaxBars     = 20000;        // maximum number of bars to calculate, 0: no limit

//---- indicator buffers
double BufferESV[];  // 0: ESV

//---- vars
string   sIndicatorName;
string   sIndSelf         = "00-ESV_v100";

//----------------------------------------------------------------------
string TimeFrameToStr(int timeFrame)
{
    switch (timeFrame) {
    case 1:     return("M1");
    case 5:     return("M5");
    case 15:    return("M15");
    case 30:    return("M30");
    case 60:    return("H1");
    case 240:   return("H4");
    case 1440:  return("D1");
    case 10080: return("W1");
    case 43200: return("MN");
    }
    
    return("??");
}

//----------------------------------------------------------------------
void init()
{
    if (timeFrame == 0) {
	timeFrame = Period();
    }
    
    string tf = TimeFrameToStr(timeFrame);
    sIndicatorName = sIndSelf + "(" + tf + "," + period + ")";
    
    IndicatorShortName(sIndicatorName);
    
    SetIndexBuffer(0, BufferESV);
    
    SetIndexLabel(0, "ESV");
    
    SetIndexStyle(0, DRAW_LINE);
    
    SetIndexDrawBegin(0, period);
    
    int n = period;
    SetIndexDrawBegin(0, n);
}

//----------------------------------------------------------------------
void start()
{
    int limit;
    int counted_bars = IndicatorCounted();
    
    if (counted_bars > 0) {
	counted_bars--;
    }
    
    limit = Bars - counted_bars;
    int limit0 = limit;
    if (nMaxBars > 0) {
	limit = MathMin(limit, nMaxBars);
    }
    
    // clear beyond limits
    for (int i = limit0 - 1; i >= limit; i--) {
	BufferESV[i] = 0;
    }
    
    if (timeFrame != Period()) {
	// MTF
	limit = MathMax(limit, timeFrame / Period());
	for (i = limit - 1; i >= 0; i--) {
	    int x = iBarShift(NULL, timeFrame, Time[i]);
	    BufferESV[i] = iCustom(NULL, timeFrame, sIndSelf, 0, period, appliedPrice, nMaxBars, 0, x);
	}
	
	return;
    }
    
    // timeFrame == Period()
    double alpha = 2.0 / (period + 1.0);
    double beta = 1.0 - alpha;
    double v1 = 0.0;
    for (i = limit - 1; i >= 0; i--) {
	double v0 = iMA(NULL, 0, 1, 0, MODE_SMA, appliedPrice, i);
	double vola = 0;
	if (v1 != 0.0) {
	    vola = (v0 - v1) / v1;
	}
	BufferESV[i] = beta * BufferESV[i + 1] + alpha * vola;
	v1 = v0;
    }
}
