#!/usr/bin/env python3 """P0 行情连通性烟测:REST 对齐次日 ATM Call/Put,可选挂 WS 数秒。 用法(仓库根目录): python scripts/smoke_market.py python scripts/smoke_market.py --ws-seconds 8 """ from __future__ import annotations import argparse import asyncio import json import sys import time from pathlib import Path ROOT = Path(__file__).resolve().parents[1] BACKEND = ROOT / "backend" sys.path.insert(0, str(BACKEND)) from app.config import get_settings # noqa: E402 from app.market import MarketGateway # noqa: E402 async def main() -> int: parser = argparse.ArgumentParser(description="eth_hedge_sim P0 market smoke") parser.add_argument("--ws-seconds", type=float, default=5.0, help="WS listen seconds") args = parser.parse_args() settings = get_settings() print(f"MODE={settings.mode} REST={settings.okx_rest_base}") print(f"perp={settings.perp_inst_id} family={settings.option_inst_family}") gw = MarketGateway(settings) t0 = time.time() try: pair = await asyncio.to_thread(gw.align_instruments) except Exception as e: print(f"FAIL align: {e}") gw.rest.close() return 1 print(f"aligned in {time.time() - t0:.2f}s") print(json.dumps(pair.to_dict() if pair else None, ensure_ascii=False, indent=2)) snap = gw.snapshot_dict() print("--- REST snapshot ---") print(json.dumps(snap, ensure_ascii=False, indent=2)) if args.ws_seconds > 0: print(f"--- WS listen {args.ws_seconds}s ---") await gw.ws.start() await asyncio.sleep(args.ws_seconds) snap2 = gw.snapshot_dict() print(json.dumps(snap2, ensure_ascii=False, indent=2)) await gw.ws.stop() gw.rest.close() ok = ( snap.get("perp", {}) or {} ).get("ask") is not None and ( snap.get("call", {}) or {} ).get("ask") is not None and ( snap.get("put", {}) or {} ).get("ask") is not None if not ok: print("FAIL: missing bid/ask on perp/call/put") return 2 print("OK: market smoke passed") return 0 if __name__ == "__main__": raise SystemExit(asyncio.run(main()))