1.ctaTemplate.py
策略模板是具体交易策略的基础,一般把大部分策略都用到的方法和公共变量放到策略模板里(如:账户权益风险控制、交易合约撤单次数),而具体策略继承该策略模板,进而增加个性方法和变量(如:入场价格、止损止盈)。一般在最基础模板上,按照交易策略的类型衍生出交易类型模板(如:CTA、套利、对冲等),具体交易策略继承衍生的交易类型模板进行开发。
解决了这个问题后,我们来了解一下CtaTemplate
- import
from ctaBase import *
from vtConstant import *
ctaBase 位于vn.trader\ctaAlgo目录下(与CtaTemplate同目录)。该文件定义了些策略中会用的常量:交易方向、停止单状态、数据库的名称、及引擎的标识,另外定义了3个类:
StopOrder
相当于一般软件上本地的止损止盈单。当StopOrder中合约(vtSymbol)的tick数据更新时,CtaEngine会将满足条件的StopOrder转为交易指令发出。
CtaBarData
相当于一般行情软件上的K线图(1根K线),只是在策略中更新数据,保存在内存中而不显示出来。满足基于K线的策略需求(一般onBar触发)。
CtaTickData
同CtaBarData类似,只是他是每个tick数据(等长时间交易数据的切片)。满足基于最新价格、最高价格及最低价格(这两个价格需要结合CtaBarData数据使用)的策略需求(一般onTick触发)。
vtConstant 位于vn.trader目录下 主要定义一些常量,具体的我就不一一列举了,大家打开就很清楚了。
PS: 由于trader目前把各级地址都注册了,所以这里直接
from ctaBase import *
一般只注册根目录,从根目录下开始import,以上就要写成
from ctaAlgo.ctaBase import *
这里简单说明一下,遇到文件路径不对,按照上面两种方法处理
- init (self, ctaEngine, setting)
'init'这个函数前后都有两个下划线。传入ctaEngine实例和setting配置初始化。初始化时定义了一些变量,其中有3个这里介绍一下:
# 参数列表,保存了参数的名称
self.paramList = ['name',
'className',
'author',
'vtSymbol']
这个变量主要记录和保存策略参数,除了'author'外,其他3个必选,根据需要可以拓展,但必须要先定义,后方可添加到参数列表。
# 变量列表,保存了变量的名称
self.varList = ['inited',
'trading',
'pos']
和前面一个变量类似,但这个是变量列表,区别主要在于,该列表中变量主要记录策略交易过程中的一些状态,当然你可以根据需要拓展,设置把这些变量放在参数列表里(但建议不要这么做)。
# 设置策略的参数
if setting:
d = self.__dict__
for key in self.paramList:
if key in setting:
d[key] = setting[key]
批量读取配置文件中保存的参数进行初始化。
- onInit
在创建实例后如有需要还可以用该方法进一步的初始化
- onStart
策略启动方法,一般做一些启动提示
- onStop
策略停止方法,如,撤单、平今转平昨,结算收盘等
- onTick(self, tick)
当最新tick数据更新时,做一些计算,信号触发,当然也可以做撤单(一般不建议这么做)。收盘后一段时间后和开盘前一段时间前(一般15分钟)之间的这段时间会有垃圾数据(至少CTP是这样),建议登出账户或在策略或者引擎里自行处理。tick为实例,获取属性请使用对象方法,如,'tick.lastPrice',下面order,trade,bar皆如此。
- onOrder(self, order)
当发出单子后,就会收到单子状态的数据,无论是否成交。 可以根据回报的信息来进行撤单追单等处理。
- onTrade(self, trade)
成交数据回报。主要用来计算持仓,也可以用来触发发单追单等。
- onBar(self, bar)
一般该方法在onTick里被调用,当满足生成新K线的时候,触发该方法,进而触发基于K线的策略。
- buy(self, price, volume, stop=False)
开仓做多,默认合约为self.vtSymbol,stop为False直接发单,为True时发本地止损止赢单,默认False。
- sell(self, price, volume, stop=False)
平多
- short(self, price, volume, stop=False)
开空
- cover(self, price, volume, stop=False)
平空
- sendOrder(self, orderType, price, volume, stop=False)
def sendOrder(self, orderType, price, volume, stop=False):
"""发送委托"""
if self.trading:
# 如果stop为True,则意味着发本地停止单
if stop:
vtOrderID = self.ctaEngine.sendStopOrder(self.vtSymbol, orderType, price, volume, self)
else:
vtOrderID = self.ctaEngine.sendOrder(self.vtSymbol, orderType, price, volume, self)
return vtOrderID
else:
# 交易停止时发单返回空字符串
return ''
前面buy,sell等方法就是对这个方法的二次封装,在这个方法里区别对待本地止损止赢单和直接发交易柜台的单子。一般用的较少。
- cancelOrder(self, vtOrderID)
def cancelOrder(self, vtOrderID):
"""撤单"""
# 如果发单号为空字符串,则不进行后续操作
if not vtOrderID:
return
if STOPORDERPREFIX in vtOrderID:
self.ctaEngine.cancelStopOrder(vtOrderID)
else:
self.ctaEngine.cancelOrder(vtOrderID)
根据发单编号进行撤单,该方法根据vtOrderID来判断撤本地单子还是交易所排队的单子
- insertTick(self, tick)
向数据库中插入tick数据。对ctaEngine函数的二次封装,方便使用,以下3个也是如此
- insertBar(self, bar)
向数据库中插入bar数据
- loadTick(self, days)
根据天数读取tick数据
- loadBar(self, days)
根据天数读取bar数据
- writeCtaLog(self, content)
def writeCtaLog(self, content):
"""记录CTA日志"""
content = self.name + ':' + content
self.ctaEngine.writeCtaLog(content)
对ctaEngine日志方法进行二次封装,主要加上策略的name,用于区分多策略日志
- putEvent
发出策略状态变化信号,主要是通知监控系统(目前是GUI,后面也可以web等)
- getEngineType
区分引擎,满足不同情况的处理