跳到主要内容

执行算法(TWAP / VWAP)与 TCA

:::info 学习目标 你将能构造 TWAP/VWAP 子单计划,计算到达价 IS 与纯摩擦,并解释冲击、价格风险和成交量预测误差之间的权衡。 :::

直觉

你需要买入 10 万股,但一次性市价砸下去会把价格冲上天(上一节讲的冲击)。执行算法就是把这笔「母单」切成很多小「子单」、分散到一段时间里慢慢执行,降低冲击。两种最基础的是 TWAP(按时间均分)和 VWAP(按预期成交量分配——开盘收盘量大、午间量小,就在量大时多买)。评估执行好坏的核心指标是执行差额(Implementation Shortfall, IS):你的平均成交价相对到达价(决策那一刻的中间价)差了多少。

TWAP 与 VWAP

设日内共 MM 段,每段成交量份额 vmv_mvm=1\sum v_m=1)、价格 PmP_m,到达价 P0=ParrivalP_0=P_{\text{arrival}}

TWAP 均价=1MmPm,VWAP 均价=mvmPm\text{TWAP 均价}=\frac{1}{M}\sum_m P_m,\qquad \text{VWAP 均价}=\sum_m v_m P_m IS(买)=均价P0(越小越好;正数=成本)\text{IS(买)}=\text{均价}-P_0\quad(\text{越小越好;正数=成本})
「人话」解释: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。评估应分解决策延迟、执行价格、机会成本和费用,并按订单规模、参与率、时段和方向分组。

实践与延伸

  1. 加入单边上涨/下跌价格路径,比较三种算法的 IS 与纯冲击。
  2. 将预测成交量曲线偏移一小时,量化 VWAP 预测误差。

延伸阅读:Perold implementation shortfall;Almgren–Chriss 最优执行。

小结

  • 执行算法把母单切成子单,降低价量冲击:TWAP 按时间均分、VWAP 按成交量加权;
  • **执行差额(IS)**衡量成交价相对到达价的偏离,是评估执行质量的金标准;
  • 成交量可预测时,VWAP 往往能稳定参与率;但单次 IS 还受价格路径影响,不能据一次模拟断言谁必然更优。

章末自测

检查核心概念

1. 关于本章主题,哪项说法更准确?