Files
dzentra_bot/docs/migrations/build_044.md

1300 lines
29 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 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"
```