323 lines
17 KiB
Markdown
323 lines
17 KiB
Markdown
# Quant OS architecture and trust boundaries
|
||
|
||
Quant OS 是项目;`quant60` 是第一版 A 股 Baseline 内核、CLI namespace
|
||
和 artifact 协议前缀。当前形态是模块化单体:共享可移植计算和稳定合同,但把
|
||
数据供应商、hosted 平台、QMT 专有运行时与券商事实放在不同信任边界内。
|
||
|
||
```text
|
||
JQData (authorized account)
|
||
get_bars(raw OHLCV/money, factor, pre_close, limits, paused)
|
||
+ daily PIT is_st + daily PIT index membership
|
||
|
|
||
v
|
||
canonical immutable snapshot
|
||
exact-set/hash + semantic reconstruction
|
||
|
|
||
+----------------------+
|
||
|
|
||
v
|
||
snapshot-backtest / snapshot-decision
|
||
portable-momentum-v1 compatibility path (smoke only)
|
||
|
||
local Baseline authority:
|
||
Universe
|
||
-> frozen Ridge model bundle / Alpha
|
||
-> risk + cost-aware Portfolio
|
||
-> post-risk TargetPackageV1 (weights, no account quantities)
|
||
-> five-layer hash trace
|
||
|
|
||
+------------+-------------+
|
||
| |
|
||
JoinQuant consumer QMT consumer
|
||
T+1-open account bind completed-close bind + quickTrade=0
|
||
order_target passorder (backtest-only)
|
||
|
||
Current TargetPackage fixture is synthetic research evidence, not market proof.
|
||
|
||
Qlib 0.9.7:
|
||
Tushare completed/checksummed Parquet -> immutable managed provider
|
||
native portable-momentum signal bridge
|
||
Alpha158 + LightGBM + Recorder research workflow
|
||
(no L3 target / L4 order-intent parity)
|
||
|
||
XtTrader:
|
||
read-only broker observation -> HMAC account-bound shadow plan
|
||
callback/mutation boundary remains uncertified and operator-inaccessible
|
||
```
|
||
|
||
箭头表示数据或合同流,不表示平台能力等价。hosted 引擎拥有自己的时钟、行情
|
||
和成交语义;broker snapshot/callback 才是现金、持仓、可卖量、订单和成交的
|
||
事实权威。本地 ledger 不能用预测持仓覆盖券商事实。
|
||
|
||
## Runtime split
|
||
|
||
| Layer | Runtime | Rule |
|
||
| --- | --- | --- |
|
||
| Quant OS / `quant60` | Python ≥3.10 | 本地回测、snapshot pipeline、research、ledger、CLI |
|
||
| JQData ingestion | 独立 Python 环境,`jqdatasdk==1.9.8` | 只从授权账户获取数据;凭据不进入快照 |
|
||
| Qlib research | CPython 3.12.x,`pyqlib==0.9.7` | 与本地/QMT 环境隔离;provider 必须授权且版本化 |
|
||
| Portable strategy core | Python 3.6-compatible source | 无第三方依赖;bundler 内联到 hosted 策略 |
|
||
| JoinQuant hosted | 平台管理 | 上传生成的单文件;不能假设安装本地包 |
|
||
| QMT built-in | QMT Python 3.6 | 只上传 bundle;模块全局 `g` 持久状态,避免 `ContextInfo` 用户属性回滚 |
|
||
| qmttools / XtTrader | 券商分发的 native Python | `xtquant` 专有且 lazy import,不进入仓库 |
|
||
| Colab | notebook runtime | 默认只跑无账号流程;JQData/Qlib 是显式可选 cell |
|
||
|
||
不要用一个 Python 环境强行兼容所有路径。
|
||
|
||
## Data plane and point-in-time semantics
|
||
|
||
本地 Tushare live mirror 是独立只读输入边界。scoped snapshot 在一次 SQLite
|
||
读事务中选择目标日期/API/指数的 canonical completed job,并重新核对文件
|
||
大小、SHA-256、Parquet 行数/footer;Qlib provider 发布到新目录,manifest
|
||
绑定 source job、build parameter、converter source、完整 provider tree 和
|
||
可重算 `data_version`。当前已有复权因子、真实 `000905.SH` benchmark/历史
|
||
权重、停牌和涨跌停数据,但 live mirror 仍可变化,且 `stock_st` 权限被拒;
|
||
因此必须先冻结、再验证,不能直接进入完整 canonical production decision。完整合同见
|
||
[`TUSHARE_LOCAL_DATA.md`](TUSHARE_LOCAL_DATA.md)。
|
||
|
||
JQData adapter 的输入合同是逐交易日历史指数成员和 `get_bars` 日线字段:
|
||
|
||
- 未复权 `open/high/low/close`、`volume`、`money`;
|
||
- 复权因子 `factor`;
|
||
- `pre_close`、`high_limit`、`low_limit`、`paused`;
|
||
- 每个 member-date 的严格布尔 PIT `is_st`;
|
||
- `skip_paused=False`,保留停牌日语义。
|
||
|
||
快照保存 `bars.jsonl`、`memberships.jsonl`、`quality.json` 和
|
||
`manifest.json`。发布期间存在 incomplete marker;完成后 verifier 要求目录
|
||
是精确 artifact 集、每个文件 hash 正确,并从 JSONL 重建领域对象,重算质量
|
||
汇总、内容 hash 和 `data_version`。这比“下载成功”更强,但在授权真实账户运行
|
||
并保存许可/lineage 前,仍不构成 G1 证据。
|
||
|
||
JQData 日线在 24:00 完成,因此 adapter 拒绝把 Asia/Shanghai retrieval
|
||
当日作为 `T_CLOSE_COMPLETE`;请求 `end` 必须早于抓取日期。字段、ST 或成员
|
||
覆盖不完整也不会被当成默认 false/空集合。
|
||
|
||
`snapshot-decision` 只用 `as_of` 当日精确 PIT 成员和截至当日的数据。
|
||
执行/名义价格保持 raw;动量把每个历史 close 乘以当日可见 factor,再归一到
|
||
决策日因子,因此后续公司行动不会改写已经形成的历史决策。held but
|
||
untradable 标的不会从 Universe 消失,而会进入 frozen / hold-only /
|
||
sell-only 状态。
|
||
|
||
若目标用于下一交易日开盘前 shadow,Signal 时钟仍是 T 日 15:00。snapshot
|
||
冻结 JQData `get_trade_days` 与 `get_all_trade_days` 一致性校验后的完整
|
||
交易日序列,并显式保存 end 日后的唯一 `next_trading_session`。decision、
|
||
broker snapshot 和 shadow plan 必须绑定同一个相邻 session,以及
|
||
Asia/Shanghai `[09:00,09:30)` 的 `first_executable_window`;elapsed-day
|
||
阈值和 weekday 近似都不是权威。周末、T 日 15:01、错过 09:30、错误 session 或
|
||
迟到多日全部 fail closed,国庆等长假只要下一 session 来自冻结日历即可。
|
||
|
||
账户绑定后还必须保持决策规模有效。shadow 对 `decision.equity` 和当前
|
||
`total_asset` 使用固定的
|
||
`max(1 元, 0.01% × abs(decision equity))` 包含边界容差;缺失、负数、
|
||
非有限值或超差都不能进入 ready,超差原因码为
|
||
`DECISION_EQUITY_DRIFT`。该合同进入 plan hash,verifier 会从原始两个权益值
|
||
重新计算差额、阈值和 blocker。
|
||
|
||
QMT shadow verifier 使用 semantic replay,而不把 plan 当成事实来源。
|
||
`broker_observation.json` 保存 query 后 adapter state、live flag、callback
|
||
error/live-authorization history 计数、query 起止、原始记录数、校验结果及
|
||
脱敏资产/持仓/委托/成交事实。原始 decision manifest 是 verify 的必需输入。
|
||
纯 replay 从这两个输入独立重建 account binding、clock gate、资产和现金
|
||
恒等式、open/order-stability、trade/fill identity、完整 blocker 集、
|
||
snapshot-valid、完整 broker snapshot、逐 symbol target/weight/lot、
|
||
board-lot/sellable feasible delta、proposal、portfolio 和 status,再与 plan
|
||
exact compare。因而 plan 中同步改写多个派生字段或删除 blocker 不能形成新的
|
||
`SHADOW_READY`;READY 也强制存在可重建 snapshot。
|
||
|
||
普通 artifact hash 之外,planner 使用既有 account HMAC key 和独立 domain
|
||
签署 `QMT_SHADOW_EVIDENCE_V1` envelope。envelope 绑定完整 plan、
|
||
broker observation、broker snapshot 的 canonical 内容 hash 和三份实际发布
|
||
bytes 的 SHA-256、原始 decision manifest hash、planner/engine 及 operator
|
||
entrypoint `tools/qmt_shadow_plan.py` source hash,以及 semantic version、
|
||
10 秒/1 元 policy ceiling 和 equity drift policy。四个发布 JSON(包括
|
||
不参与自签名的 manifest)还必须逐 byte 符合唯一 deterministic writer
|
||
encoding。verifier 从当前真实输入与磁盘实际 bytes 重建
|
||
envelope 并 constant-time 比较 MAC;缺失、错误或轮换后的 key 全部失败。
|
||
这提供的是 Quant OS 本地 evidence publisher authenticity/完整性,不是
|
||
QMT/券商对 query result 的原生签名,也不把 adapter 升级成 broker-certified。
|
||
|
||
策略安全阈值是 canonical policy:query window 上限 10 秒,资产/持仓市值和
|
||
`cash + market_value = total_asset` 的绝对容差上限 1 元。CLI 只能使用等于
|
||
或更严格的值,builder 与 replay 都拒绝更宽值。目标权重总和还必须不超过
|
||
1,作为无报价条件下可独立证明的决策现金预算;实时 buying power(含成交价、
|
||
费用和卖出先后)仍不作证明。
|
||
|
||
持仓 drift 不会复用旧持仓:每次 target diff 都从当前券商 positions 和
|
||
sellable quantity 重算,且 open/变化中订单会阻断。因此数量 residual 不会
|
||
因旧持仓静默失真。由于 shadow 没有实时执行价,现金购买力仍不能被证明;
|
||
plan 明示该限制,ready 仅供人工审阅,不能升级为 live submission。
|
||
`trade.amount` 当前会被标准化、认证和重放,但在缺少真实
|
||
terminal/xtquant build 探针时不假设它与 `price × quantity` 的精确误差
|
||
合同;它不参与 target diff,正式券商验收必须记录 build 并冻结字段容差。
|
||
|
||
`snapshot-backtest` 在每个历史决策日重新调用同一 decision path,并使用:
|
||
|
||
- 第一实际交易日完整收盘形成计划;
|
||
- 紧接着下一实际交易日开盘尝试成交;
|
||
- 当日供应商停牌/涨跌停/前收字段;
|
||
- 上一交易日成交量参与率;
|
||
- T+1、百股交易单位、显式费用和未成交撤销。
|
||
|
||
这是本地 fill model,不是 JoinQuant 或 QMT 的成交事实。
|
||
|
||
## Research and model boundary
|
||
|
||
synthetic research vertical slice 当前实际接通:
|
||
|
||
- PIT table 和未来值拒绝;
|
||
- Universe 原因码;
|
||
- 透明价量特征与 T+1-open 标签时钟;
|
||
- train-only winsor/impute/standardize;
|
||
- purge/embargo walk-forward;
|
||
- deterministic Ridge、OOS IC/RankIC 与可重放 model bundle;
|
||
- 60 日对角 realized variance;
|
||
- dated explicit fee + spread + square-root impact/capacity;
|
||
- deterministic constrained portfolio、独立 post-risk gate;
|
||
- reference execution binding、完整五层 hash trace 与 TargetPackageV1。
|
||
|
||
`factor_risk.py`、CVXPY 路径和 guarded TWAP/POV 仍是有单测的独立组件,
|
||
不在上述 vertical slice 中。Ridge 已能冻结预处理、系数、标签、训练截止日
|
||
和 lineage,但目前只有 synthetic 候选;没有授权真实长样本 OOS、真实风险/
|
||
成本校准、多期逐层 parity 或 QMT peer,因此不是生产 champion。已有的单包
|
||
JoinQuant run 只观察 execution consumer。
|
||
|
||
Qlib 路径固定为 `0.9.7`。CPython 3.12 实际 fixture smoke 已得到:
|
||
|
||
- native momentum:24 条 signal;
|
||
- Alpha158 + LightGBM:完成 fit、SignalRecord、SigAnaRecord、
|
||
PortAnaRecord 和 model 保存;
|
||
- 两条 workflow 都保存表级 hash、行列/时间边界和从 portfolio report
|
||
重算的有限值指标,明确 `investment_value_claim=false`;
|
||
- local MLflow file store 使用时,runner 以
|
||
`os.environ.setdefault("MLFLOW_ALLOW_FILE_STORE", "true")` 显式确认。
|
||
- 旧 Tushare 早期未复权 managed provider/momentum smoke 在
|
||
`PYTHONHASHSEED=0` 下连续两次得到逐 byte 相同的 evidence JSON;它只证明
|
||
旧转换器和运行时可重放;
|
||
- 2018—2025 v2 managed provider 已使用真实复权、`SH000905` benchmark 和
|
||
PIT index-weight universe,通过 verifier;同一 momentum run 两次 JSON
|
||
byte-identical。月末权重保守地从下一 provider 交易日生效,
|
||
`same_session_membership_use=false`;97 个 observed snapshots 形成 96 个
|
||
effective rosters,每个严格 500 成分、weight sum 100±0.5,最大间隔 36 天。
|
||
live DB/WAL 可被无关下载任务修改,但 221 个 scoped jobs double verified、
|
||
验证后仍为 latest;独立 lineage 工具对 221 jobs 的 6 个身份字段得到
|
||
mismatch 0,并确认 converter source 为 current。它仍是
|
||
event-time/保守次日生效 PIT 近似,不是严格 knowledge-time PIT;不同
|
||
`start` 的首观测锚 provider 不可直接拼接。它仍是 research-only、
|
||
`gate_credit=[]`,不表达历史 ST 和逐股逐日涨跌停。
|
||
|
||
该 fixture 只有两只股票和一个 benchmark,性能没有投资意义。Qlib 的单一
|
||
`limit_threshold` 也不能表达逐日板块/ST 规则,所以它只参与 L1/L2 和诊断
|
||
L6,不声称 L3 target 或 L4 order-intent parity。
|
||
|
||
## Portable strategy and platform boundary
|
||
|
||
hosted artifact 有两个互斥模式:
|
||
|
||
- `portable_momentum_smoke`:保留历史连通性回归,平台端计算动量;
|
||
- `target_package`:本地唯一权威已完成 Universe/Alpha/Portfolio/Risk,
|
||
hosted wrapper 只验证包、精确匹配 `signal_as_of + next_session`、读取账户
|
||
事实并构造 execution plan,绝不回退到 momentum。
|
||
|
||
`portable-momentum-v1` 不是生产 Baseline。TargetPackage 只有权重,没有股数、
|
||
现金、订单或成交;这些属于下一交易日平台账户绑定后的 execution layer。
|
||
|
||
canonical 股票代码采用 JoinQuant 形式:
|
||
|
||
| Canonical | QMT/XtQuant | Qlib |
|
||
| --- | --- | --- |
|
||
| `600000.XSHG` | `600000.SH` | `SH600000` |
|
||
| `000001.XSHE` | `000001.SZ` | `SZ000001` |
|
||
| `830799.XBSE` | `830799.BJ` | `BJ830799` |
|
||
|
||
转换权威是 `quant60.portable_core.normalize_symbol`。当前 XtTrader mutation
|
||
边界只接受 `.SH` / `.SZ`,不能从转换覆盖推导北交所实盘覆盖。
|
||
|
||
QMT built-in bundle 和 qmttools runner 都硬限制为 backtest/history。built-in
|
||
状态存放在模块全局 `g`,不写入可能在下个 `handlebar` 回滚的
|
||
`ContextInfo` 用户属性。动量 smoke 路径固定中证 500 benchmark、PIT 历史
|
||
成分/ST 与费率;TargetPackage 路径消费本地冻结 Universe/权重,不重新计算
|
||
Alpha/Portfolio/Risk。built-in 的 10% 参与率由 QMT GUI 设置,qmttools
|
||
程序化传入。live mutation 只存在于外部 XtTrader adapter,并且默认关闭、
|
||
未认证、没有 live 启动命令;operator 可运行的 shadow CLI 只接受查询边界。
|
||
|
||
## Stable artifacts and release integrity
|
||
|
||
最低交换合同是:
|
||
|
||
- [`model_bundle.schema.json`](../schemas/model_bundle.schema.json);
|
||
- [`target_package.schema.json`](../schemas/target_package.schema.json);
|
||
- [`release_reachability.schema.json`](../schemas/release_reachability.schema.json);
|
||
- [`signal.schema.json`](../schemas/signal.schema.json);
|
||
- [`target.schema.json`](../schemas/target.schema.json);
|
||
- [`order_event.schema.json`](../schemas/order_event.schema.json);
|
||
- [`broker_snapshot.schema.json`](../schemas/broker_snapshot.schema.json)。
|
||
|
||
`verify-manifest` 不仅检查 ledger hash chain,还检查 incomplete marker、
|
||
精确 artifact 集、SHA-256、ledger head、report/manifest identity、
|
||
saved/current source aggregate、saved/current schema aggregate 和 payload
|
||
schema。`verify-snapshot-decision` 与 data snapshot semantic verifier 承担
|
||
各自边界的同类职责。
|
||
|
||
`release_reachability` 对每层分别记录 `implemented`、`unit_tested`、
|
||
`local_entrypoint_reachable`、`jq_entrypoint_reachable`、
|
||
`qmt_entrypoint_reachable` 和 `real_platform_observed`,并逐文件验证路径与
|
||
SHA。源文件总 hash 不能冒充真实运行。测试结果仍不能替代 schema 迁移演练、
|
||
真实平台导出或券商回调认证。当前只有
|
||
`execution.real_platform_observed=true`,由一个真实 JoinQuant
|
||
TargetPackage smoke 支持;其他四层及 all-layer summary 仍为 false。
|
||
|
||
## Clocks and reconciliation
|
||
|
||
canonical weekly clock 是:
|
||
|
||
```text
|
||
ISO 周第一实际交易日:完整 close
|
||
-> 使用 as_of 之前实际可得信息形成 signal/target/order intent
|
||
紧接着下一实际交易日:open executable window
|
||
-> 刷新市场规则与 broker snapshot
|
||
-> pre-trade gate
|
||
-> backtest/shadow submit 或 fail closed
|
||
-> callback append + reconciliation
|
||
```
|
||
|
||
“紧接着下一日”是交易日关系,不是固定星期几。每个真实平台 run 必须记录
|
||
`signal_as_of`、`last_feature_bar`、`first_executable_time`、
|
||
price adjustment 和 fill model。
|
||
|
||
完整 reconciliation 要同时比较 cash、positions、sellable quantities、
|
||
open orders 和带时区的新鲜 `as_of/source_time`。legacy/partial snapshot
|
||
即使数值碰巧平衡,也不能把 `safe_to_open` 设为 true。
|
||
|
||
## Facts and current claim
|
||
|
||
| Fact | Authority |
|
||
| --- | --- |
|
||
| canonical symbol、portable calculation | versioned source + config |
|
||
| snapshot 内容 | semantic verifier 通过的 immutable snapshot + manifest |
|
||
| historical provider entitlement | 实际数据账户许可与保存的 lineage 记录 |
|
||
| hosted 回测时钟/成交 | 平台真实导出 |
|
||
| cash、position、order、fill | broker snapshot/callback |
|
||
| 程序化交易权限与报告 | 实际券商书面确认 |
|
||
| Gate 状态 | [`gate_scorecard.json`](../gate_scorecard.json) |
|
||
|
||
synthetic/fake 数据是合同测试,不是市场证据;Qlib synthetic fixture 的真实
|
||
运行是运行时证据,不是收益证据;mock parity exporter 是 wrapper 合同证据,
|
||
不计 G9。
|
||
|
||
## Remaining production gaps
|
||
|
||
当前还缺:
|
||
|
||
- 授权 JQData 真实快照、基本面公告 PIT、完整公司行动/Security Master;
|
||
- 授权真实数据训练的冻结模型包和真实 OOS 证据;
|
||
- 真实数据校准的风险、冲击、容量和 TCA;
|
||
- 授权真实数据的多期 JoinQuant 导出、逐层本地对账与真实 QMT peer;
|
||
- 券商状态映射、restart recovery daemon、连续对账,以及 Production 80
|
||
要求的同一冻结候选 60 日 shadow(Baseline 60 的前置门槛为 20 日);
|
||
- 运维监控、kill-switch 演练和券商程序化交易报告/核查确认。
|
||
|
||
所以 Quant OS 已具备本地五层 vertical slice 与 TargetPackage 平台边界,
|
||
但仍只是可继续填证据的候选骨架,不是已经达到整体 60 分的实盘系统。证据政策见
|
||
[`AUDIT_2026-07-25.md`](AUDIT_2026-07-25.md)。
|