You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在FOR循环回归中计算并存储每日残差?相关疑问

配对交易回归残差问题解答

嘿,针对你代码里的两个疑问,我来逐一给你理清:

问题1:reg._residues是不是真实Y与预测值的残差?

绝对不是。首先要明确:sklearn里的LinearRegression的_residues是个内部属性(以下划线开头,属于框架未公开的实现细节,不建议依赖),它代表的是所有训练样本残差的平方和——也就是$\sum_{i=1}^{n}(y_{真实} - y_{预测})^2$,是一个单一数值,而非每个样本对应的残差序列。

这就解释了为什么你用它做分布图时完全不符合正态/平稳特征:你其实在分析一个孤立值的分布(或者错误地重复使用这个值),根本不是每日的残差数据。如果要获取单样本残差,必须自己计算每个样本的真实值与预测值的差值。

问题2:怎么在循环里正确计算每日残差?

你的原代码在计算y_pred时犯了逻辑错误:每次循环都用了bank_matrix[['LDO.MI']][lookback:](也就是所有lookback之后的LDO数据)来预测,而不是对应当前循环步长的单一天的数据。下面是修正后的完整逻辑,同时提供两种计算残差的正确方式:

修正后的代码片段

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import pandas_datareader as pdr
from sklearn.linear_model import LinearRegression
from pandas.plotting import register_matplotlib_converters
register_matplotlib_converters()
import datetime

tickers=['EXO.MI','LDO.MI']
end=datetime.date.today()
gap=datetime.timedelta(days=650)
start=end- gap
Bank=pdr.get_data_yahoo(tickers,start=start,end=end)
bank_matrix=Bank['Adj Close']
bank_matrix=bank_matrix.dropna()
exor=bank_matrix['EXO.MI']
leonardo=bank_matrix['LDO.MI']

lookback=20
# 初始化存储列表,长度匹配有效数据
Hedge=[]
Intercetta=[]
Residuals=[]

# 循环从lookback开始,对应第i天,用前lookback天的数据拟合
for i in range(lookback, len(exor)):
    # 准确截取前lookback天的训练数据:左闭右开,正好取lookback个样本
    X_train = bank_matrix[['LDO.MI']].iloc[i-lookback:i]
    y_train = bank_matrix[['EXO.MI']].iloc[i-lookback:i]
    
    # 拟合回归模型
    reg = LinearRegression().fit(X_train, y_train)
    
    # 存储截距和对冲系数(注意取标量,因为sklearn返回的是数组)
    Intercetta.append(reg.intercept_[0])
    Hedge.append(reg.coef_[0][0])
    
    # 方式1:用模型预测当天的LDO值,计算残差
    X_today = bank_matrix[['LDO.MI']].iloc[i:i+1]
    y_pred_today = reg.predict(X_today)[0][0]
    y_true_today = exor.iloc[i]
    residual_today = y_true_today - y_pred_today
    
    # 方式2:手动计算预测值,结果和方式1完全一致
    # y_pred_today_manual = reg.intercept_[0] + reg.coef_[0][0] * leonardo.iloc[i]
    # residual_today = y_true_today - y_pred_today_manual
    
    Residuals.append(residual_today)

# 构建结果DataFrame,索引匹配有效日期
Regressione = pd.DataFrame({
    'Intercetta': Intercetta,
    'Hedge': Hedge,
    'Residuals': Residuals
}, index=bank_matrix.index[lookback:])

关键修正点:

  • 训练数据切片:用iloc[i-lookback:i]准确获取前lookback天的样本,避免了原代码中切片逻辑的模糊性。
  • 单日预测:每次循环只预测当前第i天的LDO值,保证残差是对应当天的真实值与预测值的差。
  • 维度处理:reg.intercept_和reg.coef_都是二维数组(因为sklearn要求输入是二维的),所以要通过[0]或[0][0]提取标量值,这也是你之前手动计算报错的核心原因——没有处理数组维度。

修改后你就能得到正确的每日残差序列,之后就可以正常分析它的正态性和平稳性,用于配对交易的策略开发了。


内容的提问来源于stack exchange,提问作者Polar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:15:22