第三节:时间加权平均价格算法(TWAP)
TWAP,全称 Time-Weighted Average Price。说白了,就是把一个大单子,均匀地切成很多小份,然后按时间一点点扔到市场里去。
我刚开始做算法交易时,第一个接触的就是 TWAP。当时觉得这玩意儿太简单了,不就是定时定量嘛。后来在实际项目中踩了不少坑,才发现越简单的东西,细节越要命。
TWAP 的核心原理
TWAP 的逻辑非常直观:
- 目标:让成交价格尽量接近这段时间的市场平均价
- 方法:把总订单量按时间均匀分配
- 假设:市场在短时间内是随机的,均匀下单能降低冲击
举个例子。你要在 10 分钟内买入 100 万股。TWAP 的做法是:每分钟下 10 万股,不管价格怎么变。就这么简单。
核心公式:
每期下单量 = 总订单量 / 总期数
每期时间间隔 = 总执行时间 / 总期数
嗯,这里要注意。实际交易中,期数不能设得太细。我见过有人把 1 小时切成 3600 秒,每秒下一小单。结果呢?交易所的流控直接把他拒了。所以一般建议每期至少 3-5 秒以上。
实现步骤
TWAP 的实现,我习惯分三步走。你想想看,其实跟做饭差不多:备料、下锅、出锅。
第一步:参数设定
- 总数量:比如 100 万股
- 总时间:比如 600 秒(10 分钟)
- 切片数:比如 60 片(每 10 秒下一单)
- 每片数量:1000000 / 60 ≈ 16667 股
第二步:定时执行
用一个定时器,每 10 秒触发一次。每次触发时,检查当前持仓和剩余时间,动态调整下单量。
为什么要动态调整?因为前面的单子可能没完全成交。我曾经在实盘中遇到过连续 3 秒都没吃到货的情况,如果不调整,最后肯定完不成任务。
第三步:异常处理
- 如果市场剧烈波动,暂停执行
- 如果某次下单失败,重试 3 次
- 如果剩余时间不够,加速下单
下面是一个简化版的 Python 实现:
import time
import threading
class TWAPExecutor:
def __init__(self, total_qty, total_seconds, slices):
self.total_qty = total_qty
self.total_seconds = total_seconds
self.slices = slices
self.qty_per_slice = total_qty / slices
self.interval = total_seconds / slices
self.executed_qty = 0
self.start_time = None
def execute_slice(self):
# 计算剩余需要执行的量
remaining_qty = self.total_qty - self.executed_qty
remaining_time = self.total_seconds - (time.time() - self.start_time)
# 如果剩余时间不够,加速
if remaining_time < self.interval:
qty = remaining_qty
else:
qty = min(self.qty_per_slice, remaining_qty)
# 这里调用实际的交易接口
# self.broker.place_order(qty)
print(f"下单 {qty} 股,剩余 {remaining_qty - qty} 股")
self.executed_qty += qty
def run(self):
self.start_time = time.time()
for i in range(self.slices):
if self.executed_qty >= self.total_qty:
break
self.execute_slice()
time.sleep(self.interval)
# 使用示例
twap = TWAPExecutor(total_qty=1000000, total_seconds=600, slices=60)
twap.run()
避坑指南:我曾经在回测时发现,如果切片数设得太多(比如 1000 片),TWAP 的成交价格反而比市场平均价差很多。原因是每单太小,容易被市场噪音吃掉。建议切片数控制在 10-50 之间。
优缺点分析
TWAP 的优点很明显,缺点也很致命。咱们一个一个说。
优点
- 简单可靠:逻辑清晰,不容易出 bug。我团队的新人,培训 10 分钟就能上手写 TWAP。
- 可预测性强:你知道什么时候下多少单,风控好做。
- 对市场冲击小:均匀分散,不会引起价格剧烈波动。
- 适合大单:特别是那些不着急的订单,比如指数基金的调仓。
缺点
- 不灵活:市场明明在涨,它还是按部就班地买。说白了,它不会「追涨杀跌」。
- 容易被狙击:如果对手盘知道你在跑 TWAP,他可以在你下单前拉高价格,等你买完再砸下来。
- 无法应对极端行情:遇到闪崩,TWAP 还在傻傻地买,结果全买在高位。
- 执行成本可能偏高:在趋势行情中,TWAP 的成交价往往比 VWAP 差。
重要提醒:TWAP 不是万能的。我见过有人用 TWAP 做日内高频交易,结果亏得一塌糊涂。TWAP 适合的是分钟级以上的大单执行,不是秒级的抢单。
TWAP 的适用场景
| 场景 | 是否适合 TWAP | 原因 |
|---|---|---|
| 指数基金调仓 | ✅ 非常适合 | 时间充裕,量大,不需要抢速度 |
| 大宗交易拆单 | ✅ 适合 | 避免引起市场注意 |
| 日内高频交易 | ❌ 不适合 | 速度太慢,跟不上市场节奏 |
| 趋势行情 | ⚠️ 谨慎使用 | 容易买在高点,卖在低点 |
| 流动性差的股票 | ⚠️ 谨慎使用 | 每单量太小,容易被吃单 |
TWAP 的核心逻辑图
下面这张图,是我自己画的一个 TWAP 执行流程。你看一眼就能明白整个逻辑:
这张图的核心逻辑是:先设定参数,然后循环判断是否还有剩余订单。如果有,就计算当前应该下多少,然后执行。执行完再回来判断。直到所有订单都完成,结束。
个人经验:我在做 A 股市场的 TWAP 时,发现一个规律。如果股票流动性好(比如茅台),切片数可以设多一点,比如 30 片。如果流动性差(比如一些小盘股),切片数最好控制在 10 片以内。否则你的单子会被市场吃掉,成交价会偏离很多。
好了,TWAP 的核心内容就这些。说白了,它就是最基础的拆单算法。但基础不代表简单。我见过很多量化团队,连 TWAP 都写不好,最后实盘亏钱。所以,把基础打扎实了,后面的 VWAP、POV 才能学得明白。
公众号:蓝海资料掘金营,微信deep3321