[P2] Кросс-источник дедуп аналогов (house+floor+area) — убрать ~19% двойного счёта #2215

Closed
opened 2026-07-02 19:19:05 +00:00 by lekss361 · 2 comments
Owner

Эпик: #2200

Находка (Data, High→P2 по объёму работы, verified): группы по (house_id_fk, floor, ROUND(area_m2)) среди активных с >1 источником = 4974 группы / 12 321 строка / 7347 лишних из 38 462 группируемых (19.1%). Baseline C-3 уже показывал ту же квартиру ×4 через avito+cian в analogs JSONB одной оценки. Per-address cap эстиматора не ловит кросс-источник.

Impact: одна физическая квартира входит в n_analogs несколько раз → завышенный confidence + медиана стянута к мульти-листингованному (агентскому) стоку.

Acceptance:

  • Кросс-источник дедуп в выборке аналогов (напр. канонизация по house+floor+~area, приоритет источника) до расчёта медианы/confidence.
  • Осторожно с ложными схлопываниями (редко разные юниты с тем же house+floor+area).
  • Проверка: n_analogs и confidence на тестовом адресе не раздуты дублями.

Scope: tradein-mvp/backend/app/services/estimator.py (_fetch_analogs/_filter_outliers), services/matching/.

Эпик: #2200 **Находка (Data, High→P2 по объёму работы, verified):** группы по `(house_id_fk, floor, ROUND(area_m2))` среди активных с >1 источником = 4974 группы / 12 321 строка / **7347 лишних** из 38 462 группируемых (19.1%). Baseline C-3 уже показывал ту же квартиру ×4 через avito+cian в analogs JSONB одной оценки. Per-address cap эстиматора не ловит кросс-источник. **Impact:** одна физическая квартира входит в n_analogs несколько раз → завышенный confidence + медиана стянута к мульти-листингованному (агентскому) стоку. **Acceptance:** - [ ] Кросс-источник дедуп в выборке аналогов (напр. канонизация по house+floor+~area, приоритет источника) до расчёта медианы/confidence. - [ ] Осторожно с ложными схлопываниями (редко разные юниты с тем же house+floor+area). - [ ] Проверка: n_analogs и confidence на тестовом адресе не раздуты дублями. Scope: `tradein-mvp/backend/app/services/estimator.py` (`_fetch_analogs`/`_filter_outliers`), `services/matching/`.
lekss361 added the
data
priority/p2
scope/backend
tradein
labels 2026-07-02 19:20:26 +00:00
Author
Owner

Проверено на текущем main (night shift): задача УЖЕ РЕШЕНА в PR #2173 (смержен до аудиторской ремедиации) — аудит снят со стейл-ветки.

  • _dedup_cross_source (#2087 H4, estimator.py:4564+) применяется на шаге 2b — ДО outlier-фильтра, медианы, confidence, n_analogs («лот считается один раз», представитель = свежайший scraped_at, relevance-порядок сохранён).
  • Защита от ложных схлопываний: физключ = (building по кадастру/норм-адресу, floor, area_bucket ±0.5м², price_bucket) — разные юниты с тем же house+floor+area почти всегда имеют разные цены и НЕ сливаются; лоты без данных для ключа не дедупятся (не сливаем неоднозначное).
  • Флаг estimate_dedup_analogs_enabled = True по умолчанию (коммит 3505a4e3), в проде активен.
  • Frozen backtest-гейт пинит флаг OFF для стабильности реплея — осознанное решение #2173.

Закрываю. Если нужен отдельный замер «двойной счёт после дедупа» на живых адресах — это уже мониторинговая задача поверх работающего механизма.

Проверено на текущем main (night shift): задача УЖЕ РЕШЕНА в PR #2173 (смержен до аудиторской ремедиации) — аудит снят со стейл-ветки. - ✅ `_dedup_cross_source` (#2087 H4, estimator.py:4564+) применяется на шаге 2b — ДО outlier-фильтра, медианы, confidence, n_analogs («лот считается один раз», представитель = свежайший scraped_at, relevance-порядок сохранён). - ✅ Защита от ложных схлопываний: физключ = (building по кадастру/норм-адресу, floor, area_bucket ±0.5м², **price_bucket**) — разные юниты с тем же house+floor+area почти всегда имеют разные цены и НЕ сливаются; лоты без данных для ключа не дедупятся (не сливаем неоднозначное). - ✅ Флаг `estimate_dedup_analogs_enabled` = **True по умолчанию** (коммит 3505a4e3), в проде активен. - Frozen backtest-гейт пинит флаг OFF для стабильности реплея — осознанное решение #2173. Закрываю. Если нужен отдельный замер «двойной счёт после дедупа» на живых адресах — это уже мониторинговая задача поверх работающего механизма.
Author
Owner

Пост-верификация (2026-07-03, адверсариальный аудит закрытий эпика #2200, read-only SQL на проде): механизм смержен, включён и корректен, но ключ «кадастр-или-raw-адрес» на реальных данных схлопывает лишь 859 из 6366 кросс-source дублей (13.5%) — 76.3% активных листингов без кадастра, а raw-адреса разных источников не унифицируются. Живая оценка d5fc3841 (после включения флага) всё ещё содержит квартиру ×3 источника в итоговых analogs.

Issue не переоткрываю (механизм — deliverable этого issue — реально поставлен); эффективность ключа вынесена в follow-up #2269 (канонизация по house_id_fk + замер до/после + backtest-гейт). Чекбокс #2215 в эпике оставлен нетикнутым до закрытия #2269.

**Пост-верификация (2026-07-03, адверсариальный аудит закрытий эпика #2200, read-only SQL на проде):** механизм смержен, включён и корректен, но ключ «кадастр-или-raw-адрес» на реальных данных схлопывает лишь **859 из 6366** кросс-source дублей (13.5%) — 76.3% активных листингов без кадастра, а raw-адреса разных источников не унифицируются. Живая оценка `d5fc3841` (после включения флага) всё ещё содержит квартиру ×3 источника в итоговых analogs. Issue не переоткрываю (механизм — deliverable этого issue — реально поставлен); эффективность ключа вынесена в follow-up **#2269** (канонизация по `house_id_fk` + замер до/после + backtest-гейт). Чекбокс #2215 в эпике оставлен нетикнутым до закрытия #2269.
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#2215
No description provided.