//+------------------------------------------------------------------+
//|                                               MTF_Stochastic.mq4 |
//|                                      Copyright © 2006, Keris2112 |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2006, Keris2112"
#property link      "http://www.forex-tsd.com"

#property indicator_separate_window
#property indicator_buffers 4
#property indicator_color1 LightSeaGreen
#property indicator_color2 Red
#property indicator_color3 Blue
#property indicator_color4 Red
#property indicator_level1 80
#property indicator_level2 20
#property indicator_maximum 100
#property indicator_minimum 0

//---- input parameters
/*************************************************************************
PERIOD_M1   1
PERIOD_M5   5
PERIOD_M15  15
PERIOD_M30  30 
PERIOD_H1   60
PERIOD_H4   240
PERIOD_D1   1440
PERIOD_W1   10080
PERIOD_MN1  43200
You must use the numeric value of the timeframe that you want to use
when you set the TimeFrame' value with the indicator inputs.
---------------------------------------
MODE_SMA    0 Simple moving average, 
MODE_EMA    1 Exponential moving average, 
MODE_SMMA   2 Smoothed moving average, 
MODE_LWMA   3 Linear weighted moving average. 
You must use the numeric value of the MA Method that you want to use
when you set the 'ma_method' value with the indicator inputs.

**************************************************************************/
extern string  TimeFrameCalc_Desc = "* 0=Dynamic (start from chart TF plus add timeframes), 1=Static (use static timeframe below*" ;   
extern int     TimeFrameCalc      = 0 ;  //0=when chart changes TF, indi will use chart TF plus one or more TFs e.g. M5 -> M15...otherwise 1=Uses static value below
extern int     TimeFrameAdd       = 0 ;  //If TimeFrameCalc = 0 (dynamic) add this number of timeframes to chart timeframe to give Stochastic timeframe
extern int     TimeFrameSkip      = 0;   //If TimeFrameCalc = 0 (dynamic) the next timeframe found will not include this one (e.g. 30) - leave 0 for no skip
extern int     TimeFrameStatic    = 60;  //If TimeFrameCalc = 1 then this timeframe only will be used
extern int     KPeriod=15;
extern int     DPeriod=5;
extern int     Slowing=5;
extern int     MAMethod=0;
extern int     PriceField=0;// PriceField:  0=Hi/Low   1=Close/Close

extern string note_TimeFrames = "M1;5,15,30,60H1;240H4;1440D1;10080W1;43200MN";
extern string __MA_Method = "SMA0 EMA1 SMMA2 LWMA3";
extern string __PriceField = "0=Hi/Low   1=Close/Close";
//extern string __Price = "0O,1C 2H3L,4Md 5Tp 6WghC: Md(HL/2)4,Tp(HLC/3)5,Wgh(HLCC/4)6";


double ExtMapBuffer1[];
double ExtMapBuffer2[];
double ExtMapBuffer3[];
double ExtMapBuffer4[];

datetime last_t=0;
int Periods[9] ;
int TimeFrame ;
string TimeFrameStr ;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
//---- indicator line

