3분~일봉 GT 타점 분석(03c), leg 체결 순서 수정, 총자산 90% 검증 루프, walk-forward Go/No-Go 시뮬, monitor·live_trader 및 reference 문서를 포함한다. Co-authored-by: Cursor <cursoragent@cursor.com>
93 lines
2.5 KiB
Python
93 lines
2.5 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,
|
||
) -> str:
|
||
"""
|
||
규칙 발화 알림 본문을 만듭니다.
|
||
|
||
매수: MONITOR_ALERT_KRW_AMOUNT 기준 수량·금액.
|
||
매도: 보유 수량(잔고 조회 가능 시) × 가격 = 금액, 없으면 참고 금액 기준.
|
||
|
||
Args:
|
||
hit: evaluate_live_rules 항목 (side, rule_id, dt, close).
|
||
balances: 빗썸 잔고 dict. None이면 매도도 참고 금액 기준.
|
||
|
||
Returns:
|
||
텔레그램 메시지 문자열.
|
||
"""
|
||
side = str(hit.get("side", "")).upper()
|
||
close = float(hit["close"])
|
||
rule_id = hit.get("rule_id", "")
|
||
dt = hit.get("dt", "")
|
||
|
||
qty_basis = ""
|
||
if 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)
|