12 KiB
自动化回测服务设计方案
需求背景
三国量化团队需要支持自动化批量回测场景:
- 将军们提交回测脚本和参数
- 系统自动运行回测
- 完成后返回结果给将军
- 不需要手动干预
现有环境基础
当前 Docker 容器环境已经提供:
- ✅ Python 3.10
- ✅ 完整 vnpy 框架
- ✅
vnpy.trader.backtesting.BacktestingEngine原生回测引擎 - ✅ FastAPI(已被 vnpy_webtrader 依赖)
- ✅ SSH 远程访问
- ✅ Jupyter Lab 结果分析
设计原则
- 尽量基于vnpy原生:核心回测使用原生
BacktestingEngine,不重复造轮子 - 轻量级实现:不引入过重的第三方任务队列(如 Redis/RabbitMQ)
- 保持简单:够用就好,便于维护
- 不强制自动启动:作为可选服务,需要时手动启动
架构设计
┌─────────────┐
│ 将军 │
└──────┬──────┘
│ POST /api/backtest/submit
↓
┌──────────────────────────┐
│ FastAPI 回测服务 │ ← 监听 8088 端口
│ - 接收任务 │
│ - 任务排队 │
│ - 进程池执行 │
│ - 保存结果 │
└──────┬───────────────────┘
│ 调用
↓
┌──────────────────────────┐
│ vnpy 原生 BacktestingEngine ← 核心回测计算
│ - 加载历史数据 │
│ - 运行策略回测 │
│ - 计算统计结果 │
│ - 输出图表 │
└──────┬───────────────────┘
│ 保存结果
↓
┌──────────────────────────┐
│ 文件系统存储 │
│ - 任务元数据 JSON │
│ - 回测结果 CSV/JSON │
│ - 收益曲线图片 │
└──────┬───────────────────┘
│ GET /api/backtest/result/{task_id}
↓
┌─────────────┐
│ 将军 │ ← 获取结果分析
└─────────────┘
端口分配
| 服务 | 端口 | 用途 | 状态 |
|---|---|---|---|
| SSH | 22 → 2222 | 远程登录 | ✅ 已映射 |
| Jupyter Lab | 8888 | Notebook开发 | ✅ 已映射 |
| code-server | 8080 | Web VS Code | ✅ 已映射 |
| VNPY Web Trader | 8000 | 交易Web API | ✅ 已映射 |
| VNPY RPC 交易核心 | 2018 | RPC 请求 | ✅ 已映射 |
| VNPY RPC 交易核心 | 4102 | RPC 订阅 | ✅ 已映射 |
| 自动化回测服务 | 8088 | 回测API | ✅ 已映射 |
API 接口设计
1. 提交回测任务
接口: POST /api/backtest/submit
请求体:
{
"strategy_name": "double_ma",
"strategy_code": "from vnpy.trader.strategy import ...",
"parameters": {
"fast_window": 5,
"slow_window": 20
},
"start_date": "2020-01-01",
"end_date": "2024-01-01",
"symbol": "IF888",
"interval": "1h"
}
响应:
{
"code": 0,
"msg": "success",
"data": {
"task_id": "a1b2c3d4-1234-5678-90ef-ghijklmnopqr",
"status": "pending"
}
}
2. 查询任务状态
接口: GET /api/backtest/status/{task_id}
响应:
{
"code": 0,
"msg": "success",
"data": {
"task_id": "a1b2c3d4-1234-5678-90ef-ghijklmnopqr",
"status": "running|completed|failed",
"progress": 75,
"message": "正在计算统计结果"
}
}
3. 获取回测结果
接口: GET /api/backtest/result/{task_id}
响应:
{
"code": 0,
"msg": "success",
"data": {
"task_id": "...",
"status": "completed",
"statistics": {
"total_trades": 100,
"win_rate": 0.6,
"sharpe_ratio": 1.8,
"max_drawdown": 0.15,
"total_return": 0.35,
"annual_return": 0.08
},
"result_file": "/app/backtest_results/.../result.csv",
"chart_file": "/app/backtest_results/.../equity_curve.png",
"completed_at": "2026-04-11T22:00:00Z"
}
}
4. 列出所有任务
接口: GET /api/backtest/list
响应:
{
"code": 0,
"msg": "success",
"data": {
"tasks": [
{
"task_id": "...",
"strategy_name": "...",
"status": "...",
"created_at": "..."
}
]
}
}
目录结构
/app/
├── scripts/
│ └── backtest-service/
│ ├── main.py # FastAPI 入口
│ ├── task_queue.py # 任务队列实现
│ ├── executor.py # 任务执行器
│ ├── models.py # 数据模型
│ └── README.md # 使用说明
└── backtest_jobs/
├── pending/ # 等待执行
├── running/ # 执行中
├── completed/ # 已完成
└── failed/ # 执行失败
任务队列实现
使用 Python 内置 multiprocessing.Pool 做进程池,限制并发回测数量,避免资源耗尽:
# 配置示例
MAX_WORKERS = 2 # 最大并发回测数,根据CPU核数调整
每个回测任务在独立进程中运行,互不干扰,一个失败不影响其他任务。
启动方式
手动启动(开发环境)
ssh -p 2222 vnpy@192.168.2.153
cd /app/scripts/backtest-service
python main.py
后台运行
nohup python main.py > backtest-service.log 2>&1 &
后续实现步骤
- 创建目录结构
- 编写 Pydantic 数据模型
- 编写任务队列
- 编写任务执行器
- 编写 FastAPI 路由
- 编写 README 使用说明
- 测试验证
参考文档
文档记录时间: 2026-04-11 22:21 GMT+8 记录人: 姜维 伯约 状态: 设计完成,待实现
成功部署记录 - 2026-04-12
部署信息
- 部署目标: Synology NAS @ 192.168.2.154
- 镜像名称:
sanguo_vnpy:latest - 镜像ID:
a77f153853b9 - 容器ID:
8fccf1eb15ae - 基础镜像:
python:3.10-slim
成功部署的服务
| 服务 | 地址 | 状态 | 验证结果 |
|---|---|---|---|
| Jupyter Lab | http://192.168.2.154:8888/lab?token=sanguo123 | ✅ 运行正常 | 已验证可访问 |
| SSH | ssh vnpy@192.168.2.154 -p 2222 (密码: sanguo123) |
✅ 运行正常 | 已修复 hostkey 问题 |
| VNPY Web Trader | http://192.168.2.154:8000 | ⚪ 待手动启动 | 端口已映射 |
| code-server | http://192.168.2.154:8080 | ⚪ 待手动安装 | 配置已预生成 |
| VNPY RPC 请求 | 192.168.2.154:2018 | ✅ 端口就绪 | 已映射 |
| VNPY RPC 订阅 | 192.168.2.154:4102 | ✅ 端口就绪 | 已映射 |
| 自动化回测服务 | http://192.168.2.154:8088 | ✅ 端口就绪 | 已映射,预留 |
关键修复
-
openssh-server 配置文件缺失问题
问题:openssh-server因依赖 systemd 安装报错,/etc/ssh/sshd_config缺失
解决:在 Dockerfile 添加判断,如果配置文件不存在则生成默认配置 -
sshd hostkey 缺失问题
问题:容器启动时sshd: no hostkeys available -- exiting
解决:容器启动后在容器内执行ssh-keygen -A生成 hostkeys,重启后正常 -
code-server 网络安装失败问题
问题:GitHub 访问不稳定,二进制下载失败
解决:跳过预安装,保留配置,由用户启动容器后手动安装
容器启动命令
# 停止并删除旧容器
echo "Ccf7561523" | sudo -S docker stop sanguo_vnpy
echo "Ccf7561523" | sudo -S docker rm sanguo_vnpy
# 启动新容器
echo "Ccf7561523" | sudo -S docker run -d \
-p 8888:8888 \
-p 8000:8000 \
-p 8080:8080 \
-p 8088:8088 \
-p 2018:2018 \
-p 4102:4102 \
-p 2222:22 \
--name sanguo_vnpy \
sanguo_vnpy:latest
账号信息
| 账号 | 密码 | 用途 |
|---|---|---|
| vnpy (container) | sanguo123 | SSH 登录容器 |
| Jupyter token | sanguo123 | Jupyter Lab 访问 |
| code-server | sanguo123 | code-server 访问(预配置) |
验证结果
- ✅ Jupyter Lab 已验证可正常访问
- ✅ 所有端口映射正确配置
- ✅ SSH 已修复可正常连接
- ✅ 完整 vnpy 开发环境已就绪
- ✅ 所有依赖包安装成功
记录人
姜维 伯约
2026-04-12 09:29 GMT+8
状态:✅ 部署成功,Jupyter Lab 可访问
实施完成记录 - 2026-04-12
已完成工作
1. Dockerfile 更新
- ✅ code-server 改为预装,不再跳过
- ✅ 添加 vnpy_webtrader 到 requirements-base.txt
- ✅ 更新 EXPOSE 暴露所有需要的端口(22 8000 8080 8888 2018 4102 8088)
2. 自动化回测服务代码实现
完整目录结构:
/app/scripts/backtest-service/
├── config.py # 配置
├── models.py # Pydantic 数据模型
├── task_queue.py # 任务队列管理器
├── executor.py # 回测执行器(调用 vnpy 原生 BacktestingEngine)
├── result_storage.py # 结果存储
├── api.py # FastAPI 路由
├── main.py # 服务入口
└── README.md # 使用说明
所有代码按照设计方案实现完成:
- ✅ 严格遵循 vnpy 原生设计,不修改核心架构
- ✅ 只做外层封装,完全复用原生 BacktestingEngine
- ✅ multiprocessing.Pool 做并发控制,可配置 MAX_WORKERS
- ✅ 每个回测独立进程,隔离性好,一个失败不影响其他
- ✅ 完整的 CRUD API,支持提交/查询/结果获取
3. 准备好各个服务启动脚本
/app/scripts/
├── start_rpc_server.py # VNPY 交易核心 RPC 服务启动
├── start_web_trader.py # VNPY Web Trader 服务启动
└── start_backtest_service.py # 自动化回测服务启动
按照 vnpy 官方双进程架构:
- 第一步:启动
start_rpc_server.py→ RPC 服务端监听 2018/4102 - 第二步:启动
start_web_trader.py→ Web 服务监听 8000 - 需要回测时:启动
start_backtest_service.py→ API 服务监听 8088
当前代码结构确认
| 文件路径 | 功能 | 状态 |
|---|---|---|
scripts/backtest-service/config.py |
配置 | ✅ 完成 |
scripts/backtest-service/models.py |
数据模型 | ✅ 完成 |
scripts/backtest-service/task_queue.py |
任务队列 | ✅ 完成 |
scripts/backtest-service/executor.py |
回测执行器 | ✅ 完成 |
scripts/backtest-service/result_storage.py |
结果存储 | ✅ 完成 |
scripts/backtest-service/api.py |
API 路由 | ✅ 完成 |
scripts/backtest-service/main.py |
服务入口 | ✅ 完成 |
scripts/backtest-service/README.md |
使用说明 | ✅ 完成 |
scripts/start_rpc_server.py |
VNPY RPC 启动 | ✅ 完成 |
scripts/start_web_trader.py |
VNPY Web Trader 启动 | ✅ 完成 |
scripts/start_backtest_service.py |
自动化回测服务启动 | ✅ 完成 |
待执行
- 重新构建 Docker 镜像
- 测试验证各个服务启动正常
- 运行一个示例回测验证功能
记录人: 姜维 伯约
2026-04-12 10:17 GMT+8
状态:✅ 设计实施完成,等待重新构建镜像