3.NumPy常用函数
文章目录
- 前言
- 1、文件的读写(np.savetxt()、np.eye(6))
- 2、读入CSV文件(np.loadtxt())
- 3、简单的统计分析
- 3.1、成交量加权平均价格(np.average())
- 3.2、算术平均值(np.mean())
- 3.3、时间加权平均价格(np.average())
- 3.4、取值范围(np.max()、np.min()、np.ptp())
- 3.5、中位数分析(np.median())
- 3.6、方差分析(np.var())
- 3.7、收益率分析(np.diff()、np.std()、np.log()、np.where()、np.sqrt())
- 3.8、日期分析(np.zeros()、np.take()、np.argmax()、np.argmin()、参数converters)
- 3.9、汇总数据(np.apply_along_axis())
- 3.10、真实波动幅度值(np.maximum())
- 3.11、简单移动平均线(np.convolve())
- 3.12、指数移动平均线(np.exp()、np.linspace()、np.sum())
- 3.13、数组的修剪和压缩(np.clip()、np.compress())
- 3.14、阶乘(np.prod()、np.cumprod())
- 小结
前言
以分析苹果公司历史股价为例,介绍怎样从文件中载入数据,怎样使用NumPy的基本数学和统计分析函数。还将学习读写文件的方法,并尝试函数式编程和NumPy线性代数运算。
1、文件的读写(np.savetxt()、np.eye(6))
通常情况下,数据是以文件的形式存储的。作为文件读写示例,创建一个单位矩阵并将其存储到文件中。
# 1.创建单位矩阵(即主对角线上的元素均为1,其余元素均为0的正方形矩阵)
import numpy as np
a = np.eye(6)
print(a)
# 2.使用savetxt函数将数据存储到文件中,需要指定文件名以及要保存的数组
np.savetxt("eye.txt", a)
2、读入CSV文件(np.loadtxt())
CSV(Comma-Separated Value,逗号分隔值)格式是一种常见的文件格式。通常,数据库的转存文件就是CSV格式的,文件中的各个字段对应于数据库表中的列。电子表格软件(Microsoft Excel)可以处理CSV文件。
NumPy中的loadtxt函数可以方便地读取CSV文件,自动切分字段,并将数据载入NumPy数组。
以载入苹果公司的历史股价数据为例展。股价数据存储在CSV文件中,第1列为股票代码以标识股票(苹果公司股票代码为 AAPL),第2列为dd-mm-yyyy格式的日期,第3列为空,随后依次是开盘价、最高价、最低价和收盘价和当日的成交量:
AAPL 28-01-2011 344.17 344.4 333.53 336.1 21144800
# 将收盘价和成交量分别载入到两个数组中(最后两列)
# 设置分隔符为","(英文标点逗号)
# usecols的参数为一个元组,以获取指定字段的数据
# unpack参数设置为True,意思是分拆存储不同列的数据,即分别将收盘价和成交量的数组赋值给变量c和v
c, v = np.loadtxt("data.csv", delimiter=",", usecols=(6, 7), unpack=True)
print(c)
print(v)
3、简单的统计分析
3.1、成交量加权平均价格(np.average())
VWAP(Volume-Weighted Average Price,成交量加权平均价格)是一个非常重要的经济学量,它代表着金融资产的"平均"价格。某个价格的成交量越高,该价格所占的权重就越大。VWAP就是以成交量为权重计算出来的加权平均值,常用于算法交易。
import numpy as np
# 1.数据读入数组
# c:收盘价 v:当日的成交量
c, v = np.loadtxt("data.csv", delimiter=",", usecols=(6, 7), unpack=True)
# 2.计算VWAP
vwap = np.average(c, weights=v)
print("VWAP:{:.4f}".format(vwap))
3.2、算术平均值(np.mean())
NumPy中的mean函数很友好,这个函数可以计算数组元素的算术平均值。
# 计算算术平均值
mean = np.mean(c)
print("mean:{:.4f}".format(mean))
3.3、时间加权平均价格(np.average())
在经济学中,TWAP(Time-Weighted Average Price,时间加权平均价格)是另一种"平均"价格的指标。其基本的思想就是最近的价格重要性大,所以应该对近期的价格给以较高的权重。最简单的方法就是用arange()函数创建一个从0开始依次增长的自然数序列,自然数的个数即为收盘价的个数。
# 1.创建一个从0开始依次增长的自然数序列
t = np.arange(len(c))
print(t)
# 计算TWAP
twap = np.average(c, weights=t)
print("TWAP:{:.4f}".format(twap))
3.4、取值范围(np.max()、np.min()、np.ptp())
通常,不仅仅想知道一组数据的平均值,还希望知道数据的极值以及完整的取值范围(最大值和最小值)。min()函数和max()函数能够满足需求。ptp()函数可以计算数组的取值范围,函数返回的是数组元素的最大值和最小值之间的差值。
# 1.读入数据,将最高价和最低价的数据载入数组
# h:最高价 l:最低价
h, l = np.loadtxt("data.csv", delimiter=",", usecols=(4, 5), unpack=True)
# 2.min()函数和max()函数
hightest = np.max(h)
lowest = np.min(l)
print("hightest:{}".format(hightest))
print("lowest:{}".format(lowest))
# 3.计算最大值和最小值之间的差值
print("Spread high price:%.2f" % np.ptp(h))
print("Spread low price:%.2f" % np.ptp(l))
3.5、中位数分析(np.median())
# 计算中位数:median()函数
# 1.读入数据
c = np.loadtxt("data.csv", delimiter=",", usecols=(6,), unpack=True)
# 2.median()函数
media1 = np.median(c)
print("media1:{}".format(media1))
# 3.检查中位数结果:msort()函数,对数组进行排序
sorted_close = np.msort(c)
print("Sorted:", c)
# 4.手动计算中位数(偶数个:中位数的值等于中间两个数的平均值)
N = len(c)
media2 = (sorted_close[N//2] + sorted_close[N//2]-1)/2
print("media2:{}".format(media1))
3.6、方差分析(np.var())
方差是指各个数据与所有数据算术平均数的差的平方和除以数据个数所得到的值。方差能够体现变量变化的程度。
# 1.计算方差:np.var()函数
var1 = np.var(c)
print("var1:{}".format(var1))
# 2.检查方差
var2 = np.mean((c-c.mean())**2) # 直接在数组c上调用了mean方法c.mean()
print("var2:{}".format(var2))
3.7、收益率分析(np.diff()、np.std()、np.log()、np.where()、np.sqrt())
在学术文献中,收盘价的分析是基于股票收益率和对数收益率的。
简单收益率是指相邻两个价格之间的变化率,而对数收益率是指所有价格取对数后两两之间的差值。对数知识中,"a"的对数减去"b"的对数就等于"a除以b"的对数。因此,对数收益率也可以用来衡量价格的变化率。
注意,由于收益率是一个比值,因此它是无量纲的。总之,投资者最感兴趣的是收益率的方差或标准差,因为这代表着投资风险的大小。
# 计算简单收益率:diff()函数可以返回一个由相邻数组元素的差值构成的数组
# 1.读入数据
c = np.loadtxt('data.csv', delimiter=',', usecols=(6,), unpack=True)
# 2.diff()函数计算差值
diff = np.diff(c)
# 3.计算收益率,要用差值除以前一天的价格
returns = diff / c[0:29] # 没有用收盘价数组中的最后一个值做除数
# 4.计算标准差:std()函数
std = np.std(returns)
print("Standard deviation:", std)
# 对数收益率计算,用log()函数得到每一个收盘价的对数,再对结果使用diff()函数
# 1.读入数据
c = np.loadtxt('data.csv', delimiter=',', usecols=(6,), unpack=True)
# 2.log()函数计算对数
log = np.log(c)
# 3.计算对数收益率
logreturns = np.diff(log)
# 4.计算标准差:std()函数
std = np.std(logreturns)
print("Standard deviation:", std)
# where()函数:根据指定的条件返回所有满足条件的数组元素的索引值
posretindices = np.where(logreturns > 0)
print(posretindices)
在投资学中,波动率(volatility)是对价格变动的一种度量。历史波动率可以根据历史价格数据计算得出。计算历史波动率(如年波动率或月波动率)时,需要用到对数收益率。
年波动率等于对数收益率的标准差除以其均值,再除以交易日倒数的平方根,通常交易日取252天。用std()函数和mean()函数来计算。
# 年波动率
annual_volatility = np.std(logreturns) / np.mean(logreturns)
# sqrt()函数:做除法运算时,整数的除法和浮点数的除法运算机制不同,必须使用浮点数才能得到正确的结果
annual_volatility = annual_volatility / np.sqrt(1./252.)
print("Annual Volatility:",annual_volatility)
# 月波动率
monthly_volatility = annual_volatility * np.sqrt(1./12.)
print("Monthly Volatility:",monthly_volatility)
3.8、日期分析(np.zeros()、np.take()、np.argmax()、np.argmin()、参数converters)
NumPy是面向浮点数运算的,因此需要对显式地告诉NumPy怎样来转换日期,这里要用到loadtxt函数中的一个特定的参数converters,它是数据列和转换函数之间进行映射的字典。
# 1.转换函数
import numpy as np
from datetime import datetime
def datestr2num(s):
return datetime.strptime(s.decode('ascii'), "%d-%m-%Y").date().weekday()
# 将日期作为字符串传给date2num()函数,28-01-2011这个字符串首先会按照指定的形式%d-%m-%Y转换成一个datetime对象。
# 随后,datetime对象被转换为date对象。最后,调用weekday方法返回一个数字。
# 这个数字是0到6的整数,0代表星期一,6代表星期天。具体的数字并不重要,只是用作标识。
# 2.将日期转换函数挂接上去,读入数据
dates, close = np.loadtxt('data.csv', delimiter=',', usecols=(1, 6), converters={1: datestr2num}, unpack=True)
print("Dates =", dates)
# 星期一 0
# 星期二 1
# 星期三 2
# 星期四 3
# 星期五 4
# 星期六 5
# 星期日 6
# 3.创建一个包含5个元素的数组,分别代表一周的5个工作日。数组元素将初始化为0
averages = np.zeros(5)
# 4.where()函数会根据指定的条件返回所有满足条件的数组元素的索引值。take()函数可以按照这些索引值从数组中取出相应的元素。
# 利用take()函数来获取各个工作日的收盘价:
# 在循环中遍历0到4的日期标识,用where函数得到各工作日的索引值存储在indices数组中,
# 在用take函数获取这些索引值相应的元素值。最后对每个工作日计算出平均值存放在averages数组中。
for i in range(5):
indices = np.where(dates == i)
print(indices)
prices = np.take(close, indices)
avg = np.mean(prices)
print("Day", i, "prices", prices, "Average", avg)
print()
averages[i] = avg
# 5.找出哪个工作日的平均收盘价是最高的,哪个是最低的。
top = np.max(averages)
print("Highest average", top)
print("Top day of the week", np.argmax(averages)) # argmax函数返回的是averages数组中最大元素的索引值
bottom = np.min(averages)
print("Lowest average", bottom)
print("Bottom day of the week", np.argmin(averages)) # argmin函数返回的是averages数组中最小元素的索引值
3.9、汇总数据(np.apply_along_axis())
汇总整个交易周中从周一到周五的所有数据。数据覆盖的时间段内有一个节假日,在示例数据中没有这一天的数据记录。
# 1.数据中的第一天为星期五,处理起来不太方便。按照如下步骤来汇总数据。
# 为了简单起见,只考虑前三周的数据,这样就避免了节假日造成的数据缺失。
import numpy as np
from datetime import datetime
def datestr2num(s):
return datetime.strptime(s.decode('ascii'), "%d-%m-%Y").date().weekday()
dates, open, high, low, close = np.loadtxt('data.csv', delimiter=',', usecols=(1, 3, 4, 5, 6), converters={1: datestr2num}, unpack=True)
dates = dates[:16]
close = close[:16]
# 2.首先找到数据中的第一个星期一(0),可以作为where函数的条件。
# 取出数组中的首个元素,其索引值为0。但where函数返回的结果是一个多维数组,因此要用ravel函数将其展平
first_monday = np.ravel(np.where(dates == 0))[0]
print("The first Monday index is:", first_monday)
# 找到示例数据的最后一个星期五
last_friday = np.ravel(np.where(dates == 4))[-1]
print("The last Friday index is:", last_friday)
# 创建一个数组,存储三周内每一天的索引值
weeks_indices = np.arange(first_monday, last_friday+1)
print("Weeks indices initial", weeks_indices)
# 3.按照每个子数组5个元素,用split函数切分数组
weeks_indices = np.split(week_indices, 3)
print("Weeks indices after split", weeks_indices)
# 4.编写summarize函数,为每一周的数据返回一个元组,包含这一周的开盘价、 最高价、最低价和收盘价
def summarize(a, o, h, l, c):
monday_open = o[a[0]]
week_high = np.max(np.take(h, a))
week_low = np.min(np.take(l, a))
friday_close = c[a[-1]]
return ("APPL", monday_open, week_high, week_low, friday_close)
# 5.在NumPy中,数组的维度也被称作轴。apply_along_axis()函数会调用另外一个给出的函数,作用于每一个数组元素上。
# 在调用apply_along_axis()函数时提供自定义的函数summarize(),并指定要作用的轴或维度的编号、目标数组以及可变数量的summarize函数的参数。
weeksummary = np.apply_along_axis(summarize, 1, weeks_indices, open, high, low, close)
print("Week summary", weeksummary)
# 6.使用NumPy中的savetxt函数,将数据保存至文件
np.savetxt("weeksummary.csv", weeksummary, delimiter=",", fmt="%s")
# 代码中指定了文件名、需要保存的数组名、分隔符以及存储浮点数的格式
3.10、真实波动幅度值(np.maximum())
ATR(Average True Range,真实波动幅度均值)是一个用来衡量股价波动性的技术指标。
import numpy as np
import sys
h, l, c = np.loadtxt('data.csv', delimiter=',', usecols=(4, 5, 6), unpack=True)
N = 20
h = h[-N:] # 取最近N个交易数据
l = l[-N:]
print("len(h)", len(h), "len(l)", len(l), "len(c)", len(c))
previousclose = c[-N - 1: -1] # 前一个交易日的收盘价
print("len(previousclose)", len(previousclose))
print("Previous close", previousclose)
# np.maximum()函数:逐位比较取其大者
truerange = np.maximum(h - l, h - previousclose, previousclose - l)
# h – l 当日股价范围,即当日最高价和最低价之差
# h – previousclose 当日最高价和前一个交易日收盘价之差
# previousclose – l 前一个交易日收盘价和当日最低价之差
print("True range", truerange)
atr = np.zeros(N)
atr[0] = np.mean(truerange)
for i in range(1, N):
atr[i] = (N - 1) * atr[i - 1] + truerange[i]
atr[i] /= N
print("ATR", atr)
3.11、简单移动平均线(np.convolve())
简单移动平均线(simple moving average)通常用于分析时间序列上的数据。为了计算它,需要定义一个N个周期的移动窗口。按照时间序列滑动这个窗口,并计算窗口内数据的均值。
import numpy as np
from matplotlib.pyplot import plot
from matplotlib.pyplot import show
N = 5
weights = np.ones(N) / N
print("Weights", weights)
c = np.loadtxt('data.csv', delimiter=',', usecols=(6,), unpack=True)
sma = np.convolve(weights, c)[N-1:-N+1]
t = np.arange(N - 1, len(c))
plot(t, c[N-1:], lw=1.0)
plot(t, sma, lw=2.0)
show()
3.12、指数移动平均线(np.exp()、np.linspace()、np.sum())
指数移动平均线(exponential moving average)也是一种流行的技术指标。指数移动平均线使用的权重是指数衰减的。对历史上的数据点赋予的权重以指数速度减小,但永远不会到达0。
import numpy as np
from matplotlib.pyplot import plot
from matplotlib.pyplot import show
# x = np.arange(5)
# print("Exp", np.exp(x))
# print("Linspace", np.linspace(-1, 0, 5))
N = 5
weights = np.exp(np.linspace(-1., 0., N))
weights /= weights.sum()
print("Weights", weights)
c = np.loadtxt('data.csv', delimiter=',', usecols=(6,), unpack=True)
ema = np.convolve(weights, c)[N-1:-N+1]
t = np.arange(N - 1, len(c))
plot(t, c[N-1:], lw=1.0)
plot(t, ema, lw=2.0)
show()
3.13、数组的修剪和压缩(np.clip()、np.compress())
clip()方法返回一个修剪过的数组,也就是将所有比给定最大值还大的元素全部设为给定的最大值,而所有比给定最小值还小的元素全部设为给定的最小值。
compress()方法返回一个根据给定条件筛选后的数组。
a = np.arange(5)
print(a)
b = a.clip(1, 2)
print(b)
a = np.arange(5)
print(a)
b = a.compress(a > 2)
print(b)
3.14、阶乘(np.prod()、np.cumprod())
prod()方法计算阶乘,可以计算数组中所有元素的乘积。
cumprod()方法,计算数组元素的累积乘积。
b = np.arange(1, 9)
print(b)
print(b.prod())
print(b.cumprod())
小结
介绍了很多常用的NumPy()函数。用loadtxt()读文件,用savetxt()写文件,用eye()函数创建单位矩阵,用loadtxt()函数从一个CSV文件中读取股价数据。NumPy中的average()和mean()函数可以用来计算数据的加权平均数和算术平均数。
使用min()和max()函数来确定最大、最小值,用median()函数获取数据的中位数,用std()和var()函数计算数据的标准差和方差。 diff()函数可以返回数组中相邻元素的差值。log()函数可以计算数组元素的自然对数。loadtxt函数默认将所有数据转换为浮点数类型,它有一个特定的参数可以完成转换。这个参数就是converters,它是一个可以将数据列和所谓的转换函数连接起来的参数。
可以自定义了一个函数并将其作为参数传给了apply_along_axis函数。ones()函数可以创建一个全为1的数组,而且convolve函数可以根据指定的权重计算卷积。 用exp()和linspace()函数得到了一组指数衰减的权重值。linspace()可以给出一个均匀分布的数组,然后我们计算出该数组元素的指数。调用ndarray类的sum()方法对权重值做归一化处理。