Files
dzentra_bot/docs/migrations/build_059_7.md

21 KiB
Raw Blame History

Build 059.7 — WebSocket OHLC Adapter

Проект: Dzentra Подсистема: Market Data Acquisition Этап: 059.7 Статус: Completed


Цель

Добавить верхнеуровневый адаптер обработки WebSocket OHLC-событий Dzengi, объединяющий все ранее реализованные стадии обработки в единый конвейер.

Результатом работы адаптера должна стать полностью подготовленная внутренняя модель Dzentra:

CandleCloseEvent

Адаптер становится единственной точкой входа для преобразования WebSocket-сообщения в событие, пригодное для дальнейшей обработки внутри runtime.


Причина изменения

После завершения Build 059.6 система уже содержала полный набор независимых компонентов обработки WebSocket OHLC.

К этому моменту были реализованы:

Schema Validation

Parser

Value Validation

Mapper

Каждый компонент решал строго одну задачу и обладал собственным контрактом ответственности.

Однако использование этих компонентов требовало их последовательного вызова вручную.

Подобный подход приводил к нескольким архитектурным недостаткам:

  • отсутствовала единая точка входа;
  • порядок выполнения этапов мог быть нарушен;
  • различные части системы могли использовать разные последовательности обработки;
  • возрастал риск появления дублирующего кода.

Build 059.7 устраняет эти недостатки.

Теперь вся последовательность обработки инкапсулирована внутри одного адаптера.


Реализовано

Изменён файл:

src/market_data/acquisition/adapters/dzengi/websocket.py

Создан файл:

tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_ohlc_adapter.py

Добавлена документация:

docs/migrations/build_059_7.md

Новый адаптер

Добавлен класс:

DzengiWebSocketOhlcAdapter

Основной публичный метод:

map_message()

Назначение метода:

Raw WebSocket document
        ↓
CandleCloseEvent

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


Конвейер обработки

После завершения Build 059.7 полный pipeline выглядит следующим образом:

Raw WebSocket message
        ↓
Schema Validation
        ↓
ValidatedWebSocketOhlcDocument
        ↓
Parser
        ↓
DzengiWebSocketOhlcEvent
        ↓
Value Validation
        ↓
Mapper
        ↓
CandleCloseEvent

Все стадии выполняются строго последовательно.

Порядок выполнения не может быть изменён вызывающей стороной.


Последовательность обработки

Внутри метода map_message() выполняются следующие действия.

1. Schema Validation

Выполняется проверка структуры входящего сообщения.

Проверяется наличие обязательных полей транспортного контракта Dzengi:

status
destination
payload

После успешной проверки строится модель:

ValidatedWebSocketOhlcDocument

Ошибки данного этапа приводят к возникновению:

CandleWebSocketSchemaError

2. Parser

Проверенный документ передаётся parser.

Parser преобразует транспортную модель в специализированную внутреннюю модель интеграционного слоя:

DzengiWebSocketOhlcEvent

На этом этапе выполняется преобразование структуры сообщения.

Проверка предметной корректности значений не производится.

Ошибки parser приводят к возникновению:

CandleWebSocketParseError

3. Value Validation

Полученная transport-модель проходит предметную проверку.

Контролируются:

  • корректность временной метки;
  • допустимость цен;
  • допустимость типа свечи;
  • непротиворечивость OHLC.

При обнаружении ошибок формируется:

CandleWebSocketValueError

4. Mapper

Последней стадией является mapper.

Он преобразует:

DzengiWebSocketOhlcEvent

в:

CandleCloseEvent

При этом выполняются:

  • преобразование timestamp;
  • преобразование цен в Decimal;
  • установка source;
  • перенос received_at.

После завершения mapper транспортный контракт Dzengi полностью исчезает из дальнейшего pipeline.

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


Обработка received_at

Метод map_message() принимает дополнительный необязательный параметр:

received_at

Тип параметра:

datetime | None

Возможны два режима работы.


received_at передан

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

Никаких дополнительных преобразований времени не выполняется.

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


received_at отсутствует

Если параметр не передан, адаптер автоматически создаёт значение:

datetime.now(timezone.utc)

