fix(competitors): _AVG_PRICE_SQL — фильтр latest snapshot (#1210) #1264

Merged
bot-backend merged 1 commit from fix/competitors-avg-price-latest-snapshot into main 2026-06-13 06:17:27 +00:00
Collaborator

Summary

Closes #1210 (P2 correctness, prod). _AVG_PRICE_SQL усреднял историю цен и считал sold ×N снапшотов → Competitor.avg_price_per_m2 stale, sold_pct кратно завышен.

Bug

domrf_kn_flats версионируется (UNIQUE(id, snapshot_date), м.50), scraper UPSERT per snapshot. _AVG_PRICE_SQL:443 — без snapshot фильтра:

  • AVG(price_per_m2) усредняет ВСЕ снапшоты → stale на растущем рынке (UI Competitor.avg_price_per_m2 + вход _price_similarity).
  • COUNT '%прод%' считает квартиру ×N раз (по разу на снапшот) → raw_sold/flat_count кратно завышен → либо попадает в гард-нейтраль 0.5, либо искажает stage_at_horizon как ×N-завышенный sold_pct.

Соседи фильтруют latest (best_layouts._SUPPLY_BATCH_SQL, _COMPETITORS_SQL DISTINCT ON) — здесь нет.

Fix

WHERE f.obj_id = ANY(:obj_ids)
  AND f.snapshot_date = (SELECT MAX(snapshot_date) FROM domrf_kn_flats)

Зеркало паттерна best_layouts._SUPPLY_BATCH_SQL.

Test plan

  • pytest -k competitors51 passed, 3 skipped.
  • ruff check → clean.

Closes #1210

## Summary Closes #1210 (P2 correctness, prod). `_AVG_PRICE_SQL` усреднял **историю** цен и считал sold ×N снапшотов → Competitor.avg_price_per_m2 stale, sold_pct кратно завышен. ## Bug `domrf_kn_flats` версионируется (`UNIQUE(id, snapshot_date)`, м.50), scraper UPSERT per snapshot. `_AVG_PRICE_SQL:443` — без snapshot фильтра: - `AVG(price_per_m2)` усредняет ВСЕ снапшоты → stale на растущем рынке (UI Competitor.avg_price_per_m2 + вход `_price_similarity`). - `COUNT '%прод%'` считает квартиру ×N раз (по разу на снапшот) → `raw_sold/flat_count` кратно завышен → либо попадает в гард-нейтраль 0.5, либо искажает `stage_at_horizon` как ×N-завышенный `sold_pct`. Соседи фильтруют latest (`best_layouts._SUPPLY_BATCH_SQL`, `_COMPETITORS_SQL DISTINCT ON`) — здесь нет. ## Fix ```sql WHERE f.obj_id = ANY(:obj_ids) AND f.snapshot_date = (SELECT MAX(snapshot_date) FROM domrf_kn_flats) ``` Зеркало паттерна `best_layouts._SUPPLY_BATCH_SQL`. ## Test plan - [x] `pytest -k competitors` → **51 passed, 3 skipped**. - [x] `ruff check` → clean. Closes #1210
bot-backend added 1 commit 2026-06-13 06:07:19 +00:00
fix(competitors): _AVG_PRICE_SQL — фильтр latest snapshot (#1210)
All checks were successful
CI / changes (push) Successful in 6s
CI / changes (pull_request) Successful in 6s
CI / frontend-tests (push) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / backend-tests (push) Successful in 6m30s
CI / backend-tests (pull_request) Successful in 6m27s
c1257b2671
domrf_kn_flats версионируется (UNIQUE(id, snapshot_date), м.50), scraper
UPSERT per snapshot — то же что для domrf_kn_objects (которое в L3 supply
после #1212 берём только latest). _AVG_PRICE_SQL фильтра snapshot_date НЕ
имел → AVG усреднял ИСТОРИЮ цен (stale на растущем рынке) → UI-поле
Competitor.avg_price_per_m2 + вход _price_similarity получали устаревшую
цену. COUNT '%прод%' множил sold ×N снапшотов → raw_sold/flat_count кратно
завышен → попадал в гард-нейтраль 0.5 или искажал stage_at_horizon как
×N-завышенный sold_pct.

Patch: WHERE f.snapshot_date = (SELECT MAX(snapshot_date) FROM domrf_kn_flats).
Зеркало паттерна best_layouts._SUPPLY_BATCH_SQL и _COMPETITORS_SQL DISTINCT ON
(уже было latest). 51/51 competitors-тестов зелёные.

Closes #1210
bot-backend merged commit ddbd924b02 into main 2026-06-13 06:17:27 +00:00
bot-backend deleted branch fix/competitors-avg-price-latest-snapshot 2026-06-13 06:17:27 +00:00
Sign in to join this conversation.
No reviewers
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#1264
No description provided.