// properties which tell the indicator how it should look
#property	indicator_separate_window
#property	indicator_maximum			100
#property	indicator_minimum			0
#property	indicator_buffers			2
#property	indicator_color1			DodgerBlue
#property	indicator_color2			Orange
#property	indicator_level1			20
#property	indicator_level2			80

// user-defined parameters
extern int	KPeriod		= 5;
extern int	DPeriod		= 3;
extern int	Slowing 	= 3;
extern int	Method		= MODE_EMA;
extern int	Price		= 1;		// 0=Low/High, 1=Close/Close
extern bool	PopupAlert 	= true;
extern bool	EmailAlert 	= true;

// indicator buffers
double dStochMain[];
double dStochSignal[]; 

// function which is called when indicator is loaded
int init() {

	// set the display value for upper left corner of indicator window
	IndicatorShortName("Stoch With Alert (" + KPeriod + ") (" + DPeriod + ") (" + Slowing + ")");
	
	// tell the indicator which arrays to use as buffers
	SetIndexBuffer(0,dStochMain);
	SetIndexBuffer(1,dStochSignal);
	
	// label the indicies (shows on mouseover of lines and in Data Window)
	SetIndexLabel(0,"Stoch Main");
	SetIndexLabel(1,"Stoch Signal");
}

// function which is called with every tick
int start() {

	// keep track of the bar on which an alert was last fired
	// since this variable is static, it will "remember" its value between calls
	static datetime tLastAlert = 0;

	// determine how far back to iterate
	// always recalc last completed bar incase the client was too busy to handle
	// the last tick of the last bar (very, very rare).
	int	iBarsToCalc = Bars - IndicatorCounted();
	if (iBarsToCalc < Bars) iBarsToCalc++;
	
	// iterate over bars to be calculated, starting with oldest
	for (int i=iBarsToCalc-i;i>=0;i--) {
	
		// calculate the stoch values for the bar
		dStochMain[i]	= iStochastic(NULL,0,KPeriod,DPeriod,Slowing,Method,Price,MODE_MAIN,i);
		dStochSignal[i]	= iStochastic(NULL,0,KPeriod,DPeriod,Slowing,Method,Price,MODE_SIGNAL,i);
	}
	
	// now, the indicator work has been done, all the code below could be
	// deleted and the indicator would still function, but without alerts.
	// it's time to check for an alert if there hasn't already been one this bar
	if(tLastAlert < Time[0]) {
		// if stoch dipped down under 80...
		if(dStochMain[1] >= 80 && dStochMain[0] < 80) {
			fireAlerts("Stoch Dropped Below 80 on " + Symbol() + ".");
			tLastAlert = Time[0];
		}
		// if stoch pushed up over 20...
		if(dStochMain[1] <= 20 && dStochMain[0] > 20) {
			fireAlerts("Stoch Pushed Up Above 20 on " + Symbol() + ".");
			tLastAlert = Time[0];
		}
	}
}

void fireAlerts(string sMsg) {

	if(PopupAlert)
		Alert(sMsg);
	
	if(EmailAlert)
		SendMail("Stoch Alert On " + Symbol(),sMsg);
}