//+------------------------------------------------------------------+ //| MultiSymbolPriceDivergence.mq5 | //| Copyright 2013, https://login.mql5.com/ru/users/tol64 | //| Site, http://tol64.blogspot.com | //+------------------------------------------------------------------+ //--- Свойства индикатора #property copyright "Copyright 2013, http://tol64.blogspot.com" #property link "http://tol64.blogspot.com/2013/06/218.html" #property description "email: hello.tol64@gmail.com" #property version "1.0" //--- #property indicator_chart_window // Выводить индикатор в окно графика #property indicator_buffers 25 // Количество буферов для расчёта индикатора #property indicator_plots 5 // Количество графических серий //--- Цвета цветовых буферов #property indicator_color1 clrDodgerBlue,C'0,50,100' #property indicator_color2 clrMagenta,C'130,0,130' #property indicator_color3 clrGold,C'160,140,0' #property indicator_color4 clrAqua,C'0,140,140' #property indicator_color5 clrLimeGreen,C'20,80,20' //--- Константа для возврата терминалу команды на пересчёт индикатора #define RESET 0 //--- Количество символов #define SYMBOLS 5 //--- Имя программы #define PROGRAM_NAME MQL5InfoString(MQL5_PROGRAM_NAME) //--- Подключим класс для работы с канвой #include //--- Подключаем свои библиотеки #include #include #include //--- Тип рисования данных enum ENUM_DRAWTYPE { LINES =0, // Lines BARS =1, // Bars CANDLES =2 // Candles }; //--- Режим начальной точки расхождения цен enum ENUM_START_POINT { VERT_LINE =0, // Vertical Line MONTH =1, // Month WEEK =2, // Week DAY =3, // Day HOUR =4 // Hour }; //--- Внешние параметры input ENUM_DRAWTYPE DrawType =CANDLES; // Draw Type input ENUM_START_POINT StartPriceDivergence =VERT_LINE; // Start Price Divergence input bool TwoColor =false; // Two Colored Bars/Candles sinput string dlm01=""; //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - input string Symbol02 ="EURUSD"; // Symbol 02 input bool Inverse02 =false; // Inverse Symbol 02 input string Symbol03 ="GBPUSD"; // Symbol 03 input bool Inverse03 =false; // Inverse Symbol 03 input string Symbol04 ="EURGBP"; // Symbol 04 input bool Inverse04 =false; // Inverse Symbol 04 input string Symbol05 ="USDCAD"; // Symbol 05 input bool Inverse05 =false; // Inverse Symbol 05 input string Symbol06 ="USDCHF"; // Symbol 06 input bool Inverse06 =false; // Inverse Symbol 06 //--- Структура массивов индикаторных буферов struct buffers { double open[]; // Буфер для цен открытия double high[]; // Буфер для цен максимумов double low[]; // Буфер для цен минимумов double close[]; // Буфер для цен закрытия double icolor[]; // Буфер для определения цвета элемента }; buffers buffer_data[SYMBOLS]; //--- Загрузка класса 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[]; // Спред //--- Для хранения и проверки времени первого бара в терминале datetime series_first_date[SYMBOLS]; datetime series_first_date_last[SYMBOLS]; //--- Массив времени бара, от которого начинать отрисовку datetime limit_time[SYMBOLS]; //--- Массив названий символов string symbols_names[SYMBOLS]; //--- Массив названий символов bool inverse[SYMBOLS]; //--- Цвета линий индикатора color line_color[SYMBOLS]= {clrDodgerBlue,clrLimeGreen,clrGold,clrAqua,clrMagenta}; //--- Строка символизирующая отсутствие символа string empty_symbol="EMPTY"; //--- Свойства графика int number_window =WRONG_VALUE; // Номер окна индикатора int chart_width =0; // Ширина графика int chart_height =0; // Высота графика int last_chart_width =0; // Последняя в памяти ширина графика int last_chart_height =0; // Последняя в памяти высота графика int chart_wcenter =0; // Центр графика по горизонтали int chart_vcenter =0; // Центр графика по вертикали color color_bar_up =clrRed; // Цвет бара вверх color color_bar_down =C'100,0,0'; // Цвет бара вниз string shortname_indicator ="MS_PriceDivergence"; // Короткое имя индикатора string prefix =shortname_indicator+"_"; // Префикс для объектов //--- Имя вертикальной линии начальной точки расхождения цен string start_price_divergence=prefix+"start_price_divergence"; //--- Свойства канвы 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_data_available ="Подготовка данных! Подождите пожалуйста..."; string message_is_synchronized ="Данные не синхронизированы! Подождите пожалуйста..."; string message_formation_data =""; string message_data_update =""; string message_last =""; //--- ENUM_TIMEFRAMES timeframe_start_point =Period(); // Таймфрейм для точки расхождения цен datetime first_period_time =NULL; // Время первого указанного периода данных на графике double level_divergence =0.0; // Цена начальной точки расхождения цен datetime time_divergence =NULL; // Время начальной точки расхождения цен double symbol_difference[SYMBOLS]; // Разница в цене относительно текущего символа double inverse_difference[SYMBOLS]; // Разница, которая образуется при расчёте инверсии //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- Проверим, не используется ли сейчас индикатор в тестере if(!CheckTesterMode()) return(INIT_FAILED); //--- Установим цвет барам/свечам SetBarColors(); //--- Определим период для начальной точки расхождения цен // Define the period for the starting point of price divergence. InitModeStartPriceDivergence(); //--- Проверим корректность входных параметров // Check the correctness of the input parameters if(!CheckInputParameters()) return(INIT_PARAMETERS_INCORRECT); //--- Включим таймер с интервалом 1 секунда EventSetMillisecondTimer(1000); //--- Установим шрифт для отображения в канве canvas.FontSet(font_name,font_size,FW_NORMAL); //--- Инициализация массивов InitArrays(); //--- Инициализируем массив символов InitSymbolsNames(); //--- Инициализируем массив инверсий InitInverse(); //--- Установим свойства индикатора SetPropertiesIndicator(); //--- Установим вертикальную линию начала расхождения цен SetLineStartPricesDivergence(); //--- Очистим комментарий 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(); //--- Удалим вертикальные линии DeleteVerticalLines(); //--- Удалим канву DeleteCanvas(); //--- Отключим масштабирование ChartSetInteger(0,CHART_SCALEFIX,false); //--- Очистим комментарий Comment(""); } //--- Обновим график ChartRedraw(); } //+------------------------------------------------------------------+ //| 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[]) // Спред { //--- Для определения, с какого бара производить расчёт int limit=0; //--- Сделаем копию параметров OnCalculate() CopyDataOnCalculate(rates_total,prev_calculated, time,open,high,low,close, tick_volume,volume,spread); //--- Если это первый расчёт или загружена более глубокая история или были заполнены пропуски истории // If this is the first calculation or a deeper history has been loaded or the history gaps have been filled if(prev_calculated==0) { //--- Обнулим индикаторные буферы - Zero indicator buffers ZeroIndicatorBuffers(); //--- Получим свойства подокна - Get the properties of the subwindow SetSubwindowProperties(); //--- Установим канву - Install the canvas SetCanvas(); //--- Загрузим и сформируем необходимое/имеющееся количество данных // Load and generate the necessary / available amount of data. LoadFormationData(); LoadFormationDataHighTF(); //--- Проверяет количество доступных данных у всех символов // Checks the amount of data available for all symbols. if(!CheckAvailableData()) return(RESET); //--- Если загружена более глубокая история // If a deeper hisstory is loaded if(!CheckEventLoadHistory()) return(RESET); //--- Проверим синхронизированность данных по символу/периоду на данный момент // Check the synchronization of data on the symbol / period at the moment if(!CheckSymbolIsSynchronized()) return(RESET); //--- Определим для каждого символа, с какого бара начинать отрисовку // For each symbol find the bar at which to start drawing if(!DetermineBeginForCalculate()) return(RESET); //--- Если дошли до этого момента, то значит OnCalculate() вернёт ненулевое значение // и это нужно запомнить. Reaching this point means OnCalculate() returned nonzero. on_calc_prev_calculated=rates_total; } //--- Если нужно пересчитать только последние значения // If you only need to recalculate the last else limit=prev_calculated-1; //--- Заполним индикаторные буферы - Fill indicator buffers for(int s=0; sopen) buffer_data[symbol_number].icolor[i]=0; //--- иначе это бар вниз и используем второй цвет else buffer_data[symbol_number].icolor[i]=1; } //--- Если одноцветный режим, то используем для всех баров/свечей первый цвет else buffer_data[symbol_number].icolor[i]=0; } //+------------------------------------------------------------------+ //| Копирует данные из 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 ZeroIndicatorBuffers() { for(int s=0; s