diff --git a/core/notify.py b/core/notify.py index 4526382..493af0a 100644 --- a/core/notify.py +++ b/core/notify.py @@ -9,19 +9,19 @@ import requests logger = logging.getLogger(__name__) -_TOKEN = os.getenv("TELEGRAM_TRADE_TOKEN", "") -_CHAT_ID = os.getenv("TELEGRAM_CHAT_ID", "") _API = "https://api.telegram.org/bot{token}/sendMessage" def _send(text: str) -> None: - if not _TOKEN or not _CHAT_ID: + token = os.getenv("TELEGRAM_TRADE_TOKEN", "") + chat_id = os.getenv("TELEGRAM_CHAT_ID", "") + if not token or not chat_id: logger.warning("Telegram 설정 없음, 알림 스킵") return try: requests.post( - _API.format(token=_TOKEN), - json={"chat_id": _CHAT_ID, "text": text, "parse_mode": "HTML"}, + _API.format(token=token), + json={"chat_id": chat_id, "text": text, "parse_mode": "HTML"}, timeout=5, ) except Exception as e: diff --git a/core/trader.py b/core/trader.py index 22786ec..32d7818 100644 --- a/core/trader.py +++ b/core/trader.py @@ -39,6 +39,38 @@ def get_positions() -> dict: return _positions +def restore_positions() -> None: + """시작 시 Upbit 실제 잔고를 읽어 포지션 복원 (재시작 이중 매수 방지).""" + upbit = _get_upbit() + balances = upbit.get_balances() + for b in balances: + currency = b["currency"] + if currency == "KRW": + continue + amount = float(b["balance"]) + float(b["locked"]) + if amount <= 0: + continue + ticker = f"KRW-{currency}" + current = pyupbit.get_current_price(ticker) + if not current: + continue + invested_krw = int(amount * current) + if invested_krw < 1_000: # 소액 잔고 무시 + continue + with _lock: + _positions[ticker] = { + "buy_price": current, # 정확한 매수가 불명 → 현재가로 초기화 + "peak_price": current, + "amount": amount, + "invested_krw": min(invested_krw, PER_POSITION), + "entry_time": datetime.now(), + } + logger.info( + f"[복원] {ticker} 수량={amount} | 현재가={current:,.0f}원 " + f"(재시작 시 복원, 매수가 불명으로 현재가 기준)" + ) + + def buy(ticker: str) -> bool: """시장가 매수. 예산·포지션 수 확인 후 진입.""" with _lock: diff --git a/main.py b/main.py index e9933de..96c78d0 100644 --- a/main.py +++ b/main.py @@ -17,10 +17,14 @@ logging.basicConfig( ) from core.monitor import run_monitor +from core.trader import restore_positions from daemon.runner import run_scanner def main() -> None: + # 재시작 시 기존 잔고 복원 (이중 매수 방지) + restore_positions() + # 트레일링 스탑 감시 스레드 (10초 주기) monitor_thread = threading.Thread( target=run_monitor, args=(10,), daemon=True, name="monitor"