3、执行算法入门:TWAP、VWAP、POV算法原理
各位同学,欢迎来到执行算法的世界。
说实话,很多刚入行的朋友觉得算法交易很神秘。其实没那么玄乎。说白了,就是帮你在不把市场打崩的前提下,把单子做完。
我个人习惯把执行算法分成三类:时间驱动、成交量驱动、以及参与率驱动。今天咱们就把这三个最经典的家伙——TWAP、VWAP、POV——彻底讲透。
3.1 为什么需要执行算法?
先问个问题:你有一百万股要卖,你会怎么干?
直接一笔砸出去?那叫“市场冲击”。你想想看,盘口上那点深度,瞬间就被你吃光了。价格直接跳水,你后面的单子全得卖在更低的价位上。
我在项目中遇到过一位交易员,他手动拆单,结果拆得太碎,反而被高频交易者嗅到了味道,一路被“狙击”。嗯,这就是典型的“信息泄露”。
执行算法要解决的,就是这三个核心矛盾:市场冲击、时间风险、信息泄露。
核心目标:在给定的时间窗口内,以最小的市场冲击和最优的加权价格,完成指定数量的订单。
3.2 TWAP:时间加权平均价格算法
TWAP,全称 Time-Weighted Average Price。名字听着挺唬人,其实原理简单到令人发指。
3.2.1 核心逻辑
就是把你的总订单量,按照时间均匀地切分。比如你从10:00到11:00要买100万股,那就每分钟切一点,每5分钟切一点。时间到了,任务完成。
它的数学公式长这样:
TWAP = Σ (Pi) / N
其中 Pi 是每个时间点的成交价格,N 是时间点的数量。
说白了,它根本不关心市场成交量是多少。它只关心“时间到了没”。
3.2.2 实战中的TWAP
我个人习惯把TWAP用在流动性比较好的品种上。比如沪深300的成分股,或者一些活跃的期货合约。
为什么?因为流动性好,你均匀地拆单,市场能消化掉。不会造成太大的冲击。
但要注意一个坑:TWAP在成交量稀疏的时段会很难受。
避坑指南:我曾经在下午开盘后的前几分钟用TWAP跑一个冷门小票。结果那几分钟成交量几乎为零,我的单子全挂在上面,成了“明牌”。后来我学乖了,冷门品种坚决不用纯TWAP。
3.2.3 代码示例:一个极简TWAP
def twap_schedule(total_qty, start_time, end_time, num_slices):
"""
生成TWAP切片计划
:param total_qty: 总数量
:param start_time: 开始时间 (datetime)
:param end_time: 结束时间 (datetime)
:param num_slices: 切片数量
:return: 每个时间点的委托量列表
"""
slice_qty = total_qty / num_slices
time_interval = (end_time - start_time) / num_slices
schedule = []
for i in range(num_slices):
exec_time = start_time + i * time_interval
schedule.append({
'time': exec_time,
'qty': slice_qty
})
return schedule
# 使用示例
schedule = twap_schedule(100000, '09:30', '10:30', 60)
print(f"每1分钟发单: {schedule[0]['qty']:.0f} 股")
3.3 VWAP:成交量加权平均价格算法
VWAP,全称 Volume-Weighted Average Price。这个比TWAP聪明一点。
3.3.1 核心逻辑
VWAP不按时间均匀分配,而是按历史成交量分布来分配。
你想想看,如果某个时间段成交量特别大,那你就多派点单子过去。如果某个时间段成交量很小,你就少派点。这样你的订单就能“融入”市场的自然成交中,不容易被发现。
公式如下:
VWAP = Σ (Pi * Vi) / Σ Vi
其中 Vi 是每个时间点的成交量。
3.3.2 实战中的VWAP
VWAP是我个人最常用的基准。很多机构投资者考核交易员,用的就是VWAP。如果你的成交价格比VWAP好,说明你执行得不错。
但这里有个关键点:VWAP依赖历史数据。
个人经验:我建议至少用过去5-10个交易日的平均成交量分布来做预测。单日的成交量分布噪音太大。比如某天突然有个大单砸盘,那天的成交量分布就失真了。
3.3.3 代码示例:VWAP切片
def vwap_schedule(total_qty, volume_profile):
"""
基于历史成交量分布生成VWAP切片
:param total_qty: 总数量
:param volume_profile: 每个时间段的成交量占比列表 [0.02, 0.03, ...]
:return: 每个时间段的委托量列表
"""
total_volume_ratio = sum(volume_profile)
schedule = []
for ratio in volume_profile:
slice_qty = total_qty * (ratio / total_volume_ratio)
schedule.append(slice_qty)
return schedule
# 假设某股票在10个时间段的成交量占比
volume_profile = [0.08, 0.09, 0.12, 0.15, 0.13, 0.11, 0.10, 0.09, 0.07, 0.06]
schedule = vwap_schedule(100000, volume_profile)
print(f"第一个时间段的委托量: {schedule[0]:.0f} 股")
3.4 POV:参与率算法
POV,全称 Percentage of Volume。这个算法更“动态”。
3.4.1 核心逻辑
POV不预设时间,也不预设成交量分布。它只做一件事:保持你的交易量占市场成交量的固定比例。
比如你设定参与率为10%。那么市场每成交1000股,你就成交100股。市场成交快,你就跑得快。市场成交慢,你就等着。
这个算法的好处是:你永远不会成为市场的“主角”。你始终是那个“跟着喝汤”的人。
3.4.2 实战中的POV
POV特别适合那些流动性不稳定的品种。比如一些中小盘股,或者刚上市的新股。
我记得有一次做一只科创板股票,流动性时好时坏。用TWAP,流动性差的时候挂半天成交不了。用VWAP,预测的成交量分布跟实际完全对不上。最后换成POV,设了个8%的参与率,跑得稳稳当当。
注意:POV有一个天然缺陷——它无法保证在指定时间内完成订单。如果市场成交量突然萎缩,你的订单可能永远做不完。所以实战中,POV通常会搭配一个“最晚完成时间”的硬约束。
3.4.3 代码示例:POV逻辑
class POVExecutor:
def __init__(self, total_qty, participation_rate):
self.remaining_qty = total_qty
self.participation_rate = participation_rate # 0.1 表示10%
self.executed_qty = 0
def on_market_trade(self, market_volume):
"""
当市场有成交时,计算本次应委托量
"""
target_qty = market_volume * self.participation_rate
actual_qty = min(target_qty, self.remaining_qty)
self.executed_qty += actual_qty
self.remaining_qty -= actual_qty
return actual_qty
# 使用示例
pov = POVExecutor(100000, 0.1)
market_volumes = [5000, 8000, 3000, 12000] # 模拟市场逐笔成交量
for vol in market_volumes:
order_qty = pov.on_market_trade(vol)
print(f"市场成交{vol}股,我方委托{order_qty:.0f}股,剩余{pov.remaining_qty:.0f}股")
3.5 三种算法的对比与选择
好了,三种算法都讲完了。咱们来做个对比。
| 特性 | TWAP | VWAP | POV |
|---|---|---|---|
| 驱动因素 | 时间 | 历史成交量 | 实时成交量 |
| 适用场景 | 流动性好、波动小 | 有稳定成交量模式 | 流动性不稳定 |
| 能否保证完成时间 | 能 | 能(基于预测) | 不能 |
| 市场冲击控制 | 中等 | 较好 | 最好 |
| 信息泄露风险 | 高 | 中等 | 低 |
怎么选?我个人有个简单的判断标准:
- 如果市场流动性好,且你不在乎被看出意图,用TWAP,简单粗暴。
- 如果市场有规律,你想“融入”市场,用VWAP,这是最主流的做法。
- 如果市场流动性差,或者你特别怕暴露意图,用POV,但记得加个时间上限。
3.6 本章知识体系图
下面这张图,把三种算法的核心逻辑和关系梳理清楚了。
3.7 写在最后
这三种算法,是执行算法的“三原色”。
TWAP是基础,VWAP是进阶,POV是灵活应变。实际生产中,很少有人只用一种。更多时候是组合使用:比如用VWAP做主体框架,遇到异常成交量时切换到POV模式。
嗯,这里要注意:没有完美的算法,只有适合场景的算法。你想想看,如果一种算法能解决所有问题,那其他算法早就消失了。
我个人建议,初学者先把这三种算法的代码写一遍,跑一遍回测。感受一下在不同市场环境下,它们的表现差异。纸上得来终觉浅,绝知此事要躬行。
一个小练习:找一只股票的历史分钟线数据,分别用TWAP、VWAP、POV三种算法做回测。看看在同样的市场冲击下,哪种算法的滑点最小?答案可能会让你意外。