quantecho 是我 2026 年从零搭建的一个自托管 Web 平台:前端是 Next.js,后端是几个 Python 伴生服务(sidecar),全部置于同一个网关之后,用 Docker Compose 部署,备份经 GPG 加密。它的核心是回测实验室:入场信号是一段在浏览器里写下的 Python 函数,其余(股票池、出场规则、复权与缓存)都固定写进经过测试的代码,不随信号改变。
- ~84k行代码,TypeScript 与 Python
- 1,303只标的:标普 500 · 沪深 300 · 中证 500
- 90个测试,都在回测引擎上
notebook 回测的局限
notebook 里的回测写起来容易,却也容易让自己误信结果:成交规则是隐含的,回测用的价格序列与你之前查看的那条复权方式不同,A 股的 T+1 交收规则也常常被忘掉。在 quantecho 里你只写信号,这些容易出问题的决定都只做一次,放在经过测试的代码里。
扫描流程
一个形态(pattern)就是一个 Python 文件,在页面内嵌的 Monaco 编辑器里写:其中一小块 META 生成参数表单,一个 entries() 函数对每只标的返回一串布尔值。一次扫描把它在标普 500、沪深 300 或中证 500 上跑一遍,每个入场点按三种出场规则之一处理:持有 N 天,到目标价(止盈)或超时,或先到止损;若同一根 K 线同时触及止损和止盈,则先按止损成交。A 股的 T+1 在引擎内部处理,因此形态代码从不需要知道自己在哪个市场。
行情按每只标的一个 parquet 文件缓存,价格做后复权,使比价前后一致;显示时再换回。同步层遇到限流会重试,连续失败时触发软件意义上的熔断器,中途也可以取消。每次扫描都登记在一个作业注册表里,作为作业运行;进度和日志行通过服务器推送事件(Server-Sent Events,SSE)推到浏览器,浏览器也可以要求取消。结果包括交易的统计与分布,以及逐笔交易的图,每次扫描都存档为可回放的 JSON。
平台的底层
- 只开一个端口,一次会话。 一个自己写的 Node 服务器在这个端口上同时提供 Next.js 与 Socket.IO,会话校验通过之后再把请求反向代理到伴生服务;上传、下载与 SSE 都原样透传,因此 Python 服务里没有任何鉴权代码。
- 上传可断点续传。 文件分块、带指纹,失败后退避重试,上传状态存在浏览器里,刷新页面也不会丢。
- 一次数据丢失事故。 前后两次,部署之后最近写入的数据消失了。根本原因是 POSIX 文件锁不能穿过 Docker 的绑定挂载(bind mount),于是宿主机一侧的一个 SQLite 连接可以在容器不知情的情况下删掉它的预写日志(WAL)。解决办法有三处:加一个所有者心跳,容器持有数据库期间拒绝来自宿主机的连接;每次部署前先做快照;客户端加一个发件箱(outbox),不把服务器的确认当作数据已经持久化。
- 备份。 SQLite 每天备份,并做 GPG 加密。
我做的事。 设计文档、代码、测试、部署与事故复盘,全部由我完成。平台是私有的,没有公开演示;可以公开谈的是回测实验室这一部分。
计数来自各仓库,2026 年 8 月。信号、扫描与结果都不公开。