新手发文,欢迎拍砖。
聊一下python开源包pandas中rolling的使用。
缘起
参加了万矿网举办的WQFA初级认证-12月编程考试,有题如下:
获取2016年01月04日至2018年8月30日,RB.SHF和HC.SHF的日涨跌幅数据,按以下公式,计算螺纹钢主力合约RB.SHF与热卷主力合约HC.SHF每日涨跌幅的滚动回归系数(每120日的数据回归一次) :
一看到“滚动”两个字,第一反应就是用rolling()。想都没有想面对的是DataFrame,而不是Series。
先把代码放上来,献丑了。
代码
import statsmodels.api as sm
def answer_question2():
# 第2题代码写在这里
_, p_close = w.wsd(['RB.SHF', 'HC.SHF'], 'close', '20160104', '20180830', usedf=True)
pct = p_close.pct_change().iloc[1: , :] # 首行为NaN,去除
rb_shf = pct['RB.SHF']
hc_shf = pct['HC.SHF']
# 全局变量,保存滚动回归后的截距
global_alpha = []
def rolling_ols(rb):
'''
滚动回归,返回滚动回归后的回归系数
rb: 因变量序列
'''
# 数据预处理
rb.name = 'RB.SHF'
df = pd.concat([rb, hc_shf], axis=1) # 方便index对齐
df.dropna(inplace=True)
# 回归
X = sm.add_constant(df['HC.SHF'])
model = sm.OLS(df['RB.SHF'], X)
results = model.fit()
# 结果输出
global_alpha.append(results.params['const'])
return results.params['HC.SHF']
# 滚动回归
beta = rb_shf.rolling(120).apply(rolling_ols, raw=False)
# 调整结果输出格式
beta.dropna(inplace=True)
beta.name = 'beta'
global_alpha = pd.Series(global_alpha, index=beta.index, name='alpha')
res = pd.concat([global_alpha, beta], axis=1)
return res
ans2 = answer_question2()
print(ans2)
解析
- rolling就是滚动窗口统计的函数,最主要的参数就是窗口的宽度,本题中为120;
- 在解决本题时,发现rolling对Series对象较友好,能保持原来的index;
- 而如果是对DataFrame对象进行rolling操作的话,会将整个DataFrame拉直为Series看待,同时丢弃掉了index信息;
- 所以本文借用了index对齐的功能,间接实现了对二维数据的滚动(rolling)操作。
小结
第一次发简书,欢迎大家指正和交流。本文采用了取巧的方法,避免了写for循环,但是终究是奇巧淫技,能够熟练地看文档,才是正途。同时献上官方参考答案,以供对比学习。感谢万矿提供这样一个学习和共享的平台。