第二章:TWAP算法设计——时间切片、订单分配、执行窗口与基准价格

TWAP算法,说白了就是把一个大单子切成小块,均匀地撒在时间轴上。听起来简单吧?但真正落地的时候,坑多得很。我最早做TWAP的时候,以为就是拿总数量除以总时间就完事了,结果被市场狠狠教育了一顿。

今天咱们就把TWAP的四个核心模块拆开揉碎了讲:时间切片机制、订单分配逻辑、执行时间窗口、基准价格计算。每个部分我都会结合实战经验来讲,尤其是那些我踩过的坑。

2.1 时间切片机制

时间切片,就是决定「每隔多久发一次单」。这个粒度很关键。

我个人习惯把切片分为两种:

  • 固定时间切片:比如每30秒发一次单。简单粗暴,适合流动性好的品种。
  • 动态时间切片:根据市场波动率调整切片长度。波动大的时候切细一点,波动小的时候切粗一点。

举个例子,假设你要在1小时内卖出10000股:

# 固定切片:每5分钟发一次单,共12个切片
total_shares = 10000
total_minutes = 60
slice_interval = 5  # 分钟
num_slices = total_minutes / slice_interval  # 12
per_slice = total_shares / num_slices  # 约833股

# 动态切片:根据过去5分钟的波动率调整
import numpy as np

def dynamic_slice(volatility, base_interval=5):
    # 波动率越高,切片越短
    if volatility > 0.02:  # 波动率大于2%
        return base_interval * 0.5  # 2.5分钟
    elif volatility > 0.01:
        return base_interval * 0.8  # 4分钟
    else:
        return base_interval  # 5分钟
实战经验:我建议切片数量不要少于10个,也不要多于100个。太少的话,单笔订单太大,容易引起市场冲击;太多的话,订单碎片化严重,交易所手续费可能吃掉你的利润。

2.2 订单分配逻辑

切片做好了,接下来就是「每个切片里怎么分配订单」。这里有两个流派:

  1. 均匀分配法:每个切片分配相同数量的订单。简单,但不够聪明。
  2. 加权分配法:根据市场深度、成交量、波动率等因素动态调整每个切片的订单量。

我记得有一次做美股TWAP,用均匀分配法,结果在开盘后半小时内市场突然放量,我的订单全砸在了低点上。后来我改成了加权分配法,效果好了很多。

加权分配的核心公式:

# 假设我们有历史成交量分布
volume_profile = [0.08, 0.07, 0.09, 0.10, 0.11, 0.12, 0.10, 0.09, 0.08, 0.06, 0.05, 0.05]
# 对应12个时间切片

total_shares = 10000
weighted_slices = [total_shares * w for w in volume_profile]

# 输出每个切片应分配的股数
for i, shares in enumerate(weighted_slices):
    print(f"切片{i+1}: {int(shares)}股")
注意:加权分配法依赖历史数据。如果市场结构发生突变(比如财报发布、政策调整),历史数据可能失效。我曾经在2020年3月美股熔断期间吃过这个亏,历史成交量分布完全不准。

2.3 执行时间窗口

执行时间窗口,就是「你打算在多长时间内完成这笔交易」。这个参数直接影响你的执行风险。

时间窗口越长,执行价格越接近VWAP,但暴露在市场中的时间也越长。时间窗口越短,执行速度越快,但冲击成本可能更高。

我一般用这个经验法则:

订单规模(占日均成交量比例) 建议时间窗口 说明
< 1% 15-30分钟 流动性好,可以快速执行
1% - 5% 1-2小时 需要分散,避免冲击
5% - 10% 半天到一天 必须非常小心,建议分多日执行
> 10% 多日执行 TWAP可能不适合,考虑VWAP或POV

你想想看,如果你要卖出一只小盘股,日均成交量才50万股,你一下子挂10万股的卖单,那不是明摆着告诉市场「我要跑路」吗?

核心原则:时间窗口的选择,本质上是「时间风险」和「价格风险」的权衡。时间窗口越长,价格风险越小(因为更接近市场均价),但时间风险越大(市场可能在你执行期间发生不利变动)。

2.4 基准价格计算

TWAP的基准价格,就是「时间加权平均价格」。计算方式很简单:

TWAP = (P1 + P2 + ... + Pn) / n

其中:
- P1, P2, ..., Pn 是每个时间点的价格
- n 是时间点的数量

但这里有个细节:用什么价格?

我个人习惯用中间价(mid price),也就是(买一价 + 卖一价)/ 2。为什么?因为成交价受订单流影响太大,而中间价更能反映市场的真实价值。

举个例子:

# 计算5分钟内的TWAP基准
import pandas as pd

# 假设我们有每分钟的中间价数据
data = {
    'time': ['09:30', '09:31', '09:32', '09:33', '09:34'],
    'mid_price': [100.10, 100.15, 100.12, 100.18, 100.20]
}

df = pd.DataFrame(data)
twap = df['mid_price'].mean()
print(f"TWAP基准价格: {twap:.2f}")
# 输出: TWAP基准价格: 100.15
避坑指南:我曾经用成交价计算TWAP,结果发现基准价格总是比实际成交价低。后来才意识到,因为我的大单子本身就在压低价格,用成交价计算基准相当于「自己打自己」。改用中间价后,这个问题就解决了。

2.5 知识体系总览

下面这张图把TWAP算法的核心逻辑串起来了。我建议你多看几遍,理解每个模块之间的关系。

TWAP算法核心逻辑框架 输入参数 总数量、时间窗口、品种 时间切片机制 固定切片 vs 动态切片 切片数量:10-100个 订单分配逻辑 均匀分配 vs 加权分配 基于成交量分布 执行时间窗口 15分钟到多日 时间风险 vs 价格风险 基准价格计算 中间价 vs 成交价 TWAP = (P1 + P2 + ... + Pn) / n 执行结果 成交价格、滑点分析

嗯,这张图把TWAP的四个核心模块串成了一个完整的流程。从输入参数开始,经过时间切片、订单分配、执行窗口三个并行模块,最后汇聚到基准价格计算,输出执行结果。

我个人建议你在实际开发中,先把这个框架搭好,再逐步优化每个模块的细节。别一上来就想搞个完美的算法,先跑起来,再迭代。

总结一下:TWAP算法的核心就是「把时间切成片,把订单分到片,在窗口内执行,用基准价衡量」。这四个模块环环相扣,任何一个环节出问题,最终的执行效果都会打折扣。

好了,这一章的内容就到这里。下一章我们会聊TWAP的实战部署和回测框架搭建,到时候我会分享一些具体的代码实现和调参技巧。

专注资料整理