//
// "00-Sig-MultiSTC_v103.mq4" -- Schaff Trend Cycle
//
//    Ver. 0.01  2008/10/30(Thu)  initial version
//    Ver. 1.00  2008/11/02(Sun)  release version
//    Ver. 1.03  2008/12/23(Tue)  version sync
// 
// 
#property  copyright "00 - 00mql4@gmail.com"
#property  link      "http://www.mql4.com/"

//---- indicator settings
#property  indicator_chart_window

#property  indicator_buffers  2

#property  indicator_color1  DodgerBlue
#property  indicator_color2  Crimson

#property  indicator_width1  1
#property  indicator_width2  1

//---- indicator parameters
/*extern*/ int nStopLossRange   = 3;   // draw S/L line in last N bars min/max
/*extern*/ int nBarAfterSignal  = 10;  // length of S/L line
//
/*extern*/ string sHelp0 = "--- params for \"00-MultiSTC\"";
/*extern*/ string sIndMultiSTC  = "00-MultiSTC_v103";  // indicator name of "00-SidusV2"
extern int    timeFrame0     = 0;              // time frame 0
extern int    timeFrame1     = 0;              // time frame 1
extern int    timeFrame2     = 0;              // time frame 2
extern bool   bAlert         = false;          // PlaySound() on signal
extern int    nFast          = 23;             // EMA fast
extern int    nSlow          = 50;             // EMA slow
extern int    nStochas       = 10;             // Stochas period 
extern bool   bDoubleStochas = true;           // apply stochas twice
extern int    appliedPrice   = PRICE_TYPICAL;  // 0:CLOSE 1:OPEN 2:HIGH 3:LOW 4:MEDIAN 5:TYPICAL 6:WEIGHTED
extern double levelLo        = 5;              // lower threshold for long signal
extern double levelHi        = 95;             // upper threshold for short signal
extern double clearLo        = 25;             // lower level to clear long turn
extern double clearHi        = 75;             // upper level to clear short turn
extern int    nMaxBars       = 2000;           // maximum number of bars to calculate, 0: no limit
/*extern*/ string sHelp1 = "--- end of params for \"00-MultiSTC\"";
//
/*extern*/ double point     = 0.0;         // point value
/*extern*/ color  colLong   = DodgerBlue;  // color for long lines
/*extern*/ color  colShort  = Crimson;     // color for short lines

//---- indicator buffers
double BufferLong[];   // 0: long signal
double BufferShort[];  // 2: short signal

//---- vars
string   sIndicatorName  = "00-Sig-SidusV2_v103";
string   sPrefix;
int      markLong   = 233;
int      markShort  = 234;
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("??");
}

//----------------------------------------------------------------------
int NextPeriod(int timeFrame)
{
    switch (timeFrame) {
    case 1:     return(5);
    case 5:     return(15);
    case 15:    return(30);
    case 30:    return(60);
    case 60:    return(240);
    case 240:   return(1440);
    case 1440:  return(10080);
    case 10080: return(43200);
    }
    
    return(0);
}

//----------------------------------------------------------------------
void init()
{
    if (timeFrame0 == 0 && timeFrame1 == 0 && timeFrame2 == 0) {
	timeFrame0 = Period();
	timeFrame1 = NextPeriod(timeFrame0);
	timeFrame2 = NextPeriod(timeFrame1);
    }
    
    if (timeFrame0 == 0) {
	timeFrame0 = Period();
    }
    if (timeFrame1 == 0) {
	timeFrame1 = Period();
    }
    if (timeFrame2 == 0) {
	timeFrame2 = Period();
    }
    
    sIndicatorName = (sIndMultiSTC + "(" +
		      TimeFrameToStr(timeFrame0) + "," +
		      TimeFrameToStr(timeFrame1) + "," +
		      TimeFrameToStr(timeFrame2) + ")");
    
    sPrefix = sIndicatorName;
    
    IndicatorShortName(sIndicatorName);
    
    SetIndexBuffer(0, BufferLong);
    SetIndexBuffer(1, BufferShort);
    
    SetIndexLabel(0, "Long signal");
    SetIndexLabel(1, "Short signal");
    
    SetIndexStyle(0, DRAW_ARROW);
    SetIndexStyle(1, DRAW_ARROW);
    
    SetIndexArrow(0, markLong);
    SetIndexArrow(1, markShort);
    
    int n = MathMax(nFast, nSlow) + nStochas;
    SetIndexDrawBegin(0, n);
    SetIndexDrawBegin(1, n);
    
    if (point == 0.0) {
	point = Point;
    }
}

