Приветствую дорогие читатели. Закончил недавно делать коннектор к OsEngine, который использует FIX protocol напрямую. Пришлось повозиться. Вы можете посмотреть всё это в нашем коде на GitHub. Ну а для тех кому этого будет недостаточно, напишу подробнее об использовании Fix протокола. Выясним что это такое, разберемся как им пользоваться для обмена данными с торговыми площадками. Статья в первую очередь будет полезна для тех, кто собирается писать свое подключение к какой-либо бирже при помощи fix протокола, при чем не зависимо от выбранного языка программирования. Вы поймете какую структуру должны иметь fix сообщения и много других нюансов.
Протокол был создан в 1992 году специально для обмена биржевой информацией между участниками торгов как замена торговле через телефон, преобладающей на тот момент. На данный момент поддерживается большинством крупнейших бирж мира, в том числе и московской. Со дня основания прошло не мало времени, естественно и сам протокол все это время совершенствовался. Постепенно в протокол добавлялся новый функционал, поддержка новых классов инструментов. Сейчас FIX 5.0 является последней версией, но, наиболее распространенной является FIX 4.4. Протокол существует в двух синтаксисах. Это набор пар «ключ - значение» и XML, именуемый также FIXML. В этой статье мы подробно поговорим о первом из них. Сам протокол в свою очередь разделяется на 3 уровня – транспортный, сессионный и прикладной.
Транспортный уровень протокола описывает структуру FIX сообщений, а именно то, каким образом они строится. В готовом виде оно представляет из себя обычную строку. Человеку, не знакомому с синтаксисом fix сообщений, эта строка покажется неким шифром, оно так и есть на самом деле. Давайте взглянем на него.
Это готовое к отправке сообщение на биржу Lmax, которое сообщит ей что мы хотим залогиниться в системе, так называемое LogOn сообщение. Действительно, на первый взгляд непонятно что тут зашифровано. Давайте разбираться. Как я уже выше говорил, FIX существует в двух синтаксисах, как раз из этого примера мы можем видеть первый из них. Сообщение состоит из неких частей, разделенных вертикальной чертой. Эти части называются полями(fields), каждое поле также состоит из двух частей, разделенных знаком «равно». Слева от знака равно находится ключ, справа его значение. Поэтому этот синтаксис и получил такое название. В спецификации FIX ключи принято называть тегами(Tags). Tag – всегда целое положительное число, которое является по сути указателем на имя поля. И естественно, чтобы правильно создавать и расшифровывать fix сообщения, у вас должна быть под рукой документация от биржи, к которой вы планируете подключаться, с именами тегов, описанием типа данных, которые содержит поле с указанным тегом и описанием самих данных. Большинство полей являются стандартными и всегда будут иметь один и тот же смысл на всех биржах. Но далеко не все поля поддерживаются самими биржами. В fix сообщении есть как обязательные поля, так и не обязательные, есть также условно-обязательные – это те, наличие которых зависит от наличия других полей. На схеме ниже можем наглядно увидеть разделение сообщения на поля.
В качестве разделителя полей между собой выступает символ SOH (Start of Heading) из кодировки ASCII. На самом деле он является не отображаемым, но для удобства восприятия на схеме он отображен вертикальной чертой. В формате UNICODE этот символ имеет код “\u0001”.
По мимо того что сообщение состоит из полей, оно так же разделяется на 3 составляющие:
Несмотря на то, что названия говорят сами за себя, могут возникнуть некоторые вопросы.
Заголовок может включать в себя довольно большой перечень полей, но мы разберем только основные, наличие которых обязательно в каждом сообщении.
8 = FIX.4.4 – версия протокола, всегда идет первым в сообщении.
9 = 123 – размер сообщения, всегда второе по счету, в зачет идут все символы, за исключением первых двух полей и контрольной суммы.
35 = V – тип сообщения, всегда третье поле, например, V – означает что мы хотим запросить рыночные данные.
34 = 2 – порядковый номер отправляемого сообщения за текущий сеанс соединения.
49 = FIXtest1 – идентификатор отправителя, выдается биржей.
54 = 20120924-14:05:44.952 – время отправки.
56 = LMXBDM – идентификатор получателя, выдается биржей.
С телом вопросов возникнуть не должно, обычный набор полей, специфичный для каждого типа запросов. Единственное на что обращу Ваше внимание, это возможность использования групп – набора полей с одинаковыми тегами. Например, мы хотим запросить данные по целому списку инструментов, тогда мы должны перечислить инструменты, каждый в своем поле. Все эти поля будут иметь одинаковый тег, они-то и будут называться группой. По этой причине не удастся представить сообщение списком пар ключ-значение, например, Dictionary<t,v>. Лучшим выходом, на мой взгляд, будет создание своего класса, представляющего поле сообщения. Именно так я и поступил.
Отдельного внимания требует контрольная сумма. Она считается по специальной формуле, в расчет берутся заголовок и само тело. Сначала считаем длину заголовок + тело, затем получаем остаток от деления длины на 256. Контрольная сумма всегда должна состоять из трех символов, если у нас, например, получилось число 15, мы должны перед ним добавить 0 и по итогу контрольная сумма должна выглядеть так - «10 = 015|».
Протокол сессионного уровня описывает технику установки/разрыва соединения, поддержки связи, запрос пропущенных данных. Он включает в себя следующие сообщения:
1. Logon (35=A) – аутентифицирует пользователе на стороне сервера, всегда отправляется первым для запуска сессии обмена данными. После отправки этого сообщения, клиент должен уже быть готов обрабатывать встречные сообщения. В случае успеха в ответ вернется сообщение такого же формата, иначе сообщение с ошибкой.
2. Logout (35=5) – разрывает связь с сервером.
3. Heartbeat (35=0) – сообщение пульса, отправляется обоими сторонами при отсутствии каких-либо сообщений, информирует о том, что контрагент активен и готов к приему. Интервал времени, по прошествии которого отправляется пульс, задается клиентов в Logon сообщении.
4. Test Request (35=1) – тестовое сообщение, отправляется если от контрагента за положенный интервал не пришло сообщение пульса. Если на него не ответить тем же, то сеанс связи закрывается автоматически.
5. Resend Request (35=2) – запрос на повторную отправку сообщений. Например, мы обнаружили пропуск нескольких сообщений от биржи. Resend Request сообщит об этом серверу и тот вернет нам эти данные повторно.
6. Reject (35=3) – отправляется в ответ на сообщение, которое является структурно недействительным. Например, если в сообщении недопустимый или отсутствующий тег, или неправильно сформированное поле.
7. Sequence Reset (35=4) – имеет 2 предназначения. Если поле GapFillFlag (тег 123) имеет значение “Y”, тогда используется для пропуска административных сообщений при повторной пересылке. Иначе используется для сброса счетчика MsgSeqNum.
Прикладной уровень
Описание прикладного уровня является самым обширным, потому что в нем содержится вся остальная информация, касаемо взаимодействия с биржей. В данной статье мы не будем затрагивать большинство сообщений, рассмотрим только лишь основные в общих чертах.
1. Market Data Request (35=V) – подписаться на поток данных, такие как котировки в реальном времени, ордера, сделки, объем и другие. Так же при помощи этого сообщения можно отписаться от получения данных, указав ID предыдущего запроса. В ответ биржа начнет присылать сообщения MarketDataSnapshotFullRefresh (35=W) с запрошенными данными.
2. New Order Single (35=D) – выставить ордер в систему. Мы можем указать собственный идентификатор, что упрощает отслеживание изменений, будь то исполнение, частичное исполнение или же отмена ордера.
3. Execution Report (35=8) – отчет о выполнении. Информирует о статусе выставления ордера, о его отмене по каким-либо причинам, или же о сделках, связанных с нашими ордерами. Тип отчета обозначается в поле Exec Type (Tag 150).
4. OrderCancelRequest (35=F) – запрос на отмену ордера.</t,v>
Кроме описанных, Fix поддерживает кучу других сообщений для разного рода потребностей. Тут уже нужно исходить из документации биржи и собственных предпочтений. Из-за подобного синтаксиса, протокол является легковесным, что в свою очередь обеспечивает высокую скорость обмена данными. Не смотря на свой возраст, на сегодняшний день это один из самых быстрых протоколов. Надеюсь статья кому-нибудь сэкономит время и поможет обойти подводные камни, на которые наткнулся я сам. Ниже список источников, на которых Вы сможете более подробно ознакомиться с протоколом.</t,v>
самая информативная документация на мой взгляд
документация московской биржи
fix wiki
2 комментария