MCP 수정중
This commit is contained in:
@@ -8,46 +8,85 @@ import logging
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
# 캐싱 공통 컨텍스트 — 전략 규칙을 한 번만 전송하고 이후 호출에서 캐시로 재사용.
|
||||
# Claude Sonnet 기준 캐싱 최소 임계값: 1024 토큰.
|
||||
_CACHED_CONTEXT = """[자동 주식 매매 시스템 — 리스크 규칙]
|
||||
포지션 사이징: 종목당 총자본 3~4%, 최대 보유 20~25개, 레버리지 ETF 최대 20%.
|
||||
손절(SL): 안정종목 -6%, 변동성종목 -10%, ATR 우선(진입가 - 2.5*ATR).
|
||||
익절(TP): +2R 도달 시 50% 분할매도, 나머지는 고점-(1.5*ATR) 트레일링스탑.
|
||||
MDD -10%: 신규진입 중단, 포지션 30% 축소, 단기전략 중단.
|
||||
MDD -20%: 전 포지션 50% 강제청산 (레버리지 우선).
|
||||
가격필터: 국내 5,000원 초과, 미국 $4 초과 (ETF·리츠 예외).
|
||||
상관관계: 섹터당 최대 3종목, 상관계수 0.7 초과 진입 거부.
|
||||
시장국면: SIDEWAYS(ADX<20) 진입 금지.
|
||||
전략A(평균회귀): 상승장 RSI<40·BB하단, 하락장 RSI<30·BB하단·반전캔들, 거래량>20MA.
|
||||
전략B(코스닥스캐너): 총자본 25%, 점수=0.5*RSI+0.3*BB+0.2*Vol 상위 20개.
|
||||
단기전략(15분): RSI<30·BB하단·5MA돌파·거래량>1.3배, MDD -10% 미만 비활성.
|
||||
"""
|
||||
|
||||
|
||||
class ClaudeClient:
|
||||
"""Claude AI 클라이언트"""
|
||||
|
||||
def __init__(self):
|
||||
self.client = AsyncAnthropic(api_key=settings.ANTHROPIC_API_KEY)
|
||||
self.model = settings.CLAUDE_MODEL
|
||||
|
||||
|
||||
async def analyze(
|
||||
self,
|
||||
system_prompt: str,
|
||||
user_message: str,
|
||||
tools: List[Dict[str, Any]] = None
|
||||
) -> Dict[str, Any]:
|
||||
"""Claude를 통한 분석 실행"""
|
||||
"""Claude를 통한 분석 실행.
|
||||
|
||||
시스템 프롬프트는 두 블록으로 구성:
|
||||
1) _CACHED_CONTEXT — cache_control 적용, 반복 호출 시 캐시에서 재사용.
|
||||
2) 메서드별 role 지시문 — 캐싱 없이 매번 전송.
|
||||
"""
|
||||
try:
|
||||
messages = [
|
||||
{"role": "user", "content": user_message}
|
||||
]
|
||||
|
||||
|
||||
params = {
|
||||
"model": self.model,
|
||||
"max_tokens": settings.MAX_TOKENS,
|
||||
"temperature": settings.TEMPERATURE,
|
||||
"system": system_prompt,
|
||||
"messages": messages
|
||||
"system": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": _CACHED_CONTEXT,
|
||||
"cache_control": {"type": "ephemeral"},
|
||||
},
|
||||
{
|
||||
"type": "text",
|
||||
"text": system_prompt,
|
||||
},
|
||||
],
|
||||
"messages": messages,
|
||||
}
|
||||
|
||||
|
||||
if tools:
|
||||
params["tools"] = tools
|
||||
|
||||
|
||||
response = await self.client.messages.create(**params)
|
||||
|
||||
# 응답 파싱
|
||||
usage = response.usage
|
||||
cache_read = getattr(usage, "cache_read_input_tokens", 0) or 0
|
||||
cache_write = getattr(usage, "cache_creation_input_tokens", 0) or 0
|
||||
if cache_read:
|
||||
logger.debug(f"[cache] hit={cache_read} write={cache_write} input={usage.input_tokens} output={usage.output_tokens}")
|
||||
result = {
|
||||
"content": [],
|
||||
"stop_reason": response.stop_reason,
|
||||
"usage": {
|
||||
"input_tokens": response.usage.input_tokens,
|
||||
"output_tokens": response.usage.output_tokens
|
||||
}
|
||||
"input_tokens": usage.input_tokens,
|
||||
"output_tokens": usage.output_tokens,
|
||||
"cache_read_tokens": cache_read,
|
||||
"cache_write_tokens": cache_write,
|
||||
},
|
||||
}
|
||||
|
||||
for block in response.content:
|
||||
|
||||
Reference in New Issue
Block a user