vnpy/vn.strategy/strategydemo/demoStrategy.py
msincenselee decec65092 daily
2015-10-24 08:01:02 +08:00

395 lines
14 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
# 首先写系统内置模块
import sys
print u'demoStrategy.py import sys success'
from datetime import datetime, timedelta, time
print u'demoStrategy.py import datetime.datetime/timedelta/time success'
from time import sleep
print u'demoStrategy.py import time.sleep success'
# 然后是第三方库模块如PyQt4等
import sip
print u'demoStrategy.py import sip success'
from PyQt4 import QtCore
print u'demoStrategy.py import PyQt4.QtCore success'
# 然后是自己编写的模块
from demoEngine import MainEngine
print u'demoStrategy.py import demoEngine.MainEngine success'
from strategyEngine import *
########################################################################
class SimpleEmaStrategy(StrategyTemplate):
"""简单双指数移动均线EMA演示策略"""
#----------------------------------------------------------------------
def __init__(self, name, symbol, engine):
"""Constructor"""
super(SimpleEmaStrategy, self).__init__(name, symbol, engine)
# 策略在外部设置的参数
# self.fastAlpha = 0.2 # 快速EMA的参数
self.fastAlpha = 0.2
# 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线数据的列表对象
# 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
# 初始化时读取的历史数据的起始日期(可以选择外部设置)
self.startDate = None
# Added by Incense Lee
# 属于updateMarketData推送的第一个Tick数据,忽略交易逻辑
self.firstMarketTick = True
self.lineBar = [] # K线数据
self.lineEMA = [] # 快速、慢速EMA数据
#----------------------------------------------------------------------
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'读取参数设定出错,请检查参数字典')
try:
self.initStrategy(setting['startDate'])
except KeyError:
self.initStrategy()
#----------------------------------------------------------------------
def initStrategy(self, startDate=None):
"""初始化"""
self.engine.writeLog(u'读取3天的历史TICK数据')
td = timedelta(days=1)
if startDate:
# 读取历史Tick数据
# cx = self.engine.loadTickFromMongo(self.symbol, startDate-td)
historyStartDate = self.engine.getMysqlDeltaDate(self.symbol,startDate,3)
cx = self.engine.loadTickFromMysql(self.symbol, historyStartDate, startDate-td)
else:
today = datetime.today().replace(hour=0, minute=0, second=0, microsecond=0)
# cx = self.engine.loadTickFromMongo(self.symbol, today-td)
historyStartDate = self.engine.getMysqlDeltaDate(self.symbol,today,3)
cx = self.engine.loadTickFromMysql(self.symbol, historyStartDate,today-td)
if cx:
for data in cx:
tick = Tick(data['InstrumentID'])
# tick = Tick(InstrumentID)
# tick.openPrice = data['OpenPrice']
# tick.highPrice = data['HighestPrice']
# tick.lowPrice = data['LowestPrice']
tick.lastPrice = float(data['LastPrice'])
tick.volume = data['Volume']
tick.openInterest = data['OpenInterest']
# tick.upperLimit = data['UpperLimitPrice']
# tick.lowerLimit = data['LowerLimitPrice']
tick.time = data['UpdateTime']
# tick.ms = data['UpdateMillisec']
tick.bidPrice1 = float(data['BidPrice1'])
# tick.bidPrice2 = data['BidPrice2']
# tick.bidPrice3 = data['BidPrice3']
# tick.bidPrice4 = data['BidPrice4']
# tick.bidPrice5 = data['BidPrice5']
tick.askPrice1 = float(data['AskPrice1'])
# tick.askPrice2 = data['AskPrice2']
# tick.askPrice3 = data['AskPrice3']
# tick.askPrice4 = data['AskPrice4']
# tick.askPrice5 = data['AskPrice5']
tick.bidVolume1 = data['BidVolume1']
# tick.bidVolume2 = data['BidVolume2']
# tick.bidVolume3 = data['BidVolume3']
# tick.bidVolume4 = data['BidVolume4']
# tick.bidVolume5 = data['BidVolume5']
tick.askVolume1 = data['AskVolume1']
# tick.askVolume2 = data['AskVolume2']
# tick.askVolume3 = data['AskVolume3']
# tick.askVolume4 = data['AskVolume4']
# tick.askVolume5 = data['AskVolume5']
self.onTick(tick)
self.initCompleted = True
self.engine.writeLog(self.name + u'初始化完成')
#----------------------------------------------------------------------
def onTick(self, tick):
"""行情更新
:type tick: object
"""
# 保存最新的TICK
self.currentTick = tick
# 首先生成datetime.time格式的时间便于比较
# ticktime = self.strToTime(tick.time, tick.ms)
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:
# 如果是当前一分钟内的数据
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
self.barTime = ticktime
# 如果是新一分钟的数据
else:
# 首先推送K线数据
self.onBar(self.barOpen, self.barHigh, self.barLow, self.barClose,
self.barVolume, self.barTime)
# 初始化新的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)
print log
self.engine.writeLog(log)
#----------------------------------------------------------------------
def onOrder(self, order):
"""报单更新"""
pass
#----------------------------------------------------------------------
def onStopOrder(self, orderRef):
"""停止单更新"""
pass
#----------------------------------------------------------------------
def onBar(self, o, h, l, c, volume, t):
"""K线数据更新同时进行策略的买入、卖出逻辑计算"""
# 保存K线序列数据
# self.listOpen.append(o)
# self.listHigh.append(h)
# self.listLow.append(l)
# self.listClose.append(c)
# self.listVolume.append(volume)
# self.listTime.append(t)
# 保存K线数据
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)
# 计算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
emaData = EmaData()
emaData.symbol = self.symbol
emaData.fastEMA = self.fastEMA
emaData.slowEMA = self.slowEMA
emaData.date = t.strftime('%Y-%m-%d')
emaData.time = t.strftime('%H:%M:%S')
emaData.datetime = t
self.lineEMA.append(emaData)
# 交易逻辑
if self.initCompleted: # 首先检查是否是实盘运行还是数据预处理阶段
# 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:
# 涨停价买入开仓
# Modified by Incense Lee 回测时Tick数据中没有涨停价只能使用当前价
# self.buy(self.currentTick.upperLimit, 1)
self.buy(self.currentTick.lastPrice, 1, t) # 价格,数量,下单时间
# 手头有空仓,则先平空,再开多
elif self.pos < 0:
# self.cover(self.currentTick.upperLimit, 1)
self.cover(self.currentTick.lastPrice, 1, t) # 价格,数量, 下单时间
# self.buy(self.currentTick.upperLimit, 1)
self.buy(self.currentTick.lastPrice, 1, t)
# 反之,做空
elif self.fastEMA < self.slowEMA:
if self.pos == 0:
# Modified by Incense Lee 回测时Tick数据中没有最低价价只能使用当前价
# self.short(self.currentTick.lowerLimit, 1)
self.short(self.currentTick.lastPrice, 1, t)
elif self.pos > 0:
# self.sell(self.currentTick.lowerLimit, 1)
self.sell(self.currentTick.lastPrice, 1, t)
# self.short(self.currentTick.lowerLimit, 1)
self.short(self.currentTick.lastPrice, 1, t)
# 记录日志
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
#----------------------------------------------------------------------
def saveData(self, id):
"""保存过程数据"""
# 保存K线
print u'{0}保存K线'.format(self.name)
self.engine.saveBarToMysql(id, self.lineBar)
# 保存快速EMA和慢速EMA
self.engine.saveEmaToMysql(id, self.lineEMA)
#----------------------------------------------------------------------
def print_log(event):
"""打印日志"""
log = event.dict_['log']
print str(datetime.now()), ':', log
#----------------------------------------------------------------------
def main():
"""运行在CMD中的演示程度"""
# 创建PyQt4应用对象
app = QtCore.QCoreApplication(sys.argv)
print u'demoStrategy.py Main call QtCore.QCoreApplication(sys.argv) success'
# 创建主引擎对象
me = MainEngine()
print u'demoStrategy.py Main call MainEngine() success'
# 注册事件监听
me.ee.register(EVENT_LOG, print_log)
# 登录
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秒钟初始化合约数据等
sleep(5)
# 创建策略引擎对象
se = StrategyEngine(me.ee, me)
# 创建策略对象
setting = {}
setting['fastAlpha'] = 0.2
setting['slowAlpha'] = 0.09
# se.createStrategy(u'EMA演示策略', 'IF1506', SimpleEmaStrategy, setting)
se.createStrategy(u'EMA演示策略', 'a', SimpleEmaStrategy, setting)
# 启动所有策略
se.startAll()
# 让程序连续运行
sys.exit(app.exec_())
if __name__ == '__main__':
main()