//+------------------------------------------------------------------+
//|                                            TickSmoother_v1.1.mq4 |
//|                             Copyright © 2007-08, TrendLaboratory |
//|                          Many Thanks to Rosh for Ticks indicator |
//|            http://finance.groups.yahoo.com/group/TrendLaboratory |
//|                                   E-mail: igorad2003@yahoo.co.uk |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007-08, TrendLaboratory"
#property link      "http://finance.groups.yahoo.com/group/TrendLaboratory"


#property indicator_separate_window
#property indicator_buffers 3
#property indicator_color1 Lime
#property indicator_color2 DodgerBlue
#property indicator_color3 Tomato
//---- buffers
extern int     FastMA      =     5; //Fast MA Length(Period)
extern int     SlowMA      =    14; //Slow MA Length(Period)
extern int     MA_Mode     =     0; //MA Mode: 0-SMA,1-EMA,2-Wilder(SMMA),3-LWMA 
extern int     UseDelimiter=     1;
extern color   DelimColor  =  Gray; //Color of Bars Delimiter 
extern int     MaxTicks    =   200; //Max Number of ticks   

double Ticks[];
double Fast[];
double Slow[];


int      tickCounter=0;
int      delimeterCounter;
datetime pTime;
string   short_name, setup;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
{
//---- indicators
   SetIndexStyle(0,DRAW_LINE);
   SetIndexBuffer(0, Ticks);
   SetIndexStyle(1,DRAW_LINE);
   SetIndexBuffer(1, Fast);
   SetIndexStyle(2,DRAW_LINE);
   SetIndexBuffer(2, Slow);
   
   
   IndicatorDigits(MarketInfo(Symbol(),MODE_DIGITS)+2);
   short_name="TickSmoother_v1.1("+FastMA+","+SlowMA+","+MA_Mode+","+UseDelimiter+")";
   IndicatorShortName(short_name);
   SetIndexLabel(0,"Bid");
   SetIndexLabel(1,"Fast");
   SetIndexLabel(2,"Slow");
   
   SetIndexEmptyValue(0,0.0);
   SetIndexEmptyValue(1,0.0);
   SetIndexEmptyValue(2,0.0);
      
   setup = short_name+": ";
   pTime = Time[0];
//----
   return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
{
//----
   ObjDel(setup);
//----
   return(0);
}

void SetDelimeter()
{
//----
   string delimeterName = setup + TimeToStr(Time[0]);
   
   int handle=WindowFind(short_name);
   if(!ObjectCreate(delimeterName,OBJ_VLINE,handle,Time[0],0))
   {
   Print("Error delimiter:",GetLastError());
   }
   else 
   {
   ObjectSet(delimeterName,OBJPROP_COLOR,DelimColor);
   ObjectSet(delimeterName,OBJPROP_STYLE,STYLE_DOT);
   }
}

void ShiftArray()
{
   
   for(int cnt=tickCounter-1; cnt > 0; cnt--)
   {
   Ticks[cnt] = Ticks[cnt-1];
   Fast [cnt] = Fast[cnt-1];
   Slow [cnt] = Slow[cnt-1];
   }
   
   if (UseDelimiter!=0)
   {
      for (int j=0;j<ObjectsTotal();j++)
      {
      int NumStr = StringFind(ObjectName(j),setup,0);
      
         if (NumStr == 0)
         {
         datetime Time1=ObjectGet(ObjectName(j),OBJPROP_TIME1);
         int BarTime1=iBarShift(NULL,0,Time1);
         Time1 = Time[BarTime1+1];
         ObjectSet(ObjectName(j),OBJPROP_TIME1,Time1); 
            if( BarTime1+1 > MaxTicks )
            {
               if (!ObjectDelete(ObjectName(j)))
               {
               int _GetLastError = GetLastError();
               Print("ObjectDelete: ",ObjectName(j)," Error #", _GetLastError );
               }
            }
         }       
      }
   }      
}

bool isNewBar()
{
   bool res=false;
   if (Time[0]!=pTime)
   {
   res=true;
   pTime=Time[0];
   }   

   return(res);
}

bool ObjDel(string name)
{
   int _GetLastError = 0;
     
   while(ObjFind(name,0,0) > 0)
   {
      int obtotal = ObjectsTotal();
      for (int i = 0; i < obtotal;i++)
      {
         if (StringFind(ObjectName(i),name,0) >= 0)
         {
            if (!ObjectDelete(ObjectName(i)))
            {
            _GetLastError = GetLastError();
            Print( "ObjectDelete( \"",ObjectName(i),"\" ) - Error #", _GetLastError );
            }
         }
      }
   }      
   if(_GetLastError > 0) return(false);
   else
   return (true);
}
//-----
int ObjFind(string name,int start, int num)
{
   int cnt = 0;
   
   for (int i = 0; i < ObjectsTotal();i++)
      if (StringFind(ObjectName(i),name,start) == num) cnt+=1;
   
   return(cnt);
}         
  
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
{
   if(tickCounter == 0)
   {
      for(int i=Bars-1;i>=0;i--)
      {
      Ticks[i]= 0.0; //EMPTY_VALUE;
      Fast[i]=0.0;//EMPTY_VALUE;
      Slow[i]=0.0;//EMPTY_VALUE;//0.0;
      }
   }
   
   tickCounter++;

   if(tickCounter >= MaxTicks) 
   {
   tickCounter = MaxTicks; 
   Ticks[tickCounter]=0.0;
   Fast[tickCounter]=0.0;
   Slow[tickCounter]=0.0;
   }
   
   if (isNewBar()) {if(UseDelimiter == 1) SetDelimeter();}
   else
   ShiftArray();
      
   Ticks[0]=Bid;
   
   if(MA_Mode == 0)
   {
   if(tickCounter>=FastMA) Fast[0] = TickSMA(Ticks,FastMA);          
   if(tickCounter>=SlowMA) Slow[0] = TickSMA(Ticks,SlowMA);
   }   
   else
   if(MA_Mode == 1)
   {
   if(tickCounter == FastMA) Fast[0] = TickSMA(Ticks,FastMA);  
   else if(tickCounter > FastMA) Fast[0] = TickEMA(Ticks,Fast,FastMA);
   if(tickCounter == SlowMA) Slow[0] = TickSMA(Ticks,SlowMA);  
   else if(tickCounter > SlowMA) Slow[0] = TickEMA(Ticks,Slow,SlowMA);
   }
   else
   if(MA_Mode == 2)
   {
   if(tickCounter == 2*FastMA-1) Fast[0] = TickSMA(Ticks,2*FastMA-1);  
   else if(tickCounter > 2*FastMA-1) Fast[0] = TickEMA(Ticks,Fast,2*FastMA-1);
   if(tickCounter == 2*SlowMA-1) Slow[0] = TickSMA(Ticks,2*SlowMA-1);  
   else if(tickCounter > 2*SlowMA-1) Slow[0] = TickEMA(Ticks,Slow,2*SlowMA-1);
   }
   if(MA_Mode == 3)
   {
   if(tickCounter>=FastMA) Fast[0] = TickLWMA(Ticks,FastMA);          
   if(tickCounter>=SlowMA) Slow[0] = TickLWMA(Ticks,SlowMA);
   }   
   
//----
   return(0);
}
//+------------------------------------------------------------------+
double TickSMA(double array[],int per)
{
   double Sum = 0;
   for(int i = 0;i < per;i++) Sum += array[i];
   return(Sum/per);
}                

double TickEMA(double array1[],double array2[],int per)
{
   return(array2[1] + 2.0/(1+per)*(array1[0] - array2[1]));
}

double TickLWMA(double array[],int per)
{
   double Sum = 0;
   double Weight = 0;
   
      for(int i = 0;i < per;i++)
      { 
      Weight+= (per - i);
      Sum += array[i]*(per - i);
      }
   if(Weight>0) double lwma = Sum/Weight;
   else lwma = 0; 
   return(lwma);
}                          