#property indicator_separate_window
#property indicator_buffers    6
#property indicator_color1     clrLimeGreen
#property indicator_color2     clrRed
#property indicator_color3     clrRed
#property indicator_color4     clrSlateGray
#property indicator_color5     clrSlateGray
#property indicator_color6     clrSlateGray
#property indicator_width1     2
#property indicator_width2     2
#property indicator_width3     2
#property indicator_style4     STYLE_DASH
#property indicator_style5     STYLE_DASHDOTDOT
#property indicator_style6     STYLE_DASH
#property indicator_level1     0
#property indicator_levelcolor clrDarkOrchid

//
//
//
//
//

extern string TimeFrame                = "Current time frame";
extern int    T3Period                 = 8;
extern double T3Hot                    = 0.7;
extern bool   T3Original               = false;
extern int    VolatilityBandPeriod     = 34;
extern int    VolatilityBandMAMode     = MODE_LWMA;
extern double VolatilityBandMultiplier = 1.6185;
extern bool   MultiColor               = true;

extern bool   alertsOn                 = false;
extern bool   alertsOnCurrent          = false;
extern bool   alertsMessage            = false;
extern bool   alertsSound              = false;
extern bool   alertsEmail              = false;

extern string  __                      = "arrows settings";
extern bool   ShowArrows               = true;
extern string arrowsIdentifier         = "T3RBCI arrow";
extern color  arrowsUpColor            = clrDarkGreen;
extern color  arrowsDnColor            = clrCrimson;
extern int    UpArrowCode              = 241;
extern int    DownArrowCode            = 242;
//
//
//
//
//

double T3RBCI[], T3RBCIUa[], T3RBCIUb[], bandUp[], bandMiddle[], bandDown[], trend[];

//
//
//
//
//

string indicatorFileName;
bool   calculateValue, returnBars;
int    timeFrame;

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
//
//

int OnInit()
  {
    for (int i=0; i<indicator_buffers; i++) SetIndexStyle(i,DRAW_LINE);
  IndicatorBuffers(7);
    SetIndexBuffer(0,T3RBCI);
    SetIndexBuffer(1,T3RBCIUa);
    SetIndexBuffer(2,T3RBCIUb);
    SetIndexBuffer(3,bandUp);
    SetIndexBuffer(4,bandMiddle);
    SetIndexBuffer(5,bandDown);
    SetIndexBuffer(6,trend);
    
    //
    //
    //
    //
    //
   
      indicatorFileName = WindowExpertName();
      calculateValue    = (TimeFrame=="calculateValue"); if (calculateValue) return(0);
      returnBars        = (TimeFrame=="returnBars");     if (returnBars)     return(0);
      timeFrame         = stringToTimeFrame(TimeFrame);
   
   //
   //
   //
   //
   //
   
   IndicatorShortName(timeFrameToString(timeFrame)+"  T3 RBCI bands ");
   
 return(0);
}
    
//
//
//
//
//

int deinit(){  if (!calculateValue && ShowArrows) deleteArrows();  return(0); }

//
//
//
//
//

int start()
{
   int counted_bars=IndicatorCounted();
   int i,limit;
   
   if(counted_bars < 0) return(-1);
   if(counted_bars > 0) counted_bars--;
           limit = MathMin(Bars-counted_bars,Bars-1); 
           if (returnBars)  { T3RBCI[0] = limit+1; return(0); }
   
   //
   //
   //
   //
   //
   
   if (calculateValue || timeFrame == Period())
   {
 
   if (MultiColor && !calculateValue && trend[limit]==-1) CleanPoint(limit,T3RBCIUa,T3RBCIUb);
   
   //
   //
   //
   //
   //        
      
   for(i=limit; i>=0; i--)
   {  
           double value1 = 0.1238169269451*Close[i]
                          +0.1221983501658*Close[i+1]
                          +0.1190011430108*Close[i+2]
                          +0.1143001746257*Close[i+3]
                          +0.1082083357775*Close[i+4]
                          +0.1008691117824*Close[i+5]
                          +0.0924544579826*Close[i+6]
                          +0.0831591882460*Close[i+7]
                          +0.0731968216651*Close[i+8]
                          +0.0627911325011*Close[i+9]
                          +0.0521720176304*Close[i+10]
                          +0.0415674676220*Close[i+11]
                          +0.03120052346999*Close[i+12]
                          +0.02127741353836*Close[i+13]
                          +0.01198981966718*Close[i+14]
                          +0.00350383519239*Close[i+15]
                          -0.00404130034650*Close[i+16]
                          -0.01053553119457*Close[i+17]
                          -0.01590136845728*Close[i+18]
                          -0.02009560547438*Close[i+19]
                          -0.02310598643001*Close[i+20]
                          -0.02495565070371*Close[i+21]
                          -0.02569543732024*Close[i+22]
                          -0.02540610735631*Close[i+23]
                          -0.02418933707968*Close[i+24]
                          -0.02217041377021*Close[i+25]
                          -0.01948743120540*Close[i+26]
                          -0.01629007442301*Close[i+27]
                          -0.01273209112891*Close[i+28]
                          -0.00897092800794*Close[i+29]
                          -0.00515330395028*Close[i+30]
                          -0.001424610881936*Close[i+31]
                          +0.002089714906396*Close[i+32]
                          +0.00527492988233*Close[i+33]
                          +0.00803981322228*Close[i+34]
                          +0.01031021336959*Close[i+35]
                          +0.01203833709278*Close[i+36]
                          +0.01319390261994*Close[i+37]
                          +0.01377360958119*Close[i+38]
                          +0.01379122900470*Close[i+39]
                          +0.01328501259881*Close[i+40]
                          +0.01230273314848*Close[i+41]
                          +0.01091362242228*Close[i+42]
                          +0.00919300646953*Close[i+43]
                          +0.00722551890827*Close[i+44]
                          +0.00509973699629*Close[i+45]
                          +0.002906438043441*Close[i+46]
                          +0.000729911949400*Close[i+47]
                          -0.001346036589003*Close[i+48]
                          -0.00325210803091*Close[i+49]
                          -0.00492308867006*Close[i+50]
                          -0.00631171934917*Close[i+51]
                          -0.00737835671608*Close[i+52]
                          -0.00810443966122*Close[i+53]
                          -0.00847884560573*Close[i+54]
                          -0.00850814309603*Close[i+55]
                          -0.00820791786681*Close[i+56]
                          -0.00761322935395*Close[i+57]
                          -0.00675617201370*Close[i+58]
                          -0.00569105890365*Close[i+59]
                          -0.00446463210704*Close[i+60]
                          -0.003136445450683*Close[i+61]
                          -0.001759234808441*Close[i+62]
                          -0.000391899232101*Close[i+63]
                          +0.000916713292996*Close[i+64]
                          +0.002115501258662*Close[i+65]
                          +0.00316846373575*Close[i+66]
                          +0.00404050173851*Close[i+67]
                          +0.00471194761689*Close[i+68]
                          +0.00516189438300*Close[i+69]
                          +0.00539023783301*Close[i+70]
                          +0.00540028907392*Close[i+71]
                          +0.00520072700713*Close[i+72]
                          +0.00481262249830*Close[i+73]
                          +0.00426189211234*Close[i+74]
                          +0.00357578092340*Close[i+75]
                          +0.002792791011630*Close[i+76]
                          +0.001945190969686*Close[i+77]
                          +0.001074072336198*Close[i+78]
                          +0.0002102221385011*Close[i+79]
                          -0.000610258489301*Close[i+80]
                          -0.001362909162372*Close[i+81]
                          -0.002016921408291*Close[i+82]
                          -0.002553050522480*Close[i+83]
                          -0.002955099512448*Close[i+84]
                          -0.00322723217731*Close[i+85]
                          -0.00334694099100*Close[i+86]
                          -0.00333535479504*Close[i+87]
                          -0.00319005665285*Close[i+88]
                          -0.002930348894442*Close[i+89]
                          -0.002568261433140*Close[i+90]
                          -0.002127236248681*Close[i+91]
                          -0.001623259096604*Close[i+92]
                          -0.001082462836013*Close[i+93]
                          -0.000522606151926*Close[i+94]
                          +0.00002812805821277*Close[i+95]
                          +0.000550592842051*Close[i+96]
                          +0.001019101013467*Close[i+97]
                          +0.001432459831088*Close[i+98]
                          +0.001802313902175*Close[i+99]
                          +0.002066320467808*Close[i+100]
                          +0.002267449265120*Close[i+101]
                          +0.002390634801585*Close[i+102]
                          +0.002440016443207*Close[i+103]
                          +0.002428710369870*Close[i+104]
                          +0.002363019645587*Close[i+105]
                          +0.002261631402824*Close[i+106]
                          +0.002135750325722*Close[i+107]
                          +0.002007788917687*Close[i+108]
                          +0.001891663701696*Close[i+109]
                          +0.001811330494697*Close[i+110]
                          +0.001782108479675*Close[i+111]
                          +0.001828472108508*Close[i+112]
                          -0.00923028648226*Close[i+113];

           //
           //
           //
           //
           //
           
           double value2 = 0.0982862174*Close[i+0] 
                          +0.0975682269*Close[i+1] 
                          +0.0961401078*Close[i+2] 
                          +0.0940230544*Close[i+3] 
                          +0.0912437090*Close[i+4] 
                          +0.0878391006*Close[i+5] 
                          +0.0838544303*Close[i+6] 
                          +0.0793406350*Close[i+7] 
                          +0.0743569346*Close[i+8] 
                          +0.0689666682*Close[i+9] 
                          +0.0632381578*Close[i+10] 
                          +0.0572428925*Close[i+11] 
                          +0.0510534242*Close[i+12] 
                          +0.0447468229*Close[i+13] 
                          +0.0383959950*Close[i+14] 
                          +0.0320735368*Close[i+15] 
                          +0.0258537721*Close[i+16] 
                          +0.0198005183*Close[i+17] 
                          +0.0139807863*Close[i+18] 
                          +0.0084512448*Close[i+19] 
                          +0.0032639979*Close[i+20] 
                          -0.0015350359*Close[i+21] 
                          -0.0059060082*Close[i+22] 
                          -0.0098190256*Close[i+23] 
                          -0.0132507215*Close[i+24] 
                          -0.0161875265*Close[i+25] 
                          -0.0186164872*Close[i+26] 
                          -0.0205446727*Close[i+27] 
                          -0.0219739146*Close[i+28] 
                          -0.0229204861*Close[i+29] 
                          -0.0234080863*Close[i+30] 
                          -0.0234566315*Close[i+31] 
                          -0.0231017777*Close[i+32] 
                          -0.0223796900*Close[i+33] 
                          -0.0213300463*Close[i+34] 
                          -0.0199924534*Close[i+35] 
                          -0.0184126992*Close[i+36] 
                          -0.0166377699*Close[i+37] 
                          -0.0147139428*Close[i+38] 
                          -0.0126796776*Close[i+39] 
                          -0.0105938331*Close[i+40] 
                          -0.0084736770*Close[i+41] 
                          -0.0063841850*Close[i+42] 
                          -0.0043466731*Close[i+43] 
                          -0.0023956944*Close[i+44] 
                          -0.0005535180*Close[i+45] 
                          +0.0011421469*Close[i+46] 
                          +0.0026845693*Close[i+47] 
                          +0.0040471369*Close[i+48] 
                          +0.0052380201*Close[i+49] 
                          +0.0062194591*Close[i+50] 
                          +0.0070340085*Close[i+51] 
                          +0.0076266453*Close[i+52] 
                          +0.0080376628*Close[i+53] 
                          +0.0083037666*Close[i+54] 
                          +0.0083694798*Close[i+55] 
                          +0.0082901022*Close[i+56] 
                          +0.0080741359*Close[i+57] 
                          +0.0077543820*Close[i+58] 
                          +0.0073260526*Close[i+59] 
                          +0.0068163569*Close[i+60] 
                          +0.0062325477*Close[i+61] 
                          +0.0056078229*Close[i+62] 
                          +0.0049516078*Close[i+63] 
                          +0.0161380976*Close[i+64];
             
                          T3RBCI[i] = iT3(value1 - value2,T3Period,T3Hot,T3Original,i);

             }
             
             //
             //
             //
             //
             //
             
             for(i=limit; i>=0; i--)
             {                   
              double deviation = iStdDevOnArray(T3RBCI,0,VolatilityBandPeriod,0,VolatilityBandMAMode,i);
              double   average = iMAOnArray(T3RBCI,0,VolatilityBandPeriod,0,VolatilityBandMAMode,i);
                     bandUp[i] = average+VolatilityBandMultiplier*deviation;
                   bandDown[i] = average-VolatilityBandMultiplier*deviation;
                 bandMiddle[i] = average;
                     T3RBCIUa[i] = EMPTY_VALUE;
                     T3RBCIUb[i] = EMPTY_VALUE;
                      trend[i] = trend[i+1];
 
             //
             //
             //
             //
             //
           
             if (T3RBCI[i] > T3RBCI[i+1]) trend[i]=  1;
             if (T3RBCI[i] < T3RBCI[i+1]) trend[i]= -1;
             
             if (!calculateValue) manageArrow(i);
           
             //
             //
             //
             //
             //
           
             if (MultiColor && !calculateValue && trend[i]==-1) PlotPoint(i,T3RBCIUa,T3RBCIUb,T3RBCI);
 
             }
          
             manageAlerts();           
             return (0);
             }        

             //
             //
             //
             //
             //
             
             limit = MathMax(limit,MathMin(Bars,iCustom(NULL,timeFrame,indicatorFileName,"returnBars",0,0)*timeFrame/Period()));
             
             if (MultiColor && trend[limit]==-1) CleanPoint(limit,T3RBCIUa,T3RBCIUb);
             for (i=limit;i>=0; i--)
             {
               int y = iBarShift(NULL,timeFrame,Time[i]);
                T3RBCI[i]       = iCustom(NULL,timeFrame,indicatorFileName,"calculateValue",T3Period,T3Hot,T3Original,VolatilityBandPeriod,VolatilityBandMAMode,VolatilityBandMultiplier,0,y);
                T3RBCIUa[i]     = EMPTY_VALUE;
                T3RBCIUb[i]     = EMPTY_VALUE;
                bandUp[i]     = iCustom(NULL,timeFrame,indicatorFileName,"calculateValue",T3Period,T3Hot,T3Original,VolatilityBandPeriod,VolatilityBandMAMode,VolatilityBandMultiplier,3,y);
                bandMiddle[i] = iCustom(NULL,timeFrame,indicatorFileName,"calculateValue",T3Period,T3Hot,T3Original,VolatilityBandPeriod,VolatilityBandMAMode,VolatilityBandMultiplier,4,y);
                bandDown[i]   = iCustom(NULL,timeFrame,indicatorFileName,"calculateValue",T3Period,T3Hot,T3Original,VolatilityBandPeriod,VolatilityBandMAMode,VolatilityBandMultiplier,5,y);
                trend[i]      = iCustom(NULL,timeFrame,indicatorFileName,"calculateValue",T3Period,T3Hot,T3Original,VolatilityBandPeriod,VolatilityBandMAMode,VolatilityBandMultiplier,6,y);                
                manageArrow(i);                  
             }
    
    if (MultiColor) for (i=limit;i>=0;i--) if (trend[i]==-1) PlotPoint(i,T3RBCIUa,T3RBCIUb,T3RBCI);
    manageAlerts(); 
   
 return(0);
}

