4. 延迟与执行策略:滑点的隐形推手

做配对交易这么多年,我踩过最大的坑,就是低估了「延迟」的威力。

你想想看,信号算得再准,如果执行的时候慢了半拍,利润可能就全没了。说白了,延迟就是你的交易指令从大脑传到手脚的时间差。这个时间差里,市场可能已经变天了。

4.1 延迟的来源:到底慢在哪?

延迟不是单一的问题,它是一连串环节的累加。我个人习惯把延迟拆成三块来看:

  • 网络延迟:你的电脑到交易所服务器,物理距离决定了光速上限。我在国内做A股时,服务器放上海和放深圳,延迟能差5-10毫秒。别小看这几毫秒,高频场景下就是天堂和地狱。
  • 交易所撮合延迟:交易所的撮合引擎处理订单需要时间。行情越火爆,排队越长。我记得有一次股指期货秒级波动,我的限价单在队列里等了整整200毫秒才成交,价差已经跑了两个tick。
  • API调用延迟:你用的交易接口,不管是CTP、FIX还是REST,每次请求都有开销。REST API尤其慢,一次请求可能几十到几百毫秒。我曾经用REST做高频配对,结果发现大部分时间都花在了HTTP握手和序列化上。

核心结论:延迟是累加的。网络10ms + 撮合50ms + API 30ms = 90ms。这90ms里,价差可能已经偏离你的入场点好几个bp了。

4.2 延迟对配对交易信号衰减的影响

配对交易的核心是「价差回归」。你算出价差偏离了均值,准备开仓。但信号从生成到执行,中间有延迟。

为什么会衰减?因为价差是动态的。你看到价差偏离2个标准差时下单,等订单到达交易所,价差可能已经回归了1个标准差。你实际成交的价差,远不如信号指示的那么有利。

我在项目中遇到过这样的情况:一个统计套利策略,理论夏普比2.5,实盘跑下来只有1.2。查了半天,发现是延迟导致信号衰减了40%以上。后来加了延迟模拟回测,才把预期调准。

我的建议:回测时一定要加入延迟模型。最简单的做法是,在信号生成时间戳上加上一个随机延迟(比如50-200ms),再判断成交价。你会发现,很多看起来漂亮的策略,加了延迟就原形毕露了。

4.3 TWAP(时间加权平均价格)策略

TWAP,说白了就是把一个大单拆成很多小单,按时间均匀地扔出去。目标是让成交价接近这段时间的平均价。

适用场景:你不想影响市场,只想低调地完成交易。比如你每天要调仓1000手,用TWAP拆成每5分钟20手,市场几乎感觉不到你的存在。

代码实现其实不复杂:

def twap_executor(total_quantity, total_seconds, interval_seconds):
    """
    TWAP执行器
    :param total_quantity: 总交易量
    :param total_seconds: 总执行时间(秒)
    :param interval_seconds: 每次下单间隔(秒)
    """
    num_slices = total_seconds // interval_seconds
    slice_qty = total_quantity // num_slices
    remaining = total_quantity % num_slices
    
    orders = []
    for i in range(num_slices):
        qty = slice_qty + (1 if i < remaining else 0)
        orders.append({
            'time': i * interval_seconds,
            'quantity': qty
        })
    return orders

# 示例:1000手,10分钟,每30秒一次
orders = twap_executor(1000, 600, 30)
print(f"共{len(orders)}笔订单,每笔约{orders[0]['quantity']}手")

注意:TWAP有个致命弱点——它不关心成交量。如果市场流动性枯竭,你的小单也可能砸出大坑。我曾经在下午收盘前用TWAP,结果最后几分钟流动性骤降,滑点比一次性下单还大。

4.4 VWAP(成交量加权平均价格)策略

VWAP比TWAP聪明一点。它根据历史成交量分布来分配订单。流动性好的时段多下点,流动性差的时段少下点。

你想想看,开盘和收盘通常成交量最大,中午最清淡。VWAP会把更多订单放在活跃时段,这样你的成交价更接近市场真实均价。

实现思路:先获取历史成交量分布,然后按比例分配:

def vwap_executor(total_quantity, volume_profile):
    """
    VWAP执行器
    :param total_quantity: 总交易量
    :param volume_profile: 列表,每个时间段的成交量占比(总和为1)
    """
    orders = []
    for i, vol_ratio in enumerate(volume_profile):
        qty = int(total_quantity * vol_ratio)
        if qty > 0:
            orders.append({
                'time_slot': i,
                'quantity': qty,
                'weight': vol_ratio
            })
    return orders

# 示例:假设一天分13个半小时时段,成交量占比已知
volume_profile = [0.12, 0.10, 0.09, 0.08, 0.07, 0.06, 0.05, 
                  0.06, 0.07, 0.08, 0.09, 0.10, 0.03]
orders = vwap_executor(10000, volume_profile)
print(f"最大单笔:{max(o['quantity'] for o in orders)}手")

实战经验:我个人更偏爱VWAP。TWAP太机械,容易在流动性枯竭时吃亏。VWAP至少尊重市场规律。但要注意,历史成交量分布不一定代表未来。遇到突发新闻,成交量分布会完全变形。这时候我会手动暂停算法,等市场稳定再说。

4.5 延迟与执行策略的关系图

下面这张图,是我自己梳理的延迟影响链路。你看一眼就明白了:

延迟与执行策略关系图 信号生成 价差偏离2σ 延迟来源 网络 + 撮合 + API 信号衰减 实际价差缩小 传递 导致 TWAP策略 时间均匀分配 VWAP策略 成交量加权分配 选择 选择 降低滑点 · 控制成本

从图里你能看到,信号生成后,经过延迟,信号已经衰减了。这时候再用TWAP或VWAP去执行,其实是在跟时间赛跑。选对策略,能帮你把衰减的损失补回来一部分。

一个小技巧:如果你做的是日内配对,建议用VWAP。如果是隔夜持仓,TWAP就够了。为什么?因为日内成交量分布不均匀,VWAP能帮你避开流动性陷阱。隔夜的话,时间跨度长,均匀分配反而更稳定。

嗯,关于延迟和执行策略,今天就聊这么多。记住一句话:信号是理论,执行是现实。延迟就是横在两者之间的那道坎。跨过去,你的策略才算真正落地。


公众号:蓝海资料掘金营,微信deep3321