Отправка и получение сообщений¶
Введение ¶
Эта статья служит введением в использование FIX API для всех, кто заинтересован во взаимодействии с Spotware cServer с использованием FIX.
В этой статье мы используем пример на C#, чтобы подробно описать принципы того, как создать FIX-сообщение, отправить его на сервер и получить ответ. Этот пример ни в коем случае не является безупречным приложением и был сделан максимально простым, чтобы программисты могли легко понять концепцию использования сообщений FIX API.
Для установления и поддержания правильной связи с сервером и правильной обработки ответов требуется дополнительная функциональность, которая была пропущена ради простоты и ясности. Мы рассмотрим эти темы в будущих статьях.
Пример кода ¶
Вы можете найти пример кода, обсуждаемый в этой статье, в нашем репозитории GitHub
Обзор коммуникации FIX ¶
FIX-сообщение - это просто строка, состоящая из наборов числовых тегов и значений, разделенных вертикальной чертой (|). Каждый тег представляет собой различное поле, для которого допустим определенный набор значений. Ниже вы можете увидеть пример FIX-сообщения, которое запрашивает аутентификацию у сервера.
8=FIX.4.4|9=126|35=A|49=theBroker.12345|56=CSERVER|34=1|52=20170117- 08:03:04|57=TRADE|50=any_string|98=0|108=30|141=Y|553=12345|554=passw0rd!|10=131|
Как видите, повторяющийся шаблон, встречающийся в каждом FIX-сообщении:
Tag=Value|Tag=Value|Tag=Value|...
В зависимости от цели каждого сообщения, каждый раз требуется различный набор тегов и значений. Теги и значения, необходимые для каждого сообщения, подробно описаны в Правилах взаимодействия cTrader FIX engine (всегда проверяйте последние правила взаимодействия).
Аналогичным образом ответы отправляются обратно с сервера. Ниже вы можете увидеть ответ сервера на вышеуказанное сообщение.
8=FIX.4.4|9=106|35=A|34=1|49=CSERVER|50=TRADE|52=20170117- 08:03:04.509|56=theBroker.12345|57=any_string|98=0|108=30|141=Y|10=066|
Процесс взаимодействия с FIX-сервером включает следующие этапы:
-
Создание FIX-сообщения
-
Передача FIX-сообщения
-
Получение FIX-сообщения
-
Разбор FIX-сообщения
Необработанное FIX-сообщение имеет не очень удобочитаемый формат, поскольку оно было разработано с учетом эффективности, а не понятности. Поэтому для каждого программного приложения всегда будет существовать процесс преобразования предоставленной информации в соответствующее FIX-сообщение.
В нашем примере приложения на C# мы создали класс для обработки создания сообщений, а также функции для создания FIX-сообщений на основе соответствующей информации.
После создания сообщения передаются между сервером и клиентом через интернет с помощью сетевых сокетов. Когда сообщения получены, их необходимо разобрать для представления в удобочитаемом формате.
В этой статье мы рассмотрим процесс создания, передачи и получения ответа. Разбором мы займемся в следующей статье.
Создание FIX-сообщения ¶
Структура сообщения ¶
В нашем примере приложения мы создали класс, отвечающий за создание FIX-сообщений. Класс называется MessageConstructor и находится в проекте FIX API Library.
MessageConstructor инициализируется следующими параметрами:
-
Host(*)— адрес, где расположен наш cServer. -
Username(*)— номер счета -
Password(*)— пароль -
SenderCompID(*)— предоставляется в форме FIX API cTrader. Имеет формат -
SenderSubID*— это вторая часть SenderCompID -
TargetCompID(*)— предоставляется в форме FIX API cTrader (обычно это cServer)
Эту информацию можно найти в вашей форме cTrader FIX API.
После инициализации MessageConstructor мы готовы создавать сообщения FIX API.
Все сообщения создаются аналогичным образом. Ниже приведен пример кода создания сообщения Logon.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | |
Вы можете видеть, что сначала мы создаем часть тела, затем передаем ее в функцию заголовка и, наконец, передаем обе части в функцию завершения. Эти 3 части подробно описаны ниже.
Процесс создания сообщения — это просто добавление необходимых тегов, значений и разделителей в строку.
Тело ¶
Сначала мы опишем построение тела сообщения, поскольку тело сообщения необходимо создать в первую очередь. Выше можно увидеть пример (создание сообщения Logon).
Мы начинаем с инициализации класса StringBuilder и добавляем теги один за другим на основе входных данных функции. В зависимости от типа сообщения тело должно состоять из различных наборов тегов, некоторые из которых являются обязательными, а другие — необязательными.
Структуру каждого сообщения можно найти в нашем документе Rules of Engagement (/FIX).
Затем мы создаем заголовок для сообщения Logon и добавляем к нему тело сообщения. Наконец, используя строку headerAndBody, мы генерируем трейлер. Далее мы рассмотрим, как создать заголовок и трейлер.
Заголовок ¶
Заголовок — это первая часть сообщения FIX, которая состоит из следующих полей (одинаковых для всех сообщений):
BeginString— начальная строка определяет версию протокола FIX и в нашем случае фиксирована как FIX4.4.BodyLength— длина тела указывает длину сообщения в символах, исключая поляBeginString,BodyLengthи трейлер.MsgType— в этом поле мы определяем тип сообщения, чтобы получатель знал, как разобрать тело.SenderCompID— здесь мы устанавливаемSenderCompID.TargetCompID— это получатель нашего сообщения. В нашем случае это всегда будет cServer.SenderSubID— логин трейдера.MsgSeqNum— это порядковый номер сообщения. Он должен увеличиваться для каждого сообщения, отправленного в рамках одной сессии.Sending Time— время передачи сообщения.
Ниже можно увидеть функцию ConstructHeader, отвечающую за построение заголовков.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | |
Трейлер ¶
Трейлер — это просто тег, содержащий контрольную сумму остальной части сообщения.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | |
Системные сообщения ¶
Наш пример содержит функции, которые возвращают следующие системные сообщения:
- Heartbeat:
MessageConstructor.HeartbeatMessage() - Test request:
MessageConstructor.TestRequestMessage() - Logon:
MessageConstructor.LogonMessage() - Logout:
MessageConstructor.LogoutMessage() - Resend request:
MessageConstructor.ResendMessage() - Reject:
MessageConstructor.RejectMessage() - Sequence reset:
MessageConstructor.SequenceResetMessage()
Прикладные сообщения ¶
Наш пример содержит функции, которые возвращают следующие системные сообщения:
- Market data request:
MessageConstructor.HeartbeatMessage() - Market data snapshot/full refresh:
MessageConstructor.MarketDataSnapshotMessage() - Market data incremental refresh:
MessageConstructor.MarketDataIncrementalRefreshMessage() - New order single:
MessageConstructor.NewOrderSingleMessage() - Order status request:
MessageConstructor.OrderStatusRequest() - Execution report:
MessageConstructor.ExecutionReport() - Business message reject:
MessageConstructor.BusinessMessageReject() - Request for positions:
MessageConstructor.RequestForPositions() - Position report:
MessageConstructor.PositionReport()
Отправить сообщение и получить ответ ¶
Чтобы отправить сообщение FIX на cServer, сначала необходимо установить соединение с сервером. Это можно сделать, создав TcpClient. В нашем случае мы создаем два клиента, поскольку сообщения с котировками цен и торговые сообщения обрабатываются разными портами на сервере.
Затем нужно получить два потока, по которым будут отправляться сообщения. Этот процесс происходит в конструкторе формы, как показано ниже:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | |
В конструкторе мы также инициализируем класс MessageConstructor, который будет использоваться для генерации сообщений.
Далее для отправки сообщений мы создали две разные функции: SendPriceMessage() и SendTradeMessage(). Каждая принимает сообщение FIX в качестве входных данных, а затем вызывает функцию SendMessage() с сообщением и соответствующим потоком в качестве входных данных.
Функция SendMessage() работает следующим образом:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | |
Подробные шаги следующие:
- Кодирование сообщения в массив байтов.
- Запись массива байтов в поток.
- Чтение ответа из потока.
- Увеличение порядкового номера сообщения.
- Кодирование сообщения в строку.
Функция должна возвращать сообщение FIX, отправленное сервером.
Как можно предположить, нельзя показывать пользователю необработанное сообщение FIX, поэтому необходимо разработать дополнительный шаг разбора входящего сообщения.
Заключение ¶
Это приложение представляет собой краткую демонстрацию того, как взаимодействовать с cServer с помощью сообщений FIX. Это всего лишь пример, иллюстрирующий концепции протокола FIX, и ни в коем случае не является полноценным движком FIX. Если вы хотите избежать создания собственного движка FIX, можно рассмотреть возможность использования одного из доступных сторонних движков FIX.
Примечание
Эта статья актуальна по состоянию на 03.02.2017 и разработана с учетом движка cTrader FIX, Rules of Engagement v2.9.1.