//+------------------------------------------------------------------
//|
//+------------------------------------------------------------------
//
//
//
//
//

double workT3[][6];
double workT3Coeffs[][6];
#define _period 0
#define _c1     1
#define _c2     2
#define _c3     3
#define _c4     4
#define _alpha  5

//
//
//
//
//

double iT3(double price, double period, double hot, bool original, int i, int forInstance=0)
{
   if (ArrayRange(workT3,0) !=Bars)                  ArrayResize(workT3,Bars);
   if (ArrayRange(workT3Coeffs,0) < (forInstance+1)) ArrayResize(workT3Coeffs,forInstance+1);

   if (workT3Coeffs[forInstance][_period] != period)
   {
     workT3Coeffs[forInstance][_period] = period;
        double a = hot;
            workT3Coeffs[forInstance][_c1] = -a*a*a;
            workT3Coeffs[forInstance][_c2] = 3*a*a+3*a*a*a;
            workT3Coeffs[forInstance][_c3] = -6*a*a-3*a-3*a*a*a;
            workT3Coeffs[forInstance][_c4] = 1+3*a+a*a*a+3*a*a;
            if (original)
                 workT3Coeffs[forInstance][_alpha] = 2.0/(1.0 + period);
            else workT3Coeffs[forInstance][_alpha] = 2.0/(2.0 + (period-1.0)/2.0);
   }
   
   //
   //
   //
   //
   //
   
   int buffer = forInstance*6;
   int r = Bars-i-1;
   if (r == 0)
      {
         workT3[r][0+buffer] = price;
         workT3[r][1+buffer] = price;
         workT3[r][2+buffer] = price;
         workT3[r][3+buffer] = price;
         workT3[r][4+buffer] = price;
         workT3[r][5+buffer] = price;
      }
   else
      {
         workT3[r][0+buffer] = workT3[r-1][0+buffer]+workT3Coeffs[forInstance][_alpha]*(price              -workT3[r-1][0+buffer]);
         workT3[r][1+buffer] = workT3[r-1][1+buffer]+workT3Coeffs[forInstance][_alpha]*(workT3[r][0+buffer]-workT3[r-1][1+buffer]);
         workT3[r][2+buffer] = workT3[r-1][2+buffer]+workT3Coeffs[forInstance][_alpha]*(workT3[r][1+buffer]-workT3[r-1][2+buffer]);
         workT3[r][3+buffer] = workT3[r-1][3+buffer]+workT3Coeffs[forInstance][_alpha]*(workT3[r][2+buffer]-workT3[r-1][3+buffer]);
         workT3[r][4+buffer] = workT3[r-1][4+buffer]+workT3Coeffs[forInstance][_alpha]*(workT3[r][3+buffer]-workT3[r-1][4+buffer]);
         workT3[r][5+buffer] = workT3[r-1][5+buffer]+workT3Coeffs[forInstance][_alpha]*(workT3[r][4+buffer]-workT3[r-1][5+buffer]);
      }

   //
   //
   //
   //
   //
   
   return(workT3Coeffs[forInstance][_c1]*workT3[r][5+buffer] + 
          workT3Coeffs[forInstance][_c2]*workT3[r][4+buffer] + 
          workT3Coeffs[forInstance][_c3]*workT3[r][3+buffer] + 
          workT3Coeffs[forInstance][_c4]*workT3[r][2+buffer]);
}

