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

 
Ihor Herasko #:

Вот демонстрационный скрипт того, что я описал:

Синяя линия - это изначальная линия, а красная линия показывает расчетное продолжение синей линии, приводя ее в третью точку. Именно в ту точку, цену которой хотите найти.

Благодарю! Искренне!

Я перебрал и упростил Ваш вариант:

Лучи не учитывает.

double PredictPriceFromTwoPoints(const datetime time1, const double price1, const datetime time2, const double price2, const datetime targetTime)
  {
   if(time1 == time2)
      return (price1);
 
   double k = (price2 - price1) / (double)(time2 - time1);
   return (k * (double)targetTime + (price1 - k * (double)time1));
  }
 
Vladimir Pastushak #:
Лучи не учитывает.

Не совсем понял про лучи. А вот про использование времени вместо индексов баров тут неоднократно упоминали. Нельзя так делать. Иначе получите вот такое:


Воспроизведение:

void OnStart()
{
   // Исходные данные
   int nLeftBar = 61;
   int nRightBar = 56;
   datetime dtTime1 = iTime(NULL, PERIOD_CURRENT, nLeftBar);
   datetime dtTime2 = iTime(NULL, PERIOD_CURRENT, nRightBar);
   double fPrice1 = iHigh(NULL, PERIOD_CURRENT, nLeftBar);
   double fPrice2 = iHigh(NULL, PERIOD_CURRENT, nRightBar);
   
   ShowTrendLine("TRNDLN", dtTime1, fPrice1, dtTime2, fPrice2, "/n", clrBlue, 2);
   
   // Расчет коэффициентов прямой
   double fKKoef = 0;
   double fBKoef = CalculateBAndKKoefs(nLeftBar, fPrice1, nRightBar, fPrice2, fKKoef);
   
   // Расчет цены на заданном баре
   int nThirdBar = 46;
   datetime dtTime3 = iTime(NULL, PERIOD_CURRENT, nThirdBar);
   double fPrice3 = PredictPriceFromTwoPoints(dtTime1, fPrice1, dtTime2, fPrice2, dtTime3);

   ShowTrendLine("TRNDLNNXT", dtTime2, fPrice2, dtTime3, fPrice3, "/n", clrRed, 2);
}

Проблема в том, что время на шкале МТ не является строго периодичным. Провалы происходят, как минимум, каждые выходные, не говоря уже о ТФ вроде М1. Поэтому следует оперировать именно индексами баров:

void OnStart()
{
   // Исходные данные
   int nLeftBar = 61;
   int nRightBar = 56;
   datetime dtTime1 = iTime(NULL, PERIOD_CURRENT, nLeftBar);
   datetime dtTime2 = iTime(NULL, PERIOD_CURRENT, nRightBar);
   double fPrice1 = iHigh(NULL, PERIOD_CURRENT, nLeftBar);
   double fPrice2 = iHigh(NULL, PERIOD_CURRENT, nRightBar);
   
   ShowTrendLine("TRNDLN", dtTime1, fPrice1, dtTime2, fPrice2, "/n", clrBlue, 2);
   
   // Расчет коэффициентов прямой
   double fKKoef = 0;
   double fBKoef = CalculateBAndKKoefs(nLeftBar, fPrice1, nRightBar, fPrice2, fKKoef);
   
   // Расчет цены на заданном баре
   int nThirdBar = 46;
   datetime dtTime3 = iTime(NULL, PERIOD_CURRENT, nThirdBar);
   double fPrice3 = PredictPriceFromTwoPoints(nLeftBar, fPrice1, nRightBar, fPrice2, nThirdBar);

   ShowTrendLine("TRNDLNNXT2", dtTime2, fPrice2, dtTime3, fPrice3, "/n", clrGreen, 2);
}

double PredictPriceFromTwoPoints(const int nX1, const double price1, const int nX2, const double price2, const int nTargetBar)
{
   if (nX1 == nX2)
      return (price1);
 
   double k = (price2 - price1) / (double)(nX2 - nX1);
   return (k * nTargetBar + (price1 - k * nX1));
}

Тогда и результат будет правильный:


 
Ihor Herasko #:

Не совсем понял про лучи. А вот про использование времени вместо индексов баров тут неоднократно упоминали. Нельзя так делать. Иначе получите вот такое:


Воспроизведение:

Проблема в том, что время на шкале МТ не является строго периодичным. Провалы происходят, как минимум, каждые выходные, не говоря уже о ТФ вроде М1. Поэтому следует оперировать именно индексами баров:

Тогда и результат будет правильный:


Ну ведь преобразовать ничего не сто́ит.

double PriceLineTime(datetime tim_0, double pr_0, datetime tim_1, double pr_1, datetime tim_2)
 {
  int perSec = PeriodSeconds();
  tim_0 = datetime(int(tim_0/perSec)*perSec);
  tim_1 = datetime(int(tim_1/perSec)*perSec);

Вот такое время

2026.04.17 16:20:01.158 Test (EURUSD,H1)        2026.04.13 21:59:00 : 2026.04.14 07:53:00

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


Ещё: функция ObjectGetValueByTime не видит правую координату если она находится «в будущем».

 
Alexey Viktorov #:

Ну ведь преобразовать ничего не сто́ит.

Только через iBarShift (или свою функцию обхода, если уж так нужно именно свою). А здесь не видно преобразования времени бара в индекс бара.

 
Ihor Herasko #:

Только через iBarShift (или свою функцию обхода, если уж так нужно именно свою). А здесь не видно преобразования времени бара в индекс бара.

Зачем индекс? Прекрасно всё работает с временем преобразованным в тип double, чтобы не потерять дробную часть числа. Главное отбросить лишние минуты/секунды в полученном времени.
 
Alexey Viktorov #:
Зачем индекс? Прекрасно всё работает с временем преобразованным в тип double, чтобы не потерять дробную часть числа.
В примере выше я показал, зачем: пропуски баров на выходных, как минимум. Также в середине дня могут быть пропуски баров на младших ТФ. Я уже молчу про инструменты, которые котируются по 8-10 часов в сутки.
 
Ihor Herasko #:
В примере выше я показал, зачем: пропуски баров на выходных, как минимум. Также в середине дня могут быть пропуски баров на младших ТФ. Я уже молчу про инструменты, которые котируются по 8-10 часов в сутки.
Ну да, согласен. Только в будущее не нарисуешь трендовую, там баров нет… Будет время, поколдую как обойти эту проблему.
 

Поспешил я радоваться (((


Ihor Herasko #:

Не совсем понял про лучи. А вот про использование времени вместо индексов баров тут неоднократно упоминали. Нельзя так делать. Иначе получите вот такое:


Воспроизведение:

Проблема в том, что время на шкале МТ не является строго периодичным. Провалы происходят, как минимум, каждые выходные, не говоря уже о ТФ вроде М1. Поэтому следует оперировать именно индексами баров:

Тогда и результат будет правильный:


Ваш вариант то же не работает к сожалению.

Перебрал на индексы баров

double PredictPriceFromTwoPoints(const datetime time1, const double price1, const datetime time2, const double price2, const datetime targetTime)
{
 
   int nLeftBar  = iBarShift(_Symbol,PERIOD_CURRENT,time1,true);
   int nRightBar = iBarShift(_Symbol,PERIOD_CURRENT,time2,true);
 
   double fKKoef = 0;
   double fBKoef = CalculateBAndKKoefs(nLeftBar, price1, nRightBar, price2, fKKoef);
 
   int nThirdBar = 1;
   double fPrice3 = fKKoef * nThirdBar + fBKoef;
   
   return(fPrice3);
}

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

Результат не верный 

Ваш расчет


Расчет ObjectGetValueByTime


 
Vladimir Pastushak #:

Поспешил я радоваться (((


Ваш вариант то же не работает к сожалению.

Перебрал на индексы баров

Результат не верный 

Ваш расчет


Расчет ObjectGetValueByTime


Для ObjectGetValueByTime правая координата не может быть правее текущего бара.
 
Alexey Viktorov #:
Ну да, согласен. Только в будущее не нарисуешь трендовую, там баров нет… Будет время, поколдую как обойти эту проблему.
Нет никаких проблем. Все то же самое. Просто индексы баров отрицательные. Единственное, что меняется, это обязательный перерасчет значения на каждом новом баре.