4、领先滞后关系检测:Granger因果检验、交叉相关函数(CCF)、领先滞后指标构建

正股与联动标的之间,到底谁先动?谁后动?

这个问题,我做了这么多年量化,几乎每个项目都会遇到。你想想看,如果连谁领涨、谁跟涨都搞不清楚,那所谓的「联动策略」就是空中楼阁。

这一章,我们就来彻底解决这个问题。我会用三种方法,帮你把领先滞后关系「扒个精光」。

4.1 Granger因果检验:谁是谁的「因」?

Granger因果检验,名字听着挺唬人。说白了,就是问一个问题:用A的过去值,能不能更好地预测B的未来值?

如果能,我们就说「A是B的Granger原因」。注意,这不是哲学上的因果关系,而是统计学上的「预测关系」。我在项目中遇到过很多次,有人把Granger因果当成真正的因果,结果策略一上线就亏钱。嗯,这里要注意。

核心思想:

如果加入X的滞后项后,对Y的预测模型有显著改善,则X是Y的Granger原因。

具体怎么做?我们来看代码。我个人习惯用Python的statsmodels库,非常方便。

import pandas as pd
import numpy as np
from statsmodels.tsa.stattools import grangercausalitytests

# 假设df包含两列:'stock'(正股)和'bond'(联动标的)
# 我们想检验:正股是否是债券的Granger原因?

def granger_test(df, max_lag=5):
    """
    执行Granger因果检验
    df: DataFrame,包含两列
    max_lag: 最大滞后阶数
    """
    # 提取数据
    data = df[['stock', 'bond']].dropna()
    
    # 执行检验
    test_result = grangercausalitytests(data, maxlag=max_lag, verbose=False)
    
    # 整理结果
    results = []
    for lag in range(1, max_lag+1):
        # 提取p值
        p_value = test_result[lag][0]['ssr_ftest'][1]
        results.append({
            'lag': lag,
            'p_value': p_value,
            'significant': p_value < 0.05
        })
    
    return pd.DataFrame(results)

# 使用示例
result_df = granger_test(df, max_lag=5)
print(result_df)

我的经验:

滞后阶数的选择很关键。我一般会从1到10都试一遍,看哪个滞后阶数下p值最显著。另外,数据必须是平稳的,否则检验结果不可靠。我曾经因为忘了做平稳性检验,白白浪费了一周时间。

4.2 交叉相关函数(CCF):直观的「时间差」探测器

Granger因果检验告诉你「有没有关系」,但CCF告诉你「关系在哪个时间偏移上最强」。

CCF的原理很简单:把两个时间序列,一个固定,另一个左右平移,然后计算每个平移位置上的相关系数。相关系数最大的那个平移量,就是最可能的领先滞后阶数。

from scipy import signal
import matplotlib.pyplot as plt

def ccf_analysis(series1, series2, max_lag=20):
    """
    计算交叉相关函数
    series1, series2: 两个时间序列
    max_lag: 最大滞后阶数
    """
    # 标准化
    s1 = (series1 - series1.mean()) / series1.std()
    s2 = (series2 - series2.mean()) / series2.std()
    
    # 计算CCF
    ccf = signal.correlate(s1, s2, mode='full')
    lags = signal.correlation_lags(len(s1), len(s2), mode='full')
    
    # 只保留我们关心的滞后范围
    mask = (lags >= -max_lag) & (lags <= max_lag)
    ccf = ccf[mask]
    lags = lags[mask]
    
    # 归一化
    ccf = ccf / len(s1)
    
    return lags, ccf

# 使用示例
lags, ccf_values = ccf_analysis(df['stock'], df['bond'], max_lag=10)

# 找到最大相关系数对应的滞后
max_idx = np.argmax(np.abs(ccf_values))
best_lag = lags[max_idx]
print(f"最优滞后阶数: {best_lag}")

注意:

CCF对异常值非常敏感。我建议在使用前先做一次异常值处理。另外,如果两个序列都有很强的自相关性,CCF可能会产生「伪相关」。这时候,可以先对序列做「预白化」处理,也就是用AR模型过滤掉自相关部分。

4.3 领先滞后指标构建:把理论变成可交易的信号

好了,现在我们知道谁领先、谁滞后了。下一步,就是把这个关系变成一个可以用的指标。

我个人习惯构建一个「领先滞后强度指标」,它综合了Granger检验的显著性和CCF的滞后阶数信息。

def build_lead_lag_indicator(df, stock_col='stock', bond_col='bond', 
                             granger_lag=3, ccf_max_lag=10):
    """
    构建领先滞后指标
    """
    # 1. 计算滚动Granger检验的p值
    # 这里用滚动窗口,比如过去60天
    window = 60
    p_values = []
    
    for i in range(window, len(df)):
        window_data = df.iloc[i-window:i][[stock_col, bond_col]]
        test_result = grangercausalitytests(window_data, maxlag=granger_lag, verbose=False)
        p_val = test_result[granger_lag][0]['ssr_ftest'][1]
        p_values.append(p_val)
    
    # 2. 计算滚动CCF的最优滞后
    best_lags = []
    for i in range(window, len(df)):
        window_data = df.iloc[i-window:i]
        lags, ccf = ccf_analysis(window_data[stock_col], window_data[bond_col], 
                                 max_lag=ccf_max_lag)
        max_idx = np.argmax(np.abs(ccf))
        best_lags.append(lags[max_idx])
    
    # 3. 合成指标
    indicator = pd.DataFrame({
        'date': df.index[window:],
        'granger_p': p_values,
        'best_lag': best_lags
    })
    
    # 当Granger检验显著(p<0.05)且滞后阶数>0时,认为存在领先关系
    indicator['lead_lag_signal'] = 0
    indicator.loc[(indicator['granger_p'] < 0.05) & (indicator['best_lag'] > 0), 
                  'lead_lag_signal'] = 1
    indicator.loc[(indicator['granger_p'] < 0.05) & (indicator['best_lag'] < 0), 
                  'lead_lag_signal'] = -1
    
    return indicator

# 使用示例
indicator = build_lead_lag_indicator(df)
print(indicator.tail())

实战建议:

这个指标不是一成不变的。市场环境变了,领先滞后关系也会变。我一般会每周重新计算一次,动态调整。另外,当指标显示「无显著关系」时,我建议暂停该策略,不要强行交易。

4.4 本章知识体系

下面这张图,是我自己总结的领先滞后检测的完整流程。你可以把它当作一个检查清单。

领先滞后关系检测流程 数据准备 平稳性检验、异常值处理 Granger因果检验 判断是否存在预测关系 CCF分析 确定最优滞后阶数 领先滞后指标构建 综合Granger p值和CCF最优滞后 交易信号生成 领先信号:正股涨 → 做多联动标的 滞后信号:联动标的涨 → 做多正股 动态调整:每周重新计算

这张图把整个流程串起来了。从数据准备开始,到Granger检验判断关系是否存在,再到CCF确定具体的时间偏移,最后构建成可交易的指标。每一步都环环相扣。

核心要点回顾:

  • Granger因果检验回答「有没有关系」,CCF回答「关系在哪个时间偏移」
  • 两个方法要配合使用,缺一不可
  • 指标需要动态更新,市场环境变了,关系也会变
  • 当没有显著关系时,不要强行交易

好了,这一章的内容就到这里。领先滞后检测是正股联动策略的「眼睛」,没有它,你就是在黑暗中交易。下一章,我们会把这些指标组合起来,构建一个完整的交易策略。


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