Files
dzentra_bot/docs/migrations/build_051.md

640 lines
14 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 051 — Переключение HTF-анализа на канонические Candle
## Статус
**Завершён**
---
## Цель Build
Переключить оба HTF-пути подсистемы `Market Analysis` с legacy API:
```text
ExchangeService.get_klines()
KlineBatch
batch.candles
```
на канонический API:
```text
ExchangeService.get_candles()
tuple[Candle, ...]
```
без изменения существующей HTF-семантики, расчётных алгоритмов, порогов, payload-полей и диагностических причин.
---
## Исходное состояние
До Build 051 в файле:
```text
src/trading/market_analysis/htf.py
```
существовали два legacy-пути получения свечей:
```text
htf_volatility_context()
htf_trend_context()
```
Оба использовали:
```text
ExchangeService.get_klines()
```
и затем извлекали:
```text
batch.candles
```
После Build 050 основной `MarketAnalysisService` уже был переключён на:
```text
ExchangeService.get_candles()
```
Поэтому `htf.py` оставался последним активным production-потребителем `get_klines()` внутри `src/trading/market_analysis`.
---
## Объём изменений
В Build 051 изменены:
```text
src/trading/market_analysis/htf.py
tests/unit/trading/market_analysis/test_htf_candles.py
docs/migrations/build_051.md
```
Build 051 не изменяет:
```text
src/trading/market_analysis/service.py
src/integrations/exchange/service.py
src/integrations/exchange/models.py
src/market_data/acquisition/
```
Build также не удаляет:
```text
ExchangeService.get_klines()
Kline
KlineBatch
_kline_from_candle()
```
Их удаление возможно только после отдельной общей проверки всех production-потребителей.
---
## Переключение htf_volatility_context()
До Build 051:
```text
htf_volatility_context()
ExchangeService.get_klines()
KlineBatch
batch.candles
```
После Build 051:
```text
htf_volatility_context()
ExchangeService.get_candles()
tuple[Candle, ...]
```
Удалена зависимость от:
```text
batch.candles
```
Все остальные расчёты сохранены.
---
## Переключение htf_trend_context()
До Build 051:
```text
htf_trend_context()
ExchangeService.get_klines()
KlineBatch
batch.candles
```
После Build 051:
```text
htf_trend_context()
ExchangeService.get_candles()
tuple[Candle, ...]
```
Удалена зависимость от legacy-контейнера `KlineBatch`.
---
## Каноническая модель Candle
После Build 051 оба HTF-пути непосредственно получают:
```text
tuple[Candle, ...]
```
Каноническая модель:
```text
src.market_data.acquisition.models.candle.Candle
```
использует:
```text
Decimal
```
для полей:
```text
open_price
high_price
low_price
close_price
volume
```
Поэтому для вычислительных функций была сохранена явная числовая граница:
```text
Decimal
safe_float(...)
isfinite(...)
float
```
---
## Числовая граница в htf_volatility_context()
В `htf_volatility_context()` последняя цена закрытия преобразуется через:
```text
safe_float()
```
и дополнительно проверяется через:
```text
math.isfinite()
```
Невалидные значения:
```text
NaN
Infinity
-Infinity
```
не допускаются к вычислению ATR percent.
При невозможности получить корректную цену закрытия сохраняется существующая причина:
```text
HTF_ATR_UNAVAILABLE
```
---
## Числовая граница в htf_trend_context()
В `htf_trend_context()` формируется:
```text
closes: list[float]
```
Каждая каноническая цена:
```text
Candle.close_price
```
проходит:
```text
safe_float()
isfinite()
```
Если хотя бы одно значение невалидно, HTF-анализ возвращает существующую причину:
```text
HTF_INDICATORS_UNAVAILABLE
```
Невалидные значения не пропускаются выборочно, поскольку это нарушило бы соответствие:
```text
candles[index] ↔ closes[index]
```
---
## Сохранение диагностического контракта
Несмотря на переход с `get_klines()` на `get_candles()`, существующая причина ошибки получения данных сохранена:
```text
HTF_KLINES_ERROR
```
Она используется в обоих HTF-путях.
Переименование в:
```text
HTF_CANDLES_ERROR
```
не выполнялось, поскольку это не требуется для технической миграции и могло изменить внешний диагностический контракт.
---
## Сохранённая логика htf_volatility_context()
Без изменений сохранены:
```text
проверка одинакового base и HTF interval
минимальное количество свечей
ATR
close price validation
ATR percent
ATR percent baseline
volatility ratio
classify_volatility()
rounding
формат payload
HTF_SKIPPED_SAME_INTERVAL
HTF_NOT_ENOUGH_CANDLES
HTF_ATR_UNAVAILABLE
HTF_OK
```
---
## Сохранённая логика htf_trend_context()
Без изменений сохранены:
```text
проверка одинакового base и HTF interval
минимальное количество свечей
EMA fast
EMA slow
ATR
ATR percent
adaptive thresholds
EMA slopes
trend classification
trend gap
trend strength
trend consistency
trend efficiency
EMA distance / ATR
candle noise score
price position score
trend quality
market phase
market state
alignment
confirmation score
формат HTF payload
```
---
## Новый тестовый файл
Добавлен:
```text
tests/unit/trading/market_analysis/test_htf_candles.py
```
Файл создан отдельно, поскольку до Build 051 специализированного `test_htf.py` в проекте не существовало.
---
## Покрытие htf_volatility_context()
Тесты проверяют:
1. пропуск запроса при одинаковом base и HTF interval;
2. точные аргументы `get_candles()`;
3. сохранение причины `HTF_KLINES_ERROR`;
4. сохранение причины `HTF_NOT_ENOUGH_CANDLES`;
5. отклонение не конечной close price;
6. сохранение причины `HTF_ATR_UNAVAILABLE`;
7. успешный HTF volatility payload;
8. поддержку canonical `Candle` с `Decimal`.
---
## Покрытие htf_trend_context()
Тесты проверяют:
1. пропуск запроса при одинаковом base и HTF interval;
2. точные аргументы `get_candles()`;
3. сохранение причины `HTF_KLINES_ERROR`;
4. сохранение причины `HTF_NOT_ENOUGH_CANDLES`;
5. отклонение не конечной close price;
6. сохранение причины `HTF_INDICATORS_UNAVAILABLE`;
7. преобразование `Decimal` closes в `float`;
8. успешный HTF trend payload;
9. неизменность структуры результата.
---
## Targeted tests
Выполнена команда:
```bash
python -m pytest -q \
tests/unit/trading/market_analysis/test_htf_candles.py
```
Результат:
```text
11 passed in 0.12s
```
---
## Regression-набор Market Analysis и стратегий
Выполнена команда:
```bash
python -m pytest -q \
tests/unit/trading/market_analysis \
tests/unit/trading/strategies/test_scalp_quote.py \
tests/unit/trading/strategies/test_trend_quote.py
```
Результат:
```text
38 passed in 0.14s
```
---
## Полный regression suite
Выполнена команда:
```bash
python -m pytest -q
```
Результат:
```text
805 passed in 2.72s
```
Регрессий не обнаружено.
---
## Контроль отсутствия get_klines() в Market Analysis
Выполнена команда:
```bash
grep -RIn \
--exclude-dir="__pycache__" \
--exclude="*.pyc" \
"\.get_klines(" \
src/trading/market_analysis
```
Результат:
```text
пусто
```
Это подтверждает, что в активном production-коде `Market Analysis` больше нет вызовов:
```text
ExchangeService.get_klines()
```
---
## Контроль использования get_candles()
Выполнена команда:
```bash
grep -RIn \
--exclude-dir="__pycache__" \
--exclude="*.pyc" \
"\.get_candles(" \
src/trading/market_analysis
```
Результат:
```text
src/trading/market_analysis/service.py:244: candles = ExchangeService().get_candles(
src/trading/market_analysis/htf.py:57: candles = ExchangeService().get_candles(
src/trading/market_analysis/htf.py:157: candles = ExchangeService().get_candles(
```
После Build 051 в `Market Analysis` существует ровно три production-вызова канонического API.
---
## Контроль legacy batch-зависимостей
Выполнена команда:
```bash
grep -RIn \
--exclude-dir="__pycache__" \
--exclude="*.pyc" \
"batch\.candles\|batch\.symbol\|KlineBatch\|Kline" \
src/trading/market_analysis
```
Результат:
```text
src/trading/market_analysis/indicators_legacy.py:5:from src.integrations.exchange.models import Kline
src/trading/market_analysis/indicators_legacy.py:21:def atr(candles: list[Kline], period: int = 14) -> float | None:
```
Следовательно:
- активные production-компоненты `Market Analysis` больше не зависят от `Kline`;
- единственная оставшаяся зависимость находится в подтверждённом неиспользуемом legacy-файле;
- `indicators_legacy.py` намеренно не изменяется в Build 051.
---
## Проверка форматирования
Выполнена команда:
```bash
git diff --check
```
Вывод отсутствует.
Whitespace-ошибок не обнаружено.
---
## Архитектурный результат
После Build 051 весь активный production-путь `Market Analysis` использует канонические свечи:
```text
MarketAnalysisService
ExchangeService.get_candles()
tuple[Candle, ...]
HTF volatility
ExchangeService.get_candles()
tuple[Candle, ...]
HTF trend
ExchangeService.get_candles()
tuple[Candle, ...]
```
Legacy API:
```text
ExchangeService.get_klines()
```
больше не используется активным `Market Analysis`.
---
## Что намеренно не выполнено
Build 051 намеренно не включает:
- удаление `ExchangeService.get_klines()`;
- удаление `Kline`;
- удаление `KlineBatch`;
- удаление `_kline_from_candle()`;
- удаление `indicators_legacy.py`;
- изменение диагностической причины `HTF_KLINES_ERROR`;
- изменение алгоритмов HTF;
- изменение торговой логики;
- изменение порогов;
- изменение scoring;
- изменение Market Data Acquisition;
- изменение структуры каталогов;
- удаление рабочего compatibility-кода.
---
## Критерии завершения
Build 051 считается завершённым, поскольку:
- оба HTF-пути используют `get_candles()`;
- зависимости `batch.candles` удалены;
- `Decimal` close prices безопасно преобразуются в `float`;
- `NaN` и бесконечности отклоняются;
- существующие диагностические причины сохранены;
- HTF payload не изменён;
- специализированные тесты проходят;
- regression-набор проходит;
- полный suite проходит;
- `get_klines()` отсутствует во всём активном `Market Analysis`;
- legacy `Kline` остаётся только в неиспользуемом `indicators_legacy.py`;
- `git diff --check` чистый.
---
## Итог
**Build 051 завершён успешно.**
Текущее состояние:
```text
MarketAnalysisService → get_candles()
HTF volatility → get_candles()
HTF trend → get_candles()
```
Результаты:
```text
Targeted HTF tests: 11 passed
Market Analysis + strategies: 38 passed
Full test suite: 805 passed
git diff --check: clean
```
Следующий безопасный этап — общая проверка всех оставшихся production-потребителей:
```text
ExchangeService.get_klines()
Kline
KlineBatch
_kline_from_candle()
```
Только после этой проверки можно определять отдельный Build по удалению compatibility bridge.