vnpy/vn.strategy/strategydemo/demoStrategy.py

395 lines
14 KiB
Python
Raw Normal View History

# encoding: UTF-8
# 首先写系统内置模块
import sys
2015-09-16 07:34:00 +00:00
print u'demoStrategy.py import sys success'
from datetime import datetime, timedelta, time
2015-09-16 07:34:00 +00:00
print u'demoStrategy.py import datetime.datetime/timedelta/time success'
from time import sleep
2015-09-16 07:34:00 +00:00
print u'demoStrategy.py import time.sleep success'
# 然后是第三方库模块如PyQt4等
import sip
2015-09-16 07:34:00 +00:00
print u'demoStrategy.py import sip success'
from PyQt4 import QtCore
2015-09-16 07:34:00 +00:00
print u'demoStrategy.py import PyQt4.QtCore success'
# 然后是自己编写的模块
from demoEngine import MainEngine
2015-09-16 07:34:00 +00:00
print u'demoStrategy.py import demoEngine.MainEngine success'
from strategyEngine import *
########################################################################
class SimpleEmaStrategy(StrategyTemplate):
2015-09-28 07:29:48 +00:00
"""简单双指数移动均线EMA演示策略"""
#----------------------------------------------------------------------
def __init__(self, name, symbol, engine):
"""Constructor"""
super(SimpleEmaStrategy, self).__init__(name, symbol, engine)
# 策略在外部设置的参数
2015-10-24 00:01:02 +00:00
# self.fastAlpha = 0.2 # 快速EMA的参数
2015-09-28 07:29:48 +00:00
self.fastAlpha = 0.2
2015-10-24 00:01:02 +00:00
# self.slowAlpha = 0.05 # 慢速EMA的参数
self.slowAlpha = 0.05
# 最新TICK数据市场报价
self.currentTick = None
# K线缓存对象
self.barOpen = 0
self.barHigh = 0
self.barLow = 0
self.barClose = 0
self.barVolume = 0
self.barTime = None
# 保存K线数据的列表对象
2015-10-24 00:01:02 +00:00
# self.listOpen = []
# self.listHigh = []
# self.listLow = []
# self.listClose = []
# self.listVolume = []
# s#elf.listTime = []
# 持仓
self.pos = 0
# 报单代码列表
self.listOrderRef = [] # 报单号列表
self.listStopOrder = [] # 停止单对象列表
# EMA均线
self.fastEMA = 0 # 快速EMA的数值
self.slowEMA = 0 # 慢速EMA的数值
# 是否完成了初始化
self.initCompleted = False
# 初始化时读取的历史数据的起始日期(可以选择外部设置)
2015-10-17 16:23:24 +00:00
self.startDate = None
# Added by Incense Lee
# 属于updateMarketData推送的第一个Tick数据,忽略交易逻辑
self.firstMarketTick = True
2015-10-19 08:42:17 +00:00
self.lineBar = [] # K线数据
self.lineEMA = [] # 快速、慢速EMA数据
2015-10-17 16:23:24 +00:00
#----------------------------------------------------------------------
def loadSetting(self, setting):
"""读取参数设定"""
try:
self.fastAlpha = setting['fastAlpha']
self.slowAlpha = setting['slowAlpha']
self.engine.writeLog(self.name + u'读取参数成功')
except KeyError:
self.engine.writeLog(self.name + u'读取参数设定出错,请检查参数字典')
2015-05-28 05:52:59 +00:00
try:
self.initStrategy(setting['startDate'])
except KeyError:
self.initStrategy()
#----------------------------------------------------------------------
2015-05-28 05:52:59 +00:00
def initStrategy(self, startDate=None):
"""初始化"""
2015-09-28 07:29:48 +00:00
self.engine.writeLog(u'读取3天的历史TICK数据')
td = timedelta(days=1)
2015-05-28 05:52:59 +00:00
if startDate:
2015-10-24 00:01:02 +00:00
# 读取历史Tick数据
# cx = self.engine.loadTickFromMongo(self.symbol, startDate-td)
historyStartDate = self.engine.getMysqlDeltaDate(self.symbol,startDate,3)
2015-09-28 07:29:48 +00:00
cx = self.engine.loadTickFromMysql(self.symbol, historyStartDate, startDate-td)
2015-05-28 05:52:59 +00:00
else:
today = datetime.today().replace(hour=0, minute=0, second=0, microsecond=0)
2015-10-24 00:01:02 +00:00
# cx = self.engine.loadTickFromMongo(self.symbol, today-td)
historyStartDate = self.engine.getMysqlDeltaDate(self.symbol,today,3)
2015-09-28 07:29:48 +00:00
cx = self.engine.loadTickFromMysql(self.symbol, historyStartDate,today-td)
if cx:
for data in cx:
2015-09-28 07:29:48 +00:00
tick = Tick(data['InstrumentID'])
2015-10-24 00:01:02 +00:00
# tick = Tick(InstrumentID)
2015-09-28 07:29:48 +00:00
2015-10-24 00:01:02 +00:00
# tick.openPrice = data['OpenPrice']
# tick.highPrice = data['HighestPrice']
# tick.lowPrice = data['LowestPrice']
2015-09-28 07:29:48 +00:00
tick.lastPrice = float(data['LastPrice'])
2015-10-24 00:01:02 +00:00
tick.volume = data['Volume']
tick.openInterest = data['OpenInterest']
2015-10-24 00:01:02 +00:00
# tick.upperLimit = data['UpperLimitPrice']
# tick.lowerLimit = data['LowerLimitPrice']
2015-10-10 09:08:13 +00:00
tick.time = data['UpdateTime']
2015-10-24 00:01:02 +00:00
# tick.ms = data['UpdateMillisec']
2015-10-24 00:01:02 +00:00
tick.bidPrice1 = float(data['BidPrice1'])
# tick.bidPrice2 = data['BidPrice2']
# tick.bidPrice3 = data['BidPrice3']
# tick.bidPrice4 = data['BidPrice4']
# tick.bidPrice5 = data['BidPrice5']
2015-09-28 07:29:48 +00:00
tick.askPrice1 = float(data['AskPrice1'])
2015-10-24 00:01:02 +00:00
# tick.askPrice2 = data['AskPrice2']
# tick.askPrice3 = data['AskPrice3']
# tick.askPrice4 = data['AskPrice4']
# tick.askPrice5 = data['AskPrice5']
tick.bidVolume1 = data['BidVolume1']
2015-10-24 00:01:02 +00:00
# tick.bidVolume2 = data['BidVolume2']
# tick.bidVolume3 = data['BidVolume3']
# tick.bidVolume4 = data['BidVolume4']
# tick.bidVolume5 = data['BidVolume5']
2015-09-28 07:29:48 +00:00
tick.askVolume1 = data['AskVolume1']
2015-10-24 00:01:02 +00:00
# tick.askVolume2 = data['AskVolume2']
# tick.askVolume3 = data['AskVolume3']
# tick.askVolume4 = data['AskVolume4']
# tick.askVolume5 = data['AskVolume5']
2015-09-28 07:29:48 +00:00
self.onTick(tick)
self.initCompleted = True
self.engine.writeLog(self.name + u'初始化完成')
#----------------------------------------------------------------------
def onTick(self, tick):
2015-10-24 00:01:02 +00:00
"""行情更新
:type tick: object
"""
# 保存最新的TICK
self.currentTick = tick
# 首先生成datetime.time格式的时间便于比较
2015-10-24 00:01:02 +00:00
# ticktime = self.strToTime(tick.time, tick.ms)
2015-09-28 07:29:48 +00:00
ticktime = tick.time
# 假设是收到的第一个TICK
if self.barOpen == 0:
# 初始化新的K线数据
self.barOpen = tick.lastPrice
self.barHigh = tick.lastPrice
self.barLow = tick.lastPrice
self.barClose = tick.lastPrice
self.barVolume = tick.volume
self.barTime = ticktime
else:
# 如果是当前一分钟内的数据
2015-10-17 16:23:24 +00:00
if ticktime.minute == self.barTime.minute and ticktime.hour == self.barTime.hour:
# 汇总TICK生成K线
self.barHigh = max(self.barHigh, tick.lastPrice)
self.barLow = min(self.barLow, tick.lastPrice)
self.barClose = tick.lastPrice
self.barVolume = self.barVolume + tick.volume
2015-10-24 00:01:02 +00:00
self.barTime = ticktime
# 如果是新一分钟的数据
else:
# 首先推送K线数据
2015-10-17 16:23:24 +00:00
self.onBar(self.barOpen, self.barHigh, self.barLow, self.barClose,
self.barVolume, self.barTime)
2015-10-17 16:23:24 +00:00
# 初始化新的K线数据
self.barOpen = tick.lastPrice
self.barHigh = tick.lastPrice
self.barLow = tick.lastPrice
self.barClose = tick.lastPrice
self.barVolume = tick.volume
self.barTime = ticktime
#----------------------------------------------------------------------
def onTrade(self, trade):
"""交易更新"""
if trade.direction == DIRECTION_BUY:
self.pos = self.pos + trade.volume
else:
self.pos = self.pos - trade.volume
log = self.name + u'当前持仓:' + str(self.pos)
2015-10-17 16:23:24 +00:00
print log
self.engine.writeLog(log)
#----------------------------------------------------------------------
def onOrder(self, order):
"""报单更新"""
pass
#----------------------------------------------------------------------
def onStopOrder(self, orderRef):
"""停止单更新"""
pass
#----------------------------------------------------------------------
2015-10-17 16:23:24 +00:00
def onBar(self, o, h, l, c, volume, t):
2015-10-14 16:41:45 +00:00
"""K线数据更新同时进行策略的买入、卖出逻辑计算"""
# 保存K线序列数据
2015-10-24 00:01:02 +00:00
# self.listOpen.append(o)
# self.listHigh.append(h)
# self.listLow.append(l)
# self.listClose.append(c)
# self.listVolume.append(volume)
# self.listTime.append(t)
2015-10-17 16:23:24 +00:00
# 保存K线数据
2015-10-19 08:42:17 +00:00
bar = Bar()
bar.symbol = self.symbol
bar.open = o
bar.high = h
bar.low = l
bar.close = c
bar.volume = volume
bar.date = t.strftime('%Y-%m-%d')
bar.time = t.strftime('%H:%M:%S')
bar.datetime = t
self.lineBar.append(bar)
2015-10-17 16:23:24 +00:00
# 计算EMA
if self.fastEMA:
self.fastEMA = c*self.fastAlpha + self.fastEMA*(1-self.fastAlpha)
self.slowEMA = c*self.slowAlpha + self.slowEMA*(1-self.slowAlpha)
else:
self.fastEMA = c
self.slowEMA = c
2015-10-17 16:23:24 +00:00
emaData = EmaData()
2015-10-19 08:42:17 +00:00
emaData.symbol = self.symbol
2015-10-17 16:23:24 +00:00
emaData.fastEMA = self.fastEMA
emaData.slowEMA = self.slowEMA
2015-10-19 08:42:17 +00:00
emaData.date = t.strftime('%Y-%m-%d')
emaData.time = t.strftime('%H:%M:%S')
2015-10-17 16:23:24 +00:00
emaData.datetime = t
self.lineEMA.append(emaData)
# 交易逻辑
if self.initCompleted: # 首先检查是否是实盘运行还是数据预处理阶段
2015-10-17 16:23:24 +00:00
# Added by Incense Lee
# 属于updateMarketData推送的第一个Tick数据,忽略交易逻辑
if self.firstMarketTick:
self.firstMarketTick = False
return
# End added
# 快速EMA在慢速EMA上方做多
if self.fastEMA > self.slowEMA:
# 如果当前手头无仓位,则直接做多
if self.pos == 0:
# 涨停价买入开仓
2015-10-10 09:08:13 +00:00
# Modified by Incense Lee 回测时Tick数据中没有涨停价只能使用当前价
2015-10-24 00:01:02 +00:00
# self.buy(self.currentTick.upperLimit, 1)
2015-10-17 16:23:24 +00:00
self.buy(self.currentTick.lastPrice, 1, t) # 价格,数量,下单时间
2015-10-24 00:01:02 +00:00
# 手头有空仓,则先平空,再开多
elif self.pos < 0:
2015-10-24 00:01:02 +00:00
# self.cover(self.currentTick.upperLimit, 1)
2015-10-17 16:23:24 +00:00
self.cover(self.currentTick.lastPrice, 1, t) # 价格,数量, 下单时间
2015-10-24 00:01:02 +00:00
# self.buy(self.currentTick.upperLimit, 1)
2015-10-17 16:23:24 +00:00
self.buy(self.currentTick.lastPrice, 1, t)
2015-10-24 00:01:02 +00:00
# 反之,做空
elif self.fastEMA < self.slowEMA:
if self.pos == 0:
2015-10-10 09:08:13 +00:00
# Modified by Incense Lee 回测时Tick数据中没有最低价价只能使用当前价
2015-10-24 00:01:02 +00:00
# self.short(self.currentTick.lowerLimit, 1)
2015-10-17 16:23:24 +00:00
self.short(self.currentTick.lastPrice, 1, t)
elif self.pos > 0:
2015-10-24 00:01:02 +00:00
# self.sell(self.currentTick.lowerLimit, 1)
2015-10-17 16:23:24 +00:00
self.sell(self.currentTick.lastPrice, 1, t)
2015-10-10 09:08:13 +00:00
2015-10-24 00:01:02 +00:00
# self.short(self.currentTick.lowerLimit, 1)
2015-10-17 16:23:24 +00:00
self.short(self.currentTick.lastPrice, 1, t)
# 记录日志
2015-10-17 16:23:24 +00:00
log = self.name + u'K线时间' + str(t) + '\n' + \
u'快速EMA' + str(self.fastEMA) + u'慢速EMA' + \
str(self.slowEMA)
self.engine.writeLog(log)
#----------------------------------------------------------------------
def strToTime(self, t, ms):
"""从字符串时间转化为time格式的时间"""
hh, mm, ss = t.split(':')
tt = time(int(hh), int(mm), int(ss), microsecond=ms)
return tt
2015-10-19 08:42:17 +00:00
#----------------------------------------------------------------------
def saveData(self, id):
2015-10-24 00:01:02 +00:00
"""保存过程数据"""
# 保存K线
print u'{0}保存K线'.format(self.name)
self.engine.saveBarToMysql(id, self.lineBar)
2015-10-19 08:42:17 +00:00
2015-10-24 00:01:02 +00:00
# 保存快速EMA和慢速EMA
self.engine.saveEmaToMysql(id, self.lineEMA)
2015-10-19 08:42:17 +00:00
#----------------------------------------------------------------------
def print_log(event):
"""打印日志"""
log = event.dict_['log']
print str(datetime.now()), ':', log
#----------------------------------------------------------------------
def main():
"""运行在CMD中的演示程度"""
# 创建PyQt4应用对象
app = QtCore.QCoreApplication(sys.argv)
2015-09-16 07:34:00 +00:00
print u'demoStrategy.py Main call QtCore.QCoreApplication(sys.argv) success'
# 创建主引擎对象
me = MainEngine()
2015-09-16 07:34:00 +00:00
print u'demoStrategy.py Main call MainEngine() success'
# 注册事件监听
me.ee.register(EVENT_LOG, print_log)
# 登录
2015-09-28 07:29:48 +00:00
userid = '033513'
password = 'jiajia'
brokerid = '9999'
mdAddress = 'tcp://180.168.146.187:10010'
tdAddress = 'tcp://180.168.146.187:10000'
me.login(userid, password, brokerid, mdAddress, tdAddress)
# 等待10秒钟初始化合约数据等
2015-05-28 02:09:59 +00:00
sleep(5)
# 创建策略引擎对象
se = StrategyEngine(me.ee, me)
# 创建策略对象
setting = {}
setting['fastAlpha'] = 0.2
2015-10-22 02:40:59 +00:00
setting['slowAlpha'] = 0.09
2015-10-24 00:01:02 +00:00
# se.createStrategy(u'EMA演示策略', 'IF1506', SimpleEmaStrategy, setting)
2015-10-10 09:08:13 +00:00
se.createStrategy(u'EMA演示策略', 'a', SimpleEmaStrategy, setting)
# 启动所有策略
se.startAll()
# 让程序连续运行
sys.exit(app.exec_())
2015-10-24 00:37:39 +00:00
if __name__ == '__main__':
main()