Блог им. ttools

Plaza2 и МТС. Время

время
Доброго времени суток, уважаемые Дамы и господа!

Наконец-то решил завести блог на Смартлабе, и это моя первая статья здесь
Несколько месяцев назад я начал писать цикл статей о Plaza2 и механических торговых системах (HFT в основном) и сейчас подумал, что тема то наверняка интересна и близка многим читателям (и писателям) Smart-lab'а.
Многие считают, что HFT — это секретный алгоритм плюс быстрый робот на собственном сервере, а еще лучще собственном шлюзе размещенный в метре от ядра биржи и соединенный с ним, непременно, золотым проводком. Плюс  самый быстрый в мире датафид с запада, всё это и есть залог успеха. Однако, есть еще такой важный аспект, как техническая реализация. Как бы не был продвинут торговый алгоритм и насколько золотой не была бы инфраструктура, торговый робот, технически реализованный неэффективно имеет мало шансов. В этой статье речь пойдет о синхронизации времени машины, на которой работает торговый алгоритм с временем ядра плазы.
 
При реализации торговых автоматов важно как можно точнее определять текущее время сервера в реальном времени. Это необходимо для:
  1. измерительных задач (например, измерить задержку маркетдаты)
  2. максимально точного исполнения частей торгового алгоритма, связанного со временем (например, прекратить открывать позиции после 16:30 до 16:31)
  3. Для максимально точного сохранения рыночных данных с привязкой к текущему моменту для последующего исторического тестирования
  4. Наверое, для чего-то еще.
На первый взгляд, задача достаточно проста: необходимо лишь получить время сервера, которое транслируется каждую секунду в таблице heartbeat и скорректировать время локальной машины, на которой работает торговый алгоритм.
Такой способ подходит для грубой синхронизации, с точностью примерно до секунды. Но ведь когда речь идет о Plaza2, подразумевается, что возможно торговый алгоритм будет высокочастотным и необходима максимально возможная точность. Здесь придется столкнуться с четырьмя нюансами, которые необходимо учитывать.
Первый связан с механизмом распространения рыночных данных (в том числе и таблицы heartbeat и остальных таблиц с временной меткой, которые понадобятся для синхронизации). Дело в том, что рыночные данные рассылаются биржей клиентам с определенной задержкой. Точнее, не так, чтобы абсолютно все данные задерживались ровно на N миллисекунд; каждая порция данных накапливается в течение этого времени и рассылается клиентам целиком. То есть, если событие произошло сразу после отправки клиенту очередного кванта данных, то клиент будет уведомлен через интервал N, а если событие произошло непосредственно перед очередной рассылкой, то уведомление будет отправлено клиенту без задержки. С развитием инфраструктуры биржи значение времени этой задержки постепенно уменьшается и на текущий момент значение N составляет 100 мс.
Второй нюанс связан с общей проблемой точной синхронизации двух компьютеров. Дело в том, что ни одни часы в мире не могут идти абсолютно точно, и по истечении определенного временного интервала двое самых точных часов без промежуточной синхронизации покажут существенное расхождение. Компьютерные часы в среднем могут убегать или отставать на несколько секунд за сутки. Учитывая, что накопление погрешности с течением времени может бать нелинейным, синхронизировать 2 компьютера достаточно сложно. Поэтому для синхронизации понадобится динамическая и максимально частая сверка часов.
Третий нюанс связан с технологией измерения времени операционной системы (Windows). Точкой отсчета для измерения времени, очевидно, является время локальной машины, на которой работает торговый алгоритм, более доступного точного источника времени в данной ситуации просто нет. Существует несколько функций Windows, предназначенных для получения текущего значения времени, однако не все они одинаково полезны. Для максимально точных замеров времени потребуются функции максимального разрешения. Для этих целей обычно испльзуют функции QueryPerformanceFrequency / QueryPerformanceCounter, или/и процессорную инструкцию RDTSC
Четвертый нюанс связан с особенностями синхронизации времени самого ядра биржи. Время ядра плавно подстраивается по внешнему GPS-датчику, благодаря чему обеспечивается точная синхронность времени в ядра биржи с мировым временем, но приводит к большим нелинейностям разности счета времени сервера торговой системы и ядра.
В потоках плазы есть несколько таблиц, с помощью которых можно синхронизировать время сервера торговой системы и ядра биржи. Это таблицы, которые содержат время события в «реальном времени» одним из полей. Это таблица всех сделок, собственно heartbeat, таблица полного лога заявок (если подключена). Синхронизируя время по этим таблицам можно получить точность синхронизации [0..N], а точнее, если учесть время на сетевые задержки маркетдаты T [T..N+T]. T зависит от качества маршрута между шлюзом биржи и торговым автоматом и минимизируется инвестициями в и работой над торговой инфраструктурой. Такой разброс уже гораздо лучше, чем использование heartbeat. На этом этапе можно легко добиться отклонений [0..150мс], или 75 мс в среднем. Если синхронизировать время по каждому событию из этих таблиц, то каждая синхронизация может как улучшить так и ухудшить точность, по сравнению с предыдущей синхронизацией. Причем, если пришедшее в новой реплике время меньше чем текущее – однозначно синхронизация улучшает результат, если больше – улучшает в половине случаев. То есть, если будут получены лучшие показатели, то такую синхронизацию всё равно имеет использовать частично, для корректировки случаев, если время в реплике меньше, чем установленное время в момент последней синхронизации.
Добиться лучшего результата можно, используя собственные заявки. В ответе шлюза на транзакцию добавления/перемещения заявки содержится время изменения параметров заявки, т.е. если при отправке заявки и при получении ответа запомнить локальное время, это и будет интервал времени локальной машины, внутри которого находится (можно считать посередине) время сервера, которое указано в реплике-ответе шлюза на постановку заявки. Таким способом можно получить синхронизацию серверного времени с локальным с точностью ± 15 мс, без учета корректировок по таблицам маркетдаты, т.е. на самом деле ещё точнее.
Предыдущие статьи можно прочитать здесь
★14
35 комментариев
О чем эта статья? Где хоть слова про HFT?
avatar
reist,
статья о том, как максимально точно синхронизировать время робота и ядра. Это важно для большинства HFT алгоритмов
avatar
Какие люди на смартлабе! Неистово плюсую.
avatar
mark115,
спасибо!
avatar
Спасибо за топик.
Вынес на главную.
Добавил в избранное.
Тимофей,
спасибо!
avatar
хорошая статья.
avatar
modelka,
спасибо! думаю продолжу, если будет интерес к моему творчеству
avatar
Данила, привет.

