ChartXYToTimePrice возвращает неправильные координаты за пределами окна графика

 

Доброго ВС!

Заметил, что функция ChartXYToTimePrice возвращает неправильные координаты, а именно, нули, если в ее параметры вводить координаты x и y, которые находятся за пределами визуальной области окна графика.

Однако же, для моих интерактивных элементов нужны правильные преобразования при всех возможных координатах. Есть ли вариант обхода этой функции для получения координат time и price из x и y?

void OnStart()
  {
   int x = ChartGetInteger(0, CHART_WIDTH_IN_PIXELS) + 10;//выходим за границы окна графика
   int y = ChartGetInteger(0, CHART_HEIGHT_IN_PIXELS) + 10;// выходим за границы окна графика
   datetime time = {};
   double price = {};
   int sub_window = {};
   if(!ChartXYToTimePrice(0, x, y, sub_window, time, price))
      Print("Last Error= ", GetLastError());
   Print("time= ", time, " price= ", price);//неверные координаты
  }
 

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

void OnStart()
  {
   int x = ChartGetInteger(0, CHART_WIDTH_IN_PIXELS);
   int y = ChartGetInteger(0, CHART_HEIGHT_IN_PIXELS);
   datetime time = {};
   double price = {};
   int sub_window = {};
   if(!ChartXYToTimePrice(0, x, y, sub_window, time, price))
      Print("Last Error= ", GetLastError());
   Print("time= ", time, " price= ", price);
   datetime time0 = {};
   double price0 = {};
   datetime time1 = {};
   double price1 = {};
   if(!ChartXYToTimePrice(0, 0, 0, sub_window, time0, price0))
      Print("Last Error= ", GetLastError());
   if(!ChartXYToTimePrice(0, 1, 1, sub_window, time1, price1))
      Print("Last Error= ", GetLastError());
   datetime time_per_pixel = time1 - time0;
   double price_per_pixel = price0 - price1;
   time = time0 + time_per_pixel * x;
   price = price0 - price_per_pixel * y;
   Print("time= ", time, " price= ", price);//не совпадают координаты
  }
 
Anton Iaroshenko #:

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

Там можно проще. Кроме пиксельных величин, берите так же и высоту графика в пунктах (ChartGetDouble(CHART_PRICE_MAX) - ChartGetDouble(CHART_PRICE_MIN)) и ширину графика в барах (CHART_WIDTH_IN_BARS). Из них высчитывайте уже цену/время на пиксель

 
Anton Iaroshenko #:

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

готовое решение в этой библиотеке. Не рекомендую использовать ChartXYToTimePrice и ChartTimePriceToXY. Они ооооочень медленные.
Так же все ChartGet.. функции должны использоваться только при наступлении события CHARTEVENT_CHART_CHANGE, не чаще (!!!), т.к. чрезмерное их использование также ведет к лагам.

 

@Nikolai Semko, спасибо! Ваша библиотека натолкнула меня на правильный ход мыслей.

Теперь я исправил вычисления в функции. И да, она работает

void OnStart()
  {
   int x = ChartGetInteger(0, CHART_WIDTH_IN_PIXELS);
   int y = ChartGetInteger(0, CHART_HEIGHT_IN_PIXELS);
   datetime time = {};
   double price = {};
   int sub_window = {};
   if(!ChartXYToTimePrice(0, x, y, sub_window, time, price))
      Print("Last Error= ", GetLastError());
   Print("time= ", time, " price= ", price);
   double price_per_pixel = (ChartGetDouble(0, CHART_PRICE_MAX) - ChartGetDouble(0, CHART_PRICE_MIN)) / ChartGetInteger(0, CHART_HEIGHT_IN_PIXELS);
   int first_bar = ChartGetInteger(0, CHART_FIRST_VISIBLE_BAR);
   datetime time_first_bar = iTime(Symbol(), Period(), first_bar);
   double price0 = ChartGetDouble(0, CHART_PRICE_MAX);
   int pixels_per_bar = (int)ChartGetInteger(0, CHART_WIDTH_IN_PIXELS) / (int)ChartGetInteger(0, CHART_WIDTH_IN_BARS) + 1;
   double time_per_pixel = (double)PeriodSeconds() / pixels_per_bar;
   datetime time_remaining = ((double)x / pixels_per_bar - (int)(x / pixels_per_bar)) * pixels_per_bar * time_per_pixel;
   int nearest_bar = first_bar - x / pixels_per_bar;
   datetime time_nearest_bar = {};
   if(nearest_bar < 0)
     {
      datetime time_0_move = iTime(Symbol(), Period(), 0);
      datetime delta_time_start_move = time_0_move - time_first_bar;
      datetime delta_time_stop_move = (0 - nearest_bar) * PeriodSeconds();
      time_nearest_bar = time_first_bar + delta_time_start_move + delta_time_stop_move;
     }
   else
      time_nearest_bar = iTime(Symbol(), Period(), nearest_bar);
   time = time_nearest_bar + time_remaining;
   price = price0 - price_per_pixel * y;
   Print("time= ", time, " price= ", price);//теперь все нормально
  }
Причина обращения: