feat: 实现回测功能

## 功能概述
实现完整的回测功能,支持基于历史数据模拟跟单策略的执行效果。

## 后端实现
- 数据库:新增 backtest_task 和 backtest_trade 表(V27迁移脚本)
- 实体类:BacktestTask、BacktestTrade
- Repository:BacktestTaskRepository、BacktestTradeRepository
- Service:
  - BacktestService:回测任务管理(CRUD)
  - BacktestDataService:从 Polymarket Data API 获取历史交易数据
  - BacktestExecutionService:回测算法核心实现
  - BacktestPollingService:定时轮询执行回测任务
- Controller:BacktestController(6个API接口)
- DTO:BacktestDto、TradeData
- 错误码:新增回测相关错误码和国际化消息

## 前端实现
- 页面组件:
  - BacktestList:回测任务列表
  - BacktestCreate:创建回测任务
  - BacktestDetail:回测详情(含图表)
  - BacktestChart:资金曲线图表(使用 ECharts)
- 类型定义:backtest.ts
- API 服务:集成所有回测接口
- 国际化:支持中英文

## 核心特性
- 回测天数限制:1-15 天
- 数据获取:直接从 Polymarket Data API 获取历史交易(不使用缓存表)
- 任务执行:同一时刻只执行一个任务,按创建时间顺序执行最早创建的任务
- 回测算法:完整实现市场结算、卖出匹配、价格容忍度、每日订单限制等规则
- 实时进度:支持任务进度更新和实时轮询

## 文档更新
- BACKTEST_PRD.md:产品需求文档
- BACKTEST_TECHNICAL_DESIGN.md:技术设计文档
- BACKTEST_REVIEW_CHECKLIST.md:设计评审检查清单

## 其他修改
- 移除 max_position_count 配置(V26迁移脚本)
- 移除 BacktestSyncService(不再需要实时同步)
- 修复前后端编译错误
This commit is contained in:
WrBug
2026-01-31 07:27:36 +08:00
parent fabbd81f22
commit cdd02e9f3d
34 changed files with 4880 additions and 76 deletions
@@ -0,0 +1,97 @@
-- ============================================
-- 回测功能表创建
-- ============================================
-- ============================================
-- 2. 创建回测任务表
-- ============================================
CREATE TABLE IF NOT EXISTS backtest_task (
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '回测任务ID',
task_name VARCHAR(100) NOT NULL COMMENT '回测任务名称',
leader_id BIGINT NOT NULL COMMENT 'Leader ID',
initial_balance DECIMAL(20, 8) NOT NULL COMMENT '初始资金',
final_balance DECIMAL(20, 8) DEFAULT NULL COMMENT '最终资金',
profit_amount DECIMAL(20, 8) DEFAULT NULL COMMENT '收益金额',
profit_rate DECIMAL(10, 4) DEFAULT NULL COMMENT '收益率(%)',
backtest_days INT NOT NULL COMMENT '回测天数',
start_time BIGINT NOT NULL COMMENT '回测开始时间(历史时间)',
end_time BIGINT DEFAULT NULL COMMENT '回测结束时间(历史时间)',
-- 跟单配置 (复制CopyTrading表结构)
copy_mode VARCHAR(10) NOT NULL DEFAULT 'RATIO' COMMENT '跟单模式: RATIO/FIXED',
copy_ratio DECIMAL(20, 8) NOT NULL DEFAULT 1.0 COMMENT '跟单比例',
fixed_amount DECIMAL(20, 8) DEFAULT NULL COMMENT '固定金额',
max_order_size DECIMAL(20, 8) NOT NULL DEFAULT 1000.0 COMMENT '最大单笔订单',
min_order_size DECIMAL(20, 8) NOT NULL DEFAULT 1.0 COMMENT '最小单笔订单',
max_daily_loss DECIMAL(20, 8) NOT NULL DEFAULT 10000.0 COMMENT '最大每日亏损',
max_daily_orders INT NOT NULL DEFAULT 100 COMMENT '最大每日订单数',
price_tolerance DECIMAL(5, 2) NOT NULL DEFAULT 5.0 COMMENT '价格容忍度(%)',
delay_seconds INT NOT NULL DEFAULT 0 COMMENT '延迟秒数',
support_sell BOOLEAN NOT NULL DEFAULT TRUE COMMENT '是否支持卖出',
min_order_depth DECIMAL(20, 8) DEFAULT NULL COMMENT '最小订单深度',
max_spread DECIMAL(20, 8) DEFAULT NULL COMMENT '最大价差',
min_price DECIMAL(20, 8) DEFAULT NULL COMMENT '最低价格',
max_price DECIMAL(20, 8) DEFAULT NULL COMMENT '最高价格',
max_position_value DECIMAL(20, 8) DEFAULT NULL COMMENT '最大仓位金额',
keyword_filter_mode VARCHAR(20) NOT NULL DEFAULT 'DISABLED' COMMENT '关键字过滤模式',
keywords JSON DEFAULT NULL COMMENT '关键字列表',
max_market_end_date BIGINT DEFAULT NULL COMMENT '市场截止时间限制',
-- 统计字段
avg_holding_time BIGINT DEFAULT NULL COMMENT '平均持仓时间(毫秒)',
data_source VARCHAR(50) DEFAULT 'MIXED' COMMENT '数据源: INTERNAL/API/MIXED',
-- 执行状态
status VARCHAR(20) NOT NULL DEFAULT 'PENDING' COMMENT '状态: PENDING/RUNNING/COMPLETED/STOPPED/FAILED',
progress INT DEFAULT 0 COMMENT '执行进度(0-100)',
total_trades INT DEFAULT 0 COMMENT '总交易笔数',
buy_trades INT DEFAULT 0 COMMENT '买入笔数',
sell_trades INT DEFAULT 0 COMMENT '卖出笔数',
win_trades INT DEFAULT 0 COMMENT '盈利交易笔数',
loss_trades INT DEFAULT 0 COMMENT '亏损交易笔数',
win_rate DECIMAL(5, 2) DEFAULT NULL COMMENT '胜率(%)',
max_profit DECIMAL(20, 8) DEFAULT NULL COMMENT '最大单笔盈利',
max_loss DECIMAL(20, 8) DEFAULT NULL COMMENT '最大单笔亏损',
max_drawdown DECIMAL(20, 8) DEFAULT NULL COMMENT '最大回撤',
error_message TEXT DEFAULT NULL COMMENT '错误信息',
created_at BIGINT NOT NULL COMMENT '创建时间',
execution_started_at BIGINT DEFAULT NULL COMMENT '执行开始时间(系统时间)',
execution_finished_at BIGINT DEFAULT NULL COMMENT '执行完成时间(系统时间)',
updated_at BIGINT NOT NULL COMMENT '更新时间',
INDEX idx_leader_id (leader_id),
INDEX idx_status (status),
INDEX idx_created_at (created_at),
INDEX idx_leader_profit (leader_id, profit_rate DESC),
INDEX idx_status_created (status, created_at DESC),
FOREIGN KEY (leader_id) REFERENCES copy_trading_leaders(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='回测任务表';
-- ============================================
-- 3. 创建回测交易记录表
-- ============================================
CREATE TABLE IF NOT EXISTS backtest_trade (
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '交易记录ID',
backtest_task_id BIGINT NOT NULL COMMENT '回测任务ID',
trade_time BIGINT NOT NULL COMMENT '交易时间',
market_id VARCHAR(100) NOT NULL COMMENT '市场ID',
market_title VARCHAR(500) DEFAULT NULL COMMENT '市场标题',
side VARCHAR(20) NOT NULL COMMENT '方向: BUY/SELL/SETTLEMENT',
outcome VARCHAR(50) NOT NULL COMMENT '结果: YES/NO或outcomeIndex',
outcome_index INT DEFAULT NULL COMMENT '结果索引(0, 1, 2, ...),支持多元市场',
quantity DECIMAL(20, 8) NOT NULL COMMENT '数量',
price DECIMAL(20, 8) NOT NULL COMMENT '价格',
amount DECIMAL(20, 8) NOT NULL COMMENT '金额',
fee DECIMAL(20, 8) NOT NULL DEFAULT 0.0 COMMENT '手续费',
profit_loss DECIMAL(20, 8) DEFAULT NULL COMMENT '盈亏(仅卖出时)',
balance_after DECIMAL(20, 8) NOT NULL COMMENT '交易后余额',
leader_trade_id VARCHAR(100) DEFAULT NULL COMMENT 'Leader原始交易ID',
created_at BIGINT NOT NULL COMMENT '创建时间',
INDEX idx_backtest_task_id (backtest_task_id),
INDEX idx_trade_time (trade_time),
FOREIGN KEY (backtest_task_id) REFERENCES backtest_task(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='回测交易记录表';
@@ -255,3 +255,54 @@ error.server.order_tracking_process_failed=Failed to process order tracking
error.server.order_tracking_buy_failed=Failed to process buy order
error.server.order_tracking_sell_failed=Failed to process sell order
error.server.order_tracking_match_failed=Order matching failed
# Backtest service errors
error.backtest.task_not_found=Backtest task not found
error.backtest.leader_not_found=Leader not found
error.backtest.days_invalid=Backtest days must be between 1-15 days
error.backtest.initial_balance_invalid=Invalid initial balance
error.backtest.task_running=Backtest task is running, cannot delete
error.server.backtest_create_failed=Failed to create backtest task
error.server.backtest_update_failed=Failed to update backtest task
error.server.backtest_delete_failed=Failed to delete backtest task
error.server.backtest_list_fetch_failed=Failed to fetch backtest list
error.server.backtest_detail_fetch_failed=Failed to fetch backtest detail
error.server.backtest_trades_fetch_failed=Failed to fetch backtest trades
error.server.backtest_execute_failed=Failed to execute backtest
error.server.backtest_historical_data_fetch_failed=Failed to fetch historical data
error.server.backtest_stop_failed=Failed to stop backtest task
# Backtest Management
backtest.title=Backtest Management
backtest.create_task=Create Backtest
backtest.task_name=Task Name
backtest.leader=Leader
backtest.initial_balance=Initial Balance
backtest.backtest_days=Backtest Days
backtest.profit_amount=Profit Amount
backtest.profit_rate=Profit Rate
backtest.backtest_days_range=Backtest Days Range (1-15 days)
backtest.total_trades=Total Trades
backtest.buy_trades=Buy Trades
backtest.sell_trades=Sell Trades
backtest.win_trades=Win Trades
backtest.loss_trades=Loss Trades
backtest.win_rate=Win Rate
backtest.max_profit=Max Profit
backtest.max_loss=Max Loss
backtest.max_drawdown=Max Drawdown
backtest.avg_holding_time=Avg Holding Time
# Backtest Status
backtest.status.pending=Pending
backtest.status.running=Running
backtest.status.completed=Completed
backtest.status.stopped=Stopped
backtest.status.failed=Failed
# Backtest Config
backtest.copy_mode.ratio=Ratio Mode
backtest.copy_mode.fixed=Fixed Amount
backtest.price_tolerance=Price Tolerance
backtest.delay_seconds=Delay Seconds
backtest.support_sell=Support Sell
@@ -255,3 +255,60 @@ error.server.order_tracking_process_failed=处理订单跟踪失败
error.server.order_tracking_buy_failed=处理买入订单失败
error.server.order_tracking_sell_failed=处理卖出订单失败
error.server.order_tracking_match_failed=订单匹配失败
# 回测服务错误
error.backtest.task_not_found=回测任务不存在
error.backtest.leader_not_found=Leader不存在
error.backtest.days_invalid=回测天数必须在 1-15 天之间
error.backtest.initial_balance_invalid=初始金额无效
error.backtest.task_running=回测任务正在运行,无法删除
error.server.backtest_create_failed=创建回测任务失败
error.server.backtest_update_failed=更新回测任务失败
error.server.backtest_delete_failed=删除回测任务失败
error.server.backtest_list_fetch_failed=查询回测列表失败
error.server.backtest_detail_fetch_failed=查询回测详情失败
error.server.backtest_trades_fetch_failed=查询回测交易记录失败
error.server.backtest_execute_failed=回测执行失败
error.server.backtest_historical_data_fetch_failed=历史数据获取失败
error.server.backtest_stop_failed=停止回测任务失败
# 回测管理
backtest.title=回测管理
backtest.create_task=新增回测
backtest.task_name=回测名称
backtest.leader=Leader
backtest.initial_balance=初始金额
backtest.backtest_days=回测天数
backtest.profit_amount=收益额
backtest.profit_rate=收益率
backtest.backtest_days_range=回测天数范围(1-15天)
backtest.total_trades=总交易笔数
backtest.buy_trades=买入笔数
backtest.sell_trades=卖出笔数
backtest.win_trades=盈利交易笔数
backtest.loss_trades=亏损交易笔数
backtest.win_rate=胜率
backtest.max_profit=最大单笔盈利
backtest.max_loss=最大单笔亏损
backtest.max_drawdown=最大回撤
backtest.avg_holding_time=平均持仓时间
# 回测状态
backtest.status.pending=待执行
backtest.status.running=运行中
backtest.status.completed=已完成
backtest.status.stopped=已停止
backtest.status.failed=失败
# 回测配置
backtest.copy_mode.ratio=比例模式
backtest.copy_mode.fixed=固定金额
backtest.price_tolerance=价格容忍度
backtest.delay_seconds=延迟秒数
backtest.support_sell=支持卖出
# 订单跟踪服务错误
error.server.order_tracking_process_failed=处理订单跟踪失败
error.server.order_tracking_buy_failed=处理买入订单失败
error.server.order_tracking_sell_failed=处理卖出订单失败
error.server.order_tracking_match_failed=订单匹配失败
@@ -255,3 +255,54 @@ error.server.order_tracking_process_failed=處理訂單跟蹤失敗
error.server.order_tracking_buy_failed=處理買入訂單失敗
error.server.order_tracking_sell_failed=處理賣出訂單失敗
error.server.order_tracking_match_failed=訂單匹配失敗
# 回測服務錯誤
error.backtest.task_not_found=回測任務不存在
error.backtest.leader_not_found=Leader不存在
error.backtest.days_invalid=回測天數必須在 1-15 天之間
error.backtest.initial_balance_invalid=初始金額無效
error.backtest.task_running=回測任務正在運行,無法刪除
error.server.backtest_create_failed=創建回測任務失敗
error.server.backtest_update_failed=更新回測任務失敗
error.server.backtest_delete_failed=刪除回測任務失敗
error.server.backtest_list_fetch_failed=查詢回測列表失敗
error.server.backtest_detail_fetch_failed=查詢回測詳情失敗
error.server.backtest_trades_fetch_failed=查詢回測交易記錄失敗
error.server.backtest_execute_failed=回測執行失敗
error.server.backtest_historical_data_fetch_failed=歷史數據獲取失敗
error.server.backtest_stop_failed=停止回測任務失敗
# 回測管理
backtest.title=回測管理
backtest.create_task=新增回測
backtest.task_name=回測名稱
backtest.leader=Leader
backtest.initial_balance=初始金額
backtest.backtest_days=回測天數
backtest.profit_amount=收益額
backtest.profit_rate=收益率
backtest.backtest_days_range=回測天數範圍(1-15天)
backtest.total_trades=總交易筆數
backtest.buy_trades=買入筆數
backtest.sell_trades=賣出筆數
backtest.win_trades=盈利交易筆數
backtest.loss_trades=虧損交易筆數
backtest.win_rate=勝率
backtest.max_profit=最大單筆盈利
backtest.max_loss=最大單筆虧損
backtest.max_drawdown=最大回撤
backtest.avg_holding_time=平均持倉時間
# 回測狀態
backtest.status.pending=待執行
backtest.status.running=運行中
backtest.status.completed=已完成
backtest.status.stopped=已停止
backtest.status.failed=失敗
# 回測配置
backtest.copy_mode.ratio=比例模式
backtest.copy_mode.fixed=固定金額
backtest.price_tolerance=價格容忍度
backtest.delay_seconds=延遲秒數
backtest.support_sell=支持賣出