4、锁单信号生成逻辑:基于价差的锁单信号、基于波动率的锁单信号、基于订单簿失衡的锁单信号、多因子信号融合

锁单信号,说白了就是决定「什么时候锁、什么时候解」的那道指令。信号质量直接决定了策略的生死。我见过太多人把信号搞得太复杂,结果延迟高得吓人,锁单反而成了亏损的源头。

今天我把四种主流信号生成逻辑拆开来讲。每种我都会结合实战中的坑来聊,希望能帮你少走弯路。

4.1 基于价差的锁单信号

这是最基础、也最直观的一种。核心逻辑很简单:当合约间的价差偏离正常范围时,触发锁单。

具体做法是这样的:

  • 计算主力合约与次主力合约的实时价差
  • 设定一个动态阈值(比如用过去N个Tick的价差均值±2倍标准差)
  • 当价差突破上轨,触发锁单(做空价差)
  • 当价差回归均值,解锁

我在项目中遇到过一个问题:直接用固定阈值,结果行情波动一变大,信号频繁触发,手续费都亏没了。后来我改用自适应阈值,效果好了很多。

核心要点:价差信号的关键在于阈值的选择。太窄容易误触发,太宽又抓不住机会。我个人习惯用滚动窗口的动态阈值,窗口大小根据品种流动性来调。

# 伪代码示例:基于价差的锁单信号
def generate_spread_signal(tick_data, window=100):
    spread = tick_data['ask1'] - tick_data['bid1']
    mean = rolling_mean(spread, window)
    std = rolling_std(spread, window)
    
    upper = mean + 2 * std
    lower = mean - 2 * std
    
    if spread > upper:
        return 'LOCK_SHORT'  # 锁空单
    elif spread < lower:
        return 'LOCK_LONG'   # 锁多单
    else:
        return 'UNLOCK'

4.2 基于波动率的锁单信号

波动率信号,说白了就是「市场太疯了,我先锁住再说」。这个逻辑在极端行情下特别有用。

我常用的波动率指标有两种:

  • 瞬时波动率:用过去N个Tick的价格变化率计算
  • 相对波动率:当前波动率与历史波动率的比值

嗯,这里要注意:波动率信号不能单独用,否则容易在震荡行情里反复锁单。我一般会加一个「波动率突变」的检测——只有当波动率在短时间内快速放大时,才触发锁单。

避坑指南:我曾经在螺纹钢上吃过亏。波动率信号太灵敏,结果一个乌龙指就把我锁住了,白白损失了手续费。后来我加了「连续确认」机制——连续两个Tick都满足条件才触发。

# 伪代码示例:基于波动率的锁单信号
def generate_volatility_signal(tick_data, lookback=20):
    returns = compute_returns(tick_data['price'], lookback)
    current_vol = np.std(returns[-5:])  # 短期波动率
    hist_vol = np.std(returns)          # 历史波动率
    
    vol_ratio = current_vol / hist_vol
    
    if vol_ratio > 3.0:  # 波动率放大3倍
        return 'LOCK'
    else:
        return 'UNLOCK'

4.3 基于订单簿失衡的锁单信号

这个信号,说白了就是看买卖双方的「力量对比」。订单簿失衡严重时,往往意味着价格即将快速变动。

我常用的指标:

  • 订单簿深度比:买一至买五的总量 / 卖一至卖五的总量
  • 订单簿斜率:不同档位的挂单量变化趋势
  • 订单簿压力指数:结合价格和挂单量的综合指标

你想想看,如果买一档挂了1000手,卖一档只有100手,这说明什么?说明买方在猛攻,价格大概率要往上走。这时候如果我的持仓方向相反,我就会考虑锁单。

注意:订单簿数据更新极快,信号计算必须高效。我建议用C++实现核心计算逻辑,Python只做信号聚合和决策。否则延迟会让你错过最佳锁单时机。

# 伪代码示例:基于订单簿失衡的锁单信号
def generate_orderbook_signal(orderbook):
    bid_volume = sum(orderbook['bids'][i]['volume'] for i in range(5))
    ask_volume = sum(orderbook['asks'][i]['volume'] for i in range(5))
    
    imbalance_ratio = bid_volume / ask_volume
    
    if imbalance_ratio > 2.0:  # 买方力量是卖方2倍
        return 'LOCK_LONG'
    elif imbalance_ratio < 0.5:  # 卖方力量是买方2倍
        return 'LOCK_SHORT'
    else:
        return 'UNLOCK'

4.4 多因子信号融合

单一信号都有缺陷。价差信号在趋势行情里容易失效,波动率信号在震荡行情里乱触发,订单簿信号又容易被大单欺骗。所以,我一般会把多个信号融合起来。

我常用的融合方式:

融合方法 原理 优缺点
加权投票 每个信号按权重投票,超过阈值则触发 简单,但权重难调
逻辑与/或 多个信号同时满足才触发(与),或任一满足即触发(或) 与模式信号少但可靠,或模式信号多但易误触
机器学习融合 用历史数据训练模型,自动学习信号组合 效果好,但计算开销大

我个人习惯用加权投票,因为它在效果和计算开销之间取得了平衡。权重我会用历史回测数据来优化,而不是拍脑袋定。

实战经验:我在做股指期货时,把价差信号和订单簿信号做了「与」融合。价差偏离+订单簿失衡同时出现时,锁单的成功率从65%提升到了82%。代价是信号频率降低了40%,但整体收益反而更高了。

# 伪代码示例:多因子信号融合
def fuse_signals(spread_signal, vol_signal, orderbook_signal):
    # 加权投票
    score = 0
    if spread_signal == 'LOCK':
        score += 0.4
    if vol_signal == 'LOCK':
        score += 0.3
    if orderbook_signal == 'LOCK':
        score += 0.3
    
    if score >= 0.7:  # 总分超过0.7才触发
        return 'LOCK'
    else:
        return 'UNLOCK'

4.5 信号生成的整体流程

最后,我画了一张图来展示整个信号生成流程。你看完应该就清楚了。

锁单信号生成流程图 Tick数据 / 订单簿数据 价差信号计算 波动率信号计算 订单簿信号计算 价差信号 (LOCK/UNLOCK) 波动率信号 (LOCK/UNLOCK) 订单簿信号 (LOCK/UNLOCK) 多因子信号融合(加权投票) 最终锁单信号

从图上你能看到,三个信号并行计算,最后汇聚到融合模块。这样做的好处是:每个信号的计算互不干扰,可以用多线程并行处理,延迟更低。

我的建议:刚开始做的时候,别急着上多因子融合。先把单个信号调好,再慢慢加。我见过太多人一上来就搞复杂模型,结果出了问题都不知道是哪个信号导致的。

好了,锁单信号生成逻辑就讲到这里。每种信号都有它的适用场景,关键是要理解背后的原理,然后根据你的策略特点来选。下一节我们会聊信号生成后的执行环节,那又是另一门学问了。


专注资料整理