//+------------------------------------------------------------------+ //| X_O.mq4 | //| Nthint | //| fxnthint@gmail.com | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| При внесении изменений в исходный код, пожалуйста оставляйте //| информацию об авторе индикатора и добавляйте свои данные и //| краткое описание изменений в отдельном комментарии. Спасибо. //+------------------------------------------------------------------+ #property copyright "Schneider Anatoliy (Nthint) 2010" #property link "fxnthint@gmail.com" #property indicator_chart_window extern color up_color = RoyalBlue; // цвет Х extern color down_color = Crimson; // цвет О extern color border_color = Black; // цвет рамки extern int border_width = 1; // толщина рамки extern int size = 50; // высота одного Х или О extern int reverse = 3; // разворотный параметр extern int width = 3; // ширина одного Х или О в барах extern int bars = 1000; // количество баров для расчета extern bool separate_years = true; // переключатель разделителей extern color separator_color = Black;// цвет разделителей extern int separator_style = 2; // тип линии extern bool mark_months = true; // переключатель выделения месяцев extern color winter_color = LightCyan; // цвет зимы extern color spring_color = LimeGreen; // цвет весны extern color summer_color = Yellow; // цвет лета extern color autumn_color = Orange; // цвет осени string prefix = "SXO_"; // префикс чтобы отличать объекты индикатора int num = 0; // нумеруем Х и О int last_month = -1; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int init() { calculateXO(); } //+------------------------------------------------------------------+ //| Custom indicator deinitialization function | //+------------------------------------------------------------------+ int deinit() { deleteObjects(); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int start() { calculateXO(); } //+------------------------------------------------------------------+ //| Строим ХО | //+------------------------------------------------------------------+ int calculateXO() { int i; int last_time = calculateColumns(); int start_price; string type = "-"; double last_price = 0, close_price = 0; num = 0; if (bars == 0) bars = Bars-1; for (i = bars; i >= 0; i--) { //+----------------- сначала проверяем тип первого бара в истории ---+ //+----------------------------------- и заполняем первый столбец ---+ if (type == "-") { start_price = Open[bars]/Point; while (start_price % size != 0) start_price--; last_price = (start_price)*Point; if (Low[i] < last_price - size*Point) { type = "O"; while (Low[i] < last_price - size*Point) { drawObject("O", last_price, last_time, Time[i]); last_price -= size*Point; } } else if (High[i] > last_price + size*Point) { type = "X"; while (High[i] > last_price + size*Point) { drawObject("X", last_price, last_time, Time[i]); last_price += size*Point; } } else continue; } else //+----------------------- затем выполняем алгоритм построения ХО ---+ if (type == "O") { close_price = last_price; while (Low[i] < last_price - size*Point) { drawObject("O", last_price, last_time, Time[i]); last_price -= size*Point; } if (High[i] > close_price + size*(reverse+1)*Point) { last_time -= width; type = "X"; last_price += size*Point; while (High[i] > last_price + size*Point) { drawObject("X", last_price, last_time, Time[i]); last_price += size*Point; } } } else if (type == "X") { close_price = last_price; while (High[i] > last_price + size*Point) { drawObject("X", last_price, last_time, Time[i]); last_price += size*Point; } if (Low[i] < close_price - size*(reverse+1)*Point) { last_time -= width; type = "O"; last_price -= size*Point; while (Low[i] < last_price - size*Point) { drawObject("O", last_price, last_time, Time[i]); last_price -= size*Point; } } } } // конец цикла по барам } //+------------------------------------------------------------------+ //| Расчитываем с какого бара нужно начать построение ХО | //+------------------------------------------------------------------+ int calculateColumns() { int i; int last_time; int number_of_columns = 1; int start_price; string type = "-"; double last_price = 0, close_price = 0; if (bars == 0) bars = Bars-1; last_time = bars; num = 0; for (i = bars; i >= 0; i--) { if (type == "-") { start_price = Open[bars]/Point; while (start_price % size != 0) start_price--; last_price = start_price*Point; if (Low[i] < last_price - size*Point) { type = "O"; while (Low[i] < last_price - size*Point) { last_price -= size*Point; } } else if (High[i] > last_price + size*Point) { type = "X"; while (High[i] > last_price + size*Point) { last_price += size*Point; } } else continue; } else if (type == "O") { close_price = last_price; while (Low[i] < last_price - size*Point) { last_price -= size*Point; } if (High[i] > close_price + size*(reverse+1)*Point) { last_time -= width; type = "X"; last_price += size*Point; number_of_columns++; while (High[i] > last_price + size*Point) { last_price += size*Point; } } } else if (type == "X") { close_price = last_price; while (High[i] > last_price + size*Point) { last_price += size*Point; } if (Low[i] < close_price - size*(reverse+1)*Point) { last_time -= width; type = "O"; last_price -= size*Point; number_of_columns++; while (Low[i] < last_price - size*Point) { last_price -= size*Point; } } } } // конец цикла по барам return(number_of_columns * width); } //+------------------------------------------------------------------+ //| Рисуем графические объекты | //+------------------------------------------------------------------+ void drawObject(string type, double price_01, int time, datetime price_time) { string name; datetime time_01, time_02; double price_02; color box_color; if (separate_years) { if (TimeMonth(price_time) != last_month && TimeMonth(price_time) == 1) { name = prefix + "year_separator_" + num; if(!ObjectCreate(name, OBJ_VLINE, 0, Time[time], 0)) { // продолжаем работу } ObjectSetText(name, DoubleToStr(TimeYear(price_time), 0)); ObjectSet(name, OBJPROP_COLOR, separator_color); ObjectSet(name, OBJPROP_STYLE, separator_style); ObjectSet(name, OBJPROP_BACK, true); } } if (mark_months) { if (TimeMonth(price_time) == last_month) { if (type == "O") box_color = down_color; else if (type == "X") box_color = up_color; } switch (TimeMonth(price_time)) { case 12: if (last_month != 12) box_color = winter_color; last_month = 12; break; case 1: if (last_month != 1) box_color = winter_color; last_month = 1; break; case 2: if (last_month != 2) box_color = winter_color; last_month = 2; break; case 3: if (last_month != 3) box_color = spring_color; last_month = 3; break; case 4: if (last_month != 4) box_color = spring_color; last_month = 4; break; case 5: if (last_month != 5) box_color = spring_color; last_month = 5; break; case 6: if (last_month != 6) box_color = summer_color; last_month = 6; break; case 7: if (last_month != 7) box_color = summer_color; last_month = 7; break; case 8: if (last_month != 8) box_color = summer_color; last_month = 8; break; case 9: if (last_month != 9) box_color = autumn_color; last_month = 9; break; case 10: if (last_month != 10) box_color = autumn_color; last_month = 10; break; case 11: if (last_month != 11) box_color = autumn_color; last_month = 11; break; } } else { if (type == "O") box_color = down_color; else if (type == "X") box_color = up_color; } if (type == "O") { name = prefix + num + "_" + DoubleToStr(price_01, Digits); time_01 = Time[time]; time_02 = Time[time-width]; price_02 = price_01 - size*Point; if(!ObjectCreate(name, OBJ_RECTANGLE, 0, time_01, price_01, time_02, price_02)) { // данная проверка созданы чтобы не загрязнять логи сообщениями об ошибке // когда объект с таким именем уже создан } ObjectSet(name, OBJPROP_BACK, true); ObjectSet(name, OBJPROP_COLOR, box_color); name = prefix + "border_" + num + "_" + DoubleToStr(price_01, Digits); if(!ObjectCreate(name, OBJ_RECTANGLE, 0, time_01, price_01, time_02, price_02)) { // продолжаем работу } ObjectSet(name, OBJPROP_BACK, false); ObjectSet(name, OBJPROP_COLOR, border_color); ObjectSet(name, OBJPROP_WIDTH, border_width); } else if (type == "X") { name = prefix + num + "_" + DoubleToStr(price_01, Digits); time_01 = Time[time]; time_02 = Time[time-width]; price_02 = price_01 + size*Point; if(!ObjectCreate(name, OBJ_RECTANGLE, 0, time_01, price_01, time_02, price_02)) { // продолжаем работу } ObjectSet(name, OBJPROP_BACK, true); ObjectSet(name, OBJPROP_COLOR, box_color); name = prefix + "border_" + num + "_" + DoubleToStr(price_01, Digits); if(!ObjectCreate(name, OBJ_RECTANGLE, 0, time_01, price_01, time_02, price_02)) { // продолжаем работу } ObjectSet(name, OBJPROP_BACK, false); ObjectSet(name, OBJPROP_COLOR, border_color); ObjectSet(name, OBJPROP_WIDTH, border_width); } num++; } //+------------------------------------------------------------------+ //| функция для удаления объектов, созданных индикатором | //+------------------------------------------------------------------+ void deleteObjects() { string name; int i = 0; while (i < ObjectsTotal()) { name = ObjectName(i); if ( (StringSubstr(name, 0, StringLen(prefix)) == prefix) ) { ObjectDelete(name); } else i++; } } //+------------------------------------------------------------------+