动态调整Pandas DataFrame回溯期以进行股票数据回归分析
用Pandas动态调整回溯期,基于MA交叉信号运行回归分析
完全同意你的思路——记录信号出现的索引确实是解决逐行回溯效率问题的最优方案!作为Python新手,咱们一步步来实现这个逻辑,保证清晰易懂:
1. 先构建示例数据
首先把你给出的示例数据整理成可运行的Pandas DataFrame:
import pandas as pd import numpy as np from sklearn.linear_model import LinearRegression # 构建你提供的示例数据 data = { 'date': ['20150101', '20150101', '20150102', '20150103', '20150104', '20150105', '20150106', '20150107'], 'Prices': [8.5, 11.5, 14.5, 16.67, 18, 18.5, 18.17, 17], 'Diff': [-1.5, 0.3, 4.5, 3.66, 2, 0.5, -2.17, -3], 'signal': [False, True, False, False, False, False, True, False] } df = pd.DataFrame(data)
2. 高效记录最近信号的索引
不用逐行回溯,我们用Pandas的矢量化操作快速标记每行对应的最近一次信号出现的索引:
# 只在signal为True的行记录当前索引,其他行留空(NaN) df['last_signal_idx'] = df.index.where(df['signal']) # 向前填充(ffill)空值,这样每行都会得到最近的上一个信号的索引 df['last_signal_idx'] = df['last_signal_idx'].ffill().astype(int)
运行完这两行后,你会看到:
- 索引1(第一个True信号)的
last_signal_idx是1 - 索引2-5的
last_signal_idx都是1(继承上一个信号的索引) - 索引6(第二个True信号)的
last_signal_idx是6 - 索引7的
last_signal_idx是6
完全符合你需要的回溯期定义:比如索引7的回溯范围就是从6到7(对应prices[-1:]),索引6的回溯范围可根据需求选择从1到6或者6本身。
3. 针对信号区间运行回归分析
接下来我们可以按last_signal_idx分组,对每个区间的价格数据运行线性回归:
# 定义一个回归函数,输入是分组后的DataFrame,输出回归的斜率和截距 def run_price_regression(group): # 用时间步作为自变量X(从0开始计数),价格作为因变量y X = np.arange(len(group)).reshape(-1, 1) y = group['Prices'].values # 至少需要2个数据点才能做回归 if len(X) < 2: return pd.Series({'reg_slope': np.nan, 'reg_intercept': np.nan}) model = LinearRegression() model.fit(X, y) return pd.Series({'reg_slope': round(model.coef_[0], 4), 'reg_intercept': round(model.intercept_, 4)}) # 按信号索引分组,应用回归函数 reg_results = df.groupby('last_signal_idx').apply(run_price_regression) # 将回归结果合并回原DataFrame df = df.merge(reg_results, left_on='last_signal_idx', right_index=True)
4. 验证结果
现在查看处理后的DataFrame:
print(df)
你会看到每个行都带有对应的回归参数,比如:
- 索引1-5的行共享同一个回归结果(基于索引1到5的价格数据)
- 索引6-7的行共享另一个回归结果(基于索引6到7的价格数据)
这种方法完全避免了低效的逐行查找,利用Pandas的矢量化操作和分组功能,处理大规模数据时效率会非常高。
内容的提问来源于stack exchange,提问作者Sebastien Winsor
相关产品推荐
相关产品推荐

