#property link "rodolfo.leonardo@gmail.com"
#property indicator_separate_window
#property indicator_buffers	7
#property indicator_color1		LimeGreen //C'255,255,255'   // White	   // %K line
#property indicator_color2		DarkOrange   //Yellow           // DimGray	   // %D line
#property indicator_color3		LimeGreen // C'255,255,255'  // White		// %K line of the current candle
#property indicator_color4		DarkOrange   //Yellow           // DimGray    // %D line of the current candle
#property indicator_color5    LimeGreen
#property indicator_color6    DarkOrange
#property indicator_level1		80
#property indicator_level2		20
#property indicator_level3		50
#property indicator_levelcolor DarkSlateGray
#property indicator_maximum	100
#property indicator_minimum	0

//---- input parameters
extern bool NextHigherAuto    = false;
extern bool HidePctK    = false;
extern bool HidePctD    = false;
extern int	TimeFrame	= 0,		// {1=M1, 5=M5, 15=M15, ..., 1440=D1, 10080=W1, 43200=MN1}
				KPeriod		= 21,
				DPeriod		= 5,
				Slowing		= 25,
				MAMethod		= 0,		// {0=SMA, 1=EMA, 2=SMMA, 3=LWMA}
				PriceField	= 0;		// {0=Hi/Low, 1=Close/Close}
extern bool	ShowClock	= false;	// display time to candle close countdown
extern color ClockColor	= Red;


//---- indicator buffers
double		BufferK[],
				BufferD[],
				BufferK_Curr[],
				BufferD_Curr[];
				
double g_ibuf_104[];
double g_ibuf_108[];
double g_ibuf_112[];
//----
string	IndicatorName = "",
			TimeLabelName = "";

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
{
  if ( TimeFrame == 0 )
    TimeFrame = Period();
  if ( NextHigherAuto ) TimeFrame = GetHigherTimeFrame( TimeFrame ) ;
//---- name for DataWindow and indicator subwindow label
	switch(TimeFrame)
	{
		case 1:		IndicatorName="Period M1";	break;
		case 5:		IndicatorName="Period M5"; break;
		case 15:		IndicatorName="Period M15"; break;
		case 30:		IndicatorName="Period M30"; break;
		case 60:		IndicatorName="Period H1"; break;
		case 240:	IndicatorName="Period H4"; break;
		case 1440:	IndicatorName="Period D1"; break;
		case 10080:	IndicatorName="Period W1"; break;
		case 43200:	IndicatorName="Period MN1"; break;
		default:	  {TimeFrame = Period(); init(); return(0);}
	}

	IndicatorName = IndicatorName+" Stoch("+KPeriod+","+DPeriod+","+Slowing+")";
	IndicatorShortName(IndicatorName);  
	IndicatorDigits(1);
	
   string TimeFrameStr = TF2Str(TimeFrame);
   
//---- indicator lines
	SetIndexBuffer(0,BufferK);
	SetIndexBuffer(1,BufferD);
	SetIndexBuffer(2,BufferK_Curr);
	SetIndexBuffer(3,BufferD_Curr);
 	SetIndexStyle(0,DRAW_LINE,EMPTY,1);
 	//SetIndexStyle(0,DRAW_NONE);
	SetIndexStyle(2,DRAW_LINE,EMPTY,1);
	//SetIndexStyle(2,DRAW_NONE);
	 SetIndexBuffer(4, g_ibuf_104);
   SetIndexStyle(4, DRAW_ARROW);
   SetIndexArrow(4, 108);
   SetIndexBuffer(5, g_ibuf_108);
   SetIndexStyle(5, DRAW_ARROW);
     SetIndexArrow(5, 108);
       SetIndexBuffer(6, g_ibuf_112);
	if ( ! HidePctK )
	{
	  SetIndexStyle(0,DRAW_LINE,EMPTY,1);
	  SetIndexStyle(2,DRAW_LINE,EMPTY,1);
     SetIndexLabel(0,TimeFrameStr+" %K line");
 	  SetIndexLabel(2,TimeFrameStr+" %K CurrBar");
	}
	else
	{
	  SetIndexStyle(0,DRAW_NONE);
	  SetIndexStyle(2,DRAW_NONE);
     SetIndexLabel(0,NULL);
 	  SetIndexLabel(2,NULL);
	}
	
   if ( ! HidePctD )
   {
	  SetIndexStyle(1,DRAW_LINE,EMPTY,1);
	  SetIndexStyle(3,DRAW_LINE,EMPTY,1);
     SetIndexLabel(1,TimeFrameStr+" %D Signal");
     SetIndexLabel(3,TimeFrameStr+" %D CurrBar");
	}
	else
	{
	  SetIndexStyle(1,DRAW_NONE);
	  SetIndexStyle(3,DRAW_NONE);
     SetIndexLabel(1,NULL);
     SetIndexLabel(3,NULL);
	}
}

