Изображение блога
Fininja
Fininja Блог компании Os_Engine
12 июля 2024, 16:25

Коннектор MoexFixFastSpot: обзор кода в OsEngine – архитектура и модули

Всем привет!

Сегодня расскажу, как все устроено в коде нового коннектора.

Коннектор MoexFixFastSpot: обзор кода в OsEngine – архитектура и модули 

 OsEngine – проект с открытым кодом, поэтому посмотреть раздел, относящийся к коннектору можно прямо сейчас онлайн по адресу https://github.com/AlexWan/OsEngine/tree/master/project/OsEngine/Market/Servers/MoexFixFastSpot

Также можно просто скачать весь проект и открыть его в Visual Studio, чтобы смотреть более наглядно.

Коннектор MoexFixFastSpot: обзор кода в OsEngine – архитектура и модули 

 

Если вы еще не в курсе, то весь OsEngine написан на языке C#, который сейчас считается одним из самых популярных для финтех приложений в нашей стране и в мире.

Разбор FIX-сообщений

В папке FIX находятся вспомогательные классы с разными полезностями для разбора и формирования FIX-сообщений.

Коннектор MoexFixFastSpot: обзор кода в OsEngine – архитектура и модули 

Например, в абстрактном классе заголовка можно видеть стандартные поля типа SenderCompID (идентификатор отправителя) или MsgType (тип сообщений), а также перегруженную функцию ToString, отвечающую за формирование правильного байтового представления сообщения при помощи строковых функций стандартной библиотеки C#.

Коннектор MoexFixFastSpot: обзор кода в OsEngine – архитектура и модули 

Второй более сложный пример – класс, представляющий тело сообщения типа “New Order Single” (новая заявка) и в его методе ToString формируется строка со всеми полями в необходимом порядке. Все теги (параметры) разделены символом SOH, который в юникоде обозначается как “\u0001”.

За самую важную часть, разбор входящих FIX-сообщений, отвечает класс FIXMessage.

Коннектор MoexFixFastSpot: обзор кода в OsEngine – архитектура и модули 

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

 Коннектор MoexFixFastSpot: обзор кода в OsEngine – архитектура и модули

Например, fixMessage.Fields[“TestReqID”] даст значение поля с тегом TestReqID.

Можно было бы сделать все гораздо более абстрактно, но хотелось соблюсти баланс между универсальностью и простотой.

 Коннектор MoexFixFastSpot: обзор кода в OsEngine – архитектура и модули

Всего в коннекторе 11 регионов кода, а также несколько дополнительных сервисных классов.

В начале при включении коннектор читает параметры конфигурации.

Коннектор MoexFixFastSpot: обзор кода в OsEngine – архитектура и модули 

IP-адреса, порты, идентификаторы FIX-серверов, логины, пароли и счет пользователя задаются именно тут. Настройки рыночных данных, а именно конфигурация FIX/FAST Multicast UDP и шаблоны FAST-сообщений задаются в отдельной папке, путь к которой тоже есть в параметрах.

Далее мы подключаемся к MFIX Trade, MFIX Trade Capture по TCP для управления ордерами и получения отчетов об исполнении.

Рыночные данные по FAST

Для получения рыночных данных мы подключаемся к прослушиванию UDP Multicast потоков.

 

  • 2 дублирующихся потока обновлений ордеров;
  • 2 дублирующихся потока снэпшотов ордеров;
  • 2 дублирующихся потока обновлений сделок;
  • 2 дублирующихся потока снэпшотов сделок;
  • 2 дублирующихся потока определений инструментов.

Потоки статистики и статусов инструментов (ISF, не показан на схеме) не используются. Подключение к серверу TCP Replay происходит по мере необходимости, в случае если произошла потеря данных.

Так что мы храним 10 UDP сокетов, по которым постоянно идут рыночные данные и определения инструментов.

 Коннектор MoexFixFastSpot: обзор кода в OsEngine – архитектура и модули

Разбор FAST-сообщений

Для разбора FAST-сообщений использована библиотека OpenFAST.net, а точнее ее порт на C#, так как оригинальная библиотека написана на Java.

В документации описано аж два формата данных, передаваемых от FAST-серверов Мосбиржи. И это разные форматы для UDP и TCP.

 Коннектор MoexFixFastSpot: обзор кода в OsEngine – архитектура и модули

В данных, передаваемых по UDP первые 4 байта соответствуют значению поля MsgSeqNum (номер сообщения) и за счет специфики UDP мы всегда читаем сообщение целиком. В декодер OpenFAST мы передаем прочитанные байты, начиная с 4го. На выходе получаем декодированное FIX-сообщение.

 Коннектор MoexFixFastSpot: обзор кода в OsEngine – архитектура и модули

Пример чтения сообщения, поступившего по одному из UDP сокетов.

Виды потоков данных

Данные по UDP идут в двух основных формах. Рассмотрим на примере данных о сделках (тики, трейды).

  1. В потоках обновлений идут данные в реальном времени. Это данные вида «Сбербанк продажа объем такой-то по цене такой-то + время + еще множество данных».
  2. В потоках восстановления идут, так называемые, снэпшоты данных – это просто по кругу идут блоки данных, содержащие все обновления по всем инструментам с начала торгового дня до текущего момента. Например, это может быть «Сбербанк и дальше перечисление массива сделок, которые состоялись сегодня».

Поэтому при подключении коннектор первым делом собирает данные из снэпшотов (что сегодня уже успело произойти к настоящему моменту), а потом применяет к этим снэпшотам обновления.

Таким образом, можно работать, когда получили всю информацию о том, что уже произошло и начали получать обновления в реальном времени о том, что происходит именно сейчас.

Восстановление пропущенных данных

Если в номерах сообщений обнаруживается пробел, то пропущенные сообщения необходимо восстанавливать. В документации описано два способа:

  • Восстановление из снэпшотов.
  • Восстановление по TCP.

У первого способа, из снэпшотов, есть существенный недостаток – снэпшоты транслируются по всем инструментам и время ожидания формирования снэпшота данных, содержащего пропущенные сообщения, может быть весьма значительным.

Второй способ, восстановление по TCP, позволяет подключиться к специальному серверу восстановления и запросить пропущенные данные.

 Коннектор MoexFixFastSpot: обзор кода в OsEngine – архитектура и модули

Специфика там такая, что мы сообщения серверу отправляем в FIX-формате, а он нам отвечает в FAST-формате. Причем формат сообщений тут отличается от тех, что приходят по UDP. В первых 4 байтах тут содержится длина очередного FAST-сообщения. Зная эту длину, следует читать из сокета именно такое количество байт и только после этого приступать к декодированию и разбору FAST-сообщения.

Информация о бумагах

Информация о торгуемых инструментах передается в цикле безо всяких запросов, то есть мы не можем управлять началом передачи и должны просто слушать поток, пока не получим всю информацию. И даже на тестовом сервере прослушивание полного цикла информации занимало 11 минут. В связи с этим, при первом запуске коннектор дожидается получения всей этой информации и сохраняет ее в базу данных на диске (LiteDB). При повторном запуске информация из кэша (БД) моментально загружается, и нет необходимости ждать ее получения.

Параллельная обработка

Потоки данных по UDP идут по дублированным каналам. То есть, например, есть два потока «обновления по сделкам А» и «обновления по сделкам B», и сделано это для минимизации потерь данных (то есть, если вдруг потеряли пакет с номером Х в потоке А, то скорее всего пакет с номером X придет в потоке B). Поэтому данные из обоих таких потоков читаются, и контролируется порядок номеров сообщений. Таким образом мы избегаем дублей данных и можем обнаруживать пропуски в случаях, когда какой-то пакет потерялся в обоих потоках.

 Коннектор MoexFixFastSpot: обзор кода в OsEngine – архитектура и модули

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

Многопоточная архитектура