//----------------------------------------------------------------------
void deinit()
{
    int n = ObjectsTotal();
    for (int i = n - 1; i >= 0; i--) {
	string sName = ObjectName(i);
	if (StringFind(sName, sPrefix) == 0) {
	    ObjectDelete(sName);
	}
    }
}

//----------------------------------------------------------------------
void objLine(string sName, datetime ts, double ps, datetime te, double pe, color col,
	     int width = 1, int style = STYLE_SOLID, bool bBack = true, bool bRay = false)
{
    ObjectCreate(sName, OBJ_TREND, 0, 0, 0, 0);
    ObjectSet(sName, OBJPROP_TIME1,  ts);
    ObjectSet(sName, OBJPROP_PRICE1, ps);
    ObjectSet(sName, OBJPROP_TIME2,  te);
    ObjectSet(sName, OBJPROP_PRICE2, pe);
    ObjectSet(sName, OBJPROP_COLOR, col);
    ObjectSet(sName, OBJPROP_WIDTH, width);
    ObjectSet(sName, OBJPROP_STYLE, style);
    ObjectSet(sName, OBJPROP_BACK, bBack);
    ObjectSet(sName, OBJPROP_RAY, bRay);
}	    

//----------------------------------------------------------------------
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);
    }
    
    double ofst = 3 * point;
    
    // clear beyond limits
    for (int i = limit0 - 1; i >= limit; i--) {
	BufferLong[i]  = EMPTY_VALUE;
	BufferShort[i] = EMPTY_VALUE;
    }
    
    for (i = limit - 1; i >= 0; i--) {
	BufferLong[i]  = EMPTY_VALUE;
	BufferShort[i] = EMPTY_VALUE;
	
	double bufLong  = iCustom(NULL, 0, sIndMultiSTC, timeFrame0, timeFrame1, timeFrame2, false, nFast, nSlow, nStochas,
				  bDoubleStochas, appliedPrice, levelLo, levelHi, clearLo, clearHi, nMaxBars, 0, i);
	double bufShort = iCustom(NULL, 0, sIndMultiSTC, timeFrame0, timeFrame1, timeFrame2, false, nFast, nSlow, nStochas,
				  bDoubleStochas, appliedPrice, levelLo, levelHi, clearLo, clearHi, nMaxBars, 1, i);
	bool bLong = false;
	bool bShort = false;
	
	// long
	if (bufLong != EMPTY_VALUE) {
	    bLong = true;
	    BufferLong[i] = Low[i] - ofst;
	}
	
	// short
	if (bufShort != EMPTY_VALUE) {
	    bShort = true;
	    BufferShort[i] = High[i] + ofst;
	}
	
	bool bFire = (bLong || bShort);
	
	if (bFire) {
	    if (nStopLossRange > 0) {
		string sNameStopLossH = sPrefix + Time[i] + " SL H";
		string sNameStopLossV = sPrefix + Time[i] + " SL V";
		datetime t0 = Time[i];
		datetime ts = Time[i + nStopLossRange];
		datetime te = Time[i] + nBarAfterSignal * Period() * 60;
		if (bLong) {
		    double p = Low[iLowest(NULL, 0, MODE_LOW, nStopLossRange, i + 1)];
		    objLine(sNameStopLossH, ts, p, te, p, colLong);
		    objLine(sNameStopLossV, t0, p, t0, p + 3 * Point, colLong);
		} else {
		    p = High[iHighest(NULL, 0, MODE_HIGH, nStopLossRange, i + 1)];
		    objLine(sNameStopLossH, ts, p, te, p, colShort);
		    objLine(sNameStopLossV, t0, p, t0, p - 3 * Point, colShort);
		}
	    }
	    
	    if (bAlert) {
		if (i == 0 && bFire && tAlertLast != Time[0]) {
		    PlaySound("alert.wav");
		    tAlertLast = Time[0];
		}
	    }
	}
    }
    
    WindowRedraw();
}
