fix(tradein/estimator): честный asking_to_sold_ratio — бейдж «−N% к рынку» больше не врёт #2152
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#2152
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "fix/tradein-honest-asking-to-sold-ratio"
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?
Проблема
Оценщик клиента: «большой интервал между рекомендованной ценой и оценкой». Бейдж «−23% к рынку» (web
HeroSummary+ PDF, формулаround((1−ratio)×100)) систематически завышал скидку.Root cause
Сохранённый
asking_to_sold_ratio— СЫРОЙ per-rooms/tier дисконт изratio_resolver, но фактическийexpected_soldсдвинут относительноmedian×ratioпоследующими корректировками: hedonic year+area (#2002, factor ∈ [0.75, 1.30], ON by default),le_asking-clamp, corridor-clamp. Стор ratio НЕ пересчитывался.Прод 451de30b:
median 7.75M × raw 0.771 = 5.97M, hedonic×1.226→expected_sold 7.32M, но stored ratio остался0.771, тогда как фактexpected_sold/median = 0.945. Бейдж «−23%» вместо честных «−5%». Аналогично 4605bd18 (факт 0.871), 76539fcd (факт 0.949).Fix (модельный выбор — recompute ratio, НЕ трогаем expected_sold)
После финализации
expected_soldпересчитываем сохранённыйasking_to_sold_ratio = expected_sold_price / median_price(честный дескриптор).expected_sold(выкуп) НЕ трогаем — hedonic-uplift легитимен и остаётся прибит к sale-модели; наивныйexpected = clamped_median × raw_ratioуронил бы выкуп до ~5.97M (то, чего просили избежать). Порог_RATIO_DESCRIPTOR_EPS=1e-4отсекает шум округления → без сдвига (hedonic OFF, нет клампа) табличный ratio сохраняется байт-в-байт (регрессия отсутствует).Почему recompute-ratio, а не follow-clamp: stored
asking_to_sold_ratio— чисто ДЕСКРИПТОР (web/PDF/history badge), НЕ калибровочный вход. Калибровочный ratio живёт в таблицеasking_to_sold_ratios(refresh-task → resolver) — не тронута. Backtest #1966 скоритexpected_sold_per_m2(не stored ratio) → не затронут (expected_sold без изменений). Recompute делает бейдж честным без риска для accuracy.Читатели stored ratio (аудит)
HeroSummary+ PDF_discount_pct— badgeround((1−ratio)×100)→ теперь честный автоматически (FE не трогаю)./history+ GET/estimate— pass-through дескриптора.asking_to_sold_ratio.py— пишет ТАБЛИЦУ (source), не читает estimate-колонку → не затронут._price_from_inputs, скоритexpected_sold_per_m2→ не затронут.ДО/ПОСЛЕ (451de30b)
Follow-up (вне scope)
Corridor-clamp double-discount на
expected_sold(accuracy, не badge) — отдельная тема; vault отмечает clamp как «inert на harness», трогать под backtest-контролем.Test plan
ruff check— clean;pytest tests/— 2749 passed (кроме pre-existingtest_search_cache_hit).abs(ratio − expected/median) < 1e-3), byte-identical регрессия без сдвига.Refs #2141