3. 时间加权平均价格算法(TWAP)

TWAP,全称 Time-Weighted Average Price。说白了,就是把一个大单子,均匀地拆成很多小单子,在固定的时间段内分批执行。

我刚开始做高频交易那会儿,觉得这算法太简单了。不就是把100万股拆成100份,每分钟扔1万股嘛。后来才发现,越简单的东西,坑越多。

3.1 TWAP原理

TWAP的核心思想就一句话:让成交价格尽可能接近这段时间的平均价

它的数学表达很简单:

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

其中P1到Pn是每个时间点的价格。我们的目标,就是让实际成交价尽量贴近这个值。

具体怎么做呢?

  • 把交易时间分成N个等长的时间片
  • 每个时间片内,只交易总订单量的1/N
  • 时间片内再按市场流动性做微调

举个例子。假设我要在10分钟内买入100万股。我会这样做:

  1. 把10分钟分成10个1分钟的时间片
  2. 每个时间片只交易10万股
  3. 这10万股再根据盘口深度,拆成更小的单子

嗯,这里要注意。时间片怎么切,其实很有讲究。我见过有人用固定1秒一片,也有人用动态切片。我个人习惯用5-10秒一片,太短了容易暴露意图,太长了又跟不上行情变化。

3.2 TWAP实现

来,直接上代码。这是我实际项目中用过的简化版本:

class TWAPExecutor:
    def __init__(self, total_qty, start_time, end_time, slices=20):
        self.total_qty = total_qty          # 总交易量
        self.start_time = start_time        # 开始时间
        self.end_time = end_time            # 结束时间
        self.slices = slices                # 切片数
        self.qty_per_slice = total_qty / slices
        
    def generate_schedule(self):
        """生成交易时间表"""
        interval = (self.end_time - self.start_time) / self.slices
        schedule = []
        
        for i in range(self.slices):
            slice_time = self.start_time + interval * i
            schedule.append({
                'time': slice_time,
                'qty': self.qty_per_slice,
                'status': 'pending'
            })
        return schedule
    
    def execute_slice(self, slice_info):
        """执行单个时间片的交易"""
        # 这里根据盘口深度再拆分子单
        sub_orders = self._split_by_liquidity(
            slice_info['qty'], 
            self._get_order_book()
        )
        
        for sub in sub_orders:
            self._place_order(sub)
    
    def _split_by_liquidity(self, qty, order_book):
        """根据流动性拆分子单"""
        # 我习惯控制在盘口总量的5%以内
        max_per_order = order_book['bid_size'] * 0.05
        sub_qty = min(qty, max_per_order)
        return [{'qty': sub_qty}] * int(qty / sub_qty)

这段代码看起来简单,但实际跑起来问题不少。我曾经在实盘中发现,如果市场突然没流动性了,这个算法还在傻傻地往外扔单子,结果就是滑点大得吓人。

避坑指南: 我曾经因为没加流动性检查,在开盘瞬间把一个大单子扔出去,直接打穿了三个价位。后来我加了个保护逻辑:如果盘口深度低于阈值,就暂停交易,等流动性恢复再说。

3.3 TWAP优缺点

任何算法都有两面性。TWAP也不例外。

优点 缺点
实现简单,逻辑清晰 完全不考虑市场波动
执行成本可预测 遇到大行情容易吃亏
适合大单拆分 容易被对手盘识别
监管合规性好 无法捕捉有利时机

你想想看,TWAP最大的问题是什么?它太机械了。市场在涨,它还在卖;市场在跌,它还在买。说白了,它就是个没有感情的机器人。

我记得有一次做回测,用TWAP跑一个月的交易数据。结果发现,在趋势行情里,TWAP的表现远不如VWAP。为什么?因为TWAP不关心成交量分布,而趋势行情里成交量往往集中在某个时段。

核心要点: TWAP追求的是时间上的均匀分布,而不是成交量上的均匀分布。这是它和VWAP最本质的区别。

3.4 TWAP适用场景

那么,什么时候该用TWAP呢?我总结了几种情况:

  • 低波动市场: 市场波动小的时候,TWAP的机械性反而成了优势
  • 流动性充足: 大盘股、主流币种,随便拆都不会影响价格
  • 被动执行: 不追求alpha,只求完成交易
  • 测试阶段: 新策略上线前,用TWAP做基准测试

反过来,什么时候千万别用?

  • 重大新闻发布前后
  • 开盘和收盘的集合竞价阶段
  • 流动性极差的小盘股
  • 需要抢跑的高频策略

我个人习惯,在实盘前先用TWAP跑一周的模拟盘。不是为了赚钱,而是为了摸清市场的脾气。等摸透了,再上更复杂的算法。

小技巧: 如果你非要在波动大的时候用TWAP,可以加一个动态调整因子。比如,当价格偏离均线超过1%时,自动降低交易速度。这个改动虽然简单,但能有效减少滑点。

最后说一句。TWAP虽然简单,但它是所有拆分算法的基础。你把它吃透了,后面学VWAP、POV、Implementation Shortfall都会轻松很多。别小看它。

TWAP算法核心逻辑 输入:大单 + 时间窗口 均匀切片 N 份 逐片执行 子单拆分(按流动性) 输出:成交记录 反馈调整 图:TWAP算法执行流程

专注资料整理