This commit is contained in:
msincenselee 2016-10-11 00:50:47 +08:00
parent 341ae7c08e
commit ccf3bb1b8a
6 changed files with 141 additions and 8 deletions

View File

@ -1032,7 +1032,7 @@ class BacktestingEngine(object):
self.output(u'最大回撤: \t%s' % formatNumber(min(d['drawdownList'])))
self.output(u'平均每笔盈利:\t%s' %formatNumber(d['capital']/d['totalResult']))
self.output(u'平均每笔滑点\t%s' %formatNumber(d['totalSlippage']/d['totalResult']))
self.output(u'平均每笔滑点成本\t%s' %formatNumber(d['totalSlippage']/d['totalResult']))
self.output(u'平均每笔佣金:\t%s' %formatNumber(d['totalCommission']/d['totalResult']))
# 绘图
@ -1070,7 +1070,7 @@ class BacktestingEngine(object):
#----------------------------------------------------------------------
def setRate(self, rate):
"""设置佣金比例"""
self.rate = rate
self.rate = float(rate)
#----------------------------------------------------------------------
def runOptimization(self, strategyClass, optimizationSetting):
@ -1135,7 +1135,7 @@ class TradingResult(object):
self.volume = volume # 交易数量(+/-代表方向)
self.turnover = (self.entry+self.exit)*size # 成交金额
self.commission = self.turnover*rate # 手续费成本
self.commission =round(float(self.turnover*rate),4) # 手续费成本
self.slippage = slippage*2*size # 滑点成本
self.pnl = ((self.exit - self.entry) * volume * size
- self.commission - self.slippage) # 净盈亏

View File

@ -90,7 +90,7 @@ class CtaBarData(object):
self.low = EMPTY_FLOAT
self.close = EMPTY_FLOAT
self.date = EMPTY_STRING # bar开始的时间日期
self.date = EMPTY_STRING # bar开始的时间日期通过tick生成的bar时间为开始时间其他为结束时间
self.time = EMPTY_STRING # 时间
self.datetime = None # python的datetime时间对象
@ -103,6 +103,9 @@ class CtaBarData(object):
# CTAORDER_SHORT 、CTAORDER_COVER 、 CTAORDER_OPEN_REJECT 、
# CTAORDER_OPEN_FAIL 、CTAORDER_CLOSE_FAIL
self.mid4 = EMPTY_FLOAT # (2*CLOSE+HIGH+LOW)/4;
self.mid5 = EMPTY_FLOAT # (2*CLOSE+HIGH+LOW+OPEN)/5
self.seconds = EMPTY_INT # 当前Bar的秒数针对RenkoBar)
self.highSeconds = -1 # 当前Bar的上限秒数
self.lowSeconds = -1 # 当前bar的下限秒数

View File

@ -254,7 +254,7 @@ class CtaLineBar(object):
# 与最后一个BAR的时间比对判断是否超过K线的周期
lastBar = self.lineBar[-1]
if (bar.datetime - lastBar.datetime).seconds >= self.barTimeInterval:
if abs((bar.datetime - lastBar.datetime).seconds) >= self.barTimeInterval:
self.lineBar.append(bar)
self.onBar(bar)
return
@ -265,9 +265,15 @@ class CtaLineBar(object):
lastBar.low = min(lastBar.low, bar.low)
lastBar.volume = lastBar.volume + bar.volume
lastBar.mid4 = round((2*lastBar.close + lastBar.high+lastBar.low)/4,2)
lastBar.mid5 = round((2*lastBar.close + lastBar.open+ lastBar.high+lastBar.low)/5,2)
def onBar(self, bar):
"""OnBar事件"""
# 计算相关数据
bar.mid4 = round((2*bar.close + bar.high+bar.low)/4,2)
bar.mid5 = round((2*bar.close + bar.open+ bar.high+bar.low)/5,2)
self.__recountPreHighLow()
self.__recountMa()
self.__recountEma()
@ -355,6 +361,10 @@ class CtaLineBar(object):
self.bar.low = tick.lastPrice
self.bar.close = tick.lastPrice
self.bar.mid4 = tick.lastPrice # 四价均价
self.bar.mid5 = tick.lastPrice # 四价均价
# K线的日期时间
self.bar.date = tick.date # K线的日期时间去除秒设为第一个Tick的时间
self.bar.time = tick.time # K线的日期时间去除秒设为第一个Tick的时间
@ -379,7 +389,7 @@ class CtaLineBar(object):
self.onBar(self.bar)
return
# 清除8交易小时前的数据,
# 清除480周期前的数据,
if l1 > 60 * 8:
del self.lineBar[0]

View File

@ -0,0 +1,117 @@
# encoding: UTF-8
from vtConstant import *
from ctaBase import *
import talib as ta
from datetime import datetime
DEBUGCTALOG = True
class CtaPosition:
"""策略的仓位管理类
v 0.1 简单的数值代表多仓数量和空仓数量
"""
def __init__(self, strategy):
self.strategy = strategy
self.pos = 0 # 持仓状态 0:空仓 >=1 多仓 <=-1 空仓
self.maxPos = 1 # 最大持仓量
self.step = 1 # 增仓数量
self.posList = []
self.avgPrice = EMPTY_FLOAT
def avaliablePos2Add(self):
"""剩余可加的仓位数量"""
return self.maxPos - abs(self.pos)
def openPos(self, direction, vol, price = EMPTY_FLOAT):
"""开、加仓"""
if self.pos == 0:
self.posList = []
if direction == DIRECTION_LONG: # 加多仓
if self.pos + vol > self.maxPos:
self.writeCtaLog(u'异常,超出仓位,当前仓位:{0},加仓:{1},最大仓位:{2}'.format(self.pos,vol,self.maxPos))
return False
self.writeCtaLog(u'仓位:{0}->{1}'.format(self.pos, self.pos+vol))
self.pos = self.pos + vol
self.strategy.pos = self.pos
if direction == DIRECTION_SHORT: # 加空仓
if self.pos - vol < 0 - self.maxPos:
self.writeCtaLog(u'异常,超出仓位,当前仓位:{0},加仓:{1},最大仓位:{2}'.format(self.pos, vol, self.maxPos))
return False
self.writeCtaLog(u'仓位:{0}->{1}'.format(self.pos, self.pos-vol))
self.pos = self.pos - vol
self.strategy.pos = self.pos
if price > EMPTY_FLOAT:
self.posList.append(price)
# 计算持仓均价
if len(self.posList) > 0:
self.avgPrice = sum(self.posList)/len(self.posList)
self.avgPrice = round(self.avgPrice, 3)
return True
def closePos(self, direction, vol):
"""平、减仓"""
if direction == DIRECTION_LONG: # 平空仓 Cover
if self.pos + vol > 0:
self.writeCtaLog(u'异常,超出仓位,当前仓位:{0},平仓:{1}'.format(self.pos,vol))
self.strategy.pos = self.pos
return False
self.writeCtaLog(u'仓位:{0}->{1}'.format(self.pos, self.pos+vol))
self.pos = self.pos + vol
self.strategy.pos = self.pos
if direction == DIRECTION_SHORT: # 平多仓
if self.pos - vol < 0 :
self.writeCtaLog(u'异常,超出仓位,当前仓位:{0},加仓:{1}'.format(self.pos, vol))
self.strategy.pos = self.pos
return False
self.writeCtaLog(u'仓位:{0}->{1}'.format(self.pos, self.pos-vol))
self.pos = self.pos - vol
self.strategy.pos = self.pos
if abs(self.pos) > 0:
self.posList = self.posList[:-vol]
else:
self.posList = []
# 计算持仓均价
if len(self.posList) > 0:
self.avgPrice = sum(self.posList)/len(self.posList)
self.avgPrice = round(self.avgPrice, 3)
return True
# ----------------------------------------------------------------------
def writeCtaLog(self, content):
"""记录CTA日志"""
self.strategy.writeCtaLog(content)
def debugCtaLog(self,content):
"""记录CTA日志"""
if DEBUGCTALOG:
self.strategy.writeCtaLog('[DEBUG]'+content)

View File

@ -11,8 +11,10 @@
from ctaTemplate import DataRecorder
from ctaDemo import DoubleEmaDemo
from strategy22_ArbitrageGrid import Strategy22
from strategy24_M15RB import Strategy24
STRATEGY_CLASS = {}
STRATEGY_CLASS['DataRecorder'] = DataRecorder
STRATEGY_CLASS['DoubleEmaDemo'] = DoubleEmaDemo
STRATEGY_CLASS['Strategy22'] = Strategy22
STRATEGY_CLASS['Strategy24'] = Strategy24

View File

@ -1027,6 +1027,7 @@ class TradingWidget(QtGui.QFrame):
contract = self.mainEngine.getContract(symbol)
if contract:
if not gatewayName:
gatewayName = contract.gatewayName
exchange = contract.exchange # 保证有交易所代码