周五下午一家 RMB 400 亿规模的多策略私募投资委员会。三个团队竞标资金配置。A 团队:US 大盘股动量纸面 Sharpe 1.6,年化换手 200%。B 团队:中证1000 小盘股统计套利纸面 Sharpe 2.4,年化换手 1000%。C 团队:低换手价值策略纸面 Sharpe 1.2,换手 50%。CIO 给每个团队问同一个问题:「拟上线 AUM 下的成本感知 Sharpe 多少?容量多少?纸面数字我不看。」A 团队:$500M 上线 AUM 下成本感知 Sharpe 1.4;容量 $5B。B 团队:$200M 上线 AUM 下成本感知 Sharpe 0.6;容量 RMB 25 亿——这就是问题,因为团队申请的是 RMB 50 亿。C 团队:$1B 上线 AUM 下成本感知 Sharpe 1.1;容量 $10B+。CIO 把 $400M 配给 A,$500M 配给 C,B 因为容量约束只给 $100M (盖在半容量上)。这段对话就是本模块一直在搭建的上线评审瞬间。L1 给了你显性成本条目。L2 给了你 市场冲击 (market impact) 模型 和 滑点 / 实施差额 框架。L3 给了你 Almgren-Chriss 最优执行计划。本课是集成压轴:三者如何插进 4.5.1 五层引擎,生产级成本感知回测产出什么工件,以及如何通过 TCA 在上线后验证可信度。头条数字是成本感知 夏普比率 和容量;二级数字是成本调整后 PnL 路径的 最大回撤。
(A) 成本感知撮合模拟器
4.5.1 五层引擎的撮合模拟器签名 simulate_fills(orders, bar) -> fills。4.5.1 L2 撮合模型用了 ~10 bp round-trip 占位——一个忽视规模、方向、场所、regime 的扁平数字。我们用 L1 + L2 + L3 全栈成本替代占位。
合约:对每个订单每个 bar 计算成交价和成本拆解 dict。成交价有三个分量:
fill_price = bar_open
+ half_spread × sign # L1: explicit spread cost
+ impact_function(Q, V, σ) × sign # L2: square-root impact
L3 Almgren-Chriss 计划在订单大到 Q/V > 5% 时触发——撮合模拟器沿 AC 轨迹生成子成交序列而不是单笔成交。
Inline-code 列表:成本拆解 dict 严格按此八个 key 顺序返回:
1. spread_bp — L1: half_spread × notional × 1e4
2. commission_bp — L1: commission rate × notional
3. exchange_fee_bp — L1: Section 31 + TAF (US) or 经手费 + 过户费 (CN)
4. stamp_duty_bp — L1: 印花税 sell-side only (CN)
5. borrow_bp — L1: borrow cost × holding period (shorts only)
6. temporary_impact_bp — L2: ~2/3 × Y × σ × sqrt(Q/V)
7. permanent_impact_bp — L2: ~1/3 × Y × σ × sqrt(Q/V)
8. total_cost_bp — sum of the seven components above
会计层每 bar 把 total_cost_bp × notional / 1e4 扣到 PnL 上。生产端撮合模拟器必须强制的四个工程点:
- L1 方向敏感:印花税 CN 卖方单边;海外 Section 31 + FINRA TAF 卖方单边。Maker-taker 区分(被动 vs 激进订单)——撮合模拟器必须跟踪每笔交易方向和订单类型。
- L2 参与率决策规则——Q/V > 30% 要求多 bar / 多日 切单。
- 冲击预测是随机的;生产端撮合模拟器在预测周围采样,可配置噪声水平(典型为冲击量级 1σ 的 ±20%)。
- L3 AC 计划作为每订单子订单计划插入:订单大到 Q/V > 5% 时,撮合模拟器沿 AC 轨迹生成子成交序列。
Fenced Python 实现:
import numpy as np
# L1 + L2 + L3 cost-aware fill simulator; plugs into 4.5.1 engine
def simulate_fills_cost_aware(orders, bar, rates, impact_params):
"""成本 感知 撮合 模拟器 集成 L1 显性 + L2 冲击 + L3 AC"""
fills, cost_breakdowns = [], []
for order in orders:
explicit = compute_explicit_cost(order, bar, rates)
impact = compute_impact(order, bar, impact_params)
qv = order["shares"] / bar["adv"]
sign = 1 if order["side"] == "buy" else -1
if qv > 0.05:
schedule = ac_trajectory(order["shares"], T=1.0, N=10,
sigma=bar["daily_sigma_bp"],
eta=impact_params["eta"],
gamma=impact_params["gamma"],
lam=impact_params.get("lam", 1e-6))
for child_shares in np.diff(-schedule):
fills.append(child_shares)
else:
fills.append(order["shares"])
cost_breakdown = {
"spread_bp": explicit["spread"] * 1e4 / (order["shares"] * bar["mid_price"]),
"commission_bp": rates["commission_bp"],
"exchange_fee_bp": rates["sec_fee_bp"] + rates["taf_bp"],
"stamp_duty_bp": rates["stamp_duty_bp"] if order["side"] == "sell" else 0.0,
"borrow_bp": 0.0,
"temporary_impact_bp": impact["temporary_impact_bp"],
"permanent_impact_bp": impact["permanent_impact_bp"],
}
cost_breakdown["total_cost_bp"] = sum(v for k, v in cost_breakdown.items()
if k != "total_cost_bp")
cost_breakdowns.append(cost_breakdown)
return fills, cost_breakdowns
(B) 交易成本分析 (TCA) 报告
每个生产级策略要求的上线后工件。TCA 报告服务三个目的:(i) 验证 —— 回测成本预测是否与实际实盘成本匹配?(ii) 归因 —— 哪个券商 / 算法 / 场所产生最好的成交?(iii) 风险监控 —— 哪些交易实际成本显著高于预测?
Inline-code 列表:TCA 报告的六个必备 section,按此严格顺序:
1. implementation shortfall
2. VWAP-benchmark deviation
3. arrival-price benchmark deviation
4. spread cost (predicted vs realized)
5. impact cost (predicted vs realized, temp/perm split via reversion at 5min / 30min / 1day)
6. outliers (> 2σ above predicted)
反转横向集 (5min、30min、1day) 和异常阈值 (2σ) 锚定报告的经验部分。
(1) 实施差额 (IS, bp)。综合 IS = (avg fill - arrival) / arrival × 10000 × sign。基线 IS 分布是回测冲击模型 (L2) 的预测分布;实盘分布应该重叠。
(2) VWAP 偏离 (bp)。fill − day-VWAP / day-VWAP × 10000 × sign。VWAP 是行业标准的代理-交易基准。
(3) 到达价偏离 (bp)。等价于 IS 但单独报告以区分「决策时」到达和「执行启动」到达。
(4) 价差成本 —— 预测 vs 实际。预测:L1 报价半价差 × 2。实际:trade-vs-mid 偏差回归。
(5) 冲击成本 —— 预测 vs 实际,通过 5min、30min、1day 横向上的交易后反转拆出 临时 / 永久。实盘 临时 / 永久 比例偏离预测 ~2/3 + 1/3 超过 20% 提示需要参数刷新。
(6) 异常成交。实际成本 > 预测 + 2σ 的交易标记给券商 / 算法复核。调查流程:(i) 确认交易未在停牌 / 熔断 session 内;(ii) 确认券商算法在约定参数内运行;(iii) 确认订单未泄漏;(iv) 重新检查冲击模型参数;(v) 升级到券商对接。
CN TCA 厂商 landscape:中证 行业 平均 + 公募 monthly TCA 自披露;私募买方典型自建内部 TCA。中信 CITIC、中信建投、国泰君安、海通、华泰 提供卖方内部 TCA。证监会程序化交易监管 (2024) 要求 算法 交易 标记 订单的每日 TCA 日志记录。
(C) 容量计算
容量是策略成本感知 夏普比率 降到纸面 Sharpe 50% 的毛 AUM。超过容量 AUM,成本增长比 alpha 快——策略开始自我侵蚀。低于容量,策略可靠扩展。
数学。令 = 纸面 Sharpe(gross of cost), = 纸面年化收益 bp 计, = 年化换手, = round-trip 成本 (bp) 作 AUM 的函数。从 L1 + L2:冲击项随 缩放——AUM 翻倍冲击乘 倍。
成本感知 Sharpe:
容量 AUM 是该值降到 的 AUM:
变量名——、 (纸面 Sharpe)、 (年化换手)、、、——与每一家主要买方机构的容量表上的标签一致。半 Sharpe 降级标准 0.5 × paper_sharpe 是行业标准的容量阈值。二级检查:确认成本调整后 PnL 的 最大回撤 在策略风险预算内。
算例
US 大盘股动量:, bp,,$100M 上 round-trip ~30 bp。$100M 上成本感知 Sharpe: 纸面。容量:, bp;从 sqrt 缩放容量 ~$10B。考虑 Q/V > 30% 的非线性,现实容量 ~$500M 到 $1B。
US 小盘股统计套利:, bp,,$50M 上 ~50 bp。$50M 上成本感知 Sharpe ~1.67 ≈ 67%。容量:, bp;容量 ~$112M。小盘股套利容量上限 ~$100M 到 $150M。
Markdown 表:成本感知 Sharpe 降级曲线
把 4.5.1 的 5 日动量策略(纸面 Sharpe ~0.4)放到 510300 沪深300 ETF 上算五个 AUM 水平的成本感知 Sharpe:
| AUM | Q/V (typical) | total round-trip cost (bp) | cost-aware Sharpe at 200% turnover |
|---|---|---|---|
| RMB 100M | <0.01% | ~9 | 0.39 |
| RMB 500M | ~0.5% | ~12 | 0.38 |
| RMB 1B | ~1.0% | ~15 | 0.37 |
| RMB 5B | ~3.0% | ~23 | 0.34 |
| RMB 10B | ~5.0% | ~30 | 0.30 |
头条观察:策略在 RMB 5B 之前大致保留纸面 Sharpe 的大部分价值——510300 ETF 容量异常高,因为日均成交量大且 ETF 创设-赎回通道压缩冲击。同样策略放到中证1000 小盘股单只股票上,在 RMB 10-20 亿时 Q/V 涨到 5-30%,冲击成本 30-100 bp,容量在 RMB 1-5 亿。2020-2022 中证500 指数增强 + 量化私募指数容量塌方就是 CN 标志性案例。
成本感知回测报告纪律
Inline-code 列表:每个生产级回测按此严格顺序报告以下三项:
1. cost decomposition at THREE turnover levels (current, 2×, 5×)
2. cost-aware Sharpe at THREE AUM levels (current, 2×, 5×)
3. capacity (half-Sharpe-degradation AUM) and the capacity-aware Sharpe curve
没有这些数字的回测就不是生产级回测。前置指针:4.6.2 通过对比实盘 TCA vs 回测 TCA 闭环——预测与实际成本差距在 6+ 个月内保持小时,成本模型得到验证,策略可以分配满容量。
Formula Explorer
S_{\text{cost-aware}} = S_p \times \left(1 - \frac{\tau \times C}{R}\right)变 round-trip 成本 C,看 从 滑到半 Sharpe 断点。
练习
Exercise
把 4.5.1 的 5 日动量策略(纸面 Sharpe ~0.4)放到 510300 沪深300 ETF 上。用 L1 显性成本栈(~8 bp ETF round-trip)和 L2 冲击模型 ,。做四个计算并报告。
(i) 毛 AUM RMB 100M 时,假设典型交易规模为日 PnL 贡献的 1% → ~RMB 1M 每笔 (510300 ADV ~10M 股,按 RMB 4 每股算 RMB 40M 名义 ADV);Q/V ;日 = 150 bp;计算冲击成本 bp、总 round-trip 成本 bp、和 200% 换手下的成本感知 Sharpe。
(ii) 同 (i) 但毛 AUM RMB 1B;典型交易规模线性涨 10×,Q/V → 触发 AC 切单。
(iii) 同 (i) 但毛 AUM RMB 10B;触发跨日切单。
(iv) 从 (i)-(iii) 外推容量 AUM:成本感知 Sharpe 降到 0.2 (纸面 0.4 的一半) 时的 AUM;报告容量 AUM 和该 AUM 上的 round-trip 成本。
把所有四个答案放在一张表里。
提示
提示
510300 高容量,半-Sharpe 容量在 RMB 50-100 亿区间。CN 端 TCA 实务再深一层
CN 私募在搭 TCA 时再注意几个工程点。一是分券商归因要按算法分桶——中信 CITIC、中信建投、国泰君安、海通、华泰 各自的 「智能拆单」实现细节不同,IS 分布、VWAP 偏离的形态也不同;合并归因会把好券商和坏券商平均掉,看不出真问题。二是异常交易的核查链——A 股 涨停 / 跌停 名字成交是天然的异常交易,但属于「合理异常」而不是 「执行问题异常」,TCA 异常 section 要给两个分类标签。三是分时段 TCA——9:30 开盘 + 10 分钟、最后 30 分钟收盘 拍卖前后、午间集合竞价附近都有独立的微结构,IS 在这些时段会系统性偏离全日均值,归因要按时段切。四是跨日订单的 IS 归因——T+1 结算让一笔需要 2-3 个 session 完成的清仓单产生跨日 IS,到达价的选择 (决策日 close vs 执行启动日 open) 直接影响 IS 数字,私募内部要锁定一种约定并在每份 TCA 报告里写明。
四节课串起来
本模块是四步搭建。L1 锚定显性成本栈——交易回单上的条目,确定性、可从公开费率表算。四个桶——买卖价差、佣金、交易所 / 监管 费用、融资融券——组合成 round-trip 方程,从一张表查就能给任何场所任何规模的股票交易定价。L2 在 L1 之上加隐性成本栈——总交易成本里不出现在交易回单上但出现在到达价与实际成交均价之差里的部分。平方根法则 impact_bp ≈ Y × σ × sqrt(Q/V) 是经验主力公式;线性冲击拆解是 L3 优化推导用的可解析替代形式。L3 然后推导 Almgren-Chriss 闭式 cosh 轨迹——「给定成本栈和要清仓的头寸,什么计划最小化均值-方差成本」的标准答案。L4 现在把三层装配进单一的成本感知撮合模拟器并插入 4.5.1 五层回测引擎,加上验证成本模型的 TCA 报告,加上锚定 AUM 配置决策的容量计算。开头投资委员会问的三个问题——成本感知 夏普比率、容量、最大回撤 风险预算——L4 之后你能从同一份回测里给出全部三个答案。CN 端额外注意:T+1 结算、印花税单边卖方、涨跌停截断、券商算法的程序化交易监管 (2024),这些都要写进撮合模拟器的本地化参数,否则回测在 实盘 上线后会出现「冲击 vs 滑点」不对称的偏差。
模块收尾
没有拟上线 AUM 下成本感知 Sharpe 的回测是不完整的。没有容量数字的回测是误导的。纸面 Sharpe > 1 + 成本感知 Sharpe < 0.3 的策略在任何现实部署情景下都不经济。前置指针:4.5.3 (Execution Algorithms) ——执行算法可以通过把市价单换为参与率算法回收 5-15 bp;这把容量推高。前置指针:4.6.2 (Performance Measurement & Attribution) ——实盘 TCA 对回测 TCA 是闭合部署周期的验证回路。模块 4.5.2 在此结束。
已涵盖组件
- Inline-code 列表:成本拆解 dict 八 key。
- Inline-code 列表:TCA 报告六个必备 section。
- Fenced Python
simulate_fills_cost_aware(orders, bar, rates, impact_params)集成 L1 + L2 + L3。 - 容量计算 KaTeX 块。
- Markdown 表:五个 AUM 水平的成本感知 Sharpe 降级曲线。
- Inline-code 列表:三个成本感知回测报告要求。
- FormulaExplorer——成本感知 Sharpe 降级公式。
- Exercise——
510300上的四个子任务。 - Two 递进 Hint。