Вопрос к разработчикам по порядку выдаваемых тиков функцией CopyTicksRange()

Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий
Ilya Baranov
4316
Ilya Baranov  

Вопрос к разработчикам терминала.

Верно ли, что функция CopyTicksRange() выдает тики c изменением Last & Volume с одинаковым временем в миллисекундах в произвольном порядке?

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

При этом, если запрашивать тики с параметром COPY_TICKS_ALL тики с Ask & Bid всегда получаются в одинаковом порядке, однако в произвольном порядке между ними вставлены тики с изменением Last & Volume.

Например, есть тики с изменениями Ask& Bid ab1, ab2 и тики с изменениями Last&Volume lv1, lv2, lv3. Время в миллисекундах у них одинаковое.

Функция CopyTicksRange() может выдавать их в следующем порядке:

ab1

ab2

lv1

lv3

lv2

или

lv3

ab1

ab2

lv2

lv1

или

lv1

ab1

lv2

lv3

ab2

 

Билд 2007

Спасибо

fxsaber
16744
fxsaber  
Однозначность, конечно, должна быть. Но как было на самом деле - в MT5 нет данных. Все таки это два разных источника тиков.
Ilya Baranov
4316
Ilya Baranov  
fxsaber:
Однозначность, конечно, должна быть. Но как было на самом деле - в MT5 нет данных. Все таки это два разных источника тиков.

Вы тоже видели неправильный порядок?

fxsaber
16744
fxsaber  
Ilya Baranov:

Вы тоже видели неправильный порядок?

Не обращал на это внимание. Приходить в Терминал тики могут точно в другой последовательности, нежели храниться в истории.

Что касается истории, то лучше плясать от воспроизводимого примера на MQ-Demo.

Ilya Baranov
4316
Ilya Baranov  
fxsaber:

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

Мой вопрос про запросы истории. Два "одновременных" запроса из двух индикаторов возвращают массивы с разным порядком.

Ilya Baranov
4316
Ilya Baranov  

Уточню ситуацию.

Есть индикатор запрашивающий историю тиков при запуске. Он приложен на два одинаковых графика. Параметром у индикаторов установлена разная глубина запроса.

После запроса тики сохраняются в файл без какой-либо обработки. Открываю файлы, сравниваю, вижу, что набор тиков для каждом миллисекунды одинаков, однако порядок следования различен.

Кроме того видно, что для тиков с изменением Last & Volume поля Ask & Bid заполнены копированием с предыдущего тика с изменением Ask & Bid. Соответственно, если тик переставлен на другое место, то у него другое значение полей.

Аналогично у тиков с изменением Ask & Bid поля Last, Volume скопированы с предыдущего тика с изменением Last & Volume. Если тики Last & Volume переставлены в другом порядке, то в тиках Ask & Bid другие значения полей.

fxsaber
16744
fxsaber  

Прикрепите, пожалуйста, индикатор и файлы.


ЗЫ Этот скрипт проблему не показал

// Скрипт записывает TICKS_ALL-тики с определенной даты.
#property script_show_inputs

input datetime StartTime = D'01.02.2019';

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 )
{
  return(TOSTR(time) + "." + ::IntegerToString(Tick.time_msc % 1000, 3, '0') +
         TOSTR2(bid) + TOSTR2(ask) + TOSTR2(last)+ TOSTR(volume) + GetTickFlag(Tick.flags));
}

#undef TOSTR2
#undef TOSTR


int TicksToFile( const MqlTick &Ticks[], const string FileName )
{
  const int Size = ArraySize(Ticks);

  if (Size)
  {
    const int handle = FileOpen(FileName, FILE_WRITE | FILE_ANSI | FILE_TXT);

    if (handle != INVALID_HANDLE)
    {
      FileSeek(handle, 0, SEEK_END);

      for (int i = 0; i < Size; i++)
        FileWrite(handle, TickToString(Ticks[i]));

      FileClose(handle);
    }
  }

  return(Size);
}

void OnStart()
{
  MqlTick Ticks[];
  
  if (CopyTicksRange(_Symbol, Ticks, COPY_TICKS_ALL, (ulong)StartTime * 1000, LONG_MAX) > 0)
    TicksToFile(Ticks, _Symbol + "_" + TimeToString(StartTime, TIME_DATE) + ".csv");
}
Ilya Baranov
4316
Ilya Baranov  

Прикладываю код индикатора, воспроизводящего эффект.

Похоже, что эффект проявляется только после того, как будет сделан запрос тиков большой длины. Мне удалось поймать эффект при запросе 8000 минут (примерно 5 дней). Пока использовались запросы около 600 минут, проблема не воспроизводилась.

Сервер "AMPGlobalUSA-Demo"

Символ CLEJ19


Формат файла CSV, разделители - точка с запятой, поля: 

  • время;
  • ask;
  • bid;
  • last;
  • volume;
  • флаги.


Расшифровка флагов:

  • a - TICK_FLAG_ASK;
  • b - TICK_FLAG_BID;
  • l - TICK_FLAG_LAST;
  • v - TICK_FLAG_VOLUME;
  • B - TICK_FLAG_BUY;
  • S - TICK_FLAG_SELL.

В сохраненных файлах наблюдаю следующее (показаны данные за одну миллисекунду):

запрос 660 минут:

...

10:32:29.986; 56.61; 56.60; 56.60; 2.00;   lv S

10:32:29.986; 56.61; 56.60; 56.60; 2.00; a     

10:32:29.986; 56.61; 56.60; 56.60; 1.00;   lv S

10:32:29.986; 56.61; 56.60; 56.60; 2.00;   lv S

10:32:29.986; 56.61; 56.60; 56.60; 1.00;   lv S

10:32:29.986; 56.61; 56.60; 56.60; 2.00;   lv S

10:32:29.986; 56.61; 56.60; 56.60; 1.00;   lv S

10:32:29.986; 56.61; 56.60; 56.60; 4.00;   lv S

10:32:29.986; 56.60; 56.59; 56.60; 4.00; ab    

10:32:29.986; 56.60; 56.59; 56.60; 1.00;   lvB 

10:32:29.986; 56.60; 56.59; 56.60; 2.00;   lvB 

10:32:29.986; 56.60; 56.59; 56.60; 1.00;   lvB 

10:32:29.986; 56.60; 56.59; 56.60; 1.00;   lvB 

10:32:29.986; 56.60; 56.59; 56.60; 1.00;   lvB 

10:32:29.986; 56.60; 56.59; 56.60; 1.00;   lvB

..

 

Запрос 8000 минут:

...

10:32:29.986; 56.61; 56.60; 56.60; 2.00;   lv S

10:32:29.986; 56.61; 56.60; 56.60; 1.00;   lv S

10:32:29.986; 56.61; 56.60; 56.60; 2.00;   lv S

10:32:29.986; 56.61; 56.60; 56.60; 1.00;   lv S

10:32:29.986; 56.61; 56.60; 56.60; 2.00;   lv S

10:32:29.986; 56.61; 56.60; 56.60; 1.00;   lv S

10:32:29.986; 56.61; 56.60; 56.60; 4.00;   lv S

10:32:29.986; 56.60; 56.59; 56.60; 4.00; ab    

10:32:29.986; 56.60; 56.59; 56.60; 1.00;   lvB 

10:32:29.986; 56.60; 56.59; 56.60; 2.00;   lvB 

10:32:29.986; 56.60; 56.59; 56.60; 1.00;   lvB 

10:32:29.986; 56.60; 56.59; 56.60; 1.00;   lvB 

10:32:29.986; 56.60; 56.59; 56.60; 1.00;   lvB 

10:32:29.986; 56.60; 56.59; 56.60; 1.00;   lvB 

10:32:29.986; 56.61; 56.59; 56.60; 1.00; a     

...


Наблюдается перестановка тиков местами, включая тики ask & bid.

(вопреки моему предположению в первом посте о том, что их порядок сохраняется).

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


Кроме того, в определенных местах файла наблюдаю разницу в заполнении поля volume.

Запрос 660 минут:

10:53:38.441; 56.54; 56.53; 56.53; 1.00;   lv S

10:53:38.441; 56.54; 56.53; 56.53; 2.00;   lv S

10:53:38.441; 56.54; 56.53; 56.53; 2.00;   lv S

10:53:38.441; 56.54; 56.53; 56.53; 1.00;   lv S

10:53:38.441; 56.54; 56.53; 56.53; 1.00;   lv S

10:53:38.441; 56.54; 56.53; 56.53; 1.00;   lv S

10:53:38.441; 56.54; 56.53; 56.53; 1.00;   lv S

10:53:38.441; 56.54; 56.53; 56.53; 1.00;   lv S

10:53:38.441; 56.54; 56.53; 56.53; 1.00;   lv S

10:53:38.441; 56.54; 56.52; 56.53; 0.00;  b    

10:53:38.443; 56.53; 56.52; 56.53; 0.00; a   

Запрос 8000 минут:

10:53:38.441; 56.54; 56.53; 56.53; 1.00;   lv S

10:53:38.441; 56.54; 56.53; 56.53; 2.00;   lv S

10:53:38.441; 56.54; 56.53; 56.53; 2.00;   lv S

