Files
crypto_trader/backend/api/backtesting.py

79 lines
2.8 KiB
Python
Raw Normal View History

"""Backtesting API endpoints."""
from fastapi import APIRouter, HTTPException, Depends, BackgroundTasks
from typing import Dict, Any
from sqlalchemy import select
import uuid
from ..core.dependencies import get_backtesting_engine, get_strategy_registry
from ..core.schemas import BacktestRequest, BacktestResponse
from src.core.database import Strategy, get_database
router = APIRouter()
# Store running backtests
_backtests: Dict[str, Dict[str, Any]] = {}
@router.post("/run", response_model=BacktestResponse)
async def run_backtest(
backtest_data: BacktestRequest,
background_tasks: BackgroundTasks,
backtest_engine=Depends(get_backtesting_engine)
):
"""Run a backtest."""
try:
db = get_database()
async with db.get_session() as session:
# Get strategy
stmt = select(Strategy).where(Strategy.id == backtest_data.strategy_id)
result = await session.execute(stmt)
strategy_db = result.scalar_one_or_none()
if not strategy_db:
raise HTTPException(status_code=404, detail="Strategy not found")
# Create strategy instance
registry = get_strategy_registry()
strategy_instance = registry.create_instance(
strategy_id=strategy_db.id,
name=strategy_db.class_name,
parameters=strategy_db.parameters,
timeframes=strategy_db.timeframes or [backtest_data.timeframe]
)
if not strategy_instance:
raise HTTPException(status_code=400, detail="Failed to create strategy instance")
# Run backtest
results = backtest_engine.run_backtest(
strategy=strategy_instance,
symbol=backtest_data.symbol,
exchange=backtest_data.exchange,
timeframe=backtest_data.timeframe,
start_date=backtest_data.start_date,
end_date=backtest_data.end_date,
initial_capital=backtest_data.initial_capital,
slippage=backtest_data.slippage,
fee_rate=backtest_data.fee_rate
)
if "error" in results:
raise HTTPException(status_code=400, detail=results["error"])
return BacktestResponse(
results=results,
status="completed"
)
except HTTPException:
raise
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@router.get("/results/{backtest_id}")
async def get_backtest_results(backtest_id: str):
"""Get backtest results by ID."""
if backtest_id not in _backtests:
raise HTTPException(status_code=404, detail="Backtest not found")
return _backtests[backtest_id]