"""空仓选约:跳过历史上已用到期与残留待结算到期。""" from __future__ import annotations from datetime import datetime from zoneinfo import ZoneInfo from app.strategy.clock import ( expiry_blocked_by_one_per_day, pending_residual_expiry_ymds, used_expiry_ymds, ) class _FakeDB: def __init__( self, *, groups: list[dict] | None = None, residuals: list[dict] | None = None, ) -> None: self._groups = groups or [] self._residuals = residuals or [] def fetchall(self, sql: str, params: tuple = ()) -> list[dict]: s = " ".join(sql.split()).lower() if "from groups" in s: return [ r for r in self._groups if str(r.get("expiry_ymd") or "").strip() ] if "from residual_options" in s: return [r for r in self._residuals if r.get("status") == "pending"] return [] def test_used_expiry_ymds_across_calendar_days() -> None: """8.2 开过 260803 后,8.3 零点仍须拦截同到期。""" db = _FakeDB( groups=[ {"group_id": "G-20260802-01", "expiry_ymd": "260803"}, {"group_id": "G-20260801-01", "expiry_ymd": "260802"}, ] ) now_aug3 = datetime(2026, 8, 3, 0, 0, 2, tzinfo=ZoneInfo("Asia/Shanghai")) used = used_expiry_ymds(db, now_aug3) assert used == {"260803", "260802"} assert expiry_blocked_by_one_per_day("260803", used, enabled=True) assert not expiry_blocked_by_one_per_day("260804", used, enabled=True) def test_pending_residual_expiry_ymds() -> None: db = _FakeDB( residuals=[ {"expiry_ymd": "260803", "status": "pending"}, {"expiry_ymd": "260802", "status": "settled"}, {"expiry_ymd": "", "status": "pending"}, ] ) assert pending_residual_expiry_ymds(db) == {"260803"}