recommend_mix: weighted_avg_price_per_m2 не пересчитывается после success-boost share_pct → средневзвешенная цена рассогласована с долями бакетов (пробел в фиксе #1359) #1576

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

Severity: medium · Категория: internal-consistency / stale aggregate (остаток после фикса #1359) · Файл: backend/app/services/analytics_queries.py:2497, 2763-2764, 2768-2822, 3067

Файл: backend/app/services/analytics_queries.py — расчёт line 2497, домножение 2764, success-boost блок 2768-2822, выдача 3067.

Проблема: weighted_avg_price = weighted_num/weighted_den (line 2497) считается из ДО-boost долей (share, line 2448; weighted_num/den накапливаются в цикле 2469-2470). На line 2764 домножается на combined_price_factor. В success-boost блоке (2768-2822) share_pct top-бакета поднимается на +10% (2779), остальные режутся пропорционально (2782-2787); при area_total_m2 заново считаются units_planned/revenue/total_revenue/months_to_sellout под новые доли (фикс #1359, 2793-2822). weighted_avg_price при этом НЕ пересчитывается → summary.weighted_avg_price_per_m2 (line 3067) отдаёт значение от старого микса.

Комментарий 2819-2821 утверждает, что weighted_avg_price трогать не нужно — но он учитывает только то, что combined_price_factor уже зашит в per-bucket price_median_per_m2 (повторно домножать не надо). Смену ВЕСОВ-долей этот аргумент не покрывает.

Импакт: weighted_avg_price — средневзвешенная по долям цена. success-boost (velocity+price-ориентированный) обычно поднимает долю более дорогого/ликвидного бакета → истинная средневзвешенная должна вырасти, но в выдаче остаётся до-boost значение. UI показывает summary.weighted_avg_price_per_m2, не совпадающую с отображёнными share_pct и per-bucket price_median_per_m2 — внутреннее противоречие отчёта. Та же логика, что #1359 чинил для units/revenue/velocity, но weighted_avg_price пропущен.

Условие срабатывания: success_ranking непустой (line 2768) + area_total_m2 задан (2793) + найден top с success_score>0 и n_deals>=30. Сейчас почти не случается из-за бага [0] (пустой success_ranking), но оживёт после его фикса.

Фикс: в success-boost блоке при area_total_m2 заново аккумулировать weighted_num/weighted_den по обновлённым share_pct (используя b['_area_avg_raw'] и b['price_median_per_m2']) и пересчитать weighted_avg_price = round(weighted_num/weighted_den, 2), по аналогии с пересчётом total_revenue/units на 2793-2822.

Почему баг: weighted_avg_price — это средневзвешенная по долям цена. success-boost (велосити+цена-ориентированный) обычно поднимает долю более дорогого бакета, что должно повышать истинную средневзвешенную цену; реальная же выдача остаётся на до-boost миксе. Это та же логика рассогласования, что #1359 чинил для units/revenue/velocity, но weighted_avg_price в фиксе пропущен. UI показывает summary.weighted_avg_price_per_m2, не совпадающую с отображаемыми share_pct и per-bucket price_median_per_m2 (внутреннее противоречие отчёта). Только при area_total_m2 + сработавшем boost (что сейчас почти не случается из-за бага №1 в этом отчёте, но может ожить после его фикса).

Как чинить: Внутри блока пересчёта (после изменения share_pct) пересобрать weighted_avg_price: weighted_avg_price = round(Σ(b['_area_avg_raw']·b['share_pct']·b['price_median_per_m2']) / Σ(b['_area_avg_raw']·b['share_pct']), 2). price_median_per_m2 уже содержит combined_price_factor, так что повторно его применять не нужно.


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

**Severity:** medium · **Категория:** internal-consistency / stale aggregate (остаток после фикса #1359) · **Файл:** `backend/app/services/analytics_queries.py:2497, 2763-2764, 2768-2822, 3067` Файл: backend/app/services/analytics_queries.py — расчёт line 2497, домножение 2764, success-boost блок 2768-2822, выдача 3067. Проблема: weighted_avg_price = weighted_num/weighted_den (line 2497) считается из ДО-boost долей (share, line 2448; weighted_num/den накапливаются в цикле 2469-2470). На line 2764 домножается на combined_price_factor. В success-boost блоке (2768-2822) share_pct top-бакета поднимается на +10% (2779), остальные режутся пропорционально (2782-2787); при area_total_m2 заново считаются units_planned/revenue/total_revenue/months_to_sellout под новые доли (фикс #1359, 2793-2822). weighted_avg_price при этом НЕ пересчитывается → summary.weighted_avg_price_per_m2 (line 3067) отдаёт значение от старого микса. Комментарий 2819-2821 утверждает, что weighted_avg_price трогать не нужно — но он учитывает только то, что combined_price_factor уже зашит в per-bucket price_median_per_m2 (повторно домножать не надо). Смену ВЕСОВ-долей этот аргумент не покрывает. Импакт: weighted_avg_price — средневзвешенная по долям цена. success-boost (velocity+price-ориентированный) обычно поднимает долю более дорогого/ликвидного бакета → истинная средневзвешенная должна вырасти, но в выдаче остаётся до-boost значение. UI показывает summary.weighted_avg_price_per_m2, не совпадающую с отображёнными share_pct и per-bucket price_median_per_m2 — внутреннее противоречие отчёта. Та же логика, что #1359 чинил для units/revenue/velocity, но weighted_avg_price пропущен. Условие срабатывания: success_ranking непустой (line 2768) + area_total_m2 задан (2793) + найден top с success_score>0 и n_deals>=30. Сейчас почти не случается из-за бага [0] (пустой success_ranking), но оживёт после его фикса. Фикс: в success-boost блоке при area_total_m2 заново аккумулировать weighted_num/weighted_den по обновлённым share_pct (используя b['_area_avg_raw'] и b['price_median_per_m2']) и пересчитать weighted_avg_price = round(weighted_num/weighted_den, 2), по аналогии с пересчётом total_revenue/units на 2793-2822. **Почему баг:** weighted_avg_price — это средневзвешенная по долям цена. success-boost (велосити+цена-ориентированный) обычно поднимает долю более дорогого бакета, что должно повышать истинную средневзвешенную цену; реальная же выдача остаётся на до-boost миксе. Это та же логика рассогласования, что #1359 чинил для units/revenue/velocity, но weighted_avg_price в фиксе пропущен. UI показывает summary.weighted_avg_price_per_m2, не совпадающую с отображаемыми share_pct и per-bucket price_median_per_m2 (внутреннее противоречие отчёта). Только при area_total_m2 + сработавшем boost (что сейчас почти не случается из-за бага №1 в этом отчёте, но может ожить после его фикса). **Как чинить:** Внутри блока пересчёта (после изменения share_pct) пересобрать weighted_avg_price: weighted_avg_price = round(Σ(b['_area_avg_raw']·b['share_pct']·b['price_median_per_m2']) / Σ(b['_area_avg_raw']·b['share_pct']), 2). price_median_per_m2 уже содержит combined_price_factor, так что повторно его применять не нужно. --- <sub>deep-audit backend v2 (после PR #1543) · verify+harden, confidence 0.8 · unit B12</sub>
bot-backend added the
week ревью 1
label 2026-06-16 17:07:18 +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#1576
No description provided.