TickSmoother_v1.1

Author: Copyright � 2007-08, TrendLaboratory
TickSmoother_v1.1

Overview

The TickSmoother is a specialized technical analysis tool designed for the MetaTrader platform. Unlike standard indicators that typically calculate data based on "candles" (closed price bars), this script operates at a much more granular level by analyzing individual "ticks"—the smallest possible price movements in the market.

By processing every single price change, the tool provides a smoother, more responsive visual representation of real-time price action, helping traders identify trends as they happen rather than waiting for a candle to close.

Core Functionality

1. Real-Time Tick Tracking The script captures the "Bid" price (the price at which you can sell) in real-time. It maintains a rolling history of these price points. Instead of jumping from one bar to the next, it maps out every micro-movement, providing a continuous flow of data.

2. Multi-Model Moving Averages The tool calculates two different "Moving Average" lines based on the tick data: a Fast line and a Slow line. These help traders see the immediate momentum versus the broader trend. The script allows users to choose between four different mathematical methods for calculating these averages:

  • Simple Moving Average (SMA): A basic average of price points over a specific period.
  • Exponential Moving Average (EMA): Gives more weight to recent prices, making it react faster to new changes.
  • Wilder’s Smoothing (SMMA): A smoothed average often used to reduce "noise" in volatile markets.
  • Linear Weighted Moving Average (LWMA): Applies a linear weight where the most recent price has the highest impact on the average.

3. Visual Organization and Delimiters To keep the chart organized, the script includes a visual "delimiter" system. When a new candle forms on your chart, the tool can automatically place a vertical dotted line. This helps separate different time periods visually while still maintaining the smooth, tick-based data flow between those lines.

4. Data Management & Optimization To ensure the trading platform remains fast and responsive, the script includes an automated memory management system. It only keeps a specific number of recent ticks in its active memory (customizable by the user). Once the maximum limit is reached, it clears the oldest data to prevent the software from slowing down.

Summary for the Trader

Essentially, TickSmoother acts as a high-definition lens for price action. While standard charts might show you the "big picture" of where the price ended, this tool shows you the "path" the price took to get there. It is designed to reduce the visual noise of erratic market movements, providing a clearer view of whether the current momentum is accelerating or slowing down in real-time.

Miscellaneous
Implements a curve of type %1
12 Views
0 Downloads
0 Favorites
TickSmoother_v1.1
//+------------------------------------------------------------------+
//|                                            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);
}                          

Comments