957 lines
29 KiB
Markdown
957 lines
29 KiB
Markdown
# Build 060.9 — WebSocket Trade Transport Model
|
||
|
||
**Engineering Migration Report**
|
||
|
||
---
|
||
|
||
# Контроль документа
|
||
|
||
| Свойство | Значение |
|
||
|----------|----------|
|
||
| Build | 060.9 |
|
||
| Название | WebSocket Trade Transport Model |
|
||
| Статус | Completed |
|
||
| Проект | Dzentra |
|
||
| Подсистема | Market Data Acquisition |
|
||
| Компонент | Trades Feed |
|
||
| Версия | 1.0 |
|
||
|
||
---
|
||
|
||
# Цель Build
|
||
|
||
После завершения Build 060.8 система получила источник получения сырых REST-документов Trade (`DzengiTradesDocumentSource`).
|
||
|
||
Следующим этапом развития является построение полного конвейера обработки сделок, поступающих по WebSocket.
|
||
|
||
Build 060.9 открывает вторую ветку реализации Trades Feed и вводит транспортную модель, описывающую одно WebSocket-событие биржи.
|
||
|
||
Данный Build ограничивается исключительно транспортным уровнем (Transport Layer) и не затрагивает Parser, Schema Validation, Value Validation, Mapper, Adapter, Routing и Runtime.
|
||
|
||
---
|
||
|
||
# Предпосылки
|
||
|
||
К моменту начала Build архитектура Dzentra уже содержала транспортные модели для остальных типов рыночных данных.
|
||
|
||
## REST Trades
|
||
|
||
```text
|
||
REST Document
|
||
│
|
||
▼
|
||
DzengiRestAggTrade
|
||
│
|
||
▼
|
||
Trade
|
||
```
|
||
|
||
## WebSocket Quote
|
||
|
||
```text
|
||
WebSocket Quote Document
|
||
│
|
||
▼
|
||
DzengiWebSocketQuoteResponse
|
||
│
|
||
▼
|
||
Quote
|
||
```
|
||
|
||
## WebSocket OHLC
|
||
|
||
```text
|
||
WebSocket OHLC Document
|
||
│
|
||
▼
|
||
DzengiWebSocketOhlcEvent
|
||
│
|
||
▼
|
||
Candle
|
||
```
|
||
|
||
Для WebSocket Trade аналогичная транспортная модель отсутствовала.
|
||
|
||
В результате архитектура обработки сделок оставалась неполной и асимметричной относительно остальных типов рыночных данных.
|
||
|
||
---
|
||
|
||
# Архитектурное основание
|
||
|
||
Build 060.9 не проектирует транспортный контракт самостоятельно.
|
||
|
||
В качестве первичного источника использованы результаты инженерного исследования, выполненного в рамках Build 057.
|
||
|
||
Во время исследования были изучены:
|
||
|
||
- REST `aggTrades`;
|
||
- WebSocket `trades.subscribe`;
|
||
- реальные Production-сообщения;
|
||
- соответствие REST и WebSocket контрактов.
|
||
|
||
Исследование подтвердило фактический формат события:
|
||
|
||
```json
|
||
{
|
||
"status": "OK",
|
||
"destination": "internal.trade",
|
||
"payload": {
|
||
"buyer": false,
|
||
"id": 2134846831,
|
||
"orderId": "00a02503-0079-54c4-0000-000081e62b58",
|
||
"price": 64555.55,
|
||
"size": 0.002,
|
||
"symbol": "BTC/USD_LEVERAGE",
|
||
"ts": 1784218012030
|
||
}
|
||
}
|
||
```
|
||
|
||
Именно этот контракт принят за основу реализации Build 060.9.
|
||
|
||
---
|
||
|
||
# Результаты архитектурного аудита
|
||
|
||
Перед началом реализации был выполнен аудит существующего адаптера Dzengi.
|
||
|
||
Подтверждено наличие транспортных моделей:
|
||
|
||
- `DzengiRestAggTrade`;
|
||
- `DzengiWebSocketQuoteResponse`;
|
||
- `DzengiWebSocketOhlcEvent`.
|
||
|
||
Также подтверждено существование полной иерархии ошибок обработки Trade:
|
||
|
||
- `TradeTransportError`;
|
||
- `TradeSchemaError`;
|
||
- `TradeParseError`;
|
||
- `TradeValueError`;
|
||
- `TradeMappingError`.
|
||
|
||
Одновременно подтверждено отсутствие следующих компонентов WebSocket Trade Pipeline:
|
||
|
||
- Transport Model;
|
||
- Schema Validation;
|
||
- Parser;
|
||
- Value Validation;
|
||
- Mapper;
|
||
- Adapter.
|
||
|
||
Таким образом Build 060.9 полностью соответствует утверждённой дорожной карте серии 060 и закрывает первый этап WebSocket-ветки обработки сделок.
|
||
|
||
---
|
||
|
||
# Архитектурное решение
|
||
|
||
В транспортный слой адаптера введена новая модель
|
||
|
||
```text
|
||
DzengiWebSocketTradeEvent
|
||
```
|
||
|
||
Она представляет собой типизированное описание одного события
|
||
|
||
```text
|
||
destination = internal.trade
|
||
```
|
||
|
||
и относится исключительно к транспортному уровню адаптера.
|
||
|
||
Модель не является:
|
||
|
||
- внутренней моделью Dzentra;
|
||
- бизнес-сущностью;
|
||
- канонической моделью `Trade`.
|
||
|
||
Её единственная ответственность — хранение уже разобранных транспортных данных WebSocket-сообщения.
|
||
|
||
---
|
||
|
||
# Реализованная транспортная модель
|
||
|
||
В файл
|
||
|
||
```text
|
||
src/market_data/acquisition/adapters/dzengi/models.py
|
||
```
|
||
|
||
добавлена новая транспортная модель:
|
||
|
||
```python
|
||
@dataclass(frozen=True, slots=True)
|
||
class DzengiWebSocketTradeEvent:
|
||
trade_id: int
|
||
price: DzengiRawNumeric
|
||
size: DzengiRawNumeric
|
||
timestamp: int
|
||
symbol: str
|
||
buyer: bool
|
||
order_id: str
|
||
```
|
||
|
||
Модель размещена рядом с существующими транспортными моделями адаптера.
|
||
|
||
Итоговая последовательность моделей выглядит следующим образом:
|
||
|
||
```text
|
||
DzengiRestAggTrade
|
||
DzengiWebSocketTradeEvent
|
||
DzengiWebSocketOhlcEvent
|
||
```
|
||
|
||
Такое расположение сохраняет логическую группировку транспортных сущностей по типам рыночных данных.
|
||
|
||
---
|
||
|
||
# Почему используется dataclass
|
||
|
||
`DzengiWebSocketTradeEvent` представляет собой неизменяемый контейнер транспортных данных.
|
||
|
||
Модель:
|
||
|
||
- не содержит бизнес-логики;
|
||
- не выполняет преобразование типов;
|
||
- не выполняет структурную проверку;
|
||
- не выполняет Value Validation;
|
||
- не выполняет Mapping;
|
||
- не взаимодействует с сетью;
|
||
- не содержит изменяемого состояния.
|
||
|
||
Поэтому используется конструкция
|
||
|
||
```python
|
||
@dataclass(frozen=True, slots=True)
|
||
```
|
||
|
||
что полностью соответствует архитектурному стилю остальных транспортных моделей проекта.
|
||
|
||
---
|
||
|
||
# Назначение полей
|
||
|
||
В модель включены только поля, подтверждённые реальными Production-сообщениями.
|
||
|
||
| Поле | Назначение |
|
||
|------|------------|
|
||
| `trade_id` | идентификатор сделки |
|
||
| `price` | цена сделки |
|
||
| `size` | объём сделки |
|
||
| `timestamp` | время исполнения |
|
||
| `symbol` | торговый инструмент |
|
||
| `buyer` | сторона инициатора |
|
||
| `order_id` | идентификатор ордера |
|
||
|
||
Каждое поле соответствует данным, полученным в ходе исследования Build 057.
|
||
|
||
---
|
||
|
||
# Нормализация имён полей
|
||
|
||
Во входящем WebSocket JSON используются ключи
|
||
|
||
```text
|
||
id
|
||
ts
|
||
orderId
|
||
```
|
||
|
||
Во внутренней транспортной модели используются нормализованные имена
|
||
|
||
```text
|
||
trade_id
|
||
timestamp
|
||
order_id
|
||
```
|
||
|
||
Подобная нормализация уже используется в остальных транспортных моделях Dzentra и обеспечивает единый стиль внутренних контрактов.
|
||
|
||
Преобразование JSON-ключей выполняется Parser.
|
||
|
||
Транспортная модель не зависит от формата сериализации входящего сообщения.
|
||
|
||
---
|
||
|
||
# Использование DzengiRawNumeric
|
||
|
||
Поля
|
||
|
||
```python
|
||
price
|
||
size
|
||
```
|
||
|
||
имеют тип
|
||
|
||
```python
|
||
DzengiRawNumeric
|
||
```
|
||
|
||
Такое решение уже применяется в REST Trade и других транспортных моделях адаптера.
|
||
|
||
Использование `DzengiRawNumeric` означает, что транспортная модель сохраняет числовые значения в исходном виде без выполнения каких-либо преобразований.
|
||
|
||
Ответственность за интерпретацию числовых значений относится к последующим этапам конвейера.
|
||
|
||
Это позволяет полностью разделить:
|
||
|
||
- транспортное представление данных;
|
||
- их синтаксическую корректность;
|
||
- семантическую валидацию;
|
||
- преобразование в каноническую модель.
|
||
|
||
# Неизменяемость модели
|
||
|
||
Параметр
|
||
|
||
```python
|
||
frozen=True
|
||
```
|
||
|
||
гарантирует, что после создания экземпляра его поля не могут быть изменены.
|
||
|
||
Это важно для транспортного слоя, поскольку модель представляет собой результат разбора одного входящего сообщения и после создания должна оставаться неизменной.
|
||
|
||
После формирования экземпляр проходит через последующие этапы конвейера:
|
||
|
||
```text
|
||
Validated WebSocket Document
|
||
│
|
||
▼
|
||
DzengiWebSocketTradeEvent
|
||
│
|
||
▼
|
||
Value Validation
|
||
│
|
||
▼
|
||
Mapper
|
||
│
|
||
▼
|
||
Trade
|
||
```
|
||
|
||
Неизменяемость транспортной модели обеспечивает воспроизводимость обработки сообщения и исключает случайную модификацию данных на последующих этапах.
|
||
|
||
---
|
||
|
||
# Использование slots
|
||
|
||
Параметр
|
||
|
||
```python
|
||
slots=True
|
||
```
|
||
|
||
используется для:
|
||
|
||
- фиксации структуры модели;
|
||
- предотвращения динамического добавления атрибутов;
|
||
- уменьшения накладных расходов на экземпляр;
|
||
- сохранения единого архитектурного стиля транспортных моделей Dzentra.
|
||
|
||
Экземпляр `DzengiWebSocketTradeEvent` не содержит `__dict__`, что дополнительно подтверждает его роль как лёгкого транспортного контейнера.
|
||
|
||
---
|
||
|
||
# Граница ответственности модели
|
||
|
||
`DzengiWebSocketTradeEvent` отвечает исключительно за хранение уже разобранных транспортных данных.
|
||
|
||
В обязанности модели **не входит**:
|
||
|
||
- проверка структуры исходного JSON;
|
||
- проверка значения `status`;
|
||
- проверка `destination`;
|
||
- проверка наличия обязательных полей;
|
||
- проверка корректности цены;
|
||
- проверка корректности объёма;
|
||
- проверка корректности timestamp;
|
||
- определение бизнес-семантики сделки;
|
||
- преобразование в каноническую модель `Trade`.
|
||
|
||
Каждая из перечисленных задач относится к отдельному уровню архитектуры и будет реализована в соответствующих Build.
|
||
|
||
---
|
||
|
||
# Целевой конвейер обработки WebSocket Trade
|
||
|
||
После завершения Builds 060.9–060.14 полный конвейер обработки будет иметь следующий вид:
|
||
|
||
```text
|
||
Raw WebSocket Object
|
||
│
|
||
▼
|
||
WebSocket Trade Schema Validation
|
||
│
|
||
▼
|
||
ValidatedWebSocketTradeDocument
|
||
│
|
||
▼
|
||
WebSocket Trade Parser
|
||
│
|
||
▼
|
||
DzengiWebSocketTradeEvent
|
||
│
|
||
▼
|
||
WebSocket Trade Value Validation
|
||
│
|
||
▼
|
||
WebSocket Trade Mapper
|
||
│
|
||
▼
|
||
Trade
|
||
```
|
||
|
||
Build 060.9 реализует только один компонент этого конвейера:
|
||
|
||
```text
|
||
DzengiWebSocketTradeEvent
|
||
```
|
||
|
||
Все остальные этапы будут реализованы последовательно в следующих Build.
|
||
|
||
---
|
||
|
||
# Соотношение с канонической моделью Trade
|
||
|
||
В Build 060.1 была реализована каноническая модель
|
||
|
||
```text
|
||
Trade
|
||
```
|
||
|
||
Она используется внутренними компонентами Dzentra и полностью независима от способа получения рыночных данных.
|
||
|
||
`DzengiWebSocketTradeEvent` не заменяет `Trade`.
|
||
|
||
Эти модели относятся к различным архитектурным уровням.
|
||
|
||
```text
|
||
DzengiWebSocketTradeEvent
|
||
```
|
||
|
||
— транспортное представление WebSocket-события конкретной биржи.
|
||
|
||
```text
|
||
Trade
|
||
```
|
||
|
||
— единая внутренняя модель сделки, используемая всеми компонентами Dzentra.
|
||
|
||
После реализации Mapper транспортная модель будет преобразовываться в каноническую.
|
||
|
||
---
|
||
|
||
# Соотношение REST и WebSocket транспортных моделей
|
||
|
||
REST и WebSocket описывают одну и ту же биржевую сделку, но используют различные транспортные контракты.
|
||
|
||
REST:
|
||
|
||
```json
|
||
{
|
||
"a": 2134846831,
|
||
"p": "64555.55",
|
||
"q": "0.002",
|
||
"T": 1784218012030,
|
||
"m": true
|
||
}
|
||
```
|
||
|
||
WebSocket:
|
||
|
||
```json
|
||
{
|
||
"id": 2134846831,
|
||
"price": 64555.55,
|
||
"size": 0.002,
|
||
"symbol": "BTC/USD_LEVERAGE",
|
||
"ts": 1784218012030,
|
||
"buyer": false,
|
||
"orderId": "00a02503-0079-54c4-0000-000081e62b58"
|
||
}
|
||
```
|
||
|
||
Несмотря на различие транспортных контрактов, обе модели описывают одну и ту же биржевую сущность и далее преобразуются в единую каноническую модель `Trade`.
|
||
|
||
---
|
||
|
||
# Сопоставление полей REST и WebSocket
|
||
|
||
| Каноническая семантика | REST | WebSocket |
|
||
|------------------------|------|-----------|
|
||
| идентификатор сделки | `a` | `id` |
|
||
| цена | `p` | `price` |
|
||
| объём | `q` | `size` |
|
||
| timestamp | `T` | `ts` |
|
||
| сторона инициатора | `m` | `buyer` |
|
||
| торговый инструмент | отсутствует | `symbol` |
|
||
| идентификатор ордера | отсутствует | `orderId` |
|
||
|
||
Согласно результатам исследования Build 057 выполняется соответствие:
|
||
|
||
```text
|
||
buyer == !m
|
||
```
|
||
|
||
Данная нормализация будет реализована WebSocket Trade Mapper в Build 060.13.
|
||
|
||
---
|
||
|
||
# Обработка транспортной оболочки сообщения
|
||
|
||
Фактическое WebSocket-сообщение имеет следующую структуру:
|
||
|
||
```json
|
||
{
|
||
"status": "OK",
|
||
"destination": "internal.trade",
|
||
"payload": {
|
||
"...": "..."
|
||
}
|
||
}
|
||
```
|
||
|
||
`DzengiWebSocketTradeEvent` представляет исключительно содержимое объекта `payload`.
|
||
|
||
Поля
|
||
|
||
```text
|
||
status
|
||
destination
|
||
```
|
||
|
||
не входят в транспортную модель, поскольку относятся к внешней оболочке WebSocket-документа.
|
||
|
||
Их обработка будет реализована в Build 060.10 — WebSocket Trade Schema Validation.
|
||
|
||
---
|
||
|
||
# Решение по полю clientOrderId
|
||
|
||
Во время исследования было обнаружено, что Swagger содержит дополнительное поле
|
||
|
||
```text
|
||
clientOrderId
|
||
```
|
||
|
||
Однако анализ реальных Production-сообщений подтвердил обязательное наличие только поля
|
||
|
||
```text
|
||
orderId
|
||
```
|
||
|
||
Поэтому `clientOrderId` не включён в обязательный транспортный контракт Build 060.9.
|
||
|
||
Это исключает зависимость Parser от поля, которое отсутствует в фактических сообщениях биржи.
|
||
|
||
При реализации Schema Validation будут использоваться следующие принципы:
|
||
|
||
- обязательными считаются только поля, подтверждённые Production;
|
||
- наличие дополнительных полей не должно приводить к ошибке;
|
||
- неподтверждённые поля не становятся обязательными автоматически.
|
||
|
||
---
|
||
|
||
# Изменённые файлы
|
||
|
||
В рамках Build были изменены только два файла.
|
||
|
||
## Транспортная модель
|
||
|
||
```text
|
||
src/market_data/acquisition/adapters/dzengi/models.py
|
||
```
|
||
|
||
Добавлена новая модель
|
||
|
||
```text
|
||
DzengiWebSocketTradeEvent
|
||
```
|
||
|
||
При этом существующие модели, импорты и поведение файла не изменялись.
|
||
|
||
---
|
||
|
||
## Unit-тесты
|
||
|
||
```text
|
||
tests/unit/market_data/acquisition/adapters/dzengi/test_models.py
|
||
```
|
||
|
||
Добавлены три новых unit-теста транспортной модели.
|
||
|
||
---
|
||
|
||
# Добавленные тесты
|
||
|
||
## Проверка полного транспортного контракта
|
||
|
||
Тест
|
||
|
||
```text
|
||
test_websocket_trade_event_stores_complete_transport_contract
|
||
```
|
||
|
||
проверяет сохранение всех подтверждённых полей транспортной модели.
|
||
|
||
---
|
||
|
||
## Проверка сохранения исходных числовых значений
|
||
|
||
Тест
|
||
|
||
```text
|
||
test_websocket_trade_event_preserves_raw_numeric_values
|
||
```
|
||
|
||
подтверждает, что модель сохраняет цену и объём без преобразования типов.
|
||
|
||
---
|
||
|
||
## Проверка неизменяемости и slots
|
||
|
||
Тест
|
||
|
||
```text
|
||
test_websocket_trade_event_is_immutable_and_uses_slots
|
||
```
|
||
|
||
подтверждает:
|
||
|
||
- отсутствие `__dict__`;
|
||
- невозможность изменения экземпляра после создания.
|
||
|
||
# Результаты тестирования
|
||
|
||
Выполнен целевой запуск unit-тестов транспортных моделей:
|
||
|
||
```bash
|
||
python -m pytest \
|
||
tests/unit/market_data/acquisition/adapters/dzengi/test_models.py \
|
||
-q
|
||
```
|
||
|
||
Результат выполнения:
|
||
|
||
```text
|
||
12 passed in 0.03s
|
||
```
|
||
|
||
До реализации Build 060.9 файл содержал девять тестов.
|
||
|
||
После добавления транспортной модели количество тестов увеличилось:
|
||
|
||
```text
|
||
9 → 12
|
||
```
|
||
|
||
что соответствует трём новым проверкам.
|
||
|
||
---
|
||
|
||
# Регрессионное тестирование
|
||
|
||
После завершения реализации был выполнен полный запуск тестов адаптера Dzengi.
|
||
|
||
```bash
|
||
python -m pytest \
|
||
tests/unit/market_data/acquisition/adapters/dzengi \
|
||
-q
|
||
```
|
||
|
||
Результат:
|
||
|
||
```text
|
||
246 passed in 0.11s
|
||
```
|
||
|
||
До реализации Build 060.9 набор содержал:
|
||
|
||
```text
|
||
243 passed
|
||
```
|
||
|
||
После добавления новой транспортной модели:
|
||
|
||
```text
|
||
246 passed
|
||
```
|
||
|
||
Регрессий не обнаружено.
|
||
|
||
---
|
||
|
||
# Проверка компиляции
|
||
|
||
Выполнена проверка компиляции изменённых файлов:
|
||
|
||
```bash
|
||
python -m compileall \
|
||
src/market_data/acquisition/adapters/dzengi/models.py \
|
||
tests/unit/market_data/acquisition/adapters/dzengi/test_models.py
|
||
```
|
||
|
||
Компиляция завершилась успешно.
|
||
|
||
Синтаксические ошибки отсутствуют.
|
||
|
||
---
|
||
|
||
# Проверка Git diff
|
||
|
||
Финальный анализ изменений подтвердил, что Build затронул только согласованный scope.
|
||
|
||
Добавлены:
|
||
|
||
- одна транспортная модель;
|
||
- три unit-теста.
|
||
|
||
Не изменялись:
|
||
|
||
```text
|
||
src/market_data/acquisition/adapters/dzengi/parser.py
|
||
src/market_data/acquisition/adapters/dzengi/mapper.py
|
||
src/market_data/acquisition/adapters/dzengi/websocket.py
|
||
src/market_data/acquisition/validation/schema.py
|
||
src/market_data/acquisition/validation/values.py
|
||
src/market_data/acquisition/exceptions.py
|
||
src/market_data/acquisition/runtime/
|
||
src/market_data/acquisition/feeds/
|
||
src/market_data/acquisition/handlers/
|
||
```
|
||
|
||
Таким образом Build полностью соответствует принципу локальности изменений.
|
||
|
||
---
|
||
|
||
# Scope Build 060.9
|
||
|
||
В рамках данного Build реализовано только:
|
||
|
||
```text
|
||
WebSocket Trade Transport Model
|
||
```
|
||
|
||
В Build **не входят**:
|
||
|
||
- WebSocket Trade Schema Validation;
|
||
- WebSocket Trade Parser;
|
||
- WebSocket Trade Value Validation;
|
||
- WebSocket Trade Mapper;
|
||
- WebSocket Trade Adapter;
|
||
- Unified WebSocket Routing;
|
||
- Trade Subscription Layer;
|
||
- Trades Feed Core;
|
||
- Runtime Integration.
|
||
|
||
Такое разделение обеспечивает атомарность миграции и позволяет независимо проверять каждый архитектурный уровень.
|
||
|
||
---
|
||
|
||
# Архитектурный результат
|
||
|
||
После завершения Build система содержит транспортные представления обеих форм получения сделок.
|
||
|
||
REST:
|
||
|
||
```text
|
||
REST Trade Document
|
||
│
|
||
▼
|
||
DzengiRestAggTrade
|
||
│
|
||
▼
|
||
Trade
|
||
```
|
||
|
||
WebSocket:
|
||
|
||
```text
|
||
WebSocket Trade Document
|
||
│
|
||
▼
|
||
DzengiWebSocketTradeEvent
|
||
│
|
||
▼
|
||
Trade
|
||
```
|
||
|
||
На текущем этапе WebSocket-ветка содержит только транспортную модель.
|
||
|
||
Остальные уровни конвейера будут добавлены последовательно в следующих Build.
|
||
|
||
---
|
||
|
||
# Состояние WebSocket Trade Pipeline
|
||
|
||
После завершения Build 060.9 архитектура конвейера выглядит следующим образом:
|
||
|
||
```text
|
||
Raw WebSocket Trade Document
|
||
│
|
||
▼
|
||
Schema Validation
|
||
│
|
||
▼
|
||
Parser
|
||
│
|
||
▼
|
||
DzengiWebSocketTradeEvent
|
||
│
|
||
▼
|
||
Value Validation
|
||
│
|
||
▼
|
||
Mapper
|
||
│
|
||
▼
|
||
Trade
|
||
```
|
||
|
||
Статус реализации компонентов:
|
||
|
||
| Компонент | Build | Статус |
|
||
|-----------|-------|--------|
|
||
| Canonical Trade Model | 060.1 | ✔ Completed |
|
||
| WebSocket Trade Transport Model | 060.9 | ✔ Completed |
|
||
| WebSocket Trade Schema Validation | 060.10 | Pending |
|
||
| WebSocket Trade Parser | 060.11 | Pending |
|
||
| WebSocket Trade Value Validation | 060.12 | Pending |
|
||
| WebSocket Trade Mapper | 060.13 | Pending |
|
||
| WebSocket Trade Adapter | 060.14 | Pending |
|
||
| Unified WebSocket Routing | 060.15 | Pending |
|
||
|
||
---
|
||
|
||
# Соблюдение архитектурных принципов
|
||
|
||
В рамках реализации Build сохранены все архитектурные инварианты проекта Dzentra.
|
||
|
||
## Локальность изменений
|
||
|
||
Изменены только транспортная модель и её unit-тесты.
|
||
|
||
---
|
||
|
||
## Отсутствие преждевременной интеграции
|
||
|
||
Новая модель не подключена к Adapter, Runtime и Trades Feed до появления всех промежуточных этапов обработки.
|
||
|
||
---
|
||
|
||
## Разделение транспортной и канонической моделей
|
||
|
||
`DzengiWebSocketTradeEvent` используется только внутри транспортного слоя адаптера.
|
||
|
||
Внутренние компоненты системы продолжают работать исключительно с канонической моделью `Trade`.
|
||
|
||
---
|
||
|
||
## Отсутствие бизнес-логики
|
||
|
||
Транспортная модель не выполняет:
|
||
|
||
- Parsing;
|
||
- Schema Validation;
|
||
- Value Validation;
|
||
- Mapping;
|
||
- Routing;
|
||
- Subscription;
|
||
- Network I/O.
|
||
|
||
Она представляет собой исключительно неизменяемый контейнер транспортных данных.
|
||
|
||
---
|
||
|
||
## Неизменность существующего поведения
|
||
|
||
Рабочая логика обработки Quote, OHLC и REST Trade не изменялась.
|
||
|
||
Build является полностью обратимо-совместимым с существующей архитектурой.
|
||
|
||
---
|
||
|
||
# Критерии завершения Build
|
||
|
||
Build 060.9 считается завершённым, поскольку выполнены все поставленные задачи.
|
||
|
||
- ✔ исследован Production-контракт WebSocket Trade;
|
||
- ✔ использованы результаты Build 057;
|
||
- ✔ реализована транспортная модель `DzengiWebSocketTradeEvent`;
|
||
- ✔ модель содержит все подтверждённые поля события;
|
||
- ✔ цена и объём сохраняются как `DzengiRawNumeric`;
|
||
- ✔ модель является неизменяемой;
|
||
- ✔ используется `slots`;
|
||
- ✔ добавлены три unit-теста;
|
||
- ✔ все целевые тесты успешно проходят;
|
||
- ✔ регрессионное тестирование успешно завершено;
|
||
- ✔ компиляция выполнена без ошибок;
|
||
- ✔ изменения не выходят за пределы согласованного scope.
|
||
|
||
---
|
||
|
||
# Следующий этап
|
||
|
||
Следующим этапом дорожной карты является
|
||
|
||
```text
|
||
Build 060.10 — WebSocket Trade Schema Validation
|
||
```
|
||
|
||
Цель Build:
|
||
|
||
- реализовать структурную проверку WebSocket Trade-документа;
|
||
- проверить транспортную оболочку сообщения;
|
||
- проверить `status`;
|
||
- проверить `destination = internal.trade`;
|
||
- проверить наличие объекта `payload`;
|
||
- проверить наличие обязательных ключей транспортного события;
|
||
- сформировать `ValidatedWebSocketTradeDocument`;
|
||
- использовать `TradeSchemaError` для ошибок структуры.
|
||
|
||
После завершения Build 060.10 конвейер примет следующий вид:
|
||
|
||
```text
|
||
Raw WebSocket Object
|
||
│
|
||
▼
|
||
validate_dzengi_websocket_trade_schema(...)
|
||
│
|
||
▼
|
||
ValidatedWebSocketTradeDocument
|
||
│
|
||
▼
|
||
Build 060.11 — WebSocket Trade Parser
|
||
```
|
||
|
||
Build 060.10 по-прежнему не будет выполнять:
|
||
|
||
- преобразование значений;
|
||
- семантическую валидацию;
|
||
- Mapping в `Trade`;
|
||
- WebSocket Routing;
|
||
- Runtime Integration.
|
||
|
||
---
|
||
|
||
# Итог
|
||
|
||
Build 060.9 завершил формирование транспортного уровня обработки WebSocket Trade, добавив отсутствующую транспортную модель `DzengiWebSocketTradeEvent`.
|
||
|
||
Новая модель представляет собой типизированное описание события
|
||
|
||
```text
|
||
destination = internal.trade
|
||
```
|
||
|
||
и основана на фактическом Production-контракте, подтверждённом в ходе исследования Build 057.
|
||
|
||
Реализация полностью соответствует архитектурным принципам Dzentra:
|
||
|
||
- транспортный слой отделён от канонической модели;
|
||
- Build ограничен согласованным scope;
|
||
- существующее поведение системы не изменено;
|
||
- создан фундамент для последующей реализации WebSocket Trade Schema Validation, Parser, Mapper и полного конвейера Trades Feed.
|
||
|
||
На этом Build 060.9 считается полностью завершённым. |