fix(estimator): Yandex history freshness filter в price_trend (#audit-3)
_fetch_price_trend(freshness_months) — новый параметр, дефолт из settings.estimate_price_trend_max_age_months (6 мес). WHERE scraped_at > now() - N months исключает устаревшие items (yandex_valuation 2024 и т.д.) из house_placement_history fallback. houses_price_dynamics (Source 1) не затронут. psycopg v3 CAST syntax.
This commit is contained in:
parent
6b99f7d238
commit
17edac532b
1 changed files with 15 additions and 2 deletions
|
|
@ -2978,7 +2978,12 @@ async def estimate_quality(
|
||||||
freshness_min = _compute_freshness_minutes(metadata_lots)
|
freshness_min = _compute_freshness_minutes(metadata_lots)
|
||||||
last_scraped_at = _compute_last_scraped_at(metadata_lots)
|
last_scraped_at = _compute_last_scraped_at(metadata_lots)
|
||||||
# Месячный ₽/м² тренд целевого дома (web TREND chart) — best-effort, None если нет данных.
|
# Месячный ₽/м² тренд целевого дома (web TREND chart) — best-effort, None если нет данных.
|
||||||
price_trend_raw = _fetch_price_trend(db, target_house_id=target_house_id)
|
# #audit-3: передаём freshness_months из настроек — исключаем устаревшие items.
|
||||||
|
price_trend_raw = _fetch_price_trend(
|
||||||
|
db,
|
||||||
|
target_house_id=target_house_id,
|
||||||
|
freshness_months=settings.estimate_price_trend_max_age_months,
|
||||||
|
)
|
||||||
price_trend = (
|
price_trend = (
|
||||||
[PriceTrendPoint(month=p["month"], ppm2=p["ppm2"]) for p in price_trend_raw]
|
[PriceTrendPoint(month=p["month"], ppm2=p["ppm2"]) for p in price_trend_raw]
|
||||||
if price_trend_raw
|
if price_trend_raw
|
||||||
|
|
@ -3143,6 +3148,7 @@ def _fetch_price_trend(
|
||||||
target_house_id: int | None,
|
target_house_id: int | None,
|
||||||
months: int = 24,
|
months: int = 24,
|
||||||
min_points: int = 3,
|
min_points: int = 3,
|
||||||
|
freshness_months: int | None = None,
|
||||||
) -> list[dict[str, Any]] | None:
|
) -> list[dict[str, Any]] | None:
|
||||||
"""Месячный ₽/м² тренд для целевого дома (web TREND chart) — best-effort.
|
"""Месячный ₽/м² тренд для целевого дома (web TREND chart) — best-effort.
|
||||||
|
|
||||||
|
|
@ -3200,6 +3206,10 @@ def _fetch_price_trend(
|
||||||
return trend
|
return trend
|
||||||
|
|
||||||
# ── Source 2 (fallback): aggregate house_placement_history by month ──────
|
# ── Source 2 (fallback): aggregate house_placement_history by month ──────
|
||||||
|
# #audit-3: freshness_months — фильтр по scraped_at чтобы исключить стale items
|
||||||
|
# (yandex_valuation из 2024 и т.д.). Применяется ко ВСЕМ source в этом запросе
|
||||||
|
# (avito_imv + yandex_valuation), не только к yandex_valuation. Дефолт из config.
|
||||||
|
_fresh_months = freshness_months if freshness_months is not None else months
|
||||||
try:
|
try:
|
||||||
rows = (
|
rows = (
|
||||||
db.execute(
|
db.execute(
|
||||||
|
|
@ -3223,11 +3233,14 @@ def _fetch_price_trend(
|
||||||
AND COALESCE(last_price_date, start_price_date) IS NOT NULL
|
AND COALESCE(last_price_date, start_price_date) IS NOT NULL
|
||||||
AND COALESCE(last_price_date, start_price_date) > (CURRENT_DATE
|
AND COALESCE(last_price_date, start_price_date) > (CURRENT_DATE
|
||||||
- (CAST(:months AS integer) || ' months')::interval)
|
- (CAST(:months AS integer) || ' months')::interval)
|
||||||
|
AND scraped_at > (now()
|
||||||
|
- CAST(:fresh_months AS integer)
|
||||||
|
* CAST('1 month' AS interval))
|
||||||
GROUP BY 1
|
GROUP BY 1
|
||||||
ORDER BY 1 ASC
|
ORDER BY 1 ASC
|
||||||
"""
|
"""
|
||||||
),
|
),
|
||||||
{"hid": target_house_id, "months": months},
|
{"hid": target_house_id, "months": months, "fresh_months": _fresh_months},
|
||||||
)
|
)
|
||||||
.mappings()
|
.mappings()
|
||||||
.all()
|
.all()
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue