from __future__ import annotations from datetime import datetime from zoneinfo import ZoneInfo from app.market.instruments import ( next_session_expiry_ymd, parse_option_inst_id, pick_atm_strike, select_option_pair, ) _SH = ZoneInfo("Asia/Shanghai") def test_parse_option_inst_id() -> None: y, s, o = parse_option_inst_id("ETH-USD_UM-260725-3500-C") assert y == "260725" assert s == 3500.0 assert o == "C" def test_pick_atm_strike() -> None: assert pick_atm_strike([3400, 3500, 3600], 3510) == 3500 def test_next_session_expiry_before_open() -> None: now = datetime(2026, 7, 24, 15, 0, tzinfo=_SH) assert next_session_expiry_ymd(now) == "260724" def test_next_session_expiry_after_open() -> None: now = datetime(2026, 7, 24, 16, 0, tzinfo=_SH) assert next_session_expiry_ymd(now) == "260725" def test_select_option_pair_atm() -> None: rows = [ {"instId": "ETH-USD_UM-260725-3490-C", "state": "live"}, {"instId": "ETH-USD_UM-260725-3490-P", "state": "live"}, {"instId": "ETH-USD_UM-260725-3500-C", "state": "live"}, {"instId": "ETH-USD_UM-260725-3500-P", "state": "live"}, {"instId": "ETH-USD_UM-260726-3500-C", "state": "live"}, {"instId": "ETH-USD_UM-260726-3500-P", "state": "live"}, ] pair = select_option_pair(rows, mark_px=3502, expiry_ymd="260725") assert pair is not None assert pair.strike == 3500 assert pair.call_inst_id.endswith("-3500-C") assert pair.put_inst_id.endswith("-3500-P")