Очень хороший пост.
avatar
asf-trade,
Привет! Спасибо!
avatar
Почти что «танк Нина Риччи».
Зачем создавать себе проблемы, а потом героически их решать?
Сервера биржи явно синхронизируются с мировыми серверами точного времени: ru.wikipedia.org/wiki/NTP
Это происходит по достаточно простому протоколу NTP.
То же самое может делать любой пользователь робота.
Т.е. через определённые промежутки времени синхронизировать время своего компьютера с теми же серверами, использовать его как эталонное и не морочиться с heartbeat.
В библиотеках для работы с NTP(и самом протоколе) уже учтены временные погрешности при передаче и прочее.
Будьте проще и не стройте Вавилоны, потому что ими потом управлять невозможно.
avatar
Slay,
прежде чем писать такой большой поучительный комментарий, да еще ввернув в него «танк Нина Риччи» ( это добавляет вам собственной значимости? :) ), стоило всё-же немного разобраться в вопросе.

Синхронизация по протоколу ntp дает погрешность порядка 1-2 секунды сразу после синхронизации для сервера, размещенного в датацентре биржи, поэтому здесь совершенно не подходит
avatar
За счёт чего происходит такая огромная погрешность?
avatar
Slay,
причин много, основная, думаю, в особенностях алгоритма синхронизации времени ядра биржи с точным временем по датчику GPS. На эту тему были многократные дискуссии на форуме сайта РТС. Посмотрите ради интереса, например эту ветку forum.rts.ru/viewtopic.asp?t=15432&topicdays=0&postorder=asc&start=0

Позиция биржи по этому вопросу — время ядра верно априори и обсуждению не подлежит. Та схема синхронизации, о которой я рассказал, появилась в результате долгого общения с сотрудниками технической поддержки биржи на эту тему
avatar
Slay, плаза тоже способна достигать черт знает каких скоростей… но иногда по полсекунды ответа ждешь :))))
avatar
Если имеется в виду, что время на серверах в датацентре управляется автоматически с контроллера доменов или чего-то подобного, то рациональнее решить с администраторами этот вопрос и заниматься синхронизацией самостоятельно.
Если это порождено кривой сетевой архитектурой датацентра(что почти нереально), то вопрос туда же.
Протокол NTP позволяет достигнуть высокой точности и создан специально для таких целей.
Цитирую из ru.wikipedia.org/wiki/NTP: «В версии 4 способен достигать точности 10 мс (1/100 с) при работе через Интернет, и до 0,2 мс (1/5000 с) и лучше внутри локальных сетей.»
avatar
Я всё это к тому, что нет смысла размышлять и пытаться угадать как там работает этот шлюз(биржа).
Сие лишь отнимет время.
Рациональнее брать время из тех же источников откуда берёт сам шлюз(биржа).
А это атомные часы и набор серверов вокруг этих часов.
avatar
Slay,
Пытаться угадать действительно смысла нет, а разбираться и спрашивать у сотрудников тех. поддержки — еще как есть.

