Files

678 lines
33 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Quant OS:个人 A 股量化研究到受限生产的独立工程
Quant OS 已从 `quants-strategies` 拆成独立项目。`quant-os` / `quant_os`
是长期 CLI/import`quant60` 是第一版 A 股 Baseline 的兼容包、CLI namespace
与 V1 artifact 协议前缀。60/80 是证据 profile,不再写进产品名。
> 当前交易执行范围仅覆盖上交所、深交所(沪深)。北交所尚未接入,
> 所有北交所委托必须 `fail closed`;代码映射支持 `.BJ` / `.XBSE`
> 不代表具备北交所回测或实盘交易能力。
本项目正在把 2026-07-22 的技术选型实现,从 `quant60` legacy 内核迁移成
严格边界、可执行、可审计的模块化单体:本地与 Colab 可零账号运行工程
smoke;JQData 登录后可生成不可变快照并直接运行 PIT 本地回测/目标决策;
聚宽、QMT 与 Qlib 有各自明确的运行入口。
> 当前状态仍是 `NOT_BASELINE_60`80 分评估为
> `BLOCKED_FROM_LIMITED_LIVE`、0/100 已验证证据分。本地五层 vertical slice、单测、
> synthetic、fake harness、Qlib fixture、真实聚宽 hosted 动量 smoke,以及
> 单个 synthetic-research TargetPackage 的真实聚宽 **execution smoke**
> 都不能代替授权真实数据 OOS、逐层同输入 parity、真实 QMT、券商影子盘、
> 连续对账与合规证据。
> 原文章复评为设计覆盖约 70/100、可实施规格 49/100、原实现证据 6/100、
> G1—G10 为 0/10。详见
> [`docs/AUDIT_2026-07-25.md`](docs/AUDIT_2026-07-25.md) 与
> [`gate_scorecard.json`](gate_scorecard.json)。
> 新依赖检查当前只覆盖 `src/quant_os/`;约 26k 行 legacy 仍位于
> `src/quant60/`、根级 `adapters/`、`platforms/` 与 `tools/`,按 vertical
> slice 迁移。`doctor.ok = true` 只表示独立仓必需文件和**新 namespace**
> 边界有效,不表示 legacy 已分层,也不表示达到 60/80。生产 trust provider /
> issuer registry 尚未实现,仓库不能自行签发正向 80 分资格。
先读:
- [80 分标准](docs/standards/QUANT_OS_80_STANDARD.md)
- [60 与 80 的差别](docs/standards/BASELINE_60_VS_PRODUCTION_80.md)
- [面向 80 的三平面架构](docs/architecture/ARCHITECTURE_80.md)
- [新架构上手](docs/getting-started/GETTING_STARTED_80.md)
- [独立仓迁移记录](MIGRATION.md)
## 在线公开验收面板
公开只读入口:
[`https://gomars.fun/quant-os/status/`](https://gomars.fun/quant-os/status/)
页面从 Production 80 machine profile、`gate_scorecard.json`、平台矩阵、
bundle manifest 和证据文档生成脱敏的构建时快照,逐层展示数据、模型、
回测平台、券商影子盘与证据缺口。它不是实时服务健康页,不发布本地行情、
账户状态或运行 artifacts。
更新权威记录后必须重新生成并检查页面数据:
```bash
python3 tools/build_public_status.py
python3 tools/build_public_status.py --check
```
网页源码位于 [`status/`](status/),生成器位于
[`tools/build_public_status.py`](tools/build_public_status.py)。
## 当前交付边界
| 路径 | 当前能做什么 | 已有证据 | 仍缺什么 |
| --- | --- | --- | --- |
| 本地 synthetic execution | 周度信号、T+1 开盘撮合、费用、涨跌停、部分成交、ledger、重放 | 标准库全量测试、确定性 smoke、manifest verifier | 不代表真实市场或投资价值 |
| 本地 synthetic research | Universe → Ridge Alpha → 风险/成本参与的 Portfolio → post-risk → reference execution 五层链 | 冻结 model bundle、无股数 TargetPackage、逐层 hash trace 与 manifest verifier | 仍是 synthetic;当前风险是 60 日对角方差,尚无真实样本校准或投资价值 |
| JQData → 本地 | 原始价、复权因子、前收、涨跌停、停牌、PIT ST 状态与历史指数成员快照;PIT 本地回测与单日目标 | fake-provider 端到端回归测试、完整收盘日 fail-closed 合同 | 需要用户授权登录后保存真实数据运行;基本面/公司行动尚未全接 |
| Colab | 自动 clone、测试、bundle、两套 synthetic 流程;可选 JQData/Qlib | notebook 本地逐 cell 执行 | JQData/Qlib 可选 cell 需对应账号/运行时 |
| 聚宽 hosted | 默认动量 smoke;显式注入 TargetPackage 后只消费本地 post-risk 权重并绑定平台账户/价格 | 动量模式已有一次 2024 全年 run;一个 synthetic-research TargetPackage 已真实命中、绑定 `day_open` 并产生 3 笔委托/成交 | 只观察 execution consumer;无授权真实长样本/OOS、上游四层 hosted 执行、QMT peer 或逐层真实数据 parity |
| QMT built-in/qmttools | 默认动量 smokeTargetPackage 模式为 Python 3.6 backtest-only 消费器 | Python 3.6 语法、TargetPackage/fake/qmttools 合约 | 需要已授权 QMT 客户端、历史数据权限与 TargetPackage 实跑导出 |
| Qlib 0.9.7 | native momentum backtestAlpha158/LightGBM CLI/Recorder 工作流 | Python 3.12 两条 fixture 已真实跑通,并保存表级 hash、行列/时间边界和重算指标 | synthetic 两股票没有投资价值;无真实 OOS、L3/L4 parity |
| Tushare → Qlib | 只读盘点 live mirror、冻结 scoped release、构建/验证不可变 provider、运行本地回测 | 2018—2025 v2 verifier 通过;1,111 instruments、1,942 sessions97 observed/96 effective 月末 snapshots 严格 500 成分、次日生效;lineage 221 jobs×6 fields mismatch 0、converter current true;双次 run byte-identical | event-time/保守次日生效 PIT 近似,不是严格 knowledge-time PIT;不同 start 的首观测锚 provider 不可直接拼接;research-only、`gate_credit=[]`、ST/统一 9.5% 仍缺 |
| XtTrader shadow | 只读账户查询、HMAC 账户绑定、broker observation/snapshot、零下单 target-diff 计划与完整 verifier | fake broker/QMT 合约;所有 broker mutation 均不可达 | 需要授权 QMT 环境的账户合同探针、恢复/对账和券商确认;Baseline 60 至少 20 个交易日,Production 80 当前缺口为同一冻结候选至少 60 个交易日 |
`portable-momentum-v1` 只是当前真实跑过聚宽的跨引擎连通性 smoke,不是
60 分 Baseline。Baseline 的权威决策留在本地:冻结 Ridge model bundle
完成五层链并发布无股数的 `TargetPackageV1`;聚宽/QMT 只做精确双时钟查找、
账户状态绑定和执行。当前 synthetic 包已经真实通过聚宽 execution consumer
但这只证明平台边界可运行;尚未证明上游四层的真实数据有效性、QMT peer 或
跨引擎一致性。
## 一条命令验证本地工程
要求 Python 3.10 或更高;核心没有第三方运行依赖:
```bash
make local
```
它依次执行:
1. 新 namespace 依赖边界和 80 分 profile 评估;
2. 全量单元/合约测试;
3. 聚宽与 QMT 单文件 bundle
4. synthetic execution smoke 与完整 manifest verifier
5. synthetic research-to-target 与 research manifest verifier
6. JoinQuant/QMT mock parity 报告及校验;
7. capability probe
8. Colab notebook 语法检查和逐 cell 本地执行。
等价的脚本入口:
```bash
bash scripts/validate_all.sh
```
主要本地产物位于被 Git 忽略的 `artifacts/`
```text
artifacts/
├── local-smoke/
│ ├── manifest.json
│ ├── signal.json
│ ├── target.json
│ ├── events.jsonl
│ ├── equity.json
│ └── report.json
├── research-smoke/
│ ├── manifest.json
│ ├── model_bundle.json
│ ├── target_package.json
│ ├── pipeline.json
│ ├── signals.json
│ ├── targets.json
│ ├── forecasts.json
│ ├── samples.json
│ └── report.json
└── mock-parity/report.json
```
`verify-ledger` 只验证事件 hash chain`verify-manifest` 还验证原子发布标记、
精确 artifact 集合与 SHA-256、ledger head、report/manifest 身份、
当前 source/schema 聚合 hash,以及 Signal、Target、OrderEvent JSON Schema。
## JQData:登录后直接跑真实数据本地回测
账号和密码只从无回显交互或本地环境变量读取,绝不写入 snapshot、notebook、
OB 或 Git。先创建独立环境:
```bash
python3.12 -m venv .venv-jqdata
source .venv-jqdata/bin/activate
python -m pip install -r requirements/jqdata.txt
```
生成一个中证 500 历史快照:
```bash
PYTHONPATH=src:. python tools/jqdata_snapshot.py \
--index 000905.XSHG \
--start 2024-01-02 \
--end 2024-12-31 \
--output data/snapshots/csi500-2024
```
adapter 使用官方 `get_bars` 的未复权 OHLCV/money、复权因子、
`pre_close``high_limit``low_limit``paused`,并通过
`get_extras("is_st", ...)` 保存每日 PIT ST 状态和每日历史指数成员。为避免
把尚未完成的当日线误标为完整收盘,`--end` 必须早于 Asia/Shanghai 的抓取
日期;JQData 日线 24:00 完成后才允许进入快照。字段、日期或成员覆盖不完整
都会 fail closed。快照 verifier 会重新构造领域对象、重算质量汇总与
`data_version`,不是只比文件 hash。
直接运行动态 PIT 成分的本地事件回测:
```bash
PYTHONPATH=src:. python -m quant60 snapshot-backtest \
--snapshot data/snapshots/csi500-2024/manifest.json \
--config configs/baseline.json \
--output artifacts/csi500-2024-backtest
PYTHONPATH=src:. python -m quant60 verify-manifest \
artifacts/csi500-2024-backtest/manifest.json
```
生成某个决策日的可移交 Signal/Target/Order Delta
```bash
PYTHONPATH=src:. python -m quant60 snapshot-decision \
--snapshot data/snapshots/csi500-2024/manifest.json \
--config configs/baseline.json \
--as-of 2024-12-31 \
--equity 1000000 \
--output artifacts/csi500-2024-decision
PYTHONPATH=src:. python -m quant60 verify-snapshot-decision \
artifacts/csi500-2024-decision/manifest.json
```
生产账户应把 `--equity` 换成 `--broker-snapshot`。该 canonical broker
snapshot 必须绑定同一个 T 日 Signal/decision,但其观察时钟只能位于冻结
provider calendar 的唯一下一交易日 Asia/Shanghai `[09:00,09:30)`;它还
必须没有未对账 open orders,并只保存加盐/带密钥的账户标识。不完整或错窗
状态会 fail closed。
这个本地回测采用:
- 每日精确 PIT 指数成员;
- 每日 PIT ST 状态;ST 证券不进入新目标,已持有 ST 只允许卖出;
- 原始价作为执行/名义价格;
- 仅使用截至每个决策日的 raw price + factor 构造定点前复权动量;
- 供应商每日停牌、涨跌停与前收字段;
- 第一交易日完整收盘形成信号,紧接着下一可用交易日开盘尝试成交;
- 上一交易日成交量参与率、显式费用、T+1、百股交易单位和未成交撤销。
它仍是本地 fill model,不是聚宽/QMT 的真实成交证据。
注意:现有 `snapshot-decision` 仍是 `portable-momentum-v1` 的 provider-data
路径,不能因为输入来自 JQData 就冒充 Ridge Baseline。完整候选链的权威交换物
`TargetPackageV1`;在真实数据训练、风险/成本校准与 OOS 冻结完成前,
`research-smoke/target_package.json` 只用于验证部署结构。
## Colab
打开 [`notebooks/quant_os_colab.ipynb`](notebooks/quant_os_colab.ipynb)
并执行全部默认 cell。默认流程不联网安装依赖,也不需要账号。
可选 cell
- `RUN_JQDATA=True`:无回显登录,生成 snapshot、本地 PIT backtest 与决策;
- `RUN_QLIB=True`:只在 Python 3.12 安装固定 Qlib 栈并跑 native fixture。
不要把密码、token 或带凭据的 clone URL 写进 cell。默认流程最终生成两个可下载
zip;启用 JQData 后再增加 backtest 与 decision zip。
本地可验证 notebook 本身:
```bash
python3 tools/run_colab_notebook.py notebooks/quant_os_colab.ipynb
python3 tools/run_colab_notebook.py notebooks/quant_os_colab.ipynb --execute
```
## 聚宽:直接上传回测
不传目标包时,构建的是历史兼容的动量 smoke:
```bash
python3 tools/bundle_platforms.py
```
上传完整的 [`dist/joinquant_strategy.py`](dist/joinquant_strategy.py)。
wrapper 已启用:
```python
set_option("avoid_future_data", True)
set_option("use_real_price", True)
run_daily(rebalance, time="open")
```
canonical 周时钟不是固定星期几:某 ISO 周第一实际交易日收盘形成计划,
下一实际交易日开盘执行;单交易日长假周会自然跨到下一周。wrapper 用
`context.previous_date` 查询 PIT 指数成员和 `is_st`,用批量
`history(..., fq="pre")` 取得已完成日线;卖单先行,以 `order_target`
提交 `当前数量 + 可执行 delta`,并在提交点重新检查 current data。手续费、
滑点和最大成交量占比 10% 都在策略内显式设置。科创板买卖使用当日涨/跌停价
作为限价保护;共享核心拒绝不足 200 股的普通科创板申报,只保留一次性卖清
不足 200 股余额的交易所例外。
2026-07-26 已用该动量 smoke bundle 完成一次真实聚宽全年 hosted backtest。运行记录、
bundle hash、指标、真实平台发现的问题和证据边界见
[`docs/JOINQUANT_HOSTED_EVIDENCE_2026-07-26.md`](docs/JOINQUANT_HOSTED_EVIDENCE_2026-07-26.md)。
该次运行的可见完成日志没有 `ERROR`,但尚未导出相同输入、plan、orders/fills
所以不计为 G9 通过。
真实验收必须保存:
- Git commit 与 `dist/bundle_manifest.json`
- 聚宽运行环境、日期、资金、benchmark、费率/滑点;
- `g.quant60_last_plan`、订单/成交、日志和完整回测导出;
- 与本地相同输入 close array 或其 hash。
本地 fake harness 与 `artifacts/mock-parity/report.json` 只证明 wrapper 合约。
单次 hosted smoke 是外部运行证据,但没有同输入跨引擎 manifest 时仍不算
真实聚宽 Gate 通过。
要验证五层候选链,必须显式传入已验真的 TargetPackage;打包器不会自动从
动量回退或把 smoke 提升成 Baseline
```bash
python3 tools/bundle_platforms.py \
--target-package artifacts/research-smoke/target_package.json \
--output-dir dist/target-package
```
这个示例包来自 synthetic 数据,只能验证线路。目标包保存 post-risk **权重**
及 model/data/feature/risk/cost/optimizer/config/source hash,不保存账户股数。
聚宽在包声明的 `next_session` 开盘读取真实 equity、持仓、可卖数量和价格,
形成 execution plan;包缺失、双时钟不匹配、hash 篡改或重复决策都会停止,
不会现场改算 momentum。
此时应上传
[`dist/target-package/joinquant_strategy.py`](dist/target-package/joinquant_strategy.py)
并以同目录
[`bundle_manifest.json`](dist/target-package/bundle_manifest.json)
核对 package ID、package SHA 与 tape SHA;不要误传默认 smoke 文件。
2026-07-26`TP-20240311-795dcfba` 已用 FINAL4 在真实 JoinQuant hosted
环境完成 2024-03-11 至 2024-03-13 的 execution smoke3 月 11/13 日为
精确时钟 no-op,3 月 12 日按 `CURRENT_DATA_DAY_OPEN` 命中包,生成 3 笔
委托并全部成交。`600519.XSHG` 虽有 10% 权重,但 1693.94 元开盘价使一手
价值 169,394 元,高于 100,000 元目标名义金额,因而合法取整为 0 股。
- 脱敏机器记录:
[`evidence/joinquant/TP-20240311-795dcfba/2457a7c39a276e09e0fabf99e28978e1/run.json`](evidence/joinquant/TP-20240311-795dcfba/2457a7c39a276e09e0fabf99e28978e1/run.json)
- 证据边界:
[`docs/JOINQUANT_TARGET_PACKAGE_EVIDENCE_2026-07-26.md`](docs/JOINQUANT_TARGET_PACKAGE_EVIDENCE_2026-07-26.md)
该 run 的 `platform_evidence_class``real_platform_runtime`,但输入
`input_evidence_class` 仍是 `synthetic-research`;它只支持
`execution.real_platform_observed=true`。JoinQuant 没有重跑本地冻结的
Universe、Alpha、Portfolio、Risk,三日收益字段仅用于识别 smoke,
`performance_claim=false`,不计 G9 或 Baseline 60。
## QMT built-in 与 qmttools
同一 bundler 可生成动量 smoke 或显式 TargetPackage 消费器:
```text
dist/qmt_builtin_strategy.py # 默认 momentum smoke
dist/target-package/qmt_builtin_strategy.py # synthetic 候选线路调试
dist/target-package/bundle_manifest.json # 目标包与 bundle 身份
```
在 QMT Python 策略编辑器导入,选择 `1d`**backtest**,主图/基准设为
`000905.SH`,初始资金与日期按证据计划填写,并把 GUI 的最大成交量占比设为
**10%**。bundle 兼容 Python 3.6,使用模块全局 `g` 保存策略状态,以适配
QMT 文档所述的 `ContextInfo` 用户属性回滚。它硬编码 backtest-only;参数和
环境变量均不能把它提升成实盘 `passorder`
在动量 smoke 模式,策略按原始毫秒 timetag 查询历史中证 500 成分,并通过
`ContextInfo.get_his_st_data` 读取决策日 ST/*ST/PT 区间;接口缺失、格式异常
或覆盖不足会阻止计划。首次真实验收还必须用一只已知历史 ST 股票做正例探针,
证明客户端权限和本地历史 ST 数据确实可用,不能把空结果直接解释成“当天无
ST”。在 TargetPackage 模式,Universe/Alpha/Portfolio/Risk 已由本地包冻结;
QMT 不重算这些层,只在包的 signal close 命中后绑定账户和完成日线价格,
`quickTrade=0` 交给下一执行步。两种模式的证据不得混记。
Windows 上、已登录且安装券商分发 `xtquant` 的 qmttools 入口:
```powershell
$env:PYTHONPATH = "src;."
python -m platforms.qmt_research_runner `
dist/target-package/qmt_builtin_strategy.py `
--stock-code 000905.SH `
--start 20240102 `
--end 20241231 `
--period 1d `
--asset 1000000 `
--account-id test
```
runner 固定 `trade_mode=backtest``quote_mode=history`,真实证据不得跳过
只读数据 preflight;它从 `configs/baseline.json` 固定 benchmark
`000905.SH`,并程序化传入 10% `max_vol_rate`。QMT 没有单独过户费参数,
本项目明确把它折入佣金;最低佣金与 fill 行为仍属于必须单列的引擎差异。
QMT 并不是“只给账号密码”即可远程完成:还必须有券商授权的 QMT/MiniQMT
客户端、匹配的 `xtquant`、userdata path、行情/历史数据权限和已经登录的账户。
这些就绪后,代码不需要改源文件,只注入 `.env.example` 中列出的本地参数。
## XtTrader:严格只读影子
外部 adapter 是 [`adapters/xttrader_live.py`](adapters/xttrader_live.py)。
`tools/qmt_shadow_plan.py` 只暴露查询接口,并始终以
`allow_live_orders=False` 创建 adapter;该工具没有报单或撤单命令。它会
二次检查 adapter 状态、账户归属、资产恒等式、持仓、委托、成交以及查询时长,
保存脱敏的 `broker_observation.json`、可校验的 `broker_snapshot.json`
全部 delta 为零或只读建议的 shadow plan。任一事实不可信就 fail closed。
账户绑定 decision 的绝对目标股数只在账户规模未变化时有效,因此 planner
还会比较 `decision.equity` 与当前 `total_asset`:允许差额固定为
`max(1 元, 0.01% × decision equity)`,边界包含;超过即产生
`DECISION_EQUITY_DRIFT`,状态为 `BLOCKED` 且 proposed delta 全部归零。
容差、计算规则、实际差额和结果全部写入 plan,并由 verifier 重新计算,不能
通过改 JSON 放宽。
read-only observation 还冻结 adapter query 后状态、live flag、callback
error 数、live-authorization history 数、query 起止时钟、原始记录数和事实
校验结果。query duration 的硬上限是 10 秒,资产/持仓市值及
`cash + market_value = total_asset` 的绝对容差硬上限是 1 元;CLI 只允许
收紧,builder 和 verifier 都拒绝放宽。verify 必须同时提供原始 decision
manifest。verifier 不相信 plan 中的 blockers、status、snapshot-valid、
target/weight/lot、feasible/proposed delta 或 cash/portfolio 派生值,而是从
原始 decision + `broker_observation.json` 重建唯一语义投影并逐项 exact
compare。`SHADOW_READY` 必须有可重建且内容完全一致的 broker snapshot
删除 blocker、注入假 blocker、同步改大目标量或把 snapshot 改成 `null`
重新计算普通 hash 都不能通过。
同一个本地 account HMAC key 还以独立 domain 签署 authenticated evidence
envelope;签名同时覆盖完整 plan、broker observation、broker snapshot 的
canonical 内容 hash 和三份确定性发布文件的原始 byte SHA-256,以及原始
decision manifest、planner/engine/`tools/qmt_shadow_plan.py` source 和固定
policy。四份发布 JSON(含 manifest)都必须逐 byte 等于唯一 writer 编码;
只做 minify、换序或空白改写也会失败。
verify 必须使用生成时的**既有** key;缺失/错误 key 失败,verify 不会生成
替代 key。该 MAC 只证明持 key 的 Quant OS 发布后未被无 key 改写,不是券商
对 API 原始事实的签名或 attestation。
在已登录的 Windows QMT/MiniQMT 环境先注入本地参数;不要在聊天、Git 或 OB
中发送它们:
```powershell
$env:PYTHONPATH = "src;."
$env:QMT_USERDATA_PATH = "C:\local\qmt\userdata_mini"
$env:QMT_ACCOUNT_ID = "<local-account-id>"
$env:QMT_SESSION_ID = "<unique-numeric-session-id>"
$env:QMT_ACCOUNT_HASH_KEY_FILE = "C:\local\quant-os\account-hash.key"
$env:DECISION_DATE = "<fresh-completed-trading-date>"
```
首次对一个尚未绑定账户的 snapshot decision 运行:
```powershell
python tools/qmt_shadow_plan.py plan `
--decision artifacts\csi500-2024-decision\manifest.json `
--output artifacts\qmt-shadow-bootstrap
```
若 broker 查询全部可信,首次运行仍会因 `DECISION_NOT_ACCOUNT_BOUND` 预期返回
退出码 2,但会输出可信的 `broker_snapshot.json`。若该文件内容为 JSON
`null`,说明观察事实不可信,禁止继续。用**同一个决策日**重新生成账户绑定的
decision
```powershell
python -m quant60 snapshot-decision `
--snapshot data\snapshots\latest\manifest.json `
--config configs\baseline.json `
--as-of $env:DECISION_DATE `
--broker-snapshot artifacts\qmt-shadow-bootstrap\broker_snapshot.json `
--output artifacts\qmt-bound-decision
python tools/qmt_shadow_plan.py plan `
--decision artifacts\qmt-bound-decision\manifest.json `
--output artifacts\qmt-shadow
python tools/qmt_shadow_plan.py verify `
--manifest artifacts\qmt-shadow\manifest.json `
--decision artifacts\qmt-bound-decision\manifest.json
```
Signal 仍绑定 T 日 15:00 完整收盘。JQData snapshot 冻结经过两套交易日历
API 一致性校验的 session 序列,并保存唯一 `next_trading_session`broker
查询只能在该 session 的 Asia/Shanghai `[09:00,09:30)` 盘前窗口完成。
周末、同日收盘后、09:30 边界、错误 session 和迟到多日都会 fail closed
国庆等长假按冻结交易日历接受,绝不使用 elapsed-day 阈值或 weekday 近似。
持仓变化不会沿用 decision 形成时的本地数量:target diff 每次都以当前券商
持仓和可卖量重新计算,逐 symbol 的 target quantity/weight/lot size 必须与
原始 decision 完全一致,未完成或查询期间变化的委托会直接阻断。当前 cash、
market value、total asset 和持仓市值恒等式由 verifier 独立重算。
现金/持仓变化仍可能影响购买力;
shadow 没有实时执行价,明确不做 buying-power 认定,所以
`SHADOW_READY` 只表示可人工审阅,始终不是可实盘提交。
plan 首次运行可自动生成账户 HMAC keyUnix 要求 0600verify 只读取既有
key。它必须稳定备份、限制访问且绝不
进入 Git、OB、notebook、日志或聊天。更换 key 会改变账户绑定标识并使旧决策
失配,也会使旧 evidence 无法通过 HMAC。当前流程仍是
`uncertified / not live-ready`;真实账户还必须先验证
官方 query API 对“失败”和“空列表”的返回合同,并记录实际
terminal/xtquant build、确认 `XtTrade.traded_amount` 成交金额语义与允许
误差。当前 amount 只是被认证的 informational fact,不参与 target quantity
或 proposed delta。之后还要先满足 Baseline 60 的至少 20 个交易日 shadow、
恢复演练和零未知账差;Production 80 当前要求同一冻结候选累计至少 60 个
交易日。
## Qlib 0.9.7
研究环境隔离在 CPython 3.12,关键数值/工作流依赖已固定:
```bash
python3.12 -m venv .venv-qlib312
source .venv-qlib312/bin/activate
python -m pip install -r requirements/research-py312.txt
python -c "import qlib; assert qlib.__version__ == '0.9.7'"
```
### 使用本地 Tushare 镜像
`tools/tushare_snapshot.py``tools/tushare_qlib.py` 不调用 Tushare、不读取
token,也不修改镜像。先从仍可变化的 raw mirror 冻结一个日期/API/指数范围
明确的 source manifest,再生成新 Qlib provider。provider 保存 source job、
build parameter、converter hash、tree hash 与可重算 `data_version`,并拒绝
覆盖已有目录。当前 build 不直接读取 scoped manifest,所以验收时还要确认
两份 manifest 的 source job/file hashes 完全一致。
推荐使用 Makefile 固定同一组路径和参数:
```bash
export TUSHARE_MIRROR_ROOT=/path/to/tushare-mirror
export TUSHARE_PROVIDER=data/qlib/tushare-csi500-2018-2025-next
export TUSHARE_SNAPSHOT=artifacts/local-tushare/scoped-source-manifest.json
make tushare-snapshot
make tushare-build
make tushare-verify
make tushare-lineage
make tushare-backtest
make tushare-replay
```
`TUSHARE_PROVIDER` 指向的 build 输出目录必须不存在;工具拒绝覆盖已有
provider。`tushare-replay` 会先生成第一份 run,再生成第二份并用 `cmp`
检查逐 byte 重放。
```bash
export TUSHARE_MIRROR_ROOT=/path/to/tushare-mirror
PYTHONPATH=src:. python tools/tushare_qlib.py inventory \
--mirror-root "$TUSHARE_MIRROR_ROOT" \
--skip-file-verification \
--output-json artifacts/tushare-inventory.json
python tools/tushare_snapshot.py \
--mirror-root "$TUSHARE_MIRROR_ROOT" \
--start 2018-01-01 \
--end 2025-12-31 \
--apis daily adj_factor trade_cal stock_basic index_daily index_weight \
--index-codes 000905.SH \
--output artifacts/local-tushare-20260731/scoped-source-manifest.json
PYTHONPATH=src:. python tools/tushare_qlib.py build \
--mirror-root "$TUSHARE_MIRROR_ROOT" \
--output-dir data/qlib/tushare-csi500-2018-2025-v2 \
--start 2018-01-01 --end 2025-12-31 \
--market-name tushare_csi500 \
--benchmark-index-code 000905.SH \
--universe-index-code 000905.SH \
--minimum-observations 60 \
--ohlc-policy fail \
--output-json artifacts/tushare-qlib-build.json
PYTHONPATH=src:. python tools/tushare_qlib.py verify \
data/qlib/tushare-csi500-2018-2025-v2
```
当前镜像已有 1990-12—2026-07 日线和复权因子、真实中证 500 指数行情与历史
权重、停牌和涨跌停数据;但 raw mirror 是移动目标,且历史 `stock_st` 权限被
拒。v2 provider verifier 和两次 byte-identical 真实本地 run 已完成,但
结果仍为 `production_ready=false``investment_value_claim=false`
`gate_credit=[]`。完整盘点、字段口径和本机
命令见 [`docs/TUSHARE_LOCAL_DATA.md`](docs/TUSHARE_LOCAL_DATA.md) 与
[`docs/runbooks/TUSHARE_QLIB_LOCAL_RUN.md`](docs/runbooks/TUSHARE_QLIB_LOCAL_RUN.md)。
native momentum smoke
```bash
python tools/build_qlib_tiny_fixture.py /tmp/quant-os-qlib --days 80
PYTHONPATH=src:. python -m platforms.qlib_runner \
--provider-uri /tmp/quant-os-qlib \
--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
```
本机实际运行 `pyqlib==0.9.7` 得到 24 条 signal,使用
`SimulatorExecutor + TopkDropoutStrategy`。结果 JSON 保存 signal 与
portfolio report 的稳定 hash、行列/时间边界,以及从 report 重算的累计收益、
最大回撤、基准收益、成本和换手;`investment_value_claim=false`。fixture
只有 smoke 意义。
Qlib 的统一 `limit_threshold` 不能表示逐日板块/ST 规则,因此只参加
L1/L2 与诊断 L6,不声称 L3 target/L4 order parity。
Alpha158/LightGBM CLI
```bash
PYTHONPATH=src:. python -m platforms.qlib_runner \
--workflow alpha158 \
--provider-uri /path/to/authorized/qlib-provider \
--market csi500 \
--benchmark SH000905 \
--train-start 2018-01-01 \
--train-end 2020-12-31 \
--valid-start 2021-01-01 \
--valid-end 2021-12-31 \
--test-start 2022-01-01 \
--test-end 2022-12-31 \
--experiment-name quant-os-alpha158 \
--output-json artifacts/qlib-alpha158/result.json
```
它通过 Qlib Recorder 保存 model、SignalRecord、SigAnaRecord 和
PortAnaRecordrunner 会读取 `report_normal_1day.pkl`,保存表级 hash、
行列/时间边界和有限值指标。真实研究必须换成授权且版本不可变的 provider。
## 跨引擎与证据
生成本地 wrapper 合同 parity
```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
```
报告逐层比较 score、weight、target quantity 与 order delta,并固定 source
hash;它明确写入:
```text
evidence_class = mock_contract_only
real_platform_pass = false
gate_credit = []
```
Baseline 60 的真实 G9 仍要求聚宽/QMT 导出与至少 20 个交易日 QMT 影子记录;
Production 80 当前要求同一冻结候选至少 60 个交易日。完整层级、
容差和 reason code 见
[`docs/CROSS_ENGINE_CONSISTENCY.md`](docs/CROSS_ENGINE_CONSISTENCY.md)。
## 已实现的系统模块
- `pit.py``effective_time` / `available_time`、修订版本、未来值拒绝;
- `universe.py`openable / hold-only / sell-only / frozen / excluded
- `features.py`:透明价量特征、可执行时钟标签、train-only 预处理;
- `research.py` / `experiment.py`purge/embargo、Ridge、OOS IC/RankIC
- `model_bundle.py`:冻结 train-only 预处理、Ridge 参数、标签与训练 lineage
- `baseline_pipeline.py`:唯一五层本地主链和因果 hash trace;
- `target_package.py`:无股数、双时钟、可防篡改的 post-risk 权重合同;
- `release_reachability.py`:逐层区分 implemented、tested、entrypoint
reachable 与 real-platform observed
- `factor_risk.py`:行业/风格暴露、EWMA 收缩因子协方差、特异风险、stress;
- `costs.py`:日期化费率、最低佣金、low/base/high impact 与 capacity
- `optimizer.py`deterministic fallback 与 lazy CVXPY 约束优化;
- `execution.py`guarded TWAP/POV parent-child planner
- `domain.py` / `broker.py`A 股事件撮合与订单状态;
- `ledger.py` / `replay.py` / `reconcile.py`hash-chain、幂等重放、fail-closed 对账;
- `data_snapshot.py` / `snapshot_pipeline.py` / `snapshot_backtest.py`
provider snapshot 到 PIT target 与本地历史回测;
- `platforms/` / `adapters/`:聚宽、QMT、Qlib 与 XtTrader 边界。
组件存在、单测通过、进入本地入口、进入平台入口和真实平台观察是五种不同
事实。聚宽现有 TargetPackage run 只观察 execution consumer;它不证明
factor risk、CVXPY、TWAP/POV 或 Ridge 上游四层在 hosted 环境被调用。
## 仍未达到 60 的核心原因
- 基本面公告时点、完整公司行动、Security Master 与退市链尚未形成生产数据湖;
- Ridge 已能冻结成可重放 model bundle,但目前只有 synthetic 候选;
尚无授权真实长样本 OOS,也没有必要让 hosted 引擎重新加载训练栈;
- 风险协方差、冲击参数和容量尚未用真实长样本校准;
- factor risk、CVXPY 和 guarded TWAP/POV 仍是组件级能力,尚未进入当前
Baseline vertical slice
- 聚宽已有单包 TargetPackage execution 导出,但仍缺授权真实数据的多期
TargetPackage、本地/聚宽逐层同输入对账;QMT 尚无真实 peer 导出,QMT
历史 ST 权限正例、账户 query 合同、
Baseline 60 所需 20 日只读影子、回调/恢复/对账尚未形成真实证据;
Production 80 还要求同一冻结候选累计至少 60 个交易日 shadow;
- 自动 scheduler、日终对账服务、监控告警与 kill-switch 演练未形成连续证据;
- 实际券商程序化交易报告、权限、频率与软件要求尚未书面确认。
因此当前是“已接通本地五层与平台 TargetPackage 边界的候选骨架”,不是已经
达到 60 分或可直接投入资金的成品,也不构成投资建议。
## 安全与进一步文档
凭据、cookie、QMT userdata、broker statement、licensed `xtquant` 与无转授权
行情数据一律不得进入 Git。
- 架构:[`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md)
- 五层真实结构与缺口:
[`docs/BASELINE_VERTICAL_SLICE.md`](docs/BASELINE_VERTICAL_SLICE.md)
- 平台矩阵:[`docs/PLATFORM_MATRIX.md`](docs/PLATFORM_MATRIX.md)
- 聚宽 TargetPackage 证据:
[`docs/JOINQUANT_TARGET_PACKAGE_EVIDENCE_2026-07-26.md`](docs/JOINQUANT_TARGET_PACKAGE_EVIDENCE_2026-07-26.md)
- 部署:[`runbooks/PLATFORM_DEPLOYMENT.md`](runbooks/PLATFORM_DEPLOYMENT.md)
- 安全:[`docs/SECURITY.md`](docs/SECURITY.md)
- 故障:[`runbooks/INCIDENTS.md`](runbooks/INCIDENTS.md)
- 复评:[`docs/AUDIT_2026-07-25.md`](docs/AUDIT_2026-07-25.md)