本章将介绍NumPy
的常用函数。具体来说,我们将以分析历史股价为例,介绍怎样从文件中载入数据,以及怎样使用NumPy
的基本数学和统计分析函数。这里还将学习读写文件的方法,并尝试函数式编程和NumPy
线性代数运算。
首先学习使用NumPy
读写文件。通常情况下,数据是以文件形式存储的。学会读写文件是深入学习NumPy
的基础。
作为文件读写示例,我们创建一个单位矩阵并将其存储到文件中,并按照如下步骤完成。
(1) 单位矩阵,即主对角线上的元素均为1,其余元素均为0的正方形矩阵。在NumPy
中可以用eye
函数创建一个这样的二维数组,我们只需要给定一个参数,用于指定矩阵中1
的元素个数。
(2) 使用savetxt
函数将数据存储到文件中,当然我们需要指定文件名以及要保存的数组。
import numpy as np
#创建2×2的数组
i2 = np.eye(2)
print(i2)
#保存文件
np.savetxt("eye.txt", i2)
CSV(Comma-Separated Value,逗号分隔值)格式是一种常见的文件格式。通常,数据库的转存文件就是CSV格式的,文件中的各个字段对应于数据库表中的列。众所周知,电子表格软件(如Microsoft Excel)可以处理CSV文件。
我们应该如何处理CSV文件呢?幸运的是, NumPy
中的loadtxt
函数可以方便地读取CSV文件,自动切分字段,并将数据载入NumPy数组。
下面,我们以载入苹果公司的历史股价数据为例展开叙述。
股价数据存储在CSV文件中,第一列为股票代码以标识股票(苹果公司股票代码为AAPL
),第二列为dd-mm-yyyy
格式的日期,第三列为空,随后各列依次是开盘价、最高价、最低价和收盘价,最后一列为当日的成交量。下面为一行数据:
AAPL,28-01-2011, ,344.17,344.4,333.53,336.1,21144800
从现在开始,我们只关注股票的收盘价和成交量。在上面的示例数据中,收盘价为336.1,成交量为21144800。我们将收盘价和成交量分别载入到两个数组中,如下所示:
c,v=np.loadtxt('data.csv', delimiter=',', usecols=(6,7), unpack=True)
可以看到,数据存储在data.csv
文件中,我们设置分隔符为,
(英文标点逗号),因为我们要处理一个CSV文件。 usecols
的参数为一个元组,以获取第7
字段至第8
字段的数据,也就是股票的收盘价和成交量数据。 unpack
参数设置为True
,意思是分拆存储不同列的数据,即分别将收盘价和成交量的数组赋值给变量c
和v
。
VWAP(Volume-Weighted Average Price,成交量加权平均价格)是一个非常重要的经济学量,它代表着金融资产的“平均”价格。某个价格的成交量越高,该价格所占的权重就越大。 VWAP就是以成交量为权重计算出来的加权平均值,常用于算法交易。
我们将按如下步骤计算。
import numpy as np
c,v=np.loadtxt('data.csv', delimiter=',', usecols=(6,7), unpack=True)
vwap = np.average(c, weights=v)
print("VWAP =", vwap)
输出为VWAP = 350.589549353
。
NumPy
中的mean
函数很友好,一点儿也不mean
(该词有“尖酸刻薄”的意思)。这个函数可以计算数组元素的算术平均值。具体用法如下:
print("mean =", np.mean(c))
输出为mean = 351.0376666666667
。
在经济学中, TWAP(Time-Weighted Average Price,时间加权平均价格)是另一种“平均”价格的指标。既然我们已经计算了VWAP,那也来计算一下TWAP吧。其实TWAP只是一个变种而已,基本的思想就是最近的价格重要性大一些,所以我们应该对近期的价格给以较高的权重。最简单的方法就是用arange
函数创建一个从0
开始依次增长的自然数序列,自然数的个数即为收盘价的个数。当然,这并不一定是正确的计算TWAP的方式。事实上,本书中关于股价分析的大部分示例都仅仅是为了说明问题。计算TWAP的代码如下。
t = np.arange(len(c))
print("twap =", np.average(c, weights=t))
程序将输出如下结果:
twap = 352.4283218390804
在这个例子中, TWAP的值甚至比算术平均值还要高。
import numpy as np
c,v=np.loadtxt('data.csv', delimiter=',', usecols=(6,7), unpack=True)
vwap = np.average(c, weights=v)
print("VWAP =", vwap)
print("mean =", np.mean(c))
t = np.arange(len(c))
print("twap =", np.average(c, weights=t))
通常,我们不仅仅想知道一组数据的平均值, 还希望知道数据的极值以及完整的取值范围——最大值和最小值。我们的股价示例数据中已经包含了每天的股价范围——最高价和最低价。但是,我们还需要知道最高价的最大值以及最低价的最小值。不然,我们怎样才能知道自己的股票是赚了还是赔了呢?
min
函数和max
函数能够满足需求。我们按如下步骤来找最大值和最小值。
h,l=np.loadtxt('data.csv',delimiter=',', usecols=(4,5), unpack=True)
唯一需要修改的就是usecols
中的参数,因为最高价和最低价与之前的数据在不同的列中。
print("highest =", np.max(h))
print("lowest =", np.min(l))
程序将返回如下结果:
highest = 364.9
lowest = 333.53
现在,计算区间中点就很容易了,留给读者自己尝试练习。
NumPy
中有一个**ptp
函数可以计算数组的取值范围**。该函数返回的是数组元素的最大值和最小值之间的差值。也就是说,返回值等于max(array) - min(array)
。调用ptp
函数:print("Spread high price", np.ptp(h))
print("Spread low price", np.ptp(l))
我们将看到如下结果:
Spread high price 24.859999999999957
Spread low price 26.970000000000027
import numpy as np
h,l=np.loadtxt('data.csv',delimiter=',', usecols=(4,5), unpack=True)
print("highest =", np.max(h))
print("lowest =", np.min(l))
print((np.max(h) + np.min(l)) /2)
print("Spread high price", np.ptp(h))
print("Spread low price", np.ptp(l))