§9.6 Almon-адаптер хардкодит confounded=False → §15 шок-фактор (#1222) частично мёртв в production #1636

Closed
opened 2026-06-16 18:44:30 +00:00 by bot-backend · 0 comments
Collaborator

Severity: medium · Категория: correctness/silent-data-loss · Файл: backend/app/services/forecasting/regression.py:697-711, 658-671

Где: backend/app/services/forecasting/regression.py:708 (_fit_to_sensitivity) и :668 (_insufficient_sensitivity) возвращают RateSensitivity(..., confounded=False) жёстко, без учёта фактического окна fit. compute_rate_regime_sensitivity — production-путь (demand_supply_forecast.py:75/610), его .confounded ИЛИ-агрегируется с macro_coef.confounded в _series_confounded (demand_supply_forecast.py:650-651).

Импакт: §9.6-канал шок-окна никогда не выставляет confounded. Старый compute_rate_sensitivity вычислял confounded=_series_confounded(seg_sales.months)→is_confounded_window(min,max) (rate_sensitivity.py:467/573-577). Новый адаптер этого не делает. Окна разной длины: §9.5 macro_coefficient = 12 мес (macro_coefficient.py:84), §9.6 regression = 48 мес (regression.py:72). На текущую дату (2026-06) 12-мес macro-окно НЕ пересекает шок 2024-07-01 (macro_series.py:85) → macro_coef.confounded=False; но 48-мес окно §9.6 его пересекает → должно быть True. Итог: DemandSupplyForecast.confounded=False → report_assembler._confounded (report_assembler.py:238) → compute_report_confidence → confidence_engine._confounded_factor (L244): отчёт, обязанный быть ограничен ниже 'high' из-за конфаундящего ставочного окна, НЕ помечается и может объявить 'high'. Завышение confidence в клиентских инвест-отчётах.

Фикс: добавить confounded в DistributedLagFit, вычислять его в compute_district_rate_regression через is_confounded_window(min(macro_months), max(macro_months)) (macro_months доступны на regression.py:618) и пробросить в _fit_to_sensitivity (regression.py:708). Для _insufficient_sensitivity (district=None / no fit) — оставить False допустимо, но при наличии fit-окна выставлять реальный флаг.

Почему баг: В demand_supply_forecast _series_confounded(macro_coef, sensitivity) (L641-652) берёт ИЛИ-агрегат macro_coef.confounded OR sensitivity.confounded. Половина от §9.6 теперь всегда False. Это не чисто косметика: §9.5 macro_coefficient использует окно _DEFAULT_MONTHS_BACK=12 мес, а §9.6 regression — 48 мес. На сегодня (2026-06) 12-мес окно (~2025-06..2026-06) НЕ пересекает шок 2024-07-01 → macro_coef.confounded=False; но 48-мес окно §9.6 (~2022-06..) ПЕРЕСЕКАЕТ его → должно быть True. Итог: DemandSupplyForecast.confounded=False уходит в report_assembler._confounded (L226-238) → compute_report_confidence (#990/#1222), и отчёт, который обязан быть ограничен ниже 'high' из-за конфаундящего ставочного окна, НЕ помечается. Ровно тот мёртвый §15-фактор, который docstring demand_supply_forecast L179-183 обещает живым.

Как чинить: В _fit_to_sensitivity/compute_district_rate_regression вычислить реальный флаг из окна macro-ряда (например, прокинуть is_confounded_window(min(macro_months), max(macro_months)) через DistributedLagFit) и маппить его в RateSensitivity.confounded, а не хардкодить False.


deep-audit backend v2 (2-й проход, после PR #1543) · verify+harden, confidence 0.85 · unit B24

**Severity:** medium · **Категория:** correctness/silent-data-loss · **Файл:** `backend/app/services/forecasting/regression.py:697-711, 658-671` Где: backend/app/services/forecasting/regression.py:708 (_fit_to_sensitivity) и :668 (_insufficient_sensitivity) возвращают RateSensitivity(..., confounded=False) жёстко, без учёта фактического окна fit. compute_rate_regime_sensitivity — production-путь (demand_supply_forecast.py:75/610), его .confounded ИЛИ-агрегируется с macro_coef.confounded в _series_confounded (demand_supply_forecast.py:650-651). Импакт: §9.6-канал шок-окна никогда не выставляет confounded. Старый compute_rate_sensitivity вычислял confounded=_series_confounded(seg_sales.months)→is_confounded_window(min,max) (rate_sensitivity.py:467/573-577). Новый адаптер этого не делает. Окна разной длины: §9.5 macro_coefficient = 12 мес (macro_coefficient.py:84), §9.6 regression = 48 мес (regression.py:72). На текущую дату (2026-06) 12-мес macro-окно НЕ пересекает шок 2024-07-01 (macro_series.py:85) → macro_coef.confounded=False; но 48-мес окно §9.6 его пересекает → должно быть True. Итог: DemandSupplyForecast.confounded=False → report_assembler._confounded (report_assembler.py:238) → compute_report_confidence → confidence_engine._confounded_factor (L244): отчёт, обязанный быть ограничен ниже 'high' из-за конфаундящего ставочного окна, НЕ помечается и может объявить 'high'. Завышение confidence в клиентских инвест-отчётах. Фикс: добавить confounded в DistributedLagFit, вычислять его в compute_district_rate_regression через is_confounded_window(min(macro_months), max(macro_months)) (macro_months доступны на regression.py:618) и пробросить в _fit_to_sensitivity (regression.py:708). Для _insufficient_sensitivity (district=None / no fit) — оставить False допустимо, но при наличии fit-окна выставлять реальный флаг. **Почему баг:** В demand_supply_forecast `_series_confounded(macro_coef, sensitivity)` (L641-652) берёт ИЛИ-агрегат `macro_coef.confounded OR sensitivity.confounded`. Половина от §9.6 теперь всегда False. Это не чисто косметика: §9.5 macro_coefficient использует окно `_DEFAULT_MONTHS_BACK=12` мес, а §9.6 regression — 48 мес. На сегодня (2026-06) 12-мес окно (~2025-06..2026-06) НЕ пересекает шок 2024-07-01 → macro_coef.confounded=False; но 48-мес окно §9.6 (~2022-06..) ПЕРЕСЕКАЕТ его → должно быть True. Итог: `DemandSupplyForecast.confounded=False` уходит в `report_assembler._confounded` (L226-238) → `compute_report_confidence` (#990/#1222), и отчёт, который обязан быть ограничен ниже 'high' из-за конфаундящего ставочного окна, НЕ помечается. Ровно тот мёртвый §15-фактор, который docstring demand_supply_forecast L179-183 обещает живым. **Как чинить:** В `_fit_to_sensitivity`/`compute_district_rate_regression` вычислить реальный флаг из окна macro-ряда (например, прокинуть `is_confounded_window(min(macro_months), max(macro_months))` через DistributedLagFit) и маппить его в `RateSensitivity.confounded`, а не хардкодить False. --- <sub>deep-audit backend v2 (2-й проход, после PR #1543) · verify+harden, confidence 0.85 · unit B24</sub>
bot-backend added the
week ревью 1
label 2026-06-16 18:44:30 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#1636
No description provided.