fix(forecasting): wrap long lines, guard window_months=0, correct base_pace fallback comment (#1593 review)
Some checks failed
CI / backend-tests (push) Has been cancelled
CI / frontend-tests (push) Has been cancelled
CI / openapi-codegen-check (push) Has been cancelled
CI / changes (push) Has been cancelled
CI / backend-tests (pull_request) Has been cancelled
CI / changes (pull_request) Has been cancelled
CI / openapi-codegen-check (pull_request) Has been cancelled
CI / frontend-tests (pull_request) Has been cancelled
Some checks failed
CI / backend-tests (push) Has been cancelled
CI / frontend-tests (push) Has been cancelled
CI / openapi-codegen-check (push) Has been cancelled
CI / changes (push) Has been cancelled
CI / backend-tests (pull_request) Has been cancelled
CI / changes (pull_request) Has been cancelled
CI / openapi-codegen-check (pull_request) Has been cancelled
CI / frontend-tests (pull_request) Has been cancelled
- Add window_months > 0 guard to vel_by_room dict comprehension (mirrors _monthly_rate) - Correct outer comment in recommendation.py: honest-zero for known-zero buckets, fallback only when velocity_by_room=None or bucket absent from _FORECAST_TO_METRIC_BUCKETS - Add comment in as_dict() noting velocity_by_room is intentionally not serialized (internal pipeline attr consumed directly by recommendation.py)
This commit is contained in:
parent
cc6ef80d07
commit
ec0d80c1e9
2 changed files with 7 additions and 3 deletions
|
|
@ -637,8 +637,9 @@ def _demand_only_overlay(
|
|||
# §9.2 #1593: per-bucket velocity из velocity_by_room (objective_lots
|
||||
# per комнатность). _FORECAST_TO_METRIC_BUCKETS даёт список metric-ключей
|
||||
# для данного forecast_bucket ("80+ м²" = "4"+"5+"). Суммируем ед./мес по
|
||||
# бакетам. Если velocity_by_room отсутствует ИЛИ все нужные бакеты нулевые
|
||||
# — fallback на агрегатный base_pace (лучше, чем 0-сигнал).
|
||||
# бакетам. Честный 0 при известных бакетах — НЕ fallback. Fallback на
|
||||
# агрегатный base_pace только когда velocity_by_room=None (пустая
|
||||
# выборка) или bucket неизвестен в _FORECAST_TO_METRIC_BUCKETS.
|
||||
metric_keys = _FORECAST_TO_METRIC_BUCKETS.get(forecast_bucket, [])
|
||||
if vel_by_room is not None and metric_keys:
|
||||
bucket_velocity: float = sum(vel_by_room.get(k, 0.0) for k in metric_keys)
|
||||
|
|
|
|||
|
|
@ -140,6 +140,8 @@ class MarketMetrics:
|
|||
"demand_concentration": _round_or_none(self.demand_concentration, 3),
|
||||
"price_sensitivity": _round_or_none(self.price_sensitivity, 4),
|
||||
"price_sensitivity_source": self.price_sensitivity_source,
|
||||
# velocity_by_room намеренно не сериализуется: это внутренний
|
||||
# pipeline-атрибут (потребляется recommendation.py напрямую).
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -416,9 +418,10 @@ def compute_market_metrics(
|
|||
# #1593: per-bucket velocity — ед./мес по каждой комнатности. Ключи зеркалят
|
||||
# _room_bucket() ("студия","1","2","3","4","5+"). При has_sample=False нет
|
||||
# смысла делить 0 лотов → None (graceful, зеркало unit_velocity поведения).
|
||||
# window_months > 0 защищает от ZeroDivisionError (зеркало _monthly_rate()).
|
||||
vel_by_room: dict[str, float] | None = (
|
||||
{bkt: float(cnt) / float(window_months) for bkt, cnt in sold_by_room.items()}
|
||||
if has_sample and sold_by_room
|
||||
if has_sample and sold_by_room and window_months > 0
|
||||
else None
|
||||
)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue