23. 基差交易的量化因子库:动量因子、反转因子、波动率因子、流动性因子在基差中的表现

做基差交易这些年,我越来越觉得,因子就是你的眼睛。没有因子,你就是在黑箱里瞎摸。今天咱们把这四个核心因子——动量、反转、波动率、流动性——在基差里的表现,掰开揉碎了讲清楚。

核心观点:基差因子不是孤立存在的。它们之间会互相干扰,也会互相强化。我习惯把它们组合成一个「因子矩阵」来用,而不是单独看某一个。

23.1 动量因子:趋势是你的朋友,但别太晚下车

动量因子在基差交易里,说白了就是追涨杀跌。但这里的「涨跌」不是价格,而是基差本身的变化率。

我个人习惯用过去N期的基差变化率来构建动量信号。比如,过去5天基差持续走阔,我就认为动量向上,做多基差;反之做空。

# 动量因子计算示例
def momentum_factor(basis_series, window=5):
    """
    计算基差的动量因子
    basis_series: 基差时间序列
    window: 动量窗口
    """
    # 计算基差变化率
    basis_returns = basis_series.pct_change()
    # 滚动求和作为动量信号
    momentum = basis_returns.rolling(window).sum()
    return momentum

嗯,这里要注意:动量因子的窗口选择非常敏感。我在实盘里试过,短窗口(3-5天)容易产生假信号,长窗口(20天以上)又太滞后。我个人觉得,10天左右是个不错的平衡点

避坑指南:我曾经在螺纹钢的跨期套利上,用5天动量信号做多,结果连续被止损了3次。后来发现,那段时间市场在震荡,动量因子完全失效。所以,动量因子在趋势行情里好用,震荡行情里就是个坑。

23.2 反转因子:均值回归,但别跟趋势对着干

反转因子,就是赌基差会回到均值。你想想看,基差不可能无限扩大或缩小,总有回归的时候。但问题是——什么时候回归?

我常用的反转因子是基差偏离度

def reversal_factor(basis_series, window=20):
    """
    计算基差的偏离度(反转因子)
    """
    mean = basis_series.rolling(window).mean()
    std = basis_series.rolling(window).std()
    # Z-score 标准化
    z_score = (basis_series - mean) / std
    return z_score

当Z-score超过2或低于-2时,我就认为基差过度偏离,存在反转机会。但说实话,这个阈值不是固定的。不同品种、不同市场环境下,阈值差异很大。我习惯用动态阈值,比如根据历史分位数来定。

警告:反转因子最大的风险是「趋势延续」。如果市场出现了结构性变化(比如政策突变、交割规则调整),基差可能不会回归,反而越走越远。我吃过这个亏,2019年在铁矿石上,基差偏离了4个标准差还没回来,最后被迫止损。

23.3 波动率因子:高波动是机会,也是陷阱

波动率因子,衡量的是基差的不确定性。我个人觉得,波动率是基差交易的「放大器」——它不直接告诉你方向,但告诉你机会的大小和风险的高低。

我常用的波动率指标是历史波动率(HV)已实现波动率(RV)

def volatility_factor(basis_series, window=20):
    """
    计算基差的波动率因子
    """
    # 计算对数收益率
    log_returns = np.log(basis_series / basis_series.shift(1))
    # 滚动标准差(年化)
    volatility = log_returns.rolling(window).std() * np.sqrt(252)
    return volatility

为什么波动率重要?因为高波动环境下,基差更容易出现极端值,这给反转因子提供了机会。但同时,高波动也意味着止损需要设得更宽,否则容易被震出去。

我的经验:当波动率处于历史低位时,我倾向于使用动量因子;当波动率处于历史高位时,我倾向于使用反转因子。说白了,就是「低波动追趋势,高波动赌回归」。

23.4 流动性因子:没有流动性,一切都是空谈

流动性因子,可能是最容易被忽视的。你想想看,就算你识别出了完美的套利机会,但如果市场深度不够,你根本进不去,或者进去了出不来

我衡量流动性主要看三个指标:

指标 计算方法 在基差交易中的意义
买卖价差 ask - bid 价差越大,交易成本越高,侵蚀套利利润
市场深度 盘口前5档的总挂单量 深度不足时,大单会引发滑点
成交量 过去N分钟的累计成交量 成交量萎缩时,基差容易被操纵
def liquidity_factor(bid_ask_spread, depth, volume):
    """
    综合流动性评分
    """
    # 标准化处理
    spread_score = 1 / (1 + bid_ask_spread)
    depth_score = np.log1p(depth)
    volume_score = np.log1p(volume)
    # 加权综合
    liquidity_score = 0.3 * spread_score + 0.4 * depth_score + 0.3 * volume_score
    return liquidity_score

避坑指南:我曾经在临近交割日时,发现一个基差机会特别好,但没注意流动性。结果一进场,直接把基差打穿了,反而亏了钱。从那以后,我给自己定了个规矩:流动性评分低于0.6的品种,坚决不碰

23.5 因子组合:1+1>2 的艺术

单独看任何一个因子,都有局限性。我习惯把它们组合成一个多因子信号

def combined_signal(momentum, reversal, volatility, liquidity):
    """
    多因子组合信号
    """
    # 动量信号(-1到1)
    m_signal = np.clip(momentum, -1, 1)
    # 反转信号(-1到1)
    r_signal = np.clip(-reversal, -1, 1)  # 反转信号取反
    # 波动率调节(0到1)
    v_weight = 1 - np.clip(volatility / 0.5, 0, 1)  # 低波动时权重高
    # 流动性过滤
    l_filter = (liquidity > 0.6).astype(int)
    
    # 组合信号
    final_signal = (0.4 * m_signal + 0.3 * r_signal) * v_weight * l_filter
    return final_signal

这个组合的逻辑是:动量给方向,反转给边界,波动率调权重,流动性做过滤。说白了,就是让四个因子各司其职,互相制约。

重要提醒:因子组合不是一成不变的。不同品种、不同市场环境下,因子的权重需要动态调整。我习惯用滚动窗口的因子IC值来动态分配权重——哪个因子最近表现好,就给它更高的权重。

23.6 知识体系框架

下面这张图,是我自己总结的基差因子体系。你看一眼,就能明白这四个因子是怎么协同工作的:

基差交易量化因子体系 基差因子库 动量因子 趋势跟踪 反转因子 均值回归 波动率因子 风险调节 流动性因子 执行过滤 多因子组合信号 交易信号 → 开仓/平仓 四个因子各司其职:动量给方向,反转给边界,波动率调权重,流动性做过滤

你看,这个体系其实不复杂。核心就是让每个因子发挥自己的特长,然后通过组合来弥补各自的短板。我在实盘里用了两年多,效果还不错。

最后说一句:因子库不是建完就完事了。市场在变,因子的表现也在变。我每个月都会重新跑一遍因子IC测试,看看哪些因子失效了,哪些因子变强了。说白了,因子库需要持续维护,就像养花一样,得定期浇水施肥

公众号:蓝海数据掘金营,微信 deep3321