37 KiB
Build 060.23 — Trade Stream Acquisition Integration
Engineering Migration Report
Контроль документа
| Свойство | Значение |
|---|---|
| Build | 060.23 |
| Название | Trade Stream Acquisition Integration |
| Статус | Completed |
| Проект | Dzentra |
| Подсистема | Market Data Acquisition |
| Компонент | Trade Stream Acquisition Integration Layer |
| Версия | 1.0 |
Связанные документы
- Build 060.23 Architecture — архитектурная спецификация Build.
- Build 060.22 Engineering Migration Report — предыдущий Build.
- Build 060.22 Architecture — спецификация Acquisition Runtime Service.
- Build 060.20.1 Engineering Migration Report — корректирующий Build владения состоянием Trade Stream.
- Build 060.19 Engineering Migration Report — Trade Recovery.
- Build 060.18 Engineering Migration Report — Trade Stream Consistency.
Цель Build
Build 060.22 завершил создание минимального исполняемого сервисного слоя Acquisition Runtime.
После предыдущего этапа в системе уже существовали:
AcquisitionRuntimeServiceProtocol
AcquisitionRuntimeService
AcquisitionRuntimeCommand
AcquisitionRuntimeEvent
Runtime Service уже умел детерминированно исполнять инфраструктурные команды:
ConnectCommand
DisconnectCommand
SubscribeCommand
UnsubscribeCommand
SendTextCommand
SendBinaryCommand
Однако Runtime по-прежнему оставался изолированным от Trade Stream Acquisition Pipeline.
В системе отсутствовал отдельный компонент, который:
- формировал команду подписки Trade Stream;
- передавал её в Acquisition Runtime;
- принимал один входящий WebSocket-документ;
- преобразовывал его через Unified Adapter;
- выделял канонический
Trade; - передавал
Tradeв Consistency Layer; - возвращал согласованный результат
Trade | None.
Главной задачей Build 060.23 стало создание локального интеграционного слоя:
TradeStreamAcquisitionService
и его публичного контракта:
TradeStreamAcquisitionServiceProtocol
После завершения Build система получает:
- единую сервисную точку подписки Trade Stream;
- единый путь обработки входящего Trade-сообщения;
- независимость сервиса от конкретной exchange-specific реализации адаптера;
- интеграцию с
TradeStreamConsistencyProtocol; - отдельное unit-покрытие координатора;
- интеграционные тесты полного локального Dzengi pipeline;
- подтверждённую регрессионную совместимость Runtime, Consistency, Recovery, Feeds и Dzengi Adapters.
При этом Build сознательно не реализует production WebSocket transport, receive-loop, reconnect и Runtime Recovery.
Предпосылки
К началу настоящего Build были доступны следующие подсистемы.
Runtime Layer
AcquisitionRuntimeServiceProtocol
AcquisitionRuntimeService
AcquisitionRuntimeCommandDispatcherProtocol
AcquisitionRuntimeEventPublisherProtocol
Trade Subscription Layer
build_trade_subscribe_command()
WebSocket Adapter Layer
DzengiUnifiedWebSocketAdapter
DzengiWebSocketTradeAdapter
Consistency Layer
TradeStreamConsistencyProtocol
TradeStreamConsistencyController
TradeStreamStateStore
Canonical Model
Trade
Каждый компонент уже был реализован и протестирован отдельно.
Однако их взаимодействие не было оформлено в единый Acquisition Service.
Архитектура до Build выглядела следующим образом:
Subscription Builder
│
▼
SubscribeCommand
│
▼
AcquisitionRuntimeService
и отдельно:
WebSocket Document
│
▼
DzengiUnifiedWebSocketAdapter
│
▼
Trade
и отдельно:
Trade
│
▼
TradeStreamConsistencyController
│
▼
Trade | None
Build 060.23 должен был соединить эти независимые части без изменения их существующего поведения.
Результаты архитектурного аудита
Перед реализацией были проанализированы:
src/market_data/acquisition/protocol.py
src/market_data/acquisition/service.py
src/market_data/acquisition/registry.py
src/market_data/acquisition/feeds/trades_feed.py
src/market_data/acquisition/subscriptions/trades.py
src/market_data/acquisition/adapters/dzengi/websocket.py
src/market_data/acquisition/runtime/acquisition_runtime_service.py
src/market_data/acquisition/runtime/acquisition_runtime_service_protocol.py
src/market_data/acquisition/consistency/trade_stream_protocol.py
src/market_data/acquisition/consistency/trade_stream_consistency_controller.py
src/market_data/acquisition/consistency/trade_stream_state_store.py
Дополнительно были изучены legacy-компоненты:
src/integrations/exchange/market_stream.py
src/integrations/exchange/market_data_runner.py
src/integrations/exchange/ws_client.py
src/integrations/exchange/service.py
и соответствующие unit-тесты.
Аудит подтвердил следующие выводы.
Существующий TradesFeed остаётся синхронным REST Feed
Текущий TradesFeed работает по модели:
TradeDocumentSource
│
▼
TradeDocumentHandler
│
▼
Trade
Он не владеет:
- WebSocket lifecycle;
- Runtime Commands;
- активными подписками;
- receive-loop;
- reconnect;
- Consistency State.
Поэтому внедрение Runtime в существующий TradesFeed было признано нарушением Single Responsibility.
Build 060.23 не изменяет TradesFeed.
Legacy MarketDataRunner не является точкой интеграции
MarketDataRunner уже содержит собственные:
- task lifecycle;
- reconnect-циклы;
- REST fallback;
- quote-specific runtime state;
- журналирование;
- status events.
Подключение нового Trade Stream Acquisition Service внутрь него смешало бы новую Acquisition Architecture с существующим legacy runtime и преждевременно затронуло бы Scope Build 060.24.
Поэтому MarketDataRunner не изменяется.
Legacy market_stream.py не является Composition Root
market_stream.py представляет отдельный quote-specific WebSocket-контур.
Его запуск в main.py не является активной точкой новой Trade Stream Architecture.
Файл не изменяется и не используется как Composition Root Build 060.23.
ExchangeWebSocketClient не реализует новые Runtime Protocol
ExchangeWebSocketClient является специализированным legacy-клиентом для depth stream.
Он:
- самостоятельно открывает соединение;
- самостоятельно отправляет depth request;
- самостоятельно выполняет ping;
- содержит внутренний цикл;
- возвращает raw document;
- жёстко связан со стаканом.
Следовательно он не является реализацией:
WebSocketTransportProtocol
WebSocketSessionProtocol
WebSocketSubscriptionManagerProtocol
и не адаптируется в рамках Build 060.23.
Trade consumer и Trade store отсутствуют
Repository-wide поиск не выявил утверждённых компонентов:
TradeStore
TradeConsumer
publish_trade()
on_trade()
consume_trade()
Поэтому новый сервис не публикует и не сохраняет Trade.
Его результатом остаётся:
Trade | None
trades.unsubscribe не поддерживается биржей
Предыдущий инженерный аудит Dzengi WebSocket API подтвердил отсутствие поддерживаемой операции:
trades.unsubscribe
Поэтому Build 060.23 не создаёт фиктивный exchange-specific unsubscribe builder.
Завершение Trade Stream в будущем должно выполняться через lifecycle соединения либо иной подтверждённый механизм.
Архитектурное решение
По результатам аудита утверждена следующая схема.
symbols
│
▼
TradeStreamAcquisitionService.subscribe()
│
▼
build_trade_subscribe_command()
│
▼
SubscribeCommand
│
▼
AcquisitionRuntimeServiceProtocol.dispatch()
Входящий поток:
raw WebSocket document
│
▼
TradeStreamMessageAdapterProtocol.map_message()
│
▼
Quote | CandleCloseEvent | Trade
│
▼
isinstance(result, Trade)
│
├── нет ──► None
│
▼
TradeStreamConsistencyProtocol.accept()
│
▼
Trade | None
Новый сервис является stateless-координатором.
Он не создаёт транспорт, не запускает фоновые задачи и не хранит состояние Trade Stream.
Правило уникальности имён файлов
Build 060.23 сохраняет обязательное правило проекта Dzentra:
Новые файлы должны иметь уникальные имена в масштабе репозитория независимо от каталога.
Build не создаёт новые общие файлы:
service.py
protocol.py
test_service.py
Вместо них добавлены уникальные имена:
trade_stream_acquisition_protocol.py
trade_stream_acquisition_service.py
trade_stream_message_adapter_protocol.py
test_trade_stream_acquisition_service.py
test_dzengi_trade_stream_acquisition_integration.py
Имена однозначно отражают назначение файлов и не требуют знания родительского каталога.
TradeStreamAcquisitionServiceProtocol
В рамках Build создан новый публичный контракт:
TradeStreamAcquisitionServiceProtocol
Файл:
src/market_data/acquisition/
trade_stream_acquisition_protocol.py
Protocol определяет две операции.
subscribe()
async def subscribe(
symbols: tuple[str, ...],
*,
correlation_id: str | None = None,
) -> None
Метод отвечает только за формирование и передачу команды подписки в Runtime.
handle_message()
def handle_message(
document: object,
) -> Trade | None
Метод отвечает только за обработку одного входящего документа.
Другие публичные операции не вводятся.
В частности отсутствуют:
start()
stop()
run()
receive()
reconnect()
recover()
publish()
TradeStreamMessageAdapterProtocol
Во время реализации было выявлено, что первоначальная зависимость сервиса от конкретного:
DzengiUnifiedWebSocketAdapter
создавала прямую exchange-specific связь внутри координационного слоя.
Для устранения этой связи введён отдельный контракт:
TradeStreamMessageAdapterProtocol
Файл:
src/market_data/acquisition/
trade_stream_message_adapter_protocol.py
Protocol определяет одну операцию:
def map_message(
document: object,
) -> TradeStreamMappedMessage
Тип результата:
TradeStreamMappedMessage
объединяет:
Quote
CandleCloseEvent
Trade
DzengiUnifiedWebSocketAdapter структурно удовлетворяет этому Protocol и не требует изменения.
Благодаря этому TradeStreamAcquisitionService зависит от абстракции, а конкретный Dzengi Adapter подключается только при композиции и в интеграционных тестах.
TradeStreamAcquisitionService
Главным production-компонентом Build является:
TradeStreamAcquisitionService
Файл:
src/market_data/acquisition/
trade_stream_acquisition_service.py
Сервис реализует:
TradeStreamAcquisitionServiceProtocol
и координирует три зависимости:
AcquisitionRuntimeServiceProtocol
TradeStreamMessageAdapterProtocol
TradeStreamConsistencyProtocol
Сервис не создаёт зависимости самостоятельно.
Зависимости сервиса
Конструктор принимает:
runtime_service
adapter
consistency_controller
Полная схема:
TradeStreamAcquisitionService
│
├── AcquisitionRuntimeServiceProtocol
├── TradeStreamMessageAdapterProtocol
└── TradeStreamConsistencyProtocol
Это обеспечивает:
- независимость от конкретного Runtime implementation;
- независимость от конкретной биржи;
- независимость от конкретной Consistency implementation;
- возможность изолированного unit-тестирования.
subscribe()
Метод subscribe() использует существующий builder:
build_trade_subscribe_command()
Последовательность:
symbols
│
▼
build_trade_subscribe_command(
symbols,
correlation_id=...
)
│
▼
SubscribeCommand
│
▼
runtime_service.dispatch(command)
Сервис не:
- сериализует JSON;
- создаёт TransportTextMessage вручную;
- строит subscription key самостоятельно;
- нормализует символы;
- хранит активные подписки;
- выполняет connect;
- выполняет retry.
correlation_id
Параметр:
correlation_id
передаётся без изменения существующему Subscription Builder.
Если он не задан, его создание остаётся ответственностью builder.
Сервис не генерирует correlation id самостоятельно.
handle_message()
Метод handle_message() обрабатывает один входящий документ.
Последовательность:
document
│
▼
adapter.map_message(document)
│
▼
mapped result
│
▼
isinstance(mapped result, Trade)
Если результат не является Trade, сервис возвращает:
None
Если результат является Trade, сервис вызывает:
consistency_controller.accept(trade)
и возвращает результат без изменения.
Поведение для Quote
Если Adapter возвращает:
Quote
сервис:
- не вызывает Consistency;
- не преобразует Quote;
- не публикует Quote;
- возвращает
None.
Поведение для CandleCloseEvent
Если Adapter возвращает:
CandleCloseEvent
сервис:
- не вызывает Consistency;
- не преобразует CandleCloseEvent;
- не публикует событие;
- возвращает
None.
Поведение для Trade
Если Adapter возвращает:
Trade
сервис передаёт тот же экземпляр в:
TradeStreamConsistencyProtocol.accept()
Сервис не копирует и не изменяет модель.
Поведение для дубликата
Если Consistency Layer возвращает:
None
это означает корректный дубликат.
Сервис сохраняет результат и также возвращает:
None
Дополнительная логика не выполняется.
Сохранение идентичности результата Consistency
Если TradeStreamConsistencyProtocol.accept() возвращает отдельный экземпляр Trade, сервис возвращает именно этот объект.
Сервис не заменяет его исходным результатом Adapter и не создаёт копию.
Данный инвариант подтверждён unit-тестом.
Обработка исключений
Build не вводит отдельную иерархию ошибок Trade Stream Acquisition Service.
Исключения распространяются без обёртки.
Ошибка Subscription Builder
Ошибка формирования SubscribeCommand передаётся вызывающей стороне.
Ошибка Runtime dispatch
Ошибка runtime_service.dispatch() передаётся вызывающей стороне.
Ошибка Adapter
Schema, parser, value validation или mapper error распространяется без изменения.
Ошибка Consistency
TradeConsistencyError, TradeOrderingError и иные исключения Consistency Layer распространяются без изменения.
Сервис не создаёт общий TradeStreamAcquisitionError.
Stateless-архитектура
TradeStreamAcquisitionService не хранит операционное состояние.
В объекте сохраняются только внедрённые зависимости.
Сервис не хранит:
- symbols;
- correlation id;
- active subscriptions;
- last trade;
- duplicate window;
- reconnect attempts;
- recovery state;
- runtime status;
- received documents.
Состояние Consistency принадлежит TradeStreamStateStore.
Состояние Runtime будет принадлежать будущим Session и Subscription Manager.
Изменённые и добавленные файлы
Новый Acquisition Service Protocol
src/market_data/acquisition/
trade_stream_acquisition_protocol.py
Добавлен:
TradeStreamAcquisitionServiceProtocol
Новый Trade Stream Message Adapter Protocol
src/market_data/acquisition/
trade_stream_message_adapter_protocol.py
Добавлены:
TradeStreamMappedMessage
TradeStreamMessageAdapterProtocol
Новый Trade Stream Acquisition Service
src/market_data/acquisition/
trade_stream_acquisition_service.py
Добавлен:
TradeStreamAcquisitionService
Unit-тест Acquisition Service
tests/unit/market_data/acquisition/
test_trade_stream_acquisition_service.py
Добавлены Fake-реализации:
FakeRuntimeService;FakeMessageAdapter;FakeConsistencyController.
Проверены subscribe и handle_message без привязки к Dzengi.
Интеграционный тест Dzengi pipeline
tests/unit/market_data/acquisition/
test_dzengi_trade_stream_acquisition_integration.py
Проверен реальный локальный pipeline:
Dzengi WebSocket document
│
▼
DzengiUnifiedWebSocketAdapter
│
▼
Canonical Trade
│
▼
TradeStreamConsistencyController
│
▼
Trade | None
Архитектурная документация
docs/migrations/
build_060_23_architecture.md
Документ фиксирует:
- границы Build;
- ответственность сервиса;
- dependency direction;
- ADR;
- Definition of Done;
- связь с последующими этапами.
Файлы, которые не изменялись
Build не изменяет:
src/market_data/acquisition/feeds/trades_feed.py
src/market_data/acquisition/subscriptions/trades.py
src/market_data/acquisition/adapters/dzengi/websocket.py
src/market_data/acquisition/runtime/acquisition_runtime_service.py
src/market_data/acquisition/runtime/acquisition_runtime_service_protocol.py
src/market_data/acquisition/consistency/trade_stream_protocol.py
src/market_data/acquisition/consistency/trade_stream_consistency_controller.py
src/market_data/acquisition/consistency/trade_stream_state_store.py
src/market_data/acquisition/recovery/trade_recovery_controller.py
Также не изменяются:
src/integrations/exchange/market_stream.py
src/integrations/exchange/market_data_runner.py
src/integrations/exchange/ws_client.py
src/integrations/exchange/service.py
Build не затрагивает legacy quote runtime.
Unit-тестирование TradeStreamAcquisitionService
Новый сервис покрыт отдельным набором unit-тестов.
Проверены следующие сценарии:
- сервис соответствует
TradeStreamAcquisitionServiceProtocol; subscribe()передаёт одну команду Runtime;- передаётся именно
SubscribeCommand; - symbols сохраняются в сформированной команде;
correlation_idсохраняется в payload;- Adapter вызывается один раз;
- Trade передаётся в Consistency;
- возвращается тот же объект, который вернула Consistency;
Noneдля корректного дубликата сохраняется;- Quote игнорируется;
- CandleCloseEvent игнорируется;
- Consistency не вызывается для не-Trade;
- ошибка Adapter распространяется без изменения;
- ошибка Consistency распространяется без изменения.
Результат совместного локального прогона unit и integration тестов:
14 passed
Интеграционное тестирование Dzengi pipeline
Интеграционный тест использует настоящий:
DzengiUnifiedWebSocketAdapter
и документ реального WebSocket Trade-контракта:
status
destination
payload
Проверяется полный путь:
schema validation
│
▼
parser
│
▼
value validation
│
▼
mapper
│
▼
Trade
│
▼
Consistency
Подтверждены канонические поля:
symbol
trade_id
price
quantity
executed_at
aggressor_side
source
Для WebSocket Trade подтверждён источник:
dzengi_websocket_trade
Также реальный TradeStreamConsistencyController подтвердил, что повторная обработка идентичного Trade возвращает:
None
Расширенное регрессионное тестирование
После завершения реализации выполнен совместный прогон:
Runtime
Consistency
Recovery
Feeds
Dzengi Adapters
Trade Stream Acquisition Unit Tests
Dzengi Trade Stream Acquisition Integration Tests
Охвачены каталоги:
tests/unit/market_data/acquisition/runtime
tests/unit/market_data/acquisition/consistency
tests/unit/market_data/acquisition/recovery
tests/unit/market_data/acquisition/feeds
tests/unit/market_data/acquisition/adapters/dzengi
и новые файлы:
tests/unit/market_data/acquisition/
test_trade_stream_acquisition_service.py
tests/unit/market_data/acquisition/
test_dzengi_trade_stream_acquisition_integration.py
Результат:
496 passed
Тем самым подтверждено:
- Runtime Service не нарушен;
- Runtime Protocol Layer не нарушен;
- Trade Stream Consistency не нарушена;
- TradeStreamStateStore не нарушен;
- Trade Recovery не нарушена;
- существующие Feeds не нарушены;
- REST Trade Adapter не нарушен;
- WebSocket Quote Adapter не нарушен;
- WebSocket OHLC Adapter не нарушен;
- WebSocket Trade Adapter не нарушен;
- Unified WebSocket Adapter не нарушен;
- новый Acquisition Service корректно интегрируется с реальным Dzengi Adapter;
- duplicate filtering работает через реальный Consistency Controller.
Проверка качества Git diff
После реализации выполнены:
git diff --stat
git diff --check
git diff --check не выявил ошибок форматирования в отслеживаемых изменениях.
Новые production и test-файлы на момент проверки оставались untracked, поэтому не отображались в git diff --stat.
Изменение:
.gitignore
не относится к Scope Build 060.23 и не должно включаться в коммит этапа.
Обратная совместимость
Build сохраняет существующее поведение всех ранее реализованных подсистем.
Не изменились:
TradesFeedProtocol;TradesFeed;TradeDocumentSource;TradeDocumentHandler;Trademodel;- Runtime Commands;
- Runtime Events;
- Acquisition Runtime Service;
- Trade Subscription Builder;
- Unified Dzengi Adapter;
- Trade Stream Consistency API;
- Trade Recovery API;
- Feed Registry;
- legacy Exchange Runtime.
Новый сервис добавляется как отдельный слой и не заменяет существующие REST Feed.
Производительность
subscribe()
Метод выполняет:
- один вызов Subscription Builder;
- один асинхронный вызов Runtime dispatch.
Алгоритмическая сложность зависит от существующего builder и количества symbols.
Сервис не создаёт дополнительных копий команд и payload.
handle_message()
Метод выполняет:
- один вызов Adapter;
- одну
isinstance-проверку; - не более одного вызова Consistency.
Координационные накладные расходы постоянны:
O(1)
без учёта внутренней стоимости Adapter и Consistency Layer.
Сервис не вводит:
- очереди;
- блокировки;
- фоновые задачи;
- retries;
- дополнительную сериализацию;
- storage writes.
Подтверждённые архитектурные инварианты
Runtime не знает о Trade
Новые зависимости направлены из Acquisition Service в Runtime Protocol, а не обратно.
TradeStreamAcquisitionService не зависит от Dzengi
Production-сервис зависит от:
TradeStreamMessageAdapterProtocol
а не от конкретного DzengiUnifiedWebSocketAdapter.
Dzengi Adapter проверяется отдельно
Exchange-specific корректность подтверждена интеграционным тестом.
Consistency остаётся единственной точкой проверки последовательности
Сервис не реализует duplicate detection или ordering logic самостоятельно.
TradeStreamStateStore остаётся единственным владельцем Consistency State
Новый сервис не хранит состояния по symbols.
Существующий TradesFeed не изменяется
REST Feed и WebSocket Acquisition Integration остаются отдельными путями.
Сервис не публикует Trade
До появления утверждённого Trade Consumer результат возвращается вызывающей стороне.
Сервис не владеет WebSocket lifecycle
Он не реализует connect, disconnect, receive-loop или reconnect.
trades.unsubscribe не создаётся
Build не вводит неподдерживаемую exchange-команду.
Уникальность новых имён файлов соблюдена
Все новые production и test-файлы имеют уникальные имена.
Что не входит в Scope Build
Build сознательно не реализует:
- production
WebSocketTransportProtocol; - production
WebSocketSessionProtocol; - production
WebSocketSubscriptionManagerProtocol; - Runtime Event Publisher implementation;
- Runtime Supervisor;
- receive-loop;
- reconnect;
- heartbeat;
- scheduler;
- resubscribe orchestration;
- автоматический вызов Trade Recovery;
- восстановление Trade Stream после разрыва;
- Trade Store;
- Trade Consumer;
- публикацию Trade;
- root Composition;
- изменение
MarketDataRunner; - изменение
market_stream.py; - изменение
ExchangeWebSocketClient; - изменение существующего
TradesFeed; - биржевую команду
trades.unsubscribe.
Отсутствие перечисленных компонентов является осознанной границей этапа.
Архитектурное значение Build
Build 060.23 впервые соединяет ранее независимые части Trades Acquisition Architecture:
Subscription Builder
Runtime Service
Unified Adapter
Canonical Trade
Consistency Controller
До Build каждый компонент существовал отдельно.
После завершения Build появляется единая сервисная граница:
TradeStreamAcquisitionService
которая поддерживает оба направления интеграции:
outbound subscription command
и:
inbound Trade message processing
При этом сервис остаётся stateless, exchange-independent и не вмешивается в lifecycle Runtime.
Связь с последующими Build
Ретроспективное уточнение 060.30.5 (2026-08-03).
Названия ниже сохраняют ранний прогноз. Фактически 060.24 завершил внутреннюю Runtime Recovery, 060.25 — Production Runtime Integration, 060.26 — Integration & Regression, 060.27–060.29 — Storage/Checkpoint/Access, а Final Documentation выполняется в 060.30. Актуальная последовательность: Master Roadmap. После 060.30 утверждён только 061.00; номера следующих Feed-веток ещё не назначены.
Build 060.24 — Reconnect & Runtime Recovery
На основе текущего сервиса должны быть построены:
- Runtime reconnect orchestration;
- автоматическое восстановление подписок;
- восстановление Trade Stream continuity;
- координация Consistency и Recovery после разрыва;
- lifecycle соединения.
Build 060.25 — Integration & Regression
Будет выполнена полная проверка production graph:
Runtime
Trade Stream Acquisition
Consistency
Recovery
Trades Feed
после появления реальных Runtime implementations.
Build 060.26 — Final Documentation
Будет подготовлена итоговая документация всей ветки Trades Feed Runtime.
Заключение
Build 060.23 завершает service-level интеграцию Trade Stream с Acquisition Runtime.
В рамках этапа реализованы:
TradeStreamAcquisitionServiceProtocol
TradeStreamMessageAdapterProtocol
TradeStreamAcquisitionService
Новый сервис:
- формирует Trade SubscribeCommand через существующий builder;
- передаёт команду в
AcquisitionRuntimeServiceProtocol; - обрабатывает один WebSocket-документ через Adapter Protocol;
- пропускает только канонический
Trade; - делегирует проверку последовательности Consistency Layer;
- возвращает
Trade | None; - не хранит состояние;
- не содержит exchange-specific логики;
- не реализует reconnect и Recovery.
Unit-тесты подтверждают поведение координатора независимо от биржи.
Интеграционные тесты подтверждают полный локальный Dzengi pipeline и duplicate filtering через реальный Consistency Controller.
Расширенная регрессия завершена результатом:
496 passed
Итог Build
После завершения Build 060.23 система обладает следующими возможностями.
✓ Создан TradeStreamAcquisitionServiceProtocol.
✓ Создан TradeStreamMessageAdapterProtocol.
✓ Реализован TradeStreamAcquisitionService.
✓ Подписка Trade Stream проходит через существующий Subscription Builder.
✓ SubscribeCommand передаётся через AcquisitionRuntimeServiceProtocol.
✓ Входящие сообщения проходят через Adapter Protocol.
✓ DzengiUnifiedWebSocketAdapter структурно совместим с новым Protocol.
✓ Только Trade передаётся в Consistency.
✓ Quote и CandleCloseEvent игнорируются без побочных эффектов.
✓ Дубликат возвращается как None.
✓ Исключения Adapter и Consistency распространяются без изменения.
✓ Проверена идентичность результата Consistency.
✓ Реальный Dzengi WebSocket Trade document проходит полный pipeline.
✓ Реальный Consistency Controller отклоняет идентичный дубликат.
✓ Существующий TradesFeed не изменён.
✓ Legacy Exchange Runtime не изменён.
✓ Все новые файлы имеют уникальные имена.
✓ Локальный функциональный прогон завершён результатом 14 passed.
✓ Расширенный regression завершён результатом 496 passed.
Build 060.23 — Trade Stream Acquisition Integration считается полностью завершённым и готовым к фиксации в Git.