Files
dzentra_bot/docs/migrations/build_059_7.md

768 lines
21 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Build 059.7 — WebSocket OHLC Adapter
**Проект:** Dzentra
**Подсистема:** Market Data Acquisition
**Этап:** 059.7
**Статус:** Completed
---
# Цель
Добавить верхнеуровневый адаптер обработки WebSocket OHLC-событий Dzengi, объединяющий все ранее реализованные стадии обработки в единый конвейер.
Результатом работы адаптера должна стать полностью подготовленная внутренняя модель Dzentra:
```text
CandleCloseEvent
```
Адаптер становится единственной точкой входа для преобразования WebSocket-сообщения в событие, пригодное для дальнейшей обработки внутри runtime.
---
# Причина изменения
После завершения Build 059.6 система уже содержала полный набор независимых компонентов обработки WebSocket OHLC.
К этому моменту были реализованы:
```text
Schema Validation
```
```text
Parser
```
```text
Value Validation
```
```text
Mapper
```
Каждый компонент решал строго одну задачу и обладал собственным контрактом ответственности.
Однако использование этих компонентов требовало их последовательного вызова вручную.
Подобный подход приводил к нескольким архитектурным недостаткам:
- отсутствовала единая точка входа;
- порядок выполнения этапов мог быть нарушен;
- различные части системы могли использовать разные последовательности обработки;
- возрастал риск появления дублирующего кода.
Build 059.7 устраняет эти недостатки.
Теперь вся последовательность обработки инкапсулирована внутри одного адаптера.
---
# Реализовано
Изменён файл:
```text
src/market_data/acquisition/adapters/dzengi/websocket.py
```
Создан файл:
```text
tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_ohlc_adapter.py
```
Добавлена документация:
```text
docs/migrations/build_059_7.md
```
---
# Новый адаптер
Добавлен класс:
```text
DzengiWebSocketOhlcAdapter
```
Основной публичный метод:
```text
map_message()
```
Назначение метода:
```text
Raw WebSocket document
CandleCloseEvent
```
Адаптер объединяет все ранее реализованные стадии обработки и предоставляет единый программный интерфейс для остальных компонентов системы.
---
# Конвейер обработки
После завершения Build 059.7 полный pipeline выглядит следующим образом:
```text
Raw WebSocket message
Schema Validation
ValidatedWebSocketOhlcDocument
Parser
DzengiWebSocketOhlcEvent
Value Validation
Mapper
CandleCloseEvent
```
Все стадии выполняются строго последовательно.
Порядок выполнения не может быть изменён вызывающей стороной.
---
# Последовательность обработки
Внутри метода `map_message()` выполняются следующие действия.
## 1. Schema Validation
Выполняется проверка структуры входящего сообщения.
Проверяется наличие обязательных полей транспортного контракта Dzengi:
```text
status
destination
payload
```
После успешной проверки строится модель:
```text
ValidatedWebSocketOhlcDocument
```
Ошибки данного этапа приводят к возникновению:
```text
CandleWebSocketSchemaError
```
---
## 2. Parser
Проверенный документ передаётся parser.
Parser преобразует транспортную модель в специализированную внутреннюю модель интеграционного слоя:
```text
DzengiWebSocketOhlcEvent
```
На этом этапе выполняется преобразование структуры сообщения.
Проверка предметной корректности значений не производится.
Ошибки parser приводят к возникновению:
```text
CandleWebSocketParseError
```
---
## 3. Value Validation
Полученная transport-модель проходит предметную проверку.
Контролируются:
- корректность временной метки;
- допустимость цен;
- допустимость типа свечи;
- непротиворечивость OHLC.
При обнаружении ошибок формируется:
```text
CandleWebSocketValueError
```
---
## 4. Mapper
Последней стадией является mapper.
Он преобразует:
```text
DzengiWebSocketOhlcEvent
```
в:
```text
CandleCloseEvent
```
При этом выполняются:
- преобразование timestamp;
- преобразование цен в `Decimal`;
- установка `source`;
- перенос `received_at`.
После завершения mapper транспортный контракт Dzengi полностью исчезает из дальнейшего pipeline.
Все последующие компоненты работают исключительно с внутренней моделью Dzentra.
---
# Обработка received_at
Метод `map_message()` принимает дополнительный необязательный параметр:
```text
received_at
```
Тип параметра:
```text
datetime | None
```
Возможны два режима работы.
---
## received_at передан
Если вызывающая сторона уже зафиксировала момент получения сообщения, адаптер использует именно это значение.
Никаких дополнительных преобразований времени не выполняется.
Это позволяет сохранить единый момент получения данных на всём протяжении обработки сообщения.
---
## received_at отсутствует
Если параметр не передан, адаптер автоматически создаёт значение:
```python
datetime.now(timezone.utc)
```
Таким образом каждое успешно обработанное событие всегда содержит корректное время получения.
Использование UTC обеспечивает единый формат времени независимо от локальной временной зоны системы.
---
# Контракт адаптера
Build 059.7 не вводит новых транспортных моделей.
Адаптер использует исключительно ранее реализованные компоненты.
Контракт адаптера можно представить следующим образом:
```text
Input:
Raw WebSocket document
```
```text
Output:
CandleCloseEvent
```
При этом адаптер гарантирует строго фиксированную последовательность выполнения всех промежуточных стадий.
---
# Контракт ошибок
Адаптер намеренно не перехватывает исключения нижележащих компонентов.
Каждая стадия обработки продолжает использовать собственный тип ошибки.
Полный контракт выглядит следующим образом:
```text
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 не реализует собственную бизнес-логику обработки свечей.
Вместо этого адаптер объединяет ранее созданные компоненты:
```text
Schema Validator
```
```text
Parser
```
```text
Value Validator
```
```text
Mapper
```
Таким образом Build 059.7 не дублирует уже реализованную функциональность.
Он только формирует единый программный интерфейс для использования существующего pipeline.
---
# Архитектурное значение
После появления адаптера остальные части системы больше не обязаны знать внутреннее устройство обработки WebSocket OHLC.
Для них существует единственная операция:
```text
Raw WebSocket message
CandleCloseEvent
```
Вся остальная логика полностью скрыта внутри адаптера.
Это соответствует принципу инкапсуляции и уменьшает связанность между подсистемами.
---
# Unit Tests
Создан файл:
```text
tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_ohlc_adapter.py
```
Проверяются следующие сценарии.
---
## Построение CandleCloseEvent
Проверяется полный pipeline обработки.
Исходное WebSocket-сообщение должно успешно пройти:
```text
Schema Validation
Parser
Value Validation
Mapper
CandleCloseEvent
```
Проверяется корректность всех основных полей:
- symbol;
- interval;
- candle_type;
- open_price;
- high_price;
- low_price;
- close_price;
- source;
- received_at.
---
## Автоматическая установка received_at
Если вызывающая сторона не передала параметр:
```text
received_at
```
адаптер обязан автоматически установить текущее UTC-время.
Тест подтверждает наличие значения и корректность его типа.
---
## Сохранение ошибок Value Validation
Если входное сообщение содержит недопустимые значения, адаптер не должен скрывать возникшее исключение.
Проверяется, что наружу передаётся:
```text
CandleWebSocketValueError
```
без изменения типа ошибки.
---
## Проверка полного pipeline
Отдельный тест подтверждает, что адаптер действительно выполняет все стадии обработки.
В результате вызывающая сторона получает уже полностью построенный объект:
```text
CandleCloseEvent
```
без необходимости самостоятельно вызывать parser, validator и mapper.
---
Всего выполнено:
```text
4 tests
```
---
# Проверка синтаксиса
Выполнена команда:
```bash
python -m compileall \
src/market_data/acquisition/adapters/dzengi/websocket.py \
tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_ohlc_adapter.py
```
Результат:
```text
успешно
```
---
# Целевые тесты
Выполнена команда:
```bash
python -m pytest -q \
tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_ohlc_adapter.py
```
Результат:
```text
4 passed
```
---
# Регрессия адаптеров
Выполнена команда:
```bash
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
```
Результат:
```text
6 passed
```
---
# Регрессия полного WebSocket pipeline
Выполнена команда:
```bash
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
```
Результат:
```text
65 passed
```
---
# Проверка форматирования
Выполнена команда:
```bash
git diff --check
```
Ошибок форматирования не обнаружено.
---
# Изменённые файлы
```text
src/market_data/acquisition/adapters/dzengi/websocket.py
```
Создан файл:
```text
tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_ohlc_adapter.py
```
Документация:
```text
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.
После предыдущих этапов система уже обладала всеми необходимыми компонентами:
```text
Schema Validation
Parser
Value Validation
Mapper
```
Теперь появился единый компонент, объединяющий их в законченный конвейер.
После Build 059.7 архитектура обработки выглядит следующим образом:
```text
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.
---
# Следующий этап
```text
Build 059.8 — Unified Adapter
```
На этом этапе будет реализован единый адаптер верхнего уровня, способный принимать различные типы сообщений Dzengi WebSocket, определять их тип и направлять в соответствующий специализированный адаптер, формируя унифицированную точку входа для всего WebSocket-потока.