//+------------------------------------------------------------------+ //| ATR_MS.mq5 | //| Copyright 2013, https://login.mql5.com/ru/users/tol64 | //| Site, http://tol64.blogspot.com/2013/05/216.html | //+------------------------------------------------------------------+ //--- Свойства индикатора #property copyright "Copyright 2013, http://tol64.blogspot.com" #property link "https://www.mql5.com/de/articles/752" #property description "email: hello.tol64@gmail.com" #property version "1.0" #property indicator_separate_window // Индикатор в отдельном подокне #property indicator_minimum 0 // Минимальное значение индикатора #property indicator_buffers 6 // Количество буферов для расчёта индикатора #property indicator_plots 6 // Количество графических серий //--- Константа для возврата терминалу команды на пересчёт индикатора #define RESET 0 #define LEVELS 6 // Количество уровней #define SYMBOLS 6 // Количество символов //--- Подключим класс для работы с канвой #include //--- Внешние параметры input int IndicatorPeriod=14; // Indicator Period sinput string dlm01=""; //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - input string Symbol02 ="GBPUSD"; // Symbol 02 input string Symbol03 ="AUDUSD"; // Symbol 03 input string Symbol04 ="NZDUSD"; // Symbol 04 input string Symbol05 ="USDCAD"; // Symbol 05 input string Symbol06 ="USDCHF"; // Symbol 06 sinput string dlm02=""; //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - input int Level01 =10; // Level 01 input int Level02 =50; // Level 02 input int Level03 =100; // Level 03 input int Level04 =200; // Level 04 input int Level05 =400; // Level 05 input int Level06 =600; // Level 06 //--- Глобальные переменные и массивы CCanvas canvas; // Загрузка класса //--- Переменные/массивы для копирования данных из OnCalculate() int on_calc_rates_total =0; // Размер входных таймсерий int on_calc_prev_calculated =0; // Обработано баров на предыдущем вызове datetime on_calc_time[]; // Время открытия double on_calc_open[]; // Цены открытия double on_calc_high[]; // Максимальные цены double on_calc_low[]; // Минимальные цены double on_calc_close[]; // Цены закрытия long on_calc_tick_volume[]; // Тиковые объёмы long on_calc_volume[]; // Реальные объёмы int on_calc_spread[]; // Спред //--- Структура массивов буферов // для отрисовки значений индикатора struct buffers { double data[]; }; buffers buffer_atr[SYMBOLS]; //--- Структуры массивов для подготовки данных struct temp_time { datetime time[]; }; temp_time temp_symbol_time[SYMBOLS]; struct temp_atr { double value[]; }; temp_atr temp_atr_values[SYMBOLS]; //--- Для хранения и проверки времени первого бара в терминале datetime series_first_date[SYMBOLS]; datetime series_first_date_last[SYMBOLS]; //--- Массив времени бара, от которого начинать отрисовку datetime limit_time[SYMBOLS]; //--- Массив уровней индикатора int levels[LEVELS]; //--- Массив названий символов string symbols_names[SYMBOLS]; //--- Хэндлы символов int handle_symbol[SYMBOLS]; //--- Цвета линий индикатора color line_color[SYMBOLS]= {clrRed,clrDodgerBlue,clrLimeGreen,clrGold,clrAqua,clrMagenta}; //--- Строка символизирующая отсутствие символа string empty_symbol="EMPTY"; //--- Свойства подокна индикатора int number_subwindow =WRONG_VALUE; // Номер подокна int chart_width =0; // Ширина графика int subwindow_height =0; // Высота подокна int last_chart_width =0; // Последняя в памяти ширина графика int last_subwindow_height =0; // Последняя в памяти высота подокна int subwindow_center =0; // Центр подокна по горизонтали int subwindow_vcenter =0; // Центр подокна по вертикали string shortname_subwindow ="ATR_MS"; // Короткое имя индикатора string prefix =shortname_subwindow+"_"; // Префикс для объектов //--- Свойства канвы string canvas_name =prefix+"canvas"; // Название канвы color canvas_bg_color =clrBlack; // Цвет фона канвы uchar canvas_opacity =190; // Степень прозрачности int font_size =16; // Размер шрифта string font_name ="Calibri"; // Шрифт ENUM_COLOR_FORMAT clr_format =COLOR_FORMAT_ARGB_RAW; // Компоненты цвета не обрабатываются терминалом //--- Сообщения канвы string message_invalid_handle ="Невалидный хэндл индикатора! Подождите пожалуйста..."; string message_data_available ="Подготовка данных! Подождите пожалуйста..."; string message_number_data ="Данных меньше, чем период индикатора! Попробуйте уменьшить значение."; string message_is_synchronized ="Данные не синхронизированы! Подождите пожалуйста..."; string message_formation_data =""; string message_synchro_update =""; string message_last =""; //--- Максимальное количество баров установленное в настройках терминала int terminal_max_bars=0; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- Проверим корректность входных параметров if(!CheckInputParameters()) return(INIT_PARAMETERS_INCORRECT); //--- Включим таймер с интервалом 1 секунда EventSetMillisecondTimer(1000); //--- Установим шрифт для отображения в канве canvas.FontSet(font_name,font_size,FW_NORMAL); //--- Инициализация массивов InitArrays(); //--- Инициализируем массив символов InitSymbolsNames(); //--- Инициализируем массив уровней InitLevels(); //--- Получим хэндлы индикаторов GetHandles(); //--- Установим свойства индикатора SetPropertiesIndicator(); //--- Получим количество баров установленное в настройках терминала terminal_max_bars=TerminalInfoInteger(TERMINAL_MAXBARS); //--- Очистим комментарий Comment(""); //--- Обновим график ChartRedraw(); //--- Инициализация прошла успешно return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Деинициализация | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { if(reason==REASON_REMOVE || // Если индикатор удалён с графика или reason==REASON_CHARTCHANGE || // символ или период был изменён или reason==REASON_RECOMPILE || // программа была перекомпилирована или reason==REASON_CHARTCLOSE || // график был закрыт или reason==REASON_CLOSE || // терминал был закрыт или reason==REASON_PARAMETERS) // параметры были изменены { //--- Отключим таймер EventKillTimer(); //--- Удалим уровни DeleteLevels(); //--- Удалим вертикальные линии DeleteVerticalLines(); //--- Удалим канву DeleteCanvas(); //--- Освободим расчётную часть индикатора for(int s=0; s500) { Comment("Уменьшите период индикатора! Indicator Period: ",IndicatorPeriod,"; Limit: 500;"); printf("Уменьшите период индикатора! Indicator Period: %d; Limit: %d;",IndicatorPeriod,500); return(false); } //--- return(true); } //+------------------------------------------------------------------+ //| Устанавливает свойства индикатора | //+------------------------------------------------------------------+ void SetPropertiesIndicator() { //--- Установим короткое имя IndicatorSetString(INDICATOR_SHORTNAME,shortname_subwindow); //--- Установим количество знаков IndicatorSetInteger(INDICATOR_DIGITS,_Digits); //--- Определим буферы для отрисовки for(int s=0; sPeriodSeconds()*number_bars) { datetime copied_time[]; //--- Получим первую дату символа-периода в базе терминала // Get the first date of the symbol-period in the terminal base SeriesInfoInteger(symbols_names[s],Period(),SERIES_FIRSTDATE,series_firstdate); //--- Загрузим/скопируем ещё указанное количество баров // Download / copy another specified number of bars if(CopyTime(symbols_names[s],Period(),0,array_size+number_bars,copied_time)) { //--- Если время первого бара массива с вычетом кол-ва подгружаемых баров раньше, // чем время первого бара на графике, остановим цикл // If the time of the first bar of the array minus the number of loaded bars // is earlier than the time of the first bar on the chart, we stop the cycle if(copied_time[0]-PeriodSeconds()*number_bars=total_period_bars) break; } } //--- Проверим готовность данных индикатора for(int i=0; i<5; i++) { //--- Скопируем указанное количество данных // Copy the specified amount of time data (all calculated for the indicator) if(CopyBuffer(handle_symbol[s],0,0,calculated_values,data)) { //--- Если скопировалось нужное количество, остановим цикл // If the required amount has been copied, stop the cycle if(ArraySize(data)>=calculated_values) break; } } //--- Если скопировано меньше данных // значит нужно совершить ещё одну попытку if(ArraySize(time)series_first_date[s]) { //--- Выведем сообщение в журнал Print("(",symbols_names[s],",",TimeframeToString(Period()), ") > Была загружена/сформирована более глубокая история: ", series_first_date_last[s]," > ",series_first_date[s]); //--- Запомним дату series_first_date_last[s]=series_first_date[s]; load=true; } } } } //--- Если была загружена/сформирована более глубокая история, то // отправим команду на обновление графических серий индикатора //--- If a deeper history has been loaded / formed, then // send a command to update the graphic series of the indicator if(load) return(false); //--- return(true); } //+------------------------------------------------------------------+ //| Проверяет синхронизированность по символу/периоду | //+------------------------------------------------------------------+ bool CheckSymbolIsSynchronized() { //--- Если есть соединение с сервером, то проверим синхронизированность данных // If there is a connection to the server, then we will check the data synchronization. if(TerminalInfoInteger(TERMINAL_CONNECTED)) { for(int s=0; s=limit_time[symbol_number]) { //--- Скопируем время for(int k=0; k=limit_time[symbol_number]) count_current_period++; //--- Если в зоне индикатора и // время текущего символа и время указанного символа совпадают if(count_current_period>=IndicatorPeriod && time[i]==temp_symbol_time[symbol_number].time[i]) { //--- Если полученное значение не пустое // If the received value is not empty if(temp_atr_values[symbol_number].value[i]!=EMPTY_VALUE) { check_value=true; buffer_atr[symbol_number].data[i]=temp_atr_values[symbol_number].value[i]; } } //--- Установим пустое значение, если не получилось установить выше if(!check_value) buffer_atr[symbol_number].data[i]=EMPTY_VALUE; } //+------------------------------------------------------------------+ //| Добавляет указанный символ в окно обзор рынка | //+------------------------------------------------------------------+ string CheckGetSymbol(string symbol) { int symbol_total =0; // Количество символов string nm_symbol =""; // Имя символа //--- Если передали пустую строку, то вернуть пустую строку if(symbol=="") return(empty_symbol); //--- Всего символов на сервере symbol_total=SymbolsTotal(false); //--- Пройтись по всему списку символов for(int s=symbol_total-1; s>=0; s--) { //--- Имя символа на сервере nm_symbol=SymbolName(s,false); //--- Если есть такой символ, то if(nm_symbol==symbol) { //--- установим его в окно Обзор Рынка и SymbolSelect(nm_symbol,true); //--- вернём его имя return(symbol); } } //--- Если такого символа нет, то // вернём строку символизирующую отсутствие символа return(empty_symbol); } //+------------------------------------------------------------------+ //| Установим свойства подокна | //+------------------------------------------------------------------+ void SetSubwindowProperties() { //--- Получим номер подокна индикатора number_subwindow=ChartWindowFind(0,shortname_subwindow); //--- Получим ширину и высоту подокна chart_width=(int)ChartGetInteger(0,CHART_WIDTH_IN_PIXELS); subwindow_height=(int)ChartGetInteger(0,CHART_HEIGHT_IN_PIXELS,number_subwindow); //--- Получим центр подокна subwindow_center=chart_width/2; subwindow_vcenter=subwindow_height/2; } //+------------------------------------------------------------------+ //| Копирует данные из OnCalculate | //+------------------------------------------------------------------+ void CopyDataOnCalculate(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[]) { on_calc_rates_total=rates_total; on_calc_prev_calculated=prev_calculated; ArrayCopy(on_calc_time,time); ArrayCopy(on_calc_open,open); ArrayCopy(on_calc_high,high); ArrayCopy(on_calc_low,low); ArrayCopy(on_calc_close,close); ArrayCopy(on_calc_tick_volume,tick_volume); ArrayCopy(on_calc_volume,volume); ArrayCopy(on_calc_spread,spread); } //+------------------------------------------------------------------+ //| Изменяет размер массивов под размер основного массива | //+------------------------------------------------------------------+ void ResizeCalculateArrays() { for(int s=0; s0 && subwindow_vcenter>0) { canvas.Erase(ColorToARGB(canvas_bg_color,canvas_opacity)); canvas.TextOut(subwindow_center,subwindow_vcenter,message_text,ColorToARGB(clrRed),TA_CENTER|TA_VCENTER); canvas.Update(); } } } //+------------------------------------------------------------------+ //| Удаляет канву | //+------------------------------------------------------------------+ void DeleteCanvas() { //--- Удалим канву, если она есть if(ObjectFind(0,canvas_name)>0) { //--- Перед удалением произведём эффект исчезания for(int i=canvas_opacity; i>0; i-=5) { canvas.Erase(ColorToARGB(canvas_bg_color,(uchar)i)); canvas.Update(); } //--- Удаление канвы canvas.Destroy(); } } //+------------------------------------------------------------------+ //| Процент прогресса | //+------------------------------------------------------------------+ void PercentProgress(int i,int symbols_number,double &percent) { string message_text=""; percent=(double(i)/on_calc_rates_total)*100; //--- if(percent<=9.99) message_text="0"+DoubleToString(percent,0); else if(percent<99) message_text=DoubleToString(percent,0); else message_text="99"; //--- message_last=message_synchro_update="Подготовка данных ("+IntegerToString(on_calc_rates_total)+" баров) : "+ symbols_names[symbols_number]+ "("+IntegerToString(symbols_number+1)+"/"+IntegerToString(SYMBOLS)+") - "+message_text+"% ... "; } //+------------------------------------------------------------------+ //| Установка уровней | //+------------------------------------------------------------------+ void SetLevels() { //--- Получим номер подокна индикатора number_subwindow=ChartWindowFind(0,shortname_subwindow); //--- Установим уровни for(int s=0; s=0) { //--- Если была ошибка при удалении, сообщим об этом if(!ObjectDelete(0,Name)) Print("Ошибка ("+IntegerToString(GetLastError())+") при удалении объекта!"); } } //+------------------------------------------------------------------+ //| Создание горизонтальной линии | //+------------------------------------------------------------------+ void CreateHorizontalLines(long chart_id, // id графика int number_window, // номер окна string name_line, // имя объекта double price, // уровень цены int width_line, // толщина линии ENUM_LINE_STYLE style_line, // стиль линии color color_line, // цвет линии bool selectable, // нельзя выделить объект, если FALSE bool select, // выделение bool back, // фоновое расположение string tooltip) // нет всплывающей подсказки, если "\n" { //--- Если объект успешно создан... if(ObjectCreate(chart_id,name_line,OBJ_HLINE,number_window,0,price)) { // ...установим ему свойства ObjectSetInteger(chart_id,name_line,OBJPROP_SELECTABLE,selectable); ObjectSetInteger(chart_id,name_line,OBJPROP_SELECTED,select); ObjectSetInteger(chart_id,name_line,OBJPROP_BACK,back); ObjectSetInteger(chart_id,name_line,OBJPROP_STYLE,style_line); ObjectSetInteger(chart_id,name_line,OBJPROP_WIDTH,width_line); ObjectSetInteger(chart_id,name_line,OBJPROP_COLOR,color_line); ObjectSetString(chart_id,name_line,OBJPROP_TOOLTIP,tooltip); } } //+------------------------------------------------------------------+ //| Создание вертикальной линии | //+------------------------------------------------------------------+ void CreateVerticalLines(long chart_id, // id графика int number_window, // номер окна datetime time, // время string name_line, // имя объекта int width_line, // толщина линии ENUM_LINE_STYLE style_line, // стиль линии color color_line, // цвет линии bool selectable, // нельзя выделить объект, если FALSE string description_text, // текст описания string tooltip) // нет всплывающей подсказки, если "\n" { //--- Если объект успешно создан... if(ObjectCreate(chart_id,name_line,OBJ_VLINE,number_window,time,0)) { // ...установим ему свойства ObjectSetInteger(chart_id,name_line,OBJPROP_TIME,time); ObjectSetInteger(chart_id,name_line,OBJPROP_SELECTABLE,selectable); ObjectSetInteger(chart_id,name_line,OBJPROP_STYLE,style_line); ObjectSetInteger(chart_id,name_line,OBJPROP_WIDTH,width_line); ObjectSetInteger(chart_id,name_line,OBJPROP_COLOR,color_line); ObjectSetString(chart_id,name_line,OBJPROP_TEXT,description_text); ObjectSetString(chart_id,name_line,OBJPROP_TOOLTIP,tooltip); } } //+------------------------------------------------------------------+ //| Коррекция значения по количеству знаков в цене (double) | //+------------------------------------------------------------------+ double CorrectValueBySymbolDigits(double value) { return(_Digits==3 || _Digits==5) ? value*=10 : value; } //+------------------------------------------------------------------+ //| Преобразует таймфрейм в строку | //+------------------------------------------------------------------+ string TimeframeToString(ENUM_TIMEFRAMES timeframe) { string str=""; //--- Если переданное значение некорректно, берем таймфрейм текущего графика if(timeframe==WRONG_VALUE || timeframe== NULL) timeframe= Period(); switch(timeframe) { case PERIOD_M1 : str="M1"; break; case PERIOD_M2 : str="M2"; break; case PERIOD_M3 : str="M3"; break; case PERIOD_M4 : str="M4"; break; case PERIOD_M5 : str="M5"; break; case PERIOD_M6 : str="M6"; break; case PERIOD_M10 : str="M10"; break; case PERIOD_M12 : str="M12"; break; case PERIOD_M15 : str="M15"; break; case PERIOD_M20 : str="M20"; break; case PERIOD_M30 : str="M30"; break; case PERIOD_H1 : str="H1"; break; case PERIOD_H2 : str="H2"; break; case PERIOD_H3 : str="H3"; break; case PERIOD_H4 : str="H4"; break; case PERIOD_H6 : str="H6"; break; case PERIOD_H8 : str="H8"; break; case PERIOD_H12 : str="H12"; break; case PERIOD_D1 : str="D1"; break; case PERIOD_W1 : str="W1"; break; case PERIOD_MN1 : str="MN1"; break; } //--- return(str); } //+------------------------------------------------------------------+