Помогите решить проблему на терминале МТ5.
Решил перевести свой продукт из mql4 в mql5.
В нём используются прямоугольники, которые рисуются по координатам XY.
И если в МТ4 при изменении вертикального масштаба всё плавно и без рывков, то на МТ5 тот же подход даёт фризы и заметную "неплавность".
Специально сделал упрощённый прототип для демонстрации эффекта. Одинаковый для МТ4 и МТ5. Сравните разницу при изменении вертикального масштаба (мышкой по ценовой шкале)
В МТ5 всё будет без тормозов, но перерисовка рывками. И чем больше объектов, тем хуже. А МТ4 всё плавненько.
Прикладываю исходники mq4 и mq5 файлами и вставка кода mq5.
Помогите сделать плавность.
Хочу понять: "Такой вот" МТ5 или "такой вот" мой код под МТ5.
Я уже много лет пытаюсь доказать MQ, что эти функции не должны быть асинхронными, так как таблица свойств чарта уже существует, и достаточно просто взять эти свойства и нет никакого смысла запускать асинхронный процесс.
Но все усилия тщетны.
Это реально отдает маразмом.
Я знаю о чем говорю, так как я на многих языках программирую и в том числе и с канвасом и с активным использованием событийной модели.
Причем в доисторическом MQL4 такая проблема минимальна.
ну да, Вы нарвались на 4 асинхронные функции, выполнение которых занимает 99.76% всего времени.
...
Причем в доисторическом MQL4 такая проблема минимальна.
Да, в МТ4 всё летает.
Если не затруднит, сможете пример подсказать, как грамотнее сделать?
Да, в МТ4 всё летает.
Если не затруднит, сможете пример подсказать, как грамотнее сделать?
Самый короткий способ - это прикрепить мою библу iCanvas, которая позволит не использовать асинхронные функции в цикле.
При этом совсем не обязательно пользоваться самим канвасом. Он будет висеть у вас в чарте на весь, но он будет пустой и прозрачный.
Если более длинный способ без использования iCanvas, то вам придется этот способ опять же подсмотреть в этой библе, т.к. он там и реализован, но это занятие не для слабонервных. :))
Попробую коротко объяснить, что делает iCanvas.
В ней есть внутренний обработчик OnChartEvent, который ловит событие CHARTEVENT_CHART_CHANGE и заполняет свою внутреннюю структуру W, используя все те же асинхронные ChartGet функции, но делает это только раз с наступлением этого события.
Это и позволяет более-менее оптимизировать скорость.
Так же в этой библиотеке висит объект Canvas, который растянут на весь экран и подстраивается под него, когда экран меняется.
Вот, например, добавлено три строки кода и много строк выброшено:
#property indicator_chart_window #include <Canvas\iCanvas.mqh> //https://www.mql5.com/ru/code/22164 #property indicator_buffers 0 #property indicator_plots 0 string obj_name = "Asd_"; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { 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[]) { if(NewBar()) { DrawObj(); } return(rates_total); } //+------------------------------------------------------------------+ //| ChartEvent function | //+------------------------------------------------------------------+ void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam) { if(id == CHARTEVENT_CHART_CHANGE) { DrawObj(); } } //+------------------------------------------------------------------+ //| Выводим на график | //+------------------------------------------------------------------+ void DrawObj() { string GenName = obj_name; double startPricePos = SymbolInfoDouble(Symbol(),SYMBOL_BID); int step_Pips = 50; for(int i=1; i<=20; i++) { double stp = (step_Pips*i)*SymbolInfoDouble(Symbol(),SYMBOL_POINT); RectLabelCreate(GenName+"UP_"+IntegerToString(i),startPricePos + stp); RectLabelCreate(GenName+"DN_"+IntegerToString(i),startPricePos - stp); } ChartRedraw(0); } //+------------------------------------------------------------------+ //| Создает прямоугольную метку | //+------------------------------------------------------------------+ void RectLabelCreate(string name, // имя метки double price // цена ) { const long chart_ID=0; // ID графика int sub_window=0; // номер подокна int x=0; // координата по оси X int y=0; // координата по оси Y x=W.Width/2; y = Round(Canvas.Y(price)); //x=(int)(ChartGetInteger(chart_ID,CHART_WIDTH_IN_PIXELS,sub_window)/2); //ChartXYToTimePrice(chart_ID,x,y,sub_window,time_pos_X_centr,price_pos_Y_tmp); //ChartTimePriceToXY(chart_ID,sub_window,time_pos_X_centr,price,x,y); const int width=50; // ширина const int height=10; // высота const color back_clr=C'236,233,216'; // цвет фона const ENUM_BORDER_TYPE border=BORDER_SUNKEN; // тип границы const ENUM_BASE_CORNER corner=CORNER_LEFT_UPPER; // угол графика для привязки const color clr=clrRed; // цвет плоской границы (Flat) const ENUM_LINE_STYLE style=STYLE_SOLID; // стиль плоской границы const int line_width=1; // толщина плоской границы const bool back=false; // на заднем плане const bool selection=false; // выделить для перемещений const bool hidden=true; // скрыт в списке объектов const long z_order=0; // приоритет на нажатие мышью if(ObjectCreate(chart_ID,name,OBJ_RECTANGLE_LABEL,sub_window,0,0)) { ObjectSetInteger(chart_ID,name,OBJPROP_XDISTANCE,x); ObjectSetInteger(chart_ID,name,OBJPROP_YDISTANCE,y); ObjectSetInteger(chart_ID,name,OBJPROP_XSIZE,width); ObjectSetInteger(chart_ID,name,OBJPROP_YSIZE,height); ObjectSetInteger(chart_ID,name,OBJPROP_BGCOLOR,back_clr); ObjectSetInteger(chart_ID,name,OBJPROP_BORDER_TYPE,border); ObjectSetInteger(chart_ID,name,OBJPROP_CORNER,corner); ObjectSetInteger(chart_ID,name,OBJPROP_COLOR,clr); ObjectSetInteger(chart_ID,name,OBJPROP_STYLE,style); ObjectSetInteger(chart_ID,name,OBJPROP_WIDTH,line_width); ObjectSetInteger(chart_ID,name,OBJPROP_BACK,back); ObjectSetInteger(chart_ID,name,OBJPROP_SELECTABLE,selection); ObjectSetInteger(chart_ID,name,OBJPROP_SELECTED,selection); ObjectSetInteger(chart_ID,name,OBJPROP_HIDDEN,hidden); ObjectSetInteger(chart_ID,name,OBJPROP_ZORDER,z_order); } else Print(_LastError); } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool NewBar() { static int countLastBar=0; int curBars = iBars(Symbol(),PERIOD_CURRENT); bool flg = false; if(countLastBar!=curBars) { countLastBar=curBars; flg=true; } return(flg); } //+------------------------------------------------------------------+Во всяком случае, Вы можете увеличивать количество объектов при таком алгоритме и это не будет сильно влиять на производительность.
А может это не баг, а фича? Что-нибуь там оптимизировано с графикой. А плохо работает, потому что всеми вещами желательно пользоваться по назначению. Есть специализированные графические объекты, которые привязаны к координатам цены - вот ими и надо пользоваться для данной задачи.
я тоже так думал раньше грешным делом, пока знаний не прибавилось по этому вопросу.
Причина однозначная - недомыслие.
Какой-то "авторитет" накосячил в самом начале (лет 10 назад) и никому до сих пор в голову не приходит, что он мог накосячить.
https://www.mql5.com/ru/forum/1111/page2780#comment_16886162
Вроде даже как бы согласились и обещали доработать, но нет - забили. Воз и ныне там.
https://www.mql5.com/ru/forum/1111/page2781#comment_16904132
Самый короткий способ - это прикрепить мою библу iCanvas, которая позволит не использовать асинхронные функции в цикле.
При этом совсем не обязательно пользоваться самим канвасом. Он будет висеть у вас в чарте на весь, но он будет пустой и прозрачный.
Если более длинный способ без использования iCanvas, то вам придется этот способ опять же подсмотреть в этой библе, т.к. он там и реализован, но это занятие не для слабонервных. :))
Попробую коротко объяснить, что делает iCanvas.
В ней есть внутренний обработчик OnChartEvent, который ловит событие CHARTEVENT_CHART_CHANGE и заполняет свою внутреннюю структуру W, используя все те же асинхронные ChartGet функции, но делает это только раз с наступлением этого события.
Это и позволяет более-менее оптимизировать скорость.
Так же в этой библиотеке висит объект Canvas, который растянут на весь экран и подстраивается под него, когда экран меняется.
Вот, например, добавлено три строки кода и много строк выброшено:
Спасибо за подобное решение проблемы. Действительно, скорость отрисовки возросла. Похоже придётся осваивать библиотеку.
Хотел бы ещё уточнить следующий нюанс. С такой формулировкой компилируется с предупреждением:
y = Canvas.Y(price);
А с такой без предупреждения, но скорость чутка падает
y = (int)Canvas.Y(price);
Как правильнее?)
Спасибо за подобное решение проблемы. Действительно, скорость отрисовки возросла. Похоже придётся осваивать библиотеку.
Хотел бы ещё уточнить следующий нюанс. С такой формулировкой компилируется с предупреждением:
А с такой без предупреждения, но скорость чутка падает
Как правильнее?)
у вас "y" какого типа ?
потому как если int и объективно "скорость чутка упала" это БАГ
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Помогите решить проблему на терминале МТ5.
Решил перевести свой продукт из mql4 в mql5.
В нём используются прямоугольники, которые рисуются по координатам XY.
И если в МТ4 при изменении вертикального масштаба всё плавно и без рывков, то на МТ5 тот же подход даёт фризы и заметную "неплавность".
Специально сделал упрощённый прототип для демонстрации эффекта. Одинаковый для МТ4 и МТ5. Сравните разницу при изменении вертикального масштаба (мышкой по ценовой шкале)
В МТ5 всё будет без тормозов, но перерисовка рывками. И чем больше объектов, тем хуже. А МТ4 всё плавненько.
Прикладываю исходники mq4 и mq5 файлами и вставка кода mq5.
Помогите сделать плавность.
Хочу понять: "Такой вот" МТ5 или "такой вот" мой код под МТ5.