Files
Bithumb/deepcoin/ops/alert_message.py
dsyoon c6888c9228 40만 원 기준 시뮬·dry-run 정합 및 hybrid 체결 엔진 통합.
초기 자금 GT_INITIAL_CASH_KRW=400000과 원화 한도 비율(알림·LIVE_ORDER·일한도·손실한도)을 맞추고, dry-run/live 체결을 sim_causal_hybrid(replay)와 동일 경로로 통합한다. 시뮬 리포트 갱신, Phase C 슈퍼바이저·매수매도 리허설 스크립트를 추가한다.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 11:31:24 +09:00

109 lines
3.1 KiB
Python

"""
05 규칙 알림 텔레그램 메시지 포맷.
"""
from __future__ import annotations
from typing import Any
from config import COIN_NAME, MONITOR_ALERT_KRW_AMOUNT, SYMBOL
def _fmt_krw(value: float) -> str:
"""원화 금액 표시."""
if value >= 100:
return f"{value:,.0f}"
if value >= 1:
return f"{value:,.2f}"
return f"{value:,.4f}"
def _fmt_price(value: float) -> str:
"""코인 단가 표시."""
if value >= 100:
return f"{value:,.0f}"
if value >= 10:
return f"{value:,.2f}"
if value >= 1:
return f"{value:,.3f}"
return f"{value:,.4f}"
def _holding_qty(balances: dict[str, dict[str, float]], symbol: str) -> float:
"""
잔고 dict에서 코인 보유 수량을 반환합니다.
Args:
balances: load_balances_dict() 결과.
symbol: 통화 코드 (예: WLD).
Returns:
보유 수량 (없으면 0).
"""
info = balances.get(symbol) or {}
return float(info.get("balance") or 0.0)
def build_rule_alert_message(
hit: dict[str, Any],
balances: dict[str, dict[str, float]] | None = None,
*,
trade_krw: float | None = None,
trade_qty: float | None = None,
) -> str:
"""
규칙 발화 알림 본문을 만듭니다.
trade_krw·trade_qty가 있으면 실제(모의) 체결 규모를 표시합니다.
없으면 매수는 MONITOR_ALERT_KRW_AMOUNT, 매도는 보유×가격(또는 참고 금액).
Args:
hit: evaluate_live_rules 항목 (side, rule_id, dt, close).
balances: 잔고 dict (모의·실거래).
trade_krw: 체결 원화(모의·실거래 planned/executed).
trade_qty: 체결 수량(매도 시).
Returns:
텔레그램 메시지 문자열.
"""
side = str(hit.get("side", "")).upper()
close = float(hit["close"])
rule_id = hit.get("rule_id", "")
dt = hit.get("dt", "")
qty_basis = ""
if trade_krw is not None and trade_krw > 0:
amount = float(trade_krw)
if trade_qty is not None and trade_qty > 0:
qty = float(trade_qty)
qty_basis = "체결 기준"
elif close > 0:
qty = amount / close
qty_basis = "체결 기준(원화→수량)"
else:
qty = 0.0
qty_basis = "체결 기준"
elif side == "SELL" and balances is not None:
qty = _holding_qty(balances, SYMBOL)
amount = qty * close
qty_basis = "보유 기준(체결 전)"
elif side == "BUY":
amount = float(MONITOR_ALERT_KRW_AMOUNT)
qty = amount / close if close > 0 else 0.0
qty_basis = "참고 매수 규모(알림용)"
else:
amount = float(MONITOR_ALERT_KRW_AMOUNT)
qty = amount / close if close > 0 else 0.0
qty_basis = "참고 규모(잔고 미조회)"
lines = [
f"[DeepCoin {side}] {COIN_NAME}",
f"규칙: {rule_id}",
f"시각: {dt}",
f"가격: {_fmt_price(close)}",
f"수량: {qty:,.4f} {SYMBOL} ({qty_basis})",
f"금액: {_fmt_krw(amount)}",
"※ 알림만 전송, 자동 주문 없음",
]
return "\n".join(lines)