- 量化投資:交易模型開發(fā)與數(shù)據(jù)挖掘
- 韓燾
- 8764字
- 2020-04-03 12:56:59
2.3 量化平臺(tái)常用語(yǔ)言—Python
在量化平臺(tái)中,既有用戶比較熟悉的Python語(yǔ)言,也有現(xiàn)在用途不太廣泛的Matlab語(yǔ)言,當(dāng)然,無(wú)論哪種語(yǔ)言,只有用戶能很好地應(yīng)用才行。出于對(duì)系統(tǒng)維護(hù)升級(jí)的考慮,建議選擇Python語(yǔ)言進(jìn)行開發(fā)。
2.3.1 Python簡(jiǎn)介
Python語(yǔ)言的創(chuàng)始人吉多·范羅蘇姆(Guido van Rossum)是一名荷蘭計(jì)算機(jī)程序員。1989年范羅蘇姆在阿姆斯特丹,為了打發(fā)圣誕節(jié)的無(wú)趣,決心開發(fā)一個(gè)新的腳本解釋程序,來(lái)作為ABC語(yǔ)言的繼承。Python語(yǔ)言的名字被譯為大蟒蛇是因?yàn)榉读_蘇姆很喜歡看一個(gè)英國(guó)電視節(jié)目“Monty Python”(飛行馬戲團(tuán)),從20世紀(jì)90年代初Python語(yǔ)言誕生至今,它已被逐漸廣泛應(yīng)用于系統(tǒng)管理任務(wù)的處理和Web編程中。
Python是由ABC、Modula-3、C、C++、Algol-68、SmallTalk、UNIX Shell及其他的腳本語(yǔ)言發(fā)展而來(lái)的。
Python是一個(gè)高層次的結(jié)合了解釋性、編譯性、互動(dòng)性的面向?qū)ο蟮哪_本語(yǔ)言,可以應(yīng)用于Web開發(fā)、Internet開發(fā)、科學(xué)計(jì)算和統(tǒng)計(jì)、教育、桌面界面開發(fā)、軟件開發(fā)、后端開發(fā)等領(lǐng)域。而且在開發(fā)過(guò)程中沒有編譯環(huán)節(jié)。類似于PHP和Perl語(yǔ)言。可以在一個(gè)Python提示符(>>>)后直接執(zhí)行代碼。相比其他編程語(yǔ)言經(jīng)常使用英文關(guān)鍵字和一些特殊的標(biāo)點(diǎn)符號(hào)而言,它更具有特色語(yǔ)法結(jié)構(gòu),是一種交互式語(yǔ)言。它支持面向?qū)ο蟮娘L(fēng)格或?qū)⒋a封裝在對(duì)象的編程技術(shù)。
Python已經(jīng)成為非常受歡迎的程序設(shè)計(jì)語(yǔ)言。從2004年以后,Python的使用率呈線性增長(zhǎng)。在2019年3月TIOBE的編程語(yǔ)言排行榜中,Java繼續(xù)保持第一名,而Python超越C++排在第三名,如圖2-5所示。

圖2-5
2.3.2 量化基礎(chǔ)語(yǔ)法及數(shù)據(jù)結(jié)構(gòu)
Python的基礎(chǔ)語(yǔ)法包括如下幾種。
1.Python標(biāo)識(shí)符
在Python里,標(biāo)識(shí)符由字母、數(shù)字、下畫線組成,所有標(biāo)識(shí)符可以包括字母、數(shù)字及下畫線(_),但不能以數(shù)字開頭。Python中的標(biāo)識(shí)符區(qū)分大小寫。
以下畫線開頭的標(biāo)識(shí)符是有特殊意義的。
· 以單下畫線開頭(_foo),代表不能直接訪問(wèn)的類屬性,需通過(guò)類提供的接口進(jìn)行訪問(wèn),不能用from xxx import * 來(lái)導(dǎo)入。
· 以雙下畫線開頭(__foo),代表類的私有成員。
·以雙下畫線開頭和結(jié)尾(__foo__),代表Python里特殊方法專用的標(biāo)識(shí),如__init__()代表類的構(gòu)造函數(shù)。
Python有5種標(biāo)準(zhǔn)的數(shù)據(jù)類型:Numbers(數(shù)字)、String(字符串)、List(列表)、Tuple(元組)和Dictionary(字典)。
Python支持4種不同的數(shù)字類型:int(符號(hào)整型)、long(長(zhǎng)整型,也可以代表八進(jìn)制數(shù)和十六進(jìn)制數(shù))、float(浮點(diǎn)型)和complex(復(fù)數(shù))。
Python的字符串列表有兩種取值順序:從左到右索引默認(rèn)是從0開始的,最大范圍是字符串長(zhǎng)度減1、從右到左索引默認(rèn)是從-1開始的,最大范圍是字符串開頭。
List(列表)是Python中使用最頻繁的數(shù)據(jù)類型。
列表可以完成大多數(shù)集合類的數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)。它支持字符、數(shù)字、字符串,甚至可以包含列表(即嵌套)。列表用“[]”標(biāo)識(shí),是Python最通用的復(fù)合數(shù)據(jù)類型。列表中值的切割也可以用到變量 [頭下標(biāo):尾下標(biāo)],從而可以截取相應(yīng)的列表,從左到右索引默認(rèn)從0開始,從右到左索引默認(rèn)從-1開始,下標(biāo)可以為空,表示取到頭或尾。
加號(hào)(+)是列表連接運(yùn)算符,星號(hào)(*)表示重復(fù)操作,如表2-1所示。
表2-1

Python包含的方法及其描述如表2-2所示。
表2-2

元組是另一個(gè)數(shù)據(jù)類型,類似于列表。元組用“()”標(biāo)識(shí)。內(nèi)部元素用逗號(hào)隔開。但是元組不能進(jìn)行二次賦值,相當(dāng)于只讀列表。
Python的元組與列表類似,不同之處在于:元組的元素不能修改,元組使用小括號(hào),列表使用方括號(hào)。元組內(nèi)置函數(shù)及其描述如表2-3所示。
表2-3

字典是另一種可變?nèi)萜髂P停铱纱鎯?chǔ)任意類型的對(duì)象。字典用“{}”標(biāo)識(shí)。字典是除列表外,Python中最靈活的內(nèi)置數(shù)據(jù)結(jié)構(gòu)類型。
列表是有序的對(duì)象集合,字典是無(wú)序的對(duì)象集合。兩者之間的區(qū)別在于:字典當(dāng)中的元素是通過(guò)鍵存取的,而不是通過(guò)偏移存取的。
字典由索引(key)和它對(duì)應(yīng)的值value組成。字典的每個(gè)鍵值(key/value)對(duì)用冒號(hào)(:)分隔,整個(gè)字典包括在大括號(hào)({})中。
Python字典包含的內(nèi)置函數(shù)及其描述如表2-4所示。
表2-4

Python字典包含的內(nèi)置方法及其描述如表2-5所示。
表2-5

2.Python數(shù)據(jù)類型轉(zhuǎn)換
有時(shí)候,我們需要對(duì)數(shù)據(jù)內(nèi)置的類型進(jìn)行轉(zhuǎn)換,進(jìn)行數(shù)據(jù)類型的轉(zhuǎn)換,只需要將數(shù)據(jù)類型作為函數(shù)名即可。
表2-6中列舉的內(nèi)置函數(shù)可以執(zhí)行數(shù)據(jù)類型之間的轉(zhuǎn)換。這些函數(shù)將返回一個(gè)新的對(duì)象,表示轉(zhuǎn)換的值。
表2-6

3.Python運(yùn)算符
Python中的運(yùn)算符包括算術(shù)運(yùn)算符、比較(關(guān)系)運(yùn)算符、賦值運(yùn)算符、邏輯運(yùn)算符、位運(yùn)算符、成員運(yùn)算符、身份運(yùn)算符、運(yùn)算符優(yōu)先級(jí)。
· Python算術(shù)運(yùn)算符如表2-7所示(假設(shè)變量a為10,變量b為20)。
表2-7

