29 KiB
Build 044 — Canonical Candles Feed Foundation
Документ миграции
Контроль документа
| Свойство | Значение |
|---|---|
| Документ | Build 044 — Canonical Candles Feed Foundation |
| Тип документа | Migration Build Record |
| Проект | Dzentra |
| Подсистема | Market Data Acquisition |
| Направление | OHLCV Feed / Candles Feed |
| Статус | Complete |
| Язык | Русский |
| Дата | 2026-07-15 |
1. Назначение Build
Build 044 создаёт автономную каноническую основу Candles Feed в утверждённой подсистеме:
src/market_data/acquisition/
Build реализует новую read-only цепочку получения и обработки свечей рядом с действующим legacy-потоком.
Рабочий бот после Build 044 продолжает использовать существующий метод:
ExchangeService.get_klines()
Переключение рабочего runtime на новый Candles Feed в данный Build не входит.
2. Причина выполнения Build
После завершения миграции:
Instrument Reference Data
Quotes Feed
следующим активным legacy-потоком Market Data Acquisition остаётся получение OHLCV-свечей.
До Build 044 рабочая цепочка свечей находилась в legacy exchange layer:
ExchangeService.get_klines()
↓
ExchangeRestClient
↓
GET /api/v1/klines
↓
ExchangeService._extract_klines_items()
↓
ExchangeService._parse_kline_item()
↓
Kline
↓
KlineBatch
↓
trading/market_analysis
В результате:
- endpoint
/api/v1/klinesнаходился вExchangeService; - transport parsing выполнялся в
ExchangeService; - модель
Klineнаходилась вsrc/integrations/exchange/models.py; - Market Analysis зависел от legacy-моделей;
- новая структура
Candles Feedсуществовала только как набор пустых файлов.
Build 044 создаёт новую каноническую цепочку без изменения рабочего legacy-контракта.
3. Границы Build
3.1. В Build входит
Реализована цепочка:
Dzengi REST /api/v1/klines
↓
schema validation
↓
parser
↓
value validation
↓
mapper
↓
Candle
↓
DzengiCandlesDocumentHandler
↓
CandlesFeed
Также добавлены:
- candle-specific исключения;
- transport-модели Dzengi;
- контракты source, handler и feed;
- специализированные unit-тесты;
- архитектурные проверки.
3.2. В Build не входит
Build не изменяет:
src/integrations/exchange/service.py
src/integrations/exchange/models.py
src/trading/market_analysis/
Build не выполняет:
- переключение
ExchangeService.get_klines(); - замену
Kline; - замену
KlineBatch; - миграцию consumers;
- добавление CandleStore;
- добавление candle cache;
- регистрацию Candles Feed в registry;
- публикацию через MarketDataAcquisitionService;
- WebSocket-поток свечей;
- sequence gap detection;
- дедупликацию свечей;
- resampling;
- определение закрытости свечи;
- удаление legacy parsing.
4. Реализованная архитектура
4.1. Каноническая модель
Создана модель:
src/market_data/acquisition/models/candle.py
Контракт:
@dataclass(frozen=True, slots=True)
class Candle:
symbol: str
interval: str
open_time: datetime
open_price: Decimal
high_price: Decimal
low_price: Decimal
close_price: Decimal
volume: Decimal
source: str
Свойства модели:
- immutable;
slots=True;- цены и объём представлены
Decimal; - время открытия представлено timezone-aware UTC
datetime; - модель не зависит от Dzengi;
- модель не зависит от legacy exchange layer.
В модель намеренно не добавлены:
close_time
is_closed
CandleBatch
Эти поля и сущности не требуются текущим подтверждённым контрактом.
4.2. Transport-модели Dzengi
В файл:
src/market_data/acquisition/adapters/dzengi/models.py
добавлены:
DzengiKline
DzengiKlinesResponse
Transport-модель хранит данные после parser, но до канонического mapping.
Допустимые transport numeric-типы:
str | int | float
4.3. REST source
В файл:
src/market_data/acquisition/adapters/dzengi/rest.py
добавлен endpoint:
/api/v1/klines
и источник:
DzengiCandlesDocumentSource
Источник выполняет только transport-вызов и не выполняет:
- schema validation;
- parsing;
- value validation;
- mapping;
- сортировку;
- кэширование;
- нормализацию запроса.
Transport-ошибки преобразуются в:
CandleTransportError
4.4. Schema validation
В файл:
src/market_data/acquisition/validation/schema.py
добавлены:
ValidatedCandlesDocument
validate_candles_schema()
Поддерживаются legacy-compatible envelope-форматы:
root list
root.klines
root.candles
root.data
root.result
root.payload list
root.payload.klines
root.payload.candles
root.payload.data
Поддерживаются два формата одной свечи:
JSON object
JSON array
После schema validation:
dict → MappingProxyType
list → tuple
4.5. Parser
В файл:
src/market_data/acquisition/adapters/dzengi/parser.py
добавлена функция:
parse_candles()
Поддерживаются object-поля:
openTime
open_time
time
timestamp
open
high
low
close
volume
Поддерживается array-формат:
[
open_time,
open,
high,
low,
close,
volume,
...
]
Дополнительные поля массива игнорируются.
Parser:
- проверяет transport-типы;
- не создаёт
Decimal; - не проверяет OHLC-инварианты;
- не создаёт canonical
Candle.
4.6. Value validation
В файл:
src/market_data/acquisition/validation/values.py
добавлена функция:
validate_candles_values()
Проверяются:
open_time > 0
open_price > 0
high_price > 0
low_price > 0
close_price > 0
volume >= 0
Также проверяются:
- конечность числовых значений;
- запрет
bool; - OHLC-инварианты;
high >= low;high >= open;high >= close;low <= open;low <= close.
В Build 044 не выполняются:
- проверка последовательности timestamp;
- проверка gaps;
- проверка соответствия интервалу;
- дедупликация;
- проверка равномерности шага.
4.7. Mapper
В файл:
src/market_data/acquisition/adapters/dzengi/mapper.py
добавлена функция:
map_dzengi_klines_to_candles()
Mapper выполняет:
raw numeric → Decimal
milliseconds timestamp → UTC datetime
DzengiKline → Candle
sorting by open_time
list → tuple
Mapper не выполняет:
- исправление некорректных значений;
- удаление свечей;
- обрезку по
limit; - дедупликацию;
- определение закрытости свечи.
4.8. Handler
Реализован:
src/market_data/acquisition/handlers/candles_handler.py
Основной класс:
DzengiCandlesDocumentHandler
Последовательность обработки:
validate_candles_schema()
↓
parse_candles()
↓
validate_candles_values()
↓
map_dzengi_klines_to_candles()
4.9. Feed
Реализован:
src/market_data/acquisition/feeds/candles_feed.py
Основной класс:
CandlesFeed
Feed координирует:
CandlesDocumentSource
↓
CandlesDocumentHandler
Feed не выполняет:
- transport parsing;
- value validation;
- mapping;
- кэширование;
- повторную обрезку результата по
limit.
4.10. Protocols
В файл:
src/market_data/acquisition/protocol.py
добавлены:
CandlesDocumentSource
CandlesDocumentHandler
CandlesFeedProtocol
Runtime-проверка протоколов выполнена успешно:
candles protocols: OK
4.11. Exceptions
В файл:
src/market_data/acquisition/exceptions.py
добавлены:
CandleTransportError
CandleSchemaError
CandleParseError
CandleValueError
CandleMappingError
Registry-specific исключение не добавлялось, поскольку регистрация Candles Feed не входит в Build 044.
5. Изменённые production-файлы
src/market_data/acquisition/exceptions.py
src/market_data/acquisition/protocol.py
src/market_data/acquisition/models/candle.py
src/market_data/acquisition/adapters/dzengi/models.py
src/market_data/acquisition/adapters/dzengi/rest.py
src/market_data/acquisition/adapters/dzengi/parser.py
src/market_data/acquisition/adapters/dzengi/mapper.py
src/market_data/acquisition/validation/schema.py
src/market_data/acquisition/validation/values.py
src/market_data/acquisition/handlers/candles_handler.py
src/market_data/acquisition/feeds/candles_feed.py
6. Добавленные unit-тесты
tests/unit/market_data/acquisition/models/test_candle.py
tests/unit/market_data/acquisition/adapters/dzengi/test_candle_rest.py
tests/unit/market_data/acquisition/validation/test_candle_schema.py
tests/unit/market_data/acquisition/adapters/dzengi/test_candle_parser.py
tests/unit/market_data/acquisition/validation/test_candle_values.py
tests/unit/market_data/acquisition/adapters/dzengi/test_candle_mapper.py
tests/unit/market_data/acquisition/handlers/test_candles_handler.py
tests/unit/market_data/acquisition/feeds/test_candles_feed.py
Покрыты:
- immutable-модель Candle;
- REST source;
- поддерживаемые envelope-форматы;
- object- и array-parsing;
- aliases времени;
- проверки transport-типов;
- проверки значений;
- OHLC-инварианты;
- Decimal mapping;
- UTC datetime mapping;
- сортировка;
- handler pipeline;
- feed orchestration;
- propagation исключений.
7. Результаты тестирования
7.1. Специализированные тесты Build 044
70 passed
7.2. Полный unit-test suite проекта
683 passed in 3.29s
7.3. Проверка форматирования diff
git diff --check
Результат:
пустой вывод
8. Архитектурные проверки
8.1. Endpoint /api/v1/klines
Команда:
grep -RIn \
--exclude-dir="__pycache__" \
--exclude="*.pyc" \
'"/api/v1/klines"' \
src
Результат:
src/market_data/acquisition/adapters/dzengi/rest.py
src/integrations/exchange/service.py
Две точки являются ожидаемым переходным состоянием:
- новая canonical acquisition-цепочка;
- действующий legacy-путь.
8.2. Импорты canonical Candle
Команда:
grep -RIn \
--exclude-dir="__pycache__" \
--exclude="*.pyc" \
"models.candle import Candle" \
src tests
Canonical Candle используется только в новой acquisition-цепочке и её тестах.
8.3. Обратная зависимость Market Data → Trading
Команда:
grep -RIn \
--exclude-dir="__pycache__" \
--exclude="*.pyc" \
"from src.trading\|import src.trading" \
src/market_data
Результат:
пусто
8.4. Зависимость Candle Feed от ExchangeService
Команда:
grep -RIn \
--exclude-dir="__pycache__" \
--exclude="*.pyc" \
"ExchangeService" \
src/market_data/acquisition/models/candle.py \
src/market_data/acquisition/feeds/candles_feed.py \
src/market_data/acquisition/handlers/candles_handler.py
Результат:
пусто
9. Сопутствующая очистка документации
Вместе с Build 044 намеренно удалены устаревшие временные grep-файлы:
docs/migrations/greps.txt
docs/migrations/Вывод grep по дополнительным полям.txt
Эти файлы не являлись нормативной миграционной документацией и больше не использовались.
10. Совместимость
После Build 044:
- рабочий бот продолжает использовать legacy
ExchangeService.get_klines(); KlineиKlineBatchсохранены;- Market Analysis не изменён;
- runtime не переключён;
- существующее поведение торгового бота сохранено;
- новая Candles Feed foundation работает параллельно legacy-потоку.
11. Критерии завершения
Build 044 считается завершённым, поскольку:
- создана canonical модель
Candle; - реализован REST source
/api/v1/klines; - реализована schema validation;
- реализован parser object/list форматов;
- реализована value validation;
- реализован canonical mapper;
- реализован handler;
- реализован standalone Candles Feed;
- добавлены runtime-checkable protocols;
- добавлены специализированные исключения;
- добавлено полное unit-покрытие foundation-цепочки;
- targeted-тесты проходят;
- полный suite проходит;
- архитектурные grep соответствуют ожидаемому переходному состоянию;
- legacy runtime не изменён.
12. Ориентировочный дальнейший план миграции
Ниже приведён ориентировочный план. Номера и границы Build могут уточняться после обязательного аудита фактического кода перед каждым следующим Build.
Главный принцип остаётся неизменным:
foundation
↓
service/registry integration
↓
compatibility facade
↓
consumer migration
↓
legacy removal
↓
architecture verification
12.1. Завершение OHLCV Feed
Build 045 — register canonical Candles Feed
Цель:
- добавить Candles Feed в
registry.py; - добавить candle-specific registry contract;
- добавить registry tests;
- не менять
ExchangeService; - не менять Market Analysis.
Ожидаемый результат:
CandlesFeed
↓
Candles registry
Build 046 — expose Candles Feed through Acquisition Service
Цель:
- добавить read-only метод загрузки свечей в
service.py; - сохранить точные параметры:
- symbol;
- interval;
- limit;
- price_type;
- добавить service tests;
- не переключать legacy runtime.
Ожидаемый результат:
MarketDataAcquisitionService.load_candles()
↓
CandlesFeed
Build 047 — switch ExchangeService klines facade
Цель:
- сохранить публичный контракт
ExchangeService.get_klines(); - внутри переключить получение данных на canonical Acquisition Service;
- временно преобразовывать
Candleв legacyKline; - сохранить
KlineBatch; - добавить compatibility tests;
- удалить прямой REST-вызов
/api/v1/klinesизExchangeService; - удалить legacy parsing из
ExchangeService.
Ожидаемый результат:
ExchangeService.get_klines()
↓
MarketDataAcquisitionService.load_candles()
↓
Candle
↓
temporary compatibility mapping
↓
KlineBatch
Build 048 — migrate Market Analysis to Candle
Цель:
- перевести
trading/market_analysisсKlineна canonicalCandle; - сохранить расчётную семантику;
- локально адаптировать timestamp и numeric-типы;
- не изменять сами торговые алгоритмы;
- добавить/обновить тесты consumers.
Ожидаемый результат:
Market Analysis
↓
Candle
Build 049 — remove legacy Kline compatibility
Цель:
- удалить
Kline; - удалить
KlineBatch, если он больше не нужен; - удалить compatibility mapping;
- удалить legacy candle parsing;
- очистить импорты
src.integrations.exchange.models.Kline.
Build 050 — finalize OHLCV Feed architecture verification
Цель:
- полный архитектурный аудит Candles Feed;
- контроль endpoint;
- контроль raw transport keys;
- контроль legacy imports;
- контроль consumer contracts;
- документация итогового состояния;
- полный suite.
12.2. Trades Feed — Time & Sales
После завершения OHLCV Feed выполнить отдельный аудит:
REST trades endpoints
WebSocket trade messages
journal trade events
execution trade records
market trade data
Важно не смешивать:
Market Trades Feed
с:
сделками самого торгового бота
execution events
journal events
Ориентировочная последовательность:
Build 051 — audit Trades Feed sources and consumers
- определить фактические Dzengi endpoints/messages;
- отделить рыночные сделки от execution-событий;
- определить текущие consumers;
- зафиксировать минимальный scope.
Build 052 — establish canonical Trades Feed foundation
Trade;- transport model;
- REST/WebSocket source;
- schema;
- parser;
- values;
- mapper;
- handler;
- feed;
- tests.
Build 053 — register and expose Trades Feed
- registry;
- acquisition service;
- tests.
Build 054 — integrate first read-only consumer
- подключить один фактический consumer;
- не менять торговую семантику.
Build 055 — remove legacy trade market-data path
- удалить legacy parsing;
- удалить старые transport-модели;
- очистить imports.
Build 056 — finalize Trades Feed verification
- полный suite;
- grep;
- документация.
12.3. Order Book Feed
Текущий /api/v1/depth используется для получения best bid / best ask и построения Quote.
Поэтому перед миграцией Order Book Feed обязательно разделить:
Quote use case
и:
canonical Order Book use case
Нельзя удалять WebSocket depth-путь, пока Quotes Feed использует его как источник котировки.
Ориентировочная последовательность:
Build 057 — audit Order Book and depth contracts
- определить фактический формат Dzengi depth;
- определить уровни доступной глубины;
- определить sequence identifiers;
- определить snapshot/delta семантику;
- определить consumers;
- зафиксировать зависимость Quotes Feed.
Build 058 — establish Order Book model foundation
OrderBook;OrderBookLevel;- snapshot model;
- transport model;
- schema;
- parser;
- values;
- mapper;
- tests.
Build 059 — establish Order Book snapshot feed
- REST snapshot source;
- handler;
- feed;
- registry;
- service.
Build 060 — establish Order Book WebSocket updates
- delta/update parsing;
- sequence validation;
- snapshot reconciliation;
- tests.
Build 061 — add Order Book runtime storage
Только если подтверждено фактическими consumers:
- OrderBookStore;
- atomic update;
- source/runtime keys;
- freshness policy.
Build 062 — integrate execution-quality consumers
- spread/depth/slippage consumers;
- сохранить fallback на Quote;
- не менять торговые решения одним Build.
Build 063 — separate Quotes Feed from legacy depth runtime
- оставить Quotes Feed на canonical WebSocket adapter;
- удалить старый depth parsing из legacy runtime.
Build 064 — finalize Order Book verification
12.4. Derivatives Market Feed
Перед foundation Build требуется аудит фактических данных:
funding rate
overnight fee
mark price
open interest
contract metadata
leverage limits
liquidation-related fields
Нужно отделить:
Instrument Reference Data
Trading Conditions
Derivatives Market Data
Account-specific data
Ориентировочная последовательность:
Build 065 — audit derivatives data contracts
Build 066 — establish canonical Derivatives Feed foundation
Build 067 — register and expose Derivatives Feed
Build 068 — migrate funding / overnight consumers
Build 069 — migrate mark-price / open-interest consumers
Build 070 — remove legacy derivatives parsing
Build 071 — finalize Derivatives Feed verification
12.5. Market Index Feed
Перед началом требуется подтвердить, какие индексы реально предоставляет Dzengi:
index price
reference price
composite index
underlying index
Ориентировочная последовательность:
Build 072 — audit index data sources
Build 073 — establish Market Index Feed foundation
Build 074 — register and expose Index Feed
Build 075 — integrate confirmed consumers
Build 076 — remove legacy index path
Build 077 — finalize Index Feed verification
12.6. Exchange Time Feed
Текущий endpoint:
/api/v1/time
находится в:
ExchangeService.get_exchange_server_time_ms()
и используется логикой time synchronization.
Ориентировочная последовательность:
Build 078 — establish Exchange Time Feed foundation
- canonical time model;
- REST source;
- schema;
- parser;
- values;
- mapper;
- handler;
- feed;
- tests.
Build 079 — register and expose Time Feed
Build 080 — switch ExchangeService time facade
- сохранить текущий публичный контракт;
- переключить внутренний источник;
- сохранить time-sync поведение.
Build 081 — remove legacy time REST path
Build 082 — finalize Exchange Time Feed verification
12.7. Exchange Status Feed
Перед началом требуется разделить:
exchange availability
market availability
instrument status
runtime freshness
authentication status
account availability
Не все перечисленные состояния относятся к Market Data Acquisition.
Ориентировочная последовательность:
Build 083 — audit status semantics
Build 084 — establish Exchange Status Feed foundation
Build 085 — register and expose Status Feed
Build 086 — migrate public exchange-status consumers
Build 087 — remove legacy public-status acquisition
Build 088 — finalize Exchange Status Feed verification
12.8. Runtime подсистемы Acquisition
Файлы:
runtime/heartbeat.py
runtime/reconnect.py
runtime/scheduler.py
runtime/supervisor.py
не должны наполняться заранее.
Они должны мигрироваться только после появления реальных потоков, которым необходим общий lifecycle.
Ориентировочная последовательность после стабилизации Quotes, Trades и Order Book:
Build 089 — audit acquisition runtime ownership
- определить существующие runner/stream responsibilities;
- определить lifecycle ownership;
- определить реальные retry/reconnect policies.
Build 090 — establish common reconnect policy
Build 091 — establish heartbeat contract
Build 092 — establish acquisition scheduler
Build 093 — establish acquisition supervisor
Build 094 — migrate MarketDataRunner responsibilities
Build 095 — remove legacy market runtime orchestration
Build 096 — finalize Acquisition runtime verification
12.9. Финальная консолидация Market Data Acquisition
После миграции всех фактически используемых Feed:
Build 097 — remove unused acquisition placeholders
Только после отдельного подтверждения:
- удалить неиспользуемые placeholders;
- не удалять утверждённые модули, если их реализация отложена;
- зафиксировать статус каждого Feed.
Build 098 — finalize Acquisition service surface
- единый публичный read-only API;
- отсутствие transport details;
- отсутствие consumer-specific логики;
- стабильные protocols.
Build 099 — finalize Dzengi adapter isolation
- endpoint strings только в adapter;
- raw keys только в adapter/validation;
- отсутствие Dzengi transport-моделей вне adapter.
Build 100 — complete Market Data Acquisition migration
- итоговый полный suite;
- итоговый архитектурный grep;
- удаление подтверждённого legacy Market Data кода;
- итоговая документация;
- release checkpoint.
13. Правила применения дальнейшего плана
Этот план является ориентировочным и не разрешает автоматическое выполнение всех перечисленных Build.
Перед каждым Build обязательно:
- выполнить аудит фактического текущего кода;
- определить реальные sources и consumers;
- проверить, используется ли placeholder;
- выбрать минимальный безопасный scope;
- подготовить пошаговый план;
- согласовать план;
- только после согласования изменять код;
- выполнить targeted tests;
- выполнить полный unit-test suite;
- выполнить архитектурные grep;
- оформить
docs/migrations/build_XXX.md; - создать отдельный git commit.
Запрещено:
- объединять несколько Feed в один Build;
- создавать store без подтверждённой runtime-потребности;
- добавлять поля моделей «на будущее»;
- удалять legacy до переключения consumers;
- менять торговую семантику внутри Market Data migration;
- пересматривать утверждённую структуру каталогов без отдельного обсуждения.
14. Git commit
Рекомендуемое сообщение:
git commit -m "build 044: establish canonical candles feed foundation"