//+------------------------------------------------------------------+
//|                                       James 16 patterns v1.0     |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007, Rob Rice (blueruby)."
#property link      ""

#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 Red
#property indicator_color2 Green
#property strict

extern string  b = " --- Bearish Patterns --- ";
extern bool    showDBHLC = true,
showBEOVB = true,
showTMLTB = true;

extern string  u = " --- Bullish Patterns --- ";
extern bool    showDBLHC = true,
showBUOVB = true,
showTMHTB = true;

extern string  c = " --- Non Directional or both dir --- ";
extern bool    showIB4 = true,
showKEYRV = false;

input bool alert = true; // Popup Alerts
input bool pushm = true; // Push Notifications
string atxt;

//---- buffers

double upArrow[];
double downArrow[];
string PatternText[5000];

datetime currBar;

int      digits,
Pips;


//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
{

	//---- indicators

	ObjectsDeleteAll(0, OBJ_TEXT);

	SetIndexStyle(0, DRAW_ARROW, EMPTY);
	SetIndexArrow(0, 72);
	SetIndexBuffer(0, downArrow);

	SetIndexStyle(1, DRAW_ARROW, EMPTY);
	SetIndexArrow(1, 71);
	SetIndexBuffer(1, upArrow);

	return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
{
	ObjectsDeleteAll(0, OBJ_TEXT);

	return(0);
}

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
{
	double   Range,
		Range1,
		Range2,
		Range3,
		Range4,
		AvgRange,
		O1, O2, O3,
		C1, C2, C3,
		L1, L2, L3,
		H1, H2, H3;

	int      counter,
		shift,
		shift1,
		shift2,
		shift3;

	string   pattern,
		period;

	digits = (int)MarketInfo(Symbol(), MODE_DIGITS);

	if (currBar == Time[0])
	{
		return(0);
	}

	currBar = Time[0];

	if (Period() >= 1440)
		Pips = 3;
	else
		Pips = 1;

	for (int j = 0; j < Bars; j++)
	{
		PatternText[j] = "pattern-" + IntegerToString(j);
	}

	for (shift = 0; shift < Bars; shift++)
	{
		Range = 0;
		AvgRange = 0;

		for (counter = shift; counter <= shift + 9; counter++)
		{
			AvgRange = AvgRange + MathAbs(High[counter] - Low[counter]);
		}

		Range = AvgRange / 10;

		shift1 = shift + 1;
		shift2 = shift + 2;
		shift3 = shift + 3;

		O1 = NormalizeDouble(Open[shift1], digits);
		O2 = NormalizeDouble(Open[shift2], digits);
		O3 = NormalizeDouble(Open[shift3], digits);

		H1 = NormalizeDouble(High[shift1], digits);
		H2 = NormalizeDouble(High[shift2], digits);
		H3 = NormalizeDouble(High[shift3], digits);

		L1 = NormalizeDouble(Low[shift1], digits);
		L2 = NormalizeDouble(Low[shift2], digits);
		L3 = NormalizeDouble(Low[shift3], digits);

		C1 = NormalizeDouble(Close[shift1], digits);
		C2 = NormalizeDouble(Close[shift2], digits);
		C3 = NormalizeDouble(Close[shift3], digits);

		// Bearish Patterns

		   // Check for DBHLC - Double bar high lower close

		if (showDBHLC && ((H1 == H2) || (H1 + Pips * Point == H2) || (H1 - Pips * Point == H2)) && (C1 < L2))
		{
			ObjectCreate(PatternText[shift], OBJ_TEXT, 0, Time[shift1], High[shift1] + Range*0.30);
			ObjectSetText(PatternText[shift], "DBHLC", 7, "Arial", Black);
			downArrow[shift1] = High[shift1] + Range*0.10;
			atxt = Symbol() + " DBHLC " + TimeToString(Time[shift1], TIME_MINUTES);
			if (alert && shift == 0)Alert(atxt); if (pushm) SendNotification(atxt);
		}

		//  BEOVB - bearish outside vertical bar

		if (showBEOVB && (H1 > H2 + Pips * Point) && (L1 < L2 - Pips * Point) && (C1 < C2))
		{
			ObjectCreate(PatternText[shift], OBJ_TEXT, 0, Time[shift1], High[shift1] + Range*0.45);
			ObjectSetText(PatternText[shift], "BEOVB", 7, "Arial", Black);
			downArrow[shift1] = High[shift1] + Range*0.10;
			atxt = Symbol() + " BEOVB " + TimeToString(Time[shift1], TIME_MINUTES);
			if (alert && shift == 0)Alert(atxt); if (pushm) SendNotification(atxt);
		}

		//  TMLTB - Two matching lows, trend breakout

		if (showTMLTB && ((L2 == L3) || (L2 + Pips * Point == L3) || (L2 - Pips * Point == L3)) && (C1 < L2 - Pips * Point))
		{
			ObjectCreate(PatternText[shift], OBJ_TEXT, 0, Time[shift1], High[shift1] + Range*0.45);
			ObjectSetText(PatternText[shift], "TMLTB", 7, "Arial", Black);
			downArrow[shift1] = High[shift1] + Range*0.10;
			atxt = Symbol() + " TMLTB " + TimeToString(Time[shift1], TIME_MINUTES);
			if (alert && shift == 0)Alert(atxt); if (pushm) SendNotification(atxt);
		}

		// Pin Bar pointing up

		if ((L1 >= L2) && (O1 <= H2) && (C1 <= O1) && (H1 > H2 + ((H1 - L1) / 3)))
		{
			ObjectCreate(PatternText[shift], OBJ_TEXT, 0, Time[shift1], High[shift1] + Range*0.30);
			ObjectSetText(PatternText[shift], "Pin Bar", 7, "Arial", Black);
			downArrow[shift1] = High[shift1] + Range*0.10;
			atxt = Symbol() + " Bearish Pin Bar " + TimeToString(Time[shift1], TIME_MINUTES);
			if (alert && shift == 0)Alert(atxt); if (pushm) SendNotification(atxt);
		}

		// Key Reversal

		if (showKEYRV && (H1 > H2) && (C1 < C2))
		{
			ObjectCreate(PatternText[shift], OBJ_TEXT, 0, Time[shift1], High[shift1] + Range*0.30);
			ObjectSetText(PatternText[shift], "Key Reversal", 7, "Arial", Black);
			downArrow[shift1] = High[shift1] + Range*0.10;
			atxt = Symbol() + " Bearish Key Reversal " + TimeToString(Time[shift1], TIME_MINUTES);
			if (alert && shift == 0)Alert(atxt); if (pushm) SendNotification(atxt);
		}


		//  Bullish Patterns

		   //  DBLHC - Double bar low higher close

		if (showDBLHC && ((L1 == L2) || (L1 + Pips * Point == L2) || (L1 - Pips * Point == L2)) && (C1 > H2))
		{
			ObjectCreate(PatternText[shift], OBJ_TEXT, 0, Time[shift1], Low[shift1] - Range*0.30);
			ObjectSetText(PatternText[shift], "DBLHC", 7, "Arial", Black);
			upArrow[shift1] = Low[shift1] - Range*0.10;
			atxt = Symbol() + " DBLHC " + TimeToString(Time[shift1], TIME_MINUTES);
			if (alert && shift == 0)Alert(atxt); if (pushm) SendNotification(atxt);
		}

		// BUOVB - Bullish outside vertical bar

		if (showBUOVB && (H1 > H2 + Pips * Point) && (L1 < L2 - Pips * Point) && (C1 > C2))
		{
			ObjectCreate(PatternText[shift], OBJ_TEXT, 0, Time[shift1], Low[shift1] - Range*0.30);
			ObjectSetText(PatternText[shift], "BUOVB", 7, "Arial", Black);
			upArrow[shift1] = Low[shift1] - Range*0.10;
			atxt = Symbol() + " BUOVB " + TimeToString(Time[shift1], TIME_MINUTES);
			if (alert && shift == 0)Alert(atxt); if (pushm) SendNotification(atxt);
		}

		//  TMHTB - Two matching highs, trend breakout

		if (showTMHTB && ((H2 == H3) || (H2 + Pips * Point == H3) || (H2 - Pips * Point == H3)) && (C1 > H2 + Pips * Point))
		{
			ObjectCreate(PatternText[shift], OBJ_TEXT, 0, Time[shift1], Low[shift1] - Range*0.30);
			ObjectSetText(PatternText[shift], "TMHTB", 7, "Arial", Black);
			upArrow[shift1] = Low[shift1] - Range*0.10;
			atxt = Symbol() + " TMHTB " + TimeToString(Time[shift1], TIME_MINUTES);
			if (alert && shift == 0)Alert(atxt); if (pushm) SendNotification(atxt);
		}

		// Pin Bar pointing down

		if ((H1 <= H2) && (O1 >= L2) && (C1 >= O1) && (L1 < L2 - ((H1 - L1) / 3)))
		{
			ObjectCreate(PatternText[shift], OBJ_TEXT, 0, Time[shift1], Low[shift1] - Range*0.75);
			ObjectSetText(PatternText[shift], "Pin Bar", 7, "Arial", Black);
			upArrow[shift1] = Low[shift1] - Range*0.10;
			atxt = Symbol() + " Bullish Pin Bar " + TimeToString(Time[shift1], TIME_MINUTES);
			if (alert && shift == 0)Alert(atxt); if (pushm) SendNotification(atxt);
		}

		// Key Reversal

		if (showKEYRV && (L1 < L2) && (C1 > C2))
		{
			ObjectCreate(PatternText[shift], OBJ_TEXT, 0, Time[shift1], Low[shift1] - Range*0.75);
			ObjectSetText(PatternText[shift], "Key Reversal", 7, "Arial", Black);
			upArrow[shift1] = Low[shift1] - Range*0.10;
			atxt = Symbol() + " Bullish Key Reversal " + TimeToString(Time[shift1], TIME_MINUTES);
			if (alert && shift == 0)Alert(atxt); if (pushm) SendNotification(atxt);
		}



		//  Non - directional patterns

		   //  IB4 - Inside bar with range smaller than any of the 3 preceding Bars

		Range1 = H1 - L1;
		Range2 = H2 - L2;
		Range3 = H3 - L3;
		Range4 = High[shift + 4] - Low[shift + 4];

		if (showIB4 && (H1 < H2) && (L1 > L2) && (Range1 < Range2) && (Range1 < Range3) && (Range1 < Range4))
		{
			if (downArrow[shift2] == EMPTY_VALUE || downArrow[shift2] == 0)

			{
				ObjectCreate(PatternText[shift], OBJ_TEXT, 0, Time[shift1], High[shift1] + Range*0.75);
				ObjectSetText(PatternText[shift], "IB4", 7, "Arial", Black);
				downArrow[shift1] = High[shift1] + Range*0.10;
				atxt = Symbol() + " Bearish IB4 " + TimeToString(Time[shift1], TIME_MINUTES);
				if (alert && shift == 0)Alert(atxt); if (pushm) SendNotification(atxt);
			}

			else
				//         if(upArrow[shift2] == EMPTY_VALUE || upArrow[shift2] == 0)
			{
				ObjectCreate(PatternText[shift], OBJ_TEXT, 0, Time[shift1], Low[shift1] - Range*0.75);
				ObjectSetText(PatternText[shift], "IB4", 7, "Arial", Black);
				upArrow[shift1] = Low[shift1] - Range*0.10;
				atxt = Symbol() + " Bullish IB4 " + TimeToString(Time[shift1], TIME_MINUTES);
				if (alert && shift == 0)Alert(atxt); if (pushm) SendNotification(atxt);
			}
		}
	}

	return(0);
}
//+------------------------------------------------------------------+