from datetime import datetime from zoneinfo import ZoneInfo from lib.trade.force_close_lib import ( build_force_close_state, compute_next_force_close_at_ms, force_close_label, format_force_close_countdown, is_force_close_active_hour, ) TZ = ZoneInfo("Asia/Shanghai") def _ms(y, m, d, hh, mm=0): return int(datetime(y, m, d, hh, mm, tzinfo=TZ).timestamp() * 1000) def test_force_close_label(): assert force_close_label(0) == "强制清仓 00:00" assert force_close_label(8) == "强制清仓 08:00" def test_next_force_close_at_midnight(): # 2026-07-05 23:30 -> next 2026-07-06 00:00 now = _ms(2026, 7, 5, 23, 30) assert compute_next_force_close_at_ms(bj_hour=0, now_ms=now, tz_name="Asia/Shanghai") == _ms( 2026, 7, 6, 0, 0 ) def test_next_force_close_same_day_before_hour(): now = _ms(2026, 7, 6, 15, 0) assert compute_next_force_close_at_ms(bj_hour=0, now_ms=now, tz_name="Asia/Shanghai") == _ms( 2026, 7, 7, 0, 0 ) def test_active_hour_and_countdown(): now = _ms(2026, 7, 6, 0, 15) assert is_force_close_active_hour(0, now_ms=now, tz_name="Asia/Shanghai") state = build_force_close_state(True, 0, now_ms=now, tz_name="Asia/Shanghai") assert state["enabled"] is True assert state["active"] is True assert state["countdown"] == "执行中" assert state["remaining_sec"] == 0 def test_disabled_state(): state = build_force_close_state(False, 0) assert state["enabled"] is False assert state["next_at_ms"] is None def test_format_countdown(): assert format_force_close_countdown(3661) == "01:01:01" assert format_force_close_countdown(0, active=True) == "执行中"