#property copyright "Alexander Elgin"
#property link      "alexmost113@mail.ru"
#property strict
#property indicator_chart_window

#property indicator_color1 Green
#property indicator_color2 Gold
#property indicator_color3 DarkOrange
#property indicator_color4 Red
#property indicator_color5 FireBrick

#property indicator_style1 STYLE_DOT
#property indicator_style2 STYLE_DOT
#property indicator_style3 STYLE_DASH
#property indicator_style4 STYLE_SOLID
#property indicator_style5 STYLE_DASHDOTDOT

const string INDICATOR_NAME = "Fractal Support Resistance";
enum  ENUM_DESCD_IDX { SUPPORT_DESCRIPTION, RESISTANCE_DESCRIPTION };
const string lineDescriptions[] = {"support", "resistance"};
const int BAR_TO_START_SCAN_FROM = 2;

int timeframes[] = {PERIOD_H1,        PERIOD_H4,        PERIOD_D1,        PERIOD_W1,        PERIOD_MN1};
int     styles[] = {indicator_style1, indicator_style2, indicator_style3, indicator_style4, indicator_style5};
color   colors[] = {indicator_color1, indicator_color2, indicator_color3, indicator_color4, indicator_color5};

//+------------------------------------------------------------------+
int OnInit()
 {
	int initSuccess = INIT_SUCCEEDED;
	IndicatorShortName(INDICATOR_NAME);
	return(initSuccess);
 }
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
 {
	for(int timeframe_index = 0; timeframe_index < ArraySize(timeframes); timeframe_index++)
	 {
		for(int object_type_index = 0; object_type_index < ArraySize(lineDescriptions); object_type_index++)
		 {
			ObjectDelete(getTrendLineName(lineDescriptions[object_type_index], timeframes[timeframe_index]));
		 }
    }
 }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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 &tick_volume[], const long &volume[], const int &spread[])
 {
	for(int timeframe_index = 0; timeframe_index < ArraySize(timeframes); timeframe_index++)
	 {
		if(Period() <= timeframes[timeframe_index])
		 {
			drawResistance(getUpperFractalBar(timeframes[timeframe_index], BAR_TO_START_SCAN_FROM), timeframe_index);
			drawSupport(getLowerFractalBar(timeframes[timeframe_index], BAR_TO_START_SCAN_FROM), timeframe_index);
		 }
	 }
	return(rates_total);
 }
//+------------------------------------------------------------------+
int getUpperFractalBar(int timeframe, int starting_bar)
 {
	for(int bar = starting_bar; bar < Bars; bar++)
		if(isUpperFractal(timeframe, bar))
		   return(bar);
	return (-1);
 }
//+------------------------------------------------------------------+
bool isUpperFractal(int timeframe, int bar)
 {
	for(int offset = -2; offset <= 2; offset++)
		if( (offset != 0) && (iHigh(Symbol(), timeframe, bar + offset) > iHigh(Symbol(), timeframe, bar)) )
		   return(false);
	return (true);
 }
//+------------------------------------------------------------------+
int getLowerFractalBar(int timeframe, int starting_bar)
 {
	for(int bar = starting_bar; bar < Bars; bar++)
		if(isLowerFractal(timeframe, bar)) return(bar);
	return (-1);
 }
//+------------------------------------------------------------------+
bool isLowerFractal(int timeframe, int bar)
 {
	for(int offset = -2; offset <= 2; offset++)
		if( (offset != 0) && (iLow(Symbol(), timeframe, bar + offset) < iLow(Symbol(), timeframe, bar)) ) return(false);
	return (true);
 }
//+------------------------------------------------------------------+
void drawResistance(int bar_index, int timeframe_index)
 {
	if(bar_index > 0) drawTrendLine(getTrendLineName(lineDescriptions[RESISTANCE_DESCRIPTION], timeframes[timeframe_index]), iHigh(Symbol(), timeframes[timeframe_index], bar_index), colors[timeframe_index], styles[timeframe_index]);
 }
//+------------------------------------------------------------------+
void drawSupport(int bar_index, int timeframe_index)
 {
	if(bar_index > 0) drawTrendLine(getTrendLineName(lineDescriptions[SUPPORT_DESCRIPTION], timeframes[timeframe_index]), iLow(Symbol(), timeframes[timeframe_index], bar_index), colors[timeframe_index], styles[timeframe_index]);
 }
//+------------------------------------------------------------------+
void drawTrendLine(string object_name, double price, color line_color, int line_style)
 {
	ObjectDelete(object_name);
	ObjectCreate(object_name, OBJ_HLINE, 0, Time[0], price, Time[Bars - 1], price);
	ObjectSet(object_name, OBJPROP_COLOR, line_color);
	ObjectSet(object_name, OBJPROP_STYLE, line_style);
 }
//+------------------------------------------------------------------+
string getTrendLineName(string object_type, int timeframe)
 {
	return(object_type + getTimeframeName(timeframe));
 }
//+------------------------------------------------------------------+
string getTimeframeName(int timeframe)
 {
	static int timeframe_periods[] = {PERIOD_M1, PERIOD_M5, PERIOD_M15, PERIOD_M30, PERIOD_H1, PERIOD_H4, PERIOD_D1, PERIOD_W1, PERIOD_MN1};
	static string timeframe_names[] = {"M1", "M5", "M15", "M30", "H1", "H4", "D1", "W1", "MN1"};
	
	for(int i = 0; i < ArraySize(timeframe_periods); i++)
	 {
		if(timeframe == timeframe_periods[i])
		   return (timeframe_names[i]);
    }
	return("Unknown");
 }
//+------------------------------------------------------------------+