618 lines
30 KiB
Markdown
618 lines
30 KiB
Markdown
# Quant OS:个人 A 股 60 分 Baseline 工程
|
||
|
||
Quant OS 是项目名;`quant60` 是第一版 A 股 Baseline 的 Python
|
||
包、CLI namespace 与 artifact 协议前缀。
|
||
|
||
本项目把 2026-07-22 的技术选型文章落成一个可执行、可审计的模块化单体:
|
||
本地与 Colab 可零账号运行工程 smoke;JQData 登录后可生成不可变快照并直接
|
||
运行 PIT 本地回测/目标决策;聚宽、QMT 与 Qlib 有各自明确的运行入口。
|
||
|
||
> 当前状态仍是 `NOT_BASELINE_60`。本地五层 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)。
|
||
|
||
## 在线公开验收面板
|
||
|
||
公开只读入口:
|
||
|
||
[`https://gomars.fun/quants-strategies/quant-os/status/index.html`](https://gomars.fun/quants-strategies/quant-os/status/index.html)
|
||
|
||
页面从 `gate_scorecard.json`、平台矩阵、bundle manifest 和证据文档生成
|
||
脱敏的构建时快照,逐层展示数据、模型、回测平台、券商影子盘与 G1—G10
|
||
缺口。它不是实时服务健康页,不发布本地行情、账户状态或运行 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 | 默认动量 smoke;TargetPackage 模式为 Python 3.6 backtest-only 消费器 | Python 3.6 语法、TargetPackage/fake/qmttools 合约 | 需要已授权 QMT 客户端、历史数据权限与 TargetPackage 实跑导出 |
|
||
| Qlib 0.9.7 | native momentum backtest;Alpha158/LightGBM CLI/Recorder 工作流 | Python 3.12 两条 fixture 已真实跑通,并保存表级 hash、行列/时间边界和重算指标 | synthetic 两股票没有投资价值;无真实 OOS、L3/L4 parity |
|
||
| Tushare → Qlib | 只读盘点 completed Parquet、校验 checksum、构建/验证不可变 provider、运行本地回测 | 93 个 completed 文件已验证;早期未复权 provider 与两次 byte-identical momentum run | 下载仅到 1993-10;缺复权、真实 benchmark、历史成分/ST/停牌/涨跌停,不能进入生产 decision |
|
||
| XtTrader shadow | 只读账户查询、HMAC 账户绑定、broker observation/snapshot、零下单 target-diff 计划与完整 verifier | fake broker/QMT 合约;所有 broker mutation 均不可达 | 需要授权 QMT 环境的账户合同探针、20 日影子、恢复/对账和券商确认 |
|
||
|
||
`portable-momentum-v1` 只是当前真实跑过聚宽的跨引擎连通性 smoke,不是
|
||
60 分 Baseline。Baseline 的权威决策留在本地:冻结 Ridge model bundle,
|
||
完成五层链并发布无股数的 `TargetPackageV1`;聚宽/QMT 只做精确双时钟查找、
|
||
账户状态绑定和执行。当前 synthetic 包已经真实通过聚宽 execution consumer,
|
||
但这只证明平台边界可运行;尚未证明上游四层的真实数据有效性、QMT peer 或
|
||
跨引擎一致性。
|
||
|
||
## 一条命令验证本地工程
|
||
|
||
要求 Python 3.10 或更高;核心没有第三方运行依赖:
|
||
|
||
```bash
|
||
make local
|
||
```
|
||
|
||
它依次执行:
|
||
|
||
1. 全量单元/合约测试;
|
||
2. 聚宽与 QMT 单文件 bundle;
|
||
3. synthetic execution smoke 与完整 manifest verifier;
|
||
4. synthetic research-to-target 与 research manifest verifier;
|
||
5. JoinQuant/QMT mock parity 报告及校验;
|
||
6. capability probe;
|
||
7. 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 smoke:3 月 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 key,Unix 要求 0600;verify 只读取既有
|
||
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。之后还要累计至少 20 个交易日、恢复演练和零未知账差。
|
||
|
||
## 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_qlib.py` 不调用 Tushare、不读取 token,也不修改镜像。它只接受
|
||
SQLite 中状态为 `completed` 且文件大小、SHA-256、Parquet 行数一致的分区;
|
||
生成新 Qlib provider 时保存 source job、build parameter、converter hash、
|
||
tree hash 与可重算 `data_version`,并拒绝覆盖已有目录。
|
||
|
||
```bash
|
||
export TUSHARE_MIRROR_ROOT=/path/to/tushare-mirror
|
||
|
||
PYTHONPATH=src:. python tools/tushare_qlib.py inventory \
|
||
--mirror-root "$TUSHARE_MIRROR_ROOT" \
|
||
--output-json artifacts/tushare-inventory.json
|
||
|
||
PYTHONPATH=src:. python tools/tushare_qlib.py build \
|
||
--mirror-root "$TUSHARE_MIRROR_ROOT" \
|
||
--output-dir data/qlib/tushare-early-v1 \
|
||
--start 1990-12-19 --end 1993-10-29 \
|
||
--minimum-observations 60 \
|
||
--allow-unadjusted \
|
||
--ohlc-policy expand-range \
|
||
--output-json artifacts/tushare-qlib-build.json
|
||
|
||
PYTHONPATH=src:. python tools/tushare_qlib.py verify \
|
||
data/qlib/tushare-early-v1
|
||
```
|
||
|
||
当前镜像只有 1990-12—1993-10 日线,且没有 `adj_factor`、真实指数行情、
|
||
历史成分、ST、停牌和涨跌停数据。因此 `--allow-unadjusted` 是显式技术
|
||
smoke 降级,provider 固定 `production_eligible=false`、
|
||
`investment_value_claim=false`、`gate_credit=[]`。盘点、字段口径、完整命令、
|
||
v4 hash 与两次本地回测结果见
|
||
[`docs/TUSHARE_LOCAL_DATA.md`](docs/TUSHARE_LOCAL_DATA.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 和
|
||
PortAnaRecord;runner 会读取 `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 = []
|
||
```
|
||
|
||
真实 G9 仍要求聚宽/QMT 导出与至少 20 个交易日 QMT 影子记录。完整层级、
|
||
容差和 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 合同、
|
||
20 日只读影子、回调/恢复/对账尚未形成真实证据;
|
||
- 自动 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)
|