16、订单拆分策略:TWAP、VWAP、Iceberg 订单、隐藏订单

做量化交易的朋友,迟早会撞上一个问题:

「我的大单子一挂出去,市场就跟我对着干。」

你买,价格就涨。你卖,价格就跌。好像市场里有一双眼睛,专门盯着你的订单。

其实不是市场针对你。是你的订单太大了,直接把盘口吃穿了。我早年做回测时,策略跑出来年化80%,一上实盘就亏钱。后来才发现,回测里我假设「想买就能买到」,但实盘里我的单子一进去,滑点就把利润吃光了。

所以,订单拆分策略就来了。说白了,就是把大象塞进冰箱,分几步走

核心思想:大单拆小单,降低市场冲击,隐藏交易意图。

16.1 TWAP:时间加权平均价格

TWAP,全称 Time-Weighted Average Price。名字挺唬人,其实逻辑很简单:把时间切成片,每片里扔一点单子进去

比如你想在1小时内买入10万股的BTC。TWAP的做法是:

  • 把1小时切成60个1分钟的切片
  • 每个切片里,下单 100000 / 60 ≈ 1667 股
  • 不管价格怎么变,到点就下单

我刚开始用TWAP时,觉得这玩意儿太机械了。后来发现,它最大的好处是可预测。你算好时间,算好量,执行偏差基本可控。

适用场景:市场流动性一般,你不想暴露意图,且对价格没有太强判断。比如做市商调仓、指数基金申赎。

代码实现也很直白:

def twap(total_qty, total_seconds, slice_seconds=60):
    slices = total_seconds // slice_seconds
    qty_per_slice = total_qty / slices
    for i in range(slices):
        # 每个切片执行一次下单
        place_order(qty=qty_per_slice)
        time.sleep(slice_seconds)

嗯,这里要注意:TWAP有个硬伤——它不看市场深度。如果某个切片里盘口很薄,你的单子照样会把价格打飞。我曾在ETH上吃过这个亏,盘口只有几百个ETH,我硬是塞了5000个进去,结果滑点直接吃掉了我当天的利润。

16.2 VWAP:成交量加权平均价格

VWAP,Volume-Weighted Average Price。比TWAP聪明一点:它跟着成交量走

逻辑是:市场成交量大的时候,我多下点;成交量小的时候,我少下点。这样我的订单就「融入」了市场正常的交易流里,不容易被发现。

具体做法:

  • 先拿到历史成交量分布(比如过去N天的分钟级成交量)
  • 算出每个时间片的成交量占比
  • 按这个占比分配你的订单量

举个例子:

时间片 历史成交量占比 分配订单量(总10万股)
09:30-09:31 5% 5000
09:31-09:32 8% 8000
09:32-09:33 3% 3000

我个人的习惯是,VWAP配合实时成交量做动态调整。比如某个时间片实际成交量比历史高,我就多下一点。这样更贴近真实市场。

避坑指南:VWAP依赖历史数据。如果今天市场结构变了(比如突发新闻),历史分布就失效了。我曾经在财报发布日用VWAP,结果前半小时成交量暴增,我的单子全砸在最高点……嗯,从那以后我学会了加一个「异常检测」逻辑。

16.3 Iceberg 订单:冰山订单

Iceberg,冰山订单。名字很形象:你只露出水面的一小部分,大部分藏在下面

比如你想卖10万个ETH。如果你直接挂一个卖10万的单子,盘口上所有人都能看到。做市商和量化基金立刻就会压价。但Iceberg订单会把你的10万拆成很多个小单,比如每次只显示1000个。吃掉一个,再露一个。

为什么叫冰山?因为盘口上只看到「冰山一角」。

实现逻辑:

def iceberg(total_qty, display_qty, price):
    remaining = total_qty
    while remaining > 0:
        current_qty = min(display_qty, remaining)
        place_limit_order(price=price, qty=current_qty)
        remaining -= current_qty
        # 等待当前显示的单子被吃掉
        wait_for_fill()

你想想看,Iceberg订单最大的好处是什么?隐藏真实意图。别人以为你只想买1000个,实际上你在悄悄吸筹。我见过一些做市商,用Iceberg订单在盘口上「钓鱼」,一边挂单一边撤单,把对手耍得团团转。

注意:Iceberg订单不是所有交易所都支持。有些交易所需要你自己在客户端实现「撤单-重挂」逻辑。而且频繁撤挂可能会被交易所判定为「滥用API」,小心被封。

16.4 隐藏订单:完全隐形

隐藏订单,也叫「暗单」。比Iceberg更进一步:盘口上完全看不到你的单子

只有当你这个价格上的所有可见单子都被吃掉后,你的隐藏单子才会被「激活」。换句话说,你的单子是「隐形」的,但它在订单簿里真实存在。

为什么要有隐藏订单?

  • 避免被狙击:你的大单不会吓跑对手
  • 降低冲击成本:你的单子不会让价格提前变动
  • 提高成交概率:当价格到达你的位置时,你排在所有可见单子后面,但比同价位的其他隐藏单子优先

我记得有一次,我在某个山寨币上挂了一个隐藏买单。盘口上所有人都以为买盘很弱,价格一路下跌。结果跌到我的隐藏价位时,我的单子瞬间把所有的卖单全吃了。那感觉,就像打牌时手里藏了一张王牌。

使用建议:隐藏订单适合「被动吃单」策略。如果你是想主动吃单(市价单),隐藏订单没用。它只对限价单有效。

16.5 四种策略对比

策略 核心逻辑 隐藏程度 市场冲击 适用场景
TWAP 按时间均匀分配 流动性一般,无价格判断
VWAP 按成交量分配 流动性好,跟随市场节奏
Iceberg 分批显示小单 大单被动挂单,隐藏意图
隐藏订单 完全不可见 极高 极低 被动吃单,避免被狙击

16.6 核心逻辑流程图

下面这张图,帮你理清四种策略的选择逻辑:

订单拆分策略选择逻辑 大单需要拆分 主动吃单 还是 被动挂单? 主动吃单 被动挂单 TWAP / VWAP 需要多隐藏? 部分隐藏 完全隐藏 极高隐藏 Iceberg 订单 隐藏订单 组合使用 核心原则: 降低冲击 + 隐藏意图 = 更好的执行价格

你看,选择哪种策略,核心就两个问题:你是主动吃还是被动挂?你想藏多深?

主动吃单,用TWAP或VWAP跟着市场节奏走。被动挂单,用Iceberg或隐藏订单把真实意图藏起来。如果条件允许,组合使用效果更好——比如用VWAP决定每个时间片下多少量,再用Iceberg把每个时间片里的单子拆成小单。

最后说一句:没有完美的策略。TWAP太死板,VWAP依赖历史数据,Iceberg容易被算法识别,隐藏订单成交优先级低。真正的高手,是根据市场状态动态切换。流动性好的时候用VWAP,流动性差的时候用Iceberg,遇到大行情时直接上隐藏订单。

嗯,这些经验,都是我用真金白银换来的。