_score_future_competition: count = len(всех конкурентов), а mean_weight — только по не-None весам → возможное завышение плотности при частичных данных #1595

Closed
opened 2026-06-16 17:14:46 +00:00 by bot-backend · 0 comments
Collaborator

Severity: low · Категория: logic/edge-case · Файл: backend/app/services/forecasting/product_scoring.py:800-821, 374-383

Файл backend/app/services/forecasting/product_scoring.py:820-821 (_competitor_signal) и 376-382 (_score_future_competition). weights собирается только из конкурентов с relevance_weight is not None, но n_competitors = len(response.competitors) считает ВСЕХ. В скоринге count = n_competitors масштабирует count_scale = count/(count+_COMP_HALF_COUNT), тогда как mean_weight усредняет top-N только непустых весов; density = mean_weight × count_scale → при наличии None-весов плотность завышена, future_competition (1−density) занижен. ИМПАКТ: в production отсутствует — get_competitors (competitors.py:706,731) всегда задаёт relevance_weight=round(...,3) (число, не None), поэтому множества count и weights совпадают; расхождение проявляется только на мок/частичных данных (поле float|None допускает None). ФИКС: либо считать n_competitors = len(weights) (по конкурентам с весом), либо в _competitor_signal возвращать согласованную пару (отфильтровать конкурентов без веса до подсчёта count). Низкий приоритет — латентная несогласованность.

Почему баг: Density = mean_weight × count_scale домножается на count, включающий конкурентов, чей вклад в mean_weight не учтён (None-вес). Это завышает count_scale относительно реально взвешиваемого множества → future_competition-скор занижается (рынок выглядит плотнее, чем по данным с весами). На практике get_competitors всегда проставляет relevance_weight (round(...,3), не None при сборке), поэтому расхождение редкое, но при частичных/мок-данных скор смещён.

Как чинить: Считать n_competitors по тому же подмножеству, что и weights: return weights, len(weights) — либо явно использовать len(relevance_weights) для count_scale в _score_future_competition, чтобы числитель плотности и множитель количества опирались на одно множество.


deep-audit backend v2 (после PR #1543) · verify+harden, confidence 0.8 · unit B23

**Severity:** low · **Категория:** logic/edge-case · **Файл:** `backend/app/services/forecasting/product_scoring.py:800-821, 374-383` Файл backend/app/services/forecasting/product_scoring.py:820-821 (_competitor_signal) и 376-382 (_score_future_competition). weights собирается только из конкурентов с relevance_weight is not None, но n_competitors = len(response.competitors) считает ВСЕХ. В скоринге count = n_competitors масштабирует count_scale = count/(count+_COMP_HALF_COUNT), тогда как mean_weight усредняет top-N только непустых весов; density = mean_weight × count_scale → при наличии None-весов плотность завышена, future_competition (1−density) занижен. ИМПАКТ: в production отсутствует — get_competitors (competitors.py:706,731) всегда задаёт relevance_weight=round(...,3) (число, не None), поэтому множества count и weights совпадают; расхождение проявляется только на мок/частичных данных (поле float|None допускает None). ФИКС: либо считать n_competitors = len(weights) (по конкурентам с весом), либо в _competitor_signal возвращать согласованную пару (отфильтровать конкурентов без веса до подсчёта count). Низкий приоритет — латентная несогласованность. **Почему баг:** Density = mean_weight × count_scale домножается на count, включающий конкурентов, чей вклад в mean_weight не учтён (None-вес). Это завышает count_scale относительно реально взвешиваемого множества → future_competition-скор занижается (рынок выглядит плотнее, чем по данным с весами). На практике `get_competitors` всегда проставляет relevance_weight (round(...,3), не None при сборке), поэтому расхождение редкое, но при частичных/мок-данных скор смещён. **Как чинить:** Считать n_competitors по тому же подмножеству, что и weights: `return weights, len(weights)` — либо явно использовать `len(relevance_weights)` для count_scale в `_score_future_competition`, чтобы числитель плотности и множитель количества опирались на одно множество. --- <sub>deep-audit backend v2 (после PR #1543) · verify+harden, confidence 0.8 · unit B23</sub>
bot-backend added the
week ревью 1
label 2026-06-16 17:14:46 +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#1595
No description provided.