Функция CustomTicksAdd() содержит серьезную ошибку. Надеюсь, администратор поможет решить эту проблему. Спасибо!

 
В настоящее время функция CustomTicksAdd() автоматически формирует K-линию при передаче данных tick[] в пользовательский график. Правильная логика формирования K-линии должна заключаться в формировании K-линии с ценой tick.last объема торгов, то есть, рисовать K-линию с ценой tick.last, когда tick.flag равен 88, 344, 56, 312, 120, 376. Однако текущая ситуация такова, что при выполнении функции CustomTicksAdd() все цены tick.last рисуются в K-линии пользовательского графика, что приводит к большому количеству неточной информации о K-линии пользовательского графика. Надеюсь, администратор поможет решить эту проблему. Спасибо!
 

Например, в этом случае цена открытия 2025.06.02 04:05 вызовет ошибку. Правильная цена открытия — 5887,0, но фактическая цена открытия, сгенерированная функцией CustomTicksAdd(), составляет 5887,5.

 
xiezhiqi:
В настоящее время функция CustomTicksAdd() автоматически формирует K-линию при передаче данных tick[] в пользовательский график. Правильная логика формирования K-линии должна заключаться в формировании K-линии с ценой tick.last объема торгов, то есть, рисовать K-линию с ценой tick.last, когда tick.flag равен 88, 344, 56, 312, 120, 376. Однако текущая ситуация такова, что при выполнении функции CustomTicksAdd() все цены tick.last рисуются в K-линии пользовательского графика, что приводит к большому количеству неточной информации о K-линии пользовательского графика. Надеюсь, администратор поможет решить эту проблему. Спасибо!

Что мешает делать предобработку входящих тиков и передавать функции только с нужными флагами?

 
Aleksey Vyazmikin #:

Что мешает делать предобработку входящих тиков и передавать функции только с нужными флагами?

В существующих контрактах на платформе MT5 линия К формируется по цене последней сделки. Вы можете найти это правило, загрузив данные TICK[] любого контракта и терпеливо сравнив их. Однако контракт, сформированный CustomTicksAdd(), не генерирует K-линию в соответствии с этим правилом. Это проблема внутренней конструкции MT5.

 
xiezhiqi #:
линия К

Признаюсь, я не знаю такого термина. Предположил, что речь идёт о последней цене.

 
Aleksey Vyazmikin #:

Признаюсь, я не знаю такого термина. Предположил, что речь идёт о последней цене.

Извините, я не знал, что китайская «K-линия» — это не общепринятое название, которое означает график ценовых свечей. Каждый столбец содержит цену открытия, самую высокую цену, самую низкую цену и цену закрытия.

 
xiezhiqi #:
китайская «K-линия» — это не общепринятое название

Я пробовал найти происхождение термина, когда он появился, но не смог. Однако стало понятно, что речь идёт о графике японских свечей.

xiezhiqi:
когда tick.flag равен 88, 344, 56, 312, 120, 376

Хорошо бы теперь понять, что означают эти флаги, так как стандартные флаги в терминале такие:

  • 2 — тик изменил цену бид
  • 4 — тик изменил цену аск
  • 8 — тик изменил цену последней сделки
  • 16 — тик изменил объем
  • 32 — тик возник в результате сделки на покупку
  • 64 — тик возник в результате сделки на продажу
 
xiezhiqi #:

В существующих контрактах на платформе MT5 линия К формируется по цене последней сделки. Вы можете найти это правило, загрузив данные TICK[] любого контракта и терпеливо сравнив их. Однако контракт, сформированный CustomTicksAdd(), не генерирует K-линию в соответствии с этим правилом. Это проблема внутренней конструкции MT5.

Тики (Ticks) в терминал приходят пакетами. Каждый следующий пакет может содержать тики с предыдущего пакета. Поэтому лишние нужно удалять.

