//+------------------------------------------------------------------+
//|                                         StepChartAge_v2 600+.mq4 |
//|                                Copyright © 2014, TrendLaboratory |
//|            http://finance.groups.yahoo.com/group/TrendLaboratory |
//|                                   E-mail: igorad2003@yahoo.co.uk |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2014, TrendLaboratory"
#property link      "http://finance.groups.yahoo.com/group/TrendLaboratory"

#property indicator_separate_window
#property indicator_buffers 2
#property indicator_color1 DeepSkyBlue
#property indicator_color2 Tomato
#property indicator_width1 2
#property indicator_width2 2

#property indicator_level1 0

//---- input parameters

extern int     TimeFrame      =   0;   //TimeFrame in min 
extern int     Price          =   0;   //Applied to (0...6)
extern double  StepSize       =  20;   //Size in pips
extern int     HiLoMode       =   0;   //High/Low Mode:0-off,1-on
extern int     VoltyLength    =   0;   //Volty Length(0-will be used StepSize)
extern double  VoltyRatio     =   1;   //Volty Ratio
extern double  Multiplier     =   2;   //Reversal Multiplier 
extern int     PreSmooth      =   1;   //Pre-smoothing Length 
extern int     PreSmoothMode  =   3;   //Pre-smoothing Method  
extern int     StartPriceMode =   0;   //Start Price Mode: 0-as is,1-rounded to StepSize  


//---- indicator buffers

double uptrend[];
double dntrend[];
double trend[];



double   line[2], _point;
datetime lineprevtime;
string   TF, IndicatorName;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
{
   if(TimeFrame <= Period()) TimeFrame = Period();
   IndicatorDigits(0);

//---- indicator line
   IndicatorBuffers(3);
        
   SetIndexBuffer(0,uptrend); SetIndexStyle(0,DRAW_HISTOGRAM);
   SetIndexBuffer(1,dntrend); SetIndexStyle(1,DRAW_HISTOGRAM);
   SetIndexBuffer(2,  trend);

//---- name for DataWindow and indicator subwindow label
   switch(TimeFrame)
   {
   case 1     : TF = "M1" ; break;
   case 5     : TF = "M5" ; break;
   case 15    : TF = "M15"; break;
   case 30    : TF = "M30"; break;
   case 60    : TF = "H1" ; break;
   case 240   : TF = "H4" ; break;
   case 1440  : TF = "D1" ; break;
   case 10080 : TF = "W1" ; break;
   case 43200 : TF = "MN1"; break;
   } 
   
   IndicatorName = WindowExpertName();
   string short_name = IndicatorName+"["+TF+"]("+Price+","+DoubleToStr(StepSize,2)+","+HiLoMode+","+VoltyLength+","+DoubleToStr(VoltyRatio,1)+","+DoubleToStr(Multiplier,1)+")";
   IndicatorShortName(short_name);
   
   SetIndexLabel(2,"UpTrendAge"+"["+TF+"]");
   SetIndexLabel(3,"DnTrendAge"+"["+TF+"]");
//----
   int begin = MathMax(2,Bars - iBars(NULL,TimeFrame)*TimeFrame/Period() + VoltyLength + PreSmooth); 
   SetIndexDrawBegin(0,begin);
   SetIndexDrawBegin(1,begin);
   
//----
   
   _point = MarketInfo(Symbol(),MODE_POINT) * MathPow(10,Digits%2);
   
//----
   return(0);
}

//+------------------------------------------------------------------+
//| StepChartAge_v2 600+                                             |
//+------------------------------------------------------------------+
int start()
{
   int shift,limit, counted_bars = IndicatorCounted();
    
   if(counted_bars > 0) limit = Bars - counted_bars - 1;
   if(counted_bars < 0) return(0);
   if(counted_bars < 1)
	{
   limit = Bars - 1;   
      for(int i=limit;i>=0;i--) 
      {
      uptrend[i] = EMPTY_VALUE;
      dntrend[i] = EMPTY_VALUE;
      }   
   }
	
   if(TimeFrame != Period())
	{
   limit = MathMax(limit,TimeFrame/Period());   
      
      for(shift = 0;shift < limit;shift++) 
      {	
      int y = iBarShift(NULL,TimeFrame,Time[shift]);
      
      uptrend[shift] = iCustom(NULL,TimeFrame,IndicatorName,0,Price,StepSize,HiLoMode,VoltyLength,VoltyRatio,Multiplier,PreSmooth,PreSmoothMode,StartPriceMode,0,y);   
      dntrend[shift] = iCustom(NULL,TimeFrame,IndicatorName,0,Price,StepSize,HiLoMode,VoltyLength,VoltyRatio,Multiplier,PreSmooth,PreSmoothMode,StartPriceMode,1,y);   
      }  
	return(0);
	}   
   else _StepChartAge(limit);
   
   return(0);	
}

void _StepChartAge(int limit)
{
   double volty;
     
   for(int shift = limit;shift >= 0;shift--) 
   {	
      if(lineprevtime != Time[shift])
      {
      line[1]      = line[0];   
      lineprevtime = Time[shift]; 
      }   
   
   
   line[0] = StepPrice(Price,StepSize,HiLoMode,VoltyLength,VoltyRatio,Multiplier,PreSmooth,PreSmoothMode,StartPriceMode,volty,shift);    
     
   trend[shift] = trend[shift+1];               
    
      
   if(line[0] > line[1] && trend[shift] <= 0) trend[shift] = 1;
   if(line[0] < line[1] && trend[shift] >= 0) trend[shift] =-1;    
     
      if(trend[shift] > 0) 
      {
      if(line[0] > line[1]) trend[shift] = 1; else trend[shift] += 1; 
      uptrend[shift] = trend[shift];
      dntrend[shift] = EMPTY_VALUE;
      }
      else
      if(trend[shift] < 0) 
      {
      if(line[0] < line[1]) trend[shift] =-1; else trend[shift] -= 1; 
      dntrend[shift] = trend[shift];   
      uptrend[shift] = EMPTY_VALUE;
      }    
   }      
}   


//----

int    stepprevtime, dir[2];
double sprice[2];

double StepPrice(int pricemode,double size,int hilo,int voltylen,double voltyr,double mult,int presm,int premode,int start,double& step,int bar)
{
   if(stepprevtime != Time[bar])
   {
   sprice[1]    = sprice[0];   
   dir[1]       = dir[0]; 
   stepprevtime = Time[bar]; 
   }
   
   if(voltylen > 0 && bar < Bars - MathMax(1,presm + voltylen))
   {
   double sum  = 0;
      
      if(hilo == 0)
      {
      for(int i=0;i<voltylen;i++) 
         sum += MathAbs(iMA(NULL,0,presm,0,premode,pricemode,bar+i) - iMA(NULL,0,presm,0,premode,pricemode,bar+1+i));
      }
      else
      {
      for(i=0;i<voltylen;i++) 
         sum += iMA(NULL,0,presm,0,premode,2,bar+i) - iMA(NULL,0,presm,0,premode,3,bar+i);
      }        
      
   if(size > 0) step = MathMax(size,MathRound(voltyr*sum/voltylen/_point))*_point;
   else step = MathMax(0.1,MathRound(voltyr*sum/voltylen/_point))*_point;
   }
   else 
   if(voltylen == 0) step = size*_point;
   
   
   step = NormalizeDouble(step,Digits);
    
      if(hilo == 0)
      {
      double hiprice = NormalizeDouble(iMA(NULL,0,presm,0,premode,pricemode,bar),Digits);
      double loprice = hiprice;
      }
      else
      {
      hiprice = NormalizeDouble(iMA(NULL,0,presm,0,premode,2,bar),Digits);
      loprice = NormalizeDouble(iMA(NULL,0,presm,0,premode,3,bar),Digits);
      }
  
   if(bar < Bars - MathMax(1,presm+voltylen))
   {
   sprice[0] = sprice[1];   
   dir[0]    = dir[1]; 
   
   if(dir[0] != 0) double value = NormalizeDouble(mult*step,Digits);
   else value  = NormalizeDouble(step,Digits);
   
   double price = sprice[0];
   if(hiprice > sprice[0]) price = hiprice;
   else
   if(loprice < sprice[0]) price = loprice;
      
   double hidel  = NormalizeDouble(price - sprice[0],Digits);
   double lodel  = NormalizeDouble(sprice[0] - price,Digits);
         
      if(dir[0] <= 0 && hidel < value && hidel >= 0) sprice[0] = sprice[1];
      else
      if(dir[0] >= 0 && lodel < value && lodel >= 0) sprice[0] = sprice[1];          
      else
      { 
         while(NormalizeDouble(MathAbs(price - sprice[0]),Digits) >= step) 
         {
    	      if(price > sprice[0]) sprice[0] = NormalizeDouble(sprice[0] + step,Digits);
		      if(price < sprice[0]) sprice[0] = NormalizeDouble(sprice[0] - step,Digits);
		   }
		}    
    
   double del = NormalizeDouble(sprice[0] - sprice[1],Digits);
                 
   if(del  >= value && dir[0] <= 0) dir[0] = 1;
   if(-del >= value && dir[0] >= 0) dir[0] =-1;    
         
   
   }
   else
   if(bar == Bars - MathMax(1,presm+voltylen))
   { 
      if(start == 0) sprice[0] = NormalizeDouble(iMA(NULL,0,presm,0,premode,pricemode,bar),Digits);
      else
      {
      if(step != 0.0) sprice[0] = MathRound(price/step) * step; else sprice[0] = price;         
      }
   
   dir[0] = 0;
   }
   return(sprice[0]);
}  
     