#!/usr/bin/env python3 """live 운영 전 사전 점검 — API·잔고·캐시·텔레그램.""" from __future__ import annotations import argparse import json import sys from pathlib import Path ROOT = Path(__file__).resolve().parents[1] SRC = ROOT / "src" if str(SRC) not in sys.path: sys.path.insert(0, str(SRC)) from bithumb.config import load_settings from bithumb.operations.live_bootstrap import run_preflight, save_preflight_report def main() -> int: """CLI 진입점.""" parser = argparse.ArgumentParser(description="Bithumb live 사전 점검") parser.add_argument( "--report", default="docs/spot/3_operations/live_preflight_report.json", help="점검 결과 JSON 경로", ) parser.add_argument( "--require-live", action="store_true", help="OPS_MODE=live 가 아니면 실패", ) args = parser.parse_args() settings = load_settings() if args.require_live and settings.ops_mode != "live": print(f"OPS_MODE={settings.ops_mode} — live 전환 후 다시 실행하세요.", file=sys.stderr) return 1 report = run_preflight(settings) report_path = save_preflight_report( ROOT / args.report if not Path(args.report).is_absolute() else Path(args.report), report, ) print("=== Bithumb live 사전 점검 ===") print(f"기법: {report['technique_id']} · 마켓: {report['market']} · 모드: {report['mode']}") if report.get("balances"): bal = report["balances"] print( f"잔고: KRW {bal['cash_krw']:,.0f}원 · " f"{report['symbol']} {bal['coin_qty']:.8f}" ) print() for row in report["checks"]: mark = "OK" if row["passed"] else "NG" req = "필수" if row["required"] else "선택" print(f"[{mark}] ({req}) {row['name']}: {row['detail']}") print(f"\n리포트: {report_path}") if report["ok"]: print("\n사전 점검 통과 — live 운영을 시작할 수 있습니다.") return 0 print("\n사전 점검 실패 — live 시작 전 위 항목을 해결하세요.", file=sys.stderr) return 1 if __name__ == "__main__": raise SystemExit(main())