第二章: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分钟
2.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)}股")
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
2.5 知识体系总览
下面这张图把TWAP算法的核心逻辑串起来了。我建议你多看几遍,理解每个模块之间的关系。
嗯,这张图把TWAP的四个核心模块串成了一个完整的流程。从输入参数开始,经过时间切片、订单分配、执行窗口三个并行模块,最后汇聚到基准价格计算,输出执行结果。
我个人建议你在实际开发中,先把这个框架搭好,再逐步优化每个模块的细节。别一上来就想搞个完美的算法,先跑起来,再迭代。
好了,这一章的内容就到这里。下一章我们会聊TWAP的实战部署和回测框架搭建,到时候我会分享一些具体的代码实现和调参技巧。