10:53:38.441; 56.54; 56.53; 56.53; 1.00;   lv S

10:53:38.441; 56.54; 56.53; 56.53; 1.00;   lv S

10:53:38.441; 56.54; 56.53; 56.53; 1.00;   lv S

10:53:38.441; 56.54; 56.53; 56.53; 1.00;   lv S

10:53:38.441; 56.54; 56.53; 56.53; 1.00;   lv S

10:53:38.441; 56.54; 56.53; 56.53; 1.00;   lv S

10:53:38.441; 56.54; 56.52; 56.53; 1.00;  b    

10:53:38.443; 56.53; 56.52; 56.53; 1.00; a     


Сохраненные файлы в приложенном архиве.

Код индикатора:

#define PROGRAM_NAME "TICK_SEQ_IND"
#define VERSION "1.00"

//=====================================================================
//              Parameters
input uint      PShowMinutes = 60;                      //Show minutes

//=====================================================================
//              Indicator properties
#property indicator_chart_window
#property indicator_buffers 0
#property indicator_plots 0

//=====================================================================

int OnInit(void)
{
        // Start time
        datetime startTime = TimeTradeServer() - PShowMinutes * 60;
        
        // Load ticks
        MqlTick ticks[];
        int loaded = CopyTicksRange( Symbol() , ticks , COPY_TICKS_ALL , startTime * 1000 , 0 );
        if ( loaded < 0 )
        {
                Print( "Error loading ticks" );
                return INIT_SUCCEEDED;
        }
        
        // Open file
        string fileName = "ticks" + IntegerToString( PShowMinutes ) + ".txt";
        int file = FileOpen( fileName , FILE_WRITE | FILE_TXT );
        if ( file == INVALID_HANDLE )
        {
                Print( "Error opening file" );
                return INIT_SUCCEEDED;          
        }
        
        // Saving ticks to file
        int nTick = ArraySize( ticks );
        for ( int iTick = 0 ;   iTick < nTick ;   iTick ++ )
        {
                saveTick( ticks[ iTick ] , file );
        }
        
        FileClose( file );
        Print( "Saved ticks " + IntegerToString( nTick ) );
        return INIT_SUCCEEDED;
}

void saveTick( const MqlTick& tick , int file_handle )
{
        // Запись в файлы
        int digits = (int) SymbolInfoInteger( Symbol() , SYMBOL_DIGITS );
        FileWriteString( file_handle , TimeToString( tick.time_msc / 1000 , TIME_MINUTES | TIME_SECONDS ) + "." + IntegerToString( tick.time_msc % 1000 , 3 , '0' ) );
        FileWriteString( file_handle , "; " );
        FileWriteString( file_handle , DoubleToString( tick.ask , digits ) );
        FileWriteString( file_handle , "; " );
        FileWriteString( file_handle , DoubleToString( tick.bid , digits ) );
        FileWriteString( file_handle , "; " );
        FileWriteString( file_handle , DoubleToString( tick.last , digits ) );
        FileWriteString( file_handle , "; " );
        FileWriteString( file_handle , DoubleToString( tick.volume , digits ) );
        FileWriteString( file_handle , "; " );
        string flags;
        flags += (bool) (  tick.flags & TICK_FLAG_ASK    ) ? "a" : " ";
        flags += (bool) (  tick.flags & TICK_FLAG_BID    ) ? "b" : " ";
        flags += (bool) (  tick.flags & TICK_FLAG_LAST   ) ? "l" : " ";
        flags += (bool) (  tick.flags & TICK_FLAG_VOLUME ) ? "v" : " ";
        flags += (bool) (  tick.flags & TICK_FLAG_BUY    ) ? "B" : " ";
        flags += (bool) (  tick.flags & TICK_FLAG_SELL   ) ? "S" : " ";
        FileWriteString( file_handle , flags );
        FileWriteString( file_handle , "\n" );  
}

void OnDeinit( const int reason )
{
}

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
{
        return rates_total;
}


fxsaber
16744
fxsaber  
Ilya Baranov:

Прикладываю код индикатора, воспроизводящего эффект.

Сервер и символ?

Ilya Baranov
4316
Ilya Baranov  
Ilya Baranov:

Сервер "AMPGlobalUSA-Demo"

Символ CLEJ19

fxsaber
16744
fxsaber  

Подтверждаю баг. Он проявляется, если брать тики за текущий день.

Например, берем с 2019.03.07 и 2019.03.11 (сегодня)- битые тики за текущий день.

Берем с 2019.03.07 и 2019.03.08 - совпадающие тики за сегодня.


ЗЫ Интересный сервер - полно тиковой истории.

12
Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий