官术网_书友最值得收藏!

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

主站蜘蛛池模板: 拉孜县| 山阳县| 六盘水市| 呈贡县| 获嘉县| 鄯善县| 灵石县| 石首市| 玉溪市| 广南县| 门头沟区| 嫩江县| 德兴市| 垦利县| 林州市| 从化市| 桑植县| 武城县| 江永县| 通山县| 天台县| 新河县| 贵德县| 新余市| 密山市| 专栏| 鹤峰县| 财经| 伊吾县| 湖南省| 丰宁| 南川市| 荥阳市| 扎赉特旗| 花莲市| 泸州市| 瑞金市| 思茅市| 望谟县| 平潭县| 改则县|