//---- name for DataWindow and indicator subwindow label   

   
   Periods[0] = 1 ;
   Periods[1] = 5 ;
   Periods[2] = 15 ;
   Periods[3] = 30 ;
   Periods[4] = 60 ;
   Periods[5] = 240 ;
   Periods[6] = 1440 ;  
   Periods[7] = 10080 ;
   Periods[8] = 43200 ;   

   if(TimeFrameCalc ==0)         // dynamic TF selection
   {
      int TFCount = 0 ;
      for (int tf=0; tf<=8; tf++)
      {
         if(Period() == Periods[tf])
         {         
            TFCount = tf + TimeFrameAdd ;
            break ;
         }
      }      
      
      if(Periods[TFCount] == TimeFrameSkip) 
         TimeFrame = Periods[TFCount+1] ;
      else 
         TimeFrame = Periods[TFCount] ; 
      
      if(TFCount > 8)
        TimeFrame = Periods[8] ;
   }
   else           //static TF selection
   {
      TimeFrame = TimeFrameStatic ;
   } 
   

   TimeFrameStr = tf2txt(TimeFrame) ;
   
   SetIndexBuffer(0,ExtMapBuffer1);
   SetIndexStyle(0,DRAW_LINE,EMPTY,1);
   SetIndexBuffer(1,ExtMapBuffer2);
   SetIndexStyle(1,DRAW_LINE,EMPTY,1);
   SetIndexLabel(0,  "MTF_Stochastic("+KPeriod+","+DPeriod+","+Slowing+")TF"+TimeFrame+"");
   SetIndexLabel(1,"MTF_Stochastic("+KPeriod+","+DPeriod+","+Slowing+")TF"+TimeFrame+"");
   SetIndexBuffer(2,ExtMapBuffer3);
   SetIndexStyle(2,DRAW_ARROW,EMPTY,1);
   SetIndexArrow(2,233);
   SetIndexBuffer(3,ExtMapBuffer4);
   SetIndexStyle(3,DRAW_ARROW,EMPTY,1);
   SetIndexArrow(3,234);

   
   IndicatorShortName("MTF_Stochastic("+KPeriod+","+DPeriod+","+Slowing+") "+TimeFrameStr);  
   start();
   return(0);
  }
//----
   
 
//+------------------------------------------------------------------+
//| MTF Stochastic                                                   |
//+------------------------------------------------------------------+
 int deinit()
  {
   for (int i=Bars;i>=0;i--){
      ObjectDelete("st"+Symbol()+Period()+DoubleToStr(KPeriod+DPeriod+Slowing,0)+DoubleToStr(i,0));
   }
   return(0);
  }

