//
// "00-TSI_v100.mq4" -- True Strength Index
//
//    Ver. 1.00  2009/01/11(Sun)  initial version
//
//
#property  copyright "00"
#property  link      "http://www.mql4.com/"

//---- defines

//---- indicator settings
#property  indicator_separate_window

#property  indicator_buffers  2

#property  indicator_color1  Lime
#property  indicator_color2  Lime

#property  indicator_width1  1
#property  indicator_width2  1

#property  indicator_style1  STYLE_SOLID
#property  indicator_style2  STYLE_DOT

#property indicator_level1  0.0

//---- indicator parameters
extern int  timeFrame  = 0;     // time frame
extern int  nRaw       = 13;    // TSI period
extern int  nSmooth    = 20;    // smooth period of TSI
extern int  nSlowing   = 7;     // signal slowing period
extern int  nMaxBars   = 2000;  // maximum number of bars to calculate, 0: no limit

//---- indicator buffers
double BufferTSI[];            // 0: TSI
double BufferSig[];            // 1: Sig
double BufferDiffRaw[];        // 2: tmp
double BufferDiffAbs[];        // 3: tmp
double BufferDiffRawEma[];     // 4: tmp
double BufferDiffAbsEma[];     // 5: tmp
double BufferDiffRawEmaEma[];  // 6: tmp
double BufferDiffAbsEmaEma[];  // 7: tmp

//---- vars
string   sIndicatorName   = "";
string   sIndSelf         = "00-TSI_v100";
datetime tAlertLast;

//----------------------------------------------------------------------
string TimeFrameToStr(int timeFrame)
{
    switch (timeFrame) {
    case 1:     return("M1");
    case 5:     return("M5");
    case 15:    return("M15");
    case 30:    return("M30");
    case 60:    return("H1");
    case 240:   return("H4");
    case 1440:  return("D1");
    case 10080: return("W1");
    case 43200: return("MN");
    }
    
    return("??");
}

//----------------------------------------------------------------------
void init()
{
    if (timeFrame == 0) {
	timeFrame = Period();
    }
    
    string tf = TimeFrameToStr(timeFrame);
    sIndicatorName = sIndSelf + "(" + tf + "," + nRaw + "," + nSmooth + "," + nSlowing + ")";
    
    IndicatorShortName(sIndicatorName);
    
    IndicatorBuffers(8);
    
    SetIndexBuffer(0, BufferTSI);
    SetIndexBuffer(1, BufferSig);
    SetIndexBuffer(2, BufferDiffRaw);
    SetIndexBuffer(3, BufferDiffAbs);
    SetIndexBuffer(4, BufferDiffRawEma);
    SetIndexBuffer(5, BufferDiffAbsEma);
    SetIndexBuffer(6, BufferDiffRawEmaEma);
    SetIndexBuffer(7, BufferDiffAbsEmaEma);
    
    SetIndexLabel(0, "TSI");
    SetIndexLabel(1, "TSI Signal");
    SetIndexLabel(2, "tmp, diff raw");
    SetIndexLabel(3, "tmp, diff abs");
    SetIndexLabel(4, "tmp, diff raw ema");
    SetIndexLabel(5, "tmp, diff abs ema");
    SetIndexLabel(6, "tmp, diff raw ema2");
    SetIndexLabel(7, "tmp, diff abs ema2");
    
    SetIndexStyle(0, DRAW_LINE);
    SetIndexStyle(1, DRAW_LINE);
    
    int n = nRaw + nSmooth + nSlowing;
    SetIndexDrawBegin(0, n);
    SetIndexDrawBegin(1, n);
}

//----------------------------------------------------------------------
void start()
{
    int limit;
    int counted_bars = IndicatorCounted();
    
    if (counted_bars > 0) {
	counted_bars--;
    }
    
    limit = Bars - counted_bars;
    int limit0 = limit;
    if (nMaxBars > 0) {
	limit = MathMin(limit, nMaxBars);
    }
    
    // clear beyond limits
    for (int i = limit0 - 1; i >= limit; i--) {
	BufferTSI[i] = EMPTY_VALUE;
	BufferSig[i] = EMPTY_VALUE;
    }
    
    if (timeFrame != Period()) {
	// MTF
	limit = MathMax(limit, timeFrame / Period());
	for (i = limit - 1; i >= 0; i--) {
	    int x = iBarShift(NULL, timeFrame, Time[i]);
	    BufferTSI[i] = iCustom(NULL, timeFrame, sIndSelf, 0, nRaw, nSmooth, nSlowing, nMaxBars, 0, x);
	    BufferSig[i] = iCustom(NULL, timeFrame, sIndSelf, 0, nRaw, nSmooth, nSlowing, nMaxBars, 1, x);
	}
	
	return;
    }
    
    // timeFrame == Period()
    for (i = limit - 1; i >= 0; i--) {
	double d = Close[i] - Close[i + 1];
	BufferDiffRaw[i] = d;
	BufferDiffAbs[i] = MathAbs(d);
    }
    for (i = limit - 1; i >= 0; i--) {
	BufferDiffRawEma[i] = iMAOnArray(BufferDiffRaw, 0, nRaw, 0, MODE_EMA, i);
	BufferDiffAbsEma[i] = iMAOnArray(BufferDiffAbs, 0, nRaw, 0, MODE_EMA, i);
    }
    for (i = limit - 1; i >= 0; i--) {
	double num = 100.0 * iMAOnArray(BufferDiffRawEma, 0, nSmooth, 0, MODE_EMA, i);
	double den = iMAOnArray(BufferDiffAbsEma, 0, nSmooth, 0, MODE_EMA, i);
	BufferDiffRawEmaEma[i] = num;
	BufferDiffAbsEmaEma[i] = den;
	double tsi;
	if (den != 0.0) {
	    tsi = num / den;
	} else {
	    tsi = 0.0;
	}
	BufferTSI[i] = tsi;
    }
    for (i = limit - 1; i >= 0; i--) {
	BufferSig[i] = iMAOnArray(BufferTSI, 0, nSlowing, 0, MODE_EMA, i);
    }
}