Здесь первично время ядра биржи. Если синхронизироваться с другим источником, даже супер точным, то получится рассинхронизированное время в потоках заявок, сделок и т.д., что убьёт смысл таких важных вещей для HTF, как бэктестинг например
avatar
Прочитал ссылку.
Прослезился и в очередной раз убедился в странности и запутанности нашей страны.
Однако, судя по forum.rts.ru/viewtopic.asp?p=86603#86603 вопрос решился путём создания биржей собственного NTP сервера(ntp.rts.ru).
Он доступен из интернета.

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

P/S/ Бэктестить HFT стратегии почти нет смысла, потому что время исполнения заявки там играет критически важное время.
Это всё усугубляется близостью до биржи, брокером, и тем как внутри работает ядро биржи. Так что в большинстве случаев результат бэктестинга будет обратным реальности.
avatar
Slay,
вы полностью топик почитайте, какая у людей получалась рассинхронизация при использовании ntp. Там же и о доступности ntp сервера извне.

Страна здесь вообще нипричом, вопрос сугубо технический, но у вас уже рефлекторно похоже — чуть что — сразу страна.

А ваши суждения о том, что бэктестить HFT нет смысла, они на чем основаны? Вы ведь, судя по всему далеки от HFT?
Тут вы совсем не правы: скорее без бэктеста это ОЧЕНЬ дорого и провально с большой вероятностью
avatar
Извне не доступен, а для пользователей плазы вроде как нормально.
Рассинхронизация была, но к концу кажись все поутихли.
Вообще странная ситуация.
Особенно при наличии очевидного решения.
Местами складывается впечатление, что бирже не нужны клиенты.

Супервысокочастотники не пишу, а вот скальперов делал и делаю на заказ.
Внутри программы работает по несколько экземпляров.
Работают через квик.
Штук 6 уже сделал(хотя сам больше склоняюсь к интрадею).
Так вот 4 из них были протестированы на истории и показывали вполне неплохую доходность, а в реальности получилось не очень. Как минимум стало очевидно влияние временных факторов, которые почти не поддаются контролю. Возможно, если перейти на плазу, то может стать лучше, но судя по всему — это соревнования технологий где выигрывают большие бабки(очень), вложенные в инфраструктуру, железо и спецов. В итоге из 6 зарабатывает только 1.
avatar
Если взглянуть стратегически, то скальпинг(HFT) — это очередной мэйнстрим и способ привлечь новое мясо на рынок.
Судя по количеству рекламы и прочего завлекалова типа ЛЧИ.
PLAZA вообще отдельная тема для расследования, потому как есть мировой биржевой протокол с хорошей репутацией и готовыми решениями(FIX).
Его задвинули на второй план и соорудили свою поделку(PLAZA).
А может просто поставили стандартное решение на FIX и сделали над ним обёртку в виде PLAZA.
Короче смахивает сильно на очередное отмывание бабла в ущерб качеству.
Полагаю, что скоро многое прояснится.
avatar
Slay,
Простите, я завершу с вами диалог и вам предлагаю сделать то же
avatar
Пришлось зарегистрироваться, чтобы вставить свои пять копеек.
Автор совершенно прав и если бы я увидел эту статью пару месяцев назад — она бы сэкономила для меня кучу времени. Синхронизация биржи — это единственная (и как мне уже начинает казаться, неразрешимая на данный момент) проблема в бэктестинге HFT. А самое печальное в этой ситуации, то что все эти ухищерения не дают необходимой точности (по типу сравнивать стамп в заявке с стекущим временем). Для меня лично, критична точность в 10ms. Если больше 10ms, то бэктестинг невозможен (погрешность в результате равна 100% практически). Так вот, РТС, сделав NTP сервер никак не решила проблему. Дело в том, что если не использовать реалтайм систему (а они её не используют), то точность часов напрямую зависит от нагрузки на систему. То есть скорость накопления расхождения в часах возрастает по мере роста нагрузки (зависимость, по моим наблюдениям экспоненциальная). И в итоге — чем больше активность на рынке, тем больше погрешность в часах, а следовательно наиболее активные моменты времени недоступны для бэктестинга. Усугубляет ситуацию и то, что точность синхронизации непостоянна не только в течении дня, а ещё и в течении недель и месяцев. То есть настроил ты синхронизацию приемлемую, думаешь что всё ОК, пишешь логи. А потом через пару месяцев замечаешь что ожидание не соответствует реалиям, начинаешь разбираться и выясняешь что ntp.rts.ru в половине из твоих логов просто нагло врёт. Автор, какую синхронизацию вы используете на данный момент для бэктестинга? Из заявки или по ntp или ещё что то? И какой погрешности вам удалось добиться?
avatar
stitrace,
для бэктестинга из заявки, корректирую по сделке, где это возможно. ± 15 мс максимальная погрешность, средняя меньше 7. Можно миллисекунды на 2 улучшить если использовать только ответы длительностью 25 и менее мс
avatar
ttools, а по какой причине не используете ntp.rts.ru? Он хуже результат показывает?
avatar
stitrace,
1) в ядре это время используется условно, т.е. плавно синхронизируется

2) почему-то сразу после синхронизации с ntp я вижу погрешность секундного порядка
avatar
Кстати, +-15ms в точности данного метода это не предел, есть ещё проблема с квантованием времени в операционной системе, по умолчанию в окнах она как раз 15 миллисекунд. То есть любая операция в вашей программе с потоками в windows занимает не менее 15 миллисекунд (при этом не важно что вы там в этом потоке делаетете, хоть 2 на 2 умножаете.
avatar
stitrace,
не совсем так. Не более 15 мс. Обычно потоки отдают управление гораздо раньше. Если протестировать приложение, которое просто пишет время в лог, то получим записи с гораздо меньшим временным интервалом, точно без разрывов по времени n*15
avatar
Я видимо не до конца понимаю потроха windows, но тут есть нюансы, которые связаны с тредами. Если процесс исполняется в параллельном треде, то управление передается ему раз 15 ms. Я не знаю какой язык вы используете, но попробуйте просто тупо засечь время, потом поставить sleep в одну миллисекунду, а потом напечатать разницу между текущим и запомненным. Я был удивлён, когда увидел там 15ms, вместо ожидаемой 1ms. А вопрос у меня этот возник от того что я никак не мог понять, по какой причине, чтобы я не делал, мне не пересечь барьер в 15ms в раундтрипе завки (тогда как теоритический предел у неё — 10ms).
avatar
sitrace,
не знаю, может что-то изменилось, технический предел времени обработки заявки был 16 мс, когда я последний раз общался по этому вопросу с сотрудниками РТС. Мне удавалось достигать этого предела, но очень редко.

Про функцию sleep написано в msdn.
«This function causes a thread to relinquish the remainder of its time slice and become unrunnable for an interval based on the value of dwMilliseconds. The system clock „ticks“ at a constant rate. If dwMilliseconds is less than the resolution of the system clock, the thread may sleep for less than the specified length of time. If dwMilliseconds is greater than one tick but less than two, the wait can be anywhere between one and two ticks, and so on. To increase the accuracy of the sleep interval, call the timeGetDevCaps function to determine the supported minimum timer resolution and the timeBeginPeriod function to set the timer resolution to its minimum. Use caution when calling timeBeginPeriod, as frequent calls can significantly affect the system clock, system power usage, and the scheduler. If you call timeBeginPeriod, call it one time early in the application and be sure to call the timeEndPeriod function at the very end of the application.»

По умолчанию разрешение этой функции обычно 15мс
avatar
У меня после того как я снизил timerresolution до 1ms, примерно 10-15% заявок исполняются меньше чем за 15ms. (лучший результат — 12ms). В техподдержке РТС мне тоже говорили про 16ms и как раз указывали на то что это связано с квантованием времени в windows. Причём эти 12ms, это время отработки функции Send (а не то что возвращает AsyncSend).
avatar
А насчёт теоретического предела, один из топов ЛЧИ упоминал в интервью, что у него раундтрип заявки — 11ms. Я ему поверил, т.к. особого смысла врать тут я не вижу.
avatar

теги блога ttools.ru

....все тэги



UPDONW
Новый дизайн