Numpy學習筆記(二)


最近一直在學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

布林帶

股票市場的一種常用指標,基本形態是由三條軌道線組成

中軌:簡單移動平均線

上軌:比簡單移動平均線高兩倍標准差的距離,標准差是簡單移動平均線的標准差

下軌:比簡單移動平均線低兩倍標准差的距離,標准差是簡單移動平均線的標准差

# 繪制布林帶

N = 5

# 計算權重

weights = np.ones(N)/N

 

c = np.loadtxt('D:\Learn\Code\python\exercise\data.csv', delimiter=',', usecols=(6, ), unpack=True)

# 簡單移動平均線,注意切片

sma = np.convolve(weights, c)[N-1:-N+1]

deviation = []

 

# 標准差為計算簡單移動平均線所用數據的標准差

for i in range(0, len(c)-N+1):

dev = c[i:i+N]

 

averages = np.zeros(N)

# fill函數可以將數組元素賦為單一值,平均值恰好為sma數組里的元素

averages.fill(sma[i])

dev = dev-averages

dev = dev ** 2

dev = np.sqrt(np.mean(dev))

deviation.append(dev)

 

# 書上的代碼

'''

for i in range(N-1, len(c)):

if i+N<len(c):

dev = c[i:i+N]

else:

dev = c[-N:]

 

averages = np.zeros(N)

averages.fill(sma[i-N-1])

dev = dev-averages

dev = dev ** 2

dev = np.sqrt(np.mean(dev))

deviation.append(dev)

'''

 

deviation = 2 * np.array(deviation)

# 每個sma的元素應對應一個標注差

print len(deviation), len(sma)

upperBB = sma + deviation

lowerBB = sma - deviation

 

c_slice = c[N-1:]

# 檢驗數據是否全都落入上軌和下軌內

between_bands = np.where((c_slice<upperBB)&(c_slice>lowerBB))

 

print lowerBB[between_bands]

print c[between_bands]

print upperBB[between_bands]

between_bands = len(np.ravel(between_bands))

print "Ratio between bands", float(between_bands)/len(c_slice)

 

# 繪圖,這個就比較簡單了

t = np.arange(N-1, len(c))

plt.plot(t, c_slice, lw=1.0)

plt.plot(t, sma, lw=2.0)

plt.plot(t, upperBB, lw=3.0)

plt.plot(t, lowerBB, lw=3.0)

plt.show()

結果如下:

書上的代碼略有不同,但我並沒有看懂,而是照着自己的理解,根據布林帶的規則寫的,如果大家發現有什么問題,或者我的寫法是錯誤的,希望能及時的提醒我,也好及時更改(*^_^*)

Example13

線性模型,Numpy里的linalg包是專門用來處理此類問題,今后還會接觸

# 用線性模型預測價格

 

# 用於預測所取的樣本量

N = 5

 

c = np.loadtxt("D:\Learn\Code\python\exercise\data.csv", delimiter=',', usecols = (6, ), unpack=True)

# 取后N個數

b = c[-N:]

# 倒序

b = b[::-1]

print "b", b

 

# 初始化一個N*N的二維數組A

A = np.zeros((N,N), float)

print "Zeros N by N", A

 

# A[i]與b對應

for i in range(N):

A[i, ] = c[-N-1-i:-1-i]

 

print "A", A

 

# lstsq函數擬合數據,返回值包括系數向量、殘差數組、A的秩以及A的奇異值

(x, residuals, rank, s) = np.linalg.lstsq(A, b)

 

print x, residuals, rank, s

 

# x提供系數,dot點積即可預測下一次股價

print np.dot(b, x)

結果如下:

實際查得下一個交易日收盤價為353.56,說明股票市場還是很不規律的

Example14

數組的修剪和壓縮

# 數組的修剪和壓縮

 

# clip返回一個修剪過的數組,小於等於給定最小值的設為給定最小值,反之亦然

a = np.arange(5)

print "a=", a

print "Clipped", a.clip(1, 2)

 

# compress返回一個給定篩選條件后的數組

print "Compressed", a.compress(a>2)

結果也是比較明顯:

Example15

階乘

# 階乘

b = np.arange(1, 9)

print "b=", b

# 一個prod()函數即可,省略了循環

print "Factorial", b.prod()

 

# cumprod函數可以計算累計乘積

print "Factorials", b.cumprod()

看結果:

總結:從這次的筆記中可以看到,Numpy的確是很大程度上拓展了Python的統計功能,很多時候你所需要做的無非只是寫個函數名,直接調用即可,Matplotlib同時提供了個性化很強的繪圖功能,兩者集成就可以實現很好的數據可視化。當然,這里的幾個例子無非只是拋磚引玉,接下來的學習之路還很漫長。

 

源代碼在這里:https://github.com/Lucifer25/Learn-Python/blob/master/Numpy/exercise2.py

 

參考資料:http://docs.scipy.org/doc/numpy/reference/

http://matplotlib.org/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM