项目/工具
工具 · 运行中

短线量化研究平台

A 股短线量化研究系统,从旧机器迁移到 .223,公网可访问。

Python量化A股服务迁移

这是什么

短线量化研究平台(AQF Research)是我自己写的一套 A 股短线策略研究系统:用 Python 标准库实现,自带回测流水线,跑在 Docker 容器里,网页端可以看结果、查健康状态。它本来在一台 J1900 / 3.8G 内存的小机器(.164)上跑,2026-10-16 那天连续 4 次 OOM 把整机拖死约 1 小时,负载均值冲到 54.41,网站、相册、音乐、监控台全被牵连。元凶是回测流水线容器没有内存上限,每个吃 0.8–1.4GB。

解决了什么

于是整个项目搬到了 i5-8279U / 16G 的 .223 上:程序 676MB、回测数据 1.3GB、systemd 网页服务、公网入口全部迁移,路径保持不变(/tmp/sim 用软链指向 /opt/aqf-sim),脚本一行没改。迁移做了两遍校验:逐文件校验和比对 0 差异、173 个测试全部通过、真实回测在第一阶段跑通(内存峰值 942MB,正是旧机器被 OOM 杀掉的那一步)。公网 https://xiejun-server.top/quant/ 入口不变,对使用者无感。

现在

服务在 .223 上运行中,开机自启、MemoryMax=2G、异常自动拉起。.164 上的程序与数据作为冷备份原样保留,随时可以回退。

功能

  • 程序与 1.3GB 回测数据从 .164 整体迁移到 .223,路径不变、脚本零改动
  • 迁移前后两遍逐文件校验和比对,差异 0 条(含软链与 SQLite 完整性检查)
  • 173 个自带测试在新机器全部通过,耗时从 23.9s 降到约 10.5s
  • 用真实回测流水线验证:第一阶段退出码 0,内存峰值 942MB
  • 网页服务交给 systemd 托管,开机自启、MemoryMax=2G、崩溃 5 秒内自动拉起
  • 公网反代与监控探测(Gatus、自建监控台)切到新机器,入口 URL 不变

技术栈

PythonDockersystemdSQLiteNginxGatusrsync

使用 / 部署教程

部署与使用

以下操作都在 .223 上执行。

1. 确认服务状态

systemctl status aqf-research

这是网页服务,已 enable 开机自启,配置了 MemoryMax=2G 和 Restart=always。页面地址:内网 http://192.168.50.223:5555/,公网 https://xiejun-server.top/quant/。

2. 跑回测流水线

cd /tmp/sim && bash overnight.sh

路径没变:/tmp/sim 是指向 /opt/aqf-sim 的软链,由 /etc/tmpfiles.d/aqf-sim.conf 在开机时自动重建,脚本里写死的 /tmp/sim 不需要改。

3. 手动跑单个容器

docker run --rm -v /opt/aqf-research/current:/app:ro -v /tmp/sim:/sim -w /app \
  -e AQF_DATA_DIR=/sim/d_xxx \
  docker.m.daocloud.io/library/python:3.12-alpine \
  python -u /sim/xxx.py

镜像已提前拉到本地。注意给容器加内存上限,别再重演 OOM。

4. 从旧机器补数据

.164 上如果又产出新文件,先预览再真同步(单向):

bash /opt/aqf-sim/同步164新文件到223.sh
bash /opt/aqf-sim/同步164新文件到223.sh --go

5. 回退到 .164

ssh nas 'systemctl enable --now aqf-research'

然后把 NPM 里 4 处 proxy_pass(10-lan-ssl.conf 的 /quant/ 与 /api/、1.conf 同样两处)改回 192.168.50.164:5555,同步改 Gatus 配置与监控台 collect.py 里的 URL,重载 NPM 与 Gatus。改动前的备份在 .164:/root/quant-proxy-bak-20261016-180803/。

6. 迁移校验套路(可复用)

  • rsync -rcn --itemize-changes 比内容而不是比大小,软链单独比对
  • SQLite 用 integrity_check,关键表核对行数
  • 跑一遍程序自带测试
  • 真跑一次业务流水线,确认退出码
  • 停掉旧服务冻结数据后再比对第二遍,避免两边分叉

注意

  • 回测容器务必设内存上限:.164 就是因为无上限容器连续 OOM 整机卡死,.223 上已配 MemoryMax=2G 与 sim-memcap.timer,别随手 docker run 不带限制
  • 迁移/同步前先停掉源机器的服务(systemctl disable --now aqf-research)并确认无写入,否则 SQLite 的 -shm/-wal 会造成假差异甚至数据分叉
  • 公网入口暴露在 https://xiejun-server.top/quant/,注意登录与 audit 日志,不要在两台机器上同时起服务写入同一份数据