//+------------------------------------------------------------------+ //| Article-13179-MQL5-InfoPanel-Ind-EAs.mq5 | //| Copyright 2026, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property indicator_chart_window #property indicator_buffers 1 #property indicator_plots 1 //--- plot MA #property indicator_label1 "MA" #property indicator_type1 DRAW_LINE #property indicator_color1 clrRed #property indicator_style1 STYLE_SOLID #property indicator_width1 1 //--- includes #include "Dashboard.mqh" //--- input variables input int InpPeriodMA = 10; /* MA Period */ // Период расчёта скользящей средней input ENUM_MA_METHOD InpMethodMA = MODE_SMA; /* MA Method */ // Метод расчёта скользящей средней input ENUM_APPLIED_PRICE InpPriceMA = PRICE_CLOSE; /* MA Price */ // Цена расчёта скользящей средней input int InpPanelX = 20; /* Dashboard X */ // Координата X панели input int InpPanelY = 20; /* Dashboard Y */ // Координата Y панели input int InpUniqID = 0; /* Unique ID */ // Уникальный идентификатор для объекта-панели //--- indicator buffers double BufferMA[]; //--- global variables CDashboard *dashboard=NULL; int handle_ma; // Хэндл индикатора Moving Average int period_ma; // Период расчёта Moving Average int mouse_bar_index; // Индекс бара, с которого берутся данные string plot_label; // Имя индикаторной графической серии для отображения в окне DataWindow //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- indicator buffers mapping SetIndexBuffer(0,BufferMA,INDICATOR_DATA); //--- Создаём хэндл индикатора period_ma=(InpPeriodMA<1 ? 1 : InpPeriodMA); ResetLastError(); handle_ma=iMA(Symbol(),PERIOD_CURRENT,period_ma,0,InpMethodMA,InpPriceMA); if(handle_ma==INVALID_HANDLE) { PrintFormat("%s Failed to create MA indicator handle. Error %lu",__FUNCTION__,GetLastError()); return INIT_FAILED; } //--- Устанавливаем параметры индикатора IndicatorSetInteger(INDICATOR_DIGITS,Digits()); IndicatorSetString(INDICATOR_SHORTNAME,"Test Dashboard"); //--- Устанавливаем параметры рисуемого буфера plot_label="MA("+(string)period_ma+","+StringSubstr(EnumToString(Period()),7)+")"; PlotIndexSetString(0,PLOT_LABEL,plot_label); ArraySetAsSeries(BufferMA,true); //--- Создаём объект панели dashboard=new CDashboard(InpUniqID,InpPanelX,InpPanelY,200,250); if(dashboard==NULL) { Print("Error. Failed to create dashboard object"); return INIT_FAILED; } //--- Отображаем панель с текстом в заголовке "Символ, Описание таймфрейма" dashboard.View(Symbol()+", "+StringSubstr(EnumToString(Period()),7)); //--- Рисуем табличку на фоне панели dashboard.DrawGridAutoFill(2,12,2); //dashboard.DrawGrid(2,1,12,2,19,97); //--- Выводим в журнал табличные данные dashboard.GridPrint(2); //--- Инициализируем переменную с индексом бара указателя мышки mouse_bar_index=0; //--- Успешная инициализация return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Custom indicator deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- Если объект панели существует - удаляем if(dashboard!=NULL) delete dashboard; //--- Освобождаем хэндл индикатора МА ResetLastError(); if(!IndicatorRelease(handle_ma)) PrintFormat("%s: IndicatorRelease failed. Error %ld",__FUNCTION__,GetLastError()); //--- Стираем все комментарии Comment(""); } //+------------------------------------------------------------------+ //| 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[]) { //--- Устанавливаем массивам индексацию как в таймсерии ArraySetAsSeries(time,true); ArraySetAsSeries(open,true); ArraySetAsSeries(high,true); ArraySetAsSeries(low,true); ArraySetAsSeries(close,true); ArraySetAsSeries(tick_volume,true); ArraySetAsSeries(volume,true); ArraySetAsSeries(spread,true); //--- Проверка на минимальное количество баров для расчёта if(rates_total1) { limit=rates_total-period_ma-1; ArrayInitialize(BufferMA,EMPTY_VALUE); } //--- Расчёт количества копируемых данных из хэндла индикатора в рисуемый буфер int count=(limit>1 ? rates_total : 1),copied=0; //--- Подготовка данных (получение данных в буфер скользящей средней по хэндлу) copied=CopyBuffer(handle_ma,0,0,count,BufferMA); if(copied!=count) return 0; //--- Цикл расчёта индикатора по данным скользящей средней for(int i=limit; i>=0 && !IsStopped(); i--) { // Здесь рассчитываем некий индикатор по данным стандартного Moving Average } //--- Получаем данные цен и таймсерии и выводим на панель //--- При первом запуске выводим на панель данные текущего бара static bool first=true; if(first) { DrawData(0,TimeCurrent()); first=false; } //--- Объявляем структуру цен и получаем текущие цены MqlTick tick={0}; if(!SymbolInfoTick(Symbol(),tick)) return 0; //--- Если курсор находится на текущем баре - выводим на панель все данные текущего бара if(mouse_bar_index==0) DrawData(0,time[0]); //--- Иначе - выводим на панель только цены Bid и Ask (обновляем цены на панели на каждом тике) else { dashboard.DrawText("Bid",dashboard.CellX(0,0)+2,dashboard.CellY(0,0)+2); dashboard.DrawText(DoubleToString(tick.bid,Digits()),dashboard.CellX(0,1)+2,dashboard.CellY(0,1)+2,90); dashboard.DrawText("Ask",dashboard.CellX(1,0)+2,dashboard.CellY(1,0)+2); dashboard.DrawText(DoubleToString(tick.ask,Digits()),dashboard.CellX(1,1)+2,dashboard.CellY(1,1)+2,90); } //--- return value of prev_calculated for next call return(rates_total); } //+------------------------------------------------------------------+ //| Timer function | //+------------------------------------------------------------------+ void OnTimer() { //--- } //+------------------------------------------------------------------+ //| ChartEvent function | //+------------------------------------------------------------------+ void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { //--- Вызываем обработчик событий панели dashboard.OnChartEvent(id,lparam,dparam,sparam); //--- Если курсор перемещается или щелчок по графику if(id==CHARTEVENT_MOUSE_MOVE || id==CHARTEVENT_CLICK) { //--- Объявляем переменные для записи в них координат времени и цены datetime time=0; double price=0; int wnd=0; //--- Если координаты курсора преобразованы в дату и время if(ChartXYToTimePrice(ChartID(),(int)lparam,(int)dparam,wnd,time,price)) { //--- записываем индекс бара, где расположен курсор в глобальную переменную mouse_bar_index=iBarShift(Symbol(),PERIOD_CURRENT,time); //--- Выводим данные бара под курсором на панель DrawData(mouse_bar_index,time); } } //--- Если получили пользовательское событие - выводим об этом сообщение в журнал if(id>CHARTEVENT_CUSTOM) { //--- Здесь может быть обработка щелчка по кнопке закрытия на панели PrintFormat("%s: Event id=%ld, object id (lparam): %lu, event message (sparam): %s",__FUNCTION__,id,lparam,sparam); } } //+------------------------------------------------------------------+ //| Выводит данные с указанного индекса таймсерии на панель | //+------------------------------------------------------------------+ void DrawData(const int index,const datetime time) { //--- Объявляем переменные для получения в них данных MqlTick tick={0}; MqlRates rates[1]; //--- Если текущие цены получить не удалось - уходим if(!SymbolInfoTick(Symbol(),tick)) return; //--- Если данные бара по указанному индексу получить не удалось - уходим if(CopyRates(Symbol(),PERIOD_CURRENT,index,1,rates)!=1) return; //--- Выводим на панель текущие цены и данные указанного бара dashboard.DrawText("Bid", dashboard.CellX(0,0)+2, dashboard.CellY(0,0)+2); dashboard.DrawText(DoubleToString(tick.bid,Digits()), dashboard.CellX(0,1)+2, dashboard.CellY(0,1)+2,90); dashboard.DrawText("Ask", dashboard.CellX(1,0)+2, dashboard.CellY(1,0)+2); dashboard.DrawText(DoubleToString(tick.ask,Digits()), dashboard.CellX(1,1)+2, dashboard.CellY(1,1)+2,90); dashboard.DrawText("Date", dashboard.CellX(2,0)+2, dashboard.CellY(2,0)+2); dashboard.DrawText(TimeToString(rates[0].time,TIME_DATE), dashboard.CellX(2,1)+2, dashboard.CellY(2,1)+2,90); dashboard.DrawText("Time", dashboard.CellX(3,0)+2, dashboard.CellY(3,0)+2); dashboard.DrawText(TimeToString(rates[0].time,TIME_MINUTES),dashboard.CellX(3,1)+2, dashboard.CellY(3,1)+2,90); dashboard.DrawText("Open", dashboard.CellX(4,0)+2, dashboard.CellY(4,0)+2); dashboard.DrawText(DoubleToString(rates[0].open,Digits()), dashboard.CellX(4,1)+2, dashboard.CellY(4,1)+2,90); dashboard.DrawText("High", dashboard.CellX(5,0)+2, dashboard.CellY(5,0)+2); dashboard.DrawText(DoubleToString(rates[0].high,Digits()), dashboard.CellX(5,1)+2, dashboard.CellY(5,1)+2,90); dashboard.DrawText("Low", dashboard.CellX(6,0)+2, dashboard.CellY(6,0)+2); dashboard.DrawText(DoubleToString(rates[0].low,Digits()), dashboard.CellX(6,1)+2, dashboard.CellY(6,1)+2,90); dashboard.DrawText("Close", dashboard.CellX(7,0)+2, dashboard.CellY(7,0)+2); dashboard.DrawText(DoubleToString(rates[0].close,Digits()), dashboard.CellX(7,1)+2, dashboard.CellY(7,1)+2,90); dashboard.DrawText("Volume", dashboard.CellX(8,0)+2, dashboard.CellY(8,0)+2); dashboard.DrawText((string)rates[0].real_volume, dashboard.CellX(8,1)+2, dashboard.CellY(8,1)+2,90); dashboard.DrawText("Tick Volume",dashboard.CellX(9,0)+2, dashboard.CellY(9,0)+2); dashboard.DrawText((string)rates[0].tick_volume, dashboard.CellX(9,1)+2, dashboard.CellY(9,1)+2,90); dashboard.DrawText("Spread", dashboard.CellX(10,0)+2, dashboard.CellY(10,0)+2); dashboard.DrawText((string)rates[0].spread, dashboard.CellX(10,1)+2, dashboard.CellY(10,1)+2,90); dashboard.DrawText(plot_label, dashboard.CellX(11,0)+2, dashboard.CellY(11,0)+2); dashboard.DrawText(DoubleToString(BufferMA[index],Digits()),dashboard.CellX(11,1)+2, dashboard.CellY(11,1)+2,90); //--- Перерисовываем график для немедленного отображения всех изменений на панели ChartRedraw(ChartID()); } //+------------------------------------------------------------------+