# Quant OS cross-engine consistency contract “本地、聚宽、QMT、Qlib 都能跑”不等于四条净值曲线必须逐点相同。跨引擎 一致性按层比较:相同信息集应产生相同计算;平台特有的日历、价格语义和成交 差异必须被记录、归因和限制。 ## 1. Comparison levels | Level | Compared artifact | Same canonical input required | Pass rule | | --- | --- | --- | --- | | L0 | Source/config manifest | Git state、portable-core hash、strategy/model version、symbol map | Exact | | L1 | Data/universe | `as_of`、sessions、symbols、PIT membership、raw/factor/declared adjusted prices、tradability | Exact values or explicit provider reason | | L2 | Signal | symbol、horizon、lookback/skip、score、model bundle | Exact symbol set;numeric tolerance below | | L3 | Target | target weight/quantity、frozen/sellable state | weight tolerance;exact lot quantity | | L4 | Order intent | ID、side、quantity、limit、type、TIF、timing、reason | Identical broker snapshot/rules 时 exact | | L5 | Order/fill/portfolio | status、fills、fees、cash、positions | Semantic invariants;相同 fill fixture 才要求 exact | | L6 | Performance | return、turnover、drawdown、cost | Diagnostic;不能代替 L1—L5 | 只比较 L6 不会通过 G9。Alpha158/LightGBM 与 portable momentum 是不同 model spec,本来就不是 L2 peer;可做研究比较,不能冒充同策略 parity。 ## 2. Canonical snapshot is the L1 handoff JQData ingestion 通过官方 `get_bars` 保存: - raw `open/high/low/close/volume/money`; - `factor`、`pre_close`、`high_limit`、`low_limit`、`paused`; - 每个 member-date 的 PIT `is_st`; - 每个交易日的历史指数成员。 快照必须保持 `adjustment=none`,front-adjusted feature history 在每个 decision `as_of` 时由当时已保存的 raw close + factor 构造。这样执行价仍是 raw,且后来的 factor 不能改写旧决策。 L1 verifier 不只比文件 hash,还要: 1. 拒绝 incomplete marker; 2. 要求目录是 manifest 声明的精确 artifact 集; 3. 重建每个 bar/membership 领域对象; 4. 重算质量统计、内容 hash 与 `data_version`; 5. 拒绝重复键、非法 OHLC、停牌非零量、非法限价、缺失 factor 或非布尔/ 缺失 `is_st`; 6. 拒绝 retrieval 当日仍未在 Asia/Shanghai 24:00 完成的日线。 验证入口: ```bash PYTHONPATH=src:. python -c \ "from quant60.data_snapshot import verify_data_snapshot; verify_data_snapshot('data/snapshots/csi500-2024/manifest.json')" ``` `snapshot-backtest` 和 `snapshot-decision` 都先通过该 verifier。它们能证明 同一个 snapshot 的本地可重放性,但在真实授权 JQData run 和平台导出前, 不能证明 provider entitlement 或 G9。 ## 3. Required run manifest 每个 comparison 至少保存: ```json { "run_id": "unique-id", "engine": "local|joinquant|qmt_builtin|qmttools|xttrader|qlib", "mode": "fixture|provider_snapshot|backtest|simulation|shadow|live", "git_commit": "commit-or-DIRTY", "portable_core_sha256": "sha256", "strategy_or_model_version": "immutable-id", "python_version": "major.minor.patch", "platform_version": "value-or-unknown", "config_hash": "sha256", "data_version": "immutable-id", "rules_version": "immutable-id", "timezone": "Asia/Shanghai", "signal_as_of": "ISO-8601 timestamp", "last_feature_bar": "ISO-8601 date-or-time", "first_executable_time": "ISO-8601 timestamp", "price_adjustment": "raw|pre|post|front_ratio|PIT_FRONT_FROM_RAW_AND_FACTOR", "fill_model": "declared-name", "evidence_class": "fake|synthetic|provider-snapshot|real-platform|broker" } ``` unknown platform version 可用于 smoke,但阻止 release certification。 本地 execution/provider snapshot run 保存后执行: ```bash PYTHONPATH=src:. python -m quant60 verify-manifest \ artifacts//manifest.json ``` 它检查 incomplete marker、精确 artifact set/hash、ledger chain/head、 report/manifest identity、saved/current source/schema aggregate 和 payload schema。snapshot decision 使用: ```bash PYTHONPATH=src:. python -m quant60 verify-snapshot-decision \ artifacts//manifest.json ``` ## 4. Numeric and semantic tolerances 对传入 `portable_core.py` 的同一固定 close arrays: | Field | Tolerance | | --- | --- | | canonical symbol、rank、selected set | Exact | | momentum score | absolute error ≤ `1e-12` | | target weight | absolute error ≤ `1e-10` | | target quantity | Exact integer | | order delta | Exact signed integer | 真实 provider 数据先比较输入数组。不同复权约定、停牌填充、成分股日期或 feature cutoff 导致的 score 差异是 L1 failure,不是浮点噪声。 本地货币 ledger 按配置的 currency quantum 比较。hosted NAV 只有在 bars、 company actions、fees 和 fill events 都相同时才要求相同;否则必须分类: - `input-price difference`; - `timing difference`; - `tradability/fill difference`; - `explicit-fee difference`; - `residual unexplained difference`。 residual 必须为零或低于 release-specific bound,不能静默并入 slippage。 ## 5. Clock alignment canonical weekly clock 是 ISO 周第一实际交易日完整 close,紧接着下一实际 交易日 open。它不是固定星期几;单交易日长假周会自然跨到下一 ISO 周。 comparison key 必须包含: ```text (signal_as_of, last_feature_bar, first_executable_time, adjustment_mode) ``` 任一元素不同就不是 strict peer,只能做诊断 comparison。 本地 snapshot backtest 使用: - exact daily PIT membership; - decision date raw close + factor 构造 point-in-time front-adjusted signal; - next session raw open 执行; - provider daily pause/limit/pre-close; - provider daily PIT `is_st`:ST 不新买,已持有 ST 只卖; - prior-session volume capacity。 JoinQuant/QMT 必须导出相同输入或其 hash 才能进入 L2—L4 strict comparison。 ## 6. Platform interpretation and current facts - **Local**:固定 fixture 的 deterministic contract oracle,不自动等于市场 真相。 - **JoinQuant**:以前一交易日查询 PIT index/ST,以批量 `history` 读取完成 日线,并显式设置费用、滑点和 10% 参与率;必须导出实际 close arrays/hash、plan、orders/fills 和平台配置。本地 fake harness 只证明 wiring。2026-07-26 已完成一次 2024 全年真实 hosted smoke,运行日志无 ERROR;但尚未导出上述相同输入与分层结果,所以它是 runtime evidence, 不是 strict peer/G9 证据。 - **QMT built-in / qmttools**:共享 bundle 但生命周期不同,均硬 backtest-only;固定中证 500 benchmark,以历史 timetag 查询 PIT 成分/ST。 built-in 的 10% 最大成交量占比需要 QMT UI 设置并取证,qmttools 程序化传入。真实 QMT 环境尚未运行。qmttools 把 transfer fee 折入 commission,minimum commission/fill 行为是声明差异。 - **XtTrader**:比较 broker snapshot、order intent 与 normalized callback。 当前已有只读 HMAC 账户绑定、broker observation/snapshot 和 exact shadow-plan verifier,但只有 fake broker contract,没有真实 shadow。 - **Qlib momentum**:`pyqlib==0.9.7` 的 native fixture 已真实运行,产生 24 条 signal;结果保存 signal/report hash、表边界和从 report 重算的 portfolio 指标。它证明 runtime/path 可执行,不证明真实市场或 L3/L4。 - **Qlib Alpha158/LightGBM**:fixture 上已真实完成 model + Recorder。 runner 自动以 `setdefault` 设置 `MLFLOW_ALLOW_FILE_STORE=true` 以兼容本地 MLflow file store,并读取 portfolio report 保存 hash、边界和重算指标。 两股票 synthetic 性能没有投资意义,且该模型不是 portable momentum 的 parity peer。 - **Mock parity exporter**:当前能逐层比较 JoinQuant/QMT fake wrapper 的 score、weight、quantity、delta,并校验 source hash。它明确是 `mock_contract_only`、`real_platform_pass=false`、`gate_credit=[]`。 ## 7. Difference reason codes 必须使用枚举 reason code,不能只写“平台差异”: ```text CALENDAR SYMBOL_MAP UNIVERSE MISSING_BAR SUSPENSION_FILL PRICE_ADJUSTMENT AS_OF_CLOCK ROUNDING FEE_SCHEDULE PRICE_LIMIT T_PLUS_ONE VOLUME_LIMIT FILL_MODEL BROKER_STATE FLOAT_TOLERANCE UNEXPLAINED ``` symbol set、signal、target、order intent、cash 或 position 出现任何 `UNEXPLAINED` 都阻止 release。 ## 8. Runnable comparison support mock-only exporter: ```bash PYTHONPATH=src:. python tools/export_mock_parity.py \ export --output artifacts/mock-parity/report.json PYTHONPATH=src:. python tools/export_mock_parity.py \ verify artifacts/mock-parity/report.json ``` Qlib native momentum fixture: ```bash 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 ``` 两者都不是 G9 的真实平台证据。 ## 9. What counts toward G9 | Evidence | Counts toward G9? | | --- | --- | | symbol/unit tests、fake JoinQuant/QMT harness | Supporting only | | mock parity exporter | No;contract regression only | | local snapshot twice with same hash | Supporting G7/L1 only | | Qlib 24-signal synthetic fixture smoke | Runtime evidence only | | Qlib Alpha158 synthetic Recorder smoke | Research runtime evidence only | | real JoinQuant export vs local canonical run | Yes,覆盖的 layers/dates | | licensed qmttools run with saved version/result | Yes,覆盖的 layers | | XtTrader shadow using real broker snapshot | Yes,pre-trade/order semantics | | ≥20 trading days QMT shadow, zero unexplained differences | 文章 G9 必需 | 真实 JoinQuant smoke 已运行;QMT 和 broker shadow 尚未运行,而且 JoinQuant 仍缺同输入导出与 local peer,所以 G9 继续为 `not_passed`。 状态权威是 [`gate_scorecard.json`](../gate_scorecard.json)。