前面已经对Pandas库的基础知识进行了学习,现在利用pandas对股票数据进行分析,看一看我们通过股票的交易数据能获取哪些信息。
一、数据集下载
本次分析用到的数据集是2012年每日间隔5分钟的交易数据,数据的质量可能不高,但是不影响我们的分析,主要目的还是巩固Pandas的学习。我在评论区给出了数据集的链接,大家有需要的可以点开获取,数据集是1999-2012年之间的交易数据,大家可以任意使用其中一组数据进行分析。
二、数据读取
首先,先来看一下数据
import pandas as pd
import numpy as np
names=['date',
'time',
'opening_price',
'ceiling_price',
'floor_price',
'closing_price',
'volume', #在命名的时候后缀不要带s
'amount']
raw=pd.read_csv('/opt/jupyter_file/dataset/stock2012csv/SH000018.csv',names=names,header=None,index_col='date',parse_dates=True)
raw.head()
接下来,我们将数据进行一下转化,分钟级别的数据太细了,我们转化成日数据
#我们更关心是一些长期的趋势,分钟级别的交易数据太细了,我们转换成日数据
#根据涨跌幅判断数据是否有效,例如每天的涨跌幅不超过10%
def _valid_price(prices):
return ((prices.max()-prices.min())/prices.min())<0.223
#按日期分组
days=raw.groupby(level=0).agg({#agg函数传入一个字典,键指对应的列名,值指聚合函数如{'sum', 'count', 'mean'}之类
'opening_price':lambda prices:_valid_price(prices) and prices[0] or 0,
'ceiling_price':lambda prices:_valid_price(prices) and np.max(prices) or 0,
'floor_price':lambda prices:_valid_price(prices) and np.min(prices) or 0,
'closing_price':lambda prices:_valid_price(prices) and prices[-1] or 0,
'volume':'sum',
'amount':'sum'
})
days.head()
三、填充数据
观察上面的数据我们发现,2012-01-07和2012-01-08这两天是没有数据的,原因是周末两天不进行股票交易, 所以是没有数据的,但是在我们分析数据时需要连续的数据,所以我们对缺失的数据进行填充,填充的原则是将周末的交易量和金额填充0,价格使用前一天的数据进行填充。
#abs缺少数据处理,周末没有交易
start=days.iloc[0:1].index.tolist()[0] #开始那一天
end=days.iloc[-2:-1].index.tolist()[0] #结束那一天
new_idx=pd.date_range(start=start,end=end)
print(new_idx)
data=days.reindex(new_idx) #重新索引
zero_values=data.loc[~(data.volume>0)].loc[:,['volume','amount']]#后缀带s会出错
# zero_values
data.update(zero_values.fillna(0)) #交易量和金额填0
data.fillna(method='ffill',inplace=True)#价格用前一天的填充
data.head()
四、计算平均波动率
在一定时间周期内,我们用最高价/最低价来作为股票波动的指标。其实当股票出现了波动时,并不一定就坏事。若是一只股票经常都很活跃,却突然变得波动比较小,那么它就有可能会跌。若是一只股票长期都很平稳,却突然有了波动,那么这只股票倒是有涨的可能。所以股票的波动其实是非常正常的现象,我们只需要根据情况而进行操作就好。
1、按月分组
#分组计算
#我们需要计算30个自然日里的股票平均波动周期,这样,我们必须以30天为单位,对所有历史数据进行
#分组。然后逐个分组计算其波动率
#定义产生分组索引的函数
#python2中b/c得到的结果是int,而python3中得到结果是float。range的参数必修是int。此时用//代替/即可得到int的结果
def get_grouping(total,group_len):
group_count=total//group_len
group_index=np.arange(total)
for i in range(group_count):
group_index[i * group_len:(i+1)*group_len]=i
group_index[(i+1) * group_len:]=i+1
return group_index.tolist()
period=30
group_index=get_grouping(len(data),period)
data['group_index']=group_index
data.head().append(data.tail())
2、根据索引分组计算成交额、最低价和最高价
#为负表示先出现最高价再出现最低价,即下跌波动
def get_ceiling_price(price):
return price.idxmax() > price.idxmin() and np.max(price) or (-np.max(price))
#根据索引分组计算
group=data.groupby('group_index').agg({
'volume':'sum',
'floor_price':'min',
'ceiling_price':get_ceiling_price
})
group.head()
3、添加开始日期
date_col=pd.DataFrame({'group_index':group_index,'date':new_idx})
date_col
group['date']=date_col.groupby('group_index').agg('first')#为每个索引添加开始日期
group.head()
4、计算波动率
group['ripples_ratio']=group.ceiling_price/group.floor_price#计算波动率
group.head()
5、波动率排序
#波动率排序
ripples=group.sort_values('ripples_ratio',ascending=False)
ripples
还可以计算一下,前十位和后十位的波动平均值
ripples.head(10).ripples_ratio.mean()#前十个波动平均值
ripples.tail(10).ripples_ratio.mean()#后十个波动平均值
这个就不演示了,有兴趣的同学可以试一下。通过上面的数据计算可以看出中国的股市还是比较凶险的,很容易就会被套牢。
五、计算涨跌幅(每天)
涨跌幅定义为今日收盘价减去昨日收盘价
#计算涨跌幅(每天)
rise=data.closing_price.diff()#diff函数是用来将数据进行某种移动之后与原数据进行比较得出的差异数据
data['rise']=rise
data.head()
注意到第一条记录的涨跌幅为 NaN,因为第一条记录的昨日是没有数据的。
好了,利用pandas对股票数据的分析到这里就结束了,实际的操作颗粒度肯定要比这细的多,大家也不必太纠结分析结果,我们的目的主要是巩固pandas的学习,目的达到就好了。see you ~