//+------------------------------------------------------------------+
//| avg_period_range_1_1.mq4 |
//| Original parts from Kis_avg |
//| New functionality by Ulterior (FF) 2008 |
//+------------------------------------------------------------------+

#property indicator_chart_window
#property indicator_buffers 6
#property indicator_color1 MediumOrchid
#property indicator_color2 Aqua
#property indicator_color3 MediumOrchid
#property indicator_color4 FireBrick
#property indicator_width4 2
#property indicator_color5 FireBrick
#property indicator_width5 2

#property indicator_color6 Red
#property indicator_style6 2
//---- indicator buffers
double ExtMapBuffer1[];
double ExtMapBuffer2[];
double ExtMapBuffer3[];
double ExtMapBuffer4[];
double ExtMapBuffer5[];
double ExtMapBuffer6[];

extern int period = 28;
extern bool showMiddleOfPeriod = true;
extern bool showTodaysRange = false;
extern bool skipSundays = true;
extern bool soundAlertOnTouch = true;
extern bool sendMailOnTouch = true;

static bool BottomNotified = false;
static bool TopNotified = false;

//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
SetIndexBuffer(0, ExtMapBuffer1);
SetIndexStyle(0, DRAW_LINE);
SetIndexBuffer(1, ExtMapBuffer2);
SetIndexStyle(1, DRAW_LINE);
SetIndexBuffer(2, ExtMapBuffer3);
SetIndexStyle(2, DRAW_LINE);
SetIndexBuffer(3, ExtMapBuffer4);
SetIndexStyle(3, DRAW_LINE);
SetIndexBuffer(4, ExtMapBuffer5);
SetIndexStyle(4, DRAW_LINE);
SetIndexBuffer(5, ExtMapBuffer6);
SetIndexStyle(5, DRAW_LINE);

return(0);
}

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
Comment("");
return(0);
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
 int shift, i, CurDay, BarCount;
 double DayMax, DayMin, AvgMax, AvgMin;
 double DayOpen, DayClose, Avg;

 for (shift=Bars-1; shift>=0; shift--) 
 {
  if (CurDay != TimeDay(Time[shift])) 
  {
   int daybarshift = iBarShift( Symbol(), PERIOD_D1, Time[shift] );
   int countDays = period;
   AvgMax = 0; AvgMin = 1000;

   if( skipSundays )
   for( int l=daybarshift+period+1; l>daybarshift+1; l-- )
    if( TimeDayOfWeek( iTime( Symbol(), PERIOD_D1, l ) ) == 0 ) countDays++;

   for( int k=daybarshift+countDays+1; k>daybarshift+1; k-- )
   {
    if( skipSundays && TimeDayOfWeek( iTime( Symbol(), PERIOD_D1, k ) ) == 0 ) continue;

    if (AvgMax < iHigh( Symbol(), PERIOD_D1, k )) {AvgMax = iHigh( Symbol(), PERIOD_D1, k );}
    if (AvgMin > iLow( Symbol(), PERIOD_D1, k ))  {AvgMin = iLow( Symbol(), PERIOD_D1, k );}
   }
   
   for (i=BarCount; i>=0; i--) 
   {
    if( showTodaysRange )
    {
     ExtMapBuffer1[shift+i] = DayMax;
     ExtMapBuffer2[shift+i] = (DayMax+DayMin)/2;
     ExtMapBuffer3[shift+i] = DayMin;
    } 
    ExtMapBuffer4[shift+i] = AvgMax;
    ExtMapBuffer5[shift+i] = AvgMin;

    if( showMiddleOfPeriod )
    ExtMapBuffer6[shift+i] = AvgMin + ((AvgMax - AvgMin) / 2);
   }
   CurDay = TimeDay(Time[shift]);
   BarCount = 0;
   DayMax = 0;
   DayMin = 1000; //Заранее больше, чтоб уменьшился в процессе
   DayOpen = Open[shift];
  }
  if (DayMax < High[shift]) {DayMax = High[shift];}
  if (DayMin > Low[shift]) {DayMin = Low[shift];}
  BarCount = BarCount + 1;
 }

 // это дорисовка последнего, незавершенного еще, дня
 for (i=BarCount; i>=0; i--) 
 {
  if( showTodaysRange )
  {
   ExtMapBuffer1[shift+i] = DayMax;
   ExtMapBuffer2[shift+i] = (DayMax+DayMin)/2;
   ExtMapBuffer3[shift+i] = DayMin;
  } 
  ExtMapBuffer4[shift+i] = AvgMax;
  ExtMapBuffer5[shift+i] = AvgMin;

  if( showMiddleOfPeriod )
  ExtMapBuffer6[shift+i] = AvgMin + ((AvgMax - AvgMin) / 2);
 }
 
 DayClose = Close[0];
 Avg = (DayMax+DayMin)/2; //средняя за текущий день

 if(( Bid > AvgMax) && (TopNotified == false )) 
 {
  if( soundAlertOnTouch ) Alert(  StringConcatenate( "Average period range TOP touch on ", Symbol(), " at: ", Bid ) );
  if( sendMailOnTouch ) SendMail( StringConcatenate( "Average period range TOP touch on ", Symbol() ), StringConcatenate( "Price has reaced top of the period range at: ", Bid )  );
  TopNotified = true;
 }
 else
 if(( Bid < AvgMin) && (BottomNotified == false)) 
 {
  if( soundAlertOnTouch ) Alert(  StringConcatenate( "Average period range BOTTOM touch on ", Symbol(), " at: ", Bid ) );
  if( sendMailOnTouch ) SendMail( StringConcatenate( "Average period range BOTTOM touch on ", Symbol() ), StringConcatenate( "Price has reaced bttom of the period range at: ", Bid ) );
  BottomNotified = true;
 }
 else
 if( Bid > AvgMin && Bid < AvgMin )
 {
  TopNotified = false;
  BottomNotified = false; 
 }

 //Comment("Max:", DayMax," Min:", DayMin, "\n", "Avg:", Avg, " Width:", (DayMax-DayMin)/Point,"\n","From Avg to Open:",MathRound(MathAbs(Avg-DayOpen)/Point),"\n","From Avg to Close:",MathRound(MathAbs(Avg-DayClose)/Point));
 return(0);
}
//+------------------------------------------------------------------+ 