· Python比較運(yùn)算符如表2-8所示(假設(shè)變量a為10,變量b為20)。
表2-8

· Python賦值運(yùn)算符如表2-9所示。
表2-9

· Python位運(yùn)算符如表2-10所示。
表2-10

表2-10中變量a為60, b為13,二進(jìn)制格式如下:
a = 00111100 b = 00001101 —————— a&b = 00001100 a|b = 00111101 a^b = 00110001 ~a = 11000011
· Python成員運(yùn)算符如表2-11所示。
除了以上的一些運(yùn)算符,Python還支持成員運(yùn)算符,測(cè)試實(shí)例中包括了一系列的成員,包括字符串、列表或元組。
表2-11

4.Python循環(huán)語(yǔ)句
· Python提供了for循環(huán)和while循環(huán)(在Python中沒有do…while循環(huán)),如表2-12所示。
表2-12

· 循環(huán)控制語(yǔ)句可以更改語(yǔ)句執(zhí)行的順序。Python支持的循環(huán)控制語(yǔ)句如表2-13所示。
表2-13

5.Python函數(shù)
· Python數(shù)學(xué)函數(shù)及其描述如表2-14所示。
表2-14

· 隨機(jī)數(shù)可以用于數(shù)學(xué)、游戲、安全等領(lǐng)域中,還經(jīng)常被嵌入到算法中,用以提高算法效率,并提高程序的安全性。Python隨機(jī)函數(shù)及其描述如表2-15所示。隨機(jī)函數(shù)用于產(chǎn)生隨機(jī)數(shù)。
表2-15

· Python三角函數(shù)及其描述如表2-16所示。
表2-16

· 匿名函數(shù)lambda。
Python使用lambda來(lái)創(chuàng)建匿名函數(shù)。lambda只是一個(gè)表達(dá)式,函數(shù)體比def簡(jiǎn)單很多。lambda的主體是一個(gè)表達(dá)式,而不是一個(gè)代碼塊。僅僅能在lambda表達(dá)式中封裝有限的邏輯進(jìn)去。
lambda函數(shù)擁有自己的命名空間,并且不能訪問(wèn)自有參數(shù)列表之外或全局命名空間里的參數(shù)。雖然lambda函數(shù)看起來(lái)只能寫一行,卻不等同于C語(yǔ)言或C++語(yǔ)言的內(nèi)聯(lián)函數(shù),內(nèi)聯(lián)函數(shù)的目的是調(diào)用小函數(shù)時(shí)不占用棧內(nèi)存從而增加運(yùn)行效率。
示例代碼如下:
sum = lambda arg1, arg2: arg1 + arg2; print "相加后的值為 : ", sum( 10, 20 ) //輸出30
6.Python數(shù)學(xué)常量
· Python數(shù)學(xué)常量如表2-17所示。
表2-17

7.Python字符串
· 當(dāng)需要在字符中使用特殊字符時(shí),Python使用反斜杠(\)來(lái)表示,稱為轉(zhuǎn)義字符,如表2-18所示。
表2-18

· Python字符串運(yùn)算符如表2-19所示。
其中,實(shí)例變量a值為字符串 "Hello",變量b值為"Python"。
表2-19

· Python字符串格式化。
Python支持格式化字符串的輸出。盡管這樣可能會(huì)用到非常復(fù)雜的表達(dá)式,但最基本的用法是將一個(gè)值插入一個(gè)有字符串格式符 %s的字符串中。
在Python中,字符串格式化使用的語(yǔ)法與C語(yǔ)言中sprintf()函數(shù)一樣。
示例代碼如下:
#! /usr/bin/Python print "My name is %s and weight is %d kg! " % ('BROWN',33)
以上示例輸出結(jié)果如下:
My name is BROWN and weight is 33 kg!
Python字符串格式化符號(hào)及其描述如表2-20所示。
表2-20

8.Python import語(yǔ)句
· from...import語(yǔ)句。
Python的from語(yǔ)句可以從模塊中導(dǎo)入一個(gè)指定的部分到當(dāng)前命名空間中。語(yǔ)句如下:
from modname import name1[, name2[, ... nameN]]
例如,要導(dǎo)入模塊fib的fibonacci函數(shù),可以使用如下語(yǔ)句:
from fib import fibonacci
這個(gè)聲明不會(huì)把整個(gè)fib模塊導(dǎo)入當(dāng)前的命名空間中,它只會(huì)將fib里的fibonacci單個(gè)引入到執(zhí)行這個(gè)聲明的模塊的全局符號(hào)表中。
· from...import*語(yǔ)句。
把一個(gè)模塊的所有內(nèi)容全都導(dǎo)入當(dāng)前的命名空間也是可行的,只需使用如下語(yǔ)句:
from modname import*
這提供了一個(gè)簡(jiǎn)單的方法來(lái)導(dǎo)入一個(gè)模塊中的所有項(xiàng)目。然而這種聲明不可以被過(guò)多地使用。
例如,我們想一次性引入math模塊中所有的東西,語(yǔ)句如下:
from math import*
9.Python文件操作
1)打開和關(guān)閉文件
Python提供了必要的函數(shù)和方法對(duì)文件進(jìn)行基本的操作。可以使用file對(duì)象對(duì)大部分的文件進(jìn)行操作。
· open()函數(shù)。
用戶必須先用Python內(nèi)置的open()函數(shù)打開一個(gè)文件,創(chuàng)建一個(gè)與file對(duì)象相關(guān)的方法才可以調(diào)用該函數(shù)進(jìn)行讀/寫操作。
語(yǔ)句如下:
file object = open(file_name [, access_mode][, buffering])
各個(gè)參數(shù)的說(shuō)明如下。
? file_name:包含了一個(gè)要訪問(wèn)的文件名稱的字符串值。
? access_mode:決定了打開文件的模式,包括只讀、寫入、追加等。所有可取值如表2-21所示。這個(gè)參數(shù)是非強(qiáng)制的,默認(rèn)文件訪問(wèn)模式為只讀(r)。
? buffering:如果buffering的值被設(shè)為0,就不會(huì)有寄存。如果buffering的值被設(shè)為1,訪問(wèn)文件時(shí)會(huì)寄存行。如果buffering的值被設(shè)為大于1的整數(shù),表明這就是寄存區(qū)的緩沖大小。如果buffering的值被設(shè)為負(fù)值,寄存區(qū)的緩沖大小則為系統(tǒng)默認(rèn)。
表2-21

file對(duì)象的屬性:當(dāng)一個(gè)文件被打開后,將會(huì)有一個(gè)file對(duì)象,并且可以得到有關(guān)該文件的各種信息。與file對(duì)象相關(guān)的所有屬性列表如表2-22所示。
表2-22

