212 lines
8.2 KiB
Python
212 lines
8.2 KiB
Python
from rest_framework import status, permissions
|
|
from rest_framework.decorators import api_view, permission_classes
|
|
from rest_framework.response import Response
|
|
from rest_framework.views import APIView
|
|
from django.shortcuts import get_object_or_404
|
|
from asgiref.sync import sync_to_async
|
|
import asyncio
|
|
from datetime import datetime
|
|
|
|
from apps.authentication.models import AnalysisSession
|
|
from apps.authentication.serializers import AnalysisSessionSerializer, CreateAnalysisSessionSerializer
|
|
from .services import TradingAnalysisManager, TradingAnalysisService
|
|
|
|
|
|
class AnalysisConfigView(APIView):
|
|
"""분석 설정 정보 조회"""
|
|
permission_classes = [permissions.IsAuthenticated]
|
|
|
|
def get(self, request):
|
|
"""분석 설정 옵션들 반환"""
|
|
config = {
|
|
'analysts': [
|
|
{'value': 'market', 'label': 'Market Analyst', 'description': '시장 데이터 분석'},
|
|
{'value': 'social', 'label': 'Social Analyst', 'description': '소셜 센티멘트 분석'},
|
|
{'value': 'news', 'label': 'News Analyst', 'description': '뉴스 분석'},
|
|
{'value': 'fundamentals', 'label': 'Fundamentals Analyst', 'description': '기본 분석'},
|
|
],
|
|
'research_depths': [
|
|
{'value': 1, 'label': 'Shallow', 'description': '빠른 분석, 적은 토론 라운드'},
|
|
{'value': 3, 'label': 'Medium', 'description': '중간 정도 분석, 보통 토론 라운드'},
|
|
{'value': 5, 'label': 'Deep', 'description': '깊은 분석, 많은 토론 라운드'},
|
|
],
|
|
'shallow_thinkers': [
|
|
{'value': 'gpt-4o-mini', 'label': 'GPT-4o-mini', 'description': '빠르고 효율적'},
|
|
{'value': 'gpt-4.1-nano', 'label': 'GPT-4.1-nano', 'description': '초경량 모델'},
|
|
{'value': 'gpt-4.1-mini', 'label': 'GPT-4.1-mini', 'description': '컴팩트 모델'},
|
|
{'value': 'gpt-4o', 'label': 'GPT-4o', 'description': '표준 모델'},
|
|
],
|
|
'deep_thinkers': [
|
|
{'value': 'gpt-4.1-nano', 'label': 'GPT-4.1-nano', 'description': '초경량 모델'},
|
|
{'value': 'gpt-4.1-mini', 'label': 'GPT-4.1-mini', 'description': '컴팩트 모델'},
|
|
{'value': 'gpt-4o', 'label': 'GPT-4o', 'description': '표준 모델'},
|
|
{'value': 'o4-mini', 'label': 'o4-mini', 'description': '추론 특화 모델 (컴팩트)'},
|
|
{'value': 'o3-mini', 'label': 'o3-mini', 'description': '고급 추론 모델 (경량)'},
|
|
{'value': 'o3', 'label': 'o3', 'description': '완전한 고급 추론 모델'},
|
|
{'value': 'o1', 'label': 'o1', 'description': '최고급 추론 및 문제 해결 모델'},
|
|
]
|
|
}
|
|
|
|
return Response(config)
|
|
|
|
|
|
class StartAnalysisView(APIView):
|
|
"""분석 시작"""
|
|
permission_classes = [permissions.IsAuthenticated]
|
|
|
|
def post(self, request):
|
|
"""새로운 분석 시작"""
|
|
serializer = CreateAnalysisSessionSerializer(data=request.data)
|
|
|
|
if serializer.is_valid():
|
|
# 분석 세션 생성
|
|
session = serializer.save(user=request.user)
|
|
|
|
# 백그라운드에서 분석 실행
|
|
# 실제 환경에서는 Celery나 다른 task queue를 사용하는 것이 좋습니다
|
|
asyncio.create_task(self._start_analysis_async(request.user, session.id))
|
|
|
|
return Response({
|
|
'message': '분석이 시작되었습니다.',
|
|
'session_id': session.id,
|
|
'session': AnalysisSessionSerializer(session).data
|
|
}, status=status.HTTP_201_CREATED)
|
|
|
|
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
async def _start_analysis_async(self, user, session_id):
|
|
"""비동기 분석 실행"""
|
|
try:
|
|
await TradingAnalysisManager.start_analysis(user, session_id)
|
|
except Exception as e:
|
|
print(f"분석 실행 중 오류: {e}")
|
|
|
|
|
|
class AnalysisStatusView(APIView):
|
|
"""분석 상태 조회"""
|
|
permission_classes = [permissions.IsAuthenticated]
|
|
|
|
def get(self, request, session_id):
|
|
"""특정 분석 세션의 상태 조회"""
|
|
session = get_object_or_404(
|
|
AnalysisSession,
|
|
id=session_id,
|
|
user=request.user
|
|
)
|
|
|
|
serializer = AnalysisSessionSerializer(session)
|
|
return Response(serializer.data)
|
|
|
|
|
|
class CancelAnalysisView(APIView):
|
|
"""분석 취소"""
|
|
permission_classes = [permissions.IsAuthenticated]
|
|
|
|
def post(self, request, session_id):
|
|
"""분석 취소"""
|
|
try:
|
|
success = TradingAnalysisManager.cancel_analysis(request.user, session_id)
|
|
|
|
if success:
|
|
return Response({
|
|
'message': '분석이 취소되었습니다.',
|
|
'session_id': session_id
|
|
})
|
|
else:
|
|
return Response({
|
|
'message': '취소할 수 없는 상태입니다.',
|
|
'session_id': session_id
|
|
}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
except Exception as e:
|
|
return Response({
|
|
'error': str(e)
|
|
}, status=status.HTTP_404_NOT_FOUND)
|
|
|
|
|
|
class AnalysisHistoryView(APIView):
|
|
"""분석 기록 조회"""
|
|
permission_classes = [permissions.IsAuthenticated]
|
|
|
|
def get(self, request):
|
|
"""사용자의 분석 기록 조회"""
|
|
sessions = TradingAnalysisManager.get_user_analysis_sessions(request.user)
|
|
serializer = AnalysisSessionSerializer(sessions, many=True)
|
|
|
|
return Response({
|
|
'count': len(sessions),
|
|
'results': serializer.data
|
|
})
|
|
|
|
|
|
class AnalysisReportView(APIView):
|
|
"""분석 보고서 조회"""
|
|
permission_classes = [permissions.IsAuthenticated]
|
|
|
|
def get(self, request, session_id):
|
|
"""특정 분석 세션의 보고서 조회"""
|
|
session = get_object_or_404(
|
|
AnalysisSession,
|
|
id=session_id,
|
|
user=request.user
|
|
)
|
|
|
|
if session.status != 'completed':
|
|
return Response({
|
|
'message': '분석이 완료되지 않았습니다.',
|
|
'status': session.status
|
|
}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
return Response({
|
|
'session_id': session.id,
|
|
'ticker': session.ticker,
|
|
'analysis_date': session.analysis_date,
|
|
'final_report': session.final_report,
|
|
'completed_at': session.completed_at,
|
|
'duration': (session.completed_at - session.started_at).total_seconds() if session.started_at and session.completed_at else None
|
|
})
|
|
|
|
|
|
@api_view(['GET'])
|
|
@permission_classes([permissions.IsAuthenticated])
|
|
def get_analysis_options(request):
|
|
"""분석 옵션 조회 (간단한 버전)"""
|
|
options = {
|
|
'default_values': {
|
|
'ticker': 'SPY',
|
|
'analysis_date': datetime.now().strftime('%Y-%m-%d'),
|
|
'analysts_selected': ['market', 'social', 'news', 'fundamentals'],
|
|
'research_depth': 3,
|
|
'shallow_thinker': 'gpt-4o-mini',
|
|
'deep_thinker': 'gpt-4o'
|
|
}
|
|
}
|
|
|
|
# 사용자 프로필의 기본값이 있다면 사용
|
|
if hasattr(request.user, 'profile'):
|
|
profile = request.user.profile
|
|
options['user_preferences'] = {
|
|
'default_ticker': profile.default_ticker,
|
|
'preferred_research_depth': profile.preferred_research_depth,
|
|
'preferred_shallow_thinker': profile.preferred_shallow_thinker,
|
|
'preferred_deep_thinker': profile.preferred_deep_thinker,
|
|
}
|
|
|
|
return Response(options)
|
|
|
|
|
|
@api_view(['GET'])
|
|
@permission_classes([permissions.IsAuthenticated])
|
|
def get_running_analyses(request):
|
|
"""실행 중인 분석 조회"""
|
|
running_sessions = AnalysisSession.objects.filter(
|
|
user=request.user,
|
|
status='running'
|
|
)
|
|
|
|
serializer = AnalysisSessionSerializer(running_sessions, many=True)
|
|
|
|
return Response({
|
|
'count': len(running_sessions),
|
|
'results': serializer.data
|
|
}) |