//------------------------------------------------------------------
#property link      "www.forex-station.com"
#property copyright "www.forex-station.com"
//------------------------------------------------------------------
#property indicator_separate_window
#property strict
#property indicator_buffers 5
#property indicator_label1  "Blau TVI strong up"
#property indicator_type1   DRAW_HISTOGRAM
#property indicator_color1  clrDodgerBlue
#property indicator_width1  3
#property indicator_label2  "Blau TVI weak up"
#property indicator_type2   DRAW_HISTOGRAM
#property indicator_color2  clrDodgerBlue
#property indicator_label3  "Blau TVI strong down"
#property indicator_type3   DRAW_HISTOGRAM
#property indicator_color3  clrRed
#property indicator_width3  3
#property indicator_label4  "Blau TVI weak down"
#property indicator_type4   DRAW_HISTOGRAM
#property indicator_color4  clrRed
#property indicator_label5  "Blau TVI"
#property indicator_type5   DRAW_LINE
#property indicator_color5  clrOrangeRed
#property indicator_width5  1

//
//
//

input int             tr     = 12;              // Period 1
input int             s      = 12;              // Period 2
input int             u      = 5;               // Period 3
input double          levUp  = 4.0;             // Upper level
input double          levDn  = -4.0;            // Lower level
input color           levClr = clrMediumOrchid; // Level color
input ENUM_LINE_STYLE levSty = STYLE_DOT;       // Level style 

double huu[],hud[],hdd[],hdu[],val[],valc[];

//------------------------------------------------------------------
//
//------------------------------------------------------------------

int OnInit()
{
   IndicatorBuffers(6);
   SetIndexBuffer(0,huu,INDICATOR_DATA); 
   SetIndexBuffer(1,hud,INDICATOR_DATA); 
   SetIndexBuffer(2,hdd,INDICATOR_DATA);
   SetIndexBuffer(3,hdu,INDICATOR_DATA);
   SetIndexBuffer(4,val,INDICATOR_DATA);
   SetIndexBuffer(5,valc);
   
   ema1.init(tr);
   ema2.init(s);
   ema3.init(tr);
   ema4.init(s);
   ema5.init(u);
   
   IndicatorSetInteger(INDICATOR_LEVELS,3);
   IndicatorSetDouble( INDICATOR_LEVELVALUE,0,levUp);
   IndicatorSetInteger(INDICATOR_LEVELSTYLE,0,levSty);
   IndicatorSetInteger(INDICATOR_LEVELCOLOR,0,levClr);  
   IndicatorSetDouble( INDICATOR_LEVELVALUE,1,levDn);
   IndicatorSetInteger(INDICATOR_LEVELSTYLE,1,levSty);
   IndicatorSetInteger(INDICATOR_LEVELCOLOR,1,levClr);  
   IndicatorSetDouble( INDICATOR_LEVELVALUE,2,0);
   IndicatorSetInteger(INDICATOR_LEVELSTYLE,2,levSty);
   IndicatorSetInteger(INDICATOR_LEVELCOLOR,2,levClr);  

   IndicatorSetString(INDICATOR_SHORTNAME,"Blau TVI ("+DoubleToStr(tr,2)+","+DoubleToStr(s,2)+","+DoubleToStr(u,2)+")");
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason){ } 

//------------------------------------------------------------------
//
//------------------------------------------------------------------

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[])
{
   int i=rates_total-prev_calculated+1; if (i>=rates_total) i=rates_total-1; 
   
   //
   //
   //
   
   for (; i>=0 && !_StopFlag; i--)
   {
      double upTic = (tick_volume[i]+(close[i]-open[i])/_Point)/2.0;
      double dnTic = (tick_volume[i]-upTic);
      double avgUp = ema1.OnCalculate(ema2.OnCalculate(upTic,i,rates_total),i,rates_total); //r s
      double avgDn = ema3.OnCalculate(ema4.OnCalculate(dnTic,i,rates_total),i,rates_total); //r s
 
      val[i]  = (avgUp+avgDn != 0) ? ema5.OnCalculate(100.0*(avgUp-avgDn)/(avgUp+avgDn),i,rates_total) : 0;  //u 
      valc[i] = (i<rates_total-1) ? (val[i]>0) ? (val[i]>val[i+1]) ? 0 : 1 : (val[i]<val[i+1]) ? 2 : 3 : 0;
      huu[i]  = (valc[i] == 0) ? val[i] : EMPTY_VALUE;
      hud[i]  = (valc[i] == 1) ? val[i] : EMPTY_VALUE;
      hdd[i]  = (valc[i] == 2) ? val[i] : EMPTY_VALUE;
      hdu[i]  = (valc[i] == 3) ? val[i] : EMPTY_VALUE;  
   }
return(rates_total);       
}

//------------------------------------------------------------------
//  
//------------------------------------------------------------------

class CEma
{
   private :
         double m_period;
         double m_alpha;
         double m_array[];
         int    m_arraySize;
   public :
      CEma() : m_period(1), m_alpha(1), m_arraySize(-1) { return; }
     ~CEma()                                            { return; }
    
     //
     //
     //
    
     void init(int period)
      {
            m_period = (period>1) ? period : 1;
            m_alpha  = 2.0/(1.0+m_period);
      }
      double OnCalculate(double value, int i, int bars)
      {
        if (m_arraySize<bars)
          { m_arraySize=ArrayResize(m_array,bars+500); if (m_arraySize<bars) return(0); }

            //
            //
            //
            
            i = bars-i-1;
            if (i>0)
                    m_array[i] = m_array[i-1]+m_alpha*(value-m_array[i-1]);
            else    m_array[i] = value;
            return (m_array[i]);
         }  
};
CEma ema1,ema2,ema3,ema4,ema5;