· close()方法:file對(duì)象的close()方法可以刷新緩沖區(qū)里任何還沒有寫入的信息,并關(guān)閉該文件,這之后便不能再進(jìn)行寫入。
當(dāng)一個(gè)文件對(duì)象的引用被重新指定給另一個(gè)文件時(shí),Python會(huì)關(guān)閉之前的文件。用close()方法關(guān)閉文件是一個(gè)很好的習(xí)慣。
語(yǔ)句如下:
fileObject.close();
· write()方法:將任何字符串寫入一個(gè)打開的文件中。需要重點(diǎn)注意的是,Python字符串可以是二進(jìn)制數(shù)據(jù),而不僅僅是文字。
write()方法不會(huì)在字符串的結(jié)尾添加換行符('\n')。
語(yǔ)句如下:
fileObject.write(string);
· read()方法:從一個(gè)打開的文件中讀取一個(gè)字符串。需要重點(diǎn)注意的是,Python字符串可以是二進(jìn)制數(shù)據(jù),而不僅僅是文字。
語(yǔ)句如下:
fileObject.read([count]);
· tell()方法:tell()方法指定文件內(nèi)的當(dāng)前位置;換句話說(shuō),下一次的讀/寫會(huì)發(fā)生在文件開頭的字節(jié)之后。
· seek(offset[, from])方法:改變當(dāng)前文件的位置。offset變量表示要移動(dòng)的字節(jié)數(shù)。from變量指定開始移動(dòng)字節(jié)的參考位置。
如果from被設(shè)為0,這意味著將文件的開頭作為移動(dòng)字節(jié)的參考位置;如果from被設(shè)為1,則使用當(dāng)前的位置作為參考位置;如果from被設(shè)為2,那么將該文件的末尾作為參考位置。
2)重命名和刪除文件
Python的OS模塊提供了執(zhí)行文件處理操作的方法,比如重命名和刪除文件。要使用這個(gè)模塊,必須先導(dǎo)入它,然后才可以調(diào)用相關(guān)的功能。
· remove()方法:可以使用remove()方法刪除文件,需要將要?jiǎng)h除的文件名作為參數(shù)。
Python里的所有文件都包含在各個(gè)不同的目錄下,即使這樣Python也能輕松處理。OS模塊提供了許多創(chuàng)建、刪除和更改目錄的方法。
· mkdir()方法:可以使用OS模塊的mkdir()方法在當(dāng)前目錄下創(chuàng)建新的目錄。用戶需要提供一個(gè)包含了要?jiǎng)?chuàng)建的目錄名稱的參數(shù)。
語(yǔ)句如下:
os.mkdir("newdir")
· chdir()方法:可以使用chdir()方法來(lái)更改當(dāng)前的目錄。chdir()方法需要的一個(gè)參數(shù)是:想設(shè)成當(dāng)前目錄的目錄名稱。
語(yǔ)句如下:
os.chdir("newdir")
· rmdir()方法:可以使用rmdir()方法刪除目錄,目錄名稱以參數(shù)傳遞。
在刪除某個(gè)目錄之前,這個(gè)目錄中的所有內(nèi)容應(yīng)該先被清除。
語(yǔ)句如下:
os.rmdir('dirname')
file對(duì)象方法和OS對(duì)象方法可以對(duì)Windows和UNIX操作系統(tǒng)上的文件及目錄進(jìn)行廣泛且實(shí)用的處理及操控。
· file對(duì)象方法:file對(duì)象提供了操作文件的一系列方法。
· OS對(duì)象方法:OS對(duì)象提供了處理文件及目錄的一系列方法。
10.Python file方法
file對(duì)象使用open()函數(shù)來(lái)創(chuàng)建,file對(duì)象常用的函數(shù)及其描述如表2-23所示。
表2-23

使用Python語(yǔ)言需要注意以下問(wèn)題。
· 大小寫敏感:即字母是區(qū)分大小寫的。所以如果把前面例子代碼中的若干個(gè)字母從小寫變成大寫,系統(tǒng)將會(huì)報(bào)錯(cuò)。
· 要用英文字符:冒號(hào)、逗號(hào)、分號(hào)、括號(hào)、引號(hào)等各種符號(hào)必須用英文,使用中文字符將會(huì)報(bào)錯(cuò)。
· 注釋:為了讓人們更好地理解代碼的含義,通常都會(huì)在代碼中寫入注釋。注釋是給人看的,計(jì)算機(jī)會(huì)忽略(需要注意的是,空行也會(huì)被忽略),所以用中文記錄思路也是可以的。筆者強(qiáng)烈建議養(yǎng)成寫注釋的好習(xí)慣。注釋的寫法為“#”,表示會(huì)把所在行的其后所有內(nèi)容設(shè)定為注釋。
舉例如下。
解決Python中不能輸入漢字的問(wèn)題,我們?cè)赑ython的IDE中有時(shí)候會(huì)輸入中文,Python對(duì)中文不太友好。在一般情況下,在代碼前加入“# coding: utf-8”就可以了。示例代碼如下:
# coding: utf-8 reload(sys) sys.setdefaultencoding("utf-8")
11.Python數(shù)據(jù)類型
1)列表(List)
在Python中沒有數(shù)組的概念,與數(shù)組最接近的概念就是列表和元組。列表是用來(lái)存儲(chǔ)一連串元素的容器,用“[]”來(lái)表示。例如,可以用序列表示數(shù)據(jù)庫(kù)中一個(gè)人的信息,第一個(gè)元素是姓名,第二個(gè)元素是年齡,根據(jù)上述內(nèi)容定義一個(gè)列表(列表元素通過(guò)逗號(hào)分隔,寫在方括號(hào)中),示例代碼如下:
# 定義一個(gè)列表,列表是一個(gè)可變序列 edward = ['Edward Gumby',42] # 打印列表 edward
以上示例輸出結(jié)果如下:
['Edward Gumby',42]
2)元組(Tuple)
在Python中與數(shù)組類似的還有元組,元組中的元素可以進(jìn)行索引計(jì)算。列表和元組的區(qū)別在于:列表中元素的值可以修改,而元組中元素的值不可以修改,只可以讀取;另外,列表的符號(hào)是“[]”,而元組的符號(hào)是“()”。示例代碼如下:
# 定義一個(gè)元組,元組是一個(gè)不可變序列 tom = ('Tom Teddy',37) # 打印元組 tom
以上示例輸出結(jié)果如下:
('Tom Teddy',37)
3)字典(Dictionary)
在Python中,字典也叫作關(guān)聯(lián)數(shù)組,可以理解為列表的升級(jí)版,用大括號(hào)括起來(lái),格式為{key1: value1, key2: value2, …, keyn: valuen},即字典的每個(gè)鍵值(key/value)對(duì)用冒號(hào)分隔,每個(gè)對(duì)之間用逗號(hào)分隔,整個(gè)字典包括在大括號(hào)中。示例代碼如下:
# 定義一個(gè)字典,字典是一個(gè)由鍵值對(duì)構(gòu)成的序列 age = {’張三’:27, ’李四’:29} # 打印字典 print(age)
以上示例輸出結(jié)果如下:
{’張三’:27, ’李四’:29}
4)字符串或串(String)
字符串或串是由數(shù)字、字母、下畫線組成的一串字符。一般記為s=“a1a2…an”(n≥0)。它在編程語(yǔ)言中表示文本的數(shù)據(jù)類型。在程序設(shè)計(jì)中,字符串為符號(hào)或數(shù)值的一個(gè)連續(xù)序列,如符號(hào)串(一串字符)或二進(jìn)制數(shù)字串(一串二進(jìn)制數(shù)字)。示例代碼如下:
# Python數(shù)據(jù)類型:字符串、整數(shù)、浮點(diǎn)數(shù) a = ’中國(guó)’ b = 25 c = 3.14
5)軟件包(numPy)
軟件包是Python的一個(gè)擴(kuò)展程序庫(kù),支持大量的維度數(shù)組與矩陣運(yùn)算,此外它也針對(duì)數(shù)組運(yùn)算提供了大量的數(shù)學(xué)函數(shù)庫(kù)。示例代碼如下:
# 軟件包numpy例子 # 導(dǎo)入庫(kù) import numpy as np # 創(chuàng)建一個(gè)3*5的多維數(shù)組(數(shù)據(jù)類型) a = np.arange(15).reshape(3, 5) a
輸出結(jié)果如下:
array([[ 0, 1, 2, 3, 4], [ 5, 6, 7, 8, 9], [10, 11, 12, 13, 14]])
再舉一個(gè)例子,代碼如下:
# 軟件包pandas例子 # 導(dǎo)入庫(kù) import numpy as np import pandas as pd df = pd.DataFrame([’張三’, ’李四’, ’王五’], columns = {’姓名’}, index = {1,2,3}) df
輸出結(jié)果如圖2-6所示。

