Files
quant-os/docs/SECURITY.md
T

9.0 KiB
Raw Blame History

Quant OS data, credential and live-trading safety

Quant OS 仓库需要能够被 review、clone 和推送,但不能携带可复用凭据、账户 身份、受许可限制的数据或券商专有运行时。Obsidian 只保存项目说明,也不能 成为密码、cookie 或行情文件的旁路存储。

Never commit or copy into documentation

  • JoinQuant/JQData username、password、cookie、token、session export
  • QMT/MiniQMT account ID、terminal profile、userdata directory、session file、device fingerprint
  • 从持牌 QMT 安装复制出的 xtquant binary
  • broker statement、raw callback 或含账户/个人信息的截图;
  • private key、API key、.env、subscription URL、带凭据的 clone URL
  • provider licence 不允许再分发的 raw/derived market data
  • Colab notebook output 中的 secret、完整账户值或授权数据;
  • MLflow/Recorder artifact 中意外缓存的环境变量、machine path 或身份信息。

.gitignore 不是安全边界。每次提交前必须检查 staged diff 和所有 generated artifacts。

Credential injection

提交到 Git 的配置只能含 placeholder。推荐本地变量:

JQDATA_USERNAME
JQDATA_PASSWORD
QMT_ACCOUNT_ID
QMT_USERDATA_PATH
QMT_SESSION_ID
QMT_ACCOUNT_HASH_KEY_FILE

JQData adapter 优先读取本地环境变量,也支持交互式读取;密码提示无回显。 不得把密码作为 CLI 参数,因为 shell history/process list 会泄漏。

Colab 可选 JQData cell 必须在 runtime 内通过无回显 prompt/Colab secret 注入。禁止:

  • 把 secret 写在 notebook source 或共享链接里;
  • print(os.environ)、输出 auth object 或异常中的 credential
  • 把带 secret 的 notebook output 下载、同步或提交;
  • 运行结束后继续复用包含授权数据和 secret 的共享 runtime。

用完后清除 runtime。Colab secret 只是注入渠道,不授予数据再分发权。

QMT 账号不应作为 CLI 参数。.env.example 只列变量名和安全默认值; 真实 .env 必须保留在 operator-controlled local secret store。

不得在 --help、exception、run manifest、test snapshot 或 OB 文档打印上述 值。低熵账户号的普通 SHA-256 可枚举恢复;对外证据应使用 keyed one-way identifier,并把 key 保存在独立 secret store。

QMT_ACCOUNT_HASH_KEY_FILE 只指向本地 HMAC key,不是 key 本身。 qmt_shadow_plan.py plan 在文件不存在时生成至少 32 byte 的安全随机 keyUnix 要求文件 mode 0600,并且不会为了创建 key 而放宽或改写一个已经存在的父目录 权限。verify 只读取既有 key,绝不会在 key 丢失时静默生成替代品。该 key 必须稳定备份和最小权限访问:轮换后账户 hash 会变化,历史 broker snapshot 与 decision 会按设计失配,历史 authenticated evidence 也无法再验签。key 内容不得进入 Git、OB、notebook、artifact、stdout、异常或聊天。

shadow manifest 保存的是 QMT_SHADOW_EVIDENCE_V1 HMAC,不是 secret。 它用与账户标识不同的 domain 签署 canonical evidence envelope,覆盖完整 plan、broker observation、broker snapshot 的内容 hash 和三份实际发布文件 原始 byte SHA-256、原始 decision manifest hash、planner/engine 以及 tools/qmt_shadow_plan.py operator entrypoint source hash,并绑定固定 semantic/policy ID 和阈值。四个发布 JSON(含不自签的 manifest)必须符合 唯一 deterministic writer bytesminify、key 重排和空白变化不是等价发布物。 verifier 必须同时拿到原始 decision 与既有 key,并读取磁盘实际 bytes 重建 envelope 后用 constant-time compare 验证。普通 SHA-256 重新封装、替换 decision、改写 observation 或同步修改 plan 派生字段都不能在不知道 key 时伪造该 MAC。

这个 HMAC 的信任主体是“持有本地 key 的 Quant OS evidence publisher”。 它证明发布后没有被无 key 的第三方改写;它不是 QMT/券商对 API 返回值的 签名,不证明终端、账号或 callback 未在采集前被攻陷。key 泄漏后攻击者可以 伪造本地 envelope,应立即按 credential incident 轮换、隔离旧证据并重新做 可信采集。

JQData and provider-data licence

jqdatasdk==1.9.8 adapter 可获取 raw OHLCV/money、factor、pre-close、 daily limits/paused、PIT is_st 和历史指数成员。可获取不等于可再分发。

首次真实 snapshot 前记录:

  • provider、账户 entitlement 和允许用途;
  • local/Colab 是否允许持久保存、保存期限;
  • raw 与 derived data 是否可共享;
  • API/field semantic version
  • query、retrieval time、event/effective/available time
  • partition/data hash、retention 和 deletion policy。

snapshot manifest 不含密码,但 snapshot 本身仍可能是受许可数据。默认放在 被 Git 忽略的 local storage,不上传代码仓库、OB、公开 object storage 或 公开 Colab drive。

synthetic fixture 可共享但不是市场证据。真实 JQData snapshot 只有在许可、 lineage 和语义 verifier 都完成后,才可能成为 G1 的候选证据。

QMT proprietary and licensed boundary

xtquant 由持牌 QMT/MiniQMT 与券商分发。Quant OS

  • 不 vendoring、不上传、不从非官方 PyPI 模仿包安装;
  • 仅在 QMT-specific path 内 lazy import
  • 没有专有运行时也能跑核心/fake tests;
  • 只使用实际券商支持的 Python 和 client/plugin 组合。

QMT 并非只提供用户名密码即可运行。还需要已授权 QMT/MiniQMT client、 匹配的 xtquant、userdata path、行情/历史数据 entitlement 和登录会话。 复制其他用户安装不能建立许可或兼容性。

平台导出必须先脱敏:raw account、broker order ID、userdata path、device 信息和专有异常字符串不进入 Git。

只读 shadow 的 broker_observation.json 只保存 keyed account hash、query 安全 envelope 和通过标准化的资产、持仓、委托、成交事实;不保存原始 account ID。manifest 通过 authenticated evidence HMAC 将 observation、 broker snapshot、plan、decision、source 和 canonical policy 绑定。即便如此, 它仍可能包含敏感持仓/交易信息,只能放在被 Git 忽略且访问受控的证据目录。

Qlib, MLflow and Colab artifacts

Qlib 固定为 CPython 3.12 + pyqlib==0.9.7。Alpha158 runner 为本地 MLflow file store 使用:

MLFLOW_ALLOW_FILE_STORE=true

这是对 local backend 的显式兼容确认,不是安全授权,也不会替代访问控制。 Recorder 目录可能包含 model、label、prediction、code cache/status 和 provider-derived output;提交前必须按 provider licence 与 secret scan 检查。真实模型 artifact 应存放在访问受控、可审计的 artifact store。

不要在公开 Colab runtime 上加载券商文件。JQData/Qlib 可选流程只处理研究 数据;QMT/XtTrader 应留在受控且持牌的本地/Windows 环境。

Default live posture

所有 broker-facing 路径默认只能是:

BACKTEST
SIMULATION
SHADOW

QMT built-in 和 qmttools supplied runner 硬限制 backtest/history。XtTrader allow_live_orders 默认 false,仓库不提供 live launch command。

未来任何 live mutation 至少还要求:

  1. broker read-only preflight 成功;
  2. market data 与完整 broker snapshot 新鲜且带时区;
  3. account allow-list 匹配;
  4. 无 unknown open order 或 reconciliation difference
  5. notional/order/rate limit 已配置;
  6. operator approval 与 kill switch 已演练;
  7. 程序化交易报告和软件/频率要求由实际券商确认;
  8. shadow、重启恢复和连续日终对账达到 release 条件。

环境变量本身不构成批准。mock guard、fake broker 和单元测试也不构成券商认证。

Safe evidence and redaction

可安全导出的候选内容:

  • source/config/data/rules/model hash
  • canonical symbols 和非受限聚合;
  • order state/reason code
  • keyed account hash
  • 在不需要精确值时脱敏/取整的 operational metric。

需要删除或保护:

  • raw account 和可关联 broker order ID
  • 用户 machine path、用户名、device/profile 信息;
  • proprietary client exception
  • notebook cell output 中的 token/credential
  • provider licence 不允许公开的数据行。

审计所需原始版本应留在加密、访问受控的本地/企业存储,而不是为了方便直接 提交 Git。

Incident response

如果 credential、账户标识或授权数据进入 Git/OB/Colab output

  1. 停止新订单和相关自动任务;
  2. 通过 provider/broker 撤销或轮换 credential
  3. 在仓库外保存 incident timeline
  4. 从当前树移除,并在明确批准后清理历史和 mirror;
  5. 检查 CI、artifact、OB sync、Colab/Drive 和 downstream clone
  6. 评估数据许可/个人信息泄漏范围并完成必要通知;
  7. 记录恢复和复发预防。

删除可见文件不等于 credential rotation。交易与数据故障流程见 runbooks/INCIDENTS.md