Files
quant-os/docs/AUDIT_2026-07-25.md
T

18 KiB
Raw Blame History

2026-07-25 复评:为什么原文还不是“整体 60 分”

审计对象:个人 A 股量化系统机构级 60 分 Baseline 技术选型设计:从聚宽研究到 QMT 实盘(2026-07-22

结论先行:

刻度 分数 准确含义
设计覆盖度 约 70/100 原文已经讨论研究、数据、风险、成本、组合、执行、运维与合规的大部分责任边界
可实施规格度 49/100 只有约一半内容足够明确,工程师无需继续发明字段、默认值、失败语义和验收口径
原实现证据 6/100 截至 2026-07-22,主要证据是文章、架构图、外部资料与验收清单;没有可重放代码、数据、测试或平台运行记录
硬门 0/10 G1—G10 都缺少完整验收证据;不是“部分通过”

这三条分数不能相加,也不能互相替代。设计覆盖 70 不代表系统得 70;代码文件存在也不代表 Gate 通过。依据原文自己的定义,达到 Baseline 60 必须同时满足:

证据评分 >= 60
且 G1 ... G10 全部通过

当前 Quant OS 代码交付是一个可执行、可测试的工程起点;quant60 是其第一版 A 股 Baseline 内核。它的新增得分必须在授权数据、真实平台运行、QMT 影子盘、 连续对账和券商合规确认完成后,逐项写回 gate_scorecard.json。本报告不预支这些分数。

截至 2026-07-26 的实现事实快照:

这是复评当日的历史快照,不是滚动状态页。当前五层主链、测试数和平台证据 边界以 BASELINE_VERTICAL_SLICE.mdgate_scorecard.json 和生成的公开状态为准。

  • 本次复评当时的标准库全量测试为 Ran 224 testsOK (skipped=6)
  • JQData raw/factor/pre-close/limits/paused + 每日 PIT is_st/指数成员 已连接到 semantic snapshot verifier、snapshot-backtestsnapshot-decision,并拒绝把抓取当日未到 24:00 的日线标成完整收盘, 但尚未用用户授权账号跑真实快照;
  • CPython 3.12 + pyqlib==0.9.7 native momentum fixture 已真实运行并产生 24 条 signal;
  • Qlib Alpha158 + LightGBM + Recorder fixture smoke 已真实成功;两条 Qlib workflow 均保存表级 hash、边界和从 portfolio report 重算的指标, runner 会为 local MLflow file store 显式设置 MLFLOW_ALLOW_FILE_STORE=true
  • fixture 只有两只 synthetic 股票,任何性能数字都没有投资意义;
  • JoinQuant/QMT mock parity exporter 已实现,但 real_platform_pass=false 且不计 G9
  • 2026-07-26 已完成一次 2024 全年真实 JoinQuant hosted momentum smoke,可见 日志无 ERROR;它证明 portable_momentum_smoke runtime/path,不是 Ridge/TargetPackage Baseline 证据,且尚无完整同输入导出和本地 strict peer
  • 同日一个 synthetic-research TargetPackage 已在真实 JoinQuant hosted 环境完成 exact-clock/day_open 绑定、3 笔委托和 3 笔成交;该证据只支持 execution 层真实平台观察,不支持上游四层、G9 或投资表现;
  • XtTrader 已有严格只读、HMAC 账户绑定的 observation/snapshot/shadow plan 与 verifier,但真实 QMT、broker callback/shadow 均未运行, G1—G10 仍全部 not_passed

1. 审计方法

本次没有按“名词是否出现”评分,而是对原文每个责任域检查六类问题:

  1. 是否明确输入、输出和时钟;
  2. 是否给出机器可校验的数据契约;
  3. 是否处理异常、恢复和幂等;
  4. 是否给出确定默认值或明确标记待确认;
  5. 是否有可运行实现和自动化测试;
  6. 是否有来自目标平台、真实数据或券商的运行证据。

“设计覆盖度”主要看第 1 类及责任域是否齐全;“可实施规格度”要求前 4 类足够清楚;“实现证据”只认可第 5、6 类已保存的产物。外部文档说明某 API 有能力,不等于本系统已经正确调用它。

2. 原文做对了什么

原文比常见的“因子 + 回测净值”方案完整得多,70 分设计覆盖主要来自:

  • 明确拆开 Forecast → Target → Order → Fill,避免预测、仓位和成交混为一谈;
  • 意识到 PIT、历史指数成分、退市样本、公告可得时间和公司行动;
  • 把风险、成本、换手和流动性放到事前组合决策,而不是只在绩效末尾扣滑点;
  • 讨论部分成交、撤改单、乱序回报、重启、三账对账和 kill switch
  • 把本地、聚宽、Qlib、QMT 定位为不同角色,而不是追求单一平台全包;
  • 给出十道硬门,且明确“目标 66”只有在实现、模拟和券商确认后才成立;
  • 对深模型、混合整数优化、逐笔队列与多券商容灾做了合理的 V1 边界控制。

因此问题不是方向错误,而是大量段落仍处于“正确的架构意图”,没有下降为可执行合同和证据。

3. 不足全景

责任域 原文已有 阻止整体 60 的主要缺口 最低补证
数据/PIT 分层目录、available_time、数据版本思想 无真实字段字典、供应商字段到 canonical 的映射、公告时区/盘前盘后规则、历史修订样例、许可边界和 PIT 注入测试 固定数据快照、manifest、字段级时点规范、反未来函数测试
Security Master / Universe PIT 成分、开/持/卖/冻结状态 无状态 schema、生效区间合并优先级、代码变更与退市/重组样例;指数成分来源和发布日期语义未冻结 历史 fixture 与逐原因码重放
特征/标签/验证 LightGBM + Ridge、purge/embargo、walk-forward 无特征公式和缺失值策略的完整注册表;标签价格与可执行时钟未机器化;无 purge 算法、切分日历和未触碰测试集 训练配置、切分测试、冻结 OOS 报告
风险 透明行业/风格风险模型与收缩思想 因子定义、估计窗、缺失暴露、协方差清洗、特异风险下限、行业映射版本和压力场景均未定 风险快照 schema、数值稳定性测试、压力报告
成本/容量 日期化费用、价差与冲击公式 参数没有账户交割单或真实成交校准;最低佣金的非凸性如何进入候选/rounding 未实现;机会成本缺失 费率版本、逐笔 TCA、low/base/high 校准
组合 连续优化 + rounding/repair 方向正确 目标函数量纲、风险厌恶系数、约束优先级、不可行诊断、冻结仓位与现金联立细节未形成求解器规格 可解释优化输出、不可行/rounding 回归测试
本地回测 要求与执行器同源 没有事件时钟、公司行动、现金结算、价格基准、成交量切片和可重放输出合同 小型确定性 fixture、黄金输出、费用/T+1/涨跌停测试
聚宽 定位为第二引擎 无可上传入口、参数表、调度回调、avoid_future_data 设置、结果导出和平台限制清单 上传包、平台回测记录、canonical 差异报告
QMT 内置 Python 只笼统写 QMT/XtQuant 没有处理内置 Python 3.6 与本地现代环境的边界;未说明 GUI 启动方式、回调入口和产物导出 Python 3.6 薄核心、QMT 内置回测记录
qmttools 未与其他 QMT 路径清楚分层 原文没有说明 run_strategy_file 是原生 Python 驱动 QMT 策略文件的独立运行形态,不能等同于 XtTrader OMS 独立入口、版本/参数记录、回测结果导出
XtTrader 异步 OMS 方向正确 无券商状态码映射、session/account 配置、连接恢复、查询与回调竞态、撤单确认、未知单处置 脱敏回调回放、重启/乱序/重复测试、20 日影子盘
Qlib 工作流选型合理 “接 Qlib”与“由 Qlib 完成本系统回测”边界模糊;无 provider URI、dataset handler、workflow YAML、canonical 转换和 Records 产物 Python 3.12 锁定环境、固定数据、Qlib smoke/OOS 报告
跨引擎 提出双引擎一致性 未定义到底比较输入、信号、目标、订单还是净值;没有容差、舍入、交易日历和差异原因码 CROSS_ENGINE_CONSISTENCY.md 的逐层合同
Schema/版本迁移 列出九类对象 原文只有字段清单,不是 JSON Schema;无 schema_version、兼容策略、正反例与验证命令 版本化 schema、fixture 和 CI 验证
可复现 Git/config/data/model/rules 版本思想 无 run manifest 格式、环境锁、随机源清单、原子发布、干净机复跑或 hash 容差 可保存 manifest、两次重放差异
运维/安全 提到单机、告警、runbook 无部署命令、目录权限、凭据注入、日志脱敏、磁盘满/时钟偏差/重复调度/损坏账本处置 SECURITY.md 与故障演练记录
合规 正确设为硬门 只链接通用法规;没有实际券商对账户、软件、频率、报告状态的确认 券商书面确认索引与“先报告、后交易”记录

4. 可实施规格为什么只有 49

原文的伪代码和目录树提供了良好边界,但工程实现仍需自行决定很多会改变结果的事实。例如:

  • AlphaForecast 写了“分数/预期超额”,却没有决定两者是否都必填、单位是什么、是否允许空值;
  • “按公告可得时间进入”没有定义 15:00 后公告应进入哪个交易日、时区和供应商延迟如何处理;
  • “Guarded TWAP/POV”没有冻结子单切片、限价、超时、撤单确认和窗口结束残单政策;
  • “差异在数值容差内”没有给各层容差,也没有区分浮点误差与平台成交机制差异;
  • “QMT adapter”没有区分 QMT 内置 Python、qmttools.run_strategy_file 与外部 XtTrader 三条生命周期不同的路径;
  • “Qlib workflow”没有给 provider、handler、dataset、model、record 和数据转换的可运行组合;
  • “三本账”没有定义事件唯一键、追加一致性、崩溃点、重复回调去重和 broker snapshot 的事实优先级。

当实现者必须自行补完这些选择时,文章仍是设计说明,不是完整实施规格。新仓库中的四个 JSON Schema 只是把一小部分边界机器化,不能倒推原文在 7 月 22 日已经拥有这些证据。

5. 原实现证据为什么只有 6

6 分不是对文章质量的否定,而是严格区分“说明”和“运行事实”。原文当时可认可的证据主要是:

  • 一份结构完整、明确承认条件性的设计文章;
  • 一张架构图和可编辑源图;
  • 外部官方资料链接;
  • 评分公式、Gate 定义、阶段计划与手工验收清单。

缺失的是:

  • 可安装仓库与固定 Python 环境;
  • 可运行本地回测和确定性 fixture;
  • 聚宽/QMT/Qlib 平台入口;
  • 自动化测试、schema 验证、run manifest
  • 数据质量、PIT、walk-forward、风险、成本和 TCA 报告;
  • 连续模拟、QMT 影子盘、故障演练和券商确认。

因此原实现证据只能落在“文档/原型前期”,不能用文章中的目标分 66 回填。

6. Quant OS 当前实现的正确能力边界

当前已经不只是目录骨架,以下链路可运行、可测试、可扩展:

  • 本地 deterministic event backtest、ledger hash chain、manifest verifier
  • A 股 canonical symbol、T+1 可卖量、百股单位、费用、停牌/涨跌停、 部分成交和未成交撤销;
  • PIT table、Universe 状态/原因码、透明特征、train-only 预处理、 purge/embargo walk-forward、deterministic Ridge、IC/RankIC
  • 日期化费用、impact/capacity、因子风险、约束 target 与失败诊断;
  • JQData adapter 使用 get_bars 获取 raw OHLCV/money、factor、 pre_closehigh_limitlow_limitpaused,使用 get_extras 获取 PIT is_st,并逐交易日获取历史指数成员;
  • canonical snapshot 采用 incomplete marker + exact artifact hash verifier 会重建领域对象、重算质量汇总和 data_version
  • verified snapshot 可直接进入历史 snapshot-backtest 或单日 snapshot-decision,后者可接完整 canonical broker snapshot 并 fail closed
  • 聚宽/QMT 单文件 bundle、fake harness 与 mock parity exporter
  • Qlib 0.9.7 native momentum CLI,以及 Alpha158/LightGBM/Recorder CLI
  • QMT/XtTrader 严格只读 shadow CLI:账户 HMAC、broker observation、 T 日 Signal 与 T+1 broker fact 绑定、完整 artifact verifier
  • Colab 默认无账号流程,以及显式可选的 JQData/Qlib cell。

最近一次 224-test suite、两条 Qlib fixture smoke 和 Tushare managed-provider 技术 smoke 证明上述代码路径能执行, 但仍明确不证明:

  • synthetic 数据或两股票 Qlib fixture 的收益具有投资价值;
  • 当前真实 JQData 账户的数据许可、PIT、质量与保存策略已验收;
  • 基本面公告、完整公司行动、Security Master 和退市链已生产化;
  • Ridge 或 LightGBM 已冻结为四引擎共同部署模型;
  • 聚宽与本地已在真实长样本上对齐;
  • QMT 客户端、xtquant、数据/账户权限或真实订单回调已经可用;
  • QMT 历史 ST 正例、官方 query API 的失败/空列表合同已在真实账号验证;
  • OMS 已达到断线恢复、未知单、持续对账和 20 日影子要求;
  • 程序化交易报告已经完成。

7. 平台事实应分开写

截至本次复评所依据的官方文档和本地运行记录:

  • QMT 内置策略环境仍说明为 Python 3.6;它适合运行兼容的薄策略文件,不应直接加载要求 Python ≥3.10 的完整 quant60 包;
  • XtQuant 原生 Python 文档列出 3.6—3.12 的库,并要求运行前启动 MiniQMT;实际可用版本取决于券商分发;
  • qmttools 的 run_strategy_file 是从原生 Python 驱动策略回测/运行的路径,应与 XtTrader 的查询、报单、撤单和推送生命周期分开;
  • pyqlib==0.9.7 已有 CPython 3.12 的主流平台 wheel;本项目已经在该组合 实际跑通 native momentum fixture24 signals)和 Alpha158/LightGBM/Recorder fixture
  • Alpha158 runner 使用 os.environ.setdefault 自动确认 MLFLOW_ALLOW_FILE_STORE=true,以兼容本地 MLflow file store 该确认只影响本地 tracking backend,不构成数据许可或模型有效性证明。

来源:QMT 内置 Python 快速开始XtQuant 原生 Python 快速开始原生 Python/qmttools 策略回测pyqlib 0.9.7 包与 wheel

Qlib 的运行状态现在可以写成“固定运行时已通过 fixture smoke”,不能写成 “真实 A 股研究已验收”或“与 portable target/order 一致”。两股票 synthetic fixture 的 model/portfolio 指标没有投资意义;真实 provider、冻结 OOS 和 版本化 Recorder artifact 仍要单独补证。

对应的最小验证入口:

python3.12 -m venv .venv-qlib312
source .venv-qlib312/bin/activate
python -m pip install -r requirements/research-py312.txt
python tools/build_qlib_tiny_fixture.py artifacts/qlib-fixture --days 80
PYTHONPATH=src:. python -m platforms.qlib_runner \
  --provider-uri artifacts/qlib-fixture \
  --market csi300 --benchmark SH000300 \
  --start 2024-02-01 --end 2024-04-19 \
  --lookback 20 --topk 1 --n-drop 1 --rebalance weekly \
  --output-json artifacts/qlib-native/result.json

真实 JQData 验证则必须由用户授权登录:

PYTHONPATH=src:. python tools/jqdata_snapshot.py \
  --index 000905.XSHG --start 2024-01-02 --end 2024-12-31 \
  --output data/snapshots/csi500-2024
PYTHONPATH=src:. python -c \
  "from quant60.data_snapshot import verify_data_snapshot; verify_data_snapshot('data/snapshots/csi500-2024/manifest.json')"
PYTHONPATH=src:. python -m quant60 snapshot-backtest \
  --snapshot data/snapshots/csi500-2024/manifest.json \
  --config configs/baseline.json --output artifacts/csi500-2024-backtest

8. 证据更新纪律

更新 gate_scorecard.json 时必须遵守:

  1. 先保存不可变证据,再改状态;
  2. 每条 evidence 至少包含路径、生成命令、时间、代码版本、配置 hash 和数据版本;
  3. mock、合成 fixture 和单元测试可证明代码语义,不能证明真实数据、券商或合规;
  4. Gate 只有 passednot_passed 两种对外结论;“完成 80%”仍是未通过;
  5. G9 需要真实跨引擎产物,G6/G8 需要券商认证环境或脱敏真实回调,G10 只能由实际券商材料证明;
  6. 任何代码变更使旧证据超出适用版本时,必须重新降为 not_passed
  7. 总分达到 60 但任一 Gate 未通过,系统仍必须标记 NOT_BASELINE_60

9. 下一条最短路径

按错误成本排序,而不是按模型新颖度排序:

  1. 用户授权登录 JQData,生成不可变真实 snapshot,保存许可/lineage,并通过 semantic verifier、snapshot-backtestsnapshot-decision
  2. 把已完成的单包 JoinQuant execution smoke 扩展为授权真实数据的多期 TargetPackage,并保存完整 identity/plan/orders/fills
  3. 用本地与聚宽对相同输入逐层比较 L1—L4,而不是先比较净值;mock parity 只作为回归辅助;
  4. 把基本面公告 available-time、完整公司行动/Security Master 加入真实 PIT data contract
  5. 在授权真实 provider 上运行 Qlib OOS,并把 Ridge/LightGBM 中选定的候选 冻结成 versioned model bundle;现有 synthetic Recorder 不能承担这一步;
  6. 取得实际券商 QMT client、xtquant、数据与账户权限,分别验证 built-in、 qmttools 与 XtTrader
  7. 完成 60 个交易日模拟、20 个交易日 QMT shadow、故障演练、连续零未知账差;
  8. 由实际券商确认程序化交易报告、接口权限、频率和软件要求,再讨论小资金 canary。

在第 7、8 步完成前,正确表述是“可执行、可继续填证据的 Quant OS 生产候选 框架”,不是“已达到机构级 60 分”。