13 KiB
Build 059.3 — WebSocket OHLC Parser
Проект: Dzentra Подсистема: Market Data Acquisition Этап: 059.3 Статус: Completed
Цель
Добавить parser для структурно проверенного события Dzengi WebSocket OHLC.
Parser должен преобразовывать:
ValidatedWebSocketOhlcDocument
в:
DzengiWebSocketOhlcEvent
При этом parser не должен выполнять:
- предметную проверку значений;
- проверку поддерживаемых интервалов;
- проверку допустимого типа свечи;
- преобразование timestamp в
datetime; - преобразование цен в
Decimal; - проверку OHLC-инвариантов;
- mapping во внутреннюю модель Dzentra.
Причина изменения
После Build 059.2 проект умеет проверять структуру сообщения Dzengi WebSocket:
{
"status": "OK",
"destination": "ohlc.event",
"payload": {
"symbol": "BTC/USD_LEVERAGE",
"interval": "1m",
"type": "classic",
"t": 1784224740000,
"o": 63992.0,
"h": 64032.55,
"l": 63984.0,
"c": 64032.55
}
}
Однако структурно проверенный документ ещё не преобразовывался в transport-модель адаптера Dzengi.
Build 059.3 добавляет отдельный parsing-слой между schema validation и value validation.
Реализованные изменения
Parser
В файл:
src/market_data/acquisition/adapters/dzengi/parser.py
добавлена функция:
parse_dzengi_websocket_ohlc()
Она принимает:
ValidatedWebSocketOhlcDocument
и возвращает:
DzengiWebSocketOhlcEvent
Исключение parser-слоя
В файл:
src/market_data/acquisition/exceptions.py
добавлено исключение:
CandleWebSocketParseError
Оно используется только при невозможности преобразовать структурно проверенный WebSocket OHLC-документ в transport-модель адаптера.
Unit-тесты
Создан файл:
tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_ohlc_parser.py
Он покрывает успешное преобразование и ошибки транспортных типов.
Соответствие полей
Parser выполняет следующее преобразование:
| WebSocket payload | Transport model |
|---|---|
symbol |
symbol |
interval |
interval |
type |
candle_type |
t |
open_time |
o |
open_price |
h |
high_price |
l |
low_price |
c |
close_price |
Parser не переименовывает и не интерпретирует значения предметно. Он только переносит их в явную transport-модель адаптера.
Проверка базовых транспортных типов
Строковые поля
Следующие поля обязаны быть строками:
symbol
interval
type
Если одно из них не является строкой, выбрасывается:
CandleWebSocketParseError
Пример ошибки:
$.payload.symbol должен быть строкой
Timestamp
Поле:
t
должно быть целым числом Python:
int
Не принимаются:
None
bool
float
str
list
bool отклоняется отдельно, несмотря на то что в Python он является подклассом int.
Parser не проверяет, является ли timestamp положительным или реалистичным. Это относится к Value Validation.
Поля OHLC
Поля:
o
h
l
c
могут быть представлены как:
str
int
float
Это соответствует существующему транспортному типу:
DzengiRawNumeric
Такой контракт необходим, поскольку внешнее API может передавать числовые значения как JSON-числа или строки.
Не принимаются:
None
bool
list
dict
object
Сохранение исходных числовых типов
Parser не преобразует цены.
Например, документ:
{
"o": "63992.00",
"h": 64033,
"l": 63984.0,
"c": "64032.55"
}
преобразуется в transport-модель с теми же исходными типами:
open_price = str
high_price = int
low_price = float
close_price = str
Преобразование в Decimal будет выполняться только на mapping-этапе.
Поддержка типов свечей
Parser сохраняет значение поля:
type
в поле transport-модели:
candle_type
Поддерживаются на уровне базового транспортного типа любые строки.
Например:
classic
heikin-ashi
unknown
Parser не определяет допустимость значения.
Проверка, что значение входит в подтверждённый runtime-набор:
classic
heikin-ashi
будет реализована в Build 059.4 — Value Validation.
Отсутствие предметной валидации
Parser намеренно пропускает значения, которые имеют допустимый транспортный тип, но являются предметно некорректными.
Пример:
symbol = ""
interval = "unsupported"
candle_type = "unknown"
open_time = -1
open_price = "NaN"
high_price = -10
low_price = 100
close_price = 0
Такой документ успешно преобразуется в DzengiWebSocketOhlcEvent.
Это ожидаемое поведение.
Следующий слой должен проверить:
- непустой символ;
- допустимый интервал;
- допустимый тип свечи;
- положительный timestamp;
- конечность чисел;
- положительность цен;
- OHLC-инварианты.
Игнорирование metadata envelope
Parser использует только:
document.payload
Поля внешнего envelope:
status
destination
correlation_id
не участвуют в создании DzengiWebSocketOhlcEvent.
Это обеспечивает разделение ответственности:
Schema Validation
↓
проверяет структуру envelope и payload
Parser
↓
преобразует payload в transport-модель
Value Validation
↓
проверяет предметную допустимость значений
Новый конвейер
После Build 059.3 подготовленная часть конвейера выглядит так:
Raw WebSocket message
↓
validate_dzengi_websocket_ohlc_schema()
↓
ValidatedWebSocketOhlcDocument
↓
parse_dzengi_websocket_ohlc()
↓
DzengiWebSocketOhlcEvent
↓
Value Validation
↓
Internal Close Event
↓
REST reconciliation
↓
Canonical Candle
На текущем этапе реализована часть до DzengiWebSocketOhlcEvent включительно.
Unit Tests
Добавлен файл:
tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_ohlc_parser.py
Проверяются следующие сценарии:
- успешное создание transport-модели;
- корректное соответствие всех полей;
- сохранение типа
classic; - сохранение типа
heikin-ashi; - сохранение исходных числовых типов;
- отклонение нестрокового
symbol; - отклонение нестрокового
interval; - отклонение нестрокового
type; - отклонение
Noneв timestamp; - отклонение
boolв timestamp; - отклонение
floatв timestamp; - отклонение строкового timestamp;
- отклонение коллекции вместо timestamp;
- отклонение некорректных типов для
o; - отклонение некорректных типов для
h; - отклонение некорректных типов для
l; - отклонение некорректных типов для
c; - отсутствие предметной валидации;
- игнорирование metadata внешнего envelope.
Всего выполнено:
36 tests
Проверка синтаксиса
Выполнена команда:
python -m compileall \
src/market_data/acquisition/exceptions.py \
src/market_data/acquisition/adapters/dzengi/parser.py \
tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_ohlc_parser.py
Результат:
успешно
Целевые тесты
Выполнена команда:
python -m pytest -q \
tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_ohlc_parser.py
Результат:
36 passed in 0.03s
Регрессия parser-слоя
Выполнена команда:
python -m pytest -q \
tests/unit/market_data/acquisition/adapters/dzengi/test_parser.py \
tests/unit/market_data/acquisition/adapters/dzengi/test_quote_parser.py \
tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_quote_parser.py \
tests/unit/market_data/acquisition/adapters/dzengi/test_candle_parser.py \
tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_ohlc_parser.py
Результат:
80 passed in 0.05s
Проверка форматирования
Выполнена команда:
git diff --check
Ошибок форматирования не обнаружено.
Изменённые файлы
src/market_data/acquisition/adapters/dzengi/parser.py
src/market_data/acquisition/exceptions.py
Создан файл:
tests/unit/market_data/acquisition/adapters/dzengi/test_websocket_ohlc_parser.py
Документация этапа:
docs/migrations/build_059_3.md
Совместимость
Изменение полностью обратно совместимо.
Не изменены:
- REST Candles Feed;
- REST parser свечей;
- Quotes Feed;
- WebSocket Quote parser;
- WebSocket Quote Adapter;
- ExchangeService;
- Market Analysis;
- Trading;
- runtime.
Новый parser пока не подключён к рабочему WebSocket runtime и не влияет на действующий бот.
Ограничения этапа
Build 059.3 не выполняет:
- проверку значения
status; - проверку значения
destination; - проверку допустимых интервалов;
- проверку допустимого типа свечи;
- проверку timestamp;
- проверку конечности OHLC;
- проверку положительности OHLC;
- проверку OHLC-инвариантов;
- преобразование в
Decimal; - преобразование времени в UTC
datetime; - создание внутреннего close event;
- REST reconciliation;
- выпуск канонической
Candle.
Эти обязанности остаются за последующими подпунктами Build 059.
Итог
Build 059.3 завершает parsing-слой Dzengi WebSocket OHLC.
Проект теперь умеет преобразовывать структурно проверенный документ:
ValidatedWebSocketOhlcDocument
в transport-модель:
DzengiWebSocketOhlcEvent
без смешивания parsing, value validation и domain mapping.
Следующий этап:
Build 059.4 — Value Validation