圖2-6
2.3.3 量化中函數(shù)的定義及使用方法
Python中的函數(shù)是組織好的,可重復(fù)使用的,用來(lái)實(shí)現(xiàn)單一或相關(guān)聯(lián)功能的代碼段。它能提高應(yīng)用的模塊性能和代碼的重復(fù)利用率。支持遞歸、默認(rèn)參數(shù)值、可變參數(shù),但不支持函數(shù)重載。Python提供了許多內(nèi)建函數(shù),如print()。但也可以自己創(chuàng)建函數(shù),稱為用戶自定義函數(shù)。
定義一個(gè)想要實(shí)現(xiàn)某種功能的函數(shù),要遵循以下規(guī)則。
函數(shù)代碼塊以def關(guān)鍵詞開頭,后接函數(shù)標(biāo)識(shí)符名稱和小括號(hào)。任何傳入?yún)?shù)和自變量必須放在小括號(hào)中間。小括號(hào)之間可以定義參數(shù)。函數(shù)的第一行語(yǔ)句可以選擇性地使用文檔字符串—用于存放函數(shù)說(shuō)明。函數(shù)內(nèi)容以冒號(hào)起始,并且縮進(jìn)。例如,return [表達(dá)式]結(jié)束函數(shù),選擇性地返回一個(gè)值給調(diào)用方。不帶表達(dá)式的return返回None。
1.函數(shù)語(yǔ)法
Python定義函數(shù)使用def關(guān)鍵字,一般格式如下:
def函數(shù)名 (參數(shù)列表): 函數(shù)體
在默認(rèn)情況下,參數(shù)值和參數(shù)名稱是按函數(shù)聲明中定義的順序進(jìn)行匹配的。
例如,使用函數(shù)來(lái)輸出"Hello BROWN! ",示例代碼如下:
def hell(): print("Hello BROWN! ") hell() x = itertools.compress(range(5), (True, False, True, True, False)) print(list(x)) Hello BROWN!
舉一個(gè)更復(fù)雜的例子,在函數(shù)中帶上參數(shù)變量,示例代碼如下:
# 計(jì)算面積函數(shù) def area(width, height): return width * height def print_welcome(name): print("Welcome", name) print_welcome("Runoob") w = 7 h = 8 print("width = ", "height ", h, "area ", area(w, h))
以上示例輸出結(jié)果如下:
('Welcome', 'Runoob') ('width = ', 'height ', 8, 'area ', 56)
2.函數(shù)調(diào)用
定義一個(gè)函數(shù):賦予函數(shù)一個(gè)名稱,指定函數(shù)里包含的參數(shù)和代碼塊結(jié)構(gòu)。
這個(gè)函數(shù)的基本結(jié)構(gòu)完成以后,可以通過(guò)另一個(gè)函數(shù)調(diào)用執(zhí)行,也可以直接使用Python命令提示符執(zhí)行。
調(diào)用printme() 函數(shù)的示例代碼如下:
# 定義函數(shù) def printme (str): # 打印任何傳入的字符串 print (str) return # 調(diào)用函數(shù) printme("調(diào)用王東澤函數(shù)!") printme("再次調(diào)用王東澤函數(shù)")
以上示例輸出結(jié)果如下:
調(diào)用王東澤函數(shù)! 再次調(diào)用王東澤函數(shù)
sort()函數(shù)用于對(duì)原列表進(jìn)行排序,如果指定參數(shù),則使用比較函數(shù)指定的函數(shù)。
sort()語(yǔ)句如下:
list.sort(key = None, reverse = False)
參數(shù)說(shuō)明如下。
· key:主要是用來(lái)進(jìn)行比較的元素,只有一個(gè)參數(shù),具體函數(shù)的參數(shù)取自可迭代對(duì)象,指定可迭代對(duì)象中的一個(gè)元素來(lái)進(jìn)行排序。
· reverse:排序規(guī)則,reverse = True表示降序,reverse = False表示升序(默認(rèn))。sort()函數(shù)沒有返回值,但是會(huì)對(duì)列表的對(duì)象進(jìn)行排序。
以下示例展示了sort() 函數(shù)的使用方法:
aList = [’量化網(wǎng)’, ’優(yōu)礦’, ’谷歌’, ’百度’] aList.sort() print ( "List : ", aList)
以上示例輸出結(jié)果如下:
aList = [’量化網(wǎng)’, ’優(yōu)礦’, ’谷歌’, ’百度’]
以下示例按降序輸出列表:
# 列表 vowels = ['d', 'r', 'w', 'c', 'q'] # 降序 vowels.sort(reverse=True) # 輸出結(jié)果 print(’降序輸出:', vowels)
以上示例輸出結(jié)果如下:
降序輸出: ['w', 'r', 'q', 'd', 'c']
以下示例演示了通過(guò)指定列表中的元素排序來(lái)輸出列表:
# 獲取列表第二個(gè)元素 def takeSecond(elem): return elem[1] # 列表 random = [(7,6), (3,5), (4,7), (2,1)] # 指定第二個(gè)元素排序 random.sort(key = takeSecond) # 輸出類別 print (’排序列表: ', random)
以上示例輸出結(jié)果如下:
排序列表: [(2, 1), (3, 5), (7, 6), (4, 7)]
2.3.4 面向?qū)ο缶幊蘋OP的定義及使用方法
Python從設(shè)計(jì)之初就是一門面向?qū)ο蟮恼Z(yǔ)言,所以很容易在Python中創(chuàng)建一個(gè)類和對(duì)象。
對(duì)象:以類為單位來(lái)管理所有代碼。對(duì)象包括兩個(gè)數(shù)據(jù)成員(類變量和實(shí)例變量)和方法。并且加入了類機(jī)制,可以包含任意數(shù)量和類型的數(shù)據(jù)。
Python中的類是對(duì)象的“抽象部分”,提供了面向?qū)ο缶幊痰乃谢竟δ埽侯惖睦^承機(jī)制允許有多個(gè)基類,派生類可覆蓋基類方法,方法中可調(diào)用基類的同名方法。
語(yǔ)法格式如下:
class ClassName: <statement-1> . . . <statement-N>
將類實(shí)例化可以使用其屬性,即創(chuàng)建一個(gè)類之后,可以通過(guò)類名訪問(wèn)其屬性。
類對(duì)象支持屬性引用和實(shí)例化兩種操作方法。其屬性引用使用的語(yǔ)法為:obj.name。類對(duì)象創(chuàng)建后,所有的命名都是有效屬性名。類定義代碼如下:
class MyClass: """一個(gè)簡(jiǎn)單的類實(shí)例""" i = 3.14159265 def f(self): return 'hello BROWN' # 實(shí)例化類 x = MyClass() # 訪問(wèn)類的屬性和方法 print("MyClass類的屬性i為: ", x.i) print("MyClass類的方法f輸出為: ", x.f())
以上代碼創(chuàng)建了一個(gè)新的類實(shí)例并將該對(duì)象賦給局部變量x, x是一個(gè)空的對(duì)象。
執(zhí)行以上代碼后,輸出的結(jié)果如下:
MyClass類的屬性i為: 3.14159265 MyClass類的方法f輸出為: hello BROWN
類有一個(gè)名為 __init__()的特殊構(gòu)造方法,該方法在類實(shí)例化時(shí)可自動(dòng)調(diào)用,例如:
def __init__(self): self.data = []
類定義了__init__()方法,類的實(shí)例化操作會(huì)自動(dòng)調(diào)用__init__()方法。例如,實(shí)例化類MyClass,對(duì)應(yīng)的__init__()方法就會(huì)被調(diào)用,例如:
x = MyClass()
__init__() 方法也可以設(shè)置參數(shù),參數(shù)可以通過(guò) __init__()傳遞到類。例如:
class Complex: def __init__(self, realpart, imagpart): self.r = realpart self.i = imagpart x = Complex(7.8, -2.6) print(x.r, x.i)
執(zhí)行以上代碼后,輸出的結(jié)果如下:
(7.8, -2.6)
self代表類的實(shí)例而不是類。類的方法必須有一個(gè)額外的第一個(gè)參數(shù)名稱,按照慣例它的名稱是self。這是與普通函數(shù)的唯一區(qū)別。例如:
class Test: def prt(self): print(self) print(self.__class__) t = Test() t.prt()
執(zhí)行以上代碼后,輸出的結(jié)果如下:
<__main__.Test object at 0x000001C9FBB43F60> <class'__main__.Test'>
在類的內(nèi)部,如果使用def關(guān)鍵字來(lái)定義一個(gè)方法就必須包含參數(shù)self,且為第一個(gè)參數(shù),self代表的是類的實(shí)例。這一點(diǎn)與一般函數(shù)的定義不同。
# 類定義 class people: # 定義基本屬性 name = '' age = 0 # 定義私有屬性,私有屬性在類外部無(wú)法直接進(jìn)行訪問(wèn) __weight = 0 # 定義構(gòu)造方法 def __init__(self, n, a, w): self.name = n self.age = a self.__weight = w def speak(self): print("%s說(shuō):王東澤 %d歲。" %(self.name, self.age)) # 實(shí)例化類 p = people('runoob',31,30) p.speak()
執(zhí)行以上代碼后,輸出的結(jié)果如下:
runoob說(shuō):王東澤 31歲。
· 單繼承:Python支持類的繼承,否則類就失去了意義。單繼承的類定義如下:
class DerivedClassName(BaseClassName1): <statement-1> . . . <statement-N>
注意小括號(hào)中基類的順序,如果基類中有相同的方法名,而子類使用時(shí)未指定,Python將從左到右搜索,即方法在子類中未找到時(shí),可以從左到右查找基類中是否包含方法。
BaseClassName(示例中的基類名)必須與派生類定義在一個(gè)作用域內(nèi)。基類定義在另一個(gè)模塊中時(shí)表達(dá)式非常有用,代碼如下:
class DerivedClassName(modname.BaseClassName):
示例代碼如下:
# 類定義 class people: # 定義基本屬性 name = '' age = 0 # 定義私有屬性,私有屬性在類外部無(wú)法直接進(jìn)行訪問(wèn) __weight = 0 # 定義構(gòu)造方法 def __init__(self, n, a, w): self.name = n self.age = a self.__weight = w def speak(self): print("%s說(shuō):我 %d歲。" %(self.name, self.age)) # 單繼承 class student(people): grade = '' def __init__(self, n, a, w, g): # 調(diào)用父類的構(gòu)造方法 people.__init__(self, n, a, w) self.grade = g # 覆寫父類的方法 def speak(self): print("%s說(shuō):王東澤 %d歲了,王東澤在讀 %d年級(jí)博士后"%(self.name, self. age, self.grade)) s = student('ken',31,60,2) s.speak()
執(zhí)行以上代碼后,輸出的結(jié)果如下:
ken說(shuō):王東澤 31歲了,王東澤在讀 2年級(jí)博士后
· 多繼承:Python同樣支持多繼承形式。多繼承的類定義如下:
class DerivedClassName(Base1, Base2, Base3): <statement-1> . . . <statement-N>
需要注意小括號(hào)中父類的順序,若父類中有相同的方法名,而在子類使用時(shí)未指定,Python將從左到右搜索,即方法在子類中未找到時(shí),從左到右查找父類中是否包含方法。從單繼承到多繼承的示例代碼如下:
# 類定義 class people: # 定義基本屬性 name = '' age = 0 # 定義私有屬性,私有屬性在類外部無(wú)法直接進(jìn)行訪問(wèn) __weight = 0 # 定義構(gòu)造方法 def __init__(self, n, a, w): self.name = n self.age = a self.__weight = w def speak(self): print("%s說(shuō):我 %d歲。" %(self.name, self.age)) # 單繼承 class student(people): grade = '' def __init__(self, n, a, w, g): # 調(diào)用父類的構(gòu)造方法 people.__init__(self, n, a, w) self.grade = g # 覆寫父類的方法 def speak(self): print("%s說(shuō):我 %d歲了,我在讀 %d年級(jí)"%(self.name, self.age, self.grade)) # 定義另一個(gè)類 class speaker(): topic = '' name = '' def __init__(self, n, t): self.name = n self.topic = t def speak(self): print("我叫 %s,我是一名作家,我的寫作主題是 %s"%(self.name, self.topic)) # 多繼承 class sample(speaker, student): a ='' def __init__(self, n, a, w, g, t): student.__init__(self, n, a, w, g) speaker.__init__(self, n, t) test = sample("王東澤",25,80,4, "Python") test.speak() # 與方法名相同,默認(rèn)調(diào)用的是在括號(hào)中排名靠前的父類的方法
執(zhí)行以上程序后,輸出的結(jié)果如下:
我叫 王東澤,我是一名作家,我的寫作主題是Python
2.3.5 itertools的使用方法
itertools迭代器(生成器)是Python中一種很常用也很好用的數(shù)據(jù)結(jié)構(gòu),與列表相比,迭代器最大的優(yōu)勢(shì)就是延遲計(jì)算、按需使用,從而提高開發(fā)者的體驗(yàn)度和運(yùn)行效率。所以在Python3中map、filter等操作返回的不再是列表而是迭代器。經(jīng)常用到的迭代器是range,但是通過(guò)iter()函數(shù)把列表對(duì)象轉(zhuǎn)化為迭代器對(duì)象會(huì)多此一舉,所以使用itertools更合適一些。
itertools中的函數(shù)大多會(huì)返回各種迭代器對(duì)象,其中很多函數(shù)的作用需要我們寫很多代碼才能發(fā)揮,在運(yùn)行效率上很低,因?yàn)槠涫窍到y(tǒng)庫(kù)。下面列舉itertools的使用方法。
itertools.accumulate表示累加。例如:
import itertools x = itertools.accumulate(range(10)) print(list(x))
執(zhí)行以上程序后,輸出的結(jié)果如下:
[0, 1, 3, 6, 10, 15, 21, 28, 36, 45]
itertools.chain表示連接多個(gè)列表或迭代器。例如:
x = itertools.chain(range(3), range(4), [3,2,1]) print(list(x))
執(zhí)行以上程序后,輸出的結(jié)果如下:
[0, 1, 2, 0, 1, 2, 3, 3, 2, 1]
itertools.combinations_with_replacement表示允許重復(fù)元素的組合。例如:
x = itertools.combinations_with_replacement('ABC', 2) print(list(x))
執(zhí)行以上程序后,輸出的結(jié)果如下:
[('A', 'A'), ('A', 'B'), ('A', 'C'), ('B', 'B'), ('B', 'C'), ('C', 'C')]
itertools.compress表示按照真值表篩選元素。例如:
x = itertools.compress(range(5), (True, False, True, True, False)) print(list(x))
執(zhí)行以上程序后,輸出的結(jié)果如下:
[0, 2, 3]
itertools.count是一個(gè)計(jì)數(shù)器,可以指定起始位置和步長(zhǎng)。例如:
x = itertools.count(start=20, step=-1) print(list(itertools.islice(x, 0, 10, 1)))
執(zhí)行以上程序后,輸出的結(jié)果如下:
[20, 19, 18, 17, 16, 15, 14, 13, 12, 11]
itertools.dropwhile表示按照真值函數(shù),丟棄列表和迭代器前面的元素。例如:
x = itertools.dropwhile(lambda e: e < 5, range(10)) print(list(x))
執(zhí)行以上程序后,輸出的結(jié)果如下:
[5, 6, 7, 8, 9]
itertools.filterfalse表示保留對(duì)應(yīng)真值為False的元素。例如:
x = itertools.filterfalse(lambda e: e < 5, (1, 5, 3, 6, 9, 4)) print(list(x))
執(zhí)行以上程序后,輸出的結(jié)果如下:
[5, 6, 9]
itertools.groupby表示按照分組函數(shù)的值對(duì)元素進(jìn)行分組。例如:
x = itertools.groupby(range(10), lambda x: x < 5 or x > 8) for condition, numbers in x: print(condition, list(numbers))
執(zhí)行以上程序后,輸出的結(jié)果如下:
(True, [0, 1, 2, 3, 4]) (False, [5, 6, 7, 8]) (True, [9])
itertools.islice表示對(duì)迭代器進(jìn)行切片操作。例如:
x = itertools.islice(range(10), 0, 9, 2) print(list(x))
執(zhí)行以上程序后,輸出的結(jié)果如下:
[0, 2, 4, 6, 8]
itertools.permutations返回可迭代對(duì)象的所有數(shù)學(xué)全排列方式。例如:
x = itertools.permutations(range(4), 3) print(list(x))
執(zhí)行以上程序后,輸出的結(jié)果如下:
[(0, 1, 2), (0, 1, 3), (0, 2, 1), (0, 2, 3), (0, 3, 1), (0, 3, 2), (1, 0, 2), (1, 0, 3), (1, 2, 0), (1, 2, 3), (1, 3, 0), (1, 3, 2), (2, 0, 1), (2, 0, 3), (2, 1, 0), (2, 1, 3), (2, 3, 0), (2, 3, 1), (3, 0, 1), (3, 0, 2), (3, 1, 0), (3, 1, 2), (3, 2, 0), (3, 2, 1)]
itertools.repeat表示簡(jiǎn)單地生成一個(gè)擁有指定數(shù)目元素的迭代器。例如:
x = itertools.repeat(0, 5) print(list(x))
執(zhí)行以上程序后,輸出的結(jié)果如下:
[0, 0, 0, 0, 0]
itertools.starmap與map類似。例如:
x = itertools.starmap(str.islower, 'aBCDefGhI') print(list(x))
執(zhí)行以上程序后,輸出的結(jié)果如下:
[True, False, False, False, True, True, False, True, False]
itertools.takewhile與dropwhile相反,保留元素直到真值函數(shù)值為假。例如:
x = itertools.takewhile(lambda e: e < 5, range(10)) print(list(x))
執(zhí)行以上程序后,輸出的結(jié)果如下:
[0, 1, 2, 3, 4]
itertools.zip_longest與zip類似,但是需要以較長(zhǎng)的列表和迭代器的長(zhǎng)度為準(zhǔn)。例如:
x = itertools.zip_longest(range(3), range(5)) y = zip(range(3), range(5)) print(list(x))
執(zhí)行以上程序后,輸出的結(jié)果如下:
[(0, 0), (1, 1), (2, 2), (None, 3), (None, 4)] [(0, 0), (1, 1), (2, 2)]
2.4 量化投資工具—Matplotlib
Matplotlib是Python 2D-繪圖領(lǐng)域使用非常廣泛的套件。它能讓使用者輕松地將數(shù)據(jù)圖形化,并且提供多樣化的輸出格式。下面來(lái)介紹Matplotlib的常見用法。
讀者要想使用Python繪制K線圖最好在Anaconda網(wǎng)站下載安裝包。安裝步驟如下。
(1)單擊“Windows”然后單擊“64-Bit Graphical Installer(614.3MB)”,如圖2-7所示。

