Аналог ObjectGetValueByTime может кто то реализовывал ?

 

Друзья, может кто то реализовывал аналог ObjectGetValueByTime  ?

Пробовал формулу линейной интерполяции но результат сильно отличается от ObjectGetValueByTime.

double InterpolatePrice(datetime t1, double p1, datetime t2, double p2, datetime t) // === сильные расхождения
{
   // Защита от деления на ноль
   if(t1 == t2)
      return(p1);
   
   // Линейная интерполяция
   double price = p1 + (p2 - p1) * (double)(t - t1) / (double)(t2 - t1);
   return(price);
}


Может кто то уже решал подобную задачу, поделитесь примером.

Документация по MQL5: ObjectGetValueByTime / Графические объекты
Документация по MQL5: ObjectGetValueByTime / Графические объекты
  • www.mql5.com
Возвращает значение цены для указанного времени указанного объекта. Параметры chart_id [in]  Идентификатор графика. 0 означает текущий график...
 
Vladimir Pastushak:

Друзья, может кто то реализовывал аналог ObjectGetValueByTime  ?

Пробовал формулу линейной интерполяции но результат сильно отличается от ObjectGetValueByTime.


Может кто то уже решал подобную задачу, поделитесь примером.

Используйте индексы баров, а не время их открытия. Тогда все получится. Если расчет производится в "будущем", то с каждым новым баром потребуется корректировка, т. к. могут быть дыры в барах, особенно это касается минуток. Хотя выходные также никто не отменял (касается всех ТФ).
 
Ihor Herasko #:
Используйте индексы баров, а не время их открытия. Тогда все получится. Если расчет производится в "будущем", то с каждым новым баром потребуется корректировка, т. к. могут быть дыры в барах, особенно это касается минуток. Хотя выходные также никто не отменял (касается всех ТФ).
Есть пример, можете поделиться ?
 
Vladimir Pastushak #:
Есть пример, можете поделиться ?

Вот так находим коэффициенты K и B из уравнения прямой (y = kx + b):

double CalculateBAndKKoefs(const int nX1, const int nY1, const int nX2, const int nY2, double &fKKoef)
{
   if (nX1 == nX2)
      return DBL_MAX;
      
   fKKoef = (nY2 - nY1) / 1.0 / (nX2 - nX1);
   return nY1 - fKKoef * nX1;   
}

Здесь (nX1, nY1) и (nX2, nY2) - две любые точки на прямой. nX1 и nX2 - это индексы баров. То есть предварительно нужно время открытие баров привести к индексам баров на определенном ТФ. Заметьте, что точность будет зависеть от ТФ, на разных ТФ результаты будут немного отличаться.

После расчета значений K и B подставляете их в уравнение прямой вместе с индексом того бара, на котором нужно узнать цену.

 
Vladimir Pastushak:

Друзья, может кто то реализовывал аналог ObjectGetValueByTime  ?

Пробовал формулу линейной интерполяции но результат сильно отличается от ObjectGetValueByTime.

Может кто то уже решал подобную задачу, поделитесь примером.

Я так находил цену точки на линии по времени.

//+------------------------------------------------------------------+
double PriceLineTime(datetime time1, double price1, datetime time2, double price2, datetime time3)
  {
   return(NormalizePrice(price1 + (price2 - price1) * (time3 - time1) / (time2 - time1)));
  }
//+------------------------------------------------------------------+
double NormalizePrice(double price)
  {
   double tick_size = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
   if(tick_size == 0)
      return 0;
   return(NormalizeDouble(MathRound(price / tick_size) * tick_size, (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS)));
  }
//+------------------------------------------------------------------+

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

PS. Посмотрел код индикатора, оказывается datetime time1, time2,time3 это индексы, а не время. 

 
Aleksandr Slavskii #:

Я так находил цену точки на линии по времени.

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

PS. Посмотрел код индикатора, оказывается datetime time1, time2,time3 это индексы, а не время. 

Если я все правильно сделал

double CMyLine :: Price(void) // === Возвращает цену
  {

   if(!w_work)
      return(false);

  // return(::ObjectGetValueByTime(0, m_line.Name(), ::TimeCurrent(), 0));
  
  int indx1 = iBarShift(_Symbol,PERIOD_CURRENT,m_line.Time(0),true);
  int indx2 = iBarShift(_Symbol,PERIOD_CURRENT,m_line.Time(1),true);
  int indx3 = iBarShift(_Symbol,PERIOD_CURRENT,TimeCurrent(),true);
  
  return(PriceLineTime(indx1, m_line.Price(0), indx2, m_line.Price(0), indx3));
  
  }
// =============================================================================================== //
// =                                                                                             = //
// =============================================================================================== //
double PriceLineTime(datetime time1, double price1, datetime time2, double price2, datetime time3)
  {
   return(NormalizePrice(price1 + (price2 - price1) * (time3 - time1) / (time2 - time1)));
  }
//+------------------------------------------------------------------+
double NormalizePrice(double price)
  {
   double tick_size = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
   if(tick_size == 0)
      return 0;
   return(NormalizeDouble(MathRound(price / tick_size) * tick_size, (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS)));
  }
//+------------------------------------------------------------------+


То расчет не верный



 
Ihor Herasko #:

Вот так находим коэффициенты K и B из уравнения прямой (y = kx + b):

Здесь (nX1, nY1) и (nX2, nY2) - две любые точки на прямой. nX1 и nX2 - это индексы баров. То есть предварительно нужно время открытие баров привести к индексам баров на определенном ТФ. Заметьте, что точность будет зависеть от ТФ, на разных ТФ результаты будут немного отличаться.

После расчета значений K и B подставляете их в уравнение прямой вместе с индексом того бара, на котором нужно узнать цену.

Не совсем понял что за коэфициенты и зачем они нужны.

Попробовал подставить индексы баров, в результате нет результата )))

 
Vladimir Pastushak #:

Не совсем понял что за коэфициенты и зачем они нужны.

Это коэффициенты из уравнения прямой. K - тангенс угла наклона прямой к оси абсцисс (в случае с ценовым графиком абсцисса - это время), B - цена пересечения прямой с осью ординат (для ценового графика B - это цена линии на текущем баре, т. к. x = 0). Зная эти коэффициенты, можно рассчитать цену для любого индекса бара и, соответственно, индекс бара для любой цены.

Попробовал подставить индексы баров, в результате нет результата )))

Покажите, как подставляли.
 
Vladimir Pastushak #:

Если я все правильно сделал

Не правильно .

return(PriceLineTime(indx1, m_line.Price(0), indx2, m_line.Price(0), indx3));

должны быть цены двух точек, а не одной.

 
Если время третьей точки не выходит за пределы котировочной сессии, то можно использовать время вместо индексов, чтоб не обращаться к iBarShift.
 
Aleksandr Slavskii #:

Не правильно .

return(PriceLineTime(indx1, m_line.Price(0), indx2, m_line.Price(0), indx3));

должны быть цены двух точек, а не одной.

Поправил результат всё равно не верный

double CMyLine :: Price(void) // === Возвращает цену
  {

   if(!w_work)
      return(false);

   int indx1 = iBarShift(_Symbol, PERIOD_CURRENT, m_line.Time(0), true);
   int indx2 = iBarShift(_Symbol, PERIOD_CURRENT, m_line.Time(1), true);
   int indx3 = iBarShift(_Symbol, PERIOD_CURRENT, TimeCurrent(), true);

   return(PriceLineTime(indx1, m_line.Price(0), indx2, m_line.Price(1), indx3));

//  return(::ObjectGetValueByTime(0, m_line.Name(), ::TimeCurrent(), 0));
  }
// =============================================================================================== //
// =                                                                                             = //
// =============================================================================================== //
double PriceLineTime(datetime time1, double price1, datetime time2, double price2, datetime time3)
  {
   return(NormalizePrice(price1 + (price2 - price1) * (time3 - time1) / (time2 - time1)));
  }
//+------------------------------------------------------------------+
double NormalizePrice(double price)
  {
   double tick_size = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
   if(tick_size == 0)
      return 0;
   return(NormalizeDouble(MathRound(price / tick_size) * tick_size, (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS)));
  }