Initial commit: Django quantitative strategy executor

- Django 5.2.7 project with Python 3.13+
- Quant strategy management system with version control
- Strategy implementations using registry pattern
- API endpoints for strategy listing and execution
- Sample strategy implementations (MovingAverage, RSI, BollingerBand)
- Async strategy execution with status tracking

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-10-04 13:50:46 +09:00
commit 01403c7df4
22 changed files with 1031 additions and 0 deletions

161
strategies/views.py Normal file
View File

@@ -0,0 +1,161 @@
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
})