Files
sanguo_vnpy/scripts/backtest-service/models.py
T
2026-04-28 08:49:52 +08:00

98 lines
3.3 KiB
Python
Executable File

"""
自动化回测服务 - 数据模型
"""
from enum import Enum
from datetime import date, datetime
from typing import Dict, Optional, Any, List, Generic, TypeVar
from pydantic import BaseModel, Field
class TaskStatus(str, Enum):
"""任务状态枚举"""
PENDING = "pending"
RUNNING = "running"
COMPLETED = "completed"
FAILED = "failed"
class BacktestTask(BaseModel):
"""回测任务请求"""
strategy_name: str = Field(..., description="策略名称")
strategy_code: str = Field(..., description="策略完整Python代码")
symbol: str = Field(..., description="交易品种,例如 000001.SSE")
interval: str = Field(..., description="K线周期,例如 1d、1h")
start_date: date = Field(..., description="回测开始日期")
end_date: date = Field(..., description="回测结束日期")
parameters: Dict[str, Any] = Field(default_factory=dict, description="策略参数字典")
capital: float = Field(default=1_000_000, description="起始资金")
tick_size: Optional[float] = Field(None, description="最小价格变动,不指定则自动获取")
class BacktestTaskWithId(BacktestTask):
"""带ID和状态的回测任务"""
task_id: str = Field(..., description="任务唯一ID")
status: TaskStatus = Field(..., description="任务状态")
created_at: str = Field(..., description="创建时间 ISO格式")
started_at: Optional[str] = Field(None, description="开始时间")
completed_at: Optional[str] = Field(None, description="完成时间")
class BacktestStatistics(BaseModel):
"""回测结果统计"""
start_date: str
end_date: str
total_days: int
total_trades: int
winning_trades: int
losing_trades: int
win_rate: float
total_return: float # 总收益率
annual_return: float # 年化收益率
sharpe_ratio: float # 夏普比率
max_drawdown: float # 最大回撤
max_drawdown_start: Optional[str] = None
max_drawdown_end: Optional[str] = None
profit_factor: float # 收益因子(总盈利/总亏损)
calmar_ratio: float # 卡玛比率(年化收益/最大回撤)
class BacktestResult(BaseModel):
"""完整回测结果"""
task_id: str
strategy_name: str
status: TaskStatus
statistics: Optional[BacktestStatistics] = None
result_csv_path: str # 每日净值CSV路径
equity_curve_png_path: Optional[str] = None # 收益曲线图片路径
trades_csv_path: Optional[str] = None # 成交记录CSV路径
error_message: Optional[str] = None # 失败时的错误信息
created_at: str
started_at: Optional[str] = None
completed_at: Optional[str] = None
class TaskListResponse(BaseModel):
"""任务列表响应"""
total: int
page: int
page_size: int
tasks: List[BacktestTaskWithId]
T = TypeVar("T")
class ApiResponse(BaseModel, Generic[T]):
"""通用API响应包装"""
code: int = Field(0, description="0表示成功,非0表示错误")
msg: str = Field("success", description="响应消息")
data: Optional[T] = Field(None, description="响应数据")
class HealthCheckResponse(BaseModel):
"""健康检查响应"""
pending_count: int
running_count: int
completed_count: int
failed_count: int
max_workers: int