from fastapi import APIRouter, Depends, HTTPException from typing import List, Dict, Any, Optional import json # 导入json模块 from sqlalchemy.orm import Session from app.core.deps import get_db, get_current_user from app.models.user import User from app.models.backtest_result import BacktestResult from app.schemas.backtest import ( BacktestResultResponse, BacktestDetailResponse ) router = APIRouter() @router.get("/", response_model=List[BacktestResultResponse]) async def get_backtest_results( db: Session = Depends(get_db), current_user: User = Depends(get_current_user), strategy_id: Optional[int] = None, skip: int = 0, limit: int = 20 ): """获取回测结果列表""" filters = {"user_id": current_user.id} if strategy_id: filters["strategy_id"] = strategy_id results = await BacktestResult.filter( **filters ).prefetch_related("strategy").order_by( "-created_at" ).offset(skip).limit(limit).all() response_results = [] for result in results: response_results.append({ "id": result.id, "strategy_id": result.strategy_id, "strategy_name": result.strategy.name, "start_date": result.start_date, "end_date": result.end_date, "initial_capital": result.initial_capital, "final_capital": result.final_capital, "total_return": result.total_return, "annual_return": result.annual_return, "sharpe_ratio": result.sharpe_ratio, "max_drawdown": result.max_drawdown, "win_rate": result.win_rate, "created_at": result.created_at }) return response_results @router.get("/{backtest_id}", response_model=BacktestDetailResponse) async def get_backtest_result( backtest_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_user) ): """获取回测结果详情""" result = await BacktestResult.filter( id=backtest_id ).prefetch_related("strategy").first() if not result: raise HTTPException(status_code=404, detail="回测结果不存在") # 检查权限 if result.user_id != current_user.id and not current_user.is_admin: raise HTTPException(status_code=403, detail="没有权限查看此回测结果") # 解析交易记录和每日净值数据 trades = [] daily_values = [] if result.results_data: try: results_data = json.loads(result.results_data) trades = results_data.get("trades", []) daily_values = results_data.get("daily_values", []) except Exception: # 解析失败时使用空列表 pass return { "id": result.id, "strategy_id": result.strategy_id, "strategy_name": result.strategy.name, "user_id": result.user_id, "start_date": result.start_date, "end_date": result.end_date, "initial_capital": result.initial_capital, "final_capital": result.final_capital, "total_return": result.total_return, "annual_return": result.annual_return, "sharpe_ratio": result.sharpe_ratio, "max_drawdown": result.max_drawdown, "win_rate": result.win_rate, "trades": trades, "daily_values": daily_values, "created_at": result.created_at } @router.delete("/{backtest_id}", response_model=Dict[str, Any]) async def delete_backtest_result( backtest_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_user) ): """删除回测结果""" result = await BacktestResult.get(id=backtest_id) if not result: raise HTTPException(status_code=404, detail="回测结果不存在") # 检查权限 if result.user_id != current_user.id and not current_user.is_admin: raise HTTPException(status_code=403, detail="没有权限删除此回测结果") # 删除回测结果 await result.delete() return {"success": True, "message": "回测结果已删除"}