2. TWAP核心数学原理:时间加权平均价格公式推导、切片逻辑与执行周期设计

好,咱们直接进入正题。TWAP,全称 Time-Weighted Average Price,时间加权平均价格。名字听着挺唬人,其实核心思想特别朴素——就是把一个大订单,拆成很多小单,均匀地撒在交易时间段里。

为什么要这么做?说白了,就是为了不引起市场注意。你想想看,如果你一口气砸进去100万股,盘口瞬间就被你打穿好几个价位,滑点成本高得吓人。TWAP就是帮你「润物细无声」地把单子做完。

2.1 时间加权平均价格的数学本质

先看公式。TWAP的定义其实很简单:

TWAP = (P₁ + P₂ + ... + Pₙ) / N

其中 P₁ 到 Pₙ 是每个时间切片上的成交价格,N 是切片数量。注意,这里每个价格的权重是一样的——这就是「时间加权」的含义。每个时间点,权重相同。

我刚开始做量化的时候,经常把TWAP和VWAP搞混。VWAP是按成交量加权的,哪个时间点成交量大,那个价格权重就高。TWAP不管成交量,只看时间。这个区别很关键,后面讲实战的时候你会体会到。

核心要点: TWAP假设市场在每个时间切片上的流动性是均匀的。虽然现实不完美,但这个假设在大多数情况下够用。

2.2 切片逻辑:把时间切成几块?

好,公式看完了。接下来是实操问题:怎么切?

假设你需要在1小时内买入100万股。你打算切成10份,每份10万股,每6分钟发一个单子。这就是最朴素的切片逻辑。

但问题来了——切多少份合适?

我个人习惯,切片数量取决于三个因素:

  1. 订单规模:订单越大,切片越多。我做过一个极端案例,单笔订单占日成交量的5%以上,我切了200多片。
  2. 市场流动性:流动性好的股票,切片可以少一些。流动性差的,必须多切,不然一单下去价格就飞了。
  3. 执行时间窗口:时间越短,切片越少。时间充裕,可以切得细一些。

这里有个经验公式,我用了好几年:

切片数量 = min( max( 订单量 / 预期每片成交量, 10 ), 200 )

预期每片成交量,我一般取过去5分钟平均成交量的1/10。这样既能保证每单不会太大,又不会切得太碎导致延迟成本上升。

小技巧: 切片数量不是越多越好。切得太碎,每个单子太小,频繁发单会增加网络延迟和交易所的费率成本。我一般控制在20-50片之间。

2.3 执行周期设计:什么时候发单?

切片逻辑搞定了,接下来是执行周期。说白了,就是每个切片之间的时间间隔怎么定。

最简单的做法:均匀分布。比如1小时切20片,每3分钟发一单。但这样做有个问题——如果市场在某个时间点突然波动很大,你的单子刚好撞在枪口上。

我建议的做法是:引入随机偏移

具体来说,每个切片的时间点不是固定的,而是在基准时间点附近加一个随机偏移量。比如基准是每3分钟发一单,实际发单时间可以是 2分50秒、3分05秒、2分55秒……这样随机化。

为什么要这么做?

嗯,这里要注意。如果你每次都在整点发单,其他算法交易者很容易识别出你的模式。他们可能会在你前面抢跑,导致你的成交价格变差。随机化之后,你的交易模式就难以预测了。

我曾经在实盘中吃过这个亏。一开始用固定间隔,结果被一个做市商盯上了,每次我发单前价格就往上跳一跳。后来改成随机偏移,情况立刻好转。

2.4 核心逻辑流程图

下面这张图,是我自己总结的TWAP执行流程。你看一遍,基本就明白整个链条了。

TWAP执行核心流程 输入参数 订单量 | 时间窗口 | 股票代码 计算切片数量 min(max(订单量/预期成交量, 10), 200) 生成时间表 均匀分布 + 随机偏移 循环执行切片 按时间表逐片发单 执行完成 汇总成交记录 关键参数说明 📌 切片数量:20-50片 📌 时间偏移:±5秒 📌 每片比例:均匀分配 📌 风控检查:每片执行后 📌 异常处理:超时重试 ⚠️ 常见陷阱 • 切片太少 → 冲击成本高 • 切片太多 → 延迟成本高 • 固定间隔 → 易被识别 • 忽略流动性 → 执行偏差大

2.5 执行偏差与修正机制

理论讲完了,咱们聊聊现实。TWAP在实际执行中,一定会出现偏差。原因很简单——市场不是均匀的。

偏差主要来自两个方面:

  • 时间偏差:你的单子发出去,可能因为网络延迟、交易所排队等原因,没有在预定时间成交。
  • 价格偏差:你发单时的市场价格,和切片基准价格之间可能有差距。

怎么处理?我一般用动态调整

具体做法是:每执行完一个切片,就计算一下当前的实际成交均价和理论TWAP之间的差距。如果偏差超过阈值(比如0.1%),就在下一个切片中微调订单量,把偏差拉回来。

注意: 动态调整不能太激进。我曾经在回测中试过「完全纠偏」策略——偏差多少,下一个切片就补多少。结果导致切片之间订单量忽大忽小,反而增加了冲击成本。建议每次只修正偏差的50%-70%。

2.6 一个简单的代码示例

最后,给一个Python伪代码。你拿去改改就能用。

def twap_executor(symbol, total_quantity, time_window_sec, num_slices):
    """
    TWAP执行器
    :param symbol: 股票代码
    :param total_quantity: 总订单量
    :param time_window_sec: 执行时间窗口(秒)
    :param num_slices: 切片数量
    """
    slice_qty = total_quantity / num_slices
    interval = time_window_sec / num_slices
    
    executed_qty = 0
    total_cost = 0
    
    for i in range(num_slices):
        # 生成随机偏移(±10%的间隔时间)
        offset = random.uniform(-interval * 0.1, interval * 0.1)
        sleep_time = interval + offset
        
        # 等待到预定时间
        time.sleep(sleep_time)
        
        # 发单(这里用市价单示例)
        order = market_order(symbol, slice_qty)
        
        # 记录成交
        executed_qty += order.filled_qty
        total_cost += order.filled_qty * order.avg_price
        
        # 动态调整:如果偏差过大,修正下一片
        actual_avg = total_cost / executed_qty
        theoretical_avg = get_current_market_price(symbol)
        deviation = abs(actual_avg - theoretical_avg) / theoretical_avg
        
        if deviation > 0.001:  # 偏差超过0.1%
            # 修正下一片的订单量
            slice_qty *= (1 + (theoretical_avg - actual_avg) / theoretical_avg * 0.6)
    
    return executed_qty, total_cost / executed_qty

这段代码我简化了很多,但核心逻辑都在里面了。你实际用的时候,记得加上风控、日志、异常处理这些东西。

个人经验: 代码里的修正系数0.6,是我跑了上百次回测调出来的。不同市场、不同股票,这个系数可能不一样。建议你先用历史数据跑一遍,找到最适合的参数。

好了,TWAP的核心数学原理和切片逻辑就讲到这里。说白了,就是「均匀拆分 + 随机执行 + 动态修正」这三板斧。你把这个框架搭好了,剩下的就是根据具体场景调参数。

专注资料整理