Files
dzentra_bot/docs/migrations/build_048.md

21 KiB
Raw Permalink Blame History

Build 048 — Переключение вычислительных потребителей Market Analysis на каноническую модель Candle

Статус: Completed

Дата: 2026-07-15

Подсистема: Market Data Acquisition / OHLCV Feed / Market Analysis


1. Назначение Build

Build 048 переводит активные вычислительные компоненты подсистемы Market Analysis, непосредственно работающие с последовательностями рыночных свечей, с legacy-модели:

src.integrations.exchange.models.Kline

на каноническую модель рыночной свечи:

src.market_data.acquisition.models.candle.Candle

Build является очередным этапом поэтапной миграции получения и использования OHLCV-данных в канонический слой:

Market Data Acquisition

Основная цель Build — устранить прямую зависимость активных вычислительных функций анализа рынка от legacy-модели Kline, сохранив существующую торговую семантику и поведение системы.


2. Контекст миграции

До Build 048 канонический OHLCV pipeline уже был создан и интегрирован поэтапно.

Build 044

Создан фундамент канонического Candles Feed:

REST transport
    ↓
schema validation
    ↓
parser
    ↓
value validation
    ↓
mapper
    ↓
Candle
    ↓
handler
    ↓
CandlesFeed

Каноническая модель:

src/market_data/acquisition/models/candle.py

Build 045

Создан и протестирован:

CandlesFeedRegistry

Build 046

Создан и интегрирован:

CandlesAcquisitionService

Build 047

Legacy-метод:

ExchangeService.get_klines()

переключён на канонический Candles Feed.

После Build 047 транспортный запрос:

/api/v1/klines

выполняется только внутри:

src/market_data/acquisition/adapters/dzengi/rest.py

При этом ExchangeService.get_klines() временно сохраняет обратную совместимость и преобразует канонические Candle обратно в legacy-модели Kline.

Build 048 начинает устранять эту обратную legacy-зависимость непосредственно внутри вычислительных потребителей Market Analysis.


3. Границы Build

В Build 048 изменены только активные вычислительные компоненты Market Analysis, которые непосредственно принимают последовательности свечей и используют поля OHLCV.

Изменены:

src/trading/market_analysis/indicators/volatility.py
src/trading/market_analysis/quality.py
src/trading/market_analysis/structure.py

Добавлены специализированные unit-тесты:

tests/unit/trading/market_analysis/indicators/test_volatility_candle.py
tests/unit/trading/market_analysis/test_quality_candle.py
tests/unit/trading/market_analysis/test_structure_candle.py

Build 048 не изменяет:

src/trading/market_analysis/service.py
src/trading/market_analysis/htf.py
src/trading/market_analysis/indicators_legacy.py
src/integrations/exchange/service.py
src/integrations/exchange/models.py

Build также не удаляет:

Kline
KlineBatch
ExchangeService.get_klines()

Их дальнейшая судьба определяется отдельными последующими этапами миграции.


4. Основное архитектурное изменение

До Build 048 активные вычислительные функции использовали legacy-модель:

from src.integrations.exchange.models import Kline

После Build 048 они используют каноническую модель:

from src.market_data.acquisition.models.candle import Candle

Изменение выполнено в:

src/trading/market_analysis/indicators/volatility.py
src/trading/market_analysis/quality.py
src/trading/market_analysis/structure.py

Таким образом, активные вычислительные функции:

atr()
atr_percent_baseline()
candle_noise_score()
market_structure()

больше не зависят от:

src.integrations.exchange.models.Kline

и работают непосредственно с:

src.market_data.acquisition.models.candle.Candle

5. Адаптация к канонической модели Candle

Каноническая модель Candle использует точные числовые значения:

Decimal

для полей:

open_price
high_price
low_price
close_price
volume

Legacy-модель Kline использовала:

float

Поэтому Build 048 выполняет явную адаптацию вычислительного слоя к Decimal.

Для безопасного преобразования используется существующий helper:

src.core.numbers.safe_float

Числовые значения преобразуются непосредственно на границе вычислений.

Принцип:

Candle
    ↓
Decimal OHLCV
    ↓
safe_float(...)
    ↓
float
    ↓
существующая вычислительная логика Market Analysis

Это позволяет:

  • сохранить точность канонической модели данных;
  • не переносить float в слой Market Data Acquisition;
  • сохранить существующие вычислительные алгоритмы;
  • минимизировать область изменений;
  • не изменять торговую семантику в рамках миграционного Build.

6. Изменения volatility.py

Файл:

src/trading/market_analysis/indicators/volatility.py

переведён с:

Sequence[Kline]

на:

Sequence[Candle]

Адаптированы функции:

atr()
atr_percent_baseline()

Поля канонической модели:

previous.close_price
current.high_price
current.low_price

преобразуются через:

safe_float(...)

Дополнительно выполняется проверка:

math.isfinite(...)

для исключения нечисловых конечных значений:

NaN
Infinity
-Infinity

Это необходимо, поскольку преобразование:

Decimal("NaN")

в float само по себе не возвращает None, а создаёт:

float("nan")

Без проверки isfinite() такое значение могло проникнуть в вычисление ATR.


7. Изменения quality.py

Файл:

src/trading/market_analysis/quality.py

переведён с:

Sequence[Kline]

на:

Sequence[Candle]

Адаптирована функция:

candle_noise_score()

Поля:

high_price
low_price
open_price
close_price

преобразуются через:

safe_float(...)

и проверяются через:

isfinite(...)

Невалидные свечи не участвуют в расчёте.

Если после фильтрации отсутствуют допустимые свечи, функция возвращает:

None

Существующая функция:

price_position_score()

сохранена.

Build 048 не изменяет её назначение и вычислительную семантику.


8. Изменения structure.py

Файл:

src/trading/market_analysis/structure.py

переведён с:

Sequence[Kline]

на:

Sequence[Candle]

Адаптирована функция:

market_structure()

Для построения последовательностей максимумов и минимумов используются значения:

candle.high_price
candle.low_price

с безопасным преобразованием к вычислительному типу.

Существующая логика определения структуры рынка сохранена:

HH_HL
LH_LL
MIXED
UNKNOWN

Build 048 не изменяет:

  • правила определения swing high;
  • правила определения swing low;
  • правила сравнения последних swing-точек;
  • adaptive structure parameters;
  • существующие причины результата;
  • существующую классификацию MarketStructure.

9. Защита от невалидных числовых значений

В ходе специализированного тестирования была выявлена необходимость явной проверки конечности числовых значений.

Для вычислительных функций используется:

from math import isfinite

После:

safe_float(...)

значения дополнительно проверяются на:

NaN
Infinity
-Infinity

Это предотвращает распространение невалидных числовых значений внутри:

ATR
ATR baseline
candle noise score

В частности, предотвращается ситуация:

Decimal("NaN")
    ↓
float("nan")
    ↓
результат вычисления nan

Вместо этого невалидное значение исключается из вычисления согласно локальной логике соответствующей функции.


10. Специализированные unit-тесты

Добавлены три специализированных тестовых файла.

10.1. Volatility

Файл:

tests/unit/trading/market_analysis/indicators/test_volatility_candle.py

Проверяет:

  • работу atr() с каноническими Candle;
  • поддержку Decimal;
  • недостаточное количество свечей;
  • невалидный период;
  • обработку не конечных числовых значений;
  • работу atr_percent_baseline();
  • невалидную цену закрытия.

10.2. Quality

Файл:

tests/unit/trading/market_analysis/test_quality_candle.py

Проверяет:

  • работу candle_noise_score() с Candle;
  • поддержку Decimal;
  • пустую последовательность;
  • свечу с нулевым диапазоном;
  • не конечные числовые значения;
  • применение указанного tail window.

10.3. Structure

Файл:

tests/unit/trading/market_analysis/test_structure_candle.py

Проверяет:

  • структуру HH_HL;
  • структуру LH_LL;
  • структуру MIXED;
  • недостаточное количество свечей;
  • непосредственную работу с Decimal-значениями Candle.

11. Результаты специализированных тестов

Команда:

python -m pytest -q \
  tests/unit/trading/market_analysis/indicators/test_volatility_candle.py \
  tests/unit/trading/market_analysis/test_quality_candle.py \
  tests/unit/trading/market_analysis/test_structure_candle.py

Результат:

16 passed in 0.02s

12. Regression-проверка стратегий

Дополнительно выполнена проверка стратегий:

python -m pytest -q \
  tests/unit/trading/strategies/test_scalp_quote.py \
  tests/unit/trading/strategies/test_trend_quote.py

Результат:

6 passed in 0.14s

Эта проверка подтверждает сохранение импортов и существующей интеграции Market Analysis с торговыми стратегиями.


13. Полный regression suite

Выполнена команда:

python -m pytest -q

Результат:

766 passed in 2.53s

Полный unit test suite проекта проходит успешно.


14. Контроль legacy-зависимости Kline

Выполнена команда:

grep -RIn \
  --exclude-dir="__pycache__" \
  --exclude="*.pyc" \
  "integrations.exchange.models import Kline" \
  src/trading/market_analysis

Результат:

src/trading/market_analysis/indicators_legacy.py:5:from src.integrations.exchange.models import Kline

Следовательно, после Build 048 активные вычислительные компоненты:

volatility.py
quality.py
structure.py

больше не импортируют legacy-модель Kline.

Оставшийся импорт находится только в:

indicators_legacy.py

который не изменяется в рамках Build 048.


15. Контроль использования канонической модели Candle

Выполнена команда:

grep -RIn \
  --exclude-dir="__pycache__" \
  --exclude="*.pyc" \
  "models.candle import Candle" \
  src/trading/market_analysis

