11 KiB
Build 059.5 — Internal Candle Close Event Model
Проект: Dzentra
Подсистема: Market Data Acquisition
Этап: 059.5
Статус: Completed
Цель
Добавить внутреннюю immutable-модель уведомления о закрытии OHLC-свечи.
Модель должна представлять уже проверенное WebSocket-событие внутри Dzentra, но не должна заменять каноническую модель:
Candle
Причина разделения заключается в том, что фактическое событие Dzengi WebSocket:
ohlc.event
содержит:
symbol
interval
type
t
o
h
l
c
но не содержит:
volume
Поэтому WebSocket OHLC-событие не является полноценной OHLCV-свечой.
Причина изменения
После Build 059.4 проект умеет:
- структурно проверять входящее WebSocket-сообщение;
- преобразовывать его в transport-модель;
- проверять предметную допустимость значений.
Подготовленная цепочка выглядит так:
Raw WebSocket message
↓
ValidatedWebSocketOhlcDocument
↓
DzengiWebSocketOhlcEvent
↓
Value Validation
Однако transport-модель:
DzengiWebSocketOhlcEvent
принадлежит адаптеру конкретного внешнего источника Dzengi.
Перед дальнейшим использованием в runtime требуется источник-независимая внутренняя модель Dzentra.
Реализовано
Создан файл:
src/market_data/acquisition/models/candle_close.py
Добавлена модель:
CandleCloseEvent
Структура модели
Модель содержит следующие поля:
symbol
interval
candle_type
open_time
received_at
open_price
high_price
low_price
close_price
source
Полное назначение модели:
внутреннее уведомление Dzentra
о завершении OHLC-свечи,
требующее последующего REST reconciliation
для получения полной OHLCV-свечи
Контракт модели
Модель объявлена как:
frozen=True
slots=True
Это обеспечивает:
- неизменяемость;
- отсутствие динамического
__dict__; - уменьшение вероятности случайного изменения события;
- компактное представление в памяти;
- предсказуемый runtime-контракт.
Отличие от transport-модели
Transport-модель:
DzengiWebSocketOhlcEvent
отражает внешний контракт Dzengi.
Она содержит:
open_time: int
OHLC: str | int | float
Внутренняя модель:
CandleCloseEvent
содержит:
open_time: datetime
received_at: datetime
OHLC: Decimal
source: str
Таким образом transport-особенности внешнего API не распространяются на внутренние слои Dzentra.
Отличие от канонической Candle
Каноническая модель:
Candle
представляет полноценную OHLCV-свечу.
Она содержит:
volume: Decimal
Модель:
CandleCloseEvent
не содержит volume.
Это преднамеренное архитектурное решение.
WebSocket-событие не должно:
- подставлять фиктивный нулевой объём;
- использовать nullable volume;
- притворяться полной OHLCV-свечой;
- наследоваться от
Candle; - передаваться потребителям, ожидающим каноническую свечу.
Полная Candle будет получена только после REST reconciliation.
Поля времени
open_time
Поле:
open_time
представляет время открытия завершённой свечи.
Для минутной свечи это начало минутного интервала, к которому относится событие.
Тип:
datetime
Ожидаемая timezone:
UTC
received_at
Поле:
received_at
представляет момент получения события системой Dzentra.
Оно не равно open_time.
Разделение двух времён необходимо для:
- измерения задержки WebSocket;
- диагностики запоздавших сообщений;
- определения порядка фактической обработки;
- runtime-метрик;
- журналирования;
- анализа качества источника данных.
Поля OHLC
Внутренняя модель использует:
Decimal
для:
open_price
high_price
low_price
close_price
Это исключает дальнейшее распространение внешних типов:
str
int
float
Преобразование transport-значений в Decimal будет реализовано в следующем этапе:
Build 059.6 — Mapper
Поле candle_type
Поле:
candle_type
сохраняет тип серии свечей.
Подтверждённые runtime-значения:
classic
heikin-ashi
Для production-интеграции Candles Feed основной интерес представляет:
classic
Поскольку именно классические свечи будут использоваться для REST reconciliation с каноническими OHLCV-свечами.
heikin-ashi остаётся поддерживаемым внутренним типом события, но не должен автоматически преобразовываться в обычную каноническую Candle.
Поле source
Поле:
source
фиксирует происхождение внутреннего события.
Пример:
dzengi_websocket_ohlc
Это позволит в дальнейшем:
- различать источники;
- поддерживать несколько адаптеров;
- вести диагностику;
- применять источник-зависимую политику reconciliation;
- не встраивать имя Dzengi в общую доменную модель.
Новый внутренний конвейер
После Build 059.5 архитектура выглядит так:
Raw WebSocket message
↓
Schema Validation
↓
ValidatedWebSocketOhlcDocument
↓
Parser
↓
DzengiWebSocketOhlcEvent
↓
Value Validation
↓
Mapper
↓
CandleCloseEvent
↓
REST reconciliation
↓
Canonical Candle
На текущем этапе модель CandleCloseEvent уже существует, но mapper ещё не реализован.
Unit Tests
Создан файл:
tests/unit/market_data/acquisition/models/test_candle_close.py
Проверяются:
- сохранение всех полей;
- неизменяемость модели;
- использование
slots; - отсутствие
__dict__; - отсутствие наследования от
Candle; - отсутствие поля
volume; - поддержка типа
heikin-ashi; - раздельное хранение
open_timeиreceived_at.
Всего выполнено:
7 tests
Проверка синтаксиса
Выполнена команда:
python -m compileall \
src/market_data/acquisition/models/candle_close.py \
tests/unit/market_data/acquisition/models/test_candle_close.py
Результат:
успешно
Целевые тесты
Выполнена команда:
python -m pytest -q \
tests/unit/market_data/acquisition/models/test_candle_close.py
Результат:
7 passed in 0.01s
Регрессия слоя моделей
Выполнена команда:
python -m pytest -q \
tests/unit/market_data/acquisition/models
Результат:
42 passed in 0.02s
Проверка форматирования
Выполнена команда:
git diff --check
Ошибок форматирования не обнаружено.
Созданные файлы
src/market_data/acquisition/models/candle_close.py
tests/unit/market_data/acquisition/models/test_candle_close.py
docs/migrations/build_059_5.md
Совместимость
Изменение полностью обратно совместимо.
Не изменены:
- каноническая модель
Candle; - transport-модель Dzengi;
- REST Candles Feed;
- parser;
- value validation;
- WebSocket Adapter;
- ExchangeService;
- runtime;
- Market Analysis;
- Trading.
Новая модель пока не подключена к runtime и не влияет на работающий бот.
Ограничения этапа
Build 059.5 не выполняет:
- преобразование transport-модели;
- преобразование timestamp;
- преобразование OHLC в
Decimal; - установку реального
received_at; - mapping;
- WebSocket Adapter;
- REST reconciliation;
- проверку соответствия REST и WebSocket OHLC;
- создание канонической
Candle; - публикацию события в runtime.
Итог
Build 059.5 добавляет источник-независимую внутреннюю модель:
CandleCloseEvent
Она представляет подтверждённое уведомление о завершении OHLC-свечи без фиктивного объёма.
Модель создаёт архитектурную границу между:
внешним Dzengi WebSocket контрактом
и:
внутренним runtime Dzentra
Следующий этап:
Build 059.6 — Mapper