增加CTA模块回测引擎中的灵活手数计算功能,允许每次委托的数量不一样,实现自动比较清算
This commit is contained in:
parent
e36bd4a3f2
commit
ab9d99d725
@ -455,7 +455,8 @@ class BacktestingEngine(object):
|
||||
self.output(u'计算回测结果')
|
||||
|
||||
# 首先基于回测后的成交记录,计算每笔交易的盈亏
|
||||
resultDict = OrderedDict() # 交易结果记录
|
||||
resultList = [] # 交易结果列表
|
||||
|
||||
longTrade = [] # 未平仓的多头交易
|
||||
shortTrade = [] # 未平仓的空头交易
|
||||
|
||||
@ -467,11 +468,40 @@ class BacktestingEngine(object):
|
||||
longTrade.append(trade)
|
||||
# 当前多头交易为平空
|
||||
else:
|
||||
entryTrade = shortTrade.pop(0)
|
||||
while True:
|
||||
entryTrade = shortTrade[0]
|
||||
exitTrade = trade
|
||||
|
||||
# 清算开平仓交易
|
||||
closedVolume = min(exitTrade.volume, entryTrade.volume)
|
||||
result = TradingResult(entryTrade.price, entryTrade.dt,
|
||||
exitTrade.price, exitTrade.dt,
|
||||
-closedVolume, self.rate, self.slippage, self.size)
|
||||
resultList.append(result)
|
||||
|
||||
# 计算未清算部分
|
||||
entryTrade.volume -= closedVolume
|
||||
exitTrade.volume -= closedVolume
|
||||
|
||||
# 如果开仓交易已经全部清算,则从列表中移除
|
||||
if not entryTrade.volume:
|
||||
shortTrade.pop(0)
|
||||
|
||||
# 如果平仓交易已经全部清算,则退出循环
|
||||
if not exitTrade.volume:
|
||||
break
|
||||
|
||||
# 如果平仓交易未全部清算,
|
||||
if exitTrade.volume:
|
||||
# 且开仓交易已经全部清算完,则平仓交易剩余的部分
|
||||
# 等于新的反向开仓交易,添加到队列中
|
||||
if not shortTrade:
|
||||
longTrade.append(exitTrade)
|
||||
break
|
||||
# 如果开仓交易还有剩余,则进入下一轮循环
|
||||
else:
|
||||
pass
|
||||
|
||||
result = TradingResult(entryTrade.price, trade.price, -trade.volume,
|
||||
self.rate, self.slippage, self.size)
|
||||
resultDict[trade.dt] = result
|
||||
# 空头交易
|
||||
else:
|
||||
# 如果尚无多头交易
|
||||
@ -479,14 +509,42 @@ class BacktestingEngine(object):
|
||||
shortTrade.append(trade)
|
||||
# 当前空头交易为平多
|
||||
else:
|
||||
entryTrade = longTrade.pop(0)
|
||||
while True:
|
||||
entryTrade = longTrade[0]
|
||||
exitTrade = trade
|
||||
|
||||
result = TradingResult(entryTrade.price, trade.price, trade.volume,
|
||||
self.rate, self.slippage, self.size)
|
||||
resultDict[trade.dt] = result
|
||||
# 清算开平仓交易
|
||||
closedVolume = min(exitTrade.volume, entryTrade.volume)
|
||||
result = TradingResult(entryTrade.price, entryTrade.dt,
|
||||
exitTrade.price, exitTrade.dt,
|
||||
-closedVolume, self.rate, self.slippage, self.size)
|
||||
resultList.append(result)
|
||||
|
||||
# 计算未清算部分
|
||||
entryTrade.volume -= closedVolume
|
||||
exitTrade.volume -= closedVolume
|
||||
|
||||
# 如果开仓交易已经全部清算,则从列表中移除
|
||||
if not entryTrade.volume:
|
||||
longTrade.pop(0)
|
||||
|
||||
# 如果平仓交易已经全部清算,则退出循环
|
||||
if not exitTrade.volume:
|
||||
break
|
||||
|
||||
# 如果平仓交易未全部清算,
|
||||
if exitTrade.volume:
|
||||
# 且开仓交易已经全部清算完,则平仓交易剩余的部分
|
||||
# 等于新的反向开仓交易,添加到队列中
|
||||
if not longTrade:
|
||||
shortTrade.append(exitTrade)
|
||||
break
|
||||
# 如果开仓交易还有剩余,则进入下一轮循环
|
||||
else:
|
||||
pass
|
||||
|
||||
# 检查是否有交易
|
||||
if not resultDict:
|
||||
if not resultList:
|
||||
self.output(u'无交易结果')
|
||||
return {}
|
||||
|
||||
@ -505,18 +563,13 @@ class BacktestingEngine(object):
|
||||
capitalList = [] # 盈亏汇总的时间序列
|
||||
drawdownList = [] # 回撤的时间序列
|
||||
|
||||
winningResult = 0 # 盈利次数
|
||||
losingResult = 0 # 亏损次数
|
||||
totalWinning = 0 # 总盈利金额
|
||||
totalLosing = 0 # 总亏损金额
|
||||
|
||||
for time, result in resultDict.items():
|
||||
for result in resultList:
|
||||
capital += result.pnl
|
||||
maxCapital = max(capital, maxCapital)
|
||||
drawdown = capital - maxCapital
|
||||
|
||||
pnlList.append(result.pnl)
|
||||
timeList.append(time)
|
||||
timeList.append(result.exitDt) # 交易的时间戳使用平仓时间
|
||||
capitalList.append(capital)
|
||||
drawdownList.append(drawdown)
|
||||
|
||||
@ -674,17 +727,22 @@ class TradingResult(object):
|
||||
"""每笔交易的结果"""
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
def __init__(self, entry, exit, volume, rate, slippage, size):
|
||||
def __init__(self, entryPrice, entryDt, exitPrice,
|
||||
exitDt, volume, rate, slippage, size):
|
||||
"""Constructor"""
|
||||
self.entry = entry # 开仓价格
|
||||
self.exit = exit # 平仓价格
|
||||
self.entryPrice = entryPrice # 开仓价格
|
||||
self.exitPrice = exitPrice # 平仓价格
|
||||
|
||||
self.entryDt = entryDt # 开仓时间datetime
|
||||
self.exitDt = exitDt # 平仓时间
|
||||
|
||||
self.volume = volume # 交易数量(+/-代表方向)
|
||||
|
||||
self.turnover = (self.entry+self.exit)*size*abs(volume) # 成交金额
|
||||
self.commission = self.turnover*rate # 手续费成本
|
||||
self.slippage = slippage*2*size*abs(volume) # 滑点成本
|
||||
self.pnl = ((self.exit - self.entry) * volume * size
|
||||
- self.commission - self.slippage) # 净盈亏
|
||||
self.turnover = (self.entryPrice+self.exitPrice)*size*abs(volume) # 成交金额
|
||||
self.commission = self.turnover*rate # 手续费成本
|
||||
self.slippage = slippage*2*size*abs(volume) # 滑点成本
|
||||
self.pnl = ((self.exitPrice - self.entryPrice) * volume * size
|
||||
- self.commission - self.slippage) # 净盈亏
|
||||
|
||||
|
||||
########################################################################
|
||||
|
Loading…
Reference in New Issue
Block a user