Таким образом каждое успешно обработанное событие всегда содержит корректное время получения.

Использование UTC обеспечивает единый формат времени независимо от локальной временной зоны системы.


Контракт адаптера

Build 059.7 не вводит новых транспортных моделей.

Адаптер использует исключительно ранее реализованные компоненты.

Контракт адаптера можно представить следующим образом:

Input:

Raw WebSocket document

Output:

CandleCloseEvent

При этом адаптер гарантирует строго фиксированную последовательность выполнения всех промежуточных стадий.


Контракт ошибок

Адаптер намеренно не перехватывает исключения нижележащих компонентов.

Каждая стадия обработки продолжает использовать собственный тип ошибки.

Полный контракт выглядит следующим образом:

Transport
        ↓
CandleTransportError

Schema Validation
        ↓
CandleWebSocketSchemaError

Parser
        ↓
CandleWebSocketParseError

Value Validation
        ↓
CandleWebSocketValueError

Mapper
        ↓
CandleWebSocketMappingError

При возникновении любой ошибки выполнение pipeline немедленно прекращается.

Исключение передаётся вызывающей стороне без изменения типа.

Такой подход сохраняет независимость отдельных слоёв системы и упрощает диагностику ошибок.


Почему адаптер не перехватывает исключения

Может показаться, что адаптер должен преобразовывать все ошибки в единое исключение.

В Build 059.7 это намеренно не реализовано.

Причины следующие.

Во-первых, каждая стадия уже обладает собственным контрактом.

Во-вторых, сохранение исходного типа исключения позволяет точно определить место возникновения ошибки.

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

Поэтому адаптер выступает исключительно координатором последовательного выполнения pipeline.


Ответственность адаптера

После завершения Build 059.7 ответственность адаптера ограничивается следующими задачами.

Он обязан:

  • принять исходное WebSocket-сообщение;
  • выполнить полный pipeline обработки;
  • при необходимости создать received_at;
  • вернуть CandleCloseEvent.

На этом обязанности адаптера заканчиваются.


Что адаптер НЕ делает

Build 059.7 намеренно не расширяет область ответственности адаптера.

Адаптер не выполняет:

  • подключение к WebSocket;
  • получение сообщений из сети;
  • управление соединением;
  • подписку на каналы;
  • публикацию событий в runtime;
  • REST reconciliation;
  • получение объёма свечи;
  • построение канонической модели Candle;
  • повторную синхронизацию истории;
  • обработку разрыва соединения.

Все перечисленные задачи относятся к последующим этапам реализации.


Использование существующих компонентов

Build 059.7 не реализует собственную бизнес-логику обработки свечей.

Вместо этого адаптер объединяет ранее созданные компоненты:

Schema Validator

Parser

Value Validator

Mapper

Таким образом Build 059.7 не дублирует уже реализованную функциональность.

Он только формирует единый программный интерфейс для использования существующего pipeline.


Архитектурное значение

После появления адаптера остальные части системы больше не обязаны знать внутреннее устройство обработки WebSocket OHLC.

Для них существует единственная операция:

Raw WebSocket message
        ↓
CandleCloseEvent

Вся остальная логика полностью скрыта внутри адаптера.

Это соответствует принципу инкапсуляции и уменьшает связанность между подсистемами.


Unit Tests

Создан файл:

tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_ohlc_adapter.py

Проверяются следующие сценарии.


Построение CandleCloseEvent

Проверяется полный pipeline обработки.

Исходное WebSocket-сообщение должно успешно пройти:

Schema Validation
        ↓
Parser
        ↓
Value Validation
        ↓
Mapper
        ↓
CandleCloseEvent

Проверяется корректность всех основных полей:

  • symbol;
  • interval;
  • candle_type;
  • open_price;
  • high_price;
  • low_price;
  • close_price;
  • source;
  • received_at.

Автоматическая установка received_at

Если вызывающая сторона не передала параметр:

received_at

адаптер обязан автоматически установить текущее UTC-время.

Тест подтверждает наличие значения и корректность его типа.


Сохранение ошибок Value Validation

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

Проверяется, что наружу передаётся:

CandleWebSocketValueError

без изменения типа ошибки.


Проверка полного pipeline

Отдельный тест подтверждает, что адаптер действительно выполняет все стадии обработки.

В результате вызывающая сторона получает уже полностью построенный объект:

CandleCloseEvent

без необходимости самостоятельно вызывать parser, validator и mapper.


Всего выполнено:

4 tests

Проверка синтаксиса

Выполнена команда:

python -m compileall \
  src/market_data/acquisition/adapters/dzengi/websocket.py \
  tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_ohlc_adapter.py

Результат:

успешно

Целевые тесты

Выполнена команда:

python -m pytest -q \
  tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_ohlc_adapter.py

Результат:

4 passed

Регрессия адаптеров

Выполнена команда:

python -m pytest -q \
  tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_quote_adapter.py \
  tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_ohlc_adapter.py

Результат:

6 passed

Регрессия полного WebSocket pipeline

Выполнена команда:

python -m pytest -q \
  tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_quote_parser.py \
  tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_quote_mapper.py \
  tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_quote_adapter.py \
  tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_ohlc_parser.py \
  tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_ohlc_mapper.py \
  tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_ohlc_adapter.py

Результат:

65 passed

Проверка форматирования

Выполнена команда:

git diff --check

Ошибок форматирования не обнаружено.


Изменённые файлы

src/market_data/acquisition/adapters/dzengi/websocket.py

Создан файл:

tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_ohlc_adapter.py

Документация:

docs/migrations/build_059_7.md

Совместимость

Build 059.7 полностью обратно совместим.

Не изменены:

  • REST Candles Feed;
  • REST Candle mapper;
  • Quote parser;
  • Quote mapper;
  • WebSocket Quote Adapter;
  • ExchangeService;
  • runtime;
  • Trading;
  • Market Analysis;
  • каноническая модель Candle.

Новый адаптер пока не встроен в существующий runtime и не влияет на работу действующего торгового бота.


Архитектурное значение

Build 059.7 завершает формирование верхнего уровня обработки WebSocket OHLC.

После предыдущих этапов система уже обладала всеми необходимыми компонентами:

Schema Validation
Parser
Value Validation
Mapper

Теперь появился единый компонент, объединяющий их в законченный конвейер.

После Build 059.7 архитектура обработки выглядит следующим образом:

Raw WebSocket Message
        │
        ▼
WebSocket OHLC Adapter
        │
        ▼
Schema Validation
        │
        ▼
Parser
        │
        ▼
Value Validation
        │
        ▼
Mapper
        │
        ▼
CandleCloseEvent

Таким образом внешний код взаимодействует только с адаптером.

Внутренние детали обработки полностью инкапсулированы.

Это уменьшает связанность компонентов и соответствует архитектурным принципам Dzentra.


Ограничения этапа

Build 059.7 намеренно не реализует:

  • подписку на WebSocket;
  • управление соединением;
  • автоматическое получение сообщений;
  • публикацию событий в runtime;
  • REST reconciliation;
  • получение объёма свечи;
  • построение канонической модели Candle;
  • проверку соответствия REST и WebSocket данных;
  • восстановление после разрыва соединения;
  • повторную синхронизацию истории.

Все перечисленные задачи относятся к следующим этапам серии Build 059.


Итог

Build 059.7 добавляет полноценный верхнеуровневый адаптер обработки WebSocket OHLC.

В результате система получила:

  • единую точку входа для обработки WebSocket OHLC;
  • полностью инкапсулированный pipeline обработки;
  • автоматическое создание received_at;
  • единый интерфейс получения CandleCloseEvent;
  • сохранение независимых контрактов ошибок всех стадий обработки;
  • полный набор unit-тестов и успешное прохождение регрессии.

После завершения Build 059.7 конвейер обработки WebSocket OHLC полностью готов к интеграции с механизмом подписки и дальнейшей публикации событий внутри runtime.


Следующий этап

Build 059.8 — Unified Adapter

На этом этапе будет реализован единый адаптер верхнего уровня, способный принимать различные типы сообщений Dzengi WebSocket, определять их тип и направлять в соответствующий специализированный адаптер, формируя унифицированную точку входа для всего WebSocket-потока.