1. 程式人生 > >如何用Python的面向對象編程方法節約代碼

如何用Python的面向對象編程方法節約代碼

行為 pytho 程序員 屬性 對象繼承 obj 何事 技術分享 子類

如何用對象繼承來減少量化策略代碼量


在真格量化的API文檔裏我們經常遇到“bal.CashBalance”、“order.id”這類看起來非常詭異的變量寫法。這都是些什麽東西呢?
技術分享圖片
技術分享圖片

這得從“面向對象”(Object Oriented)的編程思想說起。

首先,”對象“可以是我們想研究的任何事物,從一個自然數到一個星系,都可以視為對象。它不僅可以是具體的事物,比如一噸大豆,還可以是更抽象的規則,比如大豆期貨合約。

其次,對象具有狀態和行為。我們可以用各種數值來描述對象的狀態,如對於大豆期貨合約,可以有合約乘數、交割日期、當前價格等等。對象也有對應的行為,或者操作,比如對於大豆期貨合約,我們可以買入、賣出、開倉、平倉、交割等等。我們可以把這些狀態和行為都和這個對象關聯起來。

再次,對於具有相近特性、類似行為的對象,我們可以將其歸為一類,比如豆粕期貨合約在很多屬性和行為上與大豆期貨合約頗為相似。我們可以將它們都歸為“期貨合約”這個類別。豆粕期貨合約、大豆期貨合約等等合約的抽象就是期貨合約這個“類”。“期貨合約”這個類的具體化,可以是大豆期貨或者豆粕期貨這個“對象”。

技術分享圖片

最後,我們可以通過各種“方法”(比如期貨合約的買賣、查詢)來對對象進行操作,並且獲取各種“信息”(比如合約乘數、買賣狀態)。

還是以期貨合約為例,我們要用Python創建一個“期貨合約”的“類”:

技術分享圖片

其中init()方法是一種特殊的方法,被稱為類的初始化方法,當創建了這個類的實例時就會調用該方法。

有了期貨合約“Contract”這個類,我們可以在這個類裏通過“初始化方法”(即輸入合約名和合約乘數)創建幾個對象,也就是具體的期貨合約:

比如我們用以下語句創建了三個期貨合約對象:

con1=Contract("M.DCE",10)

con2=Contract("IF.CFFEX",300)

con3=Contract("TA.CZCE",5)

現在我們可以調用displayContrac方法就能顯示這些合約的名稱和合約乘數(我們用“.”來連接對象名和其屬性或方法,也就是”對象名.屬性“或者”對象名.方法“):

con1.displayContract()

con2.displayContract()

con3.displayContract()

結果顯示為:

Contract Name : M.DCE , multiplier: 10

Contract Name : IF.CFFEX , multiplier: 300

Contract Name : TA.CZCE , multiplier: 5

我們還可以通過Contract.ContractCount來訪問“類變量”,這裏是對合約數量的計數:

print "total contracts %d" % Contract.ContractCount

結果顯示為:

3

因為我們一共建立了3個合約對象。

對於期貨合約這個類在初始化時還沒有的屬性,我們也可以輕易地增加,比如我們設定合約1也就是con1的價格為2555:

con1.price=2555

然後我們可以用getattr(對象名,屬性名)來訪問這個屬性,或者更簡潔地,用”變量名.屬性名“來直接訪問:

print "price is %d" % getattr(con1,‘price‘)

或者

print "price is %d" % con1.price

結果都是

price is 2555

我們還可以通過GetContractValue方法來計算合約的價值(合約價格乘以合約乘數):

print con1.GetContractValue()

結果為:

25550

面向對象的編程帶來的主要好處之一是代碼的重用,實現這種重用的方法之一是通過繼承機制。比如我們可以再定義一個“期權合約”類來作為”期貨合約“類的“子類”:

技術分享圖片

子類的定義方法為:

class 子類名(父類名):

............

我們可以先創建一個期權合約對象(創建時包含合約代碼、合約乘數、對應期貨合約代碼):

op1=Options("OM.DCE",10,"M.DCE")

然後設定其價格:

op1.price=20

然後可以直接調用GetContractValue方法來求合約價值:

op1.displayContract()

輸出為:

200

也就是20×10.

雖然我們並未在期權合約類中去定義GetContractValue方法,但是期權合約類從期貨合約類直接繼承了GetContractValue方法,不勞我們寫一行代碼(這對程序員來說是絕佳的體驗),可以說是非常省事了!

技術分享圖片

知道了Python面向對象的編程方法,下次您再看到“context.accounts["回測期貨"].GetOrder(order.id)”該不會犯暈了吧?

技術分享圖片

如何用Python的面向對象編程方法節約代碼