//+------------------------------------------------------------------+
//|                                                         Trix.mq4 |
//|                                                           mladen |
//+------------------------------------------------------------------+
#property copyright "www.forex-tsd.com"
#property link      "www.forex-tsd.com"

#property indicator_separate_window
#property indicator_buffers 7
#property indicator_color1  DeepSkyBlue
#property indicator_color2  DeepSkyBlue
#property indicator_color3  PaleVioletRed
#property indicator_color4  PaleVioletRed
#property indicator_color5  DimGray
#property indicator_color6  LimeGreen
#property indicator_color7  DimGray
#property indicator_width1  2
#property indicator_width3  2
#property indicator_width6  2

//
//
//
//
//

extern string TimeFrame         = "Current time frame";
extern int    TrixPeriod        = 14;
extern int    TrixPrice         = PRICE_CLOSE;
extern int    SignalPeriod      =  9;
extern int    SignalMethod      =  3;
extern bool   UseLogOfPrice     = false;
extern bool   ShowHistogram     = false;
extern bool   ShowOnlyHistogram = false;

//
//
//
//
//

double TrixBuffer[];
double SignBuffer[];
double hist[];
double histUa[];
double histUb[];
double histDa[];
double histDb[];
double tempTrix[];

bool   calculateValue;
bool   returnBars;
int    timeFrame;
string indicatorFileName;

//+------------------------------------------------------------------
//|                                                                  
//+------------------------------------------------------------------
//
//
//
//
//

int init()
{
   IndicatorBuffers(8);
      SetIndexBuffer(0,histUa);
      SetIndexBuffer(1,histUb);
      SetIndexBuffer(2,histDa);
      SetIndexBuffer(3,histDb);
      SetIndexBuffer(4,hist);
      SetIndexBuffer(5,TrixBuffer);
      SetIndexBuffer(6,SignBuffer);
      SetIndexBuffer(7,tempTrix);
      
      //
      //
      //
      //
      //
      
      for (int i=0; i<4; i++)
         if (ShowHistogram)
               SetIndexStyle(i,DRAW_HISTOGRAM);
         else  SetIndexStyle(i,DRAW_NONE);
         timeFrame      = stringToTimeFrame(TimeFrame);
         returnBars     = (TimeFrame=="returnBars");
         calculateValue = (TimeFrame=="calculateValue");
         indicatorFileName = WindowExpertName();

      //
      //
      //
      //
      //
            
   IndicatorShortName(timeFrameToString(timeFrame)+" Trix ("+TrixPeriod+")");
   return(0);
}

//+------------------------------------------------------------------
//|                                                                  
//+------------------------------------------------------------------
//
//
//
//
//

double workTrix[][7];
#define _hist  3
#define _trend 4
#define _slope 5
#define _sign  6

//
//
//
//
//

