python

校园 长篇 古典 武侠 连载-用Python分析苹果公司股价数据

2021-12-07

https://zhuanlan.zhihu.com/c_147297848

3.利用常用函数分析价格的加权均值、收益率、年化波动率等常用指标4.处理数据中的日期

我们最后会介绍一下NumPy库中的一些非常实用和常用的函数方法。

要知道,NumPy的常用数学和统计分析的函数非常多,如果我们一个一个的分散来讲,一来非常枯燥,二来呢也记不住,就仿佛又回到了昏昏欲睡的课堂,今天我们用一个背景例子来串联一下这些零散的知识点。

我们通过分析苹果公司的股票价格,来串讲NumPy的常用函数用法

我们在我们校园 长篇 古典 武侠 连载文件的同级目录下放置数据文件AAPL.csv,用excel文件可以打开看看里面是什么样的:

依次是日期,收盘价、成交量、开盘价、最高价和最低价在校园 长篇 古典 武侠 连载文件中,每一列数据数据是被“,”隔开的,为了突出重点简化程序,我们把第一行去掉,就像下面这样

首先,我们读取“收盘价”和“成交量”这两列,即第1列和第2列(csv也是从第0列开始的)

importnumpyasnp

c,v=np.loadtxt('AAPL.csv',delimiter=',',usecols=(1,2),unpack=True)

print(c)

print(v)

[178............178....5172.5171.............5167.........178...1176.......173......6170......42]

[.............................................................]

这样,我们就完成了第一个任务,将csv数据文件中存储的数据,读取到我们两个ndarray数组c和v中了。

接下来,我们小试牛刀,对收盘价进行最简单的数据处理,求取他的平均值。

importnumpyasnp

c,v=np.loadtxt('AAPL.csv',delimiter=',',usecols=(1,2),unpack=True)

mean_c=np.mean(c)print(mean_c)

172.

即,用成交量的值来作为权重,某个价格的成交量越高,该价格所占的权重就越大。

importnumpyasnp

c,v=np.loadtxt('AAPL.csv',delimiter=',',usecols=(1,2),unpack=True)

vwap=np.aver**e(c,weights=v)

print(vwap)

170.

我们找找收盘价的最大值和最小值,以及最大值和最小值之间的差异

importnumpyasnp

c=np.loadtxt('AAPL.csv',delimiter=',',usecols=(1,),unpack=True)

print(np.max(c))

print(np.min(c))

print(np.ptp(c))

181.72

155.15

26.57

importnumpyasnp

c=np.loadtxt('AAPL.csv',delimiter=',',usecols=(1,),unpack=True)

print(np.max(c))

print(np.min(c))

print(np.median(c))

181.72

155.15

174.35

另外一个我们关心的统计量就是方差,方差能够体现变量变化的程度。在我们的例子中,方差还可以告诉我们投资风险的大小。那些股价变动过于剧烈的股票一定会给持有者带来麻烦

importnumpyasnp

c=np.loadtxt('AAPL.csv',delimiter=',',usecols=(1,),unpack=True)

print(np.var(c))

37.

我们回顾一下方差的定义,方差指的是各个数据与所有数据算数平均数的离差平方和的均值

importnumpyasnp

c=np.loadtxt('AAPL.csv',delimiter=',',usecols=(1,),unpack=True)

print(np.mean((c-c.mean())**2))

37.

,即用今天的收盘价减去昨天的收盘价,再除以昨天的收盘价格。同时我们发挥NumPy的优势,利用向量运算,可以一次性算出所有交易日的收益率

diff函数时用数组的第N项减第N-1项,得到一个n-1项的一维数组。本例中我们注意到数组中日期越近的收盘价,数组索引越小,因此得取一个相反数,综上代码:

importnumpyasnp

c=np.loadtxt('AAPL.csv',delimiter=',',usecols=(1,),unpack=True)

returns=-np.diff(c)/c[1:]

print(returns)

[-0..-0.-0....-0.-0...-0.-0.-0....-0.-0.-0......-0.-0..-0.-0...-0.-0..-0.-0..-0.-0...-0...-0.-0.-0...-0..-0...-0.-0.0.-0.-0.]

然后观察一下每日收益的标准差,就可以看看收益的波动大不大了:

importnumpyasnp

c=np.loadtxt('AAPL.csv',delimiter=',',usecols=(1,),unpack=True)

returns=-np.diff(c)/c[1:]

print(np.std(returns))

0.

如果我们想看看哪些天的收益率是正的,很简单,还记得where语句吗,拿来使用吧

importnumpyasnp

c=np.loadtxt('AAPL.csv',delimiter=',',usecols=(1,),unpack=True)

returns=-np.diff(c)/c[1:]

print(np.where(returns>0))

(array([1,4,5,6,9,10,14,15,16,20,21,22,23,24,27,30,31,34,37,40,41,43,44,48,49,51,53,54,57],dtype=int64),)

专业上我们对价格变动可以用一个叫做“波动率”的指标进行度量。计算历史波动率时需要用到对数收益率,对数收益率很简单,就是

,在计算年化波动率时,要用样本中所有的对数收益率的标准差除以其均值,再除以交易日倒数的平方根,一年交易日取252天。

importnumpyasnp

c=np.loadtxt('AAPL.csv',delimiter=',',usecols=(1,),unpack=True)

logreturns=-np.diff(np.log(c))

volatility=np.std(logreturns)/np.mean(logreturns)

annual_volatility=volatility/np.sqrt(1./252.)

print(volatility)

print(annual_volatility)

100.096757388

1588.

这里我们再强调一点就是:sqrt方法中应用了除法计算,这里必须使用浮点数进行运算。月度波动率也是同理用1./12.即可

我们可以常常会发现,在数据分析的过程中,对于日期的处理和分析也是一个很重要的内容。

importnumpyasnp

dates,c=np.loadtxt('AAPL.csv',delimiter=',',usecols=(0,1),unpack=True)

Traceback(mostrecentcalllast):

File"E:/12homework/12homework.py",line2,in

dates,c=np.loadtxt('AAPL.csv',delimiter=',',usecols=(0,1),unpack=True)

File"C:\Python34\lib\site-pack**es\numpy\lib\npyio.py",line930,inloadtxt

items=[conv(val)for(conv,val)inzip(converters,vals)]

File"C:\Python34\lib\site-pack**es\numpy\lib\npyio.py",line930,in

items=[conv(val)for(conv,val)inzip(converters,vals)]

File"C:\Python34\lib\site-pack**es\numpy\lib\npyio.py",line659,infloatconv

returnfloat(x)

ValueError:couldnotconvertstringtofloat:b'2018/3/16'

我们发现他报错了,错误信息是不能将一个字节类型的对象转换为浮点类型对象。原因是因为NumPy是面向浮点数运算的,那么我们对症下药,对日期字符串进行一些转换处理。

我们先假定日期是一个字符串类型(下载的网络数据中往往是将字符串通过utf-8编码成字节码,这个可以见第一季中字符编码相关内容的介绍)

importnumpyasnpimportdatetime

strdate='2017/3/16'

d=datetime.datetime.strptime(strdate,'%Y/%m/%d')

print(type(d))

print(d)

2017-03-1600:00:00

通过校园 长篇 古典 武侠 连载标准库中的datetime函数包,我们通过指定匹配的格式%Y/%m/%d

将日期字符串转换为了datetime类型对象,Y大写匹配完整的四位数记年,y小写就是两位数,例如17。

datetime对象有一个date方法,把datetime对象中的time部分去掉,变成一个纯的日期,再调用weekday可以转换为一周中的第几天,这里是从周日开始算起的。

importnumpyasnpimportdatetime

strdate='2018/3/16'

d=datetime.datetime.strptime(strdate,'%Y/%m/%d')

print(d.date())

print(d.date().weekday())

2018-03-164

最后,我们回到这份苹果公司股价的csv文件,来做一个综合分析,来看看周几的平均收盘价最高,周几的最低:

importnumpyasnpimportdatetime

defdatestr2num(bytedate):

returndatetime.datetime.strptime(

bytedate.decode('utf-8'),'%Y/%m/%d').date().weekday()

dates,c=np.loadtxt('AAPL.csv',delimiter=',',usecols=(0,1),

converters={0:datestr2num},unpack=True)

aver**es=np.zeros(5)

foriinrange(5):

index=np.where(dates==i)

prices=np.take(c,index)

avg=np.mean(prices)

aver**es[i]=avgprint("Day{}prices:{},avg={}".format(i,prices,avg))

top=np.max(aver**es)

top_index=np.argmax(aver**es)

bot=np.min(aver**es)

bot_index=np.argmin(aver**es)

print('highest:{},topdayis{}'.format(top,top_index))

print('lowest:{},bottomdayis{}'.format(bot,bot_index))

Day0prices:[[181.......174..42]],avg=172.

Day1prices:[[179.............54]],avg=172.

Day2prices:[[178.........1174...6174.35]],avg=172.

Day3prices:[[178...172.5172.........01]],avg=172.

Day4prices:[[178....5172...5171....169..01]],avg=172.

highest:172.,topdayis1

lowest:172.,bottomdayis2

简要的再分析一下:由于从csv中读取的数据类型为bytes,所以我们写了一个转换函数,先将bytes类型的日期数据进行解码(字符串编解码详见第一季),然后再用上一段程序介绍的方法转换为一个表示周几的数字

而np.loadtxt函数中的参数converters={0:datestr2num},就是说针对第一列的数据,我们利用这个转换函数将其转化为一个数字,并将这个整形元素构成的数组赋值给dates变量。

后面的处理就很简单了,用循环依次取出每个工作日的收盘价构成的数组,对其求平均值。然后得到周一到周五,五个平均值的最大值、最小值。

最后我们再介绍两个实用函数,一个是数组的裁剪函数,即把比给定值还小的值设置为给定值,比给定值大的值设置为给定上限

importnumpyasnp

a=np.arange(5)

print(a.clip(1,3))

[]

第二个是一个筛选函数,返回一个根据给定条件筛选后得到的结果数组

importnumpyasnp

a=np.arange(5)

print(>2))

[34]

这一小节中,我们利用NumPy的一些实用函数,对苹果公司的股价进行了一些非常非常简单的分析,目的是通过这个实例来串讲一下这些实用的数据处理函数。

其实NumPy的功能非常非常多,远不止这些,但是没有必要去一个一个学。并且另一方面,NumPy的方法都过于原始和底层,虽然功能很丰富,但是使用起来也很繁杂。这里我们为大家打一个基础,后面的章节就不会再一一介绍里面的各种函数了。后面我要介绍基于NumPy之上的一些更高层的方法库,功能更强大,使用也更简单。



友情链接: