// Heiken_Ashi_AutoWidth.mq4

// This code: Alexander Puzanov, http://www.mql5.com/en/job/new?prefered=f2011
// Idea & money: Stefan Marjoram, https://www.mql5.com/en/users/ipodbob


// 1.05.2017 7:30


#property copyright "Stefan Marjoram"
#property indicator_chart_window
#property strict
#property version "1.0"
#property indicator_buffers 4

#property indicator_label1	"HA Low/High"
#property indicator_type1		DRAW_HISTOGRAM
#property indicator_color1	clrRed
#property indicator_width1	1

#property indicator_label2	"HA High/Low"
#property indicator_type2		DRAW_HISTOGRAM
#property indicator_color2	clrRoyalBlue
#property indicator_width2	1

#property indicator_label3	"HA Down"
#property indicator_type3		DRAW_HISTOGRAM
#property indicator_color3	clrRed
#property indicator_width3	3

#property indicator_label4	"HA Up"
#property indicator_type4		DRAW_HISTOGRAM
#property indicator_color4	clrRoyalBlue
#property indicator_width4	3



input color	Color_Bullish = clrRoyalBlue;	// Bullish Color
input color	Color_Bearish = clrRed;				// Bearish Color



double
	buff_HA_Open[], buff_HA_Close[],
	buff_HA_HighLow[], buff_HA_LowHigh[]
;
int
	gi_Chart_Scale = WRONG_VALUE
;



void OnDeinit(const int reason) {}



int OnInit() {
	SetIndexBuffer(0, buff_HA_LowHigh); SetIndexEmptyValue(0, 0);
	SetIndexBuffer(1, buff_HA_HighLow); SetIndexEmptyValue(1, 0);
	SetIndexBuffer(2, buff_HA_Open); SetIndexEmptyValue(2, 0);
	SetIndexBuffer(3, buff_HA_Close); SetIndexEmptyValue(3, 0);

	SetIndexStyle(0, DRAW_HISTOGRAM, STYLE_SOLID, 1, Color_Bearish);
	SetIndexStyle(1, DRAW_HISTOGRAM, STYLE_SOLID, 1, Color_Bullish);
	f_Set_Buffers();
	
	IndicatorDigits(_Digits);
	IndicatorShortName("Heiken Ashi (auto width candle)");
	
	return(INIT_SUCCEEDED);
}



int OnCalculate(
		const int rates_total,
		const int prev_calculated,
		const datetime &time[],
		const double &open[],
		const double &high[],
		const double &low[],
		const double &close[],
		const long &TickVolume[],
		const long &volume[],
		const int &Spread[]
) {
	f_Set_Buffers();
	int
		i_Bar = fmax(1, rates_total - prev_calculated + (prev_calculated > 0))
	;
	if(prev_calculated == 0) {
		i_Bar--;
		if(Open[i_Bar] < Close[i_Bar]) {
			buff_HA_LowHigh[i_Bar] = Low[i_Bar];
			buff_HA_HighLow[i_Bar] = High[i_Bar];
		} else {
			buff_HA_LowHigh[i_Bar] = High[i_Bar];
			buff_HA_HighLow[i_Bar] = Low[i_Bar];
		}
		buff_HA_Open[i_Bar] = Open[i_Bar];
		buff_HA_Close[i_Bar] = Close[i_Bar];
	}
	double
		d_Open, d_Close, d_High, d_Low
	;
	
	i_Bar = fmin(rates_total - 2, i_Bar);
	while(i_Bar-- > 0) {
		d_Open = (buff_HA_Open[i_Bar + 1] + buff_HA_Close[i_Bar + 1]) / 2;
		d_Close = (Open[i_Bar] + High[i_Bar] + Low[i_Bar] + Close[i_Bar]) / 4;
		d_High = fmax(High[i_Bar], fmax(d_Open, d_Close));
		d_Low = fmin(Low[i_Bar], fmin(d_Open, d_Close));
		
		if(d_Open < d_Close) {
			buff_HA_LowHigh[i_Bar] = d_Low;
			buff_HA_HighLow[i_Bar] = d_High;
		} else {
			buff_HA_LowHigh[i_Bar] = d_High;
			buff_HA_HighLow[i_Bar] = d_Low;
		}
		buff_HA_Open[i_Bar] = d_Open;
		buff_HA_Close[i_Bar] = d_Close;
	}
	
	return(rates_total);
}


void OnChartEvent(
		const int Event_ID,
		const long& Event_Long,
		const double& Event_Double,
		const string& Event_String
) {
	if(IsStopped()) return;
	f_Set_Buffers();
}



void f_Set_Buffers() {
	int i_Chart_Scale = int(ChartGetInteger(0, CHART_SCALE));
	if(gi_Chart_Scale == i_Chart_Scale) return;
	
	gi_Chart_Scale = i_Chart_Scale;
	
	int i_Width = 0;
	switch(i_Chart_Scale) {
		case 0: i_Width = 1; break;
		case 1: i_Width = 1; break;
		case 2: i_Width = 2; break;
		case 3: i_Width = 3; break;
		case 4: i_Width = 6; break;
		case 5: i_Width = 14; break;
	}
	SetIndexStyle(2, DRAW_HISTOGRAM, STYLE_SOLID, i_Width, Color_Bearish);
	SetIndexStyle(3, DRAW_HISTOGRAM, STYLE_SOLID, i_Width, Color_Bullish);
	ChartRedraw();
}