feat: LLM 판단 상세 로깅 + 텔레그램 메시지에 LLM 응답 포함
- get_entry_price/get_exit_price가 전체 dict 반환 (action, price, confidence, reason, market_status, watch_needed) - 매수: 시그널→LLM 승인/스킵 사유, 확신도, 시장 상태 텔레그램 전송 - 매도: LLM 지정가 설정 시 진입 대비 수익률, 확신도, 관망 여부 텔레그램 전송 - 청산: LLM/cascade 구분 태그 (텔레그램 + 로그) - cascade fallback 전환 시 로그 명시 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -567,20 +567,21 @@ F&G지수: {fng} ({'공포' if fng <= 40 else '중립' if fng <= 50 else '탐욕
|
||||
|
||||
data = _call_llm(prompt, ticker)
|
||||
if data is None:
|
||||
log.info(f'[LLM매수] {ticker} → LLM 오류/무응답')
|
||||
return None
|
||||
|
||||
reason = data.get('reason', '')
|
||||
status = data.get('market_status', '')
|
||||
reason = data.get('reason', '')
|
||||
status = data.get('market_status', '')
|
||||
confidence = data.get('confidence', '?')
|
||||
|
||||
if data.get('action') == 'skip':
|
||||
log.info(f'[LLM매수] {ticker} → skip | {status} | {reason}')
|
||||
return None
|
||||
log.info(f'[LLM매수] {ticker} → skip | {confidence} | {status} | {reason}')
|
||||
return data # action=skip
|
||||
|
||||
if data.get('action') == 'buy':
|
||||
price = float(data['price'])
|
||||
confidence = data.get('confidence', '?')
|
||||
log.info(f'[LLM매수] {ticker} → buy {price:,.0f}원 | {confidence} | {status} | {reason}')
|
||||
return price
|
||||
data['price'] = float(data['price'])
|
||||
log.info(f'[LLM매수] {ticker} → buy {data["price"]:,.0f}원 | {confidence} | {status} | {reason}')
|
||||
return data # action=buy, price=float
|
||||
|
||||
log.warning(f'[LLM매수] {ticker} 알 수 없는 action: {data}')
|
||||
return None
|
||||
@@ -620,16 +621,22 @@ def get_exit_price(
|
||||
|
||||
data = _call_llm(prompt, ticker)
|
||||
if data is None:
|
||||
log.info(f'[LLM매도] {ticker} → LLM 오류/무응답 → cascade fallback')
|
||||
return None
|
||||
|
||||
reason = data.get('reason', '')
|
||||
status = data.get('market_status', '')
|
||||
reason = data.get('reason', '')
|
||||
status = data.get('market_status', '')
|
||||
confidence = data.get('confidence', '?')
|
||||
watch = data.get('watch_needed', False)
|
||||
|
||||
if data.get('action') == 'hold':
|
||||
log.info(f'[LLM매도] {ticker} → hold | {status} | {reason}')
|
||||
return None
|
||||
log.info(f'[LLM매도] {ticker} → hold | {confidence} | {status} | watch={watch} | {reason}')
|
||||
return data # action=hold
|
||||
|
||||
suggested = float(data['price'])
|
||||
confidence = data.get('confidence', '?')
|
||||
log.info(f'[LLM매도] {ticker} 지정가 교체: {current_target:,.0f} → {suggested:,.0f}원 | {confidence} | {status} | {reason}')
|
||||
return suggested
|
||||
data['price'] = float(data['price'])
|
||||
pnl_from_entry = (data['price'] - entry_price) / entry_price * 100
|
||||
log.info(
|
||||
f'[LLM매도] {ticker} 지정가 교체: {current_target:,.0f} → {data["price"]:,.0f}원 '
|
||||
f'(진입 대비 {pnl_from_entry:+.2f}%) | {confidence} | {status} | watch={watch} | {reason}'
|
||||
)
|
||||
return data # action=sell, price=float
|
||||
|
||||
Reference in New Issue
Block a user