最近一直在学HTML5和CSS3,Numpy的东西都有些生疏,那本书是已经看完了的,紧跟着相关的代码也都敲了一遍,还是发现了一些问题,因为这样的学习方式,总感觉太被动,紧紧跟着示例代码,缺少了整体观,即使你现在问我Numpy可以处理什么问题,我还是回答不出。所以,有必要回头重来一遍,再一次审视代码背后的意义,写博客真的是一个很不错的方式,毕竟,如果你不懂,写出来的文字必然也是混乱的。
那,下面记录一下Numpy学习笔记(二)
Example1
文件读写:数据不应该仅仅存在内存里,应该及时保存在硬盘上,以文件的形式
# -*- coding:utf-8 -*- # 导入numpy库 import numpy as np ? # 文件读写 # 先创建一个单位矩阵 a = np.eye(2) # numpy自带的eye方法 print a # 使用savetxt函数保存 np.savetxt("D:\Learn\Code\python\exercise\eye.txt", a) |
结果如下:
查看相关文件夹,已经出现eye.txt,打开
Example2
CSV文件:逗号分隔值文件,很少听见,但经常遇见,用Excel打开的效果几乎与.xls文件一模一样
Numpy是用来处理数据的,而CSV是用来存储数据的,看起来渊源很深呢。
先来看一个CSV文件
里面记录的是苹果公司的股票,第一列是股票代码,第二列是日期,第三列为空,下面依次是开盘价、最高价、最低价和收盘价和成交量
接下来我们将收盘价和成交量分别载入数组
# CSV文件 # delimiter定义分隔符,默认是空格;usecols定义选取的;unpack默认False,解包 c, v = np.loadtxt(‘D:\Learn\Code\python\exercise\data.csv‘, delimiter=",", usecols=(6, 7), unpack=True) print u"收盘价:", c print u"成交量:", v |
看结果:
并不困难
Example3
各种平均值的求法:书里面列举了三个,成交量加权平均价格、算术平均值、时间加权平均价格
成交量平均价格(VWAP)表示成绩量越大,该价格所占的权重就越大
算术平均值就是权重为1
时间加权平均价格(TWAP)表示日期越近的价格所占比重越大
# 成交量平均价格 c, v = np.loadtxt("D:\Learn\Code\python\exercise\data.csv", delimiter=",", usecols=(6, 7), unpack=True) # 计算以成交量加权的价格 vwap = np.average(c, weights=v) print "VWAP:", vwap ? # 算术平均价格 mean = np.mean(c) print "Mean:", mean ? # 时间加权平均价格 # 先构造一个时间序列 t = np.arange(len(c)) twap = np.average(c, weights=t) print "TWAP:", twap |
结果如下:
Example4
最大值与最小值
# 载入每日最高价和最低价的数据 h, l = np.loadtxt("D:\Learn\Code\python\exercise\data.csv", delimiter=",", usecols=(4, 5), unpack=True) # 直接调用max()和min()函数 print "highest:", np.max(h) print "lowest:", np.min(l) ? # ptp函数可以计算取值范围 print "Spred high price:", np.ptp(h) print "Spred low price:", np.ptp(l) |
结果如下:
无论怎么讲都是相当便捷的
Example5
简单统计分析,这里主要是中位数、和方差
# 简单统计分析 c = np.loadtxt("D:\Learn\Code\python\exercise\data.csv", delimiter=",", usecols=(6, ), unpack=True) # 寻找中位数 print "median:", np.median(c) # 利用排序来检验正确与否 sorted_c = np.msort(c) print "sorted_c:", sorted_c N = len(c) if N%2 != 0: middle = sorted_c[N/2] else: middle = (sorted_c[N/2] + sorted_c[N/2-1])/2 print "middle:", middle ? # 计算方差 variance = np.var(c) print "variance:", variance |
结果如下:
所需要的无非就只是调用个函数那么简单!
Example6
计算股票收益率,分成这么几个(都是经济学的东西,看看就好,重点还是看numpy如何使用上):简单收益率、对数收益率和波动率
# 股票收益率 c = np.loadtxt("D:\Learn\Code\python\exercise\data.csv", delimiter=",", usecols=(6, ), unpack=True) # 简单收益率 # diff函数返回相邻数组元素差值组成的数组 diff = np.diff(c) print "diff:", diff # 收益率等于这一天与前一天的差值除以前一天的值 returns = diff/c[:-1] print "returns:", returns # 计算收益率的标注差 print "Standard deviation:", np.std(returns) ? # 对数收益率 logreturns = np.diff(np.log(c)) print "logreturns:", logreturns print "Standard deviation:", np.std(logreturns) ? # 计算收益率为正值的情况 posretindices = np.where(returns > 0) print "Indices with positive returns:", posretindices ? # 波动率(对数收益率的标准差除以其均值,再除以交易日倒数的平方根,交易日通常取252天) annual_volatility = np.std(logreturns)/np.mean(logreturns)/np.sqrt(1.0/252) print "Annual volatility:", annual_volatility print "Month volatility:", annual_volatility * np.sqrt(1.0/12) |
结果如下:
Example7
日期分析:分析CSV文件,会看到有一列日期数据,格式为dd-mm-yyyy,Python自带的时间处理模块,可以很自如地处理,而Numpy本身是无法处理这样的数据的,所以在解包的时候要先编写一个转换函数,然后将这个函数传递到loadtxt里的converters参数里
# 时间处理 # 先导入时间模块 import datetime # 编写转换函数 def datetostr(s): truetime = datetime.datetime.strptime(s, ‘%d-%m-%Y‘).weekday() return truetime # 开始读取数据,并添加converters参数 dates, close = np.loadtxt("D:\Learn\Code\python\exercise\data.csv", delimiter=",", usecols=(1, 6), converters={1: datetostr}, unpack=True) print "Dates:", dates # 创建一个包含五个元素的数组 averages = np.zeros(5) # where会根据条件返回满足条件的元素索引,take可以从索引中取出数据 for i in range(5): indices = np.where(dates == i) prices = np.take(close, indices) avg = np.mean(prices) print "Day", i, "prices", prices, "Average", avg averages[i] = avg |
结果是这样的:
这个练习有些困难,不仅使用到了Python里的datetime模块,还涉及到了loadtxt转换参数converters的使用,更不必说where和take了
Example8
Data.csv文件里,每一行代表每一天,如果数据量很大,我们可以考虑将它们进行压缩,按周进行汇总
# 周汇总 import datetime def datetostr(s): truetime = datetime.datetime.strptime(s, ‘%d-%m-%Y‘).weekday() return truetime dates, open, high, low, close = np.loadtxt("D:\Learn\Code\python\exercise\data.csv", delimiter=",", usecols=(1, 3, 4, 5, 6), converters={1: datetostr}, unpack=True) # 为了方便计算,仅取前三周数据 dates = dates[:16] ? # 寻找第一个星期一 first_monday = np.ravel(np.where(dates == 0))[0] # where返回的是个多维数组,需要展平 print "First Monday", first_monday # 寻找最后一个星期五 last_friday = np.ravel(np.where(dates == 4))[-1] print "Last Friday" ? weeks_indices = np.arange(first_monday, last_friday+1) print "Weeks indices initial", weeks_indices ? weeks_indices = np.split(weeks_indices, 3) print "Weeks indices after split", weeks_indices ? # 为了后面的apply_along_axis 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) # apply_along_axis内涵很丰富 weeksummary = np.apply_along_axis(summarize, 1, weeks_indices, open, high, low, close) print "Week summary", weeksummary # savetxt参数其实有很多 np.savetxt("D:\Learn\Code\python\exercise\weeksummary.csv", weeksummary, delimiter=",", fmt="%s") |
看结果:
打开文件夹,查看weekssummay.csv文件
Example9
真实波动幅度均值(ATR),这里取20天的数据
# 真实波动幅度均值 h, l, c = np.loadtxt(‘D:\Learn\Code\python\exercise\data.csv‘, delimiter=‘,‘, usecols=(4, 5, 6), unpack=True) ? N = 20 # 切片 h = h[-N:] l = l[-N:] ? print "len(h)", len(h), "len(l)", len(l) print "Close", c # 计算前一日的收盘价 previousclose = c[-N-1:-1] ? print "len(previousclose)", len(previousclose) print "Previous close", previousclose # maximum函数可以选择出每个元素的最大值 truerange = np.maximum(h-l, h-previousclose, previousclose-l) ? print "True range", truerange # zeros函数初始化数组为0 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 |
结果是这样的
Example10
简单移动平均线
这里会涉及到一个重要的函数:consolve函数,即卷积函数。卷积的概念百度百科上是这样解释的:卷积是两个变量在某范围内相乘后求和的结果。我在知乎上看到的一个答案,说的更简洁,即加权求和。
# 简单移动平均线 # N是移动窗口的大小 N = 5 # 权重是个平均值 weights = np.ones(N) / N print "Weights", weights ? c = np.loadtxt(‘D:\Learn\Code\python\exercise\data.csv‘, delimiter=‘,‘, usecols=(6, ), unpack=True) # 要从卷积运算中取出与原数组重叠的区域 sma = np.convolve(weights, c)[N-1:-N+1] # 生成一个时间序列 t = np.arange(N-1, len(c)) # 用matplotlib绘图 plt.plot(t, c[N-1:],‘b-‘, lw=1.0) plt.plot(t, sma, ‘r-‘, lw=2.0) plt.show() |
结果是这样的
Matplotlib的绘图效果相当不错,这里还可以添加一些参数
plt.xlabel("Date") plt.ylabel("Close Price") plt.title(u"Simple Moving Average") plt.annotate(‘before convolve‘, xy=(12.8, 363), xytext=(15, 363), arrowprops=dict(facecolor=‘black‘,shrink=0.005)) plt.annotate(‘after convolve‘, xy=(15, 358), xytext=(17, 358), arrowprops=dict(facecolor=‘black‘,shrink=0.005)) |
Example11
指数移动平均线
指数移动平均线使用的权重是指数衰减的,其他的与Example10一样
# 指数移动平均线 x = np.arange(5) # 对x求指数,exp函数 print "Exp", np.exp(x) # linspace函数实现等距分隔 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(‘D:\Learn\Code\python\exercise\data.csv‘, delimiter=‘,‘, usecols=(6, ), unpack=True) ema = np.convolve(weights, c)[N-1:-N+1] t = np.arange(N-1, len(c)) plt.plot(t, c[N-1:],‘b-‘, lw=1.0) plt.plot(t, ema, ‘r-‘, lw=2.0) plt.show() |
结果如下
与上一幅图略有不同
Example12
布林带
股票市场的一种常用指标,基本形态是由三条轨道线组成
中轨:简单移动平均线
上轨:比简单移动平均线高两倍标准差的距离,标准差是简单移动平均线的标准差
下轨:比简单移动平均线低两倍标准差的距离,标准差是简单移动平均线的标准差
这个有点难,下次有时间再写吧。
?
总结:从这次的笔记中可以看到,Numpy的确是很大程度上拓展了Python的统计功能,很多时候你所需要做的无非只是写个函数名,直接调用即可,Matplotlib同时提供了个性化很强的绘图功能,两者集成就可以实现很好的数据可视化。当然,这里的几个例子无非只是抛砖引玉,接下来的学习之路还很漫长。
?
源代码在这里:https://github.com/Lucifer25/Learn-Python/blob/master/Numpy/exercise2.py
?
参考资料:http://docs.scipy.org/doc/numpy/reference/
http://matplotlib.org/