Разработка FIX API-интеграции для торговой платформы должна рассматриваться как дисциплина production-инженерии, а не как задача «подключиться к endpoint». Успешная отправка NewOrderSingle в тестовой среде не доказывает надёжность решения. Платформа должна корректно восстанавливаться после обрыва TCP-соединения, отвечать на запросы resend, не учитывать повторно execution report и объяснять состояние ордера после гонки cancel/replace.
В рамках направления FinTech и trading-системы POLADO проектирует FIX-подключения вместе с OMS-процессами, риск-контролями, аудитом и операционными инструментами. Цель — не просто запустить FIX engine, а получить управляемую, восстанавливаемую и поддерживаемую интеграцию.
Начинайте с контракта FIX, а не с фразы «мы поддерживаем FIX»
Стандарт FIX задаёт общий формат сообщений, но у каждого брокера, venue или liquidity provider есть собственный implementation guide. Для одинакового типа сообщения могут различаться обязательные теги, proprietary fields, правила идентификации инструментов, значения TimeInForce, время сессии и сценарии восстановления. Поэтому указания «FIX 4.4» недостаточно для оценки объёма работ.
До разработки документацию контрагента нужно превратить в версионируемый интерфейсный контракт:
- session и application version, BeginString, CompID, аутентификация и сетевые ограничения;
- входящие и исходящие сообщения: order entry, execution reports, cancel/replace, status и administrative flows;
- обязательные, условные, опциональные и пользовательские теги с типами и правилами валидации;
- mapping инструментов, счетов, сторон, трейдеров и routing-атрибутов;
- heartbeat, торговые часы, policy сброса sequence numbers, resend и recovery ownership;
- тестовый контур, сертификационные сценарии, production cutover и контакты для инцидентов.
Этот контракт определяет и границу адаптера. Например, одна площадка принимает symbol, а другая требует SecurityID и SecurityIDSource. Такие различия должны оставаться в counterparty adapter и контролируемом справочнике инструментов, а не проникать в интерфейс, риск-движок и базовую модель ордера.
FIX-сессия — это не TCP-соединение
На session layer FIX представляет собой двунаправленный упорядоченный поток сообщений с непрерывной серией sequence numbers. Одна сессия может продолжаться через последовательные подключения. Поэтому reconnect сам по себе не означает, что нужно снова начинать с sequence number 1. Именно сохранённое состояние делает messaging восстанавливаемым.
Храните состояние, необходимое для recovery
Для каждой сессии необходимо надёжно сохранять следующий исходящий sequence number, следующий ожидаемый входящий номер, статус logon, политику reset и историю исходящих сообщений, достаточную для ответа на допустимый ResendRequest. Сохраняйте исходное wire-сообщение либо воспроизводимое каноническое представление, timestamps и статус отправки. Если процесс остановился после выделения sequence number, но до подтверждённой записи в сеть, после рестарта система должна детерминированно понимать, что этот номер уже был использован.
В high-availability архитектуре нужен только один активный владелец FIX-сессии. Для active/passive failover требуются durable shared state и механизм лидерства или fencing. Если два узла параллельно отправляют сообщения от одного session identity, возникает race condition по outbound sequence numbers; обычный load balancer эту проблему не решает.
Heartbeat — это операционный контроль
Для heartbeat должны быть согласованы пороги задержки, момент отправки TestRequest, timeout, reconnect backoff и правила alerting. Logon, logout, disconnect, reconnect, sequence mismatch и TestRequest timeout стоит фиксировать как структурированные события. Тогда оператор может отличить удалённый сбой, проблему credentials, внутренний restart engine и настоящий gap на уровне сессии.
Восстановление sequence numbers требует двусторонней политики
Sequence numbers защищают порядок сообщений, но только при сохранении состояния и совместимом поведении обеих сторон. При обнаружении gap контрагент может отправить ResendRequest. Для повторной передачи application message могут понадобиться исходное бизнес-содержание, признаки duplicate и original sending time; для пропуска сообщений, которые не следует повторять, используется корректное gap-fill поведение через SequenceReset. Это необходимо проверять по guide конкретного контрагента, а не принимать поведение FIX engine по умолчанию как достаточное.
Не используйте ResetSeqNumFlag как удобный способ восстановиться после любого reconnect. Reset требует заранее согласованных времени, инициатора, допустимости во время establishment и обработки открытых ордеров или незакрытых gaps. Стандарт session layer FIX отдельно предупреждает, что неподдерживаемый reset может создать операционные риски, включая overfill. В runbook должно быть указано, кто разрешает reset, какие записи проверяются перед ним и что обязаны подтвердить обе стороны после него.
Сделайте обработку входящих бизнес-событий идемпотентной
Проверка sequence numbers обязательна, но не заменяет бизнес-идемпотентность. Execution report может прийти повторно после disconnect, появиться при failover или быть доставлен в дублирующем сценарии контрагента. OMS должна проверять не только ожидаемость transport-сообщения, но и то, было ли уже применено лежащее в его основе бизнес-событие.
Для этого нужен canonical store execution events: контрагент и сессия, ExecID, OrderID, цепочка ClOrdID, тип события, количества, цены, время и ссылка на raw message. Правило уникальности зависит от спецификации: в одном подключении достаточно ExecID, в другом нужен дополнительный scope. Зафиксируйте это правило в mapping specification, примените database constraints, где это возможно, и докажите его replay-тестами.
Преобразуйте FIX-ордера в каноническую модель состояния
Прямое копирование FIX tags в одну таблицу ордеров становится дорогой ошибкой после подключения следующей площадки с другим диалектом. Лучше преобразовывать внешние сообщения во внутренние сущности: order intent, order revision, order state и execution event. Raw-сообщение нужно сохранить для расследования, но внутренние сервисы должны работать со стабильной доменной моделью.
- ClOrdID идентифицирует ваш request и формирует цепочку изменений; для cancel/replace создавайте новое уникальное значение.
- OrigClOrdID связывает cancel или replace с прежним request.
- OrderID — идентификатор ордера у контрагента; при replace он может измениться или сохраниться.
- ExecID — основной кандидат на ключ дедупликации execution events.
- LastQty/LastPx описывают текущее исполнение, а CumQty/LeavesQty — агрегированное состояние ордера.
- ExecType описывает событие, а OrdStatus — текущее состояние; их нельзя сводить к одному упрощённому статусу.
Partial fill, pending cancel, pending replace, replace, cancel reject и unsolicited cancel должны быть отдельными переходами state machine. Это отличается от разработки liquidity bridge, где ключевыми становятся выбор маршрута и failover между поставщиками. Здесь фокус — на достоверной семантике FIX-сессии и ордера; пример более широкого FinTech-контекста можно посмотреть в проекте FT10.
Классифицируйте rejects так, чтобы оператор мог действовать
Session Reject, Business Message Reject, rejected Execution Report и Order Cancel Reject — разные события с разными владельцами и следующими действиями. Некорректный или out-of-sequence message может говорить о дефекте адаптера или сессии. Reject ордера может быть следствием permission, price band, instrument status или risk decision. Cancel reject может означать, что ордер уже исполнен, изменён другим request либо не может быть отменён у данного destination.
В операционном интерфейсе недостаточно статуса «order failed». Нужны raw message, распарсенные теги, внутренний order ID, reason code контрагента, correlation ID, временная линия и подходящее действие из runbook. Это ускоряет разбор инцидента и сохраняет полноценный audit trail.
Чек-лист сертификации и готовности к production
- Утверждены field-level mappings, примеры payload и негативные тесты для каждого сообщения в scope.
- Проверены disconnect/reconnect, gaps в обоих направлениях, resend, duplicate delivery и согласованный reset.
- Partial fills, delayed rejects и гонки cancel/replace воспроизведены в изолированной OMS-среде.
- Определены процедуры восстановления open orders и trades, reconciliation и ручной эскалации.
- Реализованы dashboard сессии, alerts, безопасное хранение raw messages, redaction и audit access.
- Готовы сертификация контрагента, production cutover, rollback, контактная матрица и on-call runbook.
Операционная поддержка начинается после запуска. Отслеживайте задержки heartbeat, частоту reconnect, объём resend, sequence-gap events, распределение reject codes и latency от order до acknowledgement. POLADO может обеспечить этот цикл через техническую поддержку и консалтинг: контролируемые релизы, runbooks для инцидентов и проверяемые post-release процедуры.
Как выбрать партнёра по FIX-интеграции
При выборе FIX protocol integration services спрашивайте не только о способности подключиться к endpoint. Важнее, что произойдёт после restart, как восстанавливается потерянное исходящее сообщение, какой ключ защитит баланс от повторного применения execution и как оператор подтвердит состояние открытого ордера. Сильный партнёр покажет ownership данных, persistence, тестовые сценарии, мониторинг и порядок эскалации, а не только перечень типов FIX-сообщений.
Если вы оцениваете подключение к брокеру, venue или институциональному liquidity provider, свяжитесь с POLADO для технического обзора. Мы можем проверить спецификацию контрагента, session ownership, mapping, recovery plan и модель operational support с учётом вашей OMS, риск-системы и процессов reconciliation.