Механика флага TICK_FLAG_BUY / TICK_FLAG_SELL

 
Доки говорят, что флаг показывает когда на тике произошла сделка на покупку, но не говорят, что подразумевается в виду под термином "сделка".
Интересует более детальное описание события, которые влияет на установку этого флага.
По таймзоне этого брокера у него торги на NYSE идут с 13:30 до 20:00, что соответствует 09:30 - 16:00 по Америке, поэтому к времени не надо придираться.

Для упомянутого интервала распечатываю значения флагов

Print(
index, " ", 
iSeries.ticks[k].time, " ", 
iSeries.ticks[k].flags, " ", 
(iSeries.ticks[k].flags & TICK_FLAG_BUY) == TICK_FLAG_BUY, " ", 
(iSeries.ticks[k].flags & TICK_FLAG_SELL) == TICK_FLAG_SELL, " ", 
(iSeries.ticks[k].flags & TICK_FLAG_ASK) == TICK_FLAG_ASK, " ", 
(iSeries.ticks[k].flags & TICK_FLAG_BID) == TICK_FLAG_BID
);
2018.07.07 20:19:19.605 Imbalance (NFLX,H1)     0 2018.07.05 19:10:22   344   false true  false false
2018.07.07 20:19:19.605 Imbalance (NFLX,H1)     0 2018.07.05 19:10:22   376   true  true  false false
2018.07.07 20:19:19.605 Imbalance (NFLX,H1)     0 2018.07.05 19:10:21   6     false false true  true
Эти тики говорят следующее.

- сначала была свершена "сделка" на продажу
- потом одновременно была "сделка" и на покупку и на продажу
- потом "сделок" не было, но и Ask и Bid изменились

Как могла измениться цена если "сделка" не произошла?

Что такое "сделка" в терминах МТ5? 

####################################################

Дальше - другой вопрос, тут скорее всего глючит брокера, но все же уточню.

4 июля - День независимости США, 3 июля NYSE - короткий день, закрытие биржи в 13:00

На барах в 12:00 и 13:00 суммарный обьем на тиках = 0, при этом стандартный индикатор обьема показывает какие-то значения и цена меняется.

Как может менятся цена если обьем купленных и проданных акций = 0?

2018.07.07 22:02:12.702 Imbalance (NFLX,H1)     ### 13 2018.07.03 19:00:00 2018.07.03 19:58:45 915528.0 -687913.0
2018.07.07 22:02:12.702 Imbalance (NFLX,H1)     ### 14 2018.07.03 18:00:00 2018.07.03 18:59:44 0.0 0.0
2018.07.07 22:02:12.702 Imbalance (NFLX,H1)     ### 15 2018.07.03 17:00:00 2018.07.03 17:59:43 0.0 0.0
2018.07.07 22:02:12.702 Imbalance (NFLX,H1)     ### 16 2018.07.03 16:00:00 2018.07.03 16:59:54 157123.0 -15290.0
int OnCalculate(const int bars, const int counted, const int start, const double &price[])
{
  ulong date = TimeCurrent() * 1000;  

  if (iPosition == 0)
  {
    ZeroMemory(iAsk);
    ZeroMemory(iBid);
    ZeroMemory(iLast);

    iPosition = History(date - 5 * PeriodSeconds(PERIOD_D1) * 1000, date);

    return bars;
  }
  
  if (bars != counted)
  {
    iAsk[0] = 0;
    iBid[0] = 0;
    iLast[0] = 0;
  }

  int count = iHelpers.getTicks(iSeries, iPosition);

  if (count > 0) 
  {
    iPosition = iSeries.ticks[0].time_msc + 1;
  }

  return bars;
}

ulong History(ulong start, ulong end)
{
  int count = iHelpers.getTicks(iSeries, start, 0);

  if (count > 0) 
  {
    int index = 0;
    int seconds = PeriodSeconds();
    int date = int(iSeries.ticks[0].time - iSeries.ticks[0].time % seconds);

    double buy = 0;
    double sell = 0;
    double buyTick = 0;
    double sellTick = 0;

    for (int k = 0; k < count - 1; k++)
    {
      if (iSeries.ticks[k].time < date) // go to the next bar
      {
Print("### ", index, " ", datetime(position), " ", iSeries.ticks[k].time, " ", buy, " ", sell);
        index++;
        buy = 0;
        sell = 0;
        buyTick = 0;
        sellTick = 0;
        date = int(iSeries.ticks[k].time - iSeries.ticks[k].time % seconds);
      }

      bool isBuy = (iSeries.ticks[k].flags & TICK_FLAG_BUY) == TICK_FLAG_BUY;
      bool isSell = (iSeries.ticks[k].flags & TICK_FLAG_SELL) == TICK_FLAG_SELL;
/*
if (iSeries.ticks[k].time <= d1 && iSeries.ticks[k].time >= d2)
Print(
index, " ", 
iSeries.ticks[k].time, " ", 
iSeries.ticks[k].flags, " ", 
(iSeries.ticks[k].flags & TICK_FLAG_BUY) == TICK_FLAG_BUY, " ", 
(iSeries.ticks[k].flags & TICK_FLAG_SELL) == TICK_FLAG_SELL, " ", 
(iSeries.ticks[k].flags & TICK_FLAG_ASK) == TICK_FLAG_ASK, " ", 
(iSeries.ticks[k].flags & TICK_FLAG_BID) == TICK_FLAG_BID
);
*/

      if (!isBuy && !isSell)
      {
        //isBuy = (iSeries.ticks[k].flags & TICK_FLAG_ASK) == TICK_FLAG_ASK && iSeries.ticks[k].ask > iSeries.ticks[k + 1].ask;
        //isSell = (iSeries.ticks[k].flags & TICK_FLAG_BID) == TICK_FLAG_BID && iSeries.ticks[k].bid < iSeries.ticks[k + 1].bid;
      }

if (!iSeries.ticks[k].volume)
Print(
iSeries.ticks[k].volume
);
      if (isBuy)
      {
        buy += iSeries.ticks[k].volume;
        buyTick++;
      }
  
      if (isSell)
      {
        sell -= iSeries.ticks[k].volume;
        sellTick--;
      }

      iAsk[index] = NormalizeDouble(buy, 0);
      iBid[index] = NormalizeDouble(sell, 0);
      iLast[index] = 0;
    }

    ChartRedraw();
    
    return iSeries.ticks[0].time_msc;
  }

  return 0;
}


 
ответ на второй вопрос про бары с нулевым обьемом - CopyTicks присылает минимум один тик даже для тех баров, на которых торговля не велась, поэтому если обьем = 0, то надо делать пропуск бара
 

Бид и Аск - это крайние цены стакана. Соответственно, чтобы они поменялись, сделка не нужна, достаточно передвинуть лимитники, которые стоят на этих уровнях. Можно поиграться на FxOpen-DemoECN, там лимитники внутри спреда сужают его.

Когда совершается  сделка, меняется цена ласт.

 
Andrey Khatimlianskii:

Бид и Аск - это крайние цены стакана. Соответственно, чтобы они поменялись, сделка не нужна, достаточно передвинуть лимитники, которые стоят на этих уровнях. Можно поиграться на FxOpen-DemoECN, там лимитники внутри спреда сужают его.

Когда совершается  сделка, меняется цена ласт.

Да Вы бесчестный человек... 

Причина обращения: