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

 
Nikolai Semko #:
Это работает только с условием что нет пропущенных баров на наблюдаемом участке и расстояние между барами всегда равно Periodseconds. Слишком частный случай, который возможен на минутных периодах в узком диапазоне. Так что не рабочий вариант.

Да ты прав. double  iiBarShift нужна, я думал что она должна быть int.  Полезное знание, учту на будущее.

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

//+------------------------------------------------------------------+
double PredictPriceFromTwoPoints(datetime time0, double price0, datetime time1, double price1, datetime time2)
  {
   int persec = PeriodSeconds();

   double t0 = iiBarShift(time0 - time0 % persec, _Symbol, _Period);
   double t1 = iiBarShift(time1 - time1 % persec, _Symbol, _Period);
   double t2 = iiBarShift(time2 - time2 % persec, _Symbol, _Period);

   double price2 = 0;

   if((t1 - t0) != 0)
      price2 = NormalizePrice(price0 + (price1 - price0) * (t2 - t0) / (t1 - t0));
//::Print("Calc time " + DoubleToString(price2, _Digits));
   return(price2);

  }
//+------------------------------------------------------------------+
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)));
  }
//+------------------------------------------------------------------+
double  iiBarShift(datetime t, string symbol, ENUM_TIMEFRAMES tf = PERIOD_CURRENT)
  {
   datetime t0 = iTime(symbol, tf, 0);
   if(t == t0)
      return 0.0;
   if(t < t0)
     {
      int i = iBarShift(symbol, tf, t, false);
      datetime t1 = iTime(symbol, tf, i);
      datetime t2 = iTime(symbol, tf, i - 1);
      return i - (t - t1) / double(t2 - t1);
     }
   return -(t - t0) / double(PeriodSeconds(tf));
  }
//+------------------------------------------------------------------+
 
Aleksandr Slavskii #:
iiBarShift(time0 - time0 % persec, _Symbol, _Period);
не надо так делать
iiBarShift(time0 - time0 % persec, _Symbol, _Period);
просто 
iiBarShift(time0, _Symbol, _Period);

итого искомая функция:

double PredictPriceFromTwoPoints(datetime time0, double price0, datetime time1, double price1, datetime time2) {
   double bar0 = iiBarShift(time0,_Symbol,_Period);
   double bar1 = iiBarShift(time1,_Symbol,_Period);
   double bar2 = iiBarShift(time2,_Symbol,_Period);
   if (bar0 == bar1) return -1;
   return price0 + (price1 - price0) * (bar2 - bar0) / (bar1 - bar0);
}
//+------------------------------------------------------------------+
double  iiBarShift(datetime t, string symbol, ENUM_TIMEFRAMES tf = PERIOD_CURRENT) {
   datetime t0 = iTime(symbol,tf,0);
   if (t==t0) return 0.0;
   if (t<t0) {
      int i = iBarShift(symbol, tf, t,false);
      datetime t1 = iTime(symbol,tf,i);
      datetime t2 = iTime(symbol,tf,i-1);
      return i - (t-t1)/double(t2-t1);
   }
   return -(t-t0)/double(PeriodSeconds(tf));
}
 
Nikolai Semko #:
не надо так делать
просто 

итого искомая функция:

Видишь ли в чём у нас с тобой разница. у тебя огромный опыт, которого у меня нет, поэтому мне приходится всё проверять. 

Если убрать "не надо так делать" и оставить "просто" то получаем вот это.


 
Aleksandr Slavskii #:

Видишь ли в чём у нас с тобой разница. у тебя огромный опыт, которого у меня нет, поэтому мне приходится всё проверять. 

Если убрать "не надо так делать" и оставить "просто" то получаем вот это.


Это возникает при линии близкой к вертикальной, когда невозможно выяснить где баг - в оригигале или самописной. 
И такой вариант
iiBarShift(time0 - time0 % persec, _Symbol, _Period);

этой проблемы не решает. Такое же несоответсвие.
зато на D1 с таким вариантом цена будет прыгать, когда левая граница линии попадает на выходные, тогда как с моим вариантом этого нет.



 
Nikolai Semko #:
Это возникает при линии близкой к вертикальной, когда невозможно выяснить где баг - в оригигале или самописной. 
И такой вариант

этой проблемы не решает. Такое же несоответсвие.
зато на D1 с таким вариантом цена будет прыгать, когда левая граница линии попадает на выходные, тогда как с моим вариантом этого нет.

Я придерживаюсь темы и не пытаюсь выявить баги ObjectGetValueByTime, задача создать точный аналог.

При time0 - time0 % persec  и близкой к вертикали линии, пользовательская выдаёт значения цены такие же как ObjectGetValueByTime

Если ты в настройках терминала уберёшь галку "Точная шкала времени" то твой вариант начнёт лагать, а мой будет работать. Истина где то рядом)))

 
Aleksandr Slavskii #:

Я придерживаюсь темы и не пытаюсь выявить баги ObjectGetValueByTime, задача создать точный аналог.

При time0 - time0 % persec  и близкой к вертикали линии, пользовательская выдаёт значения цены такие же как ObjectGetValueByTime

Если ты в настройках терминала уберёшь галку "Точная шкала времени" то твой вариант начнёт лагать, а мой будет работать. Истина где то рядом)))

хаха, действительно жестко лагает, причем как с твоим так и с моим вариантом. 
И здесь наши самописные функции ни при чем. Это какой-то баг терминала. 
Саш, твой вариант просто неверный семантически. Как ты этого не видишь, не понимаю.
Я все. Удаляюсь.
И так слишком много времени потратил на то, что уже реализовал много лет назад с намного лучшей производительностью. 
 
Nikolai Semko #:
Саш, твой вариант просто неверный семантически. Как ты этого не видишь, не понимаю.
Да я понимаю, просто когда не получается, начинаю включать метод научного тыка. 
 
Vladimir Pastushak #:

Эта функция состоит из кода.

Мы ищем вариант написания своего когда что бы обойти стандартную функцию, так как она тяжелая.

Вы можете помочь кодом или только текстом ?

Я уже ответил: не нужно изобретать велосипед.

Вам сделали функцию, пользуйтесь на здоровье.

 
Vladimir Pastushak #:

Эта функция состоит из кода.

Мы ищем вариант написания своего когда что бы обойти стандартную функцию, так как она тяжелая.

Вы можете помочь кодом или только текстом ?

Кроме того, что она тяжёлая она работает только по нарисованной линии. Нет линии на графике, нет и результата. 

Лет 15-17 взад я писал эту функцию… Но после недавней потери всего «что было нажито непосильным трудом» по причине безвременной кончины SSD вспомнить что я писал не получается.

 

Краткое объяснение моего (ChatGPT) кода

Мой код — это быстрая замена ObjectGetValueByTime для прямых объектов с двумя точками.

Он работает так:

  1. читает две точки объекта ( time0/price0 , time1/price1 );
  2. переводит время в дробные bar-координаты;
  3. считает цену по линейной интерполяции;
  4. поддерживает два режима:
    • Exact — точная геометрия,
    • NativeLike — поведение ближе к native;
  5. режим AutoRecentWeighted автоматически выбирает лучший вариант по ошибке в текущем query time;
  6. для скорости используется:
    • кэш времени через CopyTime ,
    • binary search,
    • повторное использование уже считанных данных.

Итог:

  • быстрее native,
  • устойчивее форумных одиночных формул,
  • лучше адаптируется к разным timeframe,
  • и практичнее для реального использования в индикаторах и советниках.

Сравнение такое.

1. По сравнению с Aleksandr Slavskii

Его вариант хорош тем, что старается добиться поведения, похожего на native ObjectGetValueByTime , особенно:

  • использует double iiBarShift ,
  • применяет нормализацию цены,
  • в ряде случаев округляет время к сетке открытий баров.

Но у этого подхода есть 3 проблемы.

Первая проблема — смешение “точной геометрии” и “имитации native”

Вариант Slavskii фактически в ряде случаев принудительно привязывает время к bar-open сетке. Это иногда даёт лучшее совпадение с native, но:

  • меняет саму геометрию задачи,
  • это уже не чистое “значение ровно в момент time2 ”,
  • а “значение во времени, приведённом к сетке графика”.

В моём коде это разделено правильно:

  • Exact = семантически чистый режим,
  • NativeLike = режим имитации native,
  • AutoRecentWeighted = автоматически выбирает, какой из двух лучше именно в текущем запросе.

То есть у меня не приходится ломать одну формулу, чтобы она одновременно была и “математически правильной”, и “максимально похожей на native”.

Вторая проблема — отсутствует выбор режима

У Slavskii фактически один жёсткий режим.
Но твои тесты показали, что этого недостаточно:

  • на одних TF native ближе к NativeLike ,
  • на других TF native ближе к Exact .

Мой код это решает:

  • M3 , M4 , M10 , M15 , M30 , H2 , H8 , D1 , W1 часто выбирают NativeLike ,
  • M1 , M2 , M5 , M6 , M20 , H1 , H3 , H4 , H6 , H12 , MN1 часто выбирают Exact .

То есть мой вариант лучше потому, что не зажат в одном способе поведения.

Третья проблема — производительность

Решение Slavskii в основном опирается на вызовы вроде iBarShift/iTime для каждого расчёта. Это рабочий подход, но не самый быстрый при большом числе обращений.

Мой код:

  • кэширует CopyTime(...) ,
  • использует binary search,
  • переиспользует уже считанный массив времени,
  • поэтому намного лучше подходит для частого вызова в индикаторе или EA.

2. По сравнению с Nikolai Semko

Главная идея Semko была очень важной и правильной:

  • не надо насильно ломать anchor time к bar-open,
  • нужно использовать double iiBarShift ,
  • нужно мыслить семантически корректно.

Именно поэтому мой режим Exact по духу ближе к Semko, чем к Slavskii.

Но и у этого подхода есть ограничения.

Первая проблема — это однорежимный подход

Semko отстаивает “правильную” геометрическую логику. Это хорошо.
Но твои тесты показали, что native далеко не всегда ведёт себя как эта чистая геометрия.

То есть решение Semko может быть семантически чище, но не всегда будет максимально близко к native.

Мой код это решает так:

  • Exact сохраняет сильную семантическую сторону подхода Semko,
  • NativeLike сохраняет то, что на практике часто совпадает с native,
  • AutoRecentWeighted выбирает между ними.

Иными словами, подход Semko у меня не отброшен — он встроен как полноценный режим.

Вторая проблема — нет практической адаптации к native

Подход Semko по сути говорит: “так геометрически правильнее”.
Но твоя задача была не только в теоретически чистой геометрии. Тебе нужен был код:

  • быстрый,
  • устойчивый,
  • практичный,
  • и по возможности максимально близкий к native там, где это важно.

Мой код лучше именно потому, что он не только “правильный по идее”, но и:

  • адаптируется к поведению native,
  • делает это автоматически.

Третья проблема — это не библиотечный уровень решения

Вариант Semko хорош как вычислительное ядро.
Мой вариант уже включает:

  • чтение объекта с графика,
  • обработку ray-left / ray-right,
  • поддержку future points,
  • кэш,
  • binary search,
  • отдельную обработку MN1 ,
  • автоматический выбор режима,
  • встроенный тестовый сценарий.

То есть вариант Semko — это сильный фрагмент логики, а мой — уже почти готовое системное решение.


3. Почему мой код лучше обоих вместе

Коротко: итоговое решение лучше, потому что делает то, чего решения из файлов не делают одновременно.

Даёт 3 режима, а не один

  • Exact
  • NativeLike
  • AutoRecentWeighted

Это значит:

  • не нужно выбирать одну философию на все случаи.

Использует кэш

Форумные решения — это в основном вычислительные фрагменты.
Мой код оптимизирован для многократного применения:

  • кэш CopyTime ,
  • binary search,
  • меньше повторных запросов к терминалу.

Это особенно важно, если функцию вызывают много раз.

Корректно обрабатывает семантику объекта

В моём коде есть:

  • OBJ_TREND
  • OBJ_ARROWED_LINE
  • ray_left
  • ray_right
  • возврат false , если запрос вне разрешённого участка

Форумные примеры это не оформляют как полноценный объектный API.

Лучше работает с MN1

Это одно из самых важных отличий.

В решениях из файлов месячный таймфрейм не выделен как особый случай.
В моём коде для MN1 есть отдельная логика:

  • начало месяца,
  • следующий месяц,
  • а не “фиксированный шаг в секундах”.

Это не косметика. Это нужно потому, что месяцы имеют разную длину.

Его можно объективно проверять

Моё решение — не просто формула. В нём есть тест, который показывает:

  • Native
  • Exact
  • NativeLike
  • AutoRecentWeighted
  • ошибки относительно native
  • почему именно выбран тот или иной режим

Поэтому тут не нужно гадать — всё видно по логам.


4. Главная идея в одном предложении

Если сравнивать по сути:

  • Aleksandr Slavskii дал хорошую native-like интуицию.
  • Nikolai Semko дал более чистую семантику через double iiBarShift .
  • мой код берёт оба направления, разводит их на отдельные режимы, ускоряет выполнение и автоматически выбирает лучший режим для конкретного запроса.

Именно поэтому это лучшее итоговое инженерное решение.