//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "www,forex-station.com"
#property link      "www,forex-station.com"

#property indicator_chart_window
#property indicator_buffers 6
#property indicator_color1  clrLightCyan
#property indicator_color2  clrLightCyan
#property indicator_color3  clrPeachPuff
#property indicator_color4  clrPeachPuff
#property indicator_color5  clrBlue
#property indicator_color6  clrRed
#property strict

//
//
//

enum enTimeFrames
{
         tf_cu  = 0,                                                    // Current time frame
         tf_m1  = PERIOD_M1,                                            // 1 minute
         tf_m5  = PERIOD_M5,                                            // 5 minutes
         tf_m15 = PERIOD_M15,                                           // 15 minutes
         tf_m30 = PERIOD_M30,                                           // 30 minutes
         tf_h1  = PERIOD_H1,                                            // 1 hour
         tf_h4  = PERIOD_H4,                                            // 4 hours
         tf_d1  = PERIOD_D1,                                            // Daily
         tf_w1  = PERIOD_W1,                                            // Weekly
         tf_mn1 = PERIOD_MN1,                                           // Monthly
         tf_n1  = -1,                                                   // First higher time frame
         tf_n2  = -2,                                                   // Second higher time frame
         tf_n3  = -3                                                    // Third higher time frame
      };
input enTimeFrames       inpTimeFrame  = tf_cu;                         // Time frame to use 
input int                inpAtrLength  = 14;                            // Atr length
input double             inpCoeficient = 4;                             // Atr distance
input bool               inpAutoWidth  = true;                          // Auto width
input int                inpWidth      = 3;                             // Width if auto width = false 
input bool               Interpolate   = true;                          // Interpolate in multi time frame mode?

double upL[],dnL[],fup1[],fup2[],fdn1[],fdn2[],trend[],count[]; 
struct sGlobalStruct
{
   string   indiFileName;
   int      indiTimeFrame,lim,width,scale;
   datetime _time;
};
sGlobalStruct glo;
#define _mtfCall(_buff,_ind) iCustom(_Symbol,glo.indiTimeFrame,glo.indiFileName,tf_cu,inpAtrLength,inpCoeficient,inpAutoWidth,inpWidth,_buff,_ind)

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+

