第四章:时间加权平均价格算法(TWAP)
TWAP,全称 Time-Weighted Average Price。说白了,就是把一个大订单,拆成很多小单,然后均匀地扔到市场里去。目标是让最终的成交均价,尽量贴近这段时间的市场平均价。
我刚开始做量化交易那会儿,觉得这玩意儿太简单了。不就是定时定量发单吗?后来在实盘中被市场狠狠教育了几次,才发现事情没那么简单。嗯,咱们今天就把 TWAP 彻底聊透。
4.1 核心原理:时间切片
TWAP 的核心思想,我总结成一句话:把时间切成片,每片吃一口。
假设你要在 10 分钟内买入 100 万股。TWAP 的做法是:
- 把 10 分钟切成 10 个 1 分钟的切片
- 每个切片只发 10 万股的订单
- 每个切片内,再随机或均匀地发单
你想想看,这样做的好处是什么?
你的交易行为不会在某个时间点集中爆发。市场不会因为你的一笔大单而剧烈波动。说白了,就是「化整为零,暗度陈仓」。
核心公式:
TWAP 目标价 = (P₁ + P₂ + ... + Pₙ) / N
其中 Pᵢ 是每个时间点的市场价格,N 是时间点总数。
我们的目标,就是让实际成交均价 ≈ 这个理论值。
4.2 数学模型:从理论到代码
TWAP 的数学模型其实不复杂。我习惯把它拆成两层:
第一层:时间分配模型
总时间 T,分成 N 个等长切片。每个切片分配的交易量是 Q/N。
这里有个坑:如果市场在某个切片内流动性极差,你硬发 Q/N 的量,可能会把价格打飞。我在项目中遇到过这种情况,后来加了个「流动性自适应」的模块。
第二层:切片内执行模型
每个切片内,再拆成 M 个子单。子单的发送时机可以随机化,避免被对手盘识别。
// 一个简单的 TWAP 拆单逻辑(伪代码)
function twapSlicer(totalQty, totalTime, sliceCount) {
let sliceQty = totalQty / sliceCount;
let sliceInterval = totalTime / sliceCount;
let orders = [];
for (let i = 0; i < sliceCount; i++) {
// 每个切片内,再随机拆成 3-5 个子单
let subCount = 3 + Math.floor(Math.random() * 3);
let subQty = sliceQty / subCount;
for (let j = 0; j < subCount; j++) {
// 子单发送时间:在切片内随机偏移
let offset = (Math.random() * 0.8 + 0.1) * sliceInterval;
let sendTime = i * sliceInterval + offset;
orders.push({
time: sendTime,
qty: subQty,
price: 'market' // 或者用限价单
});
}
}
// 按时间排序
return orders.sort((a, b) => a.time - b.time);
}
我的经验:切片数量 N 不是越大越好。N 太大,每单量太小,手续费占比会飙升。我一般建议 N 取 10-20 之间,具体看总交易时长。
4.3 适用场景:什么时候用 TWAP?
TWAP 不是万能的。我把它适用的场景总结成三个:
- 大单拆小单:单笔订单超过市场日均成交量的 1% 时,必须拆。TWAP 是最基础的拆法。
- 低波动市场:如果市场波动剧烈,TWAP 的效果会打折扣。因为价格在切片之间可能已经大幅变动了。
- 被动执行:你不急于成交,愿意花时间慢慢吃单。比如做市商的库存调整,或者 ETF 申赎的底仓构建。
我记得有一次帮一个私募做 ETF 套利策略。他们每天收盘前要调整 5000 万的底仓。用 TWAP 在最后 30 分钟慢慢吃,冲击成本从原来的 0.3% 降到了 0.05%。这就是典型的适用场景。
4.4 优缺点分析:别被表面迷惑
| 优点 | 缺点 |
|---|---|
| 实现简单,逻辑清晰 | 对市场波动不敏感 |
| 冲击成本可控 | 无法利用价格优势 |
| 容易被风控接受 | 在趋势行情中表现差 |
| 适合低流动性品种 | 执行时间较长 |
这里我要重点说一下缺点。TWAP 最大的问题是什么?是它「无脑」。它不管市场是涨是跌,只管按时间发单。
我曾经在 2020 年 3 月那波暴跌中,用 TWAP 执行一个卖出订单。结果呢?市场在 10 分钟内跌了 3%,我的 TWAP 还在傻傻地卖。最后成交均价比开盘价低了 1.5%。
避坑指南:如果你发现市场正在朝不利方向快速运动,立刻暂停 TWAP。我曾经吃过这个亏,后来在系统里加了个「紧急暂停」按钮——当价格偏离超过 0.5% 时,自动停止发单。
4.5 核心逻辑流程图
下面这张图,是我自己画的一个 TWAP 执行流程。你看完应该能对整个逻辑有个直观认识。
4.6 实战中的几个关键点
最后,我分享几个实战中总结出来的要点:
- 时间区间选择:尽量避开开盘和收盘的「竞价时段」。那个时间段波动大,TWAP 容易跑偏。
- 随机化是必须的:如果你每次都在整点发单,对手盘一眼就能看穿你的策略。加个随机偏移,成本几乎为零,收益却很大。
- 监控偏差率:实时计算「实际成交均价 - 理论 TWAP 价」。如果偏差超过 0.1%,就要检查是不是市场出了问题。
- 结合限价单:纯市价单的 TWAP 冲击成本高。我习惯用「限价单 + 小幅追单」的方式,既能控制价格,又能保证成交。
TWAP 是所有拆单算法的基础。你把它吃透了,后面学 VWAP、POV、Implementation Shortfall 都会轻松很多。说白了,TWAP 就是那个「笨但可靠」的老实人——虽然不够聪明,但永远不会给你捅大篓子。