Public note

个人 A 股量化系统机构级 60 分 Baseline 技术选型设计:从聚宽研究到 QMT 实盘(2026-07-22)

·Markdown 原文

个人 A 股量化系统机构级 60 分 Baseline 技术选型设计:从聚宽研究到 QMT 实盘(2026-07-22)

本文把LEAN 60 行骨架继续向前推进:不再只解释模块,而是为一个个人、A 股、日频、先聚宽回测与模拟、后迁移 QMT 实盘、预计持续演进 3—5 年的系统,做一套可以验收的 Baseline 技术选型。

需求来自这次完整讨论。资料与交易规则核验日为 2026-07-22

[!warning] 使用边界 “机构级 60 分”描述的是研究与生产链条的完整度,不是收益率,不表示已获得机构数据、私有 Alpha、席位、低延迟基础设施或风控审批,也不构成投资建议。纸面设计只有在每一项验收证据出现后才真正得分。

一页结论

最合适的答案不是挑一个“最强平台”,而是建立一个小而完整的组合栈:

角色 V1.0 选型 为什么
架构语言 LEAN 式稳定接口 把预测、目标仓位、订单、成交明确分开;以后替换模型或券商时不重写全系统
数据底座 授权的聚宽/JQData 数据适配器 + Parquet + DuckDB 当前 A 股适配最好,同时避免策略永久锁死在平台内部
研究与模型 Qlib 工作流 + LightGBM 主模型 + Ridge 线性挑战者 适合中等规模表格因子;训练、记录和组合实验链成熟;保留简单模型作为过拟合警报
标的池 按当时成分还原的中证 500 + 可交易性过滤 在横截面宽度、流动性和个人执行难度之间取中间值
风险 行业 + 透明风格因子模型,协方差收缩,特异风险 比“只看止损”完整,也比直接购买或复制商业 Barra 更可审计
成本 日期版本化显性费率 + 半价差 + 参与率/波动冲击 成本同时进入回测、优化与成交后校准,不再用一个固定滑点掩盖容量问题
组合 CVXPY 连续受约束优化 + 取整/离散 repair 显式权衡 Alpha、风险、换手与成本;持股数、最低佣金和交易单位不伪装成连续凸约束
执行 QMT/XtTrader 适配器 + Guarded TWAP/POV 状态机 日频不需要追求微秒,但必须正确处理异步回报、部分成交、撤单重报和对账
评估与追踪 Qlib Records + 自有账本 + 本地 MLflow + Git/data manifest 一次结果能追溯到代码、配置、数据、模型、订单和成交
当前平台分工 本地为事实源;聚宽做独立回测/模拟;QMT 做实盘 研究、验证和实盘各用其所长,业务核心不依赖平台专有回调

可以把它浓缩成一句话:

LEAN 定合约,Qlib 做研究,聚宽做第二引擎验证,QMT 做真实订单;本地的版本化数据、组合决策和账本才是系统事实源。

V1.0 的目标设计分约为 66/100。它刚好高于 60,而不是假装达到 90:数据供应仍非双源,成本冲击主要靠代理变量,风险模型尚未经过多年实盘校准,执行也没有交易所级逐笔队列模型。

一、先把“60 分”定义清楚

1. 60 分不是平均分,而是“分数 + 硬门”

系统总分由七个维度加权,但必须同时通过十道硬门。这样不能靠一个漂亮的回测 Sharpe 抵消数据泄漏,也不能靠代码整洁抵消实盘无法对账。

评分维度 权重 60 分层级应有的证据
数据与时点正确性 15% PIT 数据、成分股历史、退市样本、公司行动、字段可用时间、版本与质量报告
研究与样本外验证 15% 时间顺序切分、标签重叠 purge/embargo、walk-forward、成本后结果、多市场状态
风险与组合构建 15% 预测与仓位分离,相关性/暴露/流动性进入优化,约束可解释且有不可行降级
成本与执行现实性 15% 日期化费率、价差/冲击、成交量约束、部分成交、撤改、异步回报
工程与可复现性 15% 代码/配置/数据/环境/模型版本齐全,同一输入可重放同一决策
运行、对账与监控 15% 决策—订单—成交三账、日终券商对账、告警、断线恢复、kill switch
合规与平台迁移 10% 程序化交易报告已确认;核心逻辑与聚宽/QMT API 解耦;规则按日期版本化

定义为:

总分 = Σ(维度得分 × 权重占比),且 Σ权重占比 = 1

达到 Baseline 60 ⇔ 总分 ≥ 60
                    且 G1…G10 全部通过

十道硬门如下:

Gate 不可妥协的验收条件 失败意味着什么
G1 数据时点 任意一次预测都能回答“当时实际知道什么”;财报按公告可得时间进入 有未来函数,整份回测作废
G2 样本外 禁止随机打乱时间;有隔离的验证、测试和向前滚动评估 只有拟合,没有证据
G3 A 股现实 停复牌、涨跌幅制度、交易单位、T+1 可卖量、费用与公司行动按证券和日期处理 回测订单在现实中不存在
G4 稳定合约 Forecast → Target → Order → Fill 是不同对象并落盘 无法定位误差来自哪一层
G5 事前风险 仓位生成前检查集中度、行业/风格暴露、波动、流动性和换手 “止损”无法替代组合风控
G6 订单状态 支持提交、确认、部分成交、全成、撤单中、已撤、拒单与未知状态 实盘仓位会漂移
G7 可复现 每个 run 绑定 Git commit、环境锁、配置 hash、数据快照与随机种子 结果无法复核
G8 对账与停机 每日与券商资产/持仓/订单/成交对账;异常时能阻止新单 小故障可以累积成资金事故
G9 双引擎一致性 同一信号/目标在本地与聚宽的差异有解释;QMT 影子运行通过 迁移风险未知
G10 合规 已向实际券商确认报告、权限、频率和软件信息要求,并完成“先报告、后交易” 不得上线实盘

2. 每一层的 0—90 分语义

层级 含义
0 缺失
20 Notebook/Demo 能跑;大量理想化假设
40 回测可用;尚不能可靠模拟或实盘
60 职责、输入、输出、失败模式和验收测试齐全,并已有连续模拟/影子运行证据;系统级通过后才有资格进入受控小资金 canary
80 多数据源、压力测试、自动恢复、持续监控和实盘校准较成熟
90+ 机构私有数据、容量与成交模型、治理、权限、审计和生产基础设施长期验证

因此,本文所说的“机构级”准确含义是:采用机构常见的完整责任链与控制思想,但用个人能维护的复杂度实现其 60 分版本。

3. 本文的固定边界

V1.0 先主动放弃一些问题,否则工程面会无限膨胀:

  • 市场:沪深 A 股,暂不含港股、美股、期权、期货和跨境资产。
  • 账户:个人现金股票账户,长仓,不融资融券。
  • 频率:日频生成 Alpha,默认周度再平衡;日内数据只服务可交易性、成本和执行。
  • 目标:相对中证 500 的成本后超额收益,不把最高绝对收益当唯一目标。
  • 平台:当前在聚宽回测与模拟;本地保存研究事实;未来以实际券商可用的 QMT/XtQuant 接口实盘。
  • 非目标:高频、盘口预测、做市、深度学习端到端下单、分布式微服务、Kubernetes。

如果将来改做分钟高频、期权组合或多券商交易,本设计的接口仍可保留,但执行、风控和数据模型必须升级,不能把本文参数原样平移。

二、目标架构:研究平面与交易平面分开

LEAN 官方的 Algorithm Framework 把 Universe、Alpha、Portfolio Construction、Risk Management 和 Execution 分开。本文保留这套责任边界,但加上现实系统不可缺少的数据、成本、账本、监控与反馈。

个人 A 股量化 Baseline:研究、交易与证据反馈闭环

可编辑源图:个人 A 股量化 Baseline:研究、交易与证据反馈闭环

核心不是目录名,而是九种稳定对象:

对象 最少字段 生产含义
SecurityMaster 内部 ID、交易所代码、上市/退市日、板块、交易单位、规则版本 证券身份与规则不能靠字符串猜
UniverseSnapshot as_of、成员、纳入/排除原因、数据版本 标的池可重放,杜绝当前成分回填历史
FeatureSnapshot instrumentevent_timeavailable_time、值、版本 区分事件发生与研究者可得时间
AlphaForecast 标的、生成时点、持有期、分数/预期超额、置信度、模型版本 只表达预测,不偷偷决定股数
RiskForecast 暴露矩阵、因子协方差、特异风险、流动性、场景 描述一起跌、暴露过大和难退出的风险
CostForecast 方向、数量、显性费率、价差、冲击、置信区间 成本是数量的函数,不是一条常数
TargetPortfolio 决策时点、目标权重/数量、约束状态、优化器状态 想持有什么,与如何成交分离
ExecutionPlan 父单、子单节奏、限价边界、参与率、截止时间、退出政策 把目标差额翻译成可控的执行意图
OrderEvent/Fill client ID、broker ID、状态、成交量价费、事件时间 券商回报是事实,必须可幂等重放

稳定边界建议固定成:

alpha.predict(feature_snapshot) -> AlphaForecast
risk.estimate(market_snapshot, positions) -> RiskForecast
cost.estimate(trade_list, market_snapshot) -> CostForecast
portfolio.build(alpha, risk, cost, current_positions) -> TargetPortfolio
pretrade.check(target, broker_snapshot, rules) -> PreTradeDecision
execution.plan(decision, market_snapshot) -> ExecutionPlan
broker.submit(plan) -> stream[OrderEvent]
ledger.reconcile(order_events, broker_snapshot) -> ReconciliationReport

聚宽、Qlib 和 QMT 只能实现这些接口,不能反过来侵入领域对象。平台切换时替换 adapter;Alpha、风险、组合与验收逻辑保持不动。

三、总框架候选:为什么不选一个“大一统平台”

候选 优点 主要缺口 复杂度 生产成熟度 当前适配 / 学习 ROI 结论
聚宽全包 A 股数据、API、回测、模拟接近当前习惯 平台锁定;本地实验、实盘订单语义与券商状态难成为统一事实源 很高 / 高 保留为验证环境,不作内核
Microsoft Qlib 全包 数据处理、模型训练、记录与 A 股示例完整;论文源码公开 默认策略与执行不是 QMT 生产 OMS;公开样例数据不应当作生产源 研究高、交易低 高 / 很高 选作研究工作流,不包办实盘
QuantConnect LEAN 五层接口、事件、现实模型与订单生命周期成熟 中国本地数据、规则和 QMT 接入成本较高 中 / 很高 选其架构思想,不把整引擎搬进 V1
vn.py / NautilusTrader 类事件引擎 事件驱动、网关、订单状态适合交易工程学习 日频 A 股横截面研究和当前 QMT 路线仍需大量适配 中高 中高 中 / 中高 80 分阶段参考,不作 V1 主干
小型本地 Python 内核 + 适配器 接口、数据和账本完全受控,最容易跨聚宽/QMT 自己必须承担测试、状态、监控和文档 取决于实现 很高 / 很高 V1 主干;只自建薄层,复用成熟库

最终不是“全自研”。自建的仅是对个人系统最有长期价值的部分:领域对象、平台 adapter、约束配置、决策账本和验收测试;矩阵运算、模型、求解器、存储和追踪全部复用成熟项目。

四、数据与证券主数据层

职责:回答“在时点 t,系统对证券 i 真正知道什么、能否交易、适用什么规则”。

  • 输入:行情、财务与公司行动、指数成分、证券状态、交易日历、交易规则、数据商元数据。
  • 输出:SecurityMaster、不可变原始分区、PIT 标准表、数据质量报告和 data_version
  • 60 分失败模式:当前指数成分回填历史、使用修订后财报、只保存后复权价、退市证券消失、不同平台代码混用、规则硬编码。

候选比较

候选 优点 缺点 / 风险 复杂度 生产成熟度 当前适配 / 学习 ROI 决策
只用聚宽平台内数据 上手最快,A 股字段和回测环境统一 被平台对象与权限绑定;难做独立数据快照和 QMT 重放 很高 / 中 仅做交叉验证
聚宽/JQData 授权源 + 本地标准层 延续当前数据经验,又能固定 PIT 快照与跨平台代码 需处理授权范围、增量更新、字段语义和质量测试 中高 很高 / 很高 V1 Baseline
Qlib 示例/公开数据 快速跑通官方 workflow Qlib 仓库明确提醒公开数据可能不完善;不适合作为资金决策事实源 中 / 高 只做 smoke test
Wind / Choice 等商业数据 财务、公司行动、行业与一致预期覆盖较强 费用、许可和供应商绑定;个人阶段投入较大 中 / 中 80 分升级
自抓交易所/网站并拼接 可控、费用低 复权、修订、历史状态和长期运维成本被严重低估 很高 低至中 低 / 中 不作主源

聚宽的入门指南适合完成回测—模拟闭环;JQData 文档适合本地访问。但“API 能返回数据”不等于 PIT 正确。聚宽技术支持说明 set_option("avoid_future_data", True) 需要显式开启且默认关闭(未来数据说明),股票数据页也对全证券与历史指数成分的未来函数风险作了提示(股票数据说明);V1 仍要自己做字段可用时间测试。数据能否落本地、保存多久和用于何处,应以账户实际授权条款为准。

V1.0 实现

data/
├── raw/provider=jq/table=bars/trade_date=YYYY-MM-DD/*.parquet
├── raw/provider=jq/table=fundamentals/announce_date=YYYY-MM-DD/*.parquet
├── canonical/bars/...
├── canonical/fundamentals_pit/...
├── canonical/security_master/...
├── canonical/index_membership_pit/...
├── canonical/trading_rules/...
├── snapshots/<data_version>/manifest.json
└── quality/<run_date>/report.json

Parquet + DuckDB,原因不是它们“更量化”,而是个人单机上列式分区、SQL 审计和 Python 互操作足够强,又没有数据库服务运维负担。Qlib 只读取 canonical view,不拥有原始数据。

必须保留以下语义:

  1. 原始价、复权因子和公司行动分开保存,禁止只存一条会随查询日变化的后复权序列。
  2. 每条基本面记录同时保存 period_endannounce_timeavailable_time 和供应商抓取版本;模型按 available_time 连接。
  3. 指数成分、ST/风险警示、停复牌、上市退市和证券板块均为带生效区间的慢变表。
  4. 交易日历、交易单位、涨跌幅与有效申报规则按市场、板块、证券、日期取值,不散落在策略 if 中。
  5. 每次实验锁定 data_version = hash(manifest + schema + source partitions);供应商历史修订后旧实验仍能重放。
  6. 每日质量门检查重复键、缺口、极值、价格关系、成交额一致性、复权跳变、成分数量和供应商延迟;失败时不产生新目标仓位。

上海、深圳交易规则在 2026 年又有修订,整体自 2026-07-06 起施行(上交所规则深交所规则);上交所页面同时单列了暂缓实施条文。规则表因此不仅要保存 effective_from/effective_to,还要保存 active/deferred 状态,不能把“已发布”直接等同于“所有条款均已执行”。

数据层验收

  • 任抽 30 个历史决策日,可以还原当日指数成员、证券状态、财报可得值和规则。
  • 在数据表中人为注入未来公告,PIT join 测试必须拒绝它。
  • 代码不改、固定 data_version 重跑,特征 hash 和目标权重在数值容差内相同。
  • 退市、长期停牌、代码变更、分红送转和跨年费率至少各有一个回归测试样本。

五、Universe 层:先决定“研究谁”,再判断“今天能不能动”

职责:在每个 as_of 生成可研究集合,同时把“可持有、可开仓、可卖出”拆成不同状态。

  • 输入:PIT 指数成分、Security Master、成交额/停牌/风险警示/上市年龄、现有持仓。
  • 输出:UniverseSnapshot,包括成员、状态与逐项原因码。

候选比较

候选 优点 缺点 / 风险 复杂度 成熟度 当前适配 / 学习 ROI 决策
固定股票清单 最容易复现 生存者偏差、容量与风格集中严重 低 / 低 拒绝
用今天的指数成分回测历史 写法简单 直接泄漏未来成分;回测无效 低 / 低 硬门拒绝
PIT 中证 300 流动性最好、成本较易控制 横截面较窄,大盘风格集中 低中 高 / 高 挑战者
PIT 中证 500 + 可交易性 宽度、流动性与个人维护成本平衡 仍有成分调整和中盘风格偏置 很高 / 很高 V1 Baseline
中证 1000 / 全 A 流动性池 Alpha 空间更宽 微盘、涨跌停、冲击与数据质量难度明显上升 中高 中 / 高 80 分升级

V1.0 规则

当时有效的中证 500 成分作为 benchmark-native 初始池,默认:

  • 新股观察期先设为 120 个交易日;这是待验证的保守起点,不是市场真理。
  • 风险警示证券、已知退市整理状态禁止新开仓;退出服从真实可卖性。
  • 用过去 20 日中位成交额和停牌比例做流动性门;阈值由计划资金和容量测试反推,不先拍一个绝对金额。
  • 当日停牌、触及价格限制或无有效报价时标为 frozen,不能因为“不合格”就在回测里假装卖掉。
  • 昨日买入数量进入 unsettled_buy,当日不得卖出;系统使用券商返回的 available_to_sell,不自行乐观推算。
  • 现有持仓即使不再允许开仓,也必须继续出现在优化问题中,直到真实退出完成。

建议状态机:

researchable ──┬── openable
               ├── hold_only
               ├── sell_only
               └── frozen

这比一个布尔字段 tradable=True/False 多一点代码,却能消除大量“回测能卖、实盘卖不掉”的错误。

六、特征、Alpha 与验证层

职责:用决策时点以前的信息,为固定持有期输出横截面预期超额收益或排序;它不决定仓位。

  • 输入:PIT 特征快照、标签定义、训练窗口、Universe 快照。
  • 输出:AlphaForecast(score, expected_excess_return, horizon, uncertainty, model_version)
  • 60 分失败模式:随机交叉验证、预处理全样本拟合、标签与交易时点错位、只报告最优回测、模型升级没有挑战者。

候选比较

候选 优点 缺点 / 风险 复杂度 生产成熟度 当前适配 / 学习 ROI 决策
单均线/单规则 透明,适合验证数据—下单链路 信息维度太少,无法验证横截面研究与组合体系 低 / 中 只作管线 smoke test
OLS / Ridge / Elastic Net 快、稳定、可解释,能暴露泄漏和过拟合 难表达非线性与交互 很高 / 很高 强制挑战者
LightGBM 表格因子、缺失与非线性交互适配;训练快;Qlib 有成熟 Alpha158 配置 仍会过拟合;分数未天然校准为预期收益 很高 / 很高 V1 主模型
XGBoost / CatBoost 同属成熟 GBDT,可做模型多样性 V1 同时维护三套树模型收益有限,调参空间扩大 高 / 高 二级挑战者
LSTM / Transformer / GNN / RL 能表示序列、关系或策略决策 有效样本、非平稳、泄漏、可解释、推理与监控成本都更高 高至很高 场景依赖 低 / 中 先拒绝,80 分后再立项

Qlib 的官方 benchmark同时列出线性、GBDT 和多种深度模型;它最有价值的结论不是“某模型永远第一”,而是提供统一工作流去做可比实验。LightGBM 的原始设计强调高效梯度提升(项目与论文入口),很适合做个人 A 股结构化因子的第一个非线性 Baseline,但不保证产生超额收益。

V1.0 特征与标签

先使用 5 类、约 80—160 个透明特征,而不是一次堆数千个表达式:

  1. 动量与反转:5/20/60/120 日收益、近期反转、距高点等。
  2. 波动与下行风险:不同窗口 realized vol、下行波动、跳空、偏度代理。
  3. 流动性与交易活跃:换手、成交额、Amihud 类价格冲击代理、量价背离。
  4. 估值与质量:按真实公告时点接入的估值、盈利质量、成长、杠杆和现金流。
  5. 市场与行业相对量:相对行业/基准的动量、Beta、残差收益与拥挤度代理。

价格量特征可复用 Alpha158 的组织方式;财务因子必须额外遵守公告时点。每天横截面处理按以下顺序执行,并且所有需要拟合的参数只在训练集学习:

原始 PIT 值
→ 缺失原因标记
→ 温莎化/稳健截尾
→ 行业内或全市场标准化
→ 可选的行业、规模中性化
→ 缺失填补 + missing indicator
→ FeatureSnapshot

基准标签先定义为:在 T 日收盘数据完整到达后产生预测,以固定执行窗口的 T+1 VWAP 为起点、同一窗口的 T+6 VWAP 为终点,计算 5 个持有区间的个股收益,再减同期中证 500 收益。研究标签使用固定、事先声明的 VWAP 代理;模拟/实盘绩效再用真实成交替换。不能用 T 日收盘价生成信号后又假设自己在同一收盘价满额成交。

构造 T 日样本时,不能用事后看到的 T+1 停牌、封板或成交量反过来筛掉股票。若 T+1 没有可执行 VWAP,记录 label_status=non_executable/censored,在样本覆盖和执行机会成本里单列;不能静默删除后只训练“第二天恰好能成交”的幸存样本。T+1 盘前实际可交易状态只属于 PreTrade/Execution 层。

V1.0 验证协议

普通随机 CV 不适合有时间顺序的数据,scikit-learn 的 TimeSeriesSplit 文档也明确指出普通交叉验证会出现“用未来训练、在过去评估”的问题。本系统再向前一步处理横截面标签重叠:

  • 初始研究窗:滚动 4 年训练、1 年验证,随后 3—6 个月纯样本外;每月重训,周度出分。
  • 在相邻集合之间 purge 至少一个标签持有期,并保留 embargo;禁止重叠未来收益跨越边界。
  • 预处理器、特征选择、模型和分数—收益校准器全部只在训练/验证区间拟合。
  • 超参数先在少量预注册网格中选择;测试期只打开一次,之后进入新的向前窗口。
  • 同时保留 Ridge、LightGBM 与无 Alpha 的 benchmark;LightGBM 只有在多段样本外、成本后、稳定性和风险暴露上整体胜过 Ridge,才获得生产资格。
  • 用 IC、RankIC、ICIR、分层收益、衰减、换手和按行业/规模分组稳定性评估预测;不用单一 Sharpe 选模型。
  • 对标签、特征滞后、成分股历史、复权和费用分别做刻意破坏测试,确保测试能抓到泄漏。

模型最终输出不是“买入前 50 名”,而是一个带版本与持有期的预测。是否买、买多少,由风险和成本共同决定。

七、风险模型与风险管理层

职责:风险模型在交易前描述组合可能怎样一起亏;风险管理根据这些估计修改或拒绝目标。两者都不是“跌到某价卖出”的同义词。

  • 输入:持仓、候选权重、行业与风格暴露、协方差、特异风险、流动性、市场状态。
  • 输出:RiskForecast、约束与限额、压力测试、RiskDecision
  • 60 分失败模式:只设单股止损、只看历史波动、直接使用高维样本协方差、停牌仓位在风险报告里消失。

候选比较

候选 优点 缺点 / 风险 复杂度 生产成熟度 当前适配 / 学习 ROI 决策
单股止损/组合回撤线 易懂,适合作为事后保护 不描述集中度、相关性、Beta、流动性与隔夜跳空 低至中 中 / 低 只能作最后保险丝
历史波动 + 样本协方差 实现直接 股票数接近或超过样本数时病态、优化权重极不稳定 低中 中 / 高 仅作对照
Ledoit–Wolf 收缩协方差 数值稳定、实现成熟 仍难直接解释行业和风格风险 高 / 高 协方差挑战者
行业 + 风格因子模型,协方差收缩 可解释、可设暴露约束、适合横截面股票组合 因子定义、收益估计和特异风险要自己验证 中高 很高 / 很高 V1 Baseline
商业 Barra/供应商风险模型 数据、分类与生产流程成熟 昂贵、许可限制、内部逻辑与个人策略未必透明 很高 低 / 中 80—90 分升级

Ledoit 与 Wolf 对组合问题的核心提醒是:高维样本协方差往往不适合直接优化,收缩能改善估计稳定性(论文入口scikit-learn 实现)。MSCI 的权益因子模型说明则体现了行业、风格与特异风险的机构化表达。V1 借用思想,不复制商业模型名称或参数。

V1.0 透明因子风险模型

对股票收益使用:

rt=Bt1availft+ϵt,ΣT+1T=BTavailFT(BTavail)+DT
  • Bt1avail:在收益 rt 发生前已经可得的行业与风格暴露;不能拿 t 日收盘后才知道的数据解释同一天收益。
  • BTavail:决策时点 T 已经可得的行业 one-hot、规模、市场 Beta、动量、波动、流动性、价值/杠杆等少量透明风格暴露。
  • ft:用稳健加权横截面回归估计的因子收益;行业哑变量与截距需固定基准或施加和为零约束,避免不可识别。
  • FT:截至 T 的因子收益 EWMA 协方差,再做收缩与特征值下限处理。
  • DT:截至 T 的个股残差方差稳健估计,设样本不足和极低方差 floor。
  • ΣT+1T:交给组合优化器的事前股票协方差预测。

Qlib 的 EnhancedIndexingStrategy 已展示风险暴露、因子协方差、特异风险、blacklist 与不可交易持仓如何进入增强指数优化(策略文档实现源码)。V1 可先用它做研究参照,生产内核保留自有 RiskForecast 格式。

风险约束分三类:

  1. 组合构建前:单股、行业相对 benchmark、市场 Beta、风格暴露、预测波动、跟踪误差、换手、ADV 容量、持仓数和现金缓冲。
  2. 交易前:目标是否超限、可卖量、价格/行情新鲜度、重复订单、预计现金、单日成交与申报频率。
  3. 运行中:数据停止、券商断线、订单拒绝激增、成交价偏离、持仓对账差异、组合日损失/回撤状态。

压力测试至少覆盖:市场单日下跌、最大行业冲击、波动率翻倍、相关性向 1 收敛、交易成本 2 倍、预期成交只有 50%、若干大持仓连续不可卖。压力场景的结果是减仓、延后交易或停机规则,而不是报告里的一张装饰图。

风险层验收

  • 把两个高度相关股票同时放大,组合风险必须明显高于分散持仓。
  • 因子数据缺失或协方差非正定时,系统使用保守 fallback 并告警,不能静默输出 NaN 权重。
  • 停牌持仓以冻结权重进入总风险;无法交易不等于没有风险。
  • 所有硬限额在优化前、优化后和下单前各检查一次;三次使用同一规则版本。
  • 止损仅保留为极端保护,不参与“风险模型已经完成”的评分。

八、费用、滑点与容量层

职责:估计从当前持仓走到目标持仓所需付出的显性费用、价差、冲击和机会成本,并在交易后用真实成交校准。

  • 输入:方向、计划数量、报价/分钟量价、ADV、波动、费率版本、券商佣金、执行窗口。
  • 输出:逐股票、逐订单的 CostForecast(low, base, high) 和容量报告。
  • 60 分失败模式:零成本、永远固定一个滑点、假设目标数量全部成交、只在绩效报表末尾扣费而不影响权重。

候选比较

候选 优点 缺点 / 风险 复杂度 生产成熟度 当前适配 / 学习 ROI 决策
零成本 方便检查代码 对可交易性没有任何意义 无 / 低 拒绝
固定费率 + 固定滑点 能跑,参数少 不随方向、流动性、规模和波动变化 低至中 中 / 中 smoke test
日期化费率 + 半价差 + 参与率/波动冲击 可解释,能进入优化和容量分析 冲击系数需真实成交持续校准 很高 / 很高 V1 Baseline
Almgren–Chriss / 多期凸成本模型 风险—冲击权衡清楚,可做动态计划 参数估计与模型假设要求更高 中高 中 / 高 80 分升级
盘口/队列仿真或学习型执行成本 对高频限价单更细 数据、撮合细节和运维成本远超日频 V1 需求 很高 场景依赖 低 / 中 暂拒绝

组合决策的成熟表达不是“先求权重、最后再扣手续费”。Boyd 等人的多期交易优化把预期收益、风险、交易成本、持有成本和约束放进同一个问题;Almgren–Chriss 则系统讨论执行风险与市场冲击的权衡(论文 DOI)。V1 使用其思想的简化、可校准版本。

V1.0 成本函数

对计划交易 qi 估计:

Ci(qi)=Cifee(qi)+12spreadi·|notionali|+ηiσi|qi|ADVi·|notionali|

其中:

  • fee:印花税、经手/监管/过户等费用和券商佣金/最低佣金,全部按日期与账户配置。
  • spread:优先用可得的盘口或分钟数据估计;没有可靠报价时使用保守高低价代理,并标记较低置信度。
  • impact:以波动和参与率为主的平方根代理。它不是自然定律,ηi 必须用实盘成交拟合并做 0.5×/1×/2× 压力测试。

需要区分“账本里的真实费用”与“凸优化器里的成本代理”。单笔最低佣金在零交易与非零交易之间存在离散跳变,不能在纯连续凸问题里被精确表达。V1 的连续优化器只使用比例税费、价差、凸冲击和换手惩罚,并设置最小交易金额;取整后删除不覆盖最低佣金的碎单,执行 repair,再用账户真实最低佣金重算现金、回测与 TCA。若以后必须联合决定“是否交易”并精确计入每笔最低佣金,应升级为混合整数问题,而不是继续把它称为纯凸优化。

财政部规定证券交易印花税自 2023-08-28 起减半征收(官方公告);交易所收费项目也有各自的现行标准(上交所收费指引深交所收费页)。这些链接用于核验,不应把今天的数字永久写死在代码里。券商佣金和最低收费以实际账户交割单反推。

V1 初始容量政策:

  • 优化器同时看单笔参与率、组合一天总成交额、单只股票清仓天数和全组合容量。
  • 先把 order / ADV ≤ 5% 作为保守研究上限,并测试 1%、3%、5% 三档;上线阈值必须由分钟量和真实成交重新校准。
  • 如果策略只有在零成本或极小资金下成立,结论应是“无当前容量”,不是继续调模型。
  • 回测输出低/基准/高三条成本后净值;选型看最差合理情形是否仍可接受。

成本层验收

  • 买卖方向、最低佣金和日期切换有单元测试,并能与实际交割单逐项对上。
  • 将计划交易放大 10 倍,单位成本和成交时间不得保持不变。
  • 组合优化前的预测成本与成交后的 implementation shortfall 可逐订单关联。
  • 无分钟/盘口数据时明确降低置信度并提高冲击假设,不能悄悄回退到零滑点。

九、组合构建层:把 Alpha、风险和成本真正放在一起

职责:把预测转换成满足风险、成本、容量与真实持仓约束的目标组合。

  • 输入:AlphaForecastRiskForecastCostForecast、当前持仓与可交易边界。
  • 输出:TargetPortfolio、预计风险/成本、约束余量、优化诊断和不可行原因。
  • 60 分失败模式:Alpha 排名直接等于仓位、优化器报错就静默等权、停牌股从归一化分母消失、求出小数股后粗暴取整导致越界。

候选比较

候选 优点 缺点 / 风险 复杂度 生产成熟度 当前适配 / 学习 ROI 决策
等权 透明、稳健、参数极少 忽略预测强弱、相关性、风险、成本和容量 高(作为朴素规则) 中 / 高 必备 benchmark,不作最终 Baseline
Top-k / TopkDrop Qlib 样例成熟,换手逻辑直观 风险和成本通常没有在权重生成中被完整联合处理 低中 高 / 很高 研究挑战者
分数比例 / softmax 保留预测强弱 对分数尺度敏感,仍不处理协方差和约束 中 / 中 不选
风险平价 不依赖 Alpha 尺度,资产配置中有价值 股票横截面 Alpha 目标被弱化;行业与风格仍需约束 中 / 高 Beta 层候选,不作本层主模型
成本感知的受约束凸优化 风险、Alpha、换手、冻结仓位和容量统一;诊断可审计 需要校准参数、稳定风险模型和不可行处理 中高 很高 / 很高 V1 Baseline

V1.0 优化问题

使用 CVXPY 解一个长仓凸优化问题。这里的 C^ 特指上一节的连续凸成本代理,不假装精确包含每笔最低佣金。概念形式为:

maxwα^wλ2wΣwγC^(wwprev)ρwwprev1

四项必须先统一量纲:α^ 是校准后的 5 日预期超额收益,不是原始 LightGBM rank;Σ 与同一持有期对齐;C^ 以 NAV 比例表示;换手也是权重比例。年化波动和跟踪误差只用于展示/限额换算,不能把日频协方差、5 日 Alpha 和人民币成本未经缩放直接相加。

约束至少包括:

&iwi=1cashBuffer,wi0&wiupperi&|Bindustry(wwb)|δindustry&|βwβb|δβ&(wwb)Σ(wwb)TEmax&12i|wiwprev,i|turnovermax&|tradeNotionali|participationi·ADVi

另外将真实交易边界转成数量约束:停牌证券数量固定;卖出量不得超过券商可卖量;禁止开仓的证券只能不增仓;风险退出也不能假装穿越涨跌停。权重优化后进行交易单位取整,再用一个小型 repair pass 恢复现金、单股和行业约束。

精确持股数、最小非零仓位和“是否产生一笔订单”都是离散决策,也不属于纯连续凸问题。V1 先用当前/冻结持仓 + Alpha 预筛候选形成 60/100/150 只候选池,再做连续凸优化;取整后删除尘埃仓位并 repair,把 30—80 只作为目标带和诊断指标,而不是求解器硬约束。若未来必须严格持有恰好 50 只或精确联合最小佣金,应明确升级为混合整数优化。

V1 的初始研究网格而非永久参数:

参数 起始搜索范围 目的
候选池规模 60 / 100 / 150 预筛后进入连续优化;比较宽度、稳定性与计算量
目标持仓带 30—80 取整/repair 后的诊断范围,不是凸优化硬约束
单股上限 1%—3% 防止模型把不稳定分数集中成大仓位
现金缓冲 3%—8%,初始 5% 吸收费用、价格变化和异步成交
行业相对偏离 ±3%—5% 让超额主要来自选股而非押行业
单次单边换手 10%—20% 与周频信号、成本和容量共同验证
ADV 上限 1% / 3% / 5% 三档 输出容量敏感性,不只看一个假设

数值最终由风险预算与成本后样本外结果确定。不能先挑让回测最好看的组合,再称它为“风险参数”。

不可行和求解失败政策

这是 60 分系统与 Demo 的重要分界:

  1. 约束分为绝不放松的硬约束与允许有限 slack 的软约束。
  2. 证券规则、可卖量、现金非负、合规黑名单是硬约束。
  3. 行业偏离和换手可按预先定义的顺序小幅放松,并完整记录 slack 成本;候选池与目标持仓带在求解器外按已发布配置处理。
  4. 求解器超时、非最优或解在容差外时,先尝试上一组已验证参数;仍失败则输出 NO_TRADE 或只执行明确的风险降低单。
  5. 禁止“优化失败 → 自动等权 → 继续下单”。这会把系统错误伪装成投资决策。

为什么不是等权

等权不是坏方法:它应当永久保留为基准,因为稳定、易解释,常常能揭穿复杂模型。但它不能作为这套系统的最终 60 分答案,因为它对“两个高度相关股票是否各买 2%”“预期 Alpha 能否覆盖冲击”“某行业是否已过载”“一只股票是否根本卖不掉”都没有答案。

验收要求:每一个目标权重都能分解为 Alpha 贡献、风险惩罚、成本惩罚和活跃约束;对 Alpha 加微小扰动时,权重不能大幅跳变;rounding 后重新过全部硬约束。

十、执行与 OMS 层:目标仓位不等于订单,订单也不等于成交

职责:把目标—当前差额转成一组受限父单/子单,维护券商异步状态,最后给账本真实成交。

  • 输入:TargetPortfolio、实时持仓/现金/可卖量、行情、交易规则、成本与执行窗口。
  • 输出:ExecutionPlan、订单命令、OrderEventFill、执行异常和残余目标。
  • 60 分失败模式:回测默认瞬间全成;撤单后立即重报却未确认旧单;重启后重复下单;用本地预期仓位覆盖券商事实。

候选比较

候选 优点 缺点 / 风险 复杂度 生产成熟度 当前适配 / 学习 ROI 决策
立即市价/假设全成 代码最少 A 股订单、部分成交、容量、异步和价格限制全部被抹掉 低 / 低 拒绝
次日开盘一次性订单 与日频信号容易对齐 开盘波动、冲击和失败集中;大单不稳 中 / 中 仅小单挑战者
固定 TWAP 可解释、实现简单 不看当时成交量,冷清时段可能过度参与 高 / 高 组成部分
历史 VWAP 跟随典型量能曲线 当日量能偏离历史时失真;无法保证成交 高 / 高 组成部分
带限价边界的 TWAP/POV 混合 时间节奏、参与率、价格保护和剩余量能统一 状态机与参数校准工作较多 中高 很高 / 很高 V1 Baseline
盘口最优执行 / RL 可能适应微观结构 逐笔数据、队列建模与安全验证远超日频需求 很高 场景依赖 低 / 低 暂拒绝

QMT 的 XtQuant 快速开始把行情与交易接口分开;XtTrader 文档提供委托、撤单、资产/持仓/订单/成交查询,以及断线、委托、成交、撤单错误和异步委托回调。这些接口形态本身就说明:实盘必须是状态机,而不是一行 order_target_percent。LEAN 的实盘订单文档同样强调实盘订单异步、可部分成交且修改不保证成功。

V1.0 Guarded TWAP/POV

默认决策—执行时序:

T 日收盘后
  数据完整性通过 → 特征/预测 → 风险/成本 → 目标仓位 → 决策签名

T+1 开盘前
  查询券商资产、持仓、可卖量、未结订单 → 三账预对账 → PreTrade Gate

T+1 09:35 以后
  风险降低单 / 资金受限时的卖单优先
  → 在预定窗口按时间桶与参与率拆分
  → 限价保护、超时撤单、确认后再重报
  → 回调驱动剩余量更新

窗口结束
  按预设残余政策放弃、延后或有限追价;不得为了“完成回测目标”无界追单
  → 日终券商对账 → TCA

初版执行器要有以下机制:

  1. 父单身份decision_id + instrument + side 形成幂等 key;同一决策重放不会产生第二个父单。
  2. 订单状态机CREATED → SENT → ACKED → PARTIAL → FILLED,并允许 CANCEL_PENDING → CANCELEDREJECTEDUNKNOWN;只有确认旧单结束才能替换。
  3. 数量真相:剩余量由成交回报累计,不由“已提交量”推断;启动时先从券商拉取未结订单和成交恢复。
  4. 价格保护:限价同时受最新有效报价、可接受滑点、当日规则和策略放弃阈值约束;行情过期时停止新单。
  5. 参与率保护:子单和时间桶成交量不超过预定比例;量能不足时减少而不是假设全成。
  6. 现金与 T+1:买单只使用已确认可用资金;卖单只使用券商 available_to_sell;所有费用留缓冲。
  7. 节流:每秒报撤单数、每日总订单、单标的撤改次数和异常拒单率均有上限,且低于券商/交易所允许范围。
  8. Kill switch:断线、行情陈旧、对账不平、重复回报异常、资产变化超阈值或拒单爆发时,禁止新开仓;是否撤掉已有安全订单由场景配置。

回测成交模型必须与执行器同源

至少使用分钟数据做次日执行回放:

  • 订单价格被该分钟高低价触及只是成交的必要条件,不是充分条件;仍受可成交方向、成交量和参与率限制。
  • 单分钟成交量受 bar volume × participation cap 限制,因此允许部分成交和残单。
  • 成交价加入方向相关的价差与冲击,费用由同一个版本化 cost engine 计算。
  • 停牌、无有效报价、T+1、价格限制、交易单位、公司行动和未成交残余都真实进入仓位。
  • 对一字涨跌停或单边封板,分钟 OHLC/成交量不能证明自己的队列能成交;V1 默认不成交,除非更细数据能证明对手方可成交量,并另做乐观/基准/悲观敏感性。
  • 回测记录的是 OrderEvent 序列,不只在持仓表里瞬间改一个数字。

回测不可能完整复原队列位置,因此应偏保守,并用聚宽模拟和 QMT 影子盘校准。它的目标是排除明显不可交易策略,不是证明未来一定按模拟价格成交。

十一、评价、归因与反馈层

职责:判断预测是否有效、组合是否按预期承担风险、执行损失在哪里、实盘是否偏离研究,并把证据反馈到各层。

  • 输入:特征/预测、目标仓位、风险/成本预估、订单事件、成交、每日持仓现金、benchmark。
  • 输出:研究报告、组合归因、TCA、模型/数据漂移、运行 SLO 与升级/回滚决定。
  • 60 分失败模式:只有收益率、只看全样本 Sharpe、隐藏失败订单、每次实验无法追到代码与数据。

候选比较

候选 优点 缺点 / 风险 复杂度 生产成熟度 当前适配 / 学习 ROI 决策
累计收益 + Sharpe 快速 无法区分 Alpha、Beta、成本、风险和执行问题 低 / 低 拒绝
QuantStats/pyfolio 类 tear sheet 图表丰富,诊断方便 主要处理净值结果,不拥有决策—订单—成交链 中 / 中 辅助输出
Qlib SigAnaRecord / PortAnaRecord 信号和组合分析接入 workflow,复现实验方便 对真实 QMT 订单、成交和对账不够 研究高 高 / 很高 研究 Baseline
自有事件账本 + TCA + MLflow 能贯通研究与实盘,所有差异可追溯 需要定义 schema、监控与日常纪律 中高 很高 / 很高 生产 Baseline
商业 PMS/风险/TCA 平台 功能与治理成熟 成本和个人系统集成不匹配 很高 低 / 低 90 分选项

Qlib 提供 SigAnaRecordPortAnaRecord 等记录模板(官方 API)。MLflow Tracking则能记录参数、代码版本、指标和模型/文件 artifacts,本地运行已经足够个人 V1 使用。二者都不替代真实交易账本:研究记录回答“这个实验是什么”,账本回答“资金实际上发生了什么”。

五组必须同时看的指标

视角 核心指标 它回答什么
Alpha IC、RankIC、ICIR、分层单调性、衰减、覆盖率、分行业/规模稳定性 预测本身有没有横截面信息
组合 成本前后超额、IR、Sharpe/Sortino、最大回撤、Calmar、跟踪误差、换手、持仓集中度 信息是否被稳定地变成组合
风险 行业/风格/Beta 暴露、预测与实现波动、风险贡献、压力损失、限额触发 赚的钱是否来自意外押注
执行 / TCA arrival shortfall、VWAP/close 偏离、填单率、撤单/拒单率、完成时长、机会成本、参与率 纸面 Alpha 在哪里损失
运行 数据延迟/缺口、job 成功率、订单状态未知数、对账差异、恢复时间、告警确认 系统是否可靠运转

对收盘后决策的策略,TCA 要把隔夜跳空与日内执行分开:隔夜段从 T 收盘到 T+1 首个可执行基准价;implementation shortfall 的 arrival benchmark 使用 PreTrade Gate 通过后的首个有效报价/预先声明的执行窗基准。否则会把无法在夜间成交的价格变化错误归因给执行器。

每次再平衡至少保存四条净值或 P&L 轨迹:

理想 Alpha 组合(无约束、无成本)
→ 加风险/持仓约束后的目标组合
→ 使用回测成交模型后的模拟组合
→ 使用券商真实成交后的实盘组合

相邻两条之间的差异分别对应组合约束损失、模拟执行损失和研究—实盘偏差。只有一条最终净值时,任何层都能把错误推给别的层。

Champion / Challenger 与升级纪律

  • Champion 固定运行;Ridge、等权/Top-k、旧风险模型和旧成本模型保持为 challengers。
  • 新模型必须在预注册的样本外窗口、成本压力、多随机种子/参数邻域和暴露约束下胜出。
  • 不以一次显著性或一个市场状态升级;先 shadow,再小资金 canary,最后逐级放量。
  • 模型性能下降时先定位数据、Universe、风险、成本和执行,不默认“重新训练就会好”。
  • 每次升级写 decision record:证据、预期改善、风险、回滚条件、负责人和生效时间。

十二、工程、运行与合规层

这层不产生 Alpha,却决定研究结果是否能安全变成资金行为。

  • 职责:固化接口、版本、运行状态、权限、恢复、审计与平台适配,使研究和交易可以确定性重放。
  • 输入:前述所有领域对象、配置、外部事件、部署包和凭据引用。
  • 输出:可复现实验、已签名决策、部署 artifact、三本账、监控告警、对账与合规证据。
  • 60 分失败模式:Notebook 隐式状态、生产机手改代码、凭据进入仓库、重启重复下单、出错后没有 runbook。

工程形态候选

候选 优点 缺点 / 风险 复杂度 生产成熟度 当前适配 / 学习 ROI 决策
Notebook + 平台脚本 探索最快 隐式状态、难测试、难重放、平台锁定 中 / 中 仅探索
模块化 Python monorepo 一人可维护,接口与测试集中,部署简单 需要持续守住边界 很高 / 很高 V1 Baseline
多进程服务 + 消息队列 隔离与恢复能力更强 调试、部署和状态一致性成本上升 低 / 中 80 分按瓶颈引入
微服务/Kubernetes 团队扩展与资源调度强 个人日频系统严重过度设计 很高 很高 很低 / 低 拒绝

V1.0 仓库布局

quant-os/
├── pyproject.toml              # 锁定 Python 与依赖
├── configs/                    # 经 schema 验证的研究/风险/执行配置
├── src/
│   ├── domain/                 # 九种稳定对象,不导入任何平台 SDK
│   ├── data/                   # provider adapters、PIT、质量与版本
│   ├── universe/
│   ├── features/
│   ├── alpha/
│   ├── risk/
│   ├── cost/
│   ├── portfolio/
│   ├── execution/              # planner、OMS 状态机
│   ├── ledger/                 # 决策/订单/成交/持仓/现金
│   ├── evaluation/
│   └── adapters/
│       ├── qlib_research/
│       ├── joinquant/
│       └── qmt/
├── tests/
│   ├── unit/
│   ├── integration/
│   ├── replay/
│   └── parity/
├── migrations/                # schema 与规则迁移
├── runbooks/                   # 断线、拒单、错账、数据失败处置
└── artifacts/                 # 仅索引;大数据/模型由 manifest 指向

V1 不要求为了“像机构”而拆微服务。一个进程内也可以拥有严格接口、事件日志和恢复能力。只有观测到资源隔离、延迟或可靠性瓶颈后才拆服务。

三本账与重放

账本 写入时点 真相是什么
决策账 目标组合批准后 模型在何种数据、风险、成本和约束下想做什么
订单/成交账 每个券商回调到达时 实际提交、确认、撤改、拒绝、部分成交和费用
券商快照账 启动前、关键事件后、日终 券商认定的资产、持仓、可用量和未结订单

三账不得互相覆盖。对账输出差异及解释,只有白名单时间差允许自动清除;未知差异使次日系统进入 SAFE_MODE。所有外部事件保留原始 payload 的脱敏 hash 和解析结果,回放相同事件序列应得到相同订单状态。

测试金字塔

  • 单元:费用日期切换、可卖量、交易单位、复权、PIT join、约束与 rounding。
  • 属性测试:现金不为负、持仓数量守恒、成交累计不超过订单、重复事件不重复记账。
  • 集成:固定小样本从数据到目标,再通过模拟 broker 产生部分成交/拒单/断线。
  • Replay:保存一段 QMT 回调流,在无网络环境重建订单与持仓。
  • Parity:本地与聚宽对齐收益口径、信号日、费用、目标权重;差异必须落报告。
  • 故障注入:行情过期、数据缺列、回调乱序/重复、撤单超时、求解器失败、进程重启。

可观测性与操作

每次 run 至少记录:run_id、Git commit、dirty flag、配置 hash、数据版本、模型版本、规则版本、随机种子、依赖锁、启动人、环境和时间。日志使用结构化字段而非拼接长字符串;指标、告警和 runbook 一一对应。

实盘部署保留人工批准点:系统可以自动生成目标和执行计划,但从模拟切换到实盘、放大资金、改变最大申报频率或更换策略版本必须显式批准。密码、token、cookie 和券商凭据只放系统钥匙串/环境注入,不进入 Git、MLflow artifacts 或 OB。

合规不是上线后的补丁

证监会《证券市场程序化交易管理规定(试行)》自 2024-10-08 起施行,要求程序化交易投资者报告账户、资金、策略、软件等信息,并确立“先报告、后交易”(证监会原文)。沪深交易所实施细则自 2025-07-07 起施行(上交所深交所)。

因此,个人账户不应把“金额不大”理解为自动豁免。上线前需要向实际开户券商书面确认:

  1. QMT/MiniQMT/XtQuant 到底开通哪种、模拟与实盘各有哪些 API 和频率限制。
  2. 程序化交易报告的字段、入口、审核状态和策略/软件重大变更后的更新义务。
  3. 最大报撤频率、每日委托数、异常行为控制和券商侧熔断。
  4. 实盘可用行情层级、数据授权、委托类型、回调保证和断线重连行为。
  5. 交割单费用、最低佣金、资产/订单/成交查询的最终一致时间。

这五项未确认,系统可以继续回测和模拟,但 G10 不通过,不能标记为实盘 Baseline。

十三、V1.0 冻结配置:第一版到底采用什么

前面的候选比较最终收敛为下面这一套。这里的默认值是第一轮验证起点,所有变化都通过配置和 decision record,而不是散落在代码里。

system:
  market: CN_A_SHARE
  mode: long_only_cash
  research_engine: qlib_local
  validation_engine: joinquant
  live_adapter: qmt_xttrader
  decision_timezone: Asia/Shanghai

data:
  primary_provider: authorized_joinquant_or_jqdata
  canonical_store: parquet_duckdb
  point_in_time: strict
  raw_immutable: true
  version_by_manifest: true

universe:
  benchmark: CSI500
  membership: point_in_time
  ipo_seasoning_days: 120        # 初始研究值
  liquidity_window_days: 20
  states: [openable, hold_only, sell_only, frozen]

alpha:
  champion: lightgbm
  mandatory_challenger: ridge
  features: [momentum, reversal, volatility, liquidity, valuation, quality, relative]
  label: next_executable_5d_excess_return
  rebalance: weekly
  retrain: monthly
  validation: purged_walk_forward

risk:
  model: transparent_industry_style_factor
  covariance: ewma_shrinkage
  specific_risk: robust_residual_with_floor
  stress: [market_shock, industry_shock, vol_2x, corr_up, cost_2x, fill_50pct]

cost:
  fee_schedule: versioned_account_specific
  optimizer_model: continuous_convex_surrogate
  exact_ticket_fees: post_rounding_backtest_and_tca
  min_trade_notional: account_calibrated
  spread_model: quote_or_conservative_proxy
  impact_model: volatility_sqrt_participation
  scenarios: [low, base, high]

portfolio:
  solver: cvxpy_convex
  objective: alpha_minus_risk_minus_cost_minus_turnover
  cash_buffer: 0.05              # 初始研究值
  candidate_count_grid: [60, 100, 150]
  target_holdings_band: [30, 80] # 取整/repair 后的诊断带
  exact_cardinality_constraint: false
  single_name_cap_grid: [0.01, 0.02, 0.03]
  industry_active_cap_grid: [0.03, 0.05]
  one_way_turnover_grid: [0.10, 0.15, 0.20]
  adv_cap_grid: [0.01, 0.03, 0.05]
  solver_failure: no_trade_or_risk_reduction_only

execution:
  algorithm: guarded_twap_pov
  decision_time: T_after_close
  trade_day: T_plus_1
  start_after_open_minutes: 5
  partial_fill: true
  cancel_replace: ack_before_replace
  stale_market_data: block_new_orders
  reconciliation: startup_event_driven_eod

tracking:
  research: qlib_records_and_mlflow_local
  versions: [git_commit, env_lock, config_hash, data_version, model_version, rules_version]
  ledgers: [decision, order_fill, broker_snapshot]

一次完整再平衡的可执行顺序

  1. 数据封版:确认 T 日所需数据到齐,写 data_version 与质量报告。
  2. Universe:按 T 日状态生成研究、可开、只持、只卖和冻结集合。
  3. 预测:加载已批准 champion,对 FeatureSnapshot 出 5 日 Alpha;Ridge 同步出挑战结果但不下单。
  4. 风险/成本:估计风险暴露、协方差、特异风险、三档成本和容量。
  5. 组合:优化目标,取整与 repair,再做独立 post-check;保存 decision_id
  6. 发布一致性复核:在开发/发布 gate 中,用相同 fixture 在本地与聚宽检查规则、费用、信号和目标差异;超过容差则阻断该 release_id。实盘日不在线依赖聚宽。
  7. 开盘前对账:QMT 查询资产、持仓、可卖量、未结订单和昨日成交;不平则 SAFE_MODE
  8. PreTrade Gate:重算现金、目标差额、当日规则、行情新鲜度、限额和申报预算。
  9. 执行:父单拆子单,回调更新状态;先处理必须降低风险的可卖单,再按现金和优先级安排其余交易。
  10. 反馈:窗口结束处理残余;日终对账,生成 P&L、暴露、TCA、异常和 champion 健康报告。

平台之间传什么,不传什么

边界 允许传递 禁止依赖
Qlib → 核心 带时间、持有期、版本的预测表 Qlib 内部 dataset/model 对象直接进入交易
核心 → 聚宽 Universe、目标权重、费用/成交参数、run ID 用聚宽隐式全局状态定义策略事实
核心 → QMT 已批准的父单意图、限额和 idempotency key 把模型代码塞进券商 callback
QMT → 核心 原始回报、标准化事件、券商快照 用本地预期覆盖券商持仓或订单状态

这使“聚宽先跑、以后迁移 QMT”不再等于重写策略。真正需要重写的是平台适配器和少量时序,不是 Alpha、风险、成本与组合定义。

十四、这套 V1.0 为什么是 66 分,而不是 40 或 90

各层目标成熟度

纸面目标分 超过 60 的理由 还没到 80 的原因
数据 / Security Master 68 PIT、原始/标准分层、规则版本、快照与质量门齐全 单主源,复杂公司行动和历史修订仍需长期校验
Universe 66 PIT 成分、流动性、持有/买卖/冻结状态分离 尚无动态容量池和多 benchmark 稳定性
Alpha / 验证 65 LightGBM + Ridge、purged walk-forward、成本后多维指标 特征与标签仍是公开范式,尚无长期实盘证据
风险 64 透明多因子、收缩、特异风险、事前约束和压力测试 因子与协方差未用多年实盘/商业模型交叉验证
成本 / 容量 62 日期费率、价差、冲击、三档压力并进入优化 冲击参数尚无足量真实成交拟合
组合 68 Alpha—风险—成本联合优化,真实交易边界和失败降级 单期、参数不确定性处理仍较基础
执行 / OMS 62 异步状态、部分成交、幂等、节流、恢复与对账 没有精细量能预测、队列/盘口模型和多券商容灾
评价 / 反馈 65 预测—目标—成交四轨迹、归因、TCA、champion/challenger 自动漂移诊断与决策治理仍较轻
工程 / 运行 / 合规 64 模块单体、测试、事件账本、runbook、报告 gate 单机、人工值守、灾备与权限治理有限

总分计算

总评分维度 权重 目标得分 加权贡献
数据与时点正确性 15% 68 10.20
研究与样本外验证 15% 66 9.90
风险与组合构建 15% 67 10.05
成本与执行现实性 15% 62 9.30
工程与可复现性 15% 68 10.20
运行、对账与监控 15% 63 9.45
合规与平台迁移 10% 68 6.80
合计 100% 65.90 ≈ 66

[!important] 分数的正确读法 66 是这份设计在全部实现、测试、模拟和券商确认通过后的目标分。今天只有文档而没有证据,系统不能自称 66 分;每个 Gate 都应链接到测试报告、模拟记录或券商确认材料。

它不是 40 分,因为已经显式处理了数据时点、相关风险、成本容量、异步订单、对账与合规;它不是 90 分,因为没有私有数据优势、商业风险模型、长期成交数据库、多券商容灾、严格权限治理和多年资金验证。

十五、几条关键取舍:明确说“不选什么”

1. 不把等权当最终答案

等权保留为永远的 benchmark,但它没有使用预测强度、协方差、行业暴露、容量和交易成本。复杂优化器若长期不能成本后胜过等权,应下线复杂优化器,而不是删除等权对照。

2. 不用单均线代表 Alpha 层

单均线可以验证完整管线,也可能在趋势策略中有真实价值,但无法代表跨股票的特征、标签、排序、风险暴露和组合决策。它是测试信号,不是这篇 Baseline 的研究终点。

3. 不把止损叫风险系统

止损发生在价格已经移动以后,而且在停牌、跳空、跌停时未必能成交。它不处理相关性、行业集中、Beta、波动、流动性、容量和不可卖风险。V1 保留损失保护线,但把主要风险控制放在仓位生成以前。

4. 不假设订单瞬间全部成交

真实 API 是异步的,订单可能拒绝、部分成交、撤单失败或回报乱序。只要回测持仓能在一行代码里瞬间跳到目标,执行层就没有达到 60 分。

5. 不只看收益、Sharpe 和最大回撤

相同净值可能来自真正选股、行业押注、不可复制的成交价或数据泄漏。Alpha、风险、成本、执行和运行指标必须同时存在,并能沿 run_id/decision_id/order_id 下钻。

6. 不在 V1 先上 Transformer、GNN 或 RL

原因不是它们永远无效,而是当前主要误差更可能来自 PIT 数据、有效样本、风险暴露、费用和执行。深模型只有在稳定 Baseline 上作为 challenger,以相同信息集、相同验证协议、相同风险成本比较后才有意义。

7. 不追求一个框架包办一切

聚宽最懂当前 A 股研究体验,Qlib 最适合模型 workflow,LEAN 最值得学习架构,QMT 才连接实际券商。让一个框架承担不擅长的全部角色,会把便利变成锁定;稳定数据契约比统一 Logo 更重要。

8. 不用“最新”替代“可验证”

V1 优先成熟的树模型、收缩协方差、凸优化和确定性执行。新方法首先进入离线 challenger;只有它在净收益、稳定性、风险、运维和回滚五方面都证明增量价值,才进入生产。

9. 不用回测收益抵消代码质量,也不用漂亮架构掩盖无效 Alpha

上线采用双门:研究门要求样本外、成本后有稳定证据;工程门要求状态、测试、重放、对账和合规通过。任何一边失败都不能上线。

十六、从 60 到 80:按证据升级,不按功能堆砌

分阶段落地

阶段 目标 完成证据 禁止事项
Phase 0:合同与夹具(1—2 周) 九种对象、schema、规则表、固定小数据集 接口文档;PIT/费用/T+1/部分成交单测 先调模型找高收益
Phase 1:研究闭环(3—6 周) 本地 Qlib + Ridge/LightGBM + 风险/成本/优化 purged walk-forward 报告;实验可重放;等权/Top-k 对照 只保存一条最佳净值
Phase 2:双引擎与模拟(6—12 周) 本地与聚宽口径对齐,模拟运行 差异报告;至少 60 个交易日连续模拟;故障演练 发现差异后手工改净值
Phase 3:QMT 影子盘(4—8 周) 不发真实单,但用实时行情、券商快照和完整状态机 至少 20 个交易日;断线/重启/乱序回放;每日零未知账差 用模拟回调替代券商验证
Phase 4:小资金 canary 有人工批准、严格限额的真实成交 至少 20 个交易日;真实费用与 TCA;无未解释对账差异 初期即满资金、自动放量
Phase 5:受控放量 按容量与误差逐级扩大 每级预测—实现偏差和回滚审查 按回测收益直接决定资金量

这些天数是最低工程观察窗,不是统计显著性的保证。跨市场状态的策略有效性仍要靠更长样本与持续实盘证据。

各层 60 → 80 升级表

60 分 Baseline 到 80 分最有价值的升级 何时才值得做
数据 单主源 PIT + 版本快照 第二独立源对账、自动修订差分、字段级 lineage、更多逐笔/公告数据 主源错误已成为主要残差
Universe PIT 中证 500 + 静态容量门 资金规模驱动的动态流动性池、多 benchmark、拥挤/退市概率 CSI500 限制了容量或 Alpha
Alpha LightGBM + Ridge 稳健 ensemble、预测不确定性、正交新数据、因果/机制验证 简单模型已稳定且新数据有独立价值
风险 透明行业风格模型 动态相关、流动性/拥挤风险、商业模型交叉验证、模型风险 ensemble 风险预测误差可被量化定位
成本 代理冲击 + 压力区间 用真实成交分层拟合、日内量能预测、多日 liquidation、机会成本模型 积累足量不同股票/规模成交
组合 单期凸优化 鲁棒/多期优化、参数不确定性、分层风险预算、现金/Beta 联合组合 单期决策的短视成本已显著
执行 Guarded TWAP/POV 自适应量能/波动、智能限价、多窗口/多日计划、灾备 broker adapter TCA 证明执行损失是主要瓶颈
评价 四轨迹 + TCA + MLflow 自动归因、漂移分型、champion/canary 编排、统计过程控制 实验与实盘数量足以自动化
工程/运维 单机模块化 + 三账 热备、强权限审计、不可变事件库、异地恢复、多账户隔离 资金规模与停机损失值得成本

升级原则只有一个:先修复当前最大且可测的误差源。如果净收益主要损失在冲击,先改执行;如果模型在不同行业失效,先修 Alpha/Universe;如果每天对账都不稳,暂停所有模型升级。

十七、最终验收清单

以下项目全部打勾,才可以把 V1 标记为“达到 60 分”;其中 G10 和实盘权限必须由实际券商确认。

数据与研究

  • [ ] 历史指数成员、退市股、公司行动和财报公告时点可重放。
  • [ ] 原始价/复权因子分离;JoinQuant 与本地价格/收益口径差异有报告。
  • [ ] Random CV 已禁用;purge/embargo、walk-forward 和未触碰测试集写入代码。
  • [ ] Ridge、等权/Top-k 和 benchmark 全程保留,不只展示 LightGBM 最优结果。
  • [ ] 多时期、行业、规模和成本压力下结果无单点依赖。

风险、成本与组合

  • [ ] 行业/风格暴露、协方差、特异风险和压力测试都有版本。
  • [ ] 费率与券商交割单一致;冲击参数输出 low/base/high。
  • [ ] Alpha、风险、成本和换手共同进入优化;所有权重可解释。
  • [ ] 停牌、T+1、禁止开仓、现金和 ADV 是真实约束,不是事后修饰。
  • [ ] 求解不可行、rounding 和模型缺失均有测试过的降级路径。

执行、账本与运行

  • [ ] 分钟回放支持部分成交、残单、撤改、拒单和价格限制。
  • [ ] QMT adapter 支持幂等、重启恢复、乱序/重复回调和未知状态处置。
  • [ ] 启动前、运行中和日终三次对账;未知差异自动阻断新开仓。
  • [ ] 数据陈旧、断线、拒单激增和超限均触发明确 kill switch/runbook。
  • [ ] 每个实盘成交可追到 run_id → decision_id → parent_order → child_order → fill

复现、迁移与合规

  • [ ] Git、依赖、配置、数据、模型、规则版本和随机种子全记录。
  • [ ] 本地/聚宽双引擎差异在约定容差内,且费用和成交假设同源。
  • [ ] 聚宽策略不包含无法移植的核心业务逻辑;QMT callback 不包含模型逻辑。
  • [ ] 已完成至少 60 个交易日模拟、20 个交易日 QMT 影子盘和故障演练。
  • [ ] 已向国金等实际开户券商确认 QMT 权限、模拟/实盘差异、频率限制和程序化交易报告状态。

十八、现在只需要冻结的五个个人决策

技术栈可以先按本文实现,但以下五项最终来自你的资金目标,不应由框架替你决定:

决策 本文默认 改变它会影响什么
benchmark / 标的池 PIT 中证 500 Alpha 标签、风险暴露、持仓数与容量
资金规模与未来放量目标 未填;必须输入 ADV 门、单股上限、执行窗口和数据投入
风险预算 5% 现金缓冲;其余范围用网格 跟踪误差、行业偏离、回撤状态和仓位
调仓节奏 周频目标、次日执行 标签期限、换手、容量和执行模型
券商接口事实 待实际确认 QMT/MiniQMT Adapter、回调、频率、报告与上线日程

在这些答案出现前,系统仍能完成研究和模拟;但参数必须标记 UNCONFIRMED,不能把通用默认包装成个性化最优值。

十九、最终判断

这套 Baseline 的真正价值不在 LightGBM、CVXPY 或 QMT 任一名词,而在四个不可逆的工程习惯:

  1. 当时知道的数据与后来修订的数据分开。
  2. 预测、目标、订单、成交分开。
  3. Alpha、风险、成本、可交易性在下单前相遇。
  4. 研究结论、实盘事实和反馈证据可以沿版本与账本闭环。

只要这四点成立,未来把 LightGBM 换成 ensemble、把透明风险模型换成商业模型、把聚宽换成本地引擎、把 QMT 换成另一家券商,都属于可控升级。反过来,如果四点没有成立,再复杂的深度模型或更快的柜台只会让错误更快发生。

所以,个人 A 股系统的第一个“机构级 60 分”不应追求像一个缩小版大机构,而应该成为一个边界清楚、假设可见、失败安全、结果可复核、能够真实迁移的小系统。这足以作为未来 3—5 年的地基。

主要资料

架构与开源系统

模型、风险、组合与执行

A 股平台、规则与费用

与 OB 现有路线的关系