from django.shortcuts import render, get_object_or_404 from django.http import JsonResponse from django.views.decorators.csrf import csrf_exempt from django.views.decorators.http import require_http_methods from django.utils import timezone import json import threading import time from .models import QuantStrategy, StrategyVersion, StrategyExecution from .base import StrategyRegistry from . import implementations # 구현체들을 로드하여 레지스트리에 등록 @require_http_methods(["GET"]) def list_strategies(request): # 레지스트리에서 사용 가능한 전략들을 가져옴 available_strategies = StrategyRegistry.list_strategies() # DB에서 관리되는 전략들을 가져옴 strategies = QuantStrategy.objects.filter(is_active=True).prefetch_related('versions') strategy_list = [] for strategy in strategies: current_version = strategy.versions.filter(is_current=True).first() strategy_data = { 'id': strategy.id, 'name': strategy.name, 'description': strategy.description, 'created_at': strategy.created_at.isoformat(), 'current_version': { 'id': current_version.id, 'version': current_version.version, 'implementation_key': current_version.implementation_key, 'parameters': current_version.parameters, 'created_at': current_version.created_at.isoformat() } if current_version else None, 'total_versions': strategy.versions.count(), 'available_implementations': available_strategies.get(strategy.name, {}).get('versions', []) } strategy_list.append(strategy_data) return JsonResponse({ 'strategies': strategy_list, 'total_count': len(strategy_list), 'available_implementations': available_strategies }) @csrf_exempt @require_http_methods(["POST"]) def execute_strategy(request): try: data = json.loads(request.body) strategy_name = data.get('strategy_name') version = data.get('version') execution_parameters = data.get('parameters', {}) if not strategy_name: return JsonResponse({ 'error': 'strategy_name is required' }, status=400) strategy = get_object_or_404(QuantStrategy, name=strategy_name, is_active=True) if version: strategy_version = get_object_or_404( StrategyVersion, strategy=strategy, version=version ) else: strategy_version = strategy.versions.filter(is_current=True).first() if not strategy_version: return JsonResponse({ 'error': 'No current version found for this strategy' }, status=404) execution = StrategyExecution.objects.create( strategy_version=strategy_version, execution_parameters=execution_parameters, status='pending' ) def run_strategy(): try: execution.status = 'running' execution.save() # 전략 구현체 인스턴스를 가져와서 실행 strategy_impl = strategy_version.get_strategy_implementation() # 기본 파라미터와 실행 파라미터를 병합 merged_parameters = strategy_impl.default_parameters.copy() merged_parameters.update(execution_parameters) # 전략 실행 result = strategy_impl.execute(merged_parameters) execution.status = 'completed' execution.result = result execution.completed_at = timezone.now() execution.save() except Exception as e: execution.status = 'failed' execution.error_message = str(e) execution.completed_at = timezone.now() execution.save() thread = threading.Thread(target=run_strategy) thread.start() return JsonResponse({ 'execution_id': execution.id, 'status': 'pending', 'message': 'Strategy execution started' }) except json.JSONDecodeError: return JsonResponse({ 'error': 'Invalid JSON in request body' }, status=400) except Exception as e: return JsonResponse({ 'error': str(e) }, status=500) @require_http_methods(["GET"]) def execution_status(request, execution_id): execution = get_object_or_404(StrategyExecution, id=execution_id) response_data = { 'execution_id': execution.id, 'strategy': execution.strategy_version.strategy.name, 'version': execution.strategy_version.version, 'status': execution.status, 'started_at': execution.started_at.isoformat(), 'execution_parameters': execution.execution_parameters } if execution.completed_at: response_data['completed_at'] = execution.completed_at.isoformat() if execution.status == 'completed' and execution.result: response_data['result'] = execution.result if execution.status == 'failed' and execution.error_message: response_data['error_message'] = execution.error_message return JsonResponse(response_data) @require_http_methods(["GET"]) def list_available_implementations(request): """레지스트리에 등록된 모든 전략 구현체 목록을 반환""" available_strategies = StrategyRegistry.list_strategies() return JsonResponse({ 'available_implementations': available_strategies })