说到这个最重要的类了。这个类说白了就是策略的实现。和绝大部分回测框架一样,策略想法是一个类的抽象,一般会继承一个基础类模板,每一个真实运行的策略就是这个策略想法类的一个实例。好的,有点绕。我们来看代码吧。
在vn.py中,每一个策略类开始不出意外都是下面这样的:
1、类的定义和类变量
class TRStrategy(CtaTemplate):
"""学习版本"""
className = 'TRStrategy'
author = u'lyx'
首先,这个策略继承了一个叫做CtaTemplate的父类,然后设定了策略的名称和作者。这里,在nvpy的框架下,策略的className要和策略的类名一样。
vnpy作者的例子中,喜欢用类变量来设置一些策略的参数,个人觉得其实不是很合适。Vnpy中的作者的demo一般直接在后面会有策略的变量:
atrLength = 22 # 计算ATR指标的窗口数
atrMaLength = 10 # 计算ATR均线的窗口数
rsiLength = 5 # 计算RSI的窗口数
rsiEntry = 16 # RSI的开仓信号
也就是说这些变量是类变量,而不是实例变量。如果大家的python基础不太好的话。。。所谓的类变量就是这个变量保存在类的存储空间中,只要有一个地方改变了,所有这个类的实例都会变;但是实例类是属于实例的内存空间的,实例1和实例2的实例变量没有半毛钱关系,但是如果在一个实例中改变了对于的类变量,那么另一个实例的类变量的值也是会变的,因为,保存在类的变量空间中!这也就是为什么个人觉得这些参数放在初始化函数中更加合适的原因了,要不然有可能会有意外的情况发生。所以,我们就来看一下初始化函数吧。
2.类的初始化函数
def __init__(self, ctaEngine, setting):
"""Constructor"""
super(TRStrategy, self).__init__(ctaEngine, setting)
# 创建K线合成器对象
self.bg = BarGenerator(self.onBar)
self.bg30 = BarGenerator(self.onBar, 30, self.on30minBar)
self.am = ArrayManager()
初始化函数比较有意思,会干三件事情,首先是获得一个ctaEngine,也就是把cta引擎放进去,这个可以是回测的也可以是实盘的。这里,会把这个回测引擎绑定进来,并且传给父类。但是这个其实是有问题的,最好不要这么显示的传递。后面就是构建了k线合成器和k线管理器。其中,k线管理器是后面策略的核心。
3、策略的初始化函数
然后是初始化,不是类的初始化,而是策略的初始化函数。这个很好理解,初始化一个策略那么就是很简单的把参数初始化,同时把需要初始化的数据读出来。注意到一点,这里通过loadBar函数获取初始化需要的数据之后调用onBar函数。那么回测的逻辑相对好理解,实盘的逻辑呢