수정본
This commit is contained in:
85
mcp-server/auto_trade_claude.py
Normal file
85
mcp-server/auto_trade_claude.py
Normal file
@@ -0,0 +1,85 @@
|
||||
import re
|
||||
import asyncio
|
||||
import json
|
||||
import os
|
||||
from datetime import datetime, timezone
|
||||
from app.services.korea_investment_api import korea_investment_api
|
||||
|
||||
# Claude 응답에서 종목/가격 추출
|
||||
CLAUDE_FORMAT = r"종목[:\s]+(\d+)" # 종목코드
|
||||
ENTRY_FORMAT = r"진입가[:\s]+([\d,]+)" # 진입가
|
||||
STOP_FORMAT = r"손절가[:\s]+([\d,]+)" # 손절가
|
||||
TARGET_FORMAT = r"목표가[:\s]+([\d,]+)" # 목표가
|
||||
|
||||
ACTIVE_TRADES_FILE = os.path.join(os.path.dirname(__file__), 'active_trades.json')
|
||||
|
||||
def parse_claude_response(text):
|
||||
code = re.search(CLAUDE_FORMAT, text)
|
||||
entry = re.search(ENTRY_FORMAT, text)
|
||||
stop = re.search(STOP_FORMAT, text)
|
||||
target = re.search(TARGET_FORMAT, text)
|
||||
return {
|
||||
'stock_code': code.group(1) if code else None,
|
||||
'entry_price': int(entry.group(1).replace(',', '')) if entry else None,
|
||||
'stop_loss': int(stop.group(1).replace(',', '')) if stop else None,
|
||||
'take_profit': int(target.group(1).replace(',', '')) if target else None,
|
||||
}
|
||||
|
||||
def save_active_trade(trade_info):
|
||||
"""활성화된 거래를 JSON 파일에 저장합니다."""
|
||||
trades = []
|
||||
if os.path.exists(ACTIVE_TRADES_FILE):
|
||||
with open(ACTIVE_TRADES_FILE, 'r', encoding='utf-8') as f:
|
||||
try:
|
||||
trades = json.load(f)
|
||||
except json.JSONDecodeError:
|
||||
print(f"경고: {ACTIVE_TRADES_FILE} 파일이 비어있거나 잘못된 형식입니다. 새 파일을 생성합니다.")
|
||||
|
||||
trades.append(trade_info)
|
||||
|
||||
with open(ACTIVE_TRADES_FILE, 'w', encoding='utf-8') as f:
|
||||
json.dump(trades, f, indent=4, ensure_ascii=False)
|
||||
print(f"✅ 거래 정보 저장 완료: {trade_info['stock_code']}")
|
||||
|
||||
async def auto_trade_from_claude(text, quantity=1):
|
||||
info = parse_claude_response(text)
|
||||
if info['stock_code'] and info['entry_price']:
|
||||
print(f"▶️ 매수 주문 시도: {info['stock_code']}, 수량: {quantity}, 가격: {info['entry_price']}")
|
||||
# 지정가 매수 주문
|
||||
result = await korea_investment_api.place_order(
|
||||
stock_code=info['stock_code'],
|
||||
order_type='BUY',
|
||||
quantity=quantity,
|
||||
price=info['entry_price']
|
||||
)
|
||||
print('주문 결과:', result)
|
||||
|
||||
# API 응답 구조에 따라 rt_cd가 '0'이면 성공으로 간주
|
||||
if result and result.get('rt_cd') == '0':
|
||||
print("✅ 매수 주문 성공. 거래 정보를 저장합니다.")
|
||||
trade_details = {
|
||||
'stock_code': info['stock_code'],
|
||||
'quantity': quantity,
|
||||
'entry_price': info['entry_price'],
|
||||
'stop_loss': info['stop_loss'],
|
||||
'take_profit': info['take_profit'],
|
||||
'order_id': result.get('ODNO'), # 주문번호
|
||||
'order_time': result.get('ORD_TMD'), # 주문시각
|
||||
'timestamp': datetime.now(timezone.utc).isoformat()
|
||||
}
|
||||
save_active_trade(trade_details)
|
||||
else:
|
||||
error_message = result.get('msg1', '알 수 없는 오류')
|
||||
print(f"❌ 매수 주문 실패: {error_message}")
|
||||
|
||||
else:
|
||||
print('Claude 응답에서 종목/가격을 찾을 수 없습니다.')
|
||||
|
||||
if __name__ == "__main__":
|
||||
# 예시: Claude 응답 텍스트를 받아 자동매매 실행
|
||||
import sys
|
||||
if len(sys.argv) > 1:
|
||||
text = sys.argv[1]
|
||||
asyncio.run(auto_trade_from_claude(text))
|
||||
else:
|
||||
print("사용법: python auto_trade_claude.py 'Claude 응답 텍스트'")
|
||||
Reference in New Issue
Block a user