圖2-7
(2)點(diǎn)擊相應(yīng)鏈接進(jìn)行下載,并選擇保存的文件夾,下載完成后,即可在文件夾中找到下載的安裝包,如圖2-8所示。

圖2-8
(3)雙擊安裝包文件,在彈出的安裝對(duì)話框中單擊“Next”按鈕,然后單擊“I Agree”按鈕,如圖2-9所示。

圖2-9
(4)根據(jù)提示繼續(xù)單擊相應(yīng)按鈕進(jìn)行安裝。直到出現(xiàn)如圖2-10右圖所示的對(duì)話框,然后依次單擊“Install Microsoft VSCode”→“Cancel”按鈕,完成安裝。

圖2-10
Matplotlib僅需要幾行代碼,便可以生成繪圖、直方圖、功率譜、條形圖、錯(cuò)誤圖、散點(diǎn)圖等。
2.4.1 Matplotlib基礎(chǔ)知識(shí)
Matplotlib的基礎(chǔ)知識(shí)如下。
(1)Matplotlib中基本圖表的元素包括x軸和y軸、水平和垂直的軸線。
x軸和y軸使用刻度對(duì)坐標(biāo)軸進(jìn)行分隔,包括最小刻度和最大刻度;x軸和y軸刻度標(biāo)簽表示特定坐標(biāo)軸的值、繪圖區(qū)域等。
(2)hold屬性默認(rèn)為True,允許在一幅圖中繪制多條曲線。
(3)使用grid方法為圖添加網(wǎng)格線,方法為設(shè)置grid參數(shù)(參數(shù)與plot()函數(shù)相同), lw代表linewidth(線的粗細(xì)), Alpha表示線的明暗程度。
(4)axis方法如果沒有任何參數(shù),則返回當(dāng)前坐標(biāo)軸的上下限。
(5)除了plt.axis方法,還可以通過(guò)xlim、ylim方法設(shè)置坐標(biāo)軸范圍。
(6)legend方法如下。
· 初級(jí)繪制。
這一節(jié)中,我們將從簡(jiǎn)到繁:先嘗試用默認(rèn)配置在同一張圖上繪制正弦函數(shù)和余弦函數(shù)圖像,然后逐步美化它。
首先取得正弦函數(shù)和余弦函數(shù)的值,示例代碼如下:
from pylab import * X = np.linspace(-np.pi, np.pi, 256, endpoint=True) C, S = np.cos(X), np.sin(X)
X是一個(gè)numpy數(shù)組,包含了-π到+π之間的256個(gè)值。C和S分別是這256個(gè)值對(duì)應(yīng)的余弦函數(shù)和正弦函數(shù)值組成的numpy數(shù)組。
· 使用默認(rèn)配置。
Matplotlib的默認(rèn)配置允許用戶進(jìn)行自定義。可以調(diào)整大多數(shù)的默認(rèn)配置:圖片大小和分辨率(dpi)、線條寬度、顏色、風(fēng)格、坐標(biāo)軸、網(wǎng)格的屬性、文字和字體屬性等。不過(guò),Matplotlib的默認(rèn)配置在大多數(shù)情況下已經(jīng)做得足夠好了,可能只有在特殊的情況下才會(huì)想要更改這些默認(rèn)配置。示例代碼如下:
import numpy as np import matplotlib.pyplot as plt X = np.linspace(-np.pi, np.pi, 256, endpoint=True) C, S = np.cos(X), np.sin(X) plot(X, C) plot(X, S) show()
執(zhí)行以上程序后,輸出的結(jié)果如圖2-11所示(由于本書是黑白印刷,涉及的顏色無(wú)法在書中呈現(xiàn),請(qǐng)讀者結(jié)合軟件界面進(jìn)行辨識(shí))。

