feat(vol_breakout): 15m 현물 롱 라이브·모니터·cron 운영 추가
vol_breakout 멀티종목 tick, vol_live HTML 모니터, 마감 봉만 저장하는 캔들 다운로드, 텔레그램 체결 알림, cron/watch 감시 스크립트 및 테스트를 포함한다. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
78
scripts/3_reconcile_signals.py
Normal file
78
scripts/3_reconcile_signals.py
Normal file
@@ -0,0 +1,78 @@
|
||||
#!/usr/bin/env python3
|
||||
"""ledger backlog 신호 조회·일괄 처리 (dry-run / execute)."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
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.reconcile import inspect_ops_backlog
|
||||
from bithumb.operations.runner import OperationsRunner
|
||||
|
||||
|
||||
def main() -> int:
|
||||
"""CLI 진입점."""
|
||||
parser = argparse.ArgumentParser(description="운영 backlog 신호 reconcile")
|
||||
parser.add_argument(
|
||||
"--dry-run",
|
||||
action="store_true",
|
||||
help="pending 목록만 출력 (기본)",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--execute",
|
||||
action="store_true",
|
||||
help="OperationsRunner tick 1회로 backlog 처리",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--no-sync",
|
||||
action="store_true",
|
||||
help="execute 시 캔들 sync 생략",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
settings = load_settings()
|
||||
info = inspect_ops_backlog(settings)
|
||||
merged = info["merged_pending"]
|
||||
summary = info["summary"]
|
||||
|
||||
print("=== backlog inspect ===")
|
||||
print(f"signal_refresh: {info.get('signal_refresh')}")
|
||||
print(f"force_tail_refresh: {info.get('force_tail_refresh')}")
|
||||
print(f"ledger_pending: {len(info['ledger_pending'])}")
|
||||
print(f"catchup_pending: {len(info['catchup_pending'])}")
|
||||
print(f"merged_pending: {len(merged)}")
|
||||
print(f"backlog_signal_count: {summary['backlog_signal_count']}")
|
||||
print(f"backlog_oldest: {summary['backlog_oldest_datetime']}")
|
||||
print(f"backlog_dropped (per tick limit): {info['backlog_dropped']}")
|
||||
|
||||
for sig in merged[:50]:
|
||||
print(f" {sig['datetime']} {sig['side']} bar={sig.get('bar_index')}")
|
||||
if len(merged) > 50:
|
||||
print(f" ... 외 {len(merged) - 50}건")
|
||||
|
||||
if args.execute:
|
||||
from bithumb.operations.runner import OperationsRunner as OpsRunner
|
||||
|
||||
if settings.ops_mode == "live":
|
||||
print("\n경고: live execute — 실제 주문이 발생할 수 있습니다.")
|
||||
runner = OpsRunner(settings)
|
||||
report = runner.tick(sync_candles=not args.no_sync)
|
||||
print(f"\nexecute 완료: 체결 {len(report.get('executions', []))}건")
|
||||
print(f"ledger_pending_count: {report.get('ledger_pending_count')}")
|
||||
print(f"backlog_dropped_count: {report.get('backlog_dropped_count')}")
|
||||
return 0
|
||||
|
||||
if not args.dry_run and not args.execute:
|
||||
print("\n(--dry-run 기본, --execute 로 처리)")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
raise SystemExit(main())
|
||||
Reference in New Issue
Block a user