bool up_a=false;
bool dn_a=false;
int start()
  {
   datetime TimeArray[];
   ArrayResize(TimeArray,Bars);
   int    i,limit,y=0,counted_bars=IndicatorCounted();
    
// Plot defined timeframe on to current timeframe   
   ArrayCopySeries(TimeArray,MODE_TIME,Symbol(),TimeFrame); 
   
 //  limit=Bars-counted_bars+TimeFrame/Period(); //igorad
limit=Bars-1;
limit=MathMax(limit,TimeFrame/Period());
//limit=MathMin(limit,BarsToCount);
   for(i=0,y=0;i<limit;i++)
   {
   if (Time[i]<TimeArray[y]) y++; 
   
 /***********************************************************   
   Add your main indicator loop below.  You can reference an existing
      indicator with its iName  or iCustom.
   Rule 1:  Add extern inputs above for all neccesary values   
   Rule 2:  Use 'TimeFrame' for the indicator timeframe
   Rule 3:  Use 'y' for the indicator's shift value
 **********************************************************/  
   ExtMapBuffer3[i]=EMPTY_VALUE;  
   ExtMapBuffer4[i]=EMPTY_VALUE;
   ExtMapBuffer1[i]=EMPTY_VALUE;  
   ExtMapBuffer2[i]=EMPTY_VALUE;

   ExtMapBuffer1[i]=iStochastic(NULL,TimeFrame,KPeriod,DPeriod,Slowing,MAMethod,PriceField,0,y);
   ExtMapBuffer2[i]=iStochastic(NULL,TimeFrame,KPeriod,DPeriod,Slowing,MAMethod,PriceField,1,y);
   ObjectDelete("st"+Symbol()+Period()+DoubleToStr(KPeriod+DPeriod+Slowing,0)+DoubleToStr(i,0));   

   if (NormalizeDouble(ExtMapBuffer1[i],Digits)>NormalizeDouble(ExtMapBuffer2[i],Digits) && NormalizeDouble(ExtMapBuffer1[i+1],Digits)<=NormalizeDouble(ExtMapBuffer2[i+1],Digits)  && NormalizeDouble(ExtMapBuffer1[i+1],Digits)!=NormalizeDouble(ExtMapBuffer1[i],Digits) ){
      ExtMapBuffer3[i]=ExtMapBuffer1[i];
      ObjectDelete("st"+Symbol()+Period()+DoubleToStr(KPeriod+DPeriod+Slowing,0)+DoubleToStr(i,0));
      ObjectCreate("st"+Symbol()+Period()+DoubleToStr(KPeriod+DPeriod+Slowing,0)+DoubleToStr(i,0),22,0,Time[i],Low[i]-5*Point);
      ObjectSet("st"+Symbol()+Period()+DoubleToStr(KPeriod+DPeriod+Slowing,0)+DoubleToStr(i,0),6,Blue);
      ObjectSet("st"+Symbol()+Period()+DoubleToStr(KPeriod+DPeriod+Slowing,0)+DoubleToStr(i,0),14,233);      
   }
   if (NormalizeDouble(ExtMapBuffer1[i],Digits)<NormalizeDouble(ExtMapBuffer2[i],Digits) && NormalizeDouble(ExtMapBuffer1[i+1],Digits)>=NormalizeDouble(ExtMapBuffer2[i+1],Digits)  && NormalizeDouble(ExtMapBuffer1[i+1],Digits)!=NormalizeDouble(ExtMapBuffer1[i],Digits)){
      ExtMapBuffer4[i]=ExtMapBuffer1[i];
      ObjectDelete("st"+Symbol()+Period()+DoubleToStr(KPeriod+DPeriod+Slowing,0)+DoubleToStr(i,0));
      ObjectCreate("st"+Symbol()+Period()+DoubleToStr(KPeriod+DPeriod+Slowing,0)+DoubleToStr(i,0),22,0,Time[i],High[i]+5*Point);
      ObjectSet("st"+Symbol()+Period()+DoubleToStr(KPeriod+DPeriod+Slowing,0)+DoubleToStr(i,0),6,Red);
      ObjectSet("st"+Symbol()+Period()+DoubleToStr(KPeriod+DPeriod+Slowing,0)+DoubleToStr(i,0),14,234);      
   }
   }  
     
//
   //----  Refresh buffers ++++++++++++++ 
   if (TimeFrame < Period()) TimeFrame = Period();
   if (TimeFrame>Period()) {
     int PerINT=TimeFrame/Period()+1;
     datetime TimeArr[]; ArrayResize(TimeArr,PerINT);
     ArrayCopySeries(TimeArr,MODE_TIME,Symbol(),Period()); 
     for(i=0;i<PerINT+1;i++) {if (TimeArr[i]>=TimeArray[0]) {
 /********************************************************     
    Refresh buffers:         buffer[i] = buffer[0];
 ************************************************************/  

   ExtMapBuffer1[i]=ExtMapBuffer1[0];
   ExtMapBuffer2[i]=ExtMapBuffer2[0];

   } } }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++   Raff 

   if (ExtMapBuffer3[0]!=EMPTY_VALUE && !up_a){
      up_a=true;
      dn_a=false;    
      Alert(Symbol() + " "+ tf2txt(Period()) + " MTF Stoch Long cross");
   }
   if (ExtMapBuffer4[0]!=EMPTY_VALUE && !dn_a){
      dn_a=true;
      up_a=false;    
      Alert(Symbol() + " " + tf2txt(Period()) + " MTF Stoch Short cross");
   }

   return(0);
  }
//+------------------------------------------------------------------+

string tf2txt(int tf)
{
   switch(tf)
   {
      case 1 : return("M1"); 
      case 5 : return("M5");
      case 15 : return("M15");
      case 30 : return("M30");
      case 60 : return("H1");
      case 240 : return("H4");
      case 1440 : return("D1");
      case 10080 : return("W1");
      case 43200 : return("MN");
   } 
}
   