Files
dzentra_bot/docs/migrations/build_044.md

29 KiB
Raw Blame History

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 в legacy Kline;
  • сохранить 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 на canonical Candle;
  • сохранить расчётную семантику;
  • локально адаптировать 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 обязательно:

  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

Рекомендуемое сообщение:

git commit -m "build 044: establish canonical candles feed foundation"