fix(mera/estimate): убран предикат d.rooms в коридоре ДКП — он был вторым фильтром по площади (#3256) #3445
No reviewers
Labels
No labels
Fable 5 ревью
GG-форсайт
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
feedback/max
generative
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
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#3445
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/3256-asking-to-sold-buckets"
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?
Работа по #3256. Таблицу
asking_to_sold_ratiosне трогал — и это главный вывод, а не отказ от работы. Вместо подгонки коэффициента убран предикат, который оказался вторым фильтром по площади.Почему постановку нельзя выполнить как написано
Ось
per_area_bucket, на которой стоит критерий приёмки, слепа по построению:deals.rooms— синтетика из площади (321 559 из 321 560 сделок имеютrooms == area_bucket(area_m2),max(rooms)=4, границы точно совпадают с CASE вdeploy/import-rosreestr.sh:71-78). В обеих прод-фикстурах (1500 + 4000 целей) 0 из 5500 имеют настоящую комнатность, тогда как у реальных клиентов с ≥85 м²: 115 трёхкомнатных, 40 четырёх-, 16 пяти-, 11 шести-, 9 двух- — 79 % получают другой пул аналогов, чем харнес.«Починка» коэффициента под эту ось (+11 % к бакету 4) компенсировала бы −10 % занижения числителя харнеса и дала бы в проде переплату ~10 % по крупному жилью. Поэтому деривация не тронута; в докстринг
scripts/backtest_estimator.pyдобавлена каверза (e) с перекрёстной ссылкой на (d) — они складываются (неправильное МЕСТО + неправильный СЕГМЕНТ), обе бьют по ≥85 м².Что починено: предикат
d.roomsудалёнТак как
deals.rooms ≡ area_bucket(deals.area_m2), условиеd.rooms = <комнаты клиента>тождественно второму фильтру по площади — и он спорит с полосой ±15 %, стоящей в двух строках от него. Доля полосы, переживающей предикат:area_bucketОба ключа сжимают коридор внутрь:
p90(от неё cap) у 58 клиентов ниже более чем на 10 %,p10(от неё floor) у 68 выше более чем на 10 %. Пример: Челюскинцев 60, 1к/49 м² — p90 равен 168 632 (а) / 107 345 (б) / 154 147 (в); headline 236 085 / 150 283 / 215 806. Отрезая низ полосы, бакет выбрасывает мелкие лоты с высоким ₽/м².Замер на 1179 реальных запросах, все три пути влияния коридора
Доступность коридора:
Сдвиг headline (база — (а) на том же снимке; пути: cap/floor, sufficiency-гейт #oblast-E, deals-fallback; якорь Tier A иммунен):
Теряют цену (headline был, стал 0) — 0 в обоих вариантах.
Худший случай из ревью не подтвердился: «Белинского 86, −50 %» идёт путём якоря Tier C, где deals-fallback заблокирован гардом
anchor is None, а sufficiency-гейт headline не переписывает. Реальный эффект там — только cap: −14.2 % (б) / −9.7 % (в). Правило тонкого листинга было применено к анкерной строке: сохранённыйn_analogsу таких строк — этоanchor["n"], а не размер радиусной выборки.Настоящий худший случай общий для обоих вариантов и от выбора ключа не зависит: Малышева 84, 1к/54 м², радиусная медиана 446 366 ₽/м², коридор (а) пуст → (б)=(в) n=21, p90 185 558 → cap до 259 781 (−41.8 %). Возникает от самого появления коридора: премиальный лот прижимается к коридору обычной вторички улицы. Вынесено отдельно (#3450), это решение продукта, а не дефект правки.
Реплика замера фальсифицирована: прогнал продовый SQL для 58 оценок × 3 варианта (жирные коридоры, флип-случаи, не-ЕКБ с widen) — 174/174 совпадений по count; воспроизводит и числа предыдущего замера (809→895, 567→623), и числа ревьюера (769→850, +86/−5) из независимого кода.
Поправленные факты
min(max(rooms,0),4)затянула 27 клиентов с 5-6 комнатами). Эти 27 прироста всё равно не получают: метраж 158-456 м², в основном вне окна импортаarea BETWEEN 18 AND 200._fetch_analogs, совпадениеrooms == area_bucket: бакет 0 — 69.8 %, 1 — 63.5 %, 2 — 60.1 %, 3 — 54.6 %, 4 — 30.9 % (мода 3). Формулировка теперь «в бакетах 0-3 модальная комнатность совпадает с бакетом, в бакете 4 — нет; остальные не чисты, а лишь меньше смещены».trade_in.py:2282/:2314печаталиrooms=%dкомнатностью клиента, хотя фильтра по ней уже нет — теперь печатают фактический ключ (полосу площади).Тест-якорь против молчаливого возврата
tests/test_3256_deals_rooms_key.py::test_importer_case_still_matches_area_bucketпарситCASE … AS roomsпрямо изdeploy/import-rosreestr.shи сверяет границы сarea_bucket(); у самого CASE — комментарий-якорь с указанием вернуться в #3256. Сдвиг границы 62→60 в скрипте роняет тест (расхождение на area=61.9), замена CASE настоящей колонкой — тоже (CASE … не найден).Фальсификация основной правки: откат к пред-PR коду дал 5 failed, но
_fetch_dealsпадалTypeError(«возможности нет», а не «значение неверно»), поэтому сделана хирургическая подмена — новая сигнатура, возвращён только предикат:assert ['AND rooms = :rooms'] == []. Отдельно: тестtest_dkp_corridor_keeps_full_area_bandоставался зелёным при всех подменах, то есть не охранял ничего — усилен до «полоса единственная».Прогоны:
5747 passed, 35 skipped(rc=0); ruff чисто.Критерии приёмки issue — честно не выполнены
«Ни один бакет хуже 8 %» и «MAPE не хуже 14.28» по оси
per_area_bucketдостижимы только оракульным подбором под ту же выборку (in-sample до нулевого смещения даёт 13.38, любая принципиальная деривация 14.13-14.56) — ловушка #2255. Пока нет источника настоящей комнатности сделок, калибровка по этой оси калибрует по пулу, которого у клиента нет.fix(mera/estimate): коридор ДКП ключуется по площади, а не по синтетическим комнатам — +66 пригодных коридоров на 1177 реальных запросов (#3256)to fix(mera/estimate): убран предикат d.rooms в коридоре ДКП — он был вторым фильтром по площади (#3256)