如何用对象继承来减少量化策略代码量
在真格量化的 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)" 该不会犯晕了吧?
来源: http://www.bubuko.com/infodetail-3018980.html