//+------------------------------------------------------------------+
//|                                                 Stochastics4.mq4 |
//|                                                          k-matsu |
//|                               http://www.age.jp/~k-matsu/FX/MT4/ |
//+------------------------------------------------------------------+
#property copyright "k-matsu"
#property link      "http://www.age.jp/~k-matsu/FX/MT4/"

#property indicator_separate_window
#property indicator_minimum 0
#property indicator_maximum 100
#property indicator_buffers 4

#property indicator_color1 Green
#property indicator_color2 Red
#property indicator_color3 Magenta
#property indicator_color4 DarkOrange
#property  indicator_level1  80
#property  indicator_level2  50
#property  indicator_level3  20

//---- input parameters
extern int       KPeriod=5;
extern int       DPeriod=3;
extern int       SDPeriod=3;
extern int       SDSlowPeriod=3;
extern string    PriceFieldHelp="Price field parameter. Can be one of this values: 0 - Low/High or 1 - Close/Close.";
extern int       PriceField=0;
extern string    MAMethodHelp="MA method. It can be any of Moving Average method enumeration value.";
extern int       SDMAMethod=MODE_SMA;
extern int       SDSlowMAMethod=MODE_SMA;
/*
extern bool      GuideLabel=true;
extern int       Guide_ymargin = 0;
*/
//---- buffers
double KBuffer[];
double DBuffer[];
double SDBuffer[];
double SDSlowBuffer[];
//---- temporary buffers
double DenominatorsBuffer[];
double ElementsBuffer[];
//---- indicator name
string shortname_base="Stochastics4";
string shortname;

// subroutine
/*
int createGuideLabel(string subname, int corner, int xdistance, int ydistance, string text, int fontsize, string font, color textcolor)
{
  string objectname = shortname+subname;
  ObjectCreate(objectname, OBJ_LABEL, WindowOnDropped(), 0, 0);
   ObjectSet(objectname, OBJPROP_CORNER,corner);
   ObjectSet(objectname, OBJPROP_XDISTANCE, xdistance);
   ObjectSet(objectname, OBJPROP_YDISTANCE, ydistance);
   ObjectSetText(objectname, text, fontsize, font, textcolor);
}
*/
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
//---- indicators
   IndicatorBuffers(6);
   SetIndexStyle(0,DRAW_LINE);
   SetIndexBuffer(0,KBuffer);
   SetIndexLabel(0,"%K(Period:"+KPeriod+")");
   SetIndexStyle(1,DRAW_LINE);
   SetIndexBuffer(1,DBuffer);
   SetIndexLabel(1,"%D(Period:"+DPeriod+")");
   SetIndexStyle(2,DRAW_LINE);
   SetIndexBuffer(2,SDBuffer);
   SetIndexLabel(2,"SD(Period:"+SDPeriod+")");
   SetIndexStyle(3,DRAW_LINE);
   SetIndexBuffer(3,SDSlowBuffer);
   SetIndexLabel(3,"SD slow(Period:"+SDSlowPeriod+")");
   SetIndexBuffer(4,DenominatorsBuffer);
   SetIndexBuffer(5,ElementsBuffer);

   shortname = shortname_base+" ("+KPeriod+","+DPeriod+","+SDPeriod+","+SDSlowPeriod+")";
   IndicatorShortName(shortname);

   // parameter check
   if (KPeriod < 1) KPeriod = 1;
   if (DPeriod < 1) DPeriod = 1;
   if (SDPeriod < 1) SDPeriod = 1;
   if (SDSlowPeriod < 1) SDPeriod = 1;
   if (PriceField != 1) PriceField = 0;
   if (SDMAMethod < 0 || SDMAMethod > 3) SDMAMethod = 0;
   if (SDSlowMAMethod < 0 || SDSlowMAMethod > 3) SDSlowMAMethod = 0;

/*
   // label
   if (GuideLabel == true) {
     createGuideLabel("Kline",       1, 54, Guide_ymargin+ 0, "___", 8, "Arial", indicator_color1);
     createGuideLabel("Kguide",      1, 24, Guide_ymargin+ 5, "%K("+KPeriod+")", 8, "Arial", White);
     createGuideLabel("Dline",       1, 54, Guide_ymargin+10, "___", 8, "Arial", indicator_color2);
     createGuideLabel("Dguide",      1, 24, Guide_ymargin+15, "%D("+DPeriod+")", 8, "Arial", White);
     createGuideLabel("SDline",      1, 54, Guide_ymargin+20, "___", 8, "Arial", indicator_color3);
     createGuideLabel("SDguide",     1, 26, Guide_ymargin+25, "SD("+SDPeriod+")", 8, "Arial", White);
     createGuideLabel("SDSlowline",  1, 54, Guide_ymargin+30, "___", 8, "Arial", indicator_color4);
     createGuideLabel("SDSlowguide", 1,  2, Guide_ymargin+35, "SDSlow("+SDPeriod+")", 8, "Arial", White);
   } else {
     // delete labels
     int shortname_length=StringLen(shortname);
     for(int i = ObjectsTotal() - 1; i >= 0; i--) {
       string label = ObjectName(i);
       if(StringSubstr(label, 0, shortname_length) == shortname)
         ObjectDelete(label);   
     }
   }
*/

//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
   int    i,j,limit,Dlimit,SDlimit,SDSlowlimit;
   int    counted_bars=IndicatorCounted();
   double hx,lx;
//---- last counted bar will be recounted
   if(counted_bars>0) counted_bars--;
   if(counted_bars<KPeriod) counted_bars=KPeriod;
   limit=Bars-counted_bars;
   Dlimit=Bars - KPeriod - DPeriod + 1;
   SDlimit = Dlimit - SDPeriod + 1;
   SDSlowlimit = SDlimit - SDSlowPeriod + 1;
   for (i=limit; i>=0; i--) {
     // %K
     if (PriceField == 1) {
       hx = Close[iHighest(NULL, 0, MODE_CLOSE, KPeriod, i)];
       lx = Close[iLowest(NULL, 0, MODE_CLOSE, KPeriod, i)];
     } else {
       hx = High[iHighest(NULL, 0, MODE_HIGH, KPeriod, i)];
       lx = Low[iLowest(NULL, 0, MODE_LOW, KPeriod, i)];
     }
     DenominatorsBuffer[i] = hx - lx;
     ElementsBuffer[i] = Close[i]-lx;
     if (DenominatorsBuffer[i] != 0) {
       KBuffer[i]=100*ElementsBuffer[i]/DenominatorsBuffer[i];
     } else {
       KBuffer[i]=0;
     }

     // %d
     if (i <= Dlimit ) {
       double ddeno = 0;
       double delm = 0;
       for (j=i; j<i+DPeriod; j++) {
         ddeno += DenominatorsBuffer[j];
         delm += ElementsBuffer[j]; 
       }
       if (ddeno != 0) {
         DBuffer[i]=100*delm/ddeno;
       } else {
         DBuffer[i]=0;
       }
     }
   }

   // SD
   for (i=limit; i>=0; i--) {
     if (i <= SDlimit ) {
       SDBuffer[i]=iMAOnArray(DBuffer, 0, SDPeriod, 0, SDMAMethod, i);
     }
   }

   // SD slow
   for (i=limit; i>=0; i--) {
     if (i <= SDSlowlimit ) {
       SDSlowBuffer[i]=iMAOnArray(SDBuffer, 0, SDSlowPeriod, 0, SDSlowMAMethod, i);
     }
   }

//----
   return(0);
  }
//+------------------------------------------------------------------+