Files
dzentra_bot/docs/migrations/build_059_4.md

704 lines
14 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.4 — WebSocket OHLC Value Validation
**Проект:** Dzentra
**Подсистема:** Market Data Acquisition
**Этап:** 059.4
**Статус:** Completed
---
# Цель
Добавить предметную проверку значений транспортной модели:
```text
DzengiWebSocketOhlcEvent
```
После выполнения Build 059.3 проект умеет преобразовывать структурно проверенный WebSocket-документ в transport-модель адаптера.
Build 059.4 проверяет, что значения этой модели допустимы для дальнейшей обработки.
На данном этапе не выполняются:
- преобразование timestamp в `datetime`;
- преобразование цен в `Decimal` для внутренней модели;
- создание внутреннего события закрытия свечи;
- mapping;
- REST reconciliation;
- создание канонической `Candle`;
- runtime-интеграция.
---
# Причина изменения
Parser проверяет только базовые транспортные типы.
Например, он допускает следующие значения:
```text
symbol = ""
interval = "unsupported"
candle_type = "unknown"
open_time = -1
open_price = "NaN"
high_price = -10
low_price = 100
close_price = 0
```
Они корректны с точки зрения базовых Python-типов, но недопустимы с точки зрения предметного контракта OHLC.
Поэтому необходим отдельный слой Value Validation.
---
# Реализованные изменения
Изменён файл:
```text
src/market_data/acquisition/validation/values.py
```
Добавлена функция:
```text
validate_dzengi_websocket_ohlc_values()
```
Она принимает:
```text
DzengiWebSocketOhlcEvent
```
и проверяет предметную допустимость всех его полей.
---
# Новое исключение
В файл:
```text
src/market_data/acquisition/exceptions.py
```
добавлено специализированное исключение:
```text
CandleWebSocketValueError
```
Оно используется только для ошибок значений WebSocket OHLC-событий.
Ошибки WebSocket OHLC теперь разделены по слоям:
```text
CandleWebSocketSchemaError
CandleWebSocketParseError
CandleWebSocketValueError
```
Это сохраняет явное разделение ответственности:
```text
Schema Validation
проверка структуры JSON
Parser
проверка транспортных типов
Value Validation
проверка предметной допустимости
```
---
# Поддерживаемые интервалы
В Value Validation зафиксирован набор интервалов, который уже поддерживается действующим Candles Feed:
```text
1m
5m
15m
1h
```
Допустимые значения хранятся в immutable-наборе:
```text
_SUPPORTED_WEBSOCKET_OHLC_INTERVALS
```
Значения сравниваются без автоматической нормализации.
Поэтому отклоняются:
```text
""
"1s"
"4h"
"1M"
" 1m "
```
Это преднамеренное поведение.
Parser и validator не должны незаметно исправлять внешний контракт.
---
# Поддерживаемые типы свечей
По результатам runtime-исследования Build 058 подтверждены два допустимых значения:
```text
classic
heikin-ashi
```
Они зафиксированы в immutable-наборе:
```text
_SUPPORTED_WEBSOCKET_OHLC_TYPES
```
Отклоняются:
```text
""
"bid"
"ask"
"Classic"
"unknown"
" classic "
```
REST-параметр:
```text
priceType = bid | ask
```
не является WebSocket-параметром типа свечи.
WebSocket использует:
```text
type = classic | heikin-ashi
```
---
# Проверка символа
Поле:
```text
symbol
```
должно содержать хотя бы один непробельный символ.
Отклоняются:
```text
""
" "
"\t"
"\n"
```
Value Validation не выполняет:
- нормализацию символа;
- проверку существования инструмента;
- преобразование alias;
- обращение к Instrument Registry.
На этом слое проверяется только непустое значение.
---
# Проверка timestamp
Поле:
```text
open_time
```
должно быть больше нуля.
Отклоняются:
```text
0
-1
-1784224740000
```
Проверка базового типа `int` уже была выполнена parser-слоем в Build 059.3.
Value Validation не преобразует timestamp в `datetime`.
---
# Проверка OHLC
Поля:
```text
open_price
high_price
low_price
close_price
```
принимают транспортный тип:
```text
DzengiRawNumeric
```
То есть могут быть представлены как:
```text
str
int
float
```
На этапе Value Validation каждое значение временно преобразуется в `Decimal` только для проверки.
Transport-модель при этом не изменяется.
---
# Проверка корректности числовых значений
Каждое поле OHLC должно быть корректным числом.
Отклоняются:
```text
""
"invalid"
"--1"
```
Для таких значений выбрасывается:
```text
CandleWebSocketValueError
```
с указанием точного JSON-пути.
Пример:
```text
$.payload.o должно быть корректным числом
```
---
# Проверка конечности
Каждая цена должна быть конечным числом.
Отклоняются:
```text
"NaN"
"Infinity"
"-Infinity"
float("nan")
float("inf")
float("-inf")
```
Это предотвращает проникновение специальных значений в mapping и downstream-анализ.
---
# Проверка положительности
Все цены OHLC должны быть строго больше нуля.
Отклоняются:
```text
0
-1
"-0.01"
```
Проверка выполняется отдельно для:
```text
$.payload.o
$.payload.h
$.payload.l
$.payload.c
```
---
# OHLC-инварианты
После преобразования цен во временные `Decimal` проверяются стандартные инварианты свечи.
## High не меньше Low
Должно выполняться:
```text
high >= low
```
Иначе:
```text
$.payload.h не должно быть меньше $.payload.l
```
---
## High не меньше Open
Должно выполняться:
```text
high >= open
```
Иначе:
```text
$.payload.h не должно быть меньше $.payload.o
```
---
## High не меньше Close
Должно выполняться:
```text
high >= close
```
Иначе:
```text
$.payload.h не должно быть меньше $.payload.c
```
---
## Low не выше Open
Должно выполняться:
```text
low <= open
```
Иначе:
```text
$.payload.l не должно превышать $.payload.o
```
---
## Low не выше Close
Должно выполняться:
```text
low <= close
```
Иначе:
```text
$.payload.l не должно превышать $.payload.c
```
---
# Поддержка плоской свечи
Допускается свеча, у которой:
```text
open = high = low = close
```
Например:
```text
64000
64000
64000
64000
```
Такая свеча удовлетворяет всем OHLC-инвариантам и является допустимой.
---
# Отсутствие изменения transport-модели
Value Validation использует `Decimal` только как временный тип проверки.
Исходный объект:
```text
DzengiWebSocketOhlcEvent
```
не изменяется.
Сохраняются исходные значения и их транспортные типы:
```text
str
int
float
```
Постоянное преобразование во внутренние типы будет выполнено позже на mapping-этапе.
---
# Новый конвейер
После Build 059.4 подготовленная часть конвейера выглядит так:
```text
Raw WebSocket message
validate_dzengi_websocket_ohlc_schema()
ValidatedWebSocketOhlcDocument
parse_dzengi_websocket_ohlc()
DzengiWebSocketOhlcEvent
validate_dzengi_websocket_ohlc_values()
проверенная transport-модель
Internal Close Event Model
Mapper
REST reconciliation
Canonical Candle
```
---
# Unit Tests
Создан файл:
```text
tests/unit/market_data/acquisition/validation/test_websocket_ohlc_values.py
```
Проверяются:
- все поддерживаемые интервалы;
- оба поддерживаемых типа свечей;
- строковые, целые и вещественные представления цен;
- пустые символы;
- неподдерживаемые интервалы;
- неподдерживаемые типы свечей;
- неположительный timestamp;
- нулевые цены;
- отрицательные цены;
- `NaN`;
- положительная и отрицательная бесконечность;
- некорректные числовые строки;
- `high < low`;
- `high < open`;
- `high < close`;
- `low > open`;
- `low > close`;
- плоская свеча.
Всего выполнено:
```text
84 tests
```
---
# Проверка синтаксиса
Выполнена команда:
```bash
python -m compileall \
src/market_data/acquisition/exceptions.py \
src/market_data/acquisition/validation/values.py \
tests/unit/market_data/acquisition/validation/test_websocket_ohlc_values.py
```
Результат:
```text
успешно
```
---
# Целевые тесты
Выполнена команда:
```bash
python -m pytest -q \
tests/unit/market_data/acquisition/validation/test_websocket_ohlc_values.py
```
Результат:
```text
84 passed in 0.03s
```
---
# Регрессия value-validation слоя
Выполнена команда:
```bash
python -m pytest -q \
tests/unit/market_data/acquisition/validation/test_values.py \
tests/unit/market_data/acquisition/validation/test_quote_values.py \
tests/unit/market_data/acquisition/validation/test_websocket_quote_values.py \
tests/unit/market_data/acquisition/validation/test_candle_values.py \
tests/unit/market_data/acquisition/validation/test_websocket_ohlc_values.py
```
Результат:
```text
150 passed in 0.05s
```
---
# Проверка форматирования
Выполнена команда:
```bash
git diff --check
```
Ошибок форматирования не обнаружено.
---
# Изменённые файлы
```text
src/market_data/acquisition/exceptions.py
src/market_data/acquisition/validation/values.py
```
Создан файл:
```text
tests/unit/market_data/acquisition/validation/test_websocket_ohlc_values.py
```
Документация этапа:
```text
docs/migrations/build_059_4.md
```
---
# Совместимость
Изменение полностью обратно совместимо.
Не изменены:
- REST Candles Feed;
- REST Candle validation;
- Quote Feed;
- WebSocket Quote validation;
- parser WebSocket OHLC;
- ExchangeService;
- runtime;
- Market Analysis;
- Trading.
Новая функция пока не подключена к рабочему WebSocket Adapter и не влияет на работающий бот.
---
# Ограничения этапа
Build 059.4 не выполняет:
- преобразование timestamp в UTC `datetime`;
- преобразование цен в постоянные `Decimal`;
- создание внутреннего события закрытия свечи;
- добавление `source`;
- mapping;
- WebSocket Adapter;
- WebSocket subscription;
- REST reconciliation;
- проверку совпадения WebSocket и REST OHLC;
- создание канонической `Candle`;
- runtime-интеграцию.
---
# Итог
Build 059.4 завершает слой предметной проверки значений Dzengi WebSocket OHLC.
Проект теперь умеет безопасно проверять:
```text
DzengiWebSocketOhlcEvent
```
на:
- допустимость символа;
- допустимость интервала;
- допустимость типа свечи;
- корректность timestamp;
- корректность чисел;
- конечность цен;
- положительность цен;
- соблюдение OHLC-инвариантов.
Следующий этап:
```text
Build 059.5 — Internal Close Event Model
```