Как поймать Click по линии индикатора ?

 

Очень надо ! 

Собсно понадобиться может для многих задачек.  У меня уже неоднократно запрос выплывал, но всё откладывал реализацию. А тут приспичило.

Постановка: Допустим есть набор индикаторных буферов:

struct SBuffer
  {
   double            B[];
  };
//--- indicator buffers
SBuffer       MyIndBuffer[CountLine];

OnInit()
 {
  for(int i=0;i<CountLine;i++)
     {
      InitBuffers(i);
     }
//....
 {
void InitBuffers(int index)
  {
   SetIndexBuffer(index,MyIndBuffer[index].B,INDICATOR_DATA);
   PlotIndexSetInteger(index,PLOT_DRAW_TYPE,DRAW_LINE);
  }

Это всё работает, без проблем, но теперь задача:  При клике мышкой по конкретной линии нужно посчитать и вывести в коммент (или ещё куда) информацию об этой линии (буфере), например значение в точке клика,  конечное значение линии (на нулевом баре), стандартную девиацию линии и ещё невесть что (что именно - не проблема).

Стоит задача точной идентификации линии по которой мышка кликнула. 

Траблы:  Ну допустим номер бара я могу рассчитать из Х-координаты, это понятно как делается, затем могу просканировать все буферы и узнать значения в каждом буфере соответствующее этому номеру бара.  Но как пересчитать это значение в координату Y (соотносимую с мышиной координатой Y) ??   Напрочь не могу сообразить, заклинило.  С ценами на основном чарте ещё как-то можно разобраться, но речь об осциляторах в отдельном окне.  И тут много непоняток, начиная с определения номера подокна и кончая автомасштабированием осциляторов....

Короче, голова кругом, Хелп ми, плиз!!

Усреднение ценовых рядов без дополнительных буферов для промежуточных расчетов
Усреднение ценовых рядов без дополнительных буферов для промежуточных расчетов
  • 2010.10.25
  • Nikolay Kositsin
  • www.mql5.com
Статья о традиционных и не совсем традиционных алгоритмах усреднения, упакованных в максимально простые и достаточно однотипные классы. Они задумывались для универсального использования в практических разработках индикаторов. Надеюсь, что предложенные классы в определенных ситуациях могут оказаться достаточно актуальной альтернативой громоздким, в некотором смысле, вызовам пользовательских и технических индикаторов.
 
i_logic:
На текущий момент подозреваю что это невыполнимо, поскольку терминал в момент наведения курсора мыши на индикаторную линию,  показывает собственную всплывающую подсказку (Hint). А у вас речь идет фактически о перехвате обработки этого события и выводе пользовательской всплывающей подсказки, короче, нужна будет доработка терминала. Ждем ответа от разработчиков.

Хинт не должен мешать кликать по линии.  Событие OnClick возникает, координаты мыши предоставляются.

Можете проверить, запустите эксперта (в прицепе) и покликайте:

Файлы:
 

Да, понял. Потестировал, весь цимес в том, что в sparam не возвращается инфа о том, что мы кликали по линии индикатора, хотя имена объектов - без проблем.

Мысли крутятся:

Рисовать хренову кучу невидимых (прозрачных) объектов по линии индикатора и клики на них обрабатывать - бред...

 

Если добавить графические объекты в нужные точки (на заданном участке истории), то при клике, информация по объекту доступна:

id=1; lparam=520;  dparam=242;  sparam=значение из объекта
 
MetaDriver:

Но как пересчитать это значение в координату Y (соотносимую с мышиной координатой Y) ??  

Так вроде ж есть https://www.mql5.com/ru/docs/chart_operations/charttimepricetoxy. Или я не совсем понял суть проблемы?
Документация по MQL5: Операции с графиками / ChartTimePriceToXY
Документация по MQL5: Операции с графиками / ChartTimePriceToXY
  • www.mql5.com
Операции с графиками / ChartTimePriceToXY - Документация по MQL5
 
Scriptong:
Так вроде ж есть https://www.mql5.com/ru/docs/chart_operations/charttimepricetoxy. Или я не совсем понял суть проблемы?

Вау!  Похоже оно.  Ещё и обратная есть:  ChartXYToTimePrice(...);  А я туду не смотрел, поскольку осцилятор вроде как совсем не цены выводит... :))

Спасибо друг, ты настоящий Скриптолог! 

:)

Поскакал пробовать.  Доложусь о выполнении.

 
DC2008:

Если добавить графические объекты в нужные точки (на заданном участке истории), то при клике, информация по объекту доступна:

i_logic:

Да, понял. Потестировал, весь цимес в том, что в sparam не возвращается инфа о том, что мы кликали по линии индикатора, хотя имена объектов - без проблем.

Мысли крутятся:

Рисовать хренову кучу невидимых (прозрачных) объектов по линии индикатора и клики на них обрабатывать - бред...

Спасибо, вариант извращённый, хотя рабочий. Если таки удастся обойтись без этого было б лучче.
 
MetaDriver:

Вау!  Похоже оно.  Ещё и обратная есть:  ChartXYToTimePrice(...); 

Дарю )))
 
Scriptong:
Дарю )))
Сделал через ChartXYToTimePrice(...) , работает.  Всем СПАСИБО !  :)  :)
 
MetaDriver:
Сделал через ChartXYToTimePrice(...) , работает.  Всем СПАСИБО !  :)  :)
:) а сорцы то где?
 
sergeev:
:) а сорцы то где?

Фигасе.  Как руку помощи протягивать, так его нету.. А как задачку решили так сразу первый в очереди.... ))

Сорцы пока сыроваты. Главное путь найден и проверен:  

void OnChartEvent(const int id,         // идентификатор события  
                  const long& lparam,   // параметр события типа long
                  const double& dparam, // параметр события типа double
                  const string& sparam  // параметр события типа string  
                  )
  {
   if(id==CHARTEVENT_CLICK)
     {
       datetime t;
       double p;
       int subW;
       ChartXYToTimePrice(ChartID(),lparam,(int)(dparam),subW,t,p);
       int X, Y;
       ChartTimePriceToXY(ChartID(), subW,t,ExtBuffer[x2bar(lparam)],X,Y);
       string S= "OnClick("+IntegerToString(lparam)+", "
           +IntegerToString((long)dparam)+"); BarNum=="
           +IntegerToString(x2bar(lparam))+"; ";
       if(fabs( Y - dparam)  < 5  )
         {
          S+="         Click on line!";
         }
       Print(S);
     }
  }
int x2bar(int X)
  {
    int FirstBar = ChartGetInteger(ChartID(), CHART_FIRST_VISIBLE_BAR, 1);
    int wInPix = ChartGetInteger(ChartID(), CHART_WIDTH_IN_PIXELS, 1);
    int wInBar = ChartGetInteger(ChartID(), CHART_WIDTH_IN_BARS, 1);
    double PixInBar = wInPix*1.0/wInBar;
    Print("wInPix=", wInPix, " wInBar=", wInBar, " PixInBar=", PixInBar);
    int result = FirstBar - X/PixInBar + 1;
    return result<0?0:result;
  }
Причина обращения: