我有许多(4000+个)股票数据的CSV(日期、开盘、高位、低位、收盘),我将其导入到各个Pandas数据框中进行分析。我是python新手,希望为每种股票计算12个月的滚动beta,我找到了一篇计算滚动beta的帖子(python熊猫以矢量化方式使用滚动应用于groupby对象计算滚动股票beta),但是在我下面的代码中使用时需要2.5个多小时!考虑到我可以在3分钟内在SQL表中运行完全相同的计算,这太慢了
如何提高下面代码的性能以与SQL相匹配?我知道Pandas/python具有这种能力。我当前的方法在每一行上循环,我知道这会降低性能,但我不知道在数据帧上执行滚动窗口beta计算的任何聚合方法
注:将CSV加载到单个数据帧并计算每日回报的前两个步骤只需约20秒。我所有的CSV数据帧都存储在名为“filesload”的字典中,名字如“XAO”
非常感谢您的帮助!
谢谢:)
将熊猫作为pd导入,numpy作为np导入
导入日期时间
导入ntpath
pd.set_选项(“精度”,10)#设置要显示的小数点精度
start\u time=datetime.datetime.now()
市场指数='XAO'
周期=250
MinBetaPeriod=周期
# ***********************************************************************************************
#计算回报
# ***********************************************************************************************
对于已加载文件中的文件:
filesload[File]['Return']=filesload[File]['Close'].pct_change()
# ***********************************************************************************************
#钙β
# ***********************************************************************************************
def calc_β(df):
np_数组=df.values
m=np_数组[:,0]#市场回报是numpy数组的第0列
s=np_数组[:,1]#股票收益是numpy数组的第一列
协方差=np.cov(s,m)#计算股票和市场之间的协方差
β=协方差[0,1]/协方差[1,1]
返回贝塔
#构建自定义“滚动应用”功能
def滚动应用(df、周期、func、最小周期=无):
如果“最小周期”为“无”:
最小周期=周期
结果=pd系列(np.nan,索引=df.index)
对于范围(1,len(df)+1)内的i:
sub_df=df.iloc[max(i周期,0):i,:]
如果len(sub_df)>;=最短期限:
idx=次级测向指数[-1]
结果[idx]=func(sub_df)
返回结果
#创建与返回数据帧具有相同索引的空BETA数据帧
df_join=pd.DataFrame(index=filesload[MarketIndex].index)
df_join['market']=已加载文件[MarketIndex]['Return']
df_join['stock']=np.nan
对于已加载文件中的文件:
df_join['stock'].更新(已加载文件[File]['Return'])
df_join=df_join.replace(np.inf,np.nan)#去掉无限值“inf”(SQL不会接受“inf”)
df_join=df_join.replace(-np.inf,np.nan)#去掉无限值“inf”(SQL不会接受“inf”)
df_join=df_join.fillna(0)#去掉返回数据中的nan
文件加载[文件]['Beta']=滚动应用(df_加入[['market','stock']],期间,计算Beta,最小期间=最小期间)
# ***********************************************************************************************
#清理
# ***********************************************************************************************
打印('Run-time:{0}'。格式(datetime.datetime.now()-start_-time))
生成随机股票数据
20年4000只股票的月度数据
dates=pd.date\u范围('1995-12-31',句点=480,频率=M',名称=date')
stoks=pd.Index(['s{:04d}'。范围(4000)内i的格式(i))
df=pd.DataFrame(np.random.rand(4804000),日期,stok)
df.iloc[:5,:5]
滚动功能
返回已准备好应用自定义函数的groupby对象
见来源
def辊(df,w):
#堆栈df.w值在每个堆栈上移动一次
roll_array=np.dstack([df.values[i:i+w,:]针对范围内的i(len(df.index)-w+1)]).T
#roll_阵列现在是一个三维阵列,可以读入
#面板对象
面板=局部放电面板(滚动阵列,
项目=测向索引[w-1:],
长轴=测向柱,
短轴=局部分度(范围(w),名称=滚动)
#转换为dataframe和pivot+groupby
#现在可以正常执行任何操作
#关于groupby对象
返回面板.to_frame().unstack().T.groupby(级别=0)
测试功能
使用OLS回归的闭式解
假设第0列为市场
见来源
def测试版(df):
#第一栏是市场
X=df.值[:,[0]]
#为截取预加一列
X=np.连接([np.像(X),X],轴=1)
#矩阵代数
b=np.linalg.pinv(X.T.dot(X)).dot(X.T).dot(df.值[:,1:])
返回pd.Series(b[1],df.columns[1:],name='Beta')
演示
rdf=滚转(df,12)
betas=rdf.apply(beta)
定时
验证
将计算结果与OP进行比较
def calc_β(df):
np_数组=df.values
m=np_数组[:,0]#市场回报是numpy数组的第0列
s=np_数组[:,1]#股票收益是numpy数组的第一列
协方差=np.cov(s,m)#计算股票和市场之间的协方差
β=协方差[0,1]/协方差[1,1]
返回贝塔
打印(计算β(df.iloc[:12,:2]))
-0.311757542437
打印(beta版(df.iloc[:12,:2]))
s0001-0.311758
名称:Beta,数据类型:float64
注意第一个单元格
与上述验证计算值相同
betas=rdf.apply(beta)
betas.iloc[:5,:5]
对评论的回应
模拟多个数据帧的完整工作示例
num\u sec\u dfs=4000
cols=[‘打开’、‘高’、‘低’、‘关闭’]
dfs={'s{:04d}'。格式(i):范围(num_secu_dfs)内i的pd.DataFrame(np.random.rand(480,4),dates,cols)}
market=pd.系列(np.random.rand(480),日期,name='market')
df=pd.concat([market]+[dfs[k].Close.rename(k)表示dfs.keys()],axis=1)中的k。排序索引(1)
betas=roll(df.pct_change().dropna(),12)。apply(beta)
对于c,使用betas.iteritems()中的col:
dfs[c]['Beta']=列
dfs['s0001'].总目(20)