← 返回文章列表 执行

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)才是真正进入策略收益的那个数。

下一篇把这套执行逻辑接到模拟盘上,跑通从信号到委托的完整链路。

执行算法滑点微观结构
下一篇

动量因子的三种构造方式,哪一种在 A 股还有效