执行算法(TWAP / VWAP)与 TCA
:::info 学习目标 你将能构造 TWAP/VWAP 子单计划,计算到达价 IS 与纯摩擦,并解释冲击、价格风险和成交量预测误差之间的权衡。 :::
直觉
你需要买入 10 万股,但一次性市价砸下去会把价格冲上天(上一节讲的冲击)。执行算法就是把这笔「母单」切成很多小「子单」、分散到一段时间里慢慢执行,降低冲击。两种最基础的是 TWAP(按时间均分)和 VWAP(按预期成交量分配——开盘收盘量大、午间量小,就在量大时多买)。评估执行好坏的核心指标是执行差额(Implementation Shortfall, IS):你的平均成交价相对到达价(决策那一刻的中间价)差了多少。
TWAP 与 VWAP
设日内共 段,每段成交量份额 ()、价格 ,到达价 :
「人话」解释:TWAP 和 VWAP 各什么时候用?
TWAP 最简单——不预测成交量,只要「时间均匀」,适合成交量模式不稳定、或你希望规则透明时。VWAP 利用「开盘和收盘成交密集、午间清淡」的常见形状,在量大时多下、量小时少下,目标是贴近市场 VWAP 并稳定参与率。它不保证每次都获得更低的 IS:执行期间若价格单边上涨,慢慢买入仍可能比一次性买入贵;成交量曲线预测失准也会增加冲击。选择算法本质上是在冲击、价格风险与基准偏离之间权衡。
可运行案例:TWAP vs VWAP vs 开盘一次性
模拟一条日内价格随机游走 + U 型成交量曲线,并让冲击随参与率平方上升。分别用三种方式执行同一笔买入,同时比较执行差额(IS)与纯交易摩擦。
import numpy as np
import matplotlib.pyplot as plt
rng = np.random.default_rng(1); M = 78 # 美股完整 6.5 小时,共 78 个 5 分钟段
t = np.arange(M)
vol_prof = 0.35 + ((t - (M-1)/2) / ((M-1)/2))**2 # U 型: 开收盘量大, 午间小
vol_prof /= vol_prof.sum()
price = 100*np.exp(np.cumsum(rng.normal(0, 0.0008, M))) # 日内随机游走
arrival = price[0]
Q = 100_000
market_volume = 2_000_000 * vol_prof # 各时段市场成交量
half_spread_bps, eta = 0.5, 100.0
def execute(child_qty):
participation = np.divide(child_qty, market_volume,
out=np.zeros_like(child_qty), where=market_volume>0)
friction_bps = half_spread_bps + eta * participation**2
fills = price * (1 + friction_bps/1e4)
avg = (fills * child_qty).sum() / child_qty.sum()
pure_cost = (friction_bps * child_qty).sum() / child_qty.sum()
return avg, pure_cost
q_naive = np.zeros(M); q_naive[0] = Q
q_twap = np.full(M, Q/M)
q_vwap = Q * vol_prof
naive, naive_cost = execute(q_naive)
twap_avg, twap_cost = execute(q_twap)
vwap_avg, vwap_cost = execute(q_vwap)
def is_bps(fill): return (fill - arrival)/arrival*1e4
print(f"到达价 = {arrival:.2f}")
print(f"开盘一次性 IS={is_bps(naive):7.1f} bps 纯摩擦={naive_cost:6.1f} bps")
print(f"TWAP IS={is_bps(twap_avg):7.1f} bps 纯摩擦={twap_cost:6.1f} bps")
print(f"VWAP IS={is_bps(vwap_avg):7.1f} bps 纯摩擦={vwap_cost:6.1f} bps")
fig, ax = plt.subplots(1, 2, figsize=(11, 3.3))
ax[0].plot(t, price, color='k', lw=1); ax[0].set_title('日内价格'); ax[0].set_xlabel('5分钟段')
ax[1].bar(t, market_volume, color='steelblue'); ax[1].set_title('U 型市场成交量'); ax[1].set_xlabel('5分钟段')
plt.tight_layout(); plt.show()
print("\n→ 纯摩擦反映参与率造成的成本;IS 还混入了执行期间的价格路径风险。")
TCA 不能只看一个基准
到达价衡量从决策到成交的总损失,市场 VWAP 衡量是否跟上全市场成交节奏,收盘价适合收盘跟踪任务。交易员可能跑赢 VWAP 却仍因决策延迟而产生很差的 IS。评估应分解决策延迟、执行价格、机会成本和费用,并按订单规模、参与率、时段和方向分组。
实践与延伸
- 加入单边上涨/下跌价格路径,比较三种算法的 IS 与纯冲击。
- 将预测成交量曲线偏移一小时,量化 VWAP 预测误差。
延伸阅读:Perold implementation shortfall;Almgren–Chriss 最优执行。
小结
- 执行算法把母单切成子单,降低价量冲击:TWAP 按时间均分、VWAP 按成交量加权;
- **执行差额(IS)**衡量成交价相对到达价的偏离,是评估执行质量的金标准;
- 成交量可预测时,VWAP 往往能稳定参与率;但单次 IS 还受价格路径影响,不能据一次模拟断言谁必然更优。
章末自测
1. 关于本章主题,哪项说法更准确?