Однозначность, конечно, должна быть. Но как было на самом деле - в MT5 нет данных. Все таки это два разных источника тиков.
Вы тоже видели неправильный порядок?
Вы тоже видели неправильный порядок?
Не обращал на это внимание. Приходить в Терминал тики могут точно в другой последовательности, нежели храниться в истории.
Что касается истории, то лучше плясать от воспроизводимого примера на MQ-Demo.
Приходить в Терминал тики могут точно в другой последовательности, нежели храниться в истории.
Мой вопрос про запросы истории. Два "одновременных" запроса из двух индикаторов возвращают массивы с разным порядком.
Уточню ситуацию.
Есть индикатор запрашивающий историю тиков при запуске. Он приложен на два одинаковых графика. Параметром у индикаторов установлена разная глубина запроса.
После запроса тики сохраняются в файл без какой-либо обработки. Открываю файлы, сравниваю, вижу, что набор тиков для каждом миллисекунды одинаков, однако порядок следования различен.
Кроме того видно, что для тиков с изменением Last & Volume поля Ask & Bid заполнены копированием с предыдущего тика с изменением Ask & Bid. Соответственно, если тик переставлен на другое место, то у него другое значение полей.
Аналогично у тиков с изменением Ask & Bid поля Last, Volume скопированы с предыдущего тика с изменением Last & Volume. Если тики Last & Volume переставлены в другом порядке, то в тиках Ask & Bid другие значения полей.
Прикрепите, пожалуйста, индикатор и файлы.
ЗЫ Этот скрипт проблему не показал
// Скрипт записывает 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"); }
Прикладываю код индикатора, воспроизводящего эффект.
Похоже, что эффект проявляется только после того, как будет сделан запрос тиков большой длины. Мне удалось поймать эффект при запросе 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; }
Прикладываю код индикатора, воспроизводящего эффект.
Сервер и символ?
Сервер "AMPGlobalUSA-Demo"
Символ CLEJ19
Подтверждаю баг. Он проявляется, если брать тики за текущий день.
Например, берем с 2019.03.07 и 2019.03.11 (сегодня)- битые тики за текущий день.
Берем с 2019.03.07 и 2019.03.08 - совпадающие тики за сегодня.
ЗЫ Интересный сервер - полно тиковой истории.
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Вопрос к разработчикам терминала.
Верно ли, что функция 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
Спасибо