Разработка order management system для торговой платформы не должна сводиться к API, которое отправляет заявку брокеру или на площадку. Надежная OMS — это authoritative layer жизненного цикла: она в любой момент объясняет, что запросил клиент, что приняла платформа, что было направлено во внешний контур, что исполнилось и почему клиент видит именно такой статус.
Такая система не заменяет pricing engine, liquidity bridge, pre-trade risk или reconciliation. Ценообразование формирует котировки, bridge выбирает маршрут, риск-контроль допускает либо отклоняет инструкцию, reconciliation выявляет расхождения с внешними записями. OMS связывает принятое намерение, ревизии заявки, execution events и клиентское представление lifecycle в одну контролируемую модель.
Начните с канонических идентификаторов и неизменяемого журнала событий
Broker order lifecycle management system нельзя строить только вокруг ID, который вернула площадка. Нужны идентификаторы, не теряющие смысл при повторной отправке запроса, изменении заявки, сбоях интеграции или рестейте со стороны venue:
- InternalOrderId: неизменяемый первичный ключ записи OMS.
- RootOrderId: ключ бизнес-заявки, объединяющий все принятые ревизии в цепочке amend.
- ClientRequestId: ключ идемпотентности для submit, cancel или amend.
- RevisionId: номер каждой принятой версии инструкции.
- VenueOrderId: идентификатор брокера, биржи или liquidity provider.
- ExecutionId: уникальная ссылка на fill, correction или отмену исполнения.
- CorrelationId: технический ключ для трассировки API-вызова, очереди, gateway и действий оператора.
На этой основе ведите append-only event journal: OrderSubmitted, RiskAccepted, RouteRequested, VenueAcknowledged, ExecutionReceived, CancelRequested, ReplaceAccepted, TradeCorrected, RecoveryReconciled. Не переписывайте историю, чтобы запись выглядела проще. Если данные изменены, добавляйте новое событие со ссылкой на предыдущее и с причиной изменения.
У события должны быть собственный ID, ссылки на order и revision, тип, источник, ID исходного сообщения, время получения, source timestamp при наличии, ссылка или hash raw payload и результат обработки. Ручная операция в back office также должна содержать пользователя, роль, reason code, прежнее и новое значение, а при необходимости — approval context. Тогда можно не только расследовать инциденты, но и заново построить read model.
Нужна state machine, а не одна колонка status
Схема NEW → FILLED → CANCELED не выдерживает реального исполнения. Разделите как минимум три понятия: экономическое состояние исполнения, состояние in-flight запросов и итоговый статус, который показывается клиенту.
Практический набор состояний
- Draft, ValidationPending, RiskRejected: намерение клиента и внутренний admission control до внешней маршрутизации.
- PendingNew, Working: ожидается подтверждение venue либо заявка активна.
- PartiallyFilled, Filled: экономические статусы, определяемые cumulative executed quantity.
- PendingCancel, Canceled: запрос отмены принят, но еще не подтвержден, либо отмена уже подтверждена.
- PendingReplace, Replaced: изменение находится в обработке либо новая ревизия уже активна.
- Rejected, Expired, DoneForDay: результаты, при которых обычного дальнейшего исполнения не ожидается.
- SuspendedForRecovery: внутреннее состояние на время проверки внешней истины после сбоя.
Pending cancel не означает canceled, а pending replace не означает, что новая цена или объем уже действует. В руководстве FIX Trading Community по изменениям состояний показано, что pending cancel или pending replace могут сосуществовать с execution state: пока запрос отмены ожидает результата, может прийти fill. Поэтому интерфейс должен честно сообщать «запрошена отмена», не скрывая новое исполнение.
Partial fill, cancel и amend должны быть отдельными фактами
Для каждого исполнения OMS должна обрабатывать и проверять LastQty, LastPx, CumQty, LeavesQty и текущую projection средней цены. Базовые инварианты: cumulative quantity не бывает отрицательным; обычный fill уменьшает доступный остаток; для активной принятой ревизии leaves quantity обычно равен order quantity минус cumulative quantity.
Но correction и trade bust означают, что исполненный объем — не просто счетчик, который всегда растет. Храните каждый fill как отдельный экономический факт с execution ID. Correction или отмена исполнения должны ссылаться на изменяемое исполнение, после чего система строит новую projection. Так OMS может объяснить, почему изменился исторический результат, не уничтожая исходное сообщение.
Не реализуйте cancel/replace удалением старой заявки и молчаливым созданием новой. У одного root order могут быть несколько ревизий и несколько попыток запроса. Каждый amend должен ссылаться на последнюю принятую ревизию; конкурирующие amend-запросы нужно сериализовать в рамках заявки либо обрабатывать по явно заданным правилам последовательности. Если во время pending replace поступил fill, перед маршрутизацией проверьте, что новый запрошенный объем не меньше актуального cumulative quantity. Venue rejection сохраните как отдельное бизнес-событие, а не как безликую ошибку приложения.
Проектируйте на дубликаты, задержки и сообщения не по порядку
Надежная обработка событий исполнения сделок исходит из at-least-once delivery и обеспечивает идемпотентное применение. Consumer должен дедуплицировать событие по источнику, execution ID и типу, атомарно сохранять его в журнале и только затем обновлять projection или уведомлять другие сервисы.
Порядок поступления не является бизнес-истиной. Fill может прийти раньше acknowledgement, cancel reject — после новых fill, а execution correction — уже после терминального состояния заявки для маршрутизации. Сохраняйте source sequence number, если он предоставлен, но не отбрасывайте событие только потому, что оно выглядит запоздавшим. Если нужные order или revision пока неизвестны, направляйте сообщение в durable quarantine либо pending-association queue, создавайте операционный сигнал и закрывайте пробел через snapshot статуса, replay исполнений или запрос на venue.
Восстановление после сбоя: сначала сверка, затем обычный поток
Перезапуск с последней строки в базе данных не является recovery. Контролируемый runbook должен включать:
- Ограничение приема новых заявок или рискованных клиентских действий, пока lifecycle не подтвержден.
- Перестроение projection из durable event journal и проверку consumer offsets или source checkpoints.
- Получение для каждого активного маршрута snapshot открытых заявок, выгрузки исполнений или session recovery из внешнего контура.
- Сравнение внешней истины с локальными событиями и создание явных exception для отсутствующих fill, неизвестных заявок, расхождений quantity и повторных execution.
- Применение подтвержденных recovery adjustments как аудируемых событий, без тихой нормализации расхождений.
- Постепенное открытие трафика только после проверки активных заявок, exposure, risk controls и клиентских projection.
Если клиент видит «working», а заявка уже filled на venue, это не только проблема UX. Такая ошибка может вызвать повторное действие, спор с клиентом и неверное решение по exposure. В timeline клиента должны быть понятные бизнес-события, fill, pending requests, время и ясные статусы, а не поток необработанных протокольных сообщений.
Чек-лист для заказчика OMS
- Разделены ли и трассируются ли identifier-ы order, request, revision, venue order и execution?
- Есть ли у cancel и replace собственный lifecycle вместо прямого изменения строки заявки?
- Покрывают ли автоматические тесты duplicate fill, late acknowledgement, out-of-order event, correction и bust?
- Можно ли полностью восстановить projection заявки из неизменяемых событий?
- Защищены ли back-office override ролями, reason code и immutable audit record?
- Включает ли outage recovery venue snapshots, replay и exception queue?
- Различает ли UI pending request и его окончательный результат?
POLADO проектирует OMS как authoritative lifecycle layer с четкими границами между routing, risk, клиентскими каналами и операционным контуром. В рамках услуги FinTech и trading-системы можно определить модель событий, integration contracts и рабочие процессы до того, как multi-venue архитектуру станет сложно менять. Для безопасных релизов, recovery runbook и поддержки production подключайте техническую поддержку и консалтинг; для плотных order timeline и dealer workflow — UI/UX и продуктовый дизайн. Обратитесь в POLADO за технической консультацией по модели заявок и recovery controls для вашей торговой платформы.