第二十五节:实盘信号部署:信号延迟、交易成本、滑点处理
说实话,很多做高频的同学在回测里赚得盆满钵满,一上实盘就亏得怀疑人生。为什么?因为回测里那些完美的信号,到了真实市场里,会被三个东西狠狠教训一顿:信号延迟、交易成本、滑点。
我当年第一次部署实盘策略时,就栽在信号延迟上。回测里每次信号发出都能精准成交,结果实盘里信号到了,价格已经跑了几个tick。嗯,今天我们就来聊聊怎么处理这些“实盘杀手”。
信号延迟:你的信号到底晚了几毫秒?
信号延迟说白了,就是从行情数据到达,到你发出交易指令,中间那段时间。你想想看,在高频交易里,1毫秒的延迟可能就意味着几个tick的价差没了。
我个人习惯把信号延迟拆成三部分来看:
- 数据接收延迟:行情数据从交易所到你的服务器,网络传输需要时间
- 计算延迟:你的策略代码跑完所有逻辑,生成信号的时间
- 指令发送延迟:信号从你的系统发到交易所网关的时间
我在项目中遇到过最离谱的情况,是数据接收延迟占了总延迟的70%。后来发现是用了公共的行情数据源,而不是直接连交易所的行情网关。换掉之后,延迟直接降了一个数量级。
核心观点:信号延迟不是“有没有”的问题,而是“你能不能量化它”的问题。量化不了,你就没法优化。
如何测量信号延迟?
测量延迟其实不难,难的是精确测量。我常用的方法是“时间戳追踪法”:
# 伪代码示例:信号延迟追踪
def track_signal_latency():
# 记录行情到达时间
tick_received = time.time_ns()
# 策略计算
signal = strategy.calculate(tick_data)
# 记录信号生成时间
signal_generated = time.time_ns()
# 计算延迟
compute_latency = signal_generated - tick_received
# 记录到日志
log_latency(compute_latency)
return signal
这里要注意,time.time_ns() 的精度是纳秒级,但实际精度取决于操作系统和硬件。我建议至少用微秒级的时间戳,否则测出来的延迟误差比延迟本身还大。
小技巧:如果你用的是Linux系统,可以用 clock_gettime(CLOCK_MONOTONIC) 获取更稳定的时间戳。Windows下我一般用 QueryPerformanceCounter。
交易成本:你以为的利润,其实是成本
交易成本这东西,回测里往往被低估。我见过太多人回测时只算了手续费,结果实盘里被印花税、过户费、滑点成本吃掉了大部分利润。
交易成本主要包括:
| 成本类型 | 说明 | 典型值(A股) |
|---|---|---|
| 手续费 | 券商收取的交易佣金 | 万1.5 ~ 万3 |
| 印花税 | 卖出时收取 | 万5 |
| 过户费 | 买卖都收 | 万0.2 |
| 滑点成本 | 实际成交价与信号价的差异 | 1~3个tick |
你想想看,如果策略的预期收益是万5,光印花税和手续费就吃掉了一半。高频交易里,每笔赚得少,交易次数多,成本占比就更吓人了。
避坑指南:我曾经在回测里只算了万2的手续费,结果实盘发现券商收的是万3,加上印花税,每笔交易的实际成本比回测高了60%。那一个月白干了。
滑点处理:为什么你的成交价总比信号价差?
滑点,说白了就是你想买的时候,价格已经涨上去了;你想卖的时候,价格已经跌下来了。高频交易里,滑点是最难控制的变量。
我一般把滑点分成两类:
- 流动性滑点:订单簿深度不够,你的订单吃掉了最优价位的挂单,只能往下一个价位成交
- 竞争滑点:你的信号和别人的信号同时发出,别人比你快,抢走了更好的价格
处理滑点,我个人习惯用“保守估计法”:
# 滑点估算示例
def estimate_slippage(order_book, order_size):
"""
根据订单簿深度估算滑点
"""
# 获取当前最优买卖价
best_bid = order_book['bids'][0][0]
best_ask = order_book['asks'][0][0]
# 计算需要吃掉的深度
remaining = order_size
slippage = 0
# 如果是买单,从卖一价开始吃
for price, volume in order_book['asks']:
if remaining <= 0:
break
trade_volume = min(remaining, volume)
slippage += (price - best_ask) * trade_volume
remaining -= trade_volume
# 返回平均滑点(以tick为单位)
avg_slippage = slippage / order_size
return avg_slippage
这个代码虽然简单,但实盘里很实用。我一般会在策略里加上滑点预估,如果预估滑点超过某个阈值,就放弃这笔交易。
经验之谈:滑点不是固定的。市场波动大的时候,滑点可能是平时的3-5倍。我建议在策略里加入“动态滑点调整”,根据市场波动率实时调整滑点预估。
实盘部署的“三件套”
说了这么多,总结一下我实盘部署时的三个核心动作:
- 延迟监控:每个信号都打上时间戳,实时监控延迟分布。如果延迟突然变大,立刻报警
- 成本核算:每笔交易都记录实际成本,和回测对比。偏差超过20%就要查原因
- 滑点控制:设置滑点容忍度,超过阈值就撤单。宁可错过,不要做亏
这三个东西,我建议做成一个独立的监控模块,和策略代码分开部署。这样即使策略出问题,监控还能正常工作。
一个小建议:刚开始实盘时,先用小资金跑。我一般会用总资金的5%跑一个月,看看实际延迟、成本、滑点跟回测差多少。没问题了再加仓。
知识体系总览
下面这张图,是我对实盘信号部署核心逻辑的总结。你可以把它当成一个检查清单,部署前逐项确认。
这张图里,三个核心要素是并列关系,但实际部署时,我建议先搞定信号延迟,再处理交易成本,最后优化滑点。因为延迟是基础,延迟搞不定,后面两个优化了也没用。
最后提醒一句:实盘部署不是一锤子买卖。市场环境在变,你的策略在变,延迟、成本、滑点也在变。我每周都会跑一次延迟和成本的复盘,看看有没有异常。发现问题,立刻调整,不要等到亏钱了才想起来查。