//+------------------------------------------------------------------+
//|                                                          KDJ.mq4 |
//|                                     Copyright? 2009, Walter Choy |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright? 2009, Walter Choy"
#property link      ""

#property indicator_separate_window
#property indicator_buffers 3
#property indicator_color1 Green
#property indicator_color3 Red
#property indicator_level1 0
#property indicator_level2 20
#property indicator_level3 80
#property indicator_level4 100

//---- input parameters
extern int    nPeriod          = 9;
extern double factor_1         = 0.6666666;
extern double factor_2         = 0.3333333;
extern bool   ShowArrows       = true;
extern string arrowsIdentifier = "KDJ Arrows1";
extern double arrowsUpperGap   = 1.0;
extern double arrowsLowerGap   = 1.0;
extern color  arrowsUpColor    = LimeGreen;
extern color  arrowsDnColor    = Red;
extern color  arrowsUpCode     = 241;
extern color  arrowsDnCode     = 242;
extern int    arrowsUpSize     = 2;
extern int    arrowsDnSize     = 2;
extern bool   alertsOn         = true;
extern bool   alertsOnCurrent  = false;
extern bool   alertsMessage    = true;
extern bool   alertsSound      = false;
extern bool   alertsNotify     = true;
extern bool   alertsEmail      = true;
extern string soundFile        = "alert2.wav";

//---- buffers
double percentK[];
double percentD[];
double percentJ[];
double RSV[];
double trend[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
   IndicatorBuffers(5);

//---- indicators
   SetIndexStyle(0,DRAW_LINE);
   SetIndexBuffer(0,percentK); //red
   SetIndexLabel(0, "%K");
   SetIndexStyle(1,DRAW_LINE);
   SetIndexBuffer(1,percentD);//blue
   SetIndexLabel(1, "%D");
   SetIndexStyle(2,DRAW_LINE);
   SetIndexBuffer(2,percentJ); //green
   SetIndexLabel(2, "%J");
   SetIndexBuffer(3,RSV);
   SetIndexBuffer(4,trend); 
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
{
   deleteArrows();
    
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
{
   int    counted_bars=IndicatorCounted();
//----
   int i, k, num;
   double Ln, Hn, Cn;
//----
   i = Bars - counted_bars - 1;
   num = Bars - nPeriod;
   
   while(i>=0)
     {
         Cn = iClose(NULL,0,i); Ln = iClose(NULL,0,i); Hn = iClose(NULL,0,i);
         for(k=0; k<nPeriod; k++){
            if (Ln > iLow(NULL,0,i+k)) Ln = iLow(NULL,0,i+k);
            if (Hn < iHigh(NULL,0,i+k)) Hn = iHigh(NULL,0,i+k);
         }

         if (Hn-Ln != 0) RSV[i] = (Cn-Ln)/(Hn-Ln)*100; else RSV[i] = 50;

         if (i >= num) {
            percentK[i] = factor_1 * 50 + factor_2 * RSV[i];
            percentD[i] = factor_1 * 50 + factor_2 * percentK[i];
         } else {
            percentK[i] = factor_1 * percentK[i+1] + factor_2 * RSV[i];
            percentD[i] = factor_1 * percentD[i+1] + factor_2 * percentK[i];
         }
         percentJ[i] = 3 * percentD[i] - 2 * percentK[i];
         trend[i] = trend[i+1];
         if (percentK[i]>percentD[i] && percentK[i]>percentJ[i]) trend[i] = 1;
         if (percentK[i]<percentD[i] && percentK[i]<percentJ[i]) trend[i] =-1;
         manageArrow(i); 
       i--;
     }
     
     //
     //
     //
     //
     //
     
     if (alertsOn)
     {
         if (alertsOnCurrent)
              int whichBar = 0;
         else     whichBar = 1;
         if (trend[whichBar] != trend[whichBar+1])
         if (trend[whichBar] == 1)
               doAlert("uptrend");
         else  doAlert("downtrend");       
     } 
return(0);
}

//+------------------------------------------------------------------+


void doAlert(string doWhat)
{
   static string   previousAlert="nothing";
   static datetime previousTime;
   string message;
   
      if (previousAlert != doWhat || previousTime != Time[0]) {
          previousAlert  = doWhat;
          previousTime   = Time[0];

          //
          //
          //
          //
          //

          message =  StringConcatenate(Symbol()," at ",TimeToStr(TimeLocal(),TIME_SECONDS)," KDJ ",doWhat);
             if (alertsMessage) Alert(message);
             if (alertsNotify)  SendNotification(message);
             if (alertsEmail)   SendMail(StringConcatenate(Symbol()," KDJ "),message);
             if (alertsSound)   PlaySound(soundFile);
      }
}
 
   



//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//
//
//
//

void manageArrow(int i)
{
   if (ShowArrows)
   {
      deleteArrow(Time[i]);
      if (trend[i]!=trend[i+1])
      {
         if (trend[i] == 1) drawArrow(i,arrowsUpColor,arrowsUpCode,arrowsUpSize,false);
         if (trend[i] ==-1) drawArrow(i,arrowsDnColor,arrowsDnCode,arrowsDnSize, true);
      }
   }
}               

//
//
//
//
//

//
//
//
//
//

void drawArrow(int i,color theColor,int theCode,int theWidth, bool up)
{
   string name = arrowsIdentifier+":"+Time[i];
   double gap  = iATR(NULL,0,20,i);   
   
      //
      //
      //
      //
      //
      
      ObjectCreate(name,OBJ_ARROW,0,Time[i],0);
         ObjectSet(name,OBJPROP_ARROWCODE,theCode);
         ObjectSet(name,OBJPROP_COLOR,theColor);
         ObjectSet(name,OBJPROP_WIDTH,theWidth);
         if (up)
               ObjectSet(name,OBJPROP_PRICE1,High[i] + arrowsUpperGap * gap);
         else  ObjectSet(name,OBJPROP_PRICE1,Low[i]  - arrowsLowerGap * gap);
}

//
//
//
//
//

void deleteArrows()
{
   string lookFor       = arrowsIdentifier+":";
   int    lookForLength = StringLen(lookFor);
   for (int i=ObjectsTotal()-1; i>=0; i--)
   {
      string objectName = ObjectName(i);
         if (StringSubstr(objectName,0,lookForLength) == lookFor) ObjectDelete(objectName);
   }
}

//
//
//
//
//

void deleteArrow(datetime time)
{
   string lookFor = arrowsIdentifier+":"+time; ObjectDelete(lookFor);
}
     




