Files
quant-os/docs/ARCHITECTURE.md
T

15 KiB
Raw Blame History

Quant OS architecture and trust boundaries

Quant OS 是项目;quant60 是第一版 A 股 Baseline 内核、CLI namespace 和 artifact 协议前缀。当前形态是模块化单体:共享可移植计算和稳定合同,但把 数据供应商、hosted 平台、QMT 专有运行时与券商事实放在不同信任边界内。

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                    v
 snapshot-backtest      snapshot-decision
 local event engine     Signal -> Target -> Order Delta
          |                    |
          +---------+----------+
                    |
            portable-momentum-v1
                    |
       +------------+-------------+
       |            |             |
 JoinQuant bundle  QMT bundle   local contract oracle
 hosted backtest   built-in/qmttools backtest-only

synthetic PIT/features -> purged walk-forward -> Ridge challenger
                                                  (not deployment-frozen)

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.xpyqlib==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 镜像是独立只读输入边界。adapter 只信任 SQLite 中 completed job,并重新核对文件大小、SHA-256、Parquet 行数/footerQlib provider 发布到新目录,manifest 绑定 source job、build parameter、converter source、 完整 provider tree 和可重算 data_version。当前镜像未完成且缺复权、 真实 benchmark、历史成分/ST/停牌/涨跌停,因此只能进入 Qlib 技术 smoke 不能直接进入 canonical production decision。完整合同与实跑证据见 TUSHARE_LOCAL_DATA.md

JQData adapter 的输入合同是逐交易日历史指数成员和 get_bars 日线字段:

  • 未复权 open/high/low/closevolumemoney
  • 复权因子 factor
  • pre_closehigh_limitlow_limitpaused
  • 每个 member-date 的严格布尔 PIT is_st
  • skip_paused=False,保留停牌日语义。

快照保存 bars.jsonlmemberships.jsonlquality.jsonmanifest.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_daysget_all_trade_days 一致性校验后的完整 交易日序列,并显式保存 end 日后的唯一 next_trading_session。decision、 broker snapshot 和 shadow plan 必须绑定同一个相邻 session,以及 Asia/Shanghai [09:00,09:30)first_executable_windowelapsed-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 hashverifier 会从原始两个权益值 重新计算差额、阈值和 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 policyquery 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 pipeline 已实现:

  • PIT table 和未来值拒绝;
  • Universe 原因码;
  • 透明价量特征与 T+1-open 标签时钟;
  • train-only winsor/impute/standardize
  • purge/embargo walk-forward
  • deterministic Ridge、OOS IC/RankIC
  • factor risk、dated cost/capacity 和 constrained target。

这些功能证明研究管线可执行。Ridge 尚未冻结成带版本、输入 schema 和推理 hash 的 deployment bundle,也没有授权真实长样本 OOS 与四引擎推理验证,因此 不是生产 champion。

Qlib 路径固定为 0.9.7。CPython 3.12 实际 fixture smoke 已得到:

  • native momentum24 条 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 completed 分区已生成 managed provider;早期未复权动量 smoke 在 PYTHONHASHSEED=0 下连续两次得到逐 byte 相同的 evidence JSON。

该 fixture 只有两只股票和一个 benchmark,性能没有投资意义。Qlib 的单一 limit_threshold 也不能表达逐日板块/ST 规则,所以它只参与 L1/L2 和诊断 L6,不声称 L3 target 或 L4 order-intent parity。

Portable strategy and platform boundary

当前可跨 hosted wrapper 冻结的共同基线是 portable-momentum-v1。平台 API 不得进入 symbol normalization、momentum score、target weight、target quantity 和 order delta 计算。

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 用户属性。两条路径固定中证 500 benchmark、PIT 历史成分/ST 与 baseline 费率;built-in 的 10% 参与率由 QMT GUI 设置,qmttools 程序化传入。live mutation 只存在于外部 XtTrader adapter,并且默认关闭、 未认证、没有 live 启动命令;operator 可运行的 shadow CLI 只接受查询边界。

Stable artifacts and release integrity

最低交换合同是:

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 承担 各自边界的同类职责。

这些合同已有自动测试;最近一次标准库套件为 216 tests、OK、6 个可选路径 skip。测试结果不能替代 schema 迁移演练、真实平台导出或券商回调认证。

Clocks and reconciliation

canonical weekly clock 是:

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_oflast_feature_barfirst_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

synthetic/fake 数据是合同测试,不是市场证据;Qlib synthetic fixture 的真实 运行是运行时证据,不是收益证据;mock parity exporter 是 wrapper 合同证据, 不计 G9。

Remaining production gaps

当前还缺:

  • 授权 JQData 真实快照、基本面公告 PIT、完整公司行动/Security Master
  • Ridge/LightGBM 冻结模型包和真实 OOS 证据;
  • 真实数据校准的风险、冲击、容量和 TCA;
  • 真实 JoinQuant/QMT 导出;
  • 券商状态映射、restart recovery daemon、20 日 shadow 与连续对账;
  • 运维监控、kill-switch 演练和程序化交易合规确认。

所以 Quant OS 是可执行、可继续填证据的生产候选框架,不是已经达到整体 60 分的实盘系统。证据政策见 AUDIT_2026-07-25.md