TWAP 与 VWAP 之外:把执行拆成时间片和价格带
固定节奏的算法在流动性突变时最吃亏,加一层价格带条件能省下不少滑点。
固定节奏的代价
TWAP 把委托均匀切到每个时间片,VWAP 按历史成交量分布切。两者的共同假设是「今天的流动性分布和历史差不多」,这个假设在 90% 的交易日成立,在剩下 10% 里会让你在最差的价格上成交最多的量。
改进的方向不是换一个更复杂的曲线,而是给每个子单加一个价格条件:便宜的时候多买一点,贵的时候少买一点,但不完全停。
def child_qty(base, px, vwap_sofar, spread, beta=0.5, cap=2.0): """按价格偏离调整子单量 base : 按 VWAP 曲线算出的基准子单量 px : 当前中间价 vwap_sofar : 当日累计成交均价 spread : 当前买卖价差 beta : 价格敏感度,0 表示退化为纯 VWAP cap : 单片放大倍数上限 """ edge = (vwap_sofar - px) / max(spread, 1e-6) # 买单:价格低于均价为正 mult = 1.0 + beta * edge return base * min(max(mult, 1.0 / cap), cap)
为什么要设下限而不是允许归零
允许子单量降到 0,算法在单边上涨行情里会一整天不成交,最后被迫在收盘集合竞价上补完全部剩余量,滑点比老老实实按 VWAP 走还差。下限保证进度不失控。
进度追踪比价格更重要
任何带价格条件的算法都必须有一条进度约束:如果累计成交进度落后计划超过一定比例,价格条件就自动失效,回到纯 VWAP 模式补量。这条兜底规则的价值远大于价格模型本身的精度。
planned = vwap_curve.loc[:now].sum() * total_qty filled = fills['qty'].sum() lag = 1 - filled / max(planned, 1) if lag > 0.15: beta = 0.0 # 落后超过 15%,关闭价格择时 elif lag > 0.08: beta = 0.25 # 轻度落后,减半
怎么衡量执行好坏
不要用「成交价 vs 当日 VWAP」来评价,那只能说明你跑赢了一个基准,说明不了成本。正确的基准是决策价(信号产生那一刻的中间价),实现差额(implementation shortfall)才是真正进入策略收益的那个数。
下一篇把这套执行逻辑接到模拟盘上,跑通从信号到委托的完整链路。
执行算法滑点微观结构