Помогите разобраться с очень странным эффектом. Веду записи с помощью гидры потоков сделок и изменений стаканов по нескольким инструментам.
Затем решил построить график во времени, наложив лучшие Ask-Bid и фактические сделки.
Я обнаружил, что поток сделок (по таблице всех сделок) очень сильно запаздывает по отношению к потоку стаканов. Получилось, что для сбербанка запаздывание потока сделок составляет 15-20 секунд, для индекса RTS –примерно 35 секунд! Смотрите сами прикрепленные картинки. Я постарался подобрать наиболее наглядные фрагменты, но общая картина почти не меняется во времени. (Синий – лучший Bid, Зеленый – лучший Ask, Красный – фактические сделки)
Сбербанк за 2012-10-18, фрагмент

Фьючерс на индекс РТС за 2012-10-19, фрагмент

Все данные я получал от своего брокера.
Стаканы, очевидно, маркируются локальным временем моего компьютера, которое я перед сессией синхронизирую через интернет-тайм. Т.е. записывается компьютерное время изменения стакана в момент его изменения, когда информация об изменении УЖЕ дошла до моего терминала.
Сделки построены по времени Time в структуре Trade, как я понимаю, это должно быть время по часам биржи. Первая мысль была – мой брокер шалит и выдает поток сделок с запаздыванием. Но я проверил поток сделок, сравнив их с данными с www.finam.ru. Поток моего брокера не отличается абсолютно. Если построить графики по сделкам по данным от финама и от моего брокера, то они совпадут пиксель-в-пиксель (что само по себе меня несколько удивило – я думал, что незначительная разница может быть)
И так, наблюдается абсолютно стабильный эффект, поток сделок отстает на несколько десятков секунд от соответствующего движения в стаканах.
Вопрос к знатокам – как такое может быть и с чем это может быть связано?
评论 (8)
登录 或 创建账户, 登录或注册以发表评论
Думаю тут причины в:
Попробую по пунктам:
1.1. Как я уже писал, график сделок совпадает пиксель-в-пиксель с графиком, построенным по данным Финам. Причем график по данным Финам я строю, не используя вообще средства S# (напрямую читаю данные из текстового файла в Матлабе). Таким образом, тиковому графику по сделкам можно верить.
1.2. Часы моего компьютера устанавливаются по интернет-тайм непосредственно перед торговой сессией, т.е. можно рассчитывать на точностью в несколько десятков – единицы сотен миллисекунд. На всякий случай проверяю по телефону 100 – все ОК.
1.3. Я сделал свое собственное протоколирование потока данных. Для сделок, помимо Trade.Time и Trade.Latency записывается время по компьютерным часам на момент поступления информации о сделке. Результат: в устоявшемся режиме время по компьютерным часам примерно на 0.5 секунды МЕНЬШЕ времени Trade.Time. Объясняется это, скорее всего, тем, что Trade.Time квик или биржа округляет до секунды, плюс еще погрешность установки компьютерных часов. В общем, все в порядке.
1.4. Поток стаканов также протоколирую собственными средствами. Записываю время по компьютерным часам на момент поступления информации (в моей собственной функции) и время MarketDepth .LastChangeTime. Результат: эти два времени совпадают абсолютно. Так, собственно, и должно быть. Таким образом, со входящими потоками проблем вроде бы нет.
1.5. Для построения графиков данные беру из хранилища Гидры (закачку из своих собственных протоколов не делал – руки не дошли). Наблюдаем картинки, показанные выше.
1.6. Я могу представить себе следующие варианты объяснения (в порядке от наиболее вероятной к наименее вероятной)
1.6.1. Неправильно записывается или читается время MarketDepth .LastChangeTime. Т.е. в результате цикла сохранение – чтение LastChangeTime получает отрицательное смещение секунд в 10. Вопрос к разработчикам – может ли такое быть. Ведь LastChangeTime это – свойство, с некоторой реализацией “get”. Не может ли оказаться, что именно эта реализация дает такое смещение? Проверить это предположение можно, но очень муторно – фактически, нужно организовывать альтернативное хранилище по отношению к гидре. Поэтому хотелось бы сначала получить комментарии от разработчика.
1.6.2. Прочие мыслимые «программные» глюки вроде бы проверил и исключил, как в Матлабе так и в компоненте, использующем S#.
1.6.3. Технология формирования сделки на бирже. Сначала изымаются встречные заявки из стаканов. Затем происходят внутренние транзакции по оформлению сделки, которые занимают прядка 10 секунд. И только затем уведомление о заключенной сделке рассылается по биржевым каналам. Я про такие, гигантские по сути, биржевые задержки нигде не слышал. Может ли такое быть?
1.6.4. Мой брокер использует временной портал секунд в 10 в будущее, и берет через него будущие стаканы и милостиво рассылает их своим клиентам. Поток сделок же идет нормальным образом. В таком случае цены нет моему брокеру.
http://stocksharp.com/doc/?topic=html/e4a57b52-bd14-4640-a7c7-0979dba1ad0a.htm
Не разреженность, а прореженность... В секунду происходит около сотни регистраций и снятий. Естественно, квик, да еще и в агрегированном состоянии, такое количество изменений просто не будет транслировать. Может быть такая ситуация, что матчинговый снимок стакана просто не был передан в программу, и последующий рематчинг произошел со сдвигом только за счет принципа mean reversion
В общем , повозился и выяснил. Это – БАГ. То ли в гидре то ли еще где в недрах C# Проверял Так. Модифицировал Гидру, а именно ф-ию OnMarketDepthsChanged. Смысл в том, что я создаю свой текстовый файл, в который пишу стаканы для "SBER@EQBR" и RIZ2@RTS". При этом запоминаю момент, когда пришло управление в ф-ию OnMarketDepthsChanged() и записываю это время в свой файл вместе со временем MarketDepth.LastChangeTime.
Как видно из дальнейших логов эти два времени в точности совпадают. Прочая функциональность гидры осталась без изменений:
Далее читаю записанные данные, сохраненные гидрой. Для этого использовал доработанный вариант SampleStorage. Вот полный код:
И так, результат.
Вот, что реально приходило в OnMarketDepthsChanged() и должно было быть сохранено. Данные по моим собственным логам:
А вот, что было затем прочитано из хранилища:
Обратите внимание на времена и значения Асков-Бидов. Все прочитанные данные получили отрицательное смещение по времени на ~14 секунд.
Да, интересная ситуация. Думаю стоит выводить еще и DateTime.Ticks, так как Kind не понятно как работает.
Ну вот. Проверил с тиками. Вывод – с тиками все те же проблемы.
Чтобы не смущал DateTime.SpecifyKind() – я его на этот раз убрал.
Вот результат по моим логам из гидры:
Вот результаты считывания данных:
Сдвиг по времени меньше, чем в прошлые разы, но все равно значительный. У меня сложилось впечатление, что сдвиг зависит от времени работы Гидры – ошибка накапливается в процессе работы. В этот раз гидра работала всего 1.5 часа в вечернюю сессию, ранее - по 8 часов в дневную.
Несколько слов о заплатке с DateTime.SpecifyKind(), которую я использовал в прошлый раз. Это -обход другой проблемы со временем. При считывании данных стаканов значение LastChangeTime.Kind может оказаться или Local или Unspecified. От чего это зависит – проще разобраться самим разработчикам. В общем-то это – тоже бага. Разные LastChangeTime.Kind могут по-разному обрабатываются всякими функциями преобразования времени в другие форматы. В частности, перестают нормально работать ф-ии сравнения времени больше-меньше. Без моего фикса картинки были совсем веселые.
DateTime.SpecifyKind() меняет только поле типа времени и не трогает остальные значения.
Мои коды:
Фиксы залиты и выложены на бокс.нет
Ситуация была такая. Стаканы в Квике не имеют временной отметки, и поэтому берется локальное время компьютера. При накоплении этой информации отбрасывались значения, точнее миллисекунд (смысла в них нет особо, так как они все равно берутся с локального компьютера). В итоге происходила аккумуляционная ошибка погрешности, что со временем приводило к расхождению во временных рядах. Сейчас алгоритм переделан на другой способ (формат Гидры при этом не изменялся), и эта ошибка предотвращена.
Стаканы из Плазы, как самые достоверные, не были подвержены этой ошибке, так как маркируются временной меткой биржи.
Приносим свои извинения за доставленные неудобства, и благодарим за своевременное оповещение о проблеме.
В течение двух дней проверял.
Проблема действительно полностью устранена. Никаких расхождений более 1 миллисекунды больше не наблюдается.
Вообще, очень приятно то, что проблему устранили достаточно оперативно. Желаю дальнейших успехов разработчикам и проекту!