//
//
//
//
//

void manageAlerts()
{
   if (!calculateValue && alertsOn)
   {
      if (alertsOnCurrent)
           int whichBar = 0;
      else     whichBar = 1; whichBar = iBarShift(NULL,0,iTime(NULL,timeFrame,whichBar));
      if (trend[whichBar] != trend[whichBar+1])
      {
         if (trend[whichBar] ==  1) doAlert(whichBar,"up");
         if (trend[whichBar] == -1) doAlert(whichBar,"down");
      }
   }
}

//
//
//
//
//

void doAlert(int forBar, string doWhat)
{
   static string   previousAlert="nothing";
   static datetime previousTime;
   string message;
   
   if (previousAlert != doWhat || previousTime != Time[forBar]) {
       previousAlert  = doWhat;
       previousTime   = Time[forBar];

       //
       //
       //
       //
       //

       message =  StringConcatenate(Symbol()," ",timeFrameToString(timeFrame)," at ",TimeToStr(TimeLocal(),TIME_SECONDS)," T3RBCI changed direction to ",doWhat);
          if (alertsMessage) Alert(message);
          if (alertsEmail)   SendMail(StringConcatenate(Symbol()," T3RBCI "),message);
          if (alertsSound)   PlaySound("alert2.wav");
   }
}

//+-------------------------------------------------------------------
//|                                                                  
//+-------------------------------------------------------------------
//
//
//
//
//

void CleanPoint(int i,double& first[],double& second[])
{
   if ((second[i]  != EMPTY_VALUE) && (second[i+1] != EMPTY_VALUE))
        second[i+1] = EMPTY_VALUE;
   else
      if ((first[i] != EMPTY_VALUE) && (first[i+1] != EMPTY_VALUE) && (first[i+2] == EMPTY_VALUE))
          first[i+1] = EMPTY_VALUE;
}

//
//
//
//
//

void PlotPoint(int i,double& first[],double& second[],double& from[])
{
   if (first[i+1] == EMPTY_VALUE)
      {
         if (first[i+2] == EMPTY_VALUE) {
                first[i]   = from[i];
                first[i+1] = from[i+1];
                second[i]  = EMPTY_VALUE;
            }
         else {
                second[i]   =  from[i];
                second[i+1] =  from[i+1];
                first[i]    = EMPTY_VALUE;
            }
      }
   else
      {
         first[i]  = from[i];
         second[i] = EMPTY_VALUE;
      }
}
  
//
//
//
//
//

string sTfTable[] = {"M1","M5","M15","M30","H1","H4","D1","W1","MN"};
int    iTfTable[] = {1,5,15,30,60,240,1440,10080,43200};

//
//
//
//
//

int stringToTimeFrame(string tfs)
{
   tfs = stringUpperCase(tfs);
   for (int i=ArraySize(iTfTable)-1; i>=0; i--)
         if (tfs==sTfTable[i] || tfs==""+iTfTable[i]) return(MathMax(iTfTable[i],Period()));
                                                      return(Period());
}
string timeFrameToString(int tf)
{
   for (int i=ArraySize(iTfTable)-1; i>=0; i--) 
         if (tf==iTfTable[i]) return(sTfTable[i]);
                              return("");
}

//
//
//
//
//

string stringUpperCase(string str)
{
   string   s = str;

   for (int length=StringLen(str)-1; length>=0; length--)
   {
      int tchar = StringGetChar(s, length);
         if((tchar > 96 && tchar < 123) || (tchar > 223 && tchar < 256))
                     s = StringSetChar(s, length, tchar - 32);
         else if(tchar > -33 && tchar < 0)
                     s = StringSetChar(s, length, tchar + 224);
   }
   return(s);
}

//
//
//
//
//

void manageArrow(int i)
{
   if (ShowArrows)
   {
      deleteArrow(Time[i]);
      if (trend[i]!=trend[i+1])
      {
         if (trend[i] == 1) drawArrow(i,arrowsUpColor,UpArrowCode,false);
         if (trend[i] ==-1) drawArrow(i,arrowsDnColor,DownArrowCode,true);
      }
   }
}               

//
//
//
//
//

void drawArrow(int i,color theColor,int theCode,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);
  
         if (up)
               ObjectSet(name,OBJPROP_PRICE1,High[i]+gap);
         else  ObjectSet(name,OBJPROP_PRICE1,Low[i] -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);
}

//
//
//
//
//

