GT MTF 프로필·캘리브레이션과 04 매칭/시뮬/실거래 파이프라인을 추가한다.
3분~일봉 GT 타점 분석(03c), leg 체결 순서 수정, 총자산 90% 검증 루프, walk-forward Go/No-Go 시뮬, monitor·live_trader 및 reference 문서를 포함한다. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
92
deepcoin/ops/alert_message.py
Normal file
92
deepcoin/ops/alert_message.py
Normal file
@@ -0,0 +1,92 @@
|
||||
"""
|
||||
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)
|
||||
Reference in New Issue
Block a user