圖2-11
在下面的代碼中,我們展現(xiàn)了Matplotlib的默認(rèn)配置并輔以注釋說(shuō)明,這部分配置包含了有關(guān)繪圖樣式的所有配置。代碼中的配置與默認(rèn)配置完全相同,可以在交互模式中修改其中的值來(lái)觀察效果:
# 導(dǎo)入Matplotlib的所有內(nèi)容 from pylab import * # 創(chuàng)建一個(gè) 9*7 點(diǎn)陣圖,并設(shè)置分辨率為80像素 figure(figsize=(9,7), dpi=80) # 創(chuàng)建一個(gè)新的 1*1 的子圖,接下來(lái)的圖樣繪制在其中的第1 塊 subplot(1,1,1) X = np.linspace(-np.pi, np.pi, 256, endpoint=True) C, S = np.cos(X), np.sin(X) # 繪制余弦曲線,使用藍(lán)色的、連續(xù)的、寬度為1 像素的線條 plot(X, C, color="blue", linewidth=1.0, linestyle="-") # 繪制正弦曲線,使用綠色的、連續(xù)的、寬度為1 像素的線條 plot(X, S, color="green", linewidth=1.0, linestyle="-") # 設(shè)置橫軸的上下限 xlim(-3.0,3.0) # 設(shè)置橫軸記號(hào) xticks(np.linspace(-3,3,9, endpoint=True)) # 設(shè)置縱軸的上下限 ylim(-1.0,1.0) # 設(shè)置縱軸記號(hào) yticks(np.linspace(-2,2,5, endpoint=True)) # 以分辨率 72像素來(lái)保存圖片 # savefig("exercice_2.png", dpi=72) # 在屏幕上顯示 show()
執(zhí)行以上程序后,輸出的結(jié)果如圖2-12所示(由于本書是黑白印刷,涉及的顏色無(wú)法在書中呈現(xiàn),請(qǐng)讀者結(jié)合軟件界面進(jìn)行辨識(shí))。

圖2-12
現(xiàn)在來(lái)改變線條的顏色和粗細(xì)。我們首先以藍(lán)色和紅色分別表示余弦函數(shù)和正弦函數(shù),然后將線條變粗一點(diǎn),接下來(lái),我們以水平方向拉伸整個(gè)圖。示例代碼如下:
figure(figsize=(10,6), dpi=70) plot(X, C, color="blue", linewidth=2.5, linestyle="-") plot(X, S, color="red", linewidth=2.5, linestyle="-")
執(zhí)行以上程序后,輸出的結(jié)果如圖2-13所示(由于本書是黑白印刷,涉及的顏色無(wú)法在書中呈現(xiàn),請(qǐng)讀者結(jié)合軟件界面進(jìn)行辨識(shí))。

圖2-13
2.4.2 Matplotlib可視化工具基礎(chǔ)
可視化工具可以高效獲取信息。人眼是一個(gè)高帶寬的巨量信號(hào)輸入并行處理器,具有超強(qiáng)的模式識(shí)別能力,對(duì)可視符號(hào)的感知速度比對(duì)數(shù)字或文本快多個(gè)數(shù)量級(jí),而可視化就是迎合了人眼的這種特點(diǎn),才使得獲取信息的難度大大降低。這才會(huì)有“一圖勝千言”的說(shuō)法,一堆數(shù)據(jù)很難快速看明白,但生成圖形就會(huì)一目了然。比如用圖來(lái)表達(dá)國(guó)際象棋與圍棋的復(fù)雜度,如圖2-14所示。

圖2-14
可視化工具可以輔助人們?cè)谌四X之外保存待處理信息,從而補(bǔ)充人腦有限的記憶內(nèi)存,提高信息認(rèn)知的效率。雖然人們能夠有意識(shí)地集中注意力,但不能長(zhǎng)時(shí)間保持視覺搜索的高效狀態(tài)。而圖形化符號(hào)可以高效地傳遞信息,將用戶的注意力引導(dǎo)到重要的目標(biāo)上。
可視化的作用體現(xiàn)在多個(gè)方面,如揭示想法和關(guān)系、形成論點(diǎn)或意見、觀察事物演化的趨勢(shì)、總結(jié)或積聚數(shù)據(jù)、存檔和整理、尋求真相和真理、傳播知識(shí)和探索性數(shù)據(jù)分析等。
在計(jì)算機(jī)學(xué)科的分類中,利用人眼的感知能力對(duì)數(shù)據(jù)進(jìn)行交互的可視表達(dá),以增強(qiáng)認(rèn)知的技術(shù),稱為可視化。它將不可見或難以直接顯示的數(shù)據(jù)轉(zhuǎn)化為可感知的圖形、符號(hào)、顏色、紋理等,來(lái)增強(qiáng)數(shù)據(jù)識(shí)別效率,傳遞有效信息。
如果要同時(shí)繪制多個(gè)圖表,可以給figure() 傳遞一個(gè)整數(shù)參數(shù)來(lái)指定Figure對(duì)象的序號(hào),如果序號(hào)所指定的Figure對(duì)象已經(jīng)存在,只需要讓它成為當(dāng)前的Figure對(duì)象即可。示例代碼如下:
import numpy as np # 創(chuàng)建圖表1和圖表2 plt.figure(1) plt.figure(2) # 在圖表2中創(chuàng)建子圖1和子圖2 ax1 = plt.subplot(211) ax2 = plt.subplot(212) x = np.linspace(0, 3, 100) for i in xrange(5): # 選擇圖表1 plt.figure(1) plt.plot(x, np.exp(i*x/3)) plt.sca(ax1) # 選擇圖表2的子圖1 plt.plot(x, np.sin(i*x)) plt.sca(ax2) # 選擇圖表2的子圖2 plt.plot(x, np.cos(i*x))
執(zhí)行以上程序后,輸出的結(jié)果如圖2-15所示。

圖2-15
2.4.3 Matplotlib子畫布及l(fā)oc的使用方法
定義畫布的方法如下:
import matplotlib.pyplot as plt Populating the interactive namespace from numpy and matplotlib
Matplotlib的圖像都位于Figure畫布中,可以使用plt.figure創(chuàng)建一個(gè)新畫布。
如果要在一個(gè)圖表中繪制多個(gè)子圖,可使用subplot,示例代碼如下:
# 創(chuàng)建一個(gè)新的Figure fig = plt.figure() #不能通過(guò)空Figure繪圖,必須用add_subplot創(chuàng)建一個(gè)或多個(gè)subplot ax1 = fig.add_subplot(2, 2, 1) ax2 = fig.add_subplot(2, 2, 2) ax3 = fig.add_subplot(2, 2, 3) from numpy.random import randn # 沒有指定具體subplot的繪圖命令時(shí),會(huì)在最后一個(gè)用過(guò)的subplot上進(jìn)行繪制 plt.plot(randn(50).cumsum(), 'k--') _ = ax1.hist(randn(100), bins=25, color='k', alpha=0.4) # 這里加分號(hào)可以屏蔽不必要的輸出 ax2.scatter(np.arange(50), np.arange(50) + 3*randn(50)) ;
執(zhí)行以上代碼后,輸出的結(jié)果如圖2-16所示。

圖2-16
使用上述命令可以繪制一些圖例,并可用豐富的數(shù)學(xué)符號(hào)進(jìn)行標(biāo)注,還可在一個(gè)畫布里容納多個(gè)子圖形,這些都是很常用的功能。
在一張圖中顯示多個(gè)子圖,示例代碼如下:
# sub = 子 x = np.arange(-10, 10, 0.1) plt.figure(figsize=(12, 9)) # 1行3列的第1個(gè)子圖 axes = plt.subplot(1, 3, 1) axes.plot(x, np.sin(x)) # 設(shè)置網(wǎng)格顏色、樣式、寬度 axes.grid(color='r', linestyle='--', linewidth=2) # 1行3列的第2個(gè)子圖 axes2 = plt.subplot(1, 3, 2) axes2.plot(x, np.cos(x)) # 設(shè)置網(wǎng)格顏色、樣式、寬度 axes2.grid(color='g', linestyle='-.', linewidth=2) # 1行3列的第3個(gè)子圖 axes3 = plt.subplot(1, 3, 3) axes3.plot(x, np.sin(x)) # 設(shè)置網(wǎng)格顏色、樣式、寬度 axes3.grid(color='b', linestyle=':', linewidth=2)
執(zhí)行以上代碼后,輸出的結(jié)果如圖2-17所示。

圖2-17
下面來(lái)繪制一個(gè)子畫布,示例代碼如下:
import matplotlib.pyplot as plt import numpy as np def f(t): return np.exp(-t) * np.cos(2 * np.pi * t) # t = np.arange(0, 5, 0.2) t1 = np.arange(0, 5, 0.1) t2 = np.arange(0, 5, 0.02) # plt.plot(t, t, 'r--', t, t ** 2, 'bs', t, t ** 3, 'g^') plt.figure(12) plt.subplot(221) plt.plot(t1, f(t1), 'bo', t2, f(t2), 'r--') plt.subplot(222) plt.plot(t2, np.cos(2 * np.pi * t2), 'r--') plt.subplot(212) plt.plot([1, 2, 3, 4, 5], [1, 5, 8, 13, 18]) plt.show()
執(zhí)行以上代碼后,輸出的結(jié)果如圖2-18所示。

圖2-18
2.5 Matplotlib繪制K線圖的方法
2.5.1 安裝財(cái)經(jīng)數(shù)據(jù)接口包(TuShare)和繪圖包(mpl_finance)
TuShare是一個(gè)開源的Python財(cái)經(jīng)數(shù)據(jù)接口包,主要實(shí)現(xiàn)對(duì)股票等金融數(shù)據(jù)從數(shù)據(jù)采集、清洗加工到數(shù)據(jù)存儲(chǔ)的過(guò)程,能夠?yàn)榻鹑诜治鋈藛T提供快速、整潔和多樣的便于分析的數(shù)據(jù),極大地減輕他們獲取數(shù)據(jù)來(lái)源方面的工作量,使他們更加專注于策略和模型的研究與實(shí)現(xiàn)上。由于Python pandas包在金融量化分析中有突出的優(yōu)勢(shì),而且TuShare返回的絕大部分?jǐn)?shù)據(jù)格式都是pandas DataFrame類型,所以非常便于用pandas、numPy、Matplotlib進(jìn)行數(shù)據(jù)分析和可視化。安裝方法如下:
pip install tushare
mpl_finance是Python中用來(lái)畫蠟燭圖、線圖的分析工具,目前已經(jīng)從Matplotlib中獨(dú)立出來(lái)。安裝方法如下:
pip install mpl_finance
2.5.2 繪制K線圖示例
我們來(lái)繪制一張000001平安銀行的股價(jià)走勢(shì)圖。該示例分為3個(gè)部分,步驟如下。
(1)粘貼或輸入如下代碼:
# 2D繪圖包Matplotlib import tushare as ts # 需要先安裝 import matplotlib.pyplot as plt from matplotlib.gridspec import GridSpec from matplotlib.pylab import date2num import mpl_finance as mpf # 需要先安裝 import datetime # 下面輸入想要的股票代碼并下載數(shù)據(jù) wdyx = ts.get_k_data('000001', '2017-01-01') # wdyx.info() # print(wdyx.head())
(2)下載完成平安銀行數(shù)據(jù)后,就可以利用這個(gè)數(shù)據(jù)繪制圖形了,示例代碼如下:
def date_to_num(dates): num_time = []# 2D繪圖包Matplotlib import tushare as ts # 需要先安裝 import matplotlib.pyplot as plt from matplotlib.gridspec import GridSpec from matplotlib.pylab import date2num import mpl_finance as mpf # 需要先安裝 import datetime # 下面輸入想要的股票代碼并下載數(shù)據(jù) wdyx = ts.get_k_data('000001', '2017-01-01') # wdyx.info() # print(wdyx.head()) def date_to_num(dates): num_time = [] for date in dates: date_time = datetime.datetime.strptime(date, '%Y-%m-%d') num_date = date2num(date_time) num_time.append(num_date) return num_time
(3)輸入股票代碼后,可以將其轉(zhuǎn)換為二維數(shù)組,示例代碼如下:
# 將Dataframe轉(zhuǎn)換為二維數(shù)組 mat_wdyx = wdyx.values num_time = date_to_num(mat_wdyx[:, 0]) mat_wdyx[:, 0] = num_time # 接下來(lái)就可以繪制K線圖了 # 畫布大小 Fig, (ax0, ax1) = plt.subplots(2, sharex=True, figsize=(15, 8)) # 調(diào)整兩個(gè)子畫布大小(兩種方法) # ax0 = plt.subplot2grid((3, 1), (0, 0), rowspan=2) # ax1 = plt.subplot2grid((3, 1), (2, 0)) gs = GridSpec(3, 1) # 調(diào)整上下間隔(兩種方法) # gs.update(hspace=0.05) plt.subplots_adjust(hspace=0.05) ax0 = plt.subplot(gs[0:2]) ax1 = plt.subplot(gs[2]) # 在第一個(gè)子畫布上畫K線,在第二個(gè)子畫布上畫量的柱線 mpf.candlestick_ochl(ax0, mat_wdyx, width=1, colorup='r', colordown='g', alpha=1.0) ax0.set_title('000001') ax0.set_ylabel('Price') ax0.grid(True) plt.bar(mat_wdyx[:, 0]-0.4, mat_wdyx[:, 5], width=0.8) ax1.xaxis_date() ax1.set_ylabel('Volume') plt.show() for date in dates: date_time = datetime.datetime.strptime(date, '%Y-%m-%d') num_date = date2num(date_time) num_time.append(num_date) return num_time # 將Dataframe轉(zhuǎn)換為二維數(shù)組 mat_wdyx = wdyx.values num_time = date_to_num(mat_wdyx[:, 0]) mat_wdyx[:, 0] = num_time # 接下來(lái)就可以繪制K線圖了 # 畫布大小 fig, (ax0, ax1) = plt.subplots(2, sharex=True, figsize=(15, 8)) # 調(diào)整兩個(gè)子畫布大小(兩種方法) # ax0 = plt.subplot2grid((3, 1), (0, 0), rowspan=2) # ax1 = plt.subplot2grid((3, 1), (2, 0)) gs = GridSpec(3, 1) # 調(diào)整上下間隔(兩種方法) # gs.update(hspace=0.05) plt.subplots_adjust(hspace=0.05) ax0 = plt.subplot(gs[0:2]) ax1 = plt.subplot(gs[2]) # 在第一個(gè)子畫布上畫K線,在第二個(gè)子畫布上畫量的柱線 mpf.candlestick_ochl(ax0, mat_wdyx, width=1, colorup='r', colordown='g', alpha=1.0) ax0.set_title('000001') ax0.set_ylabel('Price') ax0.grid(True) plt.bar(mat_wdyx[:, 0]-0.4, mat_wdyx[:, 5], width=0.8) ax1.xaxis_date() ax1.set_ylabel('Volume') plt.show()
按Ctrl+Enter快捷鍵運(yùn)行以上程序,輸出的結(jié)果如圖2-19所示。

圖2-19
- GitHub Essentials
- 文本數(shù)據(jù)挖掘:基于R語(yǔ)言
- 分布式數(shù)據(jù)庫(kù)系統(tǒng):大數(shù)據(jù)時(shí)代新型數(shù)據(jù)庫(kù)技術(shù)(第3版)
- 大數(shù)據(jù)架構(gòu)和算法實(shí)現(xiàn)之路:電商系統(tǒng)的技術(shù)實(shí)戰(zhàn)
- Instant Autodesk AutoCAD 2014 Customization with .NET
- Chef Essentials
- SQL Server深入詳解
- SIEMENS數(shù)控技術(shù)應(yīng)用工程師:SINUMERIK 840D-810D數(shù)控系統(tǒng)功能應(yīng)用與維修調(diào)整教程
- R Machine Learning Essentials
- 商業(yè)智能工具應(yīng)用與數(shù)據(jù)可視化
- MySQL技術(shù)內(nèi)幕:InnoDB存儲(chǔ)引擎
- 改進(jìn)的群智能算法及其應(yīng)用
- Flume日志收集與MapReduce模式
- Hadoop大數(shù)據(jù)技術(shù)開發(fā)實(shí)戰(zhàn)
- Reactive Programming in Kotlin