//+------------------------------------------------------------------+
//|                                             Color Stochastic.mq4 |
//|                                                           mladen |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "mladen"
#property link      ""

#property indicator_separate_window
#property indicator_buffers   4
#property indicator_minimum   0
#property indicator_maximum 100
#property indicator_color1 DimGray
#property indicator_style1 STYLE_DOT
#property indicator_color2 DimGray
#property indicator_color3 Lime
#property indicator_color4 Red
#property indicator_width3 2
#property indicator_width4 2

//---- input parameters
//
//    nice setings for trend = 35,10,1

extern string note1 = "Stochastic settings";
extern int       KPeriod     =  30;
extern int       Slowing     =  10;
extern int       DPeriod     =  10;

extern string note4 = "0=sma, 1=ema, 2=smma, 3=lwma";
extern int       MAMethod    =   0;

extern string note5 = "0=high/low, 1=close/close";
extern int       PriceField  =   1;

extern string note6 = "overbought level";
extern int       overBought  =  80;

extern string note7 = "oversold level";
extern int       overSold    =  20;


// === Section 1: paste this code directly BELOW the final 'extern' statement ================================================================ //
                                                                                                                                               //
extern int     AlertCandle         = 1;                                                                                                        //
extern bool    ShowChartAlerts     = true;                                                                                                     //
extern string  AlertEmailSubject   = "Stochastic Alert";                                                                                       //
                                                                                                                                               //
datetime       LastAlertTime       = -999999;                                                                                                  //
                                                                                                                                               //
string         AlertTextCrossUp    = "Stochastic cross OVERBOUGHT";      //---- type your desired text between the quotes                      //
string         AlertTextCrossDown  = "Stochastic cross OVERSOLD";        //---- type your desired text between the quotes                      //
                                                                                                                                               //
// =========================================================================================================================================== //

double KFull[];
double DFull[];
double Upper[];
double Lower[];


//+------------------------------------------------------------------+
int init()   {
//+------------------------------------------------------------------+
  SetIndexBuffer(0,DFull);
  SetIndexBuffer(1,KFull);
  SetIndexBuffer(2,Upper);
  SetIndexBuffer(3,Lower);
  SetIndexLabel(1,"Fast");
  SetIndexLabel(2,NULL);
  SetIndexLabel(3,NULL);
         
  DPeriod = MathMax(DPeriod,1);
  if (DPeriod==1) {
    SetIndexStyle(0,DRAW_NONE);
    SetIndexLabel(0,NULL);
  } else {
    SetIndexStyle(0,DRAW_LINE); 
    SetIndexLabel(0,"Slow");
  }               
         
  string shortName = "Stochastic ("+KPeriod+","+Slowing+","+DPeriod+","+maDescription(MAMethod)+","+priceDescription(PriceField);
  if (overBought < overSold) overBought = overSold;
  if (overBought < 100)      shortName  = shortName+","+overBought;
  if (overSold   >   0)      shortName  = shortName+","+overSold;
  IndicatorShortName(shortName+")");
  return(0);
}


//+------------------------------------------------------------------+
int deinit()   {
//+------------------------------------------------------------------+
  return(0);
}


//+------------------------------------------------------------------+
int start()   {
//+------------------------------------------------------------------+
  int i, limit, counted_bars=IndicatorCounted();
  if (counted_bars<0) return(-1);
  limit=Bars-counted_bars;
      
  for (i=limit; i>=0; i--)      {
    KFull[i] = iStochastic(NULL,0,KPeriod,DPeriod,Slowing,MAMethod,PriceField,MODE_MAIN,i);
    DFull[i] = iStochastic(NULL,0,KPeriod,DPeriod,Slowing,MAMethod,PriceField,MODE_SIGNAL,i);
                                 
    if (KFull[i] > overBought)   { 
      Upper[i]   = KFull[i]; 
      Upper[i+1] = KFull[i+1]; 
    } else { 
      Upper[i] = EMPTY_VALUE;
      if (Upper[i+2] == EMPTY_VALUE)
        Upper[i+1]  = EMPTY_VALUE; 
    }                            
    if (KFull[i] < overSold)   { 
      Lower[i] = KFull[i]; 
      Lower[i+1] = KFull[i+1]; 
    } else { 
      Lower[i] = EMPTY_VALUE;
      if (Lower[i+2] == EMPTY_VALUE)
        Lower[i+1]  = EMPTY_VALUE; 
    }                            
  }

// === Section 2: paste this code just BEFORE the final 'return(0)' statement in the start() module =========================================== //
                                                                                                                                                //
  ProcessAlerts();                                                                                                                              //
                                                                                                                                                //
// ============================================================================================================================================ //

   return(0);
}

