Files
dzentra_bot/docs/migrations/build_059_3.md

13 KiB
Raw Permalink Blame History

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