feat(engine): 添加事件驱动回测引擎
- backtest/engine.py: 事件驱动回测引擎核心,支持 K 线推进/订单撮合/权益曲线 - backtest/models.py: 回测数据模型(订单/成交/持仓/账户快照) - backtest/README.md: 回测模块使用说明 - backtest/STRATEGY.md: 策略开发指南与最佳实践 - backtest/TIMEFRAME_COMPARISON*.md: 多周期回测对比分析报告
This commit is contained in:
@@ -0,0 +1,146 @@
|
||||
"""
|
||||
回测引擎数据模型 — 配置、交易记录、绩效指标和结果
|
||||
"""
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
from datetime import datetime
|
||||
from typing import Optional
|
||||
|
||||
|
||||
@dataclass
|
||||
class BacktestConfig:
|
||||
"""回测配置
|
||||
|
||||
Attributes:
|
||||
symbol: 交易对(如 BTCUSDT)
|
||||
exchange: 交易所标识
|
||||
interval: K 线周期
|
||||
start_time: 回测起始时间(None 表示从最早可用数据开始)
|
||||
end_time: 回测结束时间(None 表示到最新可用数据结束)
|
||||
commission_pct: 手续费率(0.001 = 0.1%)
|
||||
slippage_pct: 滑点率(0.0005 = 0.05%)
|
||||
min_order_qty: 最小下单量
|
||||
initial_capital: 初始资金(Quote 币种,如 USDT)
|
||||
warmup_bars: 预热 K 线条数(策略初始化指标所需最少数据量)
|
||||
"""
|
||||
|
||||
symbol: str
|
||||
exchange: str = "binance"
|
||||
interval: str = "1h"
|
||||
start_time: Optional[datetime] = None
|
||||
end_time: Optional[datetime] = None
|
||||
|
||||
# 交易成本
|
||||
commission_pct: float = 0.001
|
||||
slippage_pct: float = 0.0005
|
||||
min_order_qty: float = 0.001
|
||||
|
||||
# 资金
|
||||
initial_capital: float = 10_000.0
|
||||
|
||||
# 数据
|
||||
warmup_bars: int = 100
|
||||
|
||||
|
||||
@dataclass
|
||||
class BacktestTrade:
|
||||
"""单笔回测交易记录"""
|
||||
|
||||
timestamp: float
|
||||
"""成交时间(Unix 毫秒)"""
|
||||
symbol: str
|
||||
"""交易对"""
|
||||
side: str
|
||||
"""方向:BUY / SELL"""
|
||||
price: float
|
||||
"""成交价格(含滑点)"""
|
||||
quantity: float
|
||||
"""成交数量(Base 币种)"""
|
||||
notional: float
|
||||
"""成交额(Quote 币种 = price × quantity)"""
|
||||
commission: float
|
||||
"""手续费"""
|
||||
slippage: float
|
||||
"""滑点成本"""
|
||||
pnl: Optional[float] = None
|
||||
"""平仓盈亏(BUY 时为 None,SELL 时有效)"""
|
||||
reason: str = ""
|
||||
"""交易原因(来自 Signal.reason)"""
|
||||
|
||||
|
||||
@dataclass
|
||||
class BacktestMetrics:
|
||||
"""回测绩效指标"""
|
||||
|
||||
total_return_pct: float = 0.0
|
||||
"""总收益率(%)"""
|
||||
annual_return_pct: float = 0.0
|
||||
"""年化收益率(%)"""
|
||||
sharpe_ratio: float = 0.0
|
||||
"""夏普比率(无风险利率假定为 0)"""
|
||||
max_drawdown_pct: float = 0.0
|
||||
"""最大回撤(%),以负值表示"""
|
||||
max_drawdown_duration_days: int = 0
|
||||
"""最大回撤持续天数"""
|
||||
win_rate: float = 0.0
|
||||
"""胜率(0-1)"""
|
||||
profit_factor: float = 0.0
|
||||
"""盈亏比(总盈利 / 总亏损绝对值)"""
|
||||
total_trades: int = 0
|
||||
"""总交易次数"""
|
||||
avg_trade_pnl: float = 0.0
|
||||
"""平均每笔盈亏"""
|
||||
best_trade_pnl: float = 0.0
|
||||
"""最佳单笔盈亏"""
|
||||
worst_trade_pnl: float = 0.0
|
||||
"""最差单笔盈亏"""
|
||||
calmar_ratio: float = 0.0
|
||||
"""卡尔玛比率(年化收益 / 最大回撤绝对值)"""
|
||||
final_equity: float = 0.0
|
||||
"""最终权益"""
|
||||
|
||||
|
||||
@dataclass
|
||||
class BacktestResult:
|
||||
"""完整回测结果"""
|
||||
|
||||
config: BacktestConfig
|
||||
"""回测配置"""
|
||||
strategy_config: dict
|
||||
"""策略配置(转为 dict 便于序列化)"""
|
||||
metrics: BacktestMetrics
|
||||
"""绩效指标"""
|
||||
trades: list[BacktestTrade] = field(default_factory=list)
|
||||
"""交易记录"""
|
||||
equity_curve: list[dict] = field(default_factory=list)
|
||||
"""资金曲线 [{"timestamp": float, "equity": float, "drawdown": float}, ...]"""
|
||||
|
||||
@property
|
||||
def total_bars(self) -> int:
|
||||
"""回测 K 线总数"""
|
||||
return len(self.equity_curve)
|
||||
|
||||
def summary(self) -> str:
|
||||
"""生成人类可读的摘要"""
|
||||
m = self.metrics
|
||||
lines = [
|
||||
"=" * 60,
|
||||
f" 回测结果摘要 — {self.config.symbol} {self.config.interval}",
|
||||
"=" * 60,
|
||||
f" 初始资金: {self.config.initial_capital:>12.2f} USDT",
|
||||
f" 最终权益: {m.final_equity:>12.2f} USDT",
|
||||
f" 总收益率: {m.total_return_pct:>11.2f}%",
|
||||
f" 年化收益率: {m.annual_return_pct:>11.2f}%",
|
||||
f" 夏普比率: {m.sharpe_ratio:>12.2f}",
|
||||
f" 卡尔玛比率: {m.calmar_ratio:>12.2f}",
|
||||
f" 最大回撤: {m.max_drawdown_pct:>11.2f}%",
|
||||
f" 回撤持续: {m.max_drawdown_duration_days:>9} 天",
|
||||
f" 总交易次数: {m.total_trades:>11}",
|
||||
f" 胜率: {m.win_rate:>11.1%}",
|
||||
f" 盈亏比: {m.profit_factor:>12.2f}",
|
||||
f" 平均盈亏: {m.avg_trade_pnl:>12.4f} USDT",
|
||||
f" 最佳盈亏: {m.best_trade_pnl:>12.4f} USDT",
|
||||
f" 最差盈亏: {m.worst_trade_pnl:>12.4f} USDT",
|
||||
"=" * 60,
|
||||
]
|
||||
return "\n".join(lines)
|
||||
Reference in New Issue
Block a user