//+------------------------------------------------------------------+
int deinit()
{
	if(TimeLabelName!="")
	if(ObjectFind	(TimeLabelName) != -1)
		ObjectDelete(TimeLabelName);
}

//+------------------------------------------------------------------+
//| MTF Stochastic                                                   |
//+------------------------------------------------------------------+
int start()
{
//----
//	counted bars from indicator time frame
	static int countedBars1 = 0;

//----
//	counted bars from display time frame
	if(Bars-1-IndicatorCounted() > 1 && countedBars1!=0)
		countedBars1 = 0;

	int bars1 = iBars(NULL,TimeFrame),
		 start1 = bars1-1-countedBars1,
		 limit1 = iBarShift(NULL,TimeFrame,Time[Bars-1]);

	if(countedBars1 != bars1-1)
	{
		countedBars1  = bars1-1;
		ArrayInitialize(BufferK_Curr,EMPTY_VALUE);
		ArrayInitialize(BufferD_Curr,EMPTY_VALUE);
		if(TimeLabelName!="")
		if(ObjectFind	(TimeLabelName) != -1)
			ObjectDelete(TimeLabelName);
	}

	if(start1 > limit1 && limit1 != -1)
		start1 = limit1;

//----
//	3... 2... 1... GO!
	for(int i = start1; i >= 0; i--)
	{
		int shift1 = i;

		if(TimeFrame < Period())
			shift1 = iBarShift(NULL,TimeFrame,Time[i]);

		int time1  = iTime    (NULL,TimeFrame,shift1),
			 shift2 = iBarShift(NULL,0,time1);

		double stochK = iStochastic(NULL,TimeFrame,KPeriod,DPeriod,Slowing,MAMethod,PriceField,0,shift1),
				 stochD = iStochastic(NULL,TimeFrame,KPeriod,DPeriod,Slowing,MAMethod,PriceField,1,shift1);

	//----
	//	old (closed) candles
		if(shift1>=1)
		{
			BufferK[shift2] = stochK;
			BufferD[shift2] = stochD;
			
			
            
		}
		
		

	//----
	//	current candle
		if((TimeFrame >=Period() && shift1<=1)
		|| (TimeFrame < Period() &&(shift1==0||shift2==1)))
		{
			BufferK_Curr[shift2] = stochK;
			BufferD_Curr[shift2] = stochD;
			
			
			 
			
            
		}

	//----
	//	linear interpolatior for the number of intermediate bars, between two higher timeframe candles.
		int n = 1;
		if(TimeFrame > Period())
		{
			int shift2prev = iBarShift(NULL,0,iTime(NULL,TimeFrame,shift1+1));

			if(shift2prev!=-1 && shift2prev!=shift2)
				n = shift2prev - shift2;
		}

	//----
	//	apply interpolation
		double factor = 1.0 / n;
		if(shift1>=1)
		if(BufferK[shift2+n]!=EMPTY_VALUE && BufferK[shift2]!=EMPTY_VALUE)
		{
			for(int k = 1; k < n; k++)
			{
				BufferK[shift2+k] = k*factor*BufferK[shift2+n] + (1.0-k*factor)*BufferK[shift2];
				BufferD[shift2+k] = k*factor*BufferD[shift2+n] + (1.0-k*factor)*BufferD[shift2];
				
			  
				 
				
			}
		}

	//----
	//	current candle
		if(shift1==0)
		if(BufferK_Curr[shift2+n]!=EMPTY_VALUE && BufferK_Curr[shift2]!=EMPTY_VALUE)
		{
			for(k = 1; k < n; k++)
			{
				BufferK_Curr[shift2+k] = k*factor*BufferK_Curr[shift2+n] + (1.0-k*factor)*BufferK_Curr[shift2];
				BufferD_Curr[shift2+k] = k*factor*BufferD_Curr[shift2+n] + (1.0-k*factor)*BufferD_Curr[shift2];
				
				
            
			}


		//----
		//	candle time countdown
			if(ShowClock)
			{
				int m,s;

				s = iTime(NULL,TimeFrame,0)+TimeFrame*60 - TimeCurrent();
				m = (s-s%60)/60;
				s = s%60;

				string text;
				if(s<10)	text = "0"+s;
				else		text = ""+s;
				text = "            "+m+":"+text;

				int window = WindowFind(IndicatorName);
				if(window==-1)
					window = WindowOnDropped() ;

				TimeLabelName = IndicatorName+" Time Counter "+window;

				if(ObjectFind	(TimeLabelName) == -1)
					ObjectCreate(TimeLabelName, OBJ_TEXT, window, Time[shift2], BufferK_Curr[shift2]+3);
				else
					ObjectMove	(TimeLabelName, 0, Time[shift2], BufferK_Curr[shift2]+3);

				ObjectSetText	(TimeLabelName, text, 8, "Verdana", ClockColor);
			}
		}
		
		
            
         
      
            
         if(TimeFrame >=Period() )
		{
		g_ibuf_104[shift2] = EMPTY_VALUE;
         g_ibuf_108[shift2] = EMPTY_VALUE;
		   g_ibuf_112[i] = g_ibuf_112[i + 1];
            if(BufferK[shift2] > BufferD[shift2]) g_ibuf_112[i] = 1;
         if(BufferK[shift2] < BufferD[shift2])g_ibuf_112[i] = -1;
         
          if (g_ibuf_112[i] != g_ibuf_112[i + 1]) {
               if (g_ibuf_112[i] == 1.0) g_ibuf_104[shift2] = BufferK[shift2];
               if (g_ibuf_112[i] == -1.0) g_ibuf_108[shift2] = BufferK[shift2];
            }
         }
         
         
	else{
	g_ibuf_104[i] = EMPTY_VALUE;
         g_ibuf_108[i] = EMPTY_VALUE;
	   g_ibuf_112[i] = g_ibuf_112[i + 1];
	   
	   if(BufferK[i] > BufferD[i]) g_ibuf_112[i] = 1;
         if(BufferK[i] < BufferD[i])g_ibuf_112[i] = -1;
         
          if (g_ibuf_112[i] != g_ibuf_112[i + 1]) {
               if (g_ibuf_112[i] == 1.0) g_ibuf_104[i] = stochK;
               if (g_ibuf_112[i] == -1.0) g_ibuf_108[i] = stochK;
            }
	}
	}

	return(0);
}

string TF2Str(int iPeriod) {
  switch(iPeriod) {
    case PERIOD_M1: return("M1");
    case PERIOD_M5: return("M5");
    case PERIOD_M15: return("M15");
    case PERIOD_M30: return("M30");
    case PERIOD_H1: return("H1");
    case PERIOD_H4: return("H4");
    case PERIOD_D1: return("D1");
    case PERIOD_W1: return("W1");
    case PERIOD_MN1: return("MN1");
    default: return("M"+iPeriod);
  }
  return(0);
}

int GetHigherTimeFrame(int CurrentPeriod )
{
  if ( CurrentPeriod == 0 ) CurrentPeriod = Period();
  if(      CurrentPeriod == 1 )     { return(5); }
  else if( CurrentPeriod == 5 )     { return(15); }
  else if( CurrentPeriod == 15 )    { return(30); }
  else if( CurrentPeriod == 30 )    { return(60); }
  else if( CurrentPeriod == 60 )    { return(240); }
  else if( CurrentPeriod == 240 )   { return(1440); }
  else if( CurrentPeriod == 1440 )  { return(10080); }
  else if( CurrentPeriod == 10080 ) { return(43200); }
  else if( CurrentPeriod == 43200 ) { return(43200); }
} // int GetHigherTimeFrame()