int OnInit()
{
   if (inpAutoWidth)
   {
      glo.scale = int(ChartGetInteger(0,CHART_SCALE));
      switch(glo.scale) 
	   {
	      case 0: glo.width =  1; break;
	      case 1: glo.width =  1; break;
		   case 2: glo.width =  2; break;
		   case 3: glo.width =  3; break;
		   case 4: glo.width =  6; break;
		   case 5: glo.width = 14; break;
	   }
	}
	else { glo.width = inpWidth; }
   
   IndicatorBuffers(7);
   SetIndexBuffer(0,fup1,INDICATOR_DATA); SetIndexStyle(0,DRAW_HISTOGRAM,EMPTY,glo.width+2);    
   SetIndexBuffer(1,fup2,INDICATOR_DATA); SetIndexStyle(1,DRAW_HISTOGRAM,EMPTY,glo.width+2); 
   SetIndexBuffer(2,fdn1,INDICATOR_DATA); SetIndexStyle(2,DRAW_HISTOGRAM,EMPTY,glo.width+2);   
   SetIndexBuffer(3,fdn2,INDICATOR_DATA); SetIndexStyle(3,DRAW_HISTOGRAM,EMPTY,glo.width+2);  
   SetIndexBuffer(4,upL ,INDICATOR_DATA); SetIndexStyle(4,DRAW_LINE     ,EMPTY,glo.width+2);
   SetIndexBuffer(5,dnL ,INDICATOR_DATA); SetIndexStyle(5,DRAW_LINE     ,EMPTY,glo.width+2); 
   SetIndexBuffer(6,count,INDICATOR_CALCULATIONS);
   
   glo.indiFileName  = WindowExpertName();
   glo.indiTimeFrame = (enTimeFrames)timeFrameValue(inpTimeFrame);
   
   IndicatorSetString(INDICATOR_SHORTNAME,"nrtr atr stop");
return(INIT_SUCCEEDED);
}
      
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime& time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{
   glo.lim = fmin(rates_total-prev_calculated+1,rates_total-1); count[0] = glo.lim;
   ChartSetInteger(0,CHART_FOREGROUND,true); if(ChartGetInteger(0,CHART_SCALE) != glo.width) OnInit(); 
   if (glo.indiTimeFrame!=_Period)
   {
      glo.lim = (int)fmax(glo.lim,fmin(rates_total-1,_mtfCall(6,0)*glo.indiTimeFrame/_Period));
      for (int i=glo.lim;i>=0 && !_StopFlag; i--)
      {
         int y = iBarShift(_Symbol,glo.indiTimeFrame,time[i]);
            fup1[i] = _mtfCall(0,y);
            fup2[i] = _mtfCall(1,y);
            fdn1[i] = _mtfCall(2,y);
            fdn2[i] = _mtfCall(3,y);
            upL[i]  = _mtfCall(4,y);
            dnL[i]  = _mtfCall(5,y);
               
            //
            //
            //
                     
            if (!Interpolate || (i>0 && y==iBarShift(_Symbol,glo.indiTimeFrame,time[i-1]))) continue;
              #define _interpolate(buff) buff[i+k] = buff[i]+(buff[i+n]-buff[i])*k/n
              int n,k; glo._time = iTime(_Symbol,glo.indiTimeFrame,y);
              for(n = 1; (i+n)<rates_total && time[i+n] >= glo._time; n++) continue;	
              for(k = 1; k<n && (i+n)<rates_total && (i+k)<rates_total; k++) 
              {
                 if (upL[i] !=EMPTY_VALUE && upL[i+n] !=EMPTY_VALUE) _interpolate(upL);
                 if (dnL[i] !=EMPTY_VALUE && dnL[i+n] !=EMPTY_VALUE) _interpolate(dnL);
                 if (fup1[i]!=EMPTY_VALUE && fup1[i+n]!=EMPTY_VALUE) _interpolate(fup1);
                 if (fup2[i]!=EMPTY_VALUE && fup2[i+n]!=EMPTY_VALUE) _interpolate(fup2);
                 if (fdn1[i]!=EMPTY_VALUE && fdn1[i+n]!=EMPTY_VALUE) _interpolate(fdn1);
                 if (fdn2[i]!=EMPTY_VALUE && fdn2[i+n]!=EMPTY_VALUE) _interpolate(fdn2);
              }            
      }      
   return(rates_total);
   }
  
   //
   //
   //
   
   struct sWorkStruct {  double min,max,tre,smin,smax; };   
   static sWorkStruct wrk[];
   static int         wrkSize = -1;
                     if (wrkSize<=rates_total) wrkSize = ArrayResize(wrk,rates_total+500,2000); 
   
   //
   //
   //

   for(int i=glo.lim, r=rates_total-glo.lim-1; i>=0; i--,r++)
   { 
      wrk[r].smin = low[i] - inpCoeficient * iATR(_Symbol,_Period,inpAtrLength,i);  
	   wrk[r].smax = high[i]+ inpCoeficient * iATR(_Symbol,_Period,inpAtrLength,i); 
	   wrk[r].min  = iMA(_Symbol,_Period,1,0,MODE_SMA,PRICE_LOW,i);
	   wrk[r].max  = iMA(_Symbol,_Period,1,0,MODE_SMA,PRICE_HIGH,i);
	   wrk[r].tre  = (r>0) ? (high[i]>wrk[r-1].smax) ? 1 : (low[i]<wrk[r-1].smin) ? -1 : wrk[r-1].tre : 0;
	   if (r>0)
	   {
	      if (wrk[r].tre>0 && wrk[r].smin<wrk[r-1].smin) wrk[r].smin = wrk[r-1].smin;
	      if (wrk[r].tre<0 && wrk[r].smax>wrk[r-1].smax) wrk[r].smax = wrk[r-1].smax;
	   }
      upL[i] = fup1[i] = fup2[i] = dnL[i] = fdn1[i] = fdn2[i] = EMPTY_VALUE;
      if (wrk[r].tre == 1) {  upL[i] = wrk[r].smin; fup1[i] = upL[i]; fup2[i] = wrk[r].min; }
      if (wrk[r].tre ==-1) {  dnL[i] = wrk[r].smax; fdn1[i] = dnL[i]; fdn2[i] = wrk[r].max; }
   }
return(rates_total);
}

//
//
//

string sTfTable[] = {"M1","M5","M15","M30","H1","H4","D1","W1","MN"};
int    iTfTable[] = {1,5,15,30,60,240,1440,10080,43200};

string timeFrameToString(int tf)
{
   for (int i=ArraySize(iTfTable)-1; i>=0; i--) 
         if (tf==iTfTable[i]) return(sTfTable[i]);
                              return("");
}
int timeFrameValue(int _tf)
{
   int add  = (_tf>=0) ? 0 : fabs(_tf);
   if (add != 0) _tf = _Period;
   int size = ArraySize(iTfTable); 
      int i =0; for (;i<size; i++) if (iTfTable[i]==_tf) break;
                                   if (i==size) return(_Period);
                                                return(iTfTable[(int)fmin(i+add,size-1)]);
}

      
      