feat: add Quant OS A-share baseline
This commit is contained in:
@@ -0,0 +1,252 @@
|
||||
# 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/<run-id>/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/<decision-id>/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)。
|
||||
Reference in New Issue
Block a user