Результат:

src/trading/market_analysis/indicators/volatility.py:10:from src.market_data.acquisition.models.candle import Candle
src/trading/market_analysis/structure.py:9:from src.market_data.acquisition.models.candle import Candle
src/trading/market_analysis/quality.py:9:from src.market_data.acquisition.models.candle import Candle

Это подтверждает прямую зависимость трёх активных вычислительных потребителей от канонической модели Candle.


16. Контроль оставшихся вызовов ExchangeService.get_klines()

Выполнена команда:

grep -RIn \
  --exclude-dir="__pycache__" \
  --exclude="*.pyc" \
  "\.get_klines(" \
  src/trading/market_analysis

Результат:

src/trading/market_analysis/service.py:243:            batch = ExchangeService().get_klines(
src/trading/market_analysis/htf.py:55:        batch = ExchangeService().get_klines(
src/trading/market_analysis/htf.py:153:        batch = ExchangeService().get_klines(

Эти три вызова являются ожидаемыми и не удаляются в Build 048.

Они показывают следующую границу дальнейшей миграции:

Market Analysis orchestration
    ↓
прямое получение Candle
    ↓
устранение зависимости от ExchangeService.get_klines()

Такое переключение должно выполняться отдельным Build после анализа контрактов:

service.py
htf.py

17. Проверка форматирования diff

Выполнена команда:

git diff --check

Вывод отсутствует.

Следовательно:

trailing whitespace отсутствует
ошибки whitespace отсутствуют

18. Архитектурный результат

После Build 048 активный вычислительный путь выглядит следующим образом:

Dzengi REST API
    ↓
DzengiCandlesDocumentSource
    ↓
validate_candles_schema()
    ↓
parse_candles()
    ↓
validate_candles_values()
    ↓
map_candles()
    ↓
Candle
    ↓
CandlesDocumentHandler
    ↓
CandlesFeed
    ↓
CandlesFeedRegistry
    ↓
CandlesAcquisitionService
    ↓
ExchangeService.get_klines()
    ↓
legacy compatibility conversion
    ↓
Market Analysis orchestration
    ↓
active computational consumers typed for Candle

При этом три активных вычислительных компонента уже используют канонический контракт:

volatility.py → Candle
quality.py    → Candle
structure.py  → Candle

Однако orchestration-слой Market Analysis пока продолжает получать данные через:

ExchangeService.get_klines()

Поэтому полное устранение legacy-преобразования Candle → Kline ещё не завершено.


19. Что сознательно не сделано

В Build 048 сознательно не выполнялось:

  • удаление Kline;
  • удаление KlineBatch;
  • удаление ExchangeService.get_klines();
  • изменение MarketAnalysisService;
  • изменение HTF orchestration;
  • изменение indicators_legacy.py;
  • изменение торговых стратегий;
  • изменение scoring;
  • изменение signal logic;
  • изменение торговых порогов;
  • изменение определения market structure;
  • изменение правил ATR;
  • изменение существующей архитектуры каталогов;
  • удаление рабочего legacy-кода.

Это соответствует принципу поэтапной миграции:

сначала новый канонический путь
    ↓
затем переключение потребителей
    ↓
затем подтверждение отсутствия legacy-потребителей
    ↓
только после этого отдельное удаление legacy-кода

20. Соблюдение правил миграции

Build 048 соответствует утверждённым правилам проекта Dzentra:

  1. Рабочий код не удаляется без отдельного согласования.
  2. Изменения ограничены согласованными границами Build.
  3. Канонический слой Market Data не зависит от src.trading.
  4. Миграция выполняется поэтапно.
  5. Обратная совместимость сохраняется там, где она ещё необходима.
  6. Legacy-код не удаляется до подтверждённого переключения всех его потребителей.
  7. Существующая торговая семантика не изменяется в рамках инфраструктурной миграции.
  8. Каждый Build подтверждается специализированными тестами, полным regression suite и контрольными grep.

21. Итог Build 048

Build 048 завершён успешно.

В результате:

volatility.py
quality.py
structure.py

переведены с:

Kline

на:

Candle

Канонические Decimal-значения адаптированы к существующему вычислительному слою через:

safe_float(...)

с дополнительной защитой от:

NaN
Infinity
-Infinity

Подтверждено:

16 специализированных тестов passed
6 regression-тестов стратегий passed
766 тестов полного suite passed
git diff --check — чисто

Build 048 завершает переключение выбранных активных вычислительных потребителей Market Analysis на каноническую модель Candle.

Следующая архитектурная граница миграции — прямое переключение orchestration-компонентов:

src/trading/market_analysis/service.py
src/trading/market_analysis/htf.py

с:

ExchangeService.get_klines()

на получение канонических:

Candle

через слой:

Market Data Acquisition

Такое переключение должно выполняться отдельным Build с сохранением существующего поведения системы.