fix: 포지션 한도 초과 방지 + LLM 호출 최적화

- VOL_MIN 4→8 복원 (시그널 빈도 과다)
- process_signal: LLM 호출 전/후 포지션 한도 재확인
- check_pending_buys: 체결 시점 한도 초과면 즉시 취소
- LLM tool 중복 호출 방지 (같은 tool+args → 캐시 응답)
- 모든 tool 호출 완료 시 tool 제거해 강제 텍스트 응답
- max_rounds 8→5 축소
- 재시작 시 Upbit 잔고 기반 포지션 자동 복구
- LLM 모델: google/gemini-2.5-flash로 전환

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
joungmin
2026-03-05 22:34:35 +09:00
parent 4f9e2c44c7
commit 526003c979
2 changed files with 74 additions and 7 deletions

View File

@@ -436,15 +436,19 @@ def _call_llm(prompt: str, ticker: str) -> Optional[dict]:
}
messages = [{'role': 'user', 'content': prompt}]
max_rounds = 5
called_tools: set = set() # 중복 tool 호출 방지
try:
for _ in range(5):
for round_i in range(max_rounds):
body = {
'model': model,
'max_tokens': 512,
'tools': _TOOLS,
'messages': messages,
'response_format': {'type': 'json_object'},
}
# 마지막 라운드 또는 모든 tool 이미 호출 → tool 제거해 강제 텍스트 응답
if round_i < max_rounds - 1 and len(called_tools) < len(_TOOLS):
body['tools'] = _TOOLS
resp = _req.post(
'https://openrouter.ai/api/v1/chat/completions',
headers=headers, json=body, timeout=30,
@@ -461,8 +465,14 @@ def _call_llm(prompt: str, ticker: str) -> Optional[dict]:
for tc in tool_calls:
fn_name = tc['function']['name']
fn_args = json.loads(tc['function']['arguments'])
fn_result = _execute_tool(fn_name, fn_args)
log.info(f'[LLM-Tool] {ticker} {fn_name}({fn_args}) 호출')
call_key = f'{fn_name}:{json.dumps(fn_args, sort_keys=True)}'
if call_key in called_tools:
# 중복 호출 → 캐시된 결과 반환
fn_result = f'(이미 조회한 데이터입니다. 위 결과를 참고하세요.)'
else:
fn_result = _execute_tool(fn_name, fn_args)
called_tools.add(call_key)
log.info(f'[LLM-Tool] {ticker} {fn_name} 호출')
messages.append({
'role': 'tool',
'tool_call_id': tc['id'],