//+------------------------------------------------------------------+
//|                                               KeltnerChannel.mq4 |
//|                                                  Coded by Gilani |
//|                                  extended by JoeMcCool (2014/02) |
//|                      Copyright © 2005, MetaQuotes Software Corp. |
//|                                        http://www.metaquotes.net |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2005, MetaQuotes Software Corp."
#property link      "http://www.metaquotes.net"
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
#property indicator_chart_window
#property indicator_buffers 7
#property indicator_color1 Gray
#property indicator_color2 Gray
#property indicator_color3 Gray
#property indicator_color4 Gray
#property indicator_color5 Gray  
#property indicator_color6 ForestGreen  
#property indicator_color7 Red  


double upper[], middle[], lower[], hi[], lo[], overshot[], undershot[];
extern int     MA_PERIOD = 1;
extern int     MA_MODE = 0;
extern int     PRICE_MODE = 5;
extern bool    UseHiLo = true;
extern int     ATR_PERIOD = 14;
extern double  ATR_MULTIPLIER = 1.0;
extern int     Shift = 1;
extern string  DrawLinesNote = "Draw = 1, Donot draw = 12";
extern int     DrawUpperLine = 1;
extern int     DrawLowerLine = 1;
extern int     DrawMidLine = 12;
extern int     DrawHiLoLines = 12;
extern string  DrawBreakoutPointsNote = "Draw = 3, Donot draw = 12";
extern int     DrawBreakoutPoints = 3;
extern string  UCBO_Note = "only Close Breakouts = true, High/Low Breakouts = false";
extern bool    UseCloseBreakoutsOnly = true;
extern string  WindingsNote = "http://docs.mql4.com/constants/wingdings";
extern int     Windings = 164;
extern double  BreakoutPointsDistance = 0.0003;
extern bool    ATR_MODE = false;

int init()
  {
   SetIndexStyle(0,DrawUpperLine);
   SetIndexShift(0,Shift);
   SetIndexDrawBegin(0,0);
   SetIndexBuffer(0,upper);

   SetIndexStyle(1,DrawMidLine,STYLE_DOT);
   SetIndexShift(1,Shift);
   SetIndexDrawBegin(1,0);
   SetIndexBuffer(1,middle);

   SetIndexStyle(2,DrawLowerLine);
   SetIndexShift(2,Shift);
   SetIndexDrawBegin(2,0);
   SetIndexBuffer(2,lower);
   
   SetIndexStyle(3,DrawHiLoLines,STYLE_DOT);
   SetIndexShift(3,Shift);
   SetIndexDrawBegin(3,0);
   SetIndexBuffer(3,hi);
   
   SetIndexStyle(4,DrawHiLoLines,STYLE_DOT);
   SetIndexShift(4,Shift);
   SetIndexDrawBegin(4,0);
   SetIndexBuffer(4,lo);
   
   SetIndexStyle(5,DrawBreakoutPoints);
   SetIndexArrow(5,Windings);
   SetIndexShift(5,Shift);
   SetIndexBuffer(5,overshot);
   
   SetIndexStyle(6,DrawBreakoutPoints);
   SetIndexArrow(6,Windings);
   SetIndexShift(6,Shift);
   SetIndexBuffer(6,undershot);
   
   
    

//---- indicators
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custor indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
//---- TODO: add your code here
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start() {
   int limit;
   int counted_bars=IndicatorCounted();
   if(counted_bars<0) return(-1);
   if(counted_bars>0) counted_bars--;
   limit=Bars-counted_bars;
   
   double avg;
   
   for(int x=0; x<limit; x++) {
      
      middle[x] = iMA(NULL, 0, MA_PERIOD, 0, MA_MODE, PRICE_MODE, x);
      hi[x]     = iMA(NULL, 0, MA_PERIOD, 0, MA_MODE, 2, x);
      lo[x]     = iMA(NULL, 0, MA_PERIOD, 0, MA_MODE, 3, x);
      
      if (ATR_MODE)
      avg  = iATR(NULL,0,ATR_PERIOD, x);
      else 
      avg  = findAvg(ATR_PERIOD, x);
      
      if(UseHiLo==true) {
      upper[x] = hi[x] + ATR_MULTIPLIER*avg;
      lower[x] = lo[x] - ATR_MULTIPLIER*avg;
      }
      else {
      upper[x] = middle[x] + ATR_MULTIPLIER*avg;
      lower[x] = middle[x] - ATR_MULTIPLIER*avg;
      }
      
      if (UseCloseBreakoutsOnly==true) {
      if (Close[x-Shift]>upper[x])  overshot[x]  = High[x-Shift]+BreakoutPointsDistance;
      if (Close[x-Shift]<lower[x])    undershot[x] = Low[x-Shift]-BreakoutPointsDistance;
      }
      else {
      if (High[x-Shift]>upper[x])  overshot[x]  = High[x-Shift]+BreakoutPointsDistance;
      if (Low[x-Shift]<lower[x])    undershot[x] = Low[x-Shift]-BreakoutPointsDistance;
      }
   }
   return(0);
  }
//+------------------------------------------------------------------+


   double findAvg(int period, int shift) {
      double sum=0;
      for (int x=shift;x<(shift+period);x++) {     
         sum += High[x]-Low[x];
      }
      sum = sum/period;
      return (sum);
   }