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 本章知识体系图

下面这张图,把三种算法的核心逻辑和关系梳理清楚了。

执行算法核心体系 执行算法 TWAP VWAP POV 核心特性 • 时间均匀分配 • 不依赖成交量 • 保证完成时间 • 信息泄露风险高 • 适合高流动性品种 核心特性 • 按成交量分配 • 依赖历史数据 • 融入市场自然成交 • 最主流的基准 • 适合有规律品种 核心特性 • 固定参与率 • 实时跟随市场 • 不保证完成时间 • 信息泄露风险低 • 适合流动性差品种

3.7 写在最后

这三种算法,是执行算法的“三原色”。

TWAP是基础,VWAP是进阶,POV是灵活应变。实际生产中,很少有人只用一种。更多时候是组合使用:比如用VWAP做主体框架,遇到异常成交量时切换到POV模式。

嗯,这里要注意:没有完美的算法,只有适合场景的算法。你想想看,如果一种算法能解决所有问题,那其他算法早就消失了。

我个人建议,初学者先把这三种算法的代码写一遍,跑一遍回测。感受一下在不同市场环境下,它们的表现差异。纸上得来终觉浅,绝知此事要躬行。

一个小练习:找一只股票的历史分钟线数据,分别用TWAP、VWAP、POV三种算法做回测。看看在同样的市场冲击下,哪种算法的滑点最小?答案可能会让你意外。

专注资料整理