/* ГДЕ КИТАЙ? + волатильность вынести в отдельную библиотеку + отдельно волатильность по регионам (азию выделить) + при щелчке на метке события появляется окно с графиком статистики */ #property copyright "Клименко Сергей" #property version "1.00" #property strict #include #import "EcLib.ex4" void ref_load( string &ref_array[][150], string &words_array[]); int EcCopy( datetime TimeStart, datetime TimeEnd, ec_struct &ec_array[]); #import #property indicator_separate_window #property indicator_buffers 3 #property indicator_plots 3 #property indicator_label1 "Volatility Index" #property indicator_label2 "Volatility Index Max" #property indicator_label3 "Volatility Index Min" //================================================================================================ input int Depth = 50; //глубина в днях для вычисления волатильности int calendar_events_check_sum0 = 0, i, j, j0, l, k, //счетчики line, //количество строк в календаре font_size, news_time_sorted[][2], //1. секунды от TimeCurrent; 2 - eventID calendar_db, settings_file, event_count = 0, event_zero = 0, event_today0, event_today1, period_count = 0, //счетчики меток, реестра, флагов и ТФ today_bar_count, //счетчик баров текущего дня TF[10], //вычисленные ТФ TF_count = 0, //счетчик ТФ bars_received, total_bars, TradeDays, ref_ID, handle_READ, GMT2local, //секунды GMT2server, //секунды server2local; //секунды double Volatility_Index[], //массив для хранения индексов волатильности для разных ТФ Volatility_Index_Max[], //фиктивный индикатор - фиксирует верт. шкалу Volatility_Index_Min[], chart_scale_step, chart_scale_max, chart_scale_min, volat; MqlRates day_go_array[], //волатильность по дням current_tf_array[]; //волатильность текущего ТФ за день string str, str2, font, ref[][150], words[], words_str, tooltip_str, event_label_name; datetime last_midnight, t00, x, today0, today1, WeekStart, WeekEnd; bool Volatility_Index_Calc = true, update_calendar = false, ref_bool[][150]; MqlDateTime time_full, time_full0, time_full1; ec_struct ec[], ec00[]; struct event_label_struct { uint Event_ID; string name; datetime DT; color TextClr; }; event_label_struct event_label[]; //======================================INIT===================================================== int OnInit() { handle_READ = FileOpen("ec\\DB\\ec.ini", FILE_COMMON|FILE_READ|FILE_CSV, ';'); string str0; do str0 = FileReadString(handle_READ); while(str0 != "[GMT2serverShiftMin]"); GMT2server = StrToInteger(FileReadString(handle_READ))*60; FileClose(handle_READ); update_calendar = true; GMT2local = int(MathRound(TimeGMTOffset()/3600)*3600) * (- 1); server2local = GMT2local - GMT2server; settings_file = FileOpen("calendar\\settings.csv", FILE_COMMON|FILE_READ|FILE_CSV, ";"); TimeCurrent(time_full); ref_load(ref, words); ref_ID = ArrayRange(ref, 0) - 1; ArrayResize(ref_bool, ArraySize(ref)); //обнуляем буферный справочник for(k=0; k <= ref_ID; k++) for(j=1; j < 150; j++) ref_bool[k, j] = false; //читаем настройки while(!FileIsEnding(settings_file)) //currency { str = FileReadString(settings_file); j = 1; while(ref[2, j] != NULL) {if(ref[2, j] == str) {ref_bool[2, j] = true; break;} j++;} if(FileIsLineEnding(settings_file)) break; } while(!FileIsEnding(settings_file)) //country { str = FileReadString(settings_file); j = 1; while(ref[3, j] != NULL) {if(ref[3, j] == str) {ref_bool[3, j] = true; break;} j++;} if(FileIsLineEnding(settings_file)) break; } while(!FileIsEnding(settings_file)) //volatility { str = FileReadString(settings_file); j = 1; while(ref[9, j] != NULL) {if(ref[9, j] == str) {ref_bool[9, j] = true; break;} j++;} if(FileIsLineEnding(settings_file)) break; } FileClose(settings_file); chart_scale_max = 1.04; chart_scale_min = 0.88; ChartSetDouble(0, CHART_FIXED_MAX, chart_scale_max); ChartSetDouble(0, CHART_FIXED_MIN, chart_scale_min); chart_scale_step = (chart_scale_max - chart_scale_min) / 20; //===================================CALENDAR===================================================== TimeCurrent(time_full0); WeekStart = (TimeCurrent()+server2local - TimeDayOfWeek(TimeCurrent()+server2local)*3600*24); TimeToStruct(WeekStart, time_full0); time_full0.hour = 0; time_full0.min = 0; time_full0.sec = 0; WeekStart = StructToTime(time_full0); WeekEnd = WeekStart + 3600*24*7; j = EcCopy(WeekStart, WeekEnd, ec00); //неделя вск-вск, включая праздники j=0; for(i=0; i < ArraySize(ec00); i++) if(ref_bool[2, ec00[i].Currency_ID] && ref_bool[3, ec00[i].Country_ID] && ref_bool[9, (ec00[i].PACK & VOLATILITY)] && (ec00[i].FLAGS&EVENT_TYPE) == 2) //только новости { ArrayResize(ec, j + 1, 5); ArrayResize(event_label, j + 1, 5); ec[j] = ec00[i]; event_label[j].DT = ec[j].DT + DTSTART; event_label[j].Event_ID = ec[j].Event_ID; event_label[j].name = "event" + IntegerToString(j, 3, '0'); j++; } event_count = j; //check sum calendar_events_check_sum0 += TimeDayOfYear(StructToTime(time_full0))*1000000; calendar_events_check_sum0 += TimeDayOfYear(StructToTime(time_full1))*1000; calendar_events_check_sum0 += ref_bool[9, 1] + ref_bool[9, 2] + ref_bool[9, 3]; if(!GlobalVariableCheck("calendar_events_check_sum")) { x = GlobalVariableSet("calendar_events_check_sum", 0); update_calendar = true; } if(GlobalVariableGet("calendar_events_check_sum") != calendar_events_check_sum0) { update_calendar = true; } //===========================================EVENT_LABEL================================================ if(update_calendar) { //Рисуем календарь на графике font_size = 8; font = "Tahoma"; i = 0; while(i < event_count) { words_str = words[ec[i].Words_ID]; tooltip_str = "[" + ref[ 5,(ec[i].PACK&MEASURE)>>8] + "]"; if(ec[i].Actual != EMPTY_VALUE) tooltip_str += DoubleToString(ec[i].Actual, 2) + " "; else tooltip_str += "---- "; if(ec[i].Forecast != EMPTY_VALUE) tooltip_str += DoubleToString(ec[i].Forecast, 2) + " "; else tooltip_str += "---- "; if(ec[i].Previous != EMPTY_VALUE) tooltip_str += DoubleToString(ec[i].Previous, 2) + " "; else tooltip_str += "---- "; if((ec[i].PACK & VOLATILITY) == 3) event_label[i].TextClr = C'255,255,255'; if((ec[i].PACK & VOLATILITY) == 2) event_label[i].TextClr = C'150,150,150'; if((ec[i].PACK & VOLATILITY) == 1) event_label[i].TextClr = C'50,50,50'; str = "" + TimeToString(ec[i].DT + GMT2local, TIME_MINUTES) + " " + ref[10, ec[i].Country_ID] + " " + //country short name ref[StrToInteger(ref[17,(ec[i].Cat_ID&CAT2)>>8]), ec[i].Cat_ID&CAT3] + " " + ref[ 4,(ec[i].Cat_ID&CAT2)>>8] + " " + words_str + " [" + ref[ 6,(ec[i].PACK&COMPARE)>>4] + "][" + ref[1, ec[i].Period_ID] + "]"; StringReplace(str, "[]", ""); str = StringTrimRight(str); if (ObjectFind( event_label[i].name) == -1) ObjectCreate( event_label[i].name, OBJ_TEXT, 0, TimeCurrent(), 0); ObjectSetInteger(0, event_label[i].name, OBJPROP_BACK, 0); ObjectSetInteger(0, event_label[i].name, OBJPROP_SELECTABLE, 0); ObjectSetString( 0, event_label[i].name, OBJPROP_TEXT, str); ObjectSetInteger(0, event_label[i].name, OBJPROP_TIME, ec[i].DT + DTSTART + GMT2local - server2local); ObjectSetDouble( 0, event_label[i].name, OBJPROP_PRICE, chart_scale_max - chart_scale_step*(i)); ObjectSetString( 0, event_label[i].name, OBJPROP_FONT, font); ObjectSetInteger(0, event_label[i].name, OBJPROP_FONTSIZE, font_size); ObjectSetInteger(0, event_label[i].name, OBJPROP_ANCHOR, ANCHOR_LEFT_UPPER); ObjectSetInteger(0, event_label[i].name, OBJPROP_ALIGN, ALIGN_LEFT); ObjectSetInteger(0, event_label[i].name, OBJPROP_COLOR, event_label[i].TextClr); ObjectSetString( 0, event_label[i].name, OBJPROP_TOOLTIP, tooltip_str); i++; }//end.while //зачистка лишних меток for (k = i; k < 200; k++) { event_label_name = "event" + IntegerToString(k, 3, '0'); if(ObjectFind( event_label_name) == 0) ObjectDelete( event_label_name); } event_label_name = "CurrentTime"; if (ObjectFind( event_label_name) == -1) ObjectCreate( event_label_name, OBJ_HLINE, 0, TimeCurrent() - server2local, 1); ObjectSet( event_label_name, OBJPROP_COLOR, clrLime); ObjectSetInteger(0, event_label_name, OBJPROP_BACK, 1); ObjectSetInteger(0, event_label_name, OBJPROP_SELECTABLE, 0); event_label_name = "CurrentTimeLabel"; if (ObjectFind( event_label_name) == -1) ObjectCreate( event_label_name, OBJ_TEXT, 0, TimeCurrent() - server2local, 1); ObjectSet( event_label_name, OBJPROP_COLOR, clrLime); ObjectSetInteger(0, event_label_name, OBJPROP_BACK, 1); ObjectSetInteger(0, event_label_name, OBJPROP_SELECTABLE, 0); ObjectSetString( 0, event_label_name, OBJPROP_FONT, font); ObjectSetInteger(0, event_label_name, OBJPROP_FONTSIZE, font_size); ObjectSetInteger(0, event_label_name, OBJPROP_ANCHOR, ANCHOR_LEFT_UPPER); ObjectSetInteger(0, event_label_name, OBJPROP_ALIGN, ALIGN_LEFT); event_label_name = "vlt0"; if (ObjectFind( event_label_name) == -1) ObjectCreate( event_label_name, OBJ_VLINE, 2, TimeCurrent(), 1); ObjectSetInteger(0, event_label_name, OBJPROP_COLOR, clrLime); ObjectSetInteger(0, event_label_name, OBJPROP_BACK, 1); ObjectSetInteger(0, event_label_name, OBJPROP_SELECTABLE, 0); x = GlobalVariableSet("calendar_events_check_sum", calendar_events_check_sum0); update_calendar = false; Print("calendar updated"); }//end.if.update_calendar ChartRedraw(0); 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 &tick_volume[], const long &volume[], const int &spread[]) { //======================================NEW_BAR==================================================== if(rates_total != prev_calculated) { TimeCurrent(time_full0); time_full0.hour = 0; time_full0.min = 0; time_full0.sec = 0; today0 = StructToTime(time_full0); // server time today1 = today0 + 3600*24; // server time for (i=0; i < event_count; i++) if((ec[i].DT + DTSTART + GMT2local - server2local) >= TimeCurrent()) {event_zero = i; break;} if(i == event_count) event_zero = i; for (i=0; i < event_count; i++) if((ec[i].DT + DTSTART + GMT2local - server2local) >= today0) {event_today0 = i; break;} if(i == event_count) event_today0 = i; for (i=0; i < event_count; i++) if((ec[i].DT + DTSTART + GMT2local - server2local) >= today1) {event_today1 = i; break;} if(i == event_count) event_today1 = i; t00 = time[57]; j = 0; j0 = 0; for(i=0; i < event_count; i++) { if((i>0) && (TimeDay(event_label[i].DT + DTSTART + GMT2local) > TimeDay(event_label[i-1].DT + DTSTART + GMT2local))) { j++; if(TimeDay(event_label[i].DT + DTSTART + GMT2local) == TimeDay(TimeCurrent()+server2local)) j0=j; } ObjectSetInteger(0, event_label[i].name, OBJPROP_TIME, t00); ObjectSetDouble( 0, event_label[i].name, OBJPROP_PRICE, 1 - chart_scale_step*(i - event_zero + j)); } //обновляем метку текущего времени t00 = time[68]; ObjectSet("CurrentTimeLabel", OBJPROP_TIME1, t00); ObjectSet("CurrentTimeLabel", OBJPROP_PRICE1, 1 - chart_scale_step*j0); ObjectSet("CurrentTime", OBJPROP_PRICE1, 1 - chart_scale_step*j0); ObjectSet("vlt0", OBJPROP_TIME1, TimeCurrent()); ChartRedraw(0); } //=====================================NEW_TICK==================================================== //обновляем метку текущего времени на каждом тике ObjectSetString(0, "CurrentTimeLabel", OBJPROP_TEXT, TimeToString(TimeCurrent() + server2local, TIME_MINUTES)); //=====================================VOLATILITY================================================== if(Volatility_Index_Calc) { TimeCurrent(time_full); time_full.hour = 0; time_full.min = 0; time_full.sec = 0; last_midnight = StructToTime(time_full); today_bar_count = CopyRates(NULL, Period(), last_midnight, TimeCurrent(), current_tf_array); SetIndexStyle (0, DRAW_HISTOGRAM, STYLE_SOLID, 2, clrSilver); SetIndexBuffer (0, Volatility_Index); SetIndexShift (0, PERIOD_D1/Period() - today_bar_count); for (i=0; i<=PERIOD_D1/Period()-1; i++) Volatility_Index[i] = 0; SetIndexStyle (1, DRAW_LINE, STYLE_SOLID, 1, clrBrown); SetIndexBuffer (1, Volatility_Index_Max); SetIndexShift (1, PERIOD_D1/Period() - today_bar_count); for (i=0; i<=PERIOD_D1/Period()-1; i++) Volatility_Index_Max[i] = 0; SetIndexStyle (2, DRAW_LINE, STYLE_SOLID, 1, clrGreen); SetIndexBuffer (2, Volatility_Index_Min); SetIndexShift (2, PERIOD_D1/Period() - today_bar_count); for (i=0; i<=PERIOD_D1/Period()-1; i++) Volatility_Index_Min[i] = 0; // вычисляем индекс волатильности i = 0; TradeDays = 0; while(i < Depth*2) { bars_received = CopyRates("EURUSD", PERIOD_D1, last_midnight-60*60*24-60*60*24*i, last_midnight-60*60*24*i-1, //минус секунда, чтобы не брать свечу нового дня day_go_array); bars_received = CopyRates("EURUSD", Period(), last_midnight-60*60*24-60*60*24*i, last_midnight-60*60*24*i-1, current_tf_array); if(bars_received>0) { for(k=0; k <= ArraySize(current_tf_array)-1; k++) { volat = (current_tf_array[k].high - current_tf_array[k].low) / (day_go_array[0].high - day_go_array[0].low); Volatility_Index[ArraySize(current_tf_array)-1-k] += volat/Depth; }//end.for TradeDays++; }//end.if i++; if(TradeDays == Depth) break; }//end.while Volatility_Index_Max[PERIOD_D1/Period()] = Volatility_Index[ArrayMaximum(Volatility_Index, PERIOD_D1/Period(), 0)]; Volatility_Index_Min[PERIOD_D1/Period()] = Volatility_Index[ArrayMinimum(Volatility_Index, PERIOD_D1/Period(), 0)]; for(k = PERIOD_D1/Period()-1; k>=0; k--) { Volatility_Index_Min[k] = EMPTY_VALUE; //Volatility_Index_Min[0]; Volatility_Index_Max[k] = EMPTY_VALUE; //Volatility_Index_Max[0]; } Volatility_Index_Calc = false; ChartRedraw(0); } return(rates_total); }