vnpy/vn.trader/ctaAlgo/ctaDemo.py
chenxy123 42df562e60 初步完成了vn.trader的CTA策略模块,和vn.strategy相比的主要变化包括:
1. 重新设计的策略引擎API
2. 重新设计的策略模板,策略方面的开发更直观
3. 设计了一个基于EMA双均线的演示策略
4. 基于新的策略模板重写了行情记录工具DataRecorder
2016-02-04 20:41:37 +08:00

184 lines
6.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# encoding: UTF-8
"""
这里的Demo是一个最简单的策略实现并未考虑太多实盘中的交易细节
1. 委托价格超出涨跌停价导致的委托失败
2. 委托未成交,需要撤单后重新委托
3. 断网后恢复交易状态
4. 等等
这些点是作者选择特意忽略不去实现因此想实盘的朋友请自己多多研究CTA交易的一些细节
做到了然于胸后再去交易对自己的money和时间负责。
也希望社区能做出一个解决了以上潜在风险的Demo出来。
"""
from ctaBase import *
from ctaTemplate import CtaTemplate
########################################################################
class DoubleEmaDemo(CtaTemplate):
"""双指数均线策略Demo"""
className = 'DoubleEmaDemo'
author = u'用Python的交易员'
# 策略参数
fastK = 0.9 # 快速EMA参数
slowK = 0.1 # 慢速EMA参数
initDays = 10 # 初始化数据所用的天数
# 策略变量
bar = None
barMinute = EMPTY_STRING
fastMa = [] # 快速EMA均线数组
fastMa0 = EMPTY_FLOAT # 当前最新的快速EMA
fastMa1 = EMPTY_FLOAT # 上一根的快速EMA
slowMa = [] # 与上面相同
slowMa0 = EMPTY_FLOAT
slowMa1 = EMPTY_FLOAT
# 参数列表,保存了参数的名称
paramList = ['name',
'className',
'author',
'vtSymbol',
'fastK',
'slowK']
# 变量列表,保存了变量的名称
varList = ['inited',
'trading',
'pos',
'fastMa0',
'fastMa1',
'slowMa0',
'slowMa1']
#----------------------------------------------------------------------
def __init__(self, ctaEngine, setting):
"""Constructor"""
super(DoubleEmaDemo, self).__init__(ctaEngine, setting)
#----------------------------------------------------------------------
def onInit(self):
"""初始化策略(必须由用户继承实现)"""
self.writeCtaLog(u'双EMA演示策略初始化')
initData = self.loadBar(self.initDays)
for bar in initData:
self.onBar(bar)
self.putEvent()
#----------------------------------------------------------------------
def onStart(self):
"""启动策略(必须由用户继承实现)"""
self.writeCtaLog(u'双EMA演示策略启动')
self.putEvent()
#----------------------------------------------------------------------
def onStop(self):
"""停止策略(必须由用户继承实现)"""
self.writeCtaLog(u'双EMA演示策略停止')
self.putEvent()
#----------------------------------------------------------------------
def onTick(self, tick):
"""收到行情TICK推送必须由用户继承实现"""
# 计算K线
tickMinute = tick.datetime.minute
if tickMinute != self.barMinute:
if self.bar:
self.onBar(self.bar)
bar = CtaBarData()
bar.vtSymbol = tick.vtSymbol
bar.symbol = tick.symbol
bar.exchange = tick.exchange
bar.open = tick.lastPrice
bar.high = tick.lastPrice
bar.low = tick.lastPrice
bar.close = tick.lastPrice
bar.date = tick.date
bar.time = tick.time
bar.datetime = tick.datetime # K线的时间设为第一个Tick的时间
# 实盘中用不到的数据可以选择不算,从而加快速度
#bar.volume = tick.volume
#bar.openInterest = tick.openInterest
self.bar = bar # 这种写法为了减少一层访问,加快速度
self.barMinute = tickMinute # 更新当前的分钟
else: # 否则继续累加新的K线
bar = self.bar # 写法同样为了加快速度
bar.high = max(bar.high, tick.lastPrice)
bar.low = min(bar.low, tick.lastPrice)
bar.close = tick.lastPrice
#----------------------------------------------------------------------
def onBar(self, bar):
"""收到Bar推送必须由用户继承实现"""
# 计算快慢均线
if not self.fastMa0:
self.fastMa0 = bar.close
self.fastMa.append(self.fastMa0)
else:
self.fastMa1 = self.fastMa0
self.fastMa0 = bar.close * self.fastK + self.fastMa0 * (1 - self.fastK)
self.fastMa.append(self.fastMa0)
if not self.slowMa0:
self.slowMa0 = bar.close
self.slowMa.append(self.slowMa0)
else:
self.slowMa1 = self.slowMa0
self.slowMa0 = bar.close * self.slowK + self.slowMa0 * (1 - self.slowK)
self.slowMa.append(self.slowMa0)
# 判断买卖
crossOver = self.fastMa0>self.slowMa0 and self.fastMa1<self.slowMa1 # 金叉上穿
crossBelow = self.fastMa0<self.slowMa0 and self.fastMa1>self.slowMa1 # 死叉下穿
# 金叉和死叉的条件是互斥
# 所有的委托均以K线收盘价委托这里有一个实盘中无法成交的风险考虑添加对模拟市价单类型的支持
if crossOver:
# 如果金叉时手头没有持仓,则直接做多
if self.pos == 0:
self.buy(bar.close, 1)
# 如果有空头持仓,则先平空,再做多
elif self.pos < 0:
self.cover(bar.close, 1)
self.buy(bar.close, 1)
# 死叉和金叉相反
elif crossBelow:
if self.pos == 0:
self.short(bar.close, 1)
elif self.pos > 0:
self.sell(bar.close, 1)
self.short(bar.close, 1)
# 发出状态更新事件
self.putEvent()
#----------------------------------------------------------------------
def onOrder(self, order):
"""收到委托变化推送(必须由用户继承实现)"""
# 对于无需做细粒度委托控制的策略可以忽略onOrder
pass
#----------------------------------------------------------------------
def onTrade(self, trade):
"""收到成交推送(必须由用户继承实现)"""
# 对于无需做细粒度委托控制的策略可以忽略onOrder
pass