//+------------------------------------------------------------------+
string priceDescription(int mode)  {
//+------------------------------------------------------------------+
  string answer;
  switch(mode)  {
    case 0:  answer = "Low/High"    ; break; 
    case 1:  answer = "Close/Close" ; break;
    default: answer = "Invalid price field requested";
             Alert(answer);
  }
  return(answer);
}

//+------------------------------------------------------------------+
string maDescription(int mode)  {
//+------------------------------------------------------------------+
  string answer;
  switch(mode)   {
    case MODE_SMA:  answer = "SMA"  ; break; 
    case MODE_EMA:  answer = "EMA"  ; break;
    case MODE_SMMA: answer = "SMMA" ; break;
    case MODE_LWMA: answer = "LWMA" ; break;
    default:        answer = "Invalid MA mode requested";
                    Alert(answer);
  }
  return(answer);
}


// === Section 3: paste this code at the end of the indicator ================================================================================= //
                                                                                                                                                //
//+------------------------------------------------------------------+                                                                          //
int ProcessAlerts()   {                                                                                                                         //
//+------------------------------------------------------------------+                                                                          //
  if (AlertCandle >= 0  &&  Time[0] > LastAlertTime)   {                                                                                        //
                                                                                                                                                //
    // === Alert processing for crossover UP (indicator line crosses ABOVE signal line) ===                                                     //
    if (KFull[AlertCandle] > overBought  &&  KFull[AlertCandle+1] <= overBought)  {                                                             //
      string AlertText = Symbol() + "," + TFToStr(Period()) + ": " + AlertTextCrossUp;                                                          //
      if (ShowChartAlerts)          Alert(AlertText);                                                                                           //
      if (AlertEmailSubject > "")   SendMail(AlertEmailSubject,AlertText);                                                                      //
      LastAlertTime = Time[0];                                                                                                                  //
    }                                                                                                                                           //
                                                                                                                                                //
    // === Alert processing for crossover DOWN (indicator line crosses BELOW signal line) ===                                                   //
    if (KFull[AlertCandle] < overSold  &&  KFull[AlertCandle+1] >= overSold)  {                                                                 //
      AlertText = Symbol() + "," + TFToStr(Period()) + ": " + AlertTextCrossDown;                                                               //
      if (ShowChartAlerts)          Alert(AlertText);                                                                                           //
      if (AlertEmailSubject > "")   SendMail(AlertEmailSubject,AlertText);                                                                      //
      LastAlertTime = Time[0];                                                                                                                  //
    }                                                                                                                                           //                                                                                                                                                //
                                                                                                                                                //
  }                                                                                                                                             //
  return(0);                                                                                                                                    //
}                                                                                                                                               //
                                                                                                                                                //
//+------------------------------------------------------------------+                                                                          //
string TFToStr(int tf)   {                                                                                                                      //
//+------------------------------------------------------------------+                                                                          //
  if (tf == 0)        tf = Period();                                                                                                            //
  if (tf >= 43200)    return("MN");                                                                                                             //
  if (tf >= 10080)    return("W1");                                                                                                             //
  if (tf >=  1440)    return("D1");                                                                                                             //
  if (tf >=   240)    return("H4");                                                                                                             //
  if (tf >=    60)    return("H1");                                                                                                             //
  if (tf >=    30)    return("M30");                                                                                                            //
  if (tf >=    15)    return("M15");                                                                                                            //
  if (tf >=     5)    return("M5");                                                                                                             //
  if (tf >=     1)    return("M1");                                                                                                             //
  return("");                                                                                                                                   //
}                                                                                                                                               //
// ============================================================================================================================================ //


