//
// "00-Ratio100.mq4" -- Efficiency Ratio like indicator, for separate window
//
//    Ver. 1.00  2008/10/8(Wed)   initial version
//    Ver. 1.01  2008/10/8(Wed)   added bSignalCross0, signal on ratio-0.0 cross
//    Ver. 1.02  2008/10/12(Sun)  modified ave cross signal little
//    Ver. 1.05  2008/10/12(Sun)  version sync for release
//    Ver. 1.06  2008/10/13(Mon)  version sync for release
// 
#property  copyright "00 - 00mql4@gmail.com"
#property  link      "http://www.mql4.com/"

//---- indicator settings
#property  indicator_separate_window

#property  indicator_buffers  8

#property  indicator_color1  Lime
#property  indicator_color2  DodgerBlue
#property  indicator_color3  Crimson
#property  indicator_color4  DodgerBlue
#property  indicator_color5  Crimson
#property  indicator_color6  Red
#property  indicator_color7  Yellow
#property  indicator_color8  White

#property  indicator_width1  1
#property  indicator_width2  2
#property  indicator_width3  2
#property  indicator_width4  1
#property  indicator_width5  1
#property  indicator_width6  1
#property  indicator_width7  2
#property  indicator_width8  1

#property  indicator_style1  STYLE_SOLID
#property  indicator_style2  STYLE_SOLID
#property  indicator_style3  STYLE_SOLID
#property  indicator_style4  STYLE_SOLID
#property  indicator_style5  STYLE_SOLID
#property  indicator_style6  STYLE_SOLID
#property  indicator_style7  STYLE_SOLID
#property  indicator_style8  STYLE_DOT

//---- defines
#define M_PI  3.14159265358979323846264338

//---- indicator parameters
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

//---- indicator buffers
double BufferRatio[];       // 0: ratio
double BufferBigLong[];     // 1: long signal, big
double BufferBigShort[];    // 2: short signal, big
double BufferSmallLong[];   // 3: long signal, small
double BufferSmallShort[];  // 4: short signal, small
double BufferAveFast[];     // 5: ave, fast
double BufferAveSlow[];     // 6: ave, slow
double BufferMACD[];        // 7: MACD, fast - slow

//---- vars
string   sIndicatorName  = "00-Ratio100";
int      markBigLong     = 233;
int      markBigShort    = 234;
int      markSmallLong   = 108;
int      markSmallShort  = 108;
datetime tAlertLast;

//----------------------------------------------------------------------
void init()
{
    IndicatorShortName(sIndicatorName);
    
    SetIndexBuffer(0, BufferRatio);
    SetIndexBuffer(1, BufferBigLong);
    SetIndexBuffer(2, BufferBigShort);
    SetIndexBuffer(3, BufferSmallLong);
    SetIndexBuffer(4, BufferSmallShort);
    SetIndexBuffer(5, BufferAveFast);
    SetIndexBuffer(6, BufferAveSlow);
    SetIndexBuffer(7, BufferMACD);
    
    SetIndexLabel(0, "Ratio");
    SetIndexLabel(1, "BigLong");
    SetIndexLabel(2, "BigShort");
    SetIndexLabel(3, "SmallLong");
    SetIndexLabel(4, "SmallShort");
    SetIndexLabel(5, "AveFast");
    SetIndexLabel(6, "AveSlow");
    SetIndexLabel(7, "MACD");
    
    SetIndexStyle(0, DRAW_LINE);
    SetIndexStyle(1, DRAW_ARROW);
    SetIndexStyle(2, DRAW_ARROW);
    SetIndexStyle(3, DRAW_ARROW);
    SetIndexStyle(4, DRAW_ARROW);
    SetIndexStyle(5, DRAW_LINE);
    SetIndexStyle(6, DRAW_LINE);
    SetIndexStyle(7, DRAW_HISTOGRAM);
    
    SetIndexArrow(1, markBigLong);
    SetIndexArrow(2, markBigShort);
    SetIndexArrow(3, markSmallLong);
    SetIndexArrow(4, markSmallShort);

    SetIndexDrawBegin(0, nAveSlow);
    SetIndexDrawBegin(1, nAveSlow);
    SetIndexDrawBegin(2, nAveSlow);
    SetIndexDrawBegin(3, nAveSlow);
    SetIndexDrawBegin(4, nAveSlow);
    SetIndexDrawBegin(5, nAveSlow);
    SetIndexDrawBegin(6, nAveSlow);
    SetIndexDrawBegin(7, nAveSlow);
    
    SetLevelValue(0, 0.0);
    
    if (point == 0) {
	point = Point;
    }
    
    targetPips *= point;
}

