fix(tradein/estimate): убрать квартал соседа из квартального индекса (координатный резолв — за флагом OFF) #2839

Merged
bot-backend merged 3 commits from fix/quarter-target-from-neighbour into main 2026-08-12 15:55:25 +00:00

3 commits

Author SHA1 Message Date
b13880ff15 fix(tradein/estimate): координатный резолв квартала — за флагом OFF, порог 25 м
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI / changes (pull_request) Successful in 9s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 3m58s
CI Trade-In / browser-tests (pull_request) Has been skipped
Точность самого резолва измерена против НЕЗАВИСИМОЙ истины: 2398 домов ЕКБ, где
квартал известен из кадастра DaData (ответ на адрес, а не KNN-подсказка — см.
house_dedup_merge.py:126; вырожденный 66:41:0000000 у 146 домов исключён).

  порог   ответ выдан   чужой квартал   точность   покрытие
   15 м        475            26          94.5%      19.8%
   25 м        748            59          92.1%      31.2%
   50 м       1341           271          79.8%      55.9%
  100 м       2090           644          69.2%      87.2%

Порог 50 м, заимствованный у cadastral_geo_match, замером НЕ подтверждён: каждый
пятый ответ — чужой квартал, а промах стоит 1.111× по медиане и 1.447× в p90
(отношение индексов чужого и своего квартала). Порог 25 м обоснован замером.

Разделение: снятие фолбэка на кадастр аналога поставляется включённым (измерено
бэктестом, −0.55 пп MAPE), координатный резолв — за
estimate_quarter_from_coords_enabled=False. Причина: точность РЕЗОЛВА измерена,
эффект поправки на точность ЦЕНЫ — нет (фикстура гейта идёт с
target_house_cadnum=None и координатный путь не проходит). Критерий приёмки и
дата-предохранитель (2026-09-12) записаны в config рядом с флагом.

На рабочем тракте (координаты оценок, а не домов справочника) точность ниже:
из 20 оценок со своим кадастром ответ в 50 м выдан 9 раз, совпал 3; в 25 м —
3 ответа, 3 совпадения. Попадания на 0-4 м, промахи на 32-39 м. Один из промахов —
Малышева 84, тот самый кейс, где координатный квартал двигал цену на −20.6%.
2026-08-12 20:48:34 +05:00
86cb294949 test(tradein/backtest): эталон гейта после снятия квартала соседа
All checks were successful
CI Trade-In / changes (pull_request) Successful in 13s
CI / changes (pull_request) Successful in 13s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 4m6s
Гейт `test_backtest_regression_gate` реплеит замороженную фикстуру (277 сделок)
прямо через `_price_from_inputs` с `target_house_cadnum=None`, минуя
`estimate_quality`. То есть на фикстуре меряется ровно снятие поправки по кварталу
СОСЕДА (координатный резолв в реплей не попадает — его делает вызывающий код).

Затронуто 30 сделок из 277 (10.8% — сходится с прод-оценкой поверхности ~10%);
множитель цены стало/было: min 0.704, медиана 1.019, max 1.661 (17 вверх / 13 вниз).

Сдвиг метрик (эталон → стало):
  expected_sold.overall.mape_pct   13.18 → 12.63  (−0.55)
  calibration.low.mape_pct          13.2 → 12.67  (−0.53)
  студии mape                      19.38 → 16.96  (−2.42)
  3к mape                           9.34 →  7.79  (−1.55)
  2к mape                          18.26 → 17.39  (−0.87)
  комфорт mape                     11.80 → 10.14  (−1.66)
  бизнес mape                      14.65 → 13.65  (−1.00)
УХУДШИЛОСЬ:
  эконом mape                      13.71 → 14.20  (+0.49), bias 2.54 → 3.33
  4+ mape                          16.30 → 16.38  (+0.08), bias 3.34 → −1.32
  хвосты: студии p75 34.32 → 38.82, бизнес p25 −22.93 → −27.15

Покрытие (82.09/82.16), sharpness (0.743), n по всем бакетам и headline не менялись.
Атрибуция: на origin/main регенерация тем же путём даёт эталон байт-в-байт,
расхождение появляется ровно от правки резолва квартала.
2026-08-12 20:35:52 +05:00
2bf9e76a10 fix(tradein/estimate): квартал цели — по её координатам, а не из кадастра аналога
Some checks failed
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Failing after 3m57s
CI Trade-In / changes (pull_request) Successful in 8s
CI / changes (pull_request) Successful in 8s
CI Trade-In / frontend-checks (pull_request) Has been skipped
`target_quarter` для квартального индекса (#764) резолвился так: свой кадастр
цели (DaData) → а если пусто, кадастр ПЕРВОГО аналога с кадастром. Пусто оно
в 15 из 15 применений на проде, то есть «индекс квартала цели» на витрине
всегда был индексом квартала соседа.

Замер 2026-08-12 (прод, 1081 оценка):
- 15/15 применений — house_cadnum пуст; аналог-донор квартала стоял в 201-4087 м
  от цели (медиана ~580 м);
- индексы кварталов на такой дистанции расходятся в 1.15-1.23 раза по медиане
  и в 1.6-1.8 по p90 → множитель на витрине был чужой;
- индекс при этом НЕ шум: корреляция с независимой медианой живых объявлений
  того же квартала r(log)=0.84 (307 кварталов), 0.88 на плотных (n_deals>=50) —
  поэтому чужой квартал это реальный сдвиг цены, а не безобидная неточность.

Фикс: квартал цели снимается по СОБСТВЕННЫМ координатам цели — ближайшее здание
в cad_buildings_local (ЕКБ-зеркало Росреестра, 47 111 зданий) в пределах 50 м,
тем же geo-nearest приёмом и с тем же порогом, каким уже заполняется
listings.building_cadastral_number (tasks/cadastral_geo_match). Нет здания
в 50 м → поправки нет: это честнее, чем взять квартал соседа.

Эффект на 15 исторических применений: 7 теряют поправку (ближайшее здание
59-180 м), 8 пересчитываются от своего квартала; диапазон изменения цены
−25.0% … +66.7%.
2026-08-12 20:15:16 +05:00