asking_to_sold_ratios (миграция 080) считался ИСКЛЮЧИТЕЛЬНО по рынку Екатеринбурга
(деривация фильтровала обе стороны на city ILIKE '%Екатеринбург%'), а estimator
читал строку только по rooms_bucket/district и применял этот коэффициент к любому
адресу — включая Москву и Московскую область, чей рынок дороже на порядок (медиана
ДКП за 12 мес: 66 - 90 278 руб/кв.м, 50 - 161 176, 77 - 322 976).
Миграция 304 добавляет asking_to_sold_ratios.region_code (существующие 6 строк -
регион 66) и перестраивает PK на (region_code, rooms_bucket, district).
app/tasks/asking_to_sold_ratio.py: деривация региона 66 осталась байт-в-байт прежней
(та же городская квота, тот же порог 30/30, то же окно 12 мес) - числа для 66 не
меняются. Для каждого региона из реестра app.services.regions (кроме 66) добавлен
отдельный derivation-путь, симметрично скоупленный по region_code без городской
квоты (она была костылём конкретно исторического asking-покрытия ЕКБ).
app/services/estimator.py: _get_asking_sold_ratio теперь получает region_code цели
(target_region_code, тот же код, что уже скоупит ДКП-коридор) и ищет строку по нему;
кэш ключуется на (region_code, bucket), а не на голый bucket. Регион без единой
строки (ни per-bucket, ни global -1) деградирует явно - (None, None), без подмены
чужим региональным коэффициентом - ratio_basis в ответе честно остаётся None.