//----------------------------------------------------------------------
double lanczos3(double t)
{
    double v = 0.0;
    
    if (t == 0) {
	v = 1.0;
    } else if (t < 3.0) {
	t *= M_PI;
	v = MathSin(t) * MathSin(t / 3.0) / (t * t) * 3.0;
    }
    
    return(v);
}

//----------------------------------------------------------------------
double iLanczos3OnArray(double array[], int period, int shift)
{
    // array[]: ..3 2 1 0
    //                <-|shift
    //bool bSeries = ArrayGetAsSeries(array);
    
    int nCoeff = period * 3 + 2;
    double total = 0;
    double w = 0;
    for (int i = 0; i < nCoeff; i++) {
	double c = lanczos3((i + 0.0) / period);
	total += array[i + shift] * c;
	w += c;
    }
    double ave = 0;
    if (w > 0) {
	ave = total / w;
    }
    
    return(ave);
}

//----------------------------------------------------------------------
void start()
{
    int limit;
    int counted_bars = IndicatorCounted();
    
    if (counted_bars > 0) {
	counted_bars--;
    }
    
    limit = Bars - counted_bars;
    limit += 3;
    
    int i, j;
    int n = targetPips / point * 10;
    double rUp;
    double rDown;
    double tPlus, tMinus;
    double d;
    int delay = 0;
    
    if (bWaitSignalFixed) {
	delay = 1;
    }
    
    for (i = limit; i >= 0; i--) {
	
	// check up
	tPlus = 0;
	tMinus = 0;
	for (j = 0; j < n; j++) {
	    bool bUp = (Close[i + j] >= Open[i + j]);
	    if (!bUseHiLo) {
		d = MathAbs(Close[i + j] - Open[i + j]);
	    } else {
		d = High[i + j] - Low[i + j];
	    }
	    if (bUp) {
		tPlus += d;
		if (tPlus >= targetPips) {
		    break;
		}
	    } else {
		tMinus += d;
	    }
	}
	if (tMinus == 0) {
	    rUp = j + 1;
	} else {
	    rUp = tPlus / tMinus;
	}
	
	// check down
	tPlus = 0;
	tMinus = 0;
	for (j = 0; j < n; j++) {
	    bool bDown = (Close[i + j] < Open[i + j]);
	    if (!bUseHiLo) {
		d = MathAbs(Close[i + j] - Open[i + j]);
	    } else {
		d = High[i + j] - Low[i + j];
	    }
	    if (bDown) {
		tMinus += d;
		if (tMinus >= targetPips) {
		    break;
		}
	    } else {
		tPlus += d;
	    }
	}
	if (tPlus == 0) {
	    rDown = j + 1;
	} else {
	    rDown = tMinus / tPlus;
	}
	
	BufferRatio[i] = MathMin(MathMax(MathLog(rUp) - MathLog(rDown), -10), 10);
    }
    
    for (i = limit; i >= 0; i--) {
	double fast = iLanczos3OnArray(BufferRatio, nAveFast, i);
	double slow = iLanczos3OnArray(BufferRatio, nAveSlow, i);
	BufferAveFast[i] = fast;
	BufferAveSlow[i] = slow;
	BufferMACD[i] = fast - slow;
	//
	BufferBigLong[i] = EMPTY_VALUE;
	BufferBigShort[i] = EMPTY_VALUE;
	BufferSmallLong[i] = EMPTY_VALUE;
	BufferSmallShort[i] = EMPTY_VALUE;
    }
    
    // check signal
    for (i = limit; i >= 0; i--) {
	
	double ratio2 = BufferRatio[i + 2];
	double ratio1 = BufferRatio[i + 1];
	
	double hi1 = High[i + 1];
	double hi0 = High[i + 0];
	
	double lo1 = Low[i + 1];
	double lo0 = Low[i + 0];
	
	double close1 = Close[i + 1];
	double close0 = Close[i + 0];
	
	double open1 = Open[i + 1];
	
	if (bSignalAveCross) {
	    double fast4 = BufferAveFast[i + 4 + delay];
	    double fast3 = BufferAveFast[i + 3 + delay];
	    double fast2 = BufferAveFast[i + 2 + delay];
	    double fast1 = BufferAveFast[i + 1 + delay];
	    double fast0 = BufferAveFast[i + 0 + delay];
	    
	    double slow4 = BufferAveSlow[i + 4 + delay];
	    double slow3 = BufferAveSlow[i + 3 + delay];
	    double slow2 = BufferAveSlow[i + 2 + delay];
	    double slow1 = BufferAveSlow[i + 1 + delay];
	    double slow0 = BufferAveSlow[i + 0 + delay];
	    
	    double vFast3 = fast3 - fast4;
	    double vFast2 = fast2 - fast3;
	    double vFast1 = fast1 - fast2;
	    double vFast0 = fast0 - fast1;
	    
	    double vSlow3 = slow3 - slow4;
	    double vSlow2 = slow2 - slow3;
	    double vSlow1 = slow1 - slow2;
	    double vSlow0 = slow0 - slow1;
	    
	    double aFast2 = vFast2 - vFast3;
	    double aFast1 = vFast1 - vFast2;
	    double aFast0 = vFast0 - vFast1;
	    
	    double aSlow2 = vSlow2 - vSlow3;
	    double aSlow1 = vSlow1 - vSlow2;
	    double aSlow0 = vSlow0 - vSlow1;
	    
	    bool bCrossLong2 = (fast3 <= slow3 && fast2 > slow2);
	    bool bCrossLong1 = (fast2 <= slow2 && fast1 > slow1);
	    bool bCrossLong0 = (fast1 <= slow1 && fast0 > slow0);
	    
	    bool bCrossShort2 = (fast3 >= slow3 && fast2 < slow2);
	    bool bCrossShort1 = (fast2 >= slow2 && fast1 < slow1);
	    bool bCrossShort0 = (fast1 >= slow1 && fast0 < slow0);
	    
	    bool bBigSignal = false;
	    bool bSmallSignal = false;
	    
	    // Long
	    if ((bCrossLong2 || bCrossLong1 || bCrossLong0) && ((close0 >= close1) && (close1 >= open1))) {
		
		bool bBigLong = ((vFast0 >= 0) && (aFast0 >= 0 && aSlow0 >= 0) && vSlow0 >= 0);
		bool bSmallLong = (vFast0 >= 0 && aSlow0 >= 0 && vSlow0 >= 0);
		
		if (bBigLong) {
		    BufferBigLong[i] = 0;
		    bBigSignal = true;
		}
		if (bSmallLong) {
		    BufferSmallLong[i] = 0;
		    bSmallSignal = true;
		}
	    }
	    
	    // Short
	    if ((bCrossShort2 || bCrossShort1 || bCrossShort0) && ((close0 <= close1) && (close1 <= open1))) {
		
		bool bBigShort = ((vFast0 <= 0) && (aFast0 <= 0 && aSlow0 <= 0) && vSlow0 <= 0);
		bool bSmallShort = (vFast0 <= 0 && aSlow0 <= 0 && vSlow0 <= 0);
		
		if (bBigShort) {
		    BufferBigShort[i] = 0;
		    bBigSignal = true;
		}
		if (bSmallShort) {
		    BufferSmallShort[i] = 0;
		    bSmallSignal = true;
		}
	    }
	}
	
	if (bSignalCross0) {
	    // Long
	    if (ratio2 <= 0.0 && ratio1 > 0.0 && hi0 > hi1) {
		BufferBigLong[i] = 0;
		bBigSignal = true;
	    }
	    
	    // Short
	    if (ratio2 >= 0.0 && ratio1 < 0.0 && lo0 < lo1) {
		BufferBigShort[i] = 0;
		bBigSignal = true;
	    }
	}
	
	// alert
	if (i == 0) {
	    if ((bAlertBig && bBigSignal) || (bAlertSmall && bSmallSignal)) {
		datetime t = Time[0];
		if (tAlertLast != t) {
		    Print("t= ", TimeToStr(t), ", bBigSignal= ", bBigSignal, ", bSmallSignal= ", bSmallSignal);
		    PlaySound("alert.wav");
		    tAlertLast = t;
		}
	    }
	}
    }
}
