//
// "00-Sig-Ratio100.mq4" -- Efficiency Ratio like indicator, for char window, "00-Ratio100" is needed
//
//    Ver. 1.00  2008/10/8(Wed)   initial version
//    Ver. 1.01  2008/10/9(Thu)   added S/L lines (lowest/highest low/high in nStopLossRange)
//    Ver. 1.02  2008/10/10(Fri)  added bSignalCross0, signal on ratio-0.0 cross and draw ignore-cross-box
//    Ver. 1.03  2008/10/12(Sun)  bugfixed: for short, upper bound of ignore box is wrong
//    Ver. 1.05  2008/10/12(Sun)  version sync for release
//    Ver. 1.06  2008/10/13(Mon)  bugfixed: args for "00-Ratio100" is insufficient
// 
#property  copyright "00 - 00mql4@gmail.com"
#property  link      "http://www.mql4.com/"

//---- indicator settings
#property  indicator_chart_window

#property  indicator_buffers  4

#property  indicator_color1  DodgerBlue
#property  indicator_color2  Crimson
#property  indicator_color3  DodgerBlue
#property  indicator_color4  Crimson

#property  indicator_width1  2
#property  indicator_width2  2
#property  indicator_width3  1
#property  indicator_width4  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-Ratio100\"";
extern string sIndRatio100      = "00-Ratio100_v106";  // indicator name of "00-Ratio100"
extern double targetPips        = 300;        // go up/down till targetPips is achieved
extern int    nAveFast          = 12;         // number of bars for fast-ave
extern int    nAveSlow          = 26;         // number of bars for slow-ave
extern bool   bWaitSignalFixed  = true;       // wait signal fixed (1 bar delay)
extern bool   bUseHiLo          = false;      // use Hi/Lo or Open/Close
extern bool   bSignalAveCross   = false;      // signal on fast-slow ave cross
extern bool   bSignalCross0     = true;       // signal on ratio-0.0 cross
extern double ignoreCross0      = 0.1;        // ratio-0.0 cross in Close[1]+targetPips*ignoreCross0 pips are ignored (not yet)
extern double cross0Breakout    = -0.1;       // S/L point
extern double ignoreCross0Bars  = 0.01;       // ratio-0.0 cross in targetPips*ignoreCross0Bars bars are ignored (not yet)
extern double point             = 0.0;        // point value
extern bool   bAlertBig         = true;       // alert big signal
extern bool   bAlertSmall       = true;       // alert small signal
extern string sHelp1 = "--- end of params for \"00-Ratio100\"";
//
extern color  colLong          = DodgerBlue;  // color for long lines
extern color  colShort         = Crimson;     // color for short lines
extern color  colIgnoreBox     = Magenta;     // color for ignore-cross-box
extern int    nMaxBarStopLoss  = 100;         // max number of bar objs

//---- indicator buffers
double BufferBigLong[];
double BufferBigShort[];
double BufferSmallLong[];
double BufferSmallShort[];

//---- vars
string sIndicatorName  = "00-Sig-Ratio100";
int markBigLong        = 233;
int markBigShort       = 234;
int markSmallLong      = 108;
int markSmallShort     = 108;
string sPrefix;

//----------------------------------------------------------------------
void init()
{
    IndicatorShortName(sIndicatorName);
    
    SetIndexBuffer(0, BufferBigLong);
    SetIndexBuffer(1, BufferBigShort);
    SetIndexBuffer(2, BufferSmallLong);
    SetIndexBuffer(3, BufferSmallShort);
    
    SetIndexLabel(0, "Big Long");
    SetIndexLabel(1, "Big Short");
    SetIndexLabel(2, "Small Long");
    SetIndexLabel(3, "Small Short");
    
    SetIndexStyle(0, DRAW_ARROW);
    SetIndexStyle(1, DRAW_ARROW);
    SetIndexStyle(2, DRAW_ARROW);
    SetIndexStyle(3, DRAW_ARROW);
    
    SetIndexArrow(0, markBigLong);
    SetIndexArrow(1, markBigShort);
    SetIndexArrow(2, markSmallLong);
    SetIndexArrow(3, markSmallShort);
    
    SetIndexDrawBegin(0, nAveSlow);
    SetIndexDrawBegin(1, nAveSlow);
    SetIndexDrawBegin(2, nAveSlow);
    SetIndexDrawBegin(3, nAveSlow);
    
    if (point == 0) {
	point = Point;
    }
    
    sPrefix = sIndicatorName;
}

//----------------------------------------------------------------------
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 objRect(string sName, datetime ts, double ps, datetime te, double pe, color col,
	     int width = 1, int style = STYLE_SOLID, bool bBack = false)
{
    ObjectCreate(sName, OBJ_RECTANGLE, 0, 0, 0, 0);
    objLine(sName, ts, ps, te, pe, col, width, style, bBack, false);
}	    

//----------------------------------------------------------------------
void start()
{
    int limit;
    int counted_bars = IndicatorCounted();
    
    if (counted_bars > 0) {
	counted_bars--;
    }
    
    limit = Bars - counted_bars;
    
    double ofst = 3 * point;
    
    for (int i = limit + 1; i >= 0; i--) {
	BufferBigLong[i] = EMPTY_VALUE;
	BufferBigShort[i] = EMPTY_VALUE;
	BufferSmallLong[i] = EMPTY_VALUE;
	BufferSmallShort[i] = EMPTY_VALUE;
	
	double bigLong = iCustom(NULL, 0, sIndRatio100, targetPips, nAveFast, nAveSlow, bWaitSignalFixed, bUseHiLo,
				 bSignalAveCross, bSignalCross0, ignoreCross0, cross0Breakout, ignoreCross0Bars,
				 point, bAlertBig, bAlertSmall, 1, i);
	double bigShort = iCustom(NULL, 0, sIndRatio100, targetPips, nAveFast, nAveSlow, bWaitSignalFixed, bUseHiLo,
				  bSignalAveCross, bSignalCross0, ignoreCross0, cross0Breakout, ignoreCross0Bars,
				  point, false, false, 2, i);
	double smallLong = iCustom(NULL, 0, sIndRatio100, targetPips, nAveFast, nAveSlow, bWaitSignalFixed, bUseHiLo,
				   bSignalAveCross, bSignalCross0, ignoreCross0, cross0Breakout, ignoreCross0Bars,
				   point, false, false, 3, i);
	double smallShort = iCustom(NULL, 0, sIndRatio100, targetPips, nAveFast, nAveSlow, bWaitSignalFixed, bUseHiLo,
				    bSignalAveCross, bSignalCross0, ignoreCross0, cross0Breakout, ignoreCross0Bars,
				    point, false, false, 4, i);
	
	bool bLong = false;
	bool bShort = false;
	
	if (bigLong != EMPTY_VALUE) {
	    BufferBigLong[i] = Low[i] - ofst;
	    bLong = true;
	}
	if (bigShort != EMPTY_VALUE) {
	    BufferBigShort[i] = High[i] + ofst;
	    bShort = true;
	}
	if (smallLong != EMPTY_VALUE) {
	    BufferSmallLong[i] = Low[i] - ofst;
	    bLong = true;
	}
	if (smallShort != EMPTY_VALUE) {
	    BufferSmallShort[i] = High[i] + ofst;
	    bShort = true;
	}
	
	if (bLong || bShort) {
	    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;
		int delay = 0;
		if (bWaitSignalFixed) {
		    delay = 1;
		}
		if (bLong) {
		    double p = Low[iLowest(NULL, 0, MODE_LOW, nStopLossRange, i + delay)];
		    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 + delay)];
		    objLine(sNameStopLossH, ts, p, te, p, colShort);
		    objLine(sNameStopLossV, t0, p, t0, p - 3 * Point, colShort);
		}
	    }
	    if (bSignalCross0) {
		string sNameLong0 = sPrefix + Time[i] + " long entry0";
		string sNameLong1 = sPrefix + Time[i] + " long entry1";
		string sNameShort0 = sPrefix + Time[i] + " short entry0";
		string sNameShort1 = sPrefix + Time[i] + " short entry1";
		string sNameIgnoreBox = sPrefix + Time[i] + " ignore";
		ts = Time[i + 1];
		te = Time[i + 1] + MathRound(targetPips * ignoreCross0Bars) * Period() * 60;
		if (bLong) {
		    // ignore box
		    double ps = Close[i + 1] + targetPips * point * ignoreCross0;
		    double pe = High[i + 1] + targetPips * point * cross0Breakout;
		    objRect(sNameIgnoreBox, ts, ps, te, pe, colIgnoreBox, 1, STYLE_DOT);
		    // entry point
		    p = MathMax(High[i + 1], Low[i]);
		    ts = Time[i];
		    te = ts + 2 * Period() * 60;
		    objLine(sNameLong0, ts, p, ts + 1 * Period() * 60, p, colLong, 5, STYLE_SOLID, false);
		    objLine(sNameLong1, ts, p, ts + 2 * Period() * 60, p, White, 1, STYLE_DOT, false);
		} else {
		    // ignore box
		    ps = Close[i + 1] - targetPips * point * ignoreCross0;
		    pe = Low[i + 1] - targetPips * point * cross0Breakout;
		    objRect(sNameIgnoreBox, ts, ps, te, pe, colIgnoreBox, 1, STYLE_DOT);
		    // entry point
		    p = MathMin(Low[i + 1], High[i]);
		    ts = Time[i];
		    te = ts + 2 * Period() * 60;
		    objLine(sNameShort0, ts, p, ts + 1 * Period() * 60, p, colShort, 5, STYLE_SOLID, false);
		    objLine(sNameShort1, ts, p, ts + 2 * Period() * 60, p, White, 1, STYLE_DOT, false);
		}
	    }
	}
    }
    
    WindowRedraw();
}
