//+------------------------------------------------------------------+
//|                                                 Price Action.mq4 |
//|                                                  Jason Normandin |
//|                                                                  |
//+------------------------------------------------------------------+

#property copyright "Jason Normandin"
#property link      ""

#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 Red
#property indicator_color2 Lime


extern 	int		AtrPeriod		= 20;
extern  double	PinBarNose 		= 0.6;	// Portion of bar which must be nose
extern	int		PinBarLookback	= 3;	// Bars back to look to insure highest high / lowest low
extern  double	PinBarSize		= 0.7;	// Minimun total bar size as a portion of ATR


double	dBearPriceActionBuffer[];
double 	dBullPriceActionBuffer[];

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init() {

	SetIndexBuffer(0,dBearPriceActionBuffer);
	SetIndexStyle (0,DRAW_ARROW);
	SetIndexArrow (0,161);
   
	SetIndexBuffer(1,dBullPriceActionBuffer);
	SetIndexStyle (1,DRAW_ARROW);
	SetIndexArrow (1,161);
   
	return(0);
}


//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit() {

	return(0);
	
}


//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start() {

	// Number of bars already processed.
	// Always reprocess the last completed bar
	int		iBarsCalced = IndicatorCounted();
	if (iBarsCalced > 0) iBarsCalced--;

	// Iterate through bars checking for patterns
	// Do not process last incomplete bar
	for (int i=Bars-iBarsCalced-1;i>0;i--) {
		if (flagBullishPinBar(i)) continue;
		if (flagBearishPinBar(i)) continue;
	}
	
	return(0);
}

bool flagBullishPinBar(int i) {
	
	double 	dATR1 		= iATR(NULL,0,AtrPeriod,1);
	double 	dBarSize	= High[i] - Low[i] + Point;
	double	dNoseSize	= MathMin(Open[i],Close[i]) - Low[i];
	
	// Nose of PinBar must be of a certain percent of total bar
	if (dNoseSize / dBarSize < PinBarNose) {
		dBullPriceActionBuffer[i] = EMPTY_VALUE;
		return(false);
	}
	
	// Bar must be close to average average ATR in total length
	if (dBarSize / PinBarSize < dATR1) {
		dBullPriceActionBuffer[i] = EMPTY_VALUE;
		return(false);
	}
	
	// Low of bar must be lower than low of previous bars
	if (iLowest(NULL,0,MODE_LOW,PinBarLookback+1,i) > i) {
		dBullPriceActionBuffer[i] = EMPTY_VALUE;
		return(false);
	}
		
	// All criteria passed
	dBullPriceActionBuffer[i] = Low[i];
	return(true);
}

bool flagBearishPinBar(int i) {

	double 	dATR1 		= iATR(NULL,0,AtrPeriod,1);
	double 	dBarSize	= High[i] - Low[i] + Point;
	double	dNoseSize	= High[i] - MathMax(Open[i],Close[i]);
	
	// Nose of PinBar must be of a certain percent of total bar
	if (dNoseSize / dBarSize < PinBarNose) {
		dBearPriceActionBuffer[i] = EMPTY_VALUE;
		return(false);
	}
	
	// Bar must be at least average ATR in total length
	if (dBarSize / PinBarSize < dATR1) {
		dBearPriceActionBuffer[i] = EMPTY_VALUE;
		return(false);
	}
	
	// High of bar must be higher than high of previous bars
	if (iHighest(NULL,0,MODE_HIGH,PinBarLookback+1,i) > i) {
		dBearPriceActionBuffer[i] = EMPTY_VALUE;
		return(false);
	}
	
	// All criteria passed
	dBearPriceActionBuffer[i] = High[i];
	return(true);
}