Ещё есть ограничения на запись TICK_FLAG_BUY и TICK_FLAG_SELL  в онлайне, то есть исторические данные запишутся с этими флагами, а данные поступающие онлайн не запишутся.

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

 
Aleksey Vyazmikin #:
88, 344, 56, 312, 120, 376
88 TICK_FLAG_LAST TICK_FLAG_VOLUME TICK_FLAG_SELL
344 TICK_FLAG_LAST TICK_FLAG_VOLUME TICK_FLAG_SELL FLAG_UNKNOWN (256)
56 TICK_FLAG_LAST TICK_FLAG_VOLUME TICK_FLAG_BUY
312 TICK_FLAG_LAST TICK_FLAG_VOLUME TICK_FLAG_BUY FLAG_UNKNOWN (256)
120 TICK_FLAG_LAST TICK_FLAG_VOLUME TICK_FLAG_BUY TICK_FLAG_SELL
376 TICK_FLAG_LAST TICK_FLAG_VOLUME TICK_FLAG_BUY TICK_FLAG_SELL 
Файлы:
 
Aleksandr Slavskii #:

Думаю, уместно приложить Ваш код в сообщении:

//+------------------------------------------------------------------+
//|                                                  GetTickFlag.mq5 |
//|                                  Copyright 2022, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2022, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"

//2  TICK_FLAG_BID    – тик изменил цену бид
//4  TICK_FLAG_ASK    – тик изменил цену аск
//8  TICK_FLAG_LAST   – тик изменил цену последней сделки
//16 TICK_FLAG_VOLUME – тик изменил объем
//32 TICK_FLAG_BUY    – тик возник в результате сделки на покупку
//64 TICK_FLAG_SELL   – тик возник в результате сделки на продажу
//+------------------------------------------------------------------+
void OnStart()
  {
   Print(GetTickFlag(88));
   Print(GetTickFlag(344));
   Print(GetTickFlag(56));
   Print(GetTickFlag(312));
   Print(GetTickFlag(120));
   Print(GetTickFlag(376));
  }
//+------------------------------------------------------------------+
string GetTickFlag(uint tickflag)
  {
   string flag = " " + (string)tickflag;

#define TICKFLAG_MACRO(A) flag += ((bool)(tickflag & TICK_FLAG_##A)) ? " TICK_FLAG_" + #A : ""; \
                          tickflag -= tickflag & TICK_FLAG_##A;
   TICKFLAG_MACRO(BID)
   TICKFLAG_MACRO(ASK)
   TICKFLAG_MACRO(LAST)
   TICKFLAG_MACRO(VOLUME)
   TICKFLAG_MACRO(BUY)
   TICKFLAG_MACRO(SELL)
#undef TICKFLAG_MACRO

   if(tickflag)
      flag += " FLAG_UNKNOWN (" + (string)tickflag + ")";

   return(flag);
  }
//+------------------------------------------------------------------+
#define TOSTR(A) " " + #A + " = " + (string)Tick.A
#define TOSTR2(A) " " + #A + " = " + ::DoubleToString(Tick.A, _Digits)
//+------------------------------------------------------------------+
string TickToString(const MqlTick &Tick, const bool Flags = true)
  {
   return(TOSTR(time) + "." + ::IntegerToString(Tick.time_msc % 1000, 3, '0') +
          TOSTR2(bid) + TOSTR2(ask) + TOSTR2(last) + TOSTR(volume) +
          (Flags ? GetTickFlag(Tick.flags) : NULL));
  }
//+------------------------------------------------------------------+
#undef TOSTR2
#undef TOSTR
//+------------------------------------------------------------------+

Код сходу я не воспринимаю.

Как я понимаю, одна строка тиковой истории может содержать сразу несколько действий за тик.

 
Aleksey Vyazmikin #:

Как я понимаю, одна строка тиковой истории может содержать сразу несколько действий за тик.

Совершенно верно.

Но проблема топикстартера в другом.