Как вывести значение цены в пользовательском TOOLTIP - страница 3

 

При перемещении курсора терминал определяет, что курсор остановился над каким-то объектом и необходимо вывести тултип.

Было бы проще, если б была функция, которая выдает информацию, над каким объектом остановился курсор. То есть выдает имя объекта.

Имея имя объекта, получить информацию об объекте из самого объета и подкорректировать тултип уже не так сложно. И не надо никаких массивов.

 

Например можно координаты курсора определять с помощью ChartXYToTimePrice(0,x,y,window,dt,price).

А далее сравнивать значения dt,price с значениями ObjectGetValueByTime и ObjectGetTimeByValue для всех объектов, выведенных на график.

Как только координаты сойдутся определяем значение тултип в найденном объекте и корректируем его. Как-то так. И не надо хранить огромные массивы в памяти и обслуживать эти массивы.

 
Eugeni Neumoin:

Например можно координаты курсора определять с помощью ChartXYToTimePrice(0,x,y,window,dt,price).

А далее сравнивать значения dt,price с значениями ObjectGetValueByTime и ObjectGetTimeByValue для всех объектов, выведенных на график.

Как только координаты сойдутся определяем значение тултип в найденном объекте и корректируем его. Как-то так. И не надо хранить огромные массивы в памяти и обслуживать эти массивы.

  1. А если на графике не только те объекты, которые вывела программа? Цикл все равно гонять по всем объектам? А так уже есть готовый массив данных своих объектов, что исключает лишние итерации цикла и запрос данных через ObjectGetXXX.
  2. Не факт, что ObjectGetValueByTime и ObjectGetTimeByValue будет работать быстрее, чем расчет коэффициентов К и В напрямую при уже готовых значениях.
  3. Расчет по уравнению прямой подойдет только для линий. А как быть с другими типами объектов? Для них заранее и формируются данные об области их действия.
 

Как-то так:

   if (id==CHARTEVENT_MOUSE_MOVE) 
     {
      if(ChartXYToTimePrice(0,x,y,window,dt,price))
      for (int i=ObjectsTotal(); i>=0; i--)
        {
         if (ObjectGetValueByTime(0,ObjectName(i),dt) && ObjectGetTimeByValue(0,ObjectName(i),price))
           {
            string tt=ObjectGetString(0,ObjectName(i),OBJPROP_TOOLTIP);
            // здесь модифицируем тултип - tt

            // и записываем новое значение
            ObjectSetString(0,ObjectName(i),OBJPROP_TOOLTIP,tt);
           }
        }
     }
 
Ihor Herasko:
  1. А если на графике не только те объекты, которые вывела программа? Цикл все равно гонять по всем объектам? А так уже есть готовый массив данных своих объектов, что исключает лишние итерации цикла и запрос данных через ObjectGetXXX.
  2. Не факт, что ObjectGetValueByTime и ObjectGetTimeByValue будет работать быстрее, чем расчет коэффициентов К и В напрямую при уже готовых значениях.
  3. Расчет по уравнению прямой подойдет только для линий. А как быть с другими типами объектов? Для них заранее и формируются данные об области их действия.

А каким образом эта задача решена в терминале? Других вариантов не просматривается. Для тех объектов, для которых в терминале выводится тултип.

Расчет цены и времени через ObjectGetValueByTime и ObjectGetTimeByValue будет не медленнее.

Хранение в памяти огромного массива строкового и обслуживание этого массива также пожирает ресурс.

Допустим, надо удалить объект, состоящий из нескольких сотен отрезков. Из массива информацию об этих отрезках также надо удалять и потом сжимать массив. И т.д.


Процедуру, приведенную выше, можно применять для тех типов объектов, для которых функции ObjectGetValueByTime и ObjectGetTimeByValue работают корректно.

Для других типов объектов надо применять другую процедуру.


Но хотелось бы, чтобы Слава Стариков добавил в язык MQL функцию, например, выдающую на выходе наименование объекта, над которым находится курсор.

Например

ChartXYToObjectName(0,x,y,window,name)

