vol_breakout 멀티종목 tick, vol_live HTML 모니터, 마감 봉만 저장하는 캔들 다운로드, 텔레그램 체결 알림, cron/watch 감시 스크립트 및 테스트를 포함한다. Co-authored-by: Cursor <cursoragent@cursor.com>
88 lines
2.6 KiB
Python
88 lines
2.6 KiB
Python
#!/usr/bin/env python3
|
|
"""vol_breakout 현물 롱 — TRX/NEAR/WLD 멀티 tick (Binance 15m ATR 이식)."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import logging
|
|
import sys
|
|
import time
|
|
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.vol_breakout_runner import VolBreakoutRunner
|
|
|
|
|
|
def _configure_logging(verbose: bool) -> None:
|
|
level = logging.DEBUG if verbose else logging.INFO
|
|
logging.basicConfig(
|
|
level=level,
|
|
format="%(asctime)s [%(levelname)s] %(message)s",
|
|
datefmt="%Y-%m-%d %H:%M:%S",
|
|
)
|
|
|
|
|
|
def main() -> int:
|
|
"""CLI."""
|
|
parser = argparse.ArgumentParser(description="Bithumb vol_breakout 현물 롱 tick")
|
|
parser.add_argument("--mode", choices=("paper", "live"), default=None)
|
|
parser.add_argument("--loop", type=int, default=0, metavar="SEC")
|
|
parser.add_argument("-v", "--verbose", action="store_true")
|
|
args = parser.parse_args()
|
|
_configure_logging(args.verbose)
|
|
|
|
if args.mode:
|
|
import os
|
|
os.environ["OPS_MODE"] = args.mode
|
|
|
|
settings = load_settings()
|
|
if not settings.ops_symbols:
|
|
print("OPS_SYMBOLS 또는 DOWNLOAD_SYMBOLS(BTC 제외)가 필요합니다.", file=sys.stderr)
|
|
return 1
|
|
|
|
if settings.ops_mode == "live":
|
|
if not settings.bithumb_access_key or not settings.bithumb_secret_key:
|
|
print("live: BITHUMB_ACCESS_KEY / BITHUMB_SECRET_KEY 필요", file=sys.stderr)
|
|
return 1
|
|
print("경고: live — 실제 주문 가능")
|
|
|
|
print(
|
|
f"vol_breakout {settings.ops_mode} | symbols={settings.ops_symbols} | "
|
|
f"lookback={settings.vol_lookback} atr={settings.vol_atr_mult} "
|
|
f"buy_split={settings.vol_buy_split or settings.vol_wallet_pct} "
|
|
f"exit={settings.vol_exit_enabled}"
|
|
)
|
|
|
|
def _once() -> dict:
|
|
runner = VolBreakoutRunner(settings)
|
|
report = runner.tick()
|
|
for row in report.get("results") or []:
|
|
print(
|
|
f" {row.get('symbol')}: fills={row.get('fills')} "
|
|
f"note={row.get('note')}"
|
|
)
|
|
return report
|
|
|
|
if args.loop <= 0:
|
|
_once()
|
|
return 0
|
|
|
|
while True:
|
|
try:
|
|
_once()
|
|
except KeyboardInterrupt:
|
|
print("\n종료")
|
|
return 0
|
|
except Exception:
|
|
logging.exception("vol loop tick failed")
|
|
time.sleep(args.loop)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|