//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "www.forex-station.com"
#property link      "www.forex-station.com"

#property indicator_separate_window
#property indicator_buffers 5
#property indicator_color1  clrDeepSkyBlue
#property indicator_color2  clrPaleVioletRed
#property indicator_color3  clrMediumSeaGreen
#property indicator_width3  2
#property indicator_color4  clrOrangeRed
#property indicator_width4  2
#property indicator_color5  clrOrangeRed
#property indicator_width5  2
#property indicator_level1  50

//
//
//
//
//

extern ENUM_TIMEFRAMES TimeFrame    = PERIOD_CURRENT; // Time frame
extern int             StochK       = 14;
extern int             StochSlowing =  3;
extern int             SignalEma    =  9;
extern ENUM_STO_PRICE  Price        =  0;
extern bool            Interpolate  = true;           // Interpolate in multi time frame mode

//
//
//
//
//

double upBuffer[];
double dnBuffer[];
double miBuffer[],valda[],valdb[],valc[],count[];
string indicatorFileName;
#define _mtfCall(_buff,_ind) iCustom(NULL,TimeFrame,indicatorFileName,PERIOD_CURRENT,StochK,StochSlowing,SignalEma,Price,_buff,_ind)

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

int init()
{
   for (int i=0; i<indicator_buffers; i++) SetIndexStyle(i,DRAW_LINE);
   IndicatorBuffers(7);
   SetIndexBuffer(0,upBuffer);
   SetIndexBuffer(1,dnBuffer);
   SetIndexBuffer(2,miBuffer);
   SetIndexBuffer(3,valda);
   SetIndexBuffer(4,valdb);
   SetIndexBuffer(5,valc);
   SetIndexBuffer(6,count);
   
   indicatorFileName = WindowExpertName();
   TimeFrame         = fmax(TimeFrame,_Period); 
   
   IndicatorShortName(timeFrameToString(TimeFrame)+" ema levels - stochastic ("+StochK+","+StochSlowing+","+SignalEma+")");
   return(0);
}
int deinit() { return(0); }

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

int start()
{
   int limit,i,counted_bars=IndicatorCounted();
   
   if(counted_bars<0) return(-1);
   if(counted_bars>0) counted_bars--;
           limit=MathMin(Bars-counted_bars,Bars-1); count[0]=limit;
            if (TimeFrame!=_Period)
            {
               limit = (int)fmax(limit,fmin(Bars-1,_mtfCall(6,0)*TimeFrame/_Period));
               if (valc[limit]==-1) iCleanPoint(limit,valda,valdb); 
               for (i=limit;i>=0 && !_StopFlag; i--)
               {
                  int y = iBarShift(NULL,TimeFrame,Time[i]);
                     upBuffer[i] = _mtfCall(0,y);
                     dnBuffer[i] = _mtfCall(1,y);
                     miBuffer[i] = _mtfCall(2,y);
                     valda[i]    = valdb[i] = EMPTY_VALUE;
                     valc[i]     = _mtfCall(5,y);
                    
                     
                     //
                     //
                     //
                     //
                     //
                     
                     if (!Interpolate || (i>0 && y==iBarShift(NULL,TimeFrame,Time[i-1]))) continue;
                        #define _interpolate(buff) buff[i+k] = buff[i]+(buff[i+n]-buff[i])*k/n
                        int n,k; datetime time = iTime(NULL,TimeFrame,y);
                           for(n = 1; (i+n)<Bars && Time[i+n] >= time; n++) continue;	
                           for(k = 1; k<n && (i+n)<Bars && (i+k)<Bars; k++) 
                           {
                              _interpolate(upBuffer);
                              _interpolate(dnBuffer);
                              _interpolate(miBuffer);
                           }                           
               }
               for (i=limit;i>=0 && !_StopFlag; i--)  if (valc[i] == -1) iPlotPoint(i,valda,valdb,miBuffer); 
   return(0);
   }

   //
   //
   //
   //
   //
   
   double alpha = 2.0 / (1.0 + SignalEma);
   if (valc[limit]==-1) iCleanPoint(limit,valda,valdb);
   for(i=limit; i>=0; i--)
   {
      miBuffer[i] = iStochastic(NULL,0,StochK,1,StochSlowing,MODE_SMA,Price,MODE_MAIN,i);
      upBuffer[i] = upBuffer[i+1];
      dnBuffer[i] = dnBuffer[i+1];
         
         if (miBuffer[i]>50) upBuffer[i] = upBuffer[i+1]+alpha*(miBuffer[i]-upBuffer[i+1]);
         if (miBuffer[i]<50) dnBuffer[i] = dnBuffer[i+1]+alpha*(miBuffer[i]-dnBuffer[i+1]);
         valc[i] = (i<Bars-1) ? (miBuffer[i]>miBuffer[i+1]) ? 1 : (miBuffer[i]<miBuffer[i+1]) ? -1 : valc[i+1] : 0; 
         valda[i] = valdb[i] = EMPTY_VALUE; if (valc[i] == -1) iPlotPoint(i,valda,valdb,miBuffer);  
   }
   return(0);
}

//------------------------------------------------------------------
//
//------------------------------------------------------------------
//
//
//
//
//

void iCleanPoint(int i,double& first[],double& second[])
{
   if (i>=Bars-3) return;
   if ((second[i]  != EMPTY_VALUE) && (second[i+1] != EMPTY_VALUE))
        second[i+1] = EMPTY_VALUE;
   else
      if ((first[i] != EMPTY_VALUE) && (first[i+1] != EMPTY_VALUE) && (first[i+2] == EMPTY_VALUE))
          first[i+1] = EMPTY_VALUE;
}
void iPlotPoint(int i,double& first[],double& second[],double& from[])
{
   if (i>=Bars-2) return;
   if (first[i+1] == EMPTY_VALUE)
      if (first[i+2] == EMPTY_VALUE) 
            { first[i]  = from[i];  first[i+1]  = from[i+1]; second[i] = EMPTY_VALUE; }
      else  { second[i] =  from[i]; second[i+1] = from[i+1]; first[i]  = EMPTY_VALUE; }
   else     { first[i]  = from[i];                           second[i] = EMPTY_VALUE; }
}

//
//
//
//
//

string sTfTable[] = {"M1","M5","M15","M30","H1","H4","D1","W1","MN"};
int    iTfTable[] = {1,5,15,30,60,240,1440,10080,43200};

string timeFrameToString(int tf)
{
   for (int i=ArraySize(iTfTable)-1; i>=0; i--) 
         if (tf==iTfTable[i]) return(sTfTable[i]);
                              return("");
}


