//+------------------------------------------------------------------+ //| BKCV.mq5 | //| Azotskiy Aktiniy ICQ:695710750 | //| https://login.mql5.com/ru/users/Aktiniy | //+------------------------------------------------------------------+ //--- Build Kagi Chart Variable #property copyright "Azotskiy Aktiniy ICQ:695710750" #property link "https://login.mql5.com/ru/users/Aktiniy" #property version "1.00" #property description "Build Kagi Chart Variable" #property description " " #property description "This indicator makes drawing a chart Kagi as a matter of indicator window, and in the main chart window" #property indicator_chart_window #property indicator_buffers 0 #property indicator_plots 0 //--- plot 1 #property indicator_label1 "1" #property indicator_type1 DRAW_HISTOGRAM2 #property indicator_color1 clrRed #property indicator_style1 STYLE_SOLID #property indicator_width1 1 //--- Тип используемого разворота enum type_doorstep_enum { point=0, // Point procent=1, // Procent }; //--- input parameters input ENUM_TIMEFRAMES period_to_work=PERIOD_CURRENT; // Calculation period to build the chart input ENUM_TIMEFRAMES period_to_redraw=PERIOD_M1; // Refresh period chart input datetime start_data=D'2015.09.08 00:00:00'; // Start time to build the chart input type_doorstep_enum type_doorstep=point; // Type calculate doorstep input double doorstep=300; // Doorstep reversal input color color_yin_main=clrRed; // Color Yin line (main chart) input color color_yang_main=clrRed; // Color Yang line (main chart) input char width_yin_main=1; // Width Yin line (main chart) input char width_yang_main=2; // Width Yang line (main chart) input long magic_numb=65758473787389; // The magic number for draw objects //--- вспомогательные переменные MqlRates Price[]; // Буфер для хранения скопированных данных int bars_copy; // Количество скопированных баров //--- datetime stop_data; // Текущее время bool copy_history=false; // Результат копирования истории о ценах //--- double max; // Данные о последней линии double min; // Данные о последней линии double max_end; // Последний максимум double min_end; // Последний минимум char line_type; // Даные о последней линии 1=yang и -1=yin char line; // Даные о направлении линии 1=верх и -1=вниз datetime time; // Последнее время string name_obj; // Последнее имя //datetime time_change[]; // Массив для записи времени начала смены движения графика (в верх или в низ) //char time_line[]; // Массив для хранения информации на какой линии (Yin=0 или Yang=1) сменилось напрвление //double time_change_price[]; // Массив для записи цены смены движения графика //double time_central_price[]; // Массив для записи средней цены при смене движения графика uint a=0; // Переменная для построения графика, фиксирует количество разворотов графика //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- indicator buffers mapping //--- задание какие значения не будут прорисовываться for(char x=0; x<8; x++) { PlotIndexSetDouble(x,PLOT_EMPTY_VALUE,-1); } //--- устанавливаем внешний вид индикатора IndicatorSetString(INDICATOR_SHORTNAME,"BKCV "+IntegerToString(magic_numb)); // Имя индикатора IndicatorSetInteger(INDICATOR_DIGITS,_Digits); // Точность отображения //--- присваиваем названия графическим построениям PlotIndexSetString(0,PLOT_LABEL,"Yin"); //--- запрещяем показ результатов текущих значений для графических построений PlotIndexSetInteger(0,PLOT_SHOW_DATA,false); //--- установка цвета для линии PlotIndexSetInteger(0,PLOT_LINE_COLOR,clrRed); //--- установка толщины линии PlotIndexSetInteger(0,PLOT_LINE_WIDTH,1); //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Func Consolidation | //+------------------------------------------------------------------+ void func_consolidation() { //--- дата окончания построения stop_data=TimeCurrent(); //--- удаление всех графических объектов принадлежащих индикатору func_delete_objects(IntegerToString(magic_numb)+"_trend_yin_v",ObjectsTotal(0,-1,-1)); func_delete_objects(IntegerToString(magic_numb)+"_trend_yang_v",ObjectsTotal(0,-1,-1)); func_delete_objects(IntegerToString(magic_numb)+"_trend_h",ObjectsTotal(0,-1,-1)); func_delete_objects(IntegerToString(magic_numb)+"_trend_h",ObjectsTotal(0,-1,-1)); //--- копирование данных о ценах в основной буфер copy_history=func_all_copy(Price,period_to_work,start_data,stop_data); //--- вывод информации об ошибке при копировании данных о ценах if(copy_history==false)Alert("Error of copy history"); //--- построение графика Каги в главном окне func_kagi_main_chart(Price); //--- периресовка графика ChartRedraw(0); //--- } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[]) { //--- if(func_new_bar(period_to_redraw)==true) { func_consolidation(); } //--- return value of prev_calculated for next call return(rates_total); } //+------------------------------------------------------------------+ //| OnChartEvent | //+------------------------------------------------------------------+ void OnChartEvent(const int id, // идентификатор события const long& lparam, // параметр события типа long const double& dparam, // параметр события типа double const string& sparam) // параметр события типа string { if(id==CHARTEVENT_KEYDOWN) // Событие нажатия клавиши на клавиатуре { if(lparam==82) // Была нажата клавиша "R" { func_consolidation(); } } } //+------------------------------------------------------------------+ //| OnDeinit | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- удаление всех графических объектов принадлежащих индикатору func_delete_objects(IntegerToString(magic_numb)+"_label_2_",ObjectsTotal(0,-1,-1)); func_delete_objects(IntegerToString(magic_numb)+"_label_1_",ObjectsTotal(0,-1,-1)); func_delete_objects(IntegerToString(magic_numb)+"_time_2_",ObjectsTotal(0,-1,-1)); func_delete_objects(IntegerToString(magic_numb)+"_trend_yin_v",ObjectsTotal(0,-1,-1)); func_delete_objects(IntegerToString(magic_numb)+"_trend_yang_v",ObjectsTotal(0,-1,-1)); func_delete_objects(IntegerToString(magic_numb)+"_trend_h",ObjectsTotal(0,-1,-1)); func_delete_objects(IntegerToString(magic_numb)+"_trend_h",ObjectsTotal(0,-1,-1)); //--- периресовка графика ChartRedraw(0); } //+------------------------------------------------------------------+ //| Func Delete Objects | //+------------------------------------------------------------------+ void func_delete_objects(string name, int number) { string name_del; for(int x=0; x<=number; x++) { name_del=name+IntegerToString(x); //ObjectDelete(0,name_del); } } //+------------------------------------------------------------------+ //| Func Kagi Main Chart | //+------------------------------------------------------------------+ void func_kagi_main_chart(MqlRates &history[]) // Массив истории { //--- находим начальную точку отмечаем максимальную и минимальную цены if(history[0].open>history[0].close) //если в низ { line=-1; line_type=-1; name_obj=IntegerToString(magic_numb)+"_trend_yin_v"+IntegerToString(0); func_create_trend_line(name_obj,history[0].high,history[0].low,history[0].time,history[0].time,width_yin_main,color_yin_main); time=history[0].time; } else // если равна или в верх { line=1; line_type=1; name_obj=IntegerToString(magic_numb)+"_trend_yang_v"+IntegerToString(0); func_create_trend_line(name_obj,history[0].low,history[0].high,history[0].time,history[0].time,width_yang_main,color_yang_main); time=history[0].time; } max=history[0].high; min=history[0].low; max_end=max; min_end=min; for(int x=1; xmax_end)// Change { name_obj=IntegerToString(magic_numb)+"_trend_yin_u"+IntegerToString(x); func_create_trend_line(name_obj,min,max_end,time,time,width_yin_main,color_yin_main); name_obj=IntegerToString(magic_numb)+"_trend_yang_u"+IntegerToString(x); func_create_trend_line(name_obj,max_end,history[x].high,time,time,width_yang_main,color_yang_main); min=max_end; line_type=1; } else// No change { name_obj=IntegerToString(magic_numb)+"_trend_yin_u"+IntegerToString(x); func_create_trend_line(name_obj,min,history[x].high,time,time,width_yin_main,color_yin_main); } max=history[x].high; } break; } } if(max>(history[x].low+(func_calc_dorstep(history[x].close)*_Point)))// End low is lower on dorstep go DOWN { max_end=max; switch(line_type) { case 1:// Yang { name_obj=IntegerToString(magic_numb)+"_trend_yang_h"+IntegerToString(x); func_create_trend_line(name_obj,max_end,max_end,time,history[x].time,width_yang_main,color_yang_main); if(history[x].lowhistory[x].low)// End low is lower go DOWN { // Delete and make new object switch(line_type) { case -1:// Yin { ObjectDelete(0,name_obj); name_obj=IntegerToString(magic_numb)+"_trend_yin_d"+IntegerToString(x); func_create_trend_line(name_obj,max,history[x].low,time,time,width_yin_main,color_yin_main); min=history[x].low; } break; case 1:// Yang { ObjectDelete(0,name_obj); if(history[x].lowmax_end)// Change { name_obj=IntegerToString(magic_numb)+"_trend_yin_u"+IntegerToString(x); func_create_trend_line(name_obj,min_end,max_end,history[x].time,history[x].time,width_yin_main,color_yin_main); name_obj=IntegerToString(magic_numb)+"_trend_yang_u"+IntegerToString(x); func_create_trend_line(name_obj,max_end,history[x].high,history[x].time,history[x].time,width_yang_main,color_yang_main); min=max_end; line_type=1; } else// No change { name_obj=IntegerToString(magic_numb)+"_trend_yin_u"+IntegerToString(x); func_create_trend_line(name_obj,min_end,history[x].high,history[x].time,history[x].time,width_yin_main,color_yin_main); } } break; case 1:// Yang { name_obj=IntegerToString(magic_numb)+"_trend_yang_h"+IntegerToString(x); func_create_trend_line(name_obj,min_end,min_end,time,history[x].time,width_yang_main,color_yang_main); name_obj=IntegerToString(magic_numb)+"_trend_yang_u"+IntegerToString(x); func_create_trend_line(name_obj,min_end,history[x].high,history[x].time,history[x].time,width_yang_main,color_yang_main); } break; } time=history[x].time; max=history[x].high; line=1; } } break; } } } //+------------------------------------------------------------------+ //| Func Object Create Trend Line | //+------------------------------------------------------------------+ void func_create_trend_line(string name, double price1, double price2, datetime time1, datetime time2, int width, color color_line) { ObjectCreate(0,name,OBJ_TREND,0,time1,price1,time2,price2); //--- установим цвет линии ObjectSetInteger(0,name,OBJPROP_COLOR,color_line); //--- установим стиль отображения линии ObjectSetInteger(0,name,OBJPROP_STYLE,STYLE_SOLID); //--- установим толщину линии ObjectSetInteger(0,name,OBJPROP_WIDTH,width); //--- отобразим на переднем (false) или заднем (true) плане ObjectSetInteger(0,name,OBJPROP_BACK,false); //--- включим (true) или отключим (false) режим продолжения отображения линии влево ObjectSetInteger(0,name,OBJPROP_RAY_LEFT,false); //--- включим (true) или отключим (false) режим продолжения отображения линии вправо ObjectSetInteger(0,name,OBJPROP_RAY_RIGHT,false); } //+------------------------------------------------------------------+ //| Func New Bar | //+------------------------------------------------------------------+ bool func_new_bar(ENUM_TIMEFRAMES period_time) { //---- static datetime old_Times[22];// массив для хранения старых значений bool res=false; // переменная результата анализа int i=0; // номер ячейки массива old_Times[] datetime new_Time[1]; // время нового бара switch(period_time) { case PERIOD_M1: i= 0; break; case PERIOD_M2: i= 1; break; case PERIOD_M3: i= 2; break; case PERIOD_M4: i= 3; break; case PERIOD_M5: i= 4; break; case PERIOD_M6: i= 5; break; case PERIOD_M10: i= 6; break; case PERIOD_M12: i= 7; break; case PERIOD_M15: i= 8; break; case PERIOD_M20: i= 9; break; case PERIOD_M30: i=10; break; case PERIOD_H1: i=11; break; case PERIOD_H2: i=12; break; case PERIOD_H3: i=13; break; case PERIOD_H4: i=14; break; case PERIOD_H6: i=15; break; case PERIOD_H8: i=16; break; case PERIOD_H12: i=17; break; case PERIOD_D1: i=18; break; case PERIOD_W1: i=19; break; case PERIOD_MN1: i=20; break; case PERIOD_CURRENT: i=21; break; } // скопируем время последнего бара в ячейку new_Time[0] int copied=CopyTime(_Symbol,period_time,0,1,new_Time); if(copied>0) // все ок. данные скопированы { if(old_Times[i]!=new_Time[0]) // если старое время бара не равно новому { if(old_Times[i]!=0) res=true; // если это не первый запуск, то истина = новый бар old_Times[i]=new_Time[0]; // запоминаем время бара } } //---- return(res); } //+------------------------------------------------------------------+ //| Func All Copy | //+------------------------------------------------------------------+ bool func_all_copy(MqlRates &result_array[],// массив ответа ENUM_TIMEFRAMES period, // таймфрейм datetime data_start, // начальная дата datetime data_stop) // конечная дата { //--- объявление вспомогательных переменных bool x=false; // переменная для ответа функции int result_copy=-1; // количество скопированных данных //--- добавление переменных и массивов для расчёта static MqlRates interim_array[]; // временный динамический массив для хранения скопированных данных static int bars_to_copy; // количество баров для копирования static int bars_copied; // количество уже скопированных баров с начальной даты //--- узнаём текущее количество баров на временном промежутке bars_to_copy=Bars(_Symbol,period,data_start,data_stop); //--- подсчитываем количество баров которые надо скопировать bars_to_copy-=bars_copied; //--- если данные копируются не в первый раз if(bars_copied>0) { bars_copied--; bars_to_copy++; } //--- меняем размер приёмного массива ArrayResize(interim_array,bars_to_copy); //--- копируем данные во временный массив result_copy=CopyRates(_Symbol,period,0,bars_to_copy,interim_array); //--- проверяем результат копирования данных if(result_copy!=-1) // если копирование в промежуточный массив было успешно { ArrayCopy(result_array,interim_array,bars_copied,0,WHOLE_ARRAY); // копируем данные из временного в основной массив x=true; // присваиваем положительный ответ функции bars_copied+=result_copy; // увеличиваем значение скопированных данных bars_copy=bars_copied; // выводим значение о скопированных барах в глобальную переменную } //--- return(x); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Func Calculate Doorstep | //+------------------------------------------------------------------+ int func_calc_dorstep(double price) { double x=0; // Переменная для ответа if(type_doorstep==0) // Если расчет нужно произволить по пунктам { x=doorstep; } if(type_doorstep==1) // Если расчет нужно производить в процентах { x=price/_Point*doorstep/100; } return((int)x); } //+------------------------------------------------------------------+