int start()
{
   double alpha = 2.0/(1.0+TrixPeriod);
   int    limit,i,r,counted_bars=IndicatorCounted();

   if(counted_bars < 0) return(-1);
   if(counted_bars>0) counted_bars--;
         limit  = MathMin(Bars-counted_bars,Bars-1);
         if (returnBars) { histUa[0] = limit+1; return(0); }

   //
   //
   //
   //
   //

   if (calculateValue || timeFrame==Period())
   {
      if (ArrayRange(workTrix,0)!=Bars) ArrayResize(workTrix,Bars);
      for(i=limit, r=Bars-i-1; i>=0; i--, r++)
      {
         double price =  iMA(NULL,0,1,0,MODE_SMA,TrixPrice,i);
         if (UseLogOfPrice) price = MathLog(price);
            workTrix[r][0] = workTrix[r-1][0]+alpha*(price         -workTrix[r-1][0]);
            workTrix[r][1] = workTrix[r-1][1]+alpha*(workTrix[r][0]-workTrix[r-1][1]);
            workTrix[r][2] = workTrix[r-1][2]+alpha*(workTrix[r][1]-workTrix[r-1][2]);
   
            //
            //
            //
            //
            //
                  
            if (workTrix[r-1][2]!=0)
                 tempTrix[i] = 10000*(workTrix[r][2]-workTrix[r-1][2])/workTrix[r-1][2];
            else tempTrix[i] = 0.00;
         
      }   
      for(i=limit, r=Bars-i-1; i>=0; i--, r++)
      {
         workTrix[r][_sign] = iMAOnArray(tempTrix,0,SignalPeriod,0,SignalMethod,i);
         workTrix[r][_hist] = tempTrix[i]-workTrix[r][_sign];
       
         //
         //
         //
         //
         //
       
         if (ShowHistogram)
         {
            histUa[i] = EMPTY_VALUE;
            histUb[i] = EMPTY_VALUE;
            histDa[i] = EMPTY_VALUE;
            histDb[i] = EMPTY_VALUE;
            workTrix[r][_trend] = workTrix[r-1][_trend];
            workTrix[r][_slope] = workTrix[r-1][_slope];
               if (workTrix[r][_hist]>0)                    workTrix[r][_trend] =  1;
               if (workTrix[r][_hist]<0)                    workTrix[r][_trend] = -1;
               if (workTrix[r][_hist]>workTrix[r-1][_hist]) workTrix[r][_slope] =  1;
               if (workTrix[r][_hist]<workTrix[r-1][_hist]) workTrix[r][_slope] = -1;
            
               if (workTrix[r][_trend]==1)
               {
                  if (workTrix[r][_slope]== 1) histUa[i] = workTrix[r][3];
                  if (workTrix[r][_slope]==-1) histUb[i] = workTrix[r][3];
               }
               if (workTrix[r][_trend]==-1)
               {
                  if (workTrix[r][_slope]== 1) histDb[i] = workTrix[r][3];
                  if (workTrix[r][_slope]==-1) histDa[i] = workTrix[r][3];
               }
               hist[i] = workTrix[r][_hist];
          }
       
          //
          //
          //
          //
          //
       
          if (!ShowOnlyHistogram || !ShowHistogram)
          {
               TrixBuffer[i] = tempTrix[i];
               SignBuffer[i] = workTrix[r][_sign];
         }
      }
      return(0);
   }            
   
   //
   //
   //
   //
   //

   limit = MathMax(limit,MathMin(Bars-1,iCustom(NULL,timeFrame,indicatorFileName,"returnBars",0,0)*timeFrame/Period()));
   for (i=limit; i>=0; i--)
   {
      int y = iBarShift(NULL,timeFrame,Time[i]);
         histUa[i]     = iCustom(NULL,timeFrame,indicatorFileName,"calculateValue",TrixPeriod,TrixPrice,SignalPeriod,SignalMethod,UseLogOfPrice,ShowHistogram,ShowOnlyHistogram,0,y);
         histUb[i]     = iCustom(NULL,timeFrame,indicatorFileName,"calculateValue",TrixPeriod,TrixPrice,SignalPeriod,SignalMethod,UseLogOfPrice,ShowHistogram,ShowOnlyHistogram,1,y);
         histDa[i]     = iCustom(NULL,timeFrame,indicatorFileName,"calculateValue",TrixPeriod,TrixPrice,SignalPeriod,SignalMethod,UseLogOfPrice,ShowHistogram,ShowOnlyHistogram,2,y);
         histDb[i]     = iCustom(NULL,timeFrame,indicatorFileName,"calculateValue",TrixPeriod,TrixPrice,SignalPeriod,SignalMethod,UseLogOfPrice,ShowHistogram,ShowOnlyHistogram,3,y);
         hist  [i]     = iCustom(NULL,timeFrame,indicatorFileName,"calculateValue",TrixPeriod,TrixPrice,SignalPeriod,SignalMethod,UseLogOfPrice,ShowHistogram,ShowOnlyHistogram,4,y);
         TrixBuffer[i] = iCustom(NULL,timeFrame,indicatorFileName,"calculateValue",TrixPeriod,TrixPrice,SignalPeriod,SignalMethod,UseLogOfPrice,ShowHistogram,ShowOnlyHistogram,5,y);
         SignBuffer[i] = iCustom(NULL,timeFrame,indicatorFileName,"calculateValue",TrixPeriod,TrixPrice,SignalPeriod,SignalMethod,UseLogOfPrice,ShowHistogram,ShowOnlyHistogram,6,y);
   }
   return(0);
}

//+-------------------------------------------------------------------
//|                                                                  
//+-------------------------------------------------------------------
//
//
//
//
//

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 char = StringGetChar(s, length);
         if((char > 96 && char < 123) || (char > 223 && char < 256))
                     s = StringSetChar(s, length, char - 32);
         else if(char > -33 && char < 0)
                     s = StringSetChar(s, length, char + 224);
   }
   return(s);
}