fix(tradein/location): заменить сломанный коэффициент локации на калиброванный индекс #2531
No reviewers
Labels
No labels
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
Fable 5 ревью
feedback/max
generative
GG-форсайт
needs-discussion
needs-human
observability
pause-bots
performance
priority/p0
priority/p1
priority/p2
priority/p3
scope/backend
scope/db
scope/devops
scope/frontend
scope/qa
scrapers
security
site-finder
stage/1
stage/2
status/blocked
status/done
status/needs-analysis
status/needs-fix
status/qa
status/ready
status/review
status/wip
tech-debt
tradein
ux
week ревью 1
wontfix
вторичка
ИРД
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#2531
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/tradein-location-index-calibration"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Жалоба пользователя: «коэффициент локации всегда 0». Разбор показал три разные проблемы, из которых жалоба — самая безобидная.
Замеры на боевой БД
1. Схлопывание в ноль. По 1500 адресам ЕКБ 67% попадают в −1%…+1%, ровно 0% показывается почти четверти. Весь город умещается в −4%…+5%, размах 1,10×. Это не случайность: нормировка подбиралась так, чтобы «сильный центр ≈ 1.0».
2. Связи с ценой нет. По 4000 активных лотов медиана ₽/м² по бакетам коэффициента плоская и немонотонная:
Бакет −4% дороже бакета +3%.
3. Масштаб не тот на порядок. Одна тривиальная переменная — расстояние до центра — даёт монотонный градиент по 31 тыс. лотов: 249 686 ₽/м² в центре против 93 677 на краю, размах 2,70×. Реальный сигнал локации примерно в 25 раз шире того, что формула способна выразить.
Ключевой факт
Коэффициент никогда не влиял на цену — в
estimator.pyноль упоминанийlocation_coef. При этом панель «КАК РАССЧИТАНО» рисовала пару «база → результат» (result_price_rub = round(base_price_rub * coef)), обещая клиенту влияние, которого нет.Что сделано
Новый показатель — отклонение медианы ₽/м² сопоставимых активных объявлений в радиусе от медианы по городу (
percentile_cont, лестница радиусов 800/1500/2500 м до набора выборки ≥20). Диапазон искусственно не зажимается. В цену по-прежнему не идёт и идти не должен: аналоги берутся из того же района, локация в базовой цене уже учтена — умножение дало бы двойной учёт и систематическое завышение центра.Честная деградация вместо молчаливого вырождения в 0.95:
out_of_coverage(адрес вне ЕКБ) иinsufficient_data(мало сопоставимых) — разные, объяснённые состояния.Контракт:
/location-coef→/location-index; убраныcoef,base_price_rub,result_price_rub,weight.Тексты: «КОЭФ. ЛОКАЦИИ» → «ЛОКАЦИЯ», в подсказке прямо: «Сравнение медианы ₽/м² района и города. На итоговую оценку не влияет.»
Попутно: потеря 46% точек интереса
Разбираясь, почему признак не работает, нашли причину глубже.
v_tradein_osm_poi_ekbрезала всё, что не редактировали в OSM два года. Замерено на проде: из 5133 точек доходило 2787. Потеря систематически смещена — режет стабильную инфраструктуру и не трогает часто правимую:Из девяти станций метро терялись четыре, включая Площадь 1905 года — центральную. У всех четырёх
last_osm_edit_date— февраль 2023.Это объясняет и провал самого коэффициента: в зеркале осталось 1020 остановок из 2787 точек, то есть «взвешенный счёт по семи POI» вырождался в «сколько рядом остановок».
Требование свежести задумывалось как мягкий сигнал уверенности — Site Finder так его и использует (
parcels.pyтолько понижает confidence-подscore, ни одной точки не выбрасывает). Расхождение возникло во view для trade-in при постройке FDW-моста. Миграция188_tradein_osm_poi_view_relax_freshness.sqlубирает фильтр. Плюс вpoi_loader.pyрасширен Overpass-фильтр метро: ловил толькоstation=subway, добавлена комбинацияrailway=station + subway=yes.Test plan
uv run pytest -q— 2633 passed, 8 skipped (33 новых теста: деградация вне ЕКБ, недостаточная выборка на каждом уровне лестницы, устойчивость к выбросам, монотонность на синтетике, IDOR эндпоинта)ruff checkчерезuv runс проектным конфигом — чистоnpx tsc --noEmit— чисто, грепом подтверждено 0 живых упоминаний старого контрактаosm_poi_ekb_refreshна tradein):SELECT category, count(*) FROM osm_poi_ekb_local GROUP BY category— метро должно стать 9, общее число вырасти примерно вдвое