А лучше сделать процедуру (функцию) чтения и изменения тултипа в момент вывода тултипа. Каким-то образом терминал находит объект для вывода тултипа. Это, на мой взгляд, достаточно затратно.

Тратить ресурс на чтение имени объекта, над которым находится курсор, а потом вторично тратить тот же ресурс на вывод тултипа - слишком расточительно.

 
Eugeni Neumoin:

Не  катит? Ваш вариант уже опробован прежде чем была создана эта тема. Я на форум стараюсь выносить вопросы, которые не получается реализовать имеющимися средствами.

Чтобы реализовать Ваше предложение, надо перерисовывать все имеющиеся на графичке объекты, чтобы актуализировать информацию в тултипе при каждом движении мыши. А если объектов на графике много? При движении мыши терминал может просто зависнуть.

А можно уточнить что конкретно не получилось? Что было сделано?

Например, вот вручную создана трендовая с такими параметрами

Вот значения OBJPROP_TOOLTIP установленные программно

И вот промежуточное значение полученное при помощи ObjectGetValueByShift



Для пользовательских индикаторов достаточно добавить обработчик события

void OnChartEvent(const int id,         // идентификатор события   
                  const long& lparam,   // параметр события типа long 
                  const double& dparam, // параметр события типа double 
                  const string& sparam  // параметр события типа string 
  );
и в нём получать цену графического объекта при каждом перемещении мышы и устанавливать OBJPROP_TOOLTIP. А отображается тултип только при наведении мыши на объект.
 
Alexey Viktorov:

А можно уточнить что конкретно не получилось? Что было сделано?

Этот момент уже улажен. Насколько я понял, такое решение воспринималось как слишком затратное в плане ресурсов, т. к. объектов используется слишком много (более 1000). Потом было предложено решение, которое не приводит к к несоизмеримо большим затратам ресурсов.

На данный момент проблемой осталось только одно - реализация. Она не такая уж и легкая, как могло показаться изначально, но и не такая уж и сложная, чтобы ее нельзя было воплотить в жизнь. 

 

Кстати, Евгений. Сейчас в одной из топовых тем Peter Konow как раз описывает решение поставленной Вами задачи. Вот его пост.

 
Ihor Herasko:

Этот момент уже улажен. Насколько я понял, такое решение воспринималось как слишком затратное в плане ресурсов, т. к. объектов используется слишком много (более 1000). Потом было предложено решение, которое не приводит к к несоизмеримо большим затратам ресурсов.

На данный момент проблемой осталось только одно - реализация. Она не такая уж и легкая, как могло показаться изначально, но и не такая уж и сложная, чтобы ее нельзя было воплотить в жизнь. 

Игорь, но в том посте который я цитировал, говорится о перерисовке объектов. А кому оно надо-то??? перерисовывать...

Ну, допустим, что объектов > 1000 и что? Сколько времени тратится на присвоение тултипа? Сколько времени тратится на цикл 1000 итераций? Потому я и спросил "что было сделано и что не получилось". Мой пример был сделан для одной трендовой. Но ради проверки чужой проблемы рисовать 1000 объектов мне влом ради того чтобы замерить время на цикл. Кроме этого я не очень верю в проблему скорости исполнения и подвисания МТ.

Я конечно не могу спорить, просто по незнанию, но интуитивно кажется что не так уж и затратно, даже в каждом индикаторе, советнике тем более, определить координаты мыши и перевести в TimePrice. А если это будет отдельный индикатор (советник), определяющий время где находится мышь, читающий имена объектов и присваивающий им тултип в соответствии с ObjectGetValueByTime вообще никаких проблем не вижу.

 
Alexey Viktorov:

Мы разобрались. Чуть выше приведены коды, как это сделать. Cейчас проверю быстродействие на примерно в районе 1000 объектов.

Некоторое замедление есть. На количестве порядка 1000 объектов. Это терпимо.

Сделал пока только для спиралей. Эти две спирали примерно из 1000 отрезков прямых состоят.

Но если отрезок является вертикальным значение цены не выводится.

Причина обращения: