14 KiB
Build 047 — Переключение ExchangeService.get_klines() на канонический Candles Feed
Статус: Completed
Дата: 2026-07-15
Подсистема: Market Data Acquisition / OHLCV Feed
Тип изменения: Миграция legacy-потребителя на канонический Acquisition pipeline
1. Цель Build
Цель Build 047 — переключить существующий публичный метод:
ExchangeService.get_klines()
с прямого получения и самостоятельной обработки ответа Dzengi /api/v1/klines на канонический pipeline подсистемы:
src/market_data/acquisition/
При этом необходимо сохранить существующий публичный контракт ExchangeService.get_klines() и обратную совместимость с текущими потребителями legacy-слоя.
2. Исходное состояние
До Build 047 метод:
ExchangeService.get_klines()
самостоятельно:
- выполнял прямой REST-запрос к
/api/v1/klines; - извлекал элементы ответа;
- разбирал отдельные свечи;
- создавал legacy-модели
Kline; - формировал
KlineBatch.
В ExchangeService существовали собственные legacy-функции обработки свечей:
_parse_klines_payload()
_extract_klines_items()
_parse_kline_item()
Таким образом, после появления канонического Candles Feed в системе существовали два независимых пути получения и обработки OHLCV-данных.
Это создавало дублирование ответственности между:
src/integrations/exchange/
и:
src/market_data/acquisition/
3. Границы Build
В Build 047 выполнено:
- переключение внутренней реализации
ExchangeService.get_klines()на канонический Candles Feed; - сохранение публичного контракта
ExchangeService.get_klines(); - сохранение legacy-моделей
KlineиKlineBatch; - добавление внутреннего адаптационного преобразования
Candle -> Kline; - удаление прямого REST-запроса
/api/v1/klinesизExchangeService; - удаление legacy-функций:
_parse_klines_payload();_extract_klines_items();_parse_kline_item();
- добавление специализированных unit-тестов для
ExchangeService.get_klines()и его интеграции с каноническим Acquisition pipeline.
В Build 047 не выполнялось:
- изменение публичного контракта
ExchangeService.get_klines(); - изменение legacy-потребителей в
trading/market_analysis; - удаление моделей
KlineиKlineBatch; - прямое переключение
trading/market_analysisнаCandlesAcquisitionService; - изменение архитектуры других Market Data feeds;
- изменение runtime-компонентов Acquisition.
4. Изменённые production-файлы
4.1. src/integrations/exchange/service.py
Метод:
ExchangeService.get_klines()
сохранён как публичный compatibility-контракт.
Внутренний путь получения данных изменён.
До Build 047:
ExchangeService.get_klines()
↓
прямой REST-запрос /api/v1/klines
↓
_parse_klines_payload()
↓
_extract_klines_items()
↓
_parse_kline_item()
↓
Kline
↓
KlineBatch
После Build 047:
ExchangeService.get_klines()
↓
_load_candles_via_acquisition()
↓
DzengiCandlesDocumentSource
↓
DzengiCandlesDocumentHandler
↓
CandlesFeed
↓
CandlesFeedRegistry
↓
CandlesAcquisitionService
↓
Candle
↓
_kline_from_candle()
↓
Kline
↓
KlineBatch
5. Канонический путь получения свечей
После Build 047 единственный production-путь прямого обращения к endpoint:
/api/v1/klines
расположен в:
src/market_data/acquisition/adapters/dzengi/rest.py
Это соответствует архитектурному разделению ответственности:
Exchange-specific transport
↓
Market Data Acquisition
↓
Canonical Candle
↓
Legacy compatibility boundary
↓
Kline / KlineBatch
ExchangeService больше не владеет транспортной логикой получения OHLCV-данных от Dzengi.
6. Добавленные внутренние методы
6.1. _load_candles_via_acquisition()
Добавлен внутренний compatibility-helper:
ExchangeService._load_candles_via_acquisition()
Его ответственность:
- создать
DzengiCandlesDocumentSource; - создать
DzengiCandlesDocumentHandler; - создать
CandlesFeed; - зарегистрировать feed в
CandlesFeedRegistry; - создать
CandlesAcquisitionService; - вызвать канонический
load_candles(); - вернуть immutable-набор моделей
Candle.
Метод является внутренней границей между legacy ExchangeService и канонической подсистемой Market Data Acquisition.
6.2. _kline_from_candle()
Добавлен внутренний адаптер:
ExchangeService._kline_from_candle()
Преобразование выполняется по следующему правилу:
Candle.symbol -> Kline.symbol
Candle.interval -> Kline.interval
Candle.open_time -> Kline.open_time
Candle.open_price -> Kline.open_price
Candle.high_price -> Kline.high_price
Candle.low_price -> Kline.low_price
Candle.close_price -> Kline.close_price
Candle.volume -> Kline.volume
Это позволяет сохранить существующий legacy-контракт без переноса legacy-моделей внутрь market_data/acquisition.
7. Удалённая legacy-логика
Из:
src/integrations/exchange/service.py
удалены:
_parse_klines_payload()
_extract_klines_items()
_parse_kline_item()
Также удалён прямой вызов:
/api/v1/klines
из ExchangeService.
После Build 047 parsing, schema validation, value validation и mapping OHLCV-данных выполняются только канонической подсистемой:
src/market_data/acquisition/
8. Сохранённая обратная совместимость
Публичный контракт:
ExchangeService.get_klines(...)
сохранён.
Существующие production-потребители не изменялись:
src/trading/market_analysis/service.py
src/trading/market_analysis/htf.py
Они продолжают работать через:
ExchangeService.get_klines()
и получать:
KlineBatch
Таким образом, Build 047 меняет внутренний источник данных, но не требует одновременного переписывания legacy-потребителей.
9. Добавленные тесты
Добавлен специализированный файл:
tests/unit/integrations/exchange/test_service_klines.py
Тесты покрывают:
- использование
default_symbol; - нормализацию
limit; - нормализацию
interval; - отклонение неподдерживаемого interval;
- передачу
price_type; - обработку выключенной биржи;
- обработку неизвестного символа;
- передачу параметров в Acquisition pipeline;
- преобразование
CandleвKline; - формирование
KlineBatch; - обработку пустого набора свечей;
- обработку исключений канонического Acquisition pipeline;
- построение полного composition pipeline;
- сохранение публичного legacy-контракта.
Результат targeted-проверки:
26 passed in 0.17s
10. Полная регрессионная проверка
Выполнено:
python -m pytest -q
Результат:
750 passed in 2.83s
Регрессий не обнаружено.
11. Контроль прямого использования /api/v1/klines
Команда:
grep -RIn \
--exclude-dir="__pycache__" \
--exclude="*.pyc" \
'"/api/v1/klines"' \
src
Результат:
src/market_data/acquisition/adapters/dzengi/rest.py:17:_KLINES_PATH = "/api/v1/klines"
Вывод:
Прямое знание endpoint /api/v1/klines находится только в каноническом Dzengi REST-адаптере.
12. Контроль удаления legacy-парсеров
Команда:
grep -RIn \
--exclude-dir="__pycache__" \
--exclude="*.pyc" \
"_parse_klines_payload\|_extract_klines_items\|_parse_kline_item" \
src tests
Результат:
пусто
Вывод:
Legacy-функции обработки kline payload полностью удалены.
13. Контроль оставшихся потребителей ExchangeService.get_klines()
Команда:
grep -RIn \
--exclude-dir="__pycache__" \
--exclude="*.pyc" \
"\.get_klines(" \
src tests
Production-потребители:
src/trading/market_analysis/service.py
src/trading/market_analysis/htf.py
Дополнительно присутствуют специализированные вызовы в:
tests/unit/integrations/exchange/test_service_klines.py
Вывод:
Публичный compatibility-контракт ExchangeService.get_klines() продолжает обслуживать существующие legacy-потребители.
14. Контроль интеграции с Acquisition pipeline
Команда:
grep -RIn \
--exclude-dir="__pycache__" \
--exclude="*.pyc" \
"CandlesAcquisitionService\|CandlesFeedRegistry\|DzengiCandlesDocumentSource" \
src/integrations/exchange/service.py
Результат подтверждает использование:
DzengiCandlesDocumentSource
CandlesFeedRegistry
CandlesAcquisitionService
внутри compatibility boundary ExchangeService.
15. Контроль качества diff
Выполнено:
git diff --check
Результат:
пусто
Whitespace-ошибок не обнаружено.
16. Архитектурный результат
После Build 047 путь OHLCV-данных имеет следующую структуру:
Dzengi REST API
↓
DzengiCandlesDocumentSource
↓
schema validation
↓
parser
↓
value validation
↓
mapper
↓
Candle
↓
CandlesFeed
↓
CandlesFeedRegistry
↓
CandlesAcquisitionService
↓
ExchangeService compatibility boundary
↓
Kline / KlineBatch
↓
legacy trading consumers
Главный архитектурный результат:
ExchangeService больше не получает и не разбирает
сырой ответ /api/v1/klines самостоятельно.
Владение получением и канонической обработкой OHLCV-данных теперь принадлежит:
src/market_data/acquisition/
17. Состояние после Build 047
На момент завершения Build:
Targeted tests: 26 passed
Full test suite: 750 passed
git diff --check: clean
Прямой endpoint:
/api/v1/klines
остался только в:
src/market_data/acquisition/adapters/dzengi/rest.py
Legacy parsing helpers:
_parse_klines_payload
_extract_klines_items
_parse_kline_item
полностью отсутствуют.
Публичный контракт:
ExchangeService.get_klines()
сохранён.
18. Итог Build
Build 047 завершён успешно.
Канонический Candles Feed интегрирован в существующий ExchangeService.get_klines() без изменения его публичного контракта.
Дублирующая legacy-логика получения и разбора /api/v1/klines удалена.
Существующие потребители продолжают работать без изменений.
Полная регрессионная проверка подтверждает отсутствие нарушений существующего поведения:
750 passed