# 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** в утверждённой подсистеме: ```text src/market_data/acquisition/ ``` Build реализует новую read-only цепочку получения и обработки свечей рядом с действующим legacy-потоком. Рабочий бот после Build 044 продолжает использовать существующий метод: ```text ExchangeService.get_klines() ``` Переключение рабочего runtime на новый Candles Feed в данный Build не входит. --- ## 2. Причина выполнения Build После завершения миграции: ```text Instrument Reference Data Quotes Feed ``` следующим активным legacy-потоком Market Data Acquisition остаётся получение OHLCV-свечей. До Build 044 рабочая цепочка свечей находилась в legacy exchange layer: ```text 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 входит Реализована цепочка: ```text 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 не изменяет: ```text 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. Каноническая модель Создана модель: ```text src/market_data/acquisition/models/candle.py ``` Контракт: ```python @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. В модель намеренно не добавлены: ```text close_time is_closed CandleBatch ``` Эти поля и сущности не требуются текущим подтверждённым контрактом. --- ### 4.2. Transport-модели Dzengi В файл: ```text src/market_data/acquisition/adapters/dzengi/models.py ``` добавлены: ```text DzengiKline DzengiKlinesResponse ``` Transport-модель хранит данные после parser, но до канонического mapping. Допустимые transport numeric-типы: ```text str | int | float ``` --- ### 4.3. REST source В файл: ```text src/market_data/acquisition/adapters/dzengi/rest.py ``` добавлен endpoint: ```text /api/v1/klines ``` и источник: ```text DzengiCandlesDocumentSource ``` Источник выполняет только transport-вызов и не выполняет: - schema validation; - parsing; - value validation; - mapping; - сортировку; - кэширование; - нормализацию запроса. Transport-ошибки преобразуются в: ```text CandleTransportError ``` --- ### 4.4. Schema validation В файл: ```text src/market_data/acquisition/validation/schema.py ``` добавлены: ```text ValidatedCandlesDocument validate_candles_schema() ``` Поддерживаются legacy-compatible envelope-форматы: ```text root list root.klines root.candles root.data root.result root.payload list root.payload.klines root.payload.candles root.payload.data ``` Поддерживаются два формата одной свечи: ```text JSON object JSON array ``` После schema validation: ```text dict → MappingProxyType list → tuple ``` --- ### 4.5. Parser В файл: ```text src/market_data/acquisition/adapters/dzengi/parser.py ``` добавлена функция: ```text parse_candles() ``` Поддерживаются object-поля: ```text openTime open_time time timestamp open high low close volume ``` Поддерживается array-формат: ```text [ open_time, open, high, low, close, volume, ... ] ``` Дополнительные поля массива игнорируются. Parser: - проверяет transport-типы; - не создаёт `Decimal`; - не проверяет OHLC-инварианты; - не создаёт canonical `Candle`. --- ### 4.6. Value validation В файл: ```text src/market_data/acquisition/validation/values.py ``` добавлена функция: ```text validate_candles_values() ``` Проверяются: ```text 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 В файл: ```text src/market_data/acquisition/adapters/dzengi/mapper.py ``` добавлена функция: ```text map_dzengi_klines_to_candles() ``` Mapper выполняет: ```text raw numeric → Decimal milliseconds timestamp → UTC datetime DzengiKline → Candle sorting by open_time list → tuple ``` Mapper не выполняет: - исправление некорректных значений; - удаление свечей; - обрезку по `limit`; - дедупликацию; - определение закрытости свечи. --- ### 4.8. Handler Реализован: ```text src/market_data/acquisition/handlers/candles_handler.py ``` Основной класс: ```text DzengiCandlesDocumentHandler ``` Последовательность обработки: ```text validate_candles_schema() ↓ parse_candles() ↓ validate_candles_values() ↓ map_dzengi_klines_to_candles() ``` --- ### 4.9. Feed Реализован: ```text src/market_data/acquisition/feeds/candles_feed.py ``` Основной класс: ```text CandlesFeed ``` Feed координирует: ```text CandlesDocumentSource ↓ CandlesDocumentHandler ``` Feed не выполняет: - transport parsing; - value validation; - mapping; - кэширование; - повторную обрезку результата по `limit`. --- ### 4.10. Protocols В файл: ```text src/market_data/acquisition/protocol.py ``` добавлены: ```text CandlesDocumentSource CandlesDocumentHandler CandlesFeedProtocol ``` Runtime-проверка протоколов выполнена успешно: ```text candles protocols: OK ``` --- ### 4.11. Exceptions В файл: ```text src/market_data/acquisition/exceptions.py ``` добавлены: ```text CandleTransportError CandleSchemaError CandleParseError CandleValueError CandleMappingError ``` Registry-specific исключение не добавлялось, поскольку регистрация Candles Feed не входит в Build 044. --- ## 5. Изменённые production-файлы ```text 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-тесты ```text 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 ```text 70 passed ``` ### 7.2. Полный unit-test suite проекта ```text 683 passed in 3.29s ``` ### 7.3. Проверка форматирования diff ```text git diff --check ``` Результат: ```text пустой вывод ``` --- ## 8. Архитектурные проверки ### 8.1. Endpoint `/api/v1/klines` Команда: ```bash grep -RIn \ --exclude-dir="__pycache__" \ --exclude="*.pyc" \ '"/api/v1/klines"' \ src ``` Результат: ```text src/market_data/acquisition/adapters/dzengi/rest.py src/integrations/exchange/service.py ``` Две точки являются ожидаемым переходным состоянием: - новая canonical acquisition-цепочка; - действующий legacy-путь. --- ### 8.2. Импорты canonical Candle Команда: ```bash grep -RIn \ --exclude-dir="__pycache__" \ --exclude="*.pyc" \ "models.candle import Candle" \ src tests ``` Canonical `Candle` используется только в новой acquisition-цепочке и её тестах. --- ### 8.3. Обратная зависимость Market Data → Trading Команда: ```bash grep -RIn \ --exclude-dir="__pycache__" \ --exclude="*.pyc" \ "from src.trading\|import src.trading" \ src/market_data ``` Результат: ```text пусто ``` --- ### 8.4. Зависимость Candle Feed от ExchangeService Команда: ```bash 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 ``` Результат: ```text пусто ``` --- ## 9. Сопутствующая очистка документации Вместе с Build 044 намеренно удалены устаревшие временные grep-файлы: ```text 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. Главный принцип остаётся неизменным: ```text 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. Ожидаемый результат: ```text CandlesFeed ↓ Candles registry ``` --- ### Build 046 — expose Candles Feed through Acquisition Service Цель: - добавить read-only метод загрузки свечей в `service.py`; - сохранить точные параметры: - symbol; - interval; - limit; - price_type; - добавить service tests; - не переключать legacy runtime. Ожидаемый результат: ```text MarketDataAcquisitionService.load_candles() ↓ CandlesFeed ``` --- ### Build 047 — switch ExchangeService klines facade Цель: - сохранить публичный контракт `ExchangeService.get_klines()`; - внутри переключить получение данных на canonical Acquisition Service; - временно преобразовывать `Candle` в legacy `Kline`; - сохранить `KlineBatch`; - добавить compatibility tests; - удалить прямой REST-вызов `/api/v1/klines` из `ExchangeService`; - удалить legacy parsing из `ExchangeService`. Ожидаемый результат: ```text ExchangeService.get_klines() ↓ MarketDataAcquisitionService.load_candles() ↓ Candle ↓ temporary compatibility mapping ↓ KlineBatch ``` --- ### Build 048 — migrate Market Analysis to Candle Цель: - перевести `trading/market_analysis` с `Kline` на canonical `Candle`; - сохранить расчётную семантику; - локально адаптировать timestamp и numeric-типы; - не изменять сами торговые алгоритмы; - добавить/обновить тесты consumers. Ожидаемый результат: ```text 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 выполнить отдельный аудит: ```text REST trades endpoints WebSocket trade messages journal trade events execution trade records market trade data ``` Важно не смешивать: ```text Market Trades Feed ``` с: ```text сделками самого торгового бота 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 обязательно разделить: ```text Quote use case ``` и: ```text 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 требуется аудит фактических данных: ```text funding rate overnight fee mark price open interest contract metadata leverage limits liquidation-related fields ``` Нужно отделить: ```text 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: ```text 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: ```text /api/v1/time ``` находится в: ```text 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 Перед началом требуется разделить: ```text 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 Файлы: ```text 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 обязательно: 1. выполнить аудит фактического текущего кода; 2. определить реальные sources и consumers; 3. проверить, используется ли placeholder; 4. выбрать минимальный безопасный scope; 5. подготовить пошаговый план; 6. согласовать план; 7. только после согласования изменять код; 8. выполнить targeted tests; 9. выполнить полный unit-test suite; 10. выполнить архитектурные grep; 11. оформить `docs/migrations/build_XXX.md`; 12. создать отдельный git commit. Запрещено: - объединять несколько Feed в один Build; - создавать store без подтверждённой runtime-потребности; - добавлять поля моделей «на будущее»; - удалять legacy до переключения consumers; - менять торговую семантику внутри Market Data migration; - пересматривать утверждённую структуру каталогов без отдельного обсуждения. --- ## 14. Git commit Рекомендуемое сообщение: ```bash git commit -m "build 044: establish canonical candles feed foundation" ```