//+------------------------------------------------------------------+ //| Article-16461-MQL5-Market-Profile-Introduction.mq5 | //| Copyright 2026, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property indicator_chart_window #property indicator_plots 0 //--- input parameters input uint InpStartDate =0; /* day number to start calculation */ // номер дня, с которого начнём расчёт (0 - текущий, 1 - предыдущий, и т.д.) input uint InpShowDays =3; /* number of days to display */ // количество отображаемых дней, начиная и включая день в InpStartDate input int InpMultiplier =1; /* histogram length multiplier */ // множитель длины гистограммы input color InpAsiaSession =clrGold; /* Asian session */ // цвет гистограммы азиатской сессии input color InpEuropeSession =clrBlue; /* European session */ // цвет гистограммы европейской сессии input color InpAmericaSession =clrViolet; /* American session */ // цвет гистограммы американской сессии input uint InpEuropeStartHour =8; /* European session opening hour */ // час открытия европейской сессии input uint InpAmericaStartHour=14; /* American session opening hour */ // час открытия американской сессии //--- уникальный префикс для идентификации графических объектов, принадлежащих индикатору string ExtPrefixUniq; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- создаём префикс для имён объектов string number=StringFormat("%I64d", GetTickCount64()); ExtPrefixUniq=StringSubstr(number, StringLen(number)-4); Print("Indicator \"Market Profile\" started, prefix=", ExtPrefixUniq); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| 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[]) { //--- время открытия текущего дневного бара datetime static open_time=0; //--- номер последнего дня для расчетов //--- (при InpStartDate = 0 и InpShowDays = 3, lastday = 3) //--- (при InpStartDate = 1 и InpShowDays = 3, lastday = 4) etc ... uint lastday=InpStartDate+InpShowDays; //--- если первый расчет уже был if(prev_calculated!=0) { //--- получаем время открытия текущего дневного бара datetime current_open=iTime(Symbol(), PERIOD_D1, 0); //--- если текущий день не рассчитываем if(InpStartDate!=0) { //--- если время открытия не было получено - уходим if(current_open==open_time) return(rates_total); } //--- обновляем время открытия open_time=current_open; //--- далее будем рассчитывать только один день, так как все остальные дни уже посчитаны при первом запуске lastday=InpStartDate+1; } //--- в цикле по указанному количеству дней (либо InpStartDate+InpShowDays при первом запуске, либо InpStartDate+1 на каждом тике) for(uint day=InpStartDate; day=InpAmericaStartHour) { //--- в массиве американской сессии, в ячейках от start_box до stop_box увеличиваем счётчики баров for(int ind=start_box; ind=InpEuropeStartHour && hour0) { //--- получаем очередную цену методом прибавления количества пунктов ind к цене Low дневного бара //--- получаем время начала отрезка (время открытия дневного бара) //--- и время конца отрезка (время открытия дневного бара + количество баров, хранящееся в ячейке ind массива boxes_asia[]) double price=low_day+ind*point; datetime time1=day_rate[0].time; datetime time2=time1+boxes_asia[ind]*box_length*InpMultiplier; //--- создаём префикс имени графического объекта азиатской сессии string prefix=ExtPrefixUniq+"_"+day_prefix+"_Asia_"+StringFormat("%.5f", price); //--- рисуем прямоугольник (отрезок линии) на рассчитанных координатах с цветом для азиатской сессии DrawBox(prefix, price, time1, time2, InpAsiaSession); } } //--- европейская сессия //--- в цикле по количеству пунктов дневного бара for(int ind=0; ind0) { //--- получаем очередную цену методом прибавления количества пунктов ind к цене Low дневного бара //--- получаем время начала отрезка (время открытия дневного бара + время правого края профиля азиатской сессии) //--- и время конца отрезка (время начала отрезка европейской сессии + количество баров, хранящееся в ячейке ind массива boxes_europe[]) double price=low_day+ind*point; datetime time1=day_rate[0].time+boxes_asia[ind]*box_length*InpMultiplier; datetime time2=time1+boxes_europe[ind]*box_length*InpMultiplier; //--- создаём префикс имени графического объекта европейской сессии string prefix=ExtPrefixUniq+"_"+day_prefix+"_Europe_"+StringFormat("%.5f", price); //--- рисуем прямоугольник (отрезок линии) на рассчитанных координатах с цветом для европейской сессии DrawBox(prefix, price, time1, time2, InpEuropeSession); } } //--- американская сессия //--- в цикле по количеству пунктов дневного бара for(int ind=0; ind0) { //--- получаем очередную цену методом прибавления количества пунктов ind к цене Low дневного бара //--- получаем время начала отрезка (время открытия дневного бара + время правого края профиля азиатской сессии + время правого края профиля европейской сессии) //--- и время конца отрезка (время начала отрезка американской сессии + количество баров, хранящееся в ячейке ind массива boxes_america[]) double price=low_day+ind*point; datetime time1=day_rate[0].time+(boxes_asia[ind]+boxes_europe[ind])*box_length*InpMultiplier; datetime time2=time1+boxes_america[ind]*box_length*InpMultiplier; //--- создаём префикс имени графического объекта американской сессии string prefix=ExtPrefixUniq+"_"+day_prefix+"_America_"+StringFormat("%.5f", price); //--- рисуем прямоугольник (отрезок линии) на рассчитанных координатах с цветом для американской сессии DrawBox(prefix, price, time1, time2, InpAmericaSession); } } } //--- по завершении цикла перерисуем график ChartRedraw(0); //--- возвращаем количество баров для следующего вызова OnCalculate return(rates_total); } //+------------------------------------------------------------------+ //| Custom indicator deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- после использования удалим все графические объекты, созданные индикатором Print("Indicator \"Market Profile\" stopped, delete all objects with prefix=", ExtPrefixUniq); ObjectsDeleteAll(0, ExtPrefixUniq, 0, OBJ_RECTANGLE); ChartRedraw(0); } //+------------------------------------------------------------------+ //| Draw color box | //+------------------------------------------------------------------+ void DrawBox(string bar_prefix, double price, datetime time1, datetime time2, color clr) { ObjectCreate(0, bar_prefix, OBJ_RECTANGLE, 0, time1, price, time2, price); ObjectSetInteger(0, bar_prefix, OBJPROP_COLOR, clr); ObjectSetInteger(0, bar_prefix, OBJPROP_STYLE, STYLE_SOLID); ObjectSetInteger(0, bar_prefix, OBJPROP_WIDTH, 1); ObjectSetString(0, bar_prefix, OBJPROP_TOOLTIP, "\n"); ObjectSetInteger(0, bar_prefix, OBJPROP_BACK, true); } //+------------------------------------------------------------------+