之前在讲MainEngine的时候,有这样一个代码:
me.addApp(ctaStrategy)
这里,我们来看一下MainEngine里面这个addApp函数的代码:
def addApp(self, appModule):
"""添加上层应用"""
appName = appModule.appName
# 创建应用实例
self.appDict[appName] = appModule.appEngine(self, self.eventEngine)
# 将应用引擎实例添加到主引擎的属性中
self.__dict__[appName] = self.appDict[appName]
# 保存应用信息
d = {
'appName': appModule.appName,
'appDisplayName': appModule.appDisplayName,
'appWidget': appModule.appWidget,
'appIco': appModule.appIco
}
self.appDetailList.append(d)
我发现,不管是变量命名还是整个过程,都和gateway很像,所以后面分析起来应该会很容易。
同样的,我们看一下ctaStrategy的内容。同样的,在vnpy/trader/app/ctaStrategy文件夹下面的init文件中,是这样的代码:
from .ctaEngine import CtaEngine
from .uiCtaWidget import CtaEngineManager
appName = 'CtaStrategy'
appDisplayName = u'CTA策略'
appEngine = CtaEngine
appWidget = CtaEngineManager
appIco = 'cta.ico'
我们看一下,appEngine到底是一个怎么样的类。其实就是CtaEngine,
我们大致看一下这个类是怎么实现的。
class CtaEngine(AppEngine):
"""CTA策略引擎"""
settingFileName = 'CTA_setting.json'
settingfilePath = getJsonPath(settingFileName, __file__)
STATUS_FINISHED = set([STATUS_REJECTED, STATUS_CANCELLED, STATUS_ALLTRADED])
#----------------------------------------------------------------------
def __init__(self, mainEngine, eventEngine):
"""Constructor"""
self.mainEngine = mainEngine
self.eventEngine = eventEngine
# 当前日期
self.today = todayDate()
# 保存策略实例的字典
# key为策略名称,value为策略实例,注意策略名称不允许重复
self.strategyDict = {}
# 保存vtSymbol和策略实例映射的字典(用于推送tick数据)
# 由于可能多个strategy交易同一个vtSymbol,因此key为vtSymbol
# value为包含所有相关strategy对象的list
self.tickStrategyDict = {}
# 保存vtOrderID和strategy对象映射的字典(用于推送order和trade数据)
# key为vtOrderID,value为strategy对象
self.orderStrategyDict = {}
# 本地停止单编号计数
self.stopOrderCount = 0
# stopOrderID = STOPORDERPREFIX + str(stopOrderCount)
# 本地停止单字典
# key为stopOrderID,value为stopOrder对象
self.stopOrderDict = {} # 停止单撤销后不会从本字典中删除
self.workingStopOrderDict = {} # 停止单撤销后会从本字典中删除
# 保存策略名称和委托号列表的字典
# key为name,value为保存orderID(限价+本地停止)的集合
self.strategyOrderDict = {}
# 成交号集合,用来过滤已经收到过的成交推送
self.tradeSet = set()
# 引擎类型为实盘
self.engineType = ENGINETYPE_TRADING
# 注册日式事件类型
self.mainEngine.registerLogEvent(EVENT_CTA_LOG)
# 注册事件监听
self.registerEvent()
我们发现,ctaEngine类的初始化函数居然要传入MainEngine和EventEngine,感觉有那么点点乱。。。init函数中,前面都比较简单,就是初始化了一些内部有使用的变量,从最后一个函数入手,注册事件监听。我们看一下这个方法:
def registerEvent(self):
"""注册事件监听"""
self.eventEngine.register(EVENT_TICK, self.processTickEvent)
self.eventEngine.register(EVENT_ORDER, self.processOrderEvent)
self.eventEngine.register(EVENT_TRADE, self.processTradeEvent)
所以,我们现在只要考察这几个事件回调方法就可以了。
具体的这几个方法的内容就不说了。这个类当中处理这些process开头的回调函数之外,还有其他的方法,用于产生下单、撤单之类的事件。这些方法包括:sendOrder、cancelOrder、sendStopOrder、cancelStopOrder。
我们以sendOrder为例,