Коннектор создает множество дополнительных потоков:

  • Поток контроля соединения с серверами – контроль времени поступления последних данных для FAST и отправка Test Request/ Heartbeat для FIX-серверов;
  • Потоки чтения данных ордеров (Orders Incremental A+B, Orders Snapshots A+B);
  • По аналогии – чтение данных сделок;
  • Поток чтения данных доступных инструментов;
  • Отдельные потоки разбора очередей сообщений с данными по ордерам и сделкам. Тут происходит контроль пропусков и восстановление данных при необходимости;
  • Два потока для MFIX Trade, MFIX Trade Capture – управление и контроль ордеров;
  • Поток восстановления данных через TCP Historical Replay сервер.

 Коннектор MoexFixFastSpot: обзор кода в OsEngine – архитектура и модули

Реализованные команды

В коннекторе реализованы все доступные в FIX-интерфейсе виды сообщений (команд).

 

В том числе Order Cancel Replace Request, более известный как Move. Если не знаете, то при помощи этой команды можно быстро отменить уже существующий ордер и создать новый взамен с другими параметрами цены и объема. Биржа создает новый ордер, отменяет старый, но в OsEngine это происходит как изменение цены и/или объема существующего ордера, отсюда и Move (от англ. «перемещение»).

 Коннектор MoexFixFastSpot: обзор кода в OsEngine – архитектура и модули

Что не реализовано, и ограничения коннектора.

К сожалению, Мосбиржа исключила из FIX-интерфейса команду для запроса состояния ордера Order Status Request.

Коннектор MoexFixFastSpot: обзор кода в OsEngine – архитектура и модули

В документации оно просто зачеркнуто, поэтому у коннектора нет возможности запросить список активных ордеров в случае потери соединения. Они эту проблему решили добавлением функциональности Cancel On Disconnect, то есть все активные ордера будут сняты биржей при обрыве связи.

Нет возможности получить информацию о портфеле. Через FIX или FAST подключения информации о вашем торговом счете просто нет. Поэтому за состоянием счета участника торгов придется смотреть либо через ЛК/терминал брокера, либо через другой коннектор OsEngine или терминал Мосбиржи.

 

Реализованы только основные режимы торгов фондовой секции:

 Коннектор MoexFixFastSpot: обзор кода в OsEngine – архитектура и модули

При необходимости, конечно, все легко расширить до поддержки всех остальных доступных режимов. Такое решение было принято, так как OsEngine не поддерживает выбор режима торгов, а на Мосбирже пара данных «символ инструмента – режим торгов» является отдельным инструментом. То есть SBER@TQBR и SBER@SMAL – это разные инструменты.

 Коннектор MoexFixFastSpot: обзор кода в OsEngine – архитектура и модули

Кто не знал, у того же Сбера список режимов торгов не уместился на экране (https://www.moex.com/ru/issue.aspx?board=TQBR&code=SBER).

Заключение

Коннектор MoexFixFastSpot в OsEngine реализует весь основной функционал торгов через прямой доступ к рынку Московской Биржи на фондовой секции.

Это подтверждено его сертификацией от специалистов Мосбиржи.
Коннектор MoexFixFastSpot: обзор кода в OsEngine – архитектура и модули
Реализация надежна и неоптимальна, что предполагает возможность последующих улучшений.

При желании может быть легко расширен и для поддержки специальных режимов торгов или использования дополнительных параметров.

Спасибо за внимание и удачных алгоритмов!

Коннектор MoexFixFastSpot: обзор кода в OsEngine – архитектура и модули

OsEngine: https://github.com/AlexWan/OsEngine
Поддержка OsEngine: https://t.me/osengine_official_support

Регистрируйся в АЛОР и получай бонусы: https://www.alorbroker.ru/open
Сайт АЛОР БРОКЕР: https://www.alorbroker.ru
Раздел «Для клиентов»: https://www.alorbroker.ru/openinfo/for-clients
Программа лояльности от АЛОР БРОКЕР и OsEngine: https://smart-lab.ru/company/os_engine/blog/972745.php

 Коннектор MoexFixFastSpot: обзор кода в OsEngine – архитектура и модули

0 Комментариев

Активные форумы
Что сейчас обсуждают

Старый дизайн
Старый
дизайн