← 返回文章列表
July 15, 2026
5 分钟阅读

TWAP、VWAP与POV对比:如何选择执行基准(以及何时它们会对你撒谎)

TWAP、VWAP与POV对比:如何选择执行基准(以及何时它们会对你撒谎)
#execution
#twap
#vwap
#pov
#implementation-shortfall
#volume-curve
#algotrading
#backtest

每一种执行调度算法,本质上都是在对成交量预测下注。TWAP押注的是流动性在时间上是均匀分布的。VWAP押注的是今天的成交量曲线会和昨天相似。POV押注的是此刻盘口上正在打印的成交量,就是现在交易的好理由——而这其中还包括你自己制造的那部分成交量。这些"押注"在厂商文档里从来不会被标注为"押注",这也是为什么大多数关于三者的对比文章读起来像功能对照表:TWAP"简单",VWAP"智能",POV"自适应"。这种表述方式完全没有告诉你,哪种算法会让你亏钱、什么时候亏、亏多少。

这是我们在《算法交易中的订单类型》一文中开启的系列的第二篇,那篇文章里我们用大约各40行Python代码搭建了玩具版的TWAP和VWAP执行器。作为管道基础设施,那些执行器已经够用了。而这篇文章要讲的,是那套管道背后隐藏的一切:隐含假设、基准之争,以及一个在回放订单簿数据上可复现的正面对比实验——它会告诉你,这三种算法不是"不同风味"的选择,而是拥有不同风险特征和不同失效模式的策略。

三种调度算法,三种隐藏的赌注

先定义符号。一笔规模为 XX 的母单必须在时间区间 [0,T][0, T] 内执行完毕,拆分为 NN 个区间。设 xix_i 为区间 ii 中的子单数量,viv_i 为区间 ii 的市场成交量,pip_i 为区间 ii 的均价。整个执行区间上的市场VWAP为

VWAP=ipiviivi.\mathrm{VWAP} = \frac{\sum_i p_i v_i}{\sum_i v_i}.

TWAP 交易 xi=X/Nx_i = X/N:在相等的时间内交易相等的数量。其隐含假设是流动性——深度、价差、成交量——在时间上是均匀的,因此等量的切片会产生相等的冲击成本。这个假设在现存的任何一个市场中都不成立,但它的失效方式是"优雅的":调度是确定性的,完成度由构造本身保证,最坏情况不过是把固定的一笔单交易进了一个清淡的时段,多付一些更宽的价差而已。第二个较少被讨论的假设是:没有人在盯着你。如果一个TWAP每隔60秒在整点准时打出一笔子单,它就是一个节拍器,而节拍器是会被抢跑的。任何靠谱的TWAP都会对子单的时间和数量做随机化处理;调度应该是一个期望值平坦的类泊松过程,而不是一个时钟。

VWAP 交易 xi=Xuix_i = X \cdot u_i,其中 uiu_i 是对区间 ii 占全天成交量比例的预测值,且 iui=1\sum_i u_i = 1。这里的赌注就变得明确了:你手握一条根据历史数据估计出的曲线 {ui}\{u_i\},并假设今天会遵循这条曲线。这里的假设不是成交量是平坦的,而是它是可预测且外生的——曲线不关心你是否在交易。当预测准确时,VWAP会把你的交易集中在市场能够吸收的地方,你相对于市场VWAP的滑点几乎必然很小。当预测不准时——比如一次未预定的新闻事件把当天40%的成交量挤进了曲线里只分配了6%权重的那个小时——VWAP依旧不动声色地按照过时的计划交易,差价则由你来买单。VWAP把执行风险转化为了成交量预测风险。这就是全部的权衡所在,也正是为什么VWAP引擎里真正有趣的工程工作是预测器,而不是切单器。

POV(成交量占比,也叫"参与率")放弃了预测:以观测到的每个区间成交量的固定比例 γ\gamma 来交易,即 xt=γVtx_t = \gamma \cdot V_t。这看起来似乎胜过VWAP——既然可以直接跟随成交量,何必去预测它?问题在于,这个信号现在是内生的。你自己的成交也会打印在盘口上。如果市场其余部分在某区间内成交了 MM,而你的目标是占总盘口成交量的 γ\gamma,那么你的数量需要满足 x=γ(M+x)x = \gamma(M + x),即

x=γ1γM.x = \frac{\gamma}{1-\gamma}\,M.

γ=0.10\gamma = 0.10 时,这个修正是温和的(相当于其他人成交量的11.1%)。在 γ=0.25\gamma = 0.25 时,你已经在交易其他所有人流量的33%;在 γ=0.5\gamma = 0.5 时,你已经和市场其余部分的规模一一对等,不动点直接发散。POV还放弃了TWAP和VWAP都提供的一项保证:没有完成时限。如果成交量枯竭,你的调度也就跟着枯竭了。我们下面会回到POV的病态问题,因为这些问题值得单独成节讨论。

还有一点将在后面变得重要:这三者在任何形式化意义上都不是"最优"的。真正能够最小化成本—风险目标函数的调度算法是Almgren–Chriss族算法(Almgren and Chriss, 2000, "Optimal Execution of Portfolio Transactions," Journal of Risk 3, 5–39),我们在《Almgren–Chriss与最优执行调度理论》中对其进行了系统处理。TWAP是Almgren–Chriss模型在线性冲击下、风险厌恶为零时的特例;VWAP是相对于成交量加权基准的最小跟踪误差策略(Konishi, 2002, "Optimal slice of a VWAP trade," Journal of Financial Markets 5(2));POV则是一种不对应任何目标函数的启发式方法,这正是它的失效模式如此古怪的根本原因。

在一个永不收盘的市场里估计成交量曲线

股票市场的文献处理起来相对轻松。股票日内成交量呈U型——开盘时段成交活跃,午间清淡,收盘前又转向活跃——这一现象自Jain and Joh(1988,"The Dependence between Hourly Prices and Trading Volume," JFQA 23(3))以来就有文献记载,Admati and Pfleiderer(1988,"A Theory of Intraday Patterns: Volume and Price Variability," Review of Financial Studies 1(1))则为其提供了理论基础,指出自由裁量型流动性交易者和知情交易者会在时间上内生地聚集。这个U型曲线由两个硬性事件——开盘集合竞价和收盘集合竞价——所锚定,因此曲线是稳定的,用20天滚动平均的区间成交量占比就能覆盖90%的情况。

加密货币市场没有开盘也没有收盘,天真的想法是成交量应该是平坦的,TWAP应该约等于VWAP。这种天真的想法是错的。加密货币的日内成交量是有结构的——只是锚定在不同的时钟上:

时段效应。 成交量跟随交易者和交易台的作息时间波动。在BTC和ETH等主流币上,成交最活跃的时段是美国下午与欧洲晚间重叠的时段(大致为UTC 13:00—21:00),亚洲时段(UTC 00:00—08:00)则形成一个次高的成交量台阶,而主流币在UTC 04:00—06:00左右往往会出现明显的低谷。区域持仓集中度较高的山寨币对,其成交量会更强烈地偏向本地时段。

资金费率结算时间点。 永续合约在固定的UTC时间点结算资金费率——历史上每8小时一次,分别为UTC 00:00、08:00、16:00,而自2025—2026年起,币安等交易所已经把许多合约的结算周期缩短到4小时甚至1小时。结算时间点前后的几分钟里,成交量会稳定地出现放大:基差交易者会在此时开平仓,任何想要操纵资金费率快照的人也会恰好在这个边界时点交易。这些是尖峰而不是台阶——用30分钟为一个桶的曲线能够捕捉到它们;而用2小时为一个桶的曲线会把它们平均掉,导致你的VWAP恰恰在流动性最好的时候参与不足。

周度季节性。 主流币在周末的成交量结构性地低于工作日,而UTC周日晚间(对应亚洲周一早晨,再加上CME BTC期货的重新开盘)有其自己的特征。把所有天数汇总成一条单一的时间曲线是设定错误的;你需要的是一个"星期几 × 一天中的时刻"的二维网格。

预定事件。 Deribit期权在UTC 08:00到期(每周五,季度到期时会形成更大的成交集群),美国宏观数据在UTC 12:30/14:00公布,CME结算也会影响基差流量。这些是日历特征,而不是季节性——应该用哑变量来处理,而不是污染基线曲线。

一个可用的估计器,本着让预测器在变聪明之前先保持诚实的精神:

import pandas as pd

def volume_curve(trades: pd.DataFrame, bucket="30min") -> pd.Series:
    """day-of-week x time-of-day volume shares from a trades tape."""
    v = trades["qty"].resample(bucket).sum()
    day_total = v.groupby(v.index.date).transform("sum")
    share = v / day_total                      # fraction of that day's volume
    key = [v.index.dayofweek, v.index.time]
    curve = share.groupby(key).median()
    return curve / curve.groupby(level=0).transform("sum")  # renormalize per day

用中位数而不是均值,这不是风格上的选择。加密货币的成交量具有极强的重尾特性;一次连环爆仓可能在10分钟内占到全天成交量的15%,如果用基于均值的曲线,它会从此永远预期那个时段会出现一次尖峰。股票文献比静态曲线走得更远:Białkowski、Darolles and Le Fol(2008,"Improving VWAP strategies: A dynamic volume approach," Journal of Banking & Finance 32(9), 1709–1722)把区间成交量分解为一个共同的市场成分和一个用ARMA/SETAR动态建模的个股特有成分,并证明这种分解相比静态经典曲线能显著降低VWAP的跟踪风险。这种方法迁移到加密货币市场是直接可行的:从头部N个交易对中估计出一条全市场共同曲线(共同因子很强——资金费率结算时钟和交易时段是共享的),然后把你所交易的这个交易对相对该曲线的偏离建模为一个你实时更新的均值回归日内过程。更近期地,Genet(2025,"Deep Learning for VWAP Execution in Crypto Markets: Beyond the Volume Curve," arXiv:2502.13722)证明,端到端学习的调度在币安数据上的表现优于基于静态曲线的VWAP——这说明在加密货币市场中,成交量曲线才是整条流水线中最薄弱的一环,而不是切单逻辑本身。

操作上的结论是:一条不分日期的静态曲线是一个稻草人版的VWAP。如果你的对比结果显示"VWAP在加密货币市场上仅仅勉强战胜TWAP",先检查一下这条VWAP曲线是否真的包含了资金费率尖峰以及工作日/周末的区分,再下任何结论。

加密货币日内成交量热力图,显示资金费率尖峰与时段结构

POV的病态问题:追逐自己尾巴的算法

POV的卖点是自适应性:市场交易时就跟着交易。有三种截然不同的病态问题会削弱这一优势。

1. 反馈回路。 前文提到的内生性不仅仅是一个记账层面的修正。你的子单会创造成交量;成交量会抬高你的目标;你的目标又会创造更多成交量。在中等 γ\gamma 水平下,不动点 x=γ1γMx = \frac{\gamma}{1-\gamma}M 是稳定的,但你的交易后报告所显示的已测量参与率(占总盘口成交量的 γ\gamma)低估了你相对于"没有你参与时市场本会是什么样"的真实足迹(占其他所有人成交量的 γ1γ\frac{\gamma}{1-\gamma})。更糟的是,还存在二阶反馈:你的成交推动了价格,价格变动吸引了动量型资金流并触发止损单,这些流量抬高了盘口成交量,而你的POV引擎把自己造成的这部分成交量读作了加速交易的邀请。这与最优行为恰好相反——具有冲击感知能力的调度算法(参数合理的Almgren–Chriss模型,以及Almgren、Thum、Hauptmann and Li(2005,"Direct Estimation of Equity Market Impact," Risk 18(7))等实证冲击估计研究)会要求你在推高价格之后放慢速度,而不是加速。连环爆仓正是这种病态的极限情形:盘口成交量巨大、订单簿单边化,而一个普通的POV会在挤压行情的最高点买得最狠,因为那里正是成交打印最密集的地方。

2. 被人算计。 POV算法本质上是一台由成交量触发的订单流机器,而任何被触发的东西都可以被诱饵引诱。如果某个掠食者怀疑存在一个大额参与率买家,他可以主动制造成交量——在规则允许的地方自成交,或者只是用小规模主动交易——把POV引擎往前拉,然后再以更高的报价向它提供流动性。这是Brunnermeier and Pedersen(2005,"Predatory Trading," Journal of Finance 60(4))所描述的一般机制的一个小规模实例:当你未来的需求可以从你过去的行为中被预测出来时,其他人就会抢在你之前交易,你实际面对的价格路径会比你预测的更差。TWAP泄露的是一份时间上的计划;POV泄露的则是一个响应函数,这更加危险,因为对手可以随时按需触发它。

3. 永远收不了尾的尾部。 POV没有时钟。如果你必须在UTC 16:00之前买入500个BTC,而成交量在14:00蒸发了,纯粹的POV只能干等——按照设计,它天生无法自行完成任务。因此每一个生产环境中的POV都会带有一个最低速率下限和一个追赶模式,而追赶模式正是损失藏身之处:你可能整天都以10%的参与率被动交易,然后在收盘前一个清淡的窗口期,以三倍于目标参与率的有效速度,把剩余的30%母单硬生生打出去。交易后的平均值看起来还不错,但最后一批的边际成本却非常惨烈。如果你的POV报告没有单独拆分出这条尾部,你就还没有看到它的真实成本。

def pov_child_qty(tape_vol: float, gamma: float, remaining: float,
                  t_left_s: float, min_rate: float) -> float:
    target = gamma / (1.0 - gamma) * tape_vol   # exclude our own prints
    floor = remaining / max(t_left_s, 1.0) * CHILD_INTERVAL_S
    if t_left_s < CATCHUP_HORIZON_S:            # deadline dominates
        floor = max(floor, remaining * CHILD_INTERVAL_S / t_left_s)
    return min(remaining, max(target, floor, min_rate))

这段代码里有两个细节真正起作用:目标值使用的是剔除自己成交后盘口成交量的 γ1γ\frac{\gamma}{1-\gamma}(你必须从你所参照的盘口成交量中减去自己的成交——出人意料地,相当一部分实现并没有这样做),而截止期限下限会在时间耗尽时把POV转化为"在剩余量上执行TWAP",这样至少能让尾部成本变得可预测。

POV反馈回路:成交创造成交量,成交量又抬高目标

基准:为什么跑赢VWAP依然可能亏钱

调度算法和基准是两个相互独立的选择,把二者混为一谈是交易后分析中最常见的错误。目前有两种基准占主导地位。

VWAP基准——将你的平均成交价与区间VWAP作比较——由Berkowitz、Logue and Noser(1988,"The Total Cost of Transactions on the NYSE," Journal of Finance 43(1))提出,他们建议将当日成交量加权价格作为衡量机构执行质量的中性标尺。它成为行业默认标准的原因,社会性因素和技术性因素同样重要:它计算简单、易于解释,只要你把交易分散在全天,就很难在这个基准面前显得难看。

执行缺口(相对于到达价) 来自Perold(1988,"The Implementation Shortfall: Paper Versus Reality," Journal of Portfolio Management 14(3), 4–9):以决策发生那一刻的价格 p0p_0 为基准衡量一切。对于规模为 XX 的买单,已成交数量为 XfX_f,平均成交价为 pˉ\bar{p},终止价格为 pTp_T

IS=(pˉp0)Xf执行成本  +  (pTp0)(XXf)机会成本  +  手续费.\mathrm{IS} = \underbrace{(\bar{p} - p_0)\,X_f}_{\text{执行成本}} \;+\; \underbrace{(p_T - p_0)\,(X - X_f)}_{\text{机会成本}} \;+\; \text{手续费}.

Perold的核心观点是,纸面组合和真实组合之间的差距,恰恰就是这个量——注意它会对你未能成交的部分收取成本,而VWAP基准对此则悄无声息地忽略不计。正是这个机会成本项,让执行缺口成为衡量POV的唯一诚实基准,因为POV的标志性失效模式恰恰就是未成交的数量。

现在说说陷阱。作为基准,VWAP存在两个结构性盲区:

它是自我指涉的。 你的成交本身就在基准之内。如果你占了该区间成交量的30%,那么VWAP当中大约30%就是你自己的平均成交价,你相对于VWAP的已测量滑点会因你自身的参与而被机械性地压缩——你的订单规模越大、冲击越大,得分反而越好看。在极限情形下,如果你是唯一的交易者,那么无论你把价格推得多离谱,你相对VWAP的胜出幅度恰好都是零。VWAP滑点衡量的是调度的执行贴合度,而不是成本。

它忽略了相对于决策时刻的价格漂移。 举一个具体的例子:你决定以60,000美元的决策价买入100个BTC。市场整个下午都在上涨,区间VWAP报出60,320美元,而你的平均成交价是60,290美元。VWAP报告显示:–5个基点,跑赢基准,交易台拿到一个绿色的评分格。到达价报告则显示:你在100个BTC上比决策价多付了290美元——+48个基点,29,000美元的执行缺口。两个数字都是对的。但只有一个是真金白银。而这种激励扭曲还有更深一层:一个按VWAP考核的交易员在趋势上涨的一天里应该放慢交易速度(把交易分散开来更贴合基准),而这恰恰与最小化执行缺口所需要的行为相反——因为此时价格正在离你远去。这个基准不仅错误地度量了成本,它还在指导错误的行为。Kissell(2013,The Science of Algorithmic Trading and Portfolio Management, Academic Press)对这个基准选择问题有详尽的论述;他的表述值得内化:基准本质上编码了"你在为谁的风险负责"。VWAP管理的是执行交易台的难堪风险。到达价管理的才是投资组合的盈亏。

实践中的解决方案:以执行缺口为准来评估策略;将VWAP滑点用作诊断工具(它能把调度技巧从择时运气中分离出来,因为价格漂移对你和基准的影响是一样的);并且,任何订单占区间成交量超过10%的人,在引用VWAP滑点时都必须同时报出参与率。

实验:三种算法,一份行情带

定义已经明确,我们现在可以做那些对比文章从来不做的事情:在相同的回放数据上,对同一批母单运行三种调度算法,观察成本的分布,而不是形容词。测试框架运行在《成交模拟:部分成交、排队位置,以及为什么你的回测成交是假的》一文中描述的事件驱动成交模拟器之上——回放的L2深度数据,子单限价单需要争取排队位置,激进的子单会扫穿订单簿,而我们的成交会扰动调度算法所观测到的行情带(这一点对POV的影响尤其巨大,正如前面反馈回路一节所述)。

具体设置,方便你在自己的数据上复现:

  • 标的/数据: BTCUSDT永续合约,90天的L2回放数据(前20档,100毫秒粒度)+ 成交行情带。
  • 母单: 每种算法各500笔,跨算法完全一致:随机起始时间,执行区间 T=4T = 4 小时,规模为过去30天日均成交量(ADV)的0.75%(足够大以体现真实冲击,又足够小使三种算法都能大致完成),买方向,决策价 = 起始时刻的中间价。
  • TWAP: 48个子单切片,时间/数量各有±30%的抖动。
  • VWAP: 30分钟粒度的"星期几 × 一天中的时刻"中位数曲线(使用上文的估计器),每周重新拟合,不做日内实时更新——刻意选择简单版本。
  • POV: 目标为剔除自身成交后行情带成交量的 γ=12%\gamma = 12\%,设有最低速率下限,最后30分钟启动TWAP式追赶。
  • 指标: 以决策价的基点数表示的执行缺口(含手续费)、VWAP滑点(基点)、完成率,以及——没有人会去报告的一项——每笔母单最后四分之一部分的执行缺口。

我们运行结果的代表性数据(你的数字会有所不同,但形态不应该有本质差异):

指标(相对到达价的基点数) TWAP VWAP POV 12%
平均执行缺口 11.8 9.6 8.9
中位数执行缺口 9.1 7.7 6.4
执行缺口标准差 21.5 19.8 26.3
执行缺口95分位数 46 41 58
平均VWAP滑点 +1.9 +0.4 –0.8
T时刻完成率 100% 100% 96.4%
母单最后四分之一部分的平均执行缺口 12.5 10.2 19.7

按重要性递增排列,有三点解读:

均值美化了POV,而尾部则揭穿了它。 POV在平均和中位数执行缺口上都胜出——相对于静态曲线,根据实际流动性自适应调整确实能带来实实在在的几个基点优势。但它的执行缺口标准差和95分位数是三者中最差的,完成率也不是100%,而且它最后四分之一部分的成本是其整体均值的两倍还多:永远收不了尾的尾部加上追赶模式,恰好把成本集中在了均值所掩盖的地方。如果你的母单是由alpha驱动、有硬性时限的,那条尾部才是真正重要的数字,POV在均值上的优势根本无法弥补它。

VWAP相对TWAP的优势,恰恰就是它的预测质量本身。 把VWAP与TWAP的执行缺口差距,按照已实现成交量曲线误差(预测值 uiu_i 与实际占比之间的 L1L_1 距离)分组,可以看到一个单调的关系:在预测最准的三分之一天数中,VWAP领先TWAP约4个基点;在预测最差的三分之一天数中,差距处于噪声范围内,有时甚至反转。在加密货币市场中,预测最差的这三分之一并不是随机分布的——它们是爆仓日和新闻日,而这些恰恰也是整体成本最高的日子。VWAP之所以能提升平均表现,是因为它在原本就容易的日子里跑赢了。

VWAP滑点和执行缺口对算法的排名完全不同。 POV的平均VWAP滑点是的——这并不奇怪,因为它正是按照定义基准的那部分成交量的比例来交易的,它的成交本身就嵌在基准之内。按VWAP计分板,POV是这里表现最好的算法;按到达价计分板加上完成风险,它却是最危险的。同一份行情带、同一批成交,结论却截然相反——这正是上一节全部论点以表格形式的呈现。

TWAP、VWAP和POV的执行缺口分布

这个测试框架本身大约只有50行代码,围绕成交模拟器构建,但每一分钟的投入都值得,因为它把调度算法的选择从一场品味之争变成了一次测量:

for parent in sample_parents(n=500, horizon="4h", adv_frac=0.0075):
    for algo in (twap, vwap, pov):
        sim = ReplaySim(l2_stream(parent.window), fees=TAKER_MAKER)
        fills = sim.run(algo.schedule(parent))          # fills perturb the tape
        report(parent, algo, is_bps(fills, parent.p0),
               vwap_slip_bps(fills, sim.tape), fills.completion)

实践中如何选择

从以上所有分析中得出的诚实的选择原则:

  • 有硬性截止时限、由alpha驱动的母单: 使用TWAP,或者一个前置加权的Almgren–Chriss调度。付出流动性平坦这一假设所带来的成本,换取完成度保证和有界的尾部风险。对子单做随机化处理。
  • 由基准驱动的流量(你确实是按VWAP考核的),或者普通日子里的大额订单: 使用VWAP——并把你的工程预算投入到成交量预测器上:星期几网格、资金费率尖峰的精细化处理、以及像Białkowski–Darolles–Le Fol那样的日内动态更新。一个配备了偷懒曲线的VWAP引擎,不过是多绕了几道弯子的TWAP。
  • 机会主义、没有硬性截止时限、对流动性敏感: 使用适度 γ\gamma(≤15%)的POV,基于剔除自身成交后的成交量计算,配备一个连环爆仓过滤器(当行情带成交量的z分数爆表时限制参与率),以及一个成本被单独测量的截止期限兜底机制。
  • 无论运行哪种算法: 都应按照Perold的方法,以相对到达价的执行缺口来评分。把VWAP滑点保留作为调度技巧的诊断工具,但绝不能作为计分板——计分板必须以真金白银计价,而只有到达价才做到了这一点。

以及这个实验反复印证的元规则:在你自己的回放数据上比较分布,而不是均值。调度算法本质上是对成交量预测的一次押注,而你不应该只看平均回报而忽略尾部来评判一次押注——市场正是靠这种方式把POV卖给你的。

免责声明:本文提供的信息仅用于教育和参考目的,不构成财务、投资或交易建议。加密货币交易涉及重大损失风险。

Authors

Eugen Soloviov
Eugen Soloviov

Trading-systems engineer

Trading-systems engineer building bots since 2017: cross-exchange arbitrage (connected up to 30 venues), cointegration-based pairs arbitrage across spot and futures, scalping, news and sentiment-driven strategies, trend algorithms, and portfolio management and balancing algorithms. Also builds sub-millisecond order execution, big-data warehouses, backtesting engines, AI agents, and trading interfaces (incl. open-source profitmaker.cc). Stack: JS/TS, Python, Rust/Zig/Go, DevOps, backend, frontend, architecture.

Newsletter

紧跟市场步伐

订阅我们的时事通讯,获取独家 AI 交易见解、市场分析和平台更新。

我们尊重您的隐私。您可以随时退订。