[Mod]移除ctaBacktesting中对pandas的依赖

This commit is contained in:
vn.py 2018-09-30 22:23:51 +08:00
parent 8af3355553
commit 145d5215e7

View File

@ -955,6 +955,7 @@ class BacktestingEngine(object):
resultList.sort(reverse=True, key=lambda result:result[1]) resultList.sort(reverse=True, key=lambda result:result[1])
return resultList return resultList
#----------------------------------------------------------------------
def outputOptimizeResult(self, resultList): def outputOptimizeResult(self, resultList):
self.output('-' * 30) self.output('-' * 30)
self.output(u'优化结果:') self.output(u'优化结果:')
@ -997,66 +998,71 @@ class BacktestingEngine(object):
dailyResult.calculatePnl(openPosition, self.size, self.rate, self.slippage ) dailyResult.calculatePnl(openPosition, self.size, self.rate, self.slippage )
openPosition = dailyResult.closePosition openPosition = dailyResult.closePosition
# 生成DataFrame
resultDict = {k:[] for k in dailyResult.__dict__.keys()}
for dailyResult in self.dailyResultDict.values():
for k, v in dailyResult.__dict__.items():
resultDict[k].append(v)
resultDf = pd.DataFrame.from_dict(resultDict)
# 计算衍生数据
resultDf = resultDf.set_index('date')
return resultDf
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def calculateDailyStatistics(self, df): def calculateDailyStatistics(self, annualDays=240):
"""计算按日统计的结果""" """计算按日统计的结果"""
df['balance'] = df['netPnl'].cumsum() + self.capital dateList = self.dailyResultDict.keys()
df['return'] = (np.log(df['balance']) - np.log(df['balance'].shift(1))).fillna(0) resultList = self.dailyResultDict.values()
df['highlevel'] = df['balance'].rolling(min_periods=1,window=len(df),center=False).max()
df['drawdown'] = df['balance'] - df['highlevel']
df['ddPercent'] = df['drawdown'] / df['highlevel'] * 100
# 计算统计结果 startDate = dateList[0]
startDate = df.index[0] endDate = dateList[-1]
endDate = df.index[-1] totalDays = len(dateList)
totalDays = len(df)
profitDays = len(df[df['netPnl']>0])
lossDays = len(df[df['netPnl']<0])
endBalance = df['balance'].iloc[-1] profitDays = 0
maxDrawdown = df['drawdown'].min() lossDays = 0
maxDdPercent = df['ddPercent'].min() endBalance = self.capital
highlevel = self.capital
totalNetPnl = 0
totalTurnover = 0
totalCommission = 0
totalSlippage = 0
totalTradeCount = 0
totalNetPnl = df['netPnl'].sum() netPnlList = []
dailyNetPnl = totalNetPnl / totalDays balanceList = []
highlevelList = []
drawdownList = []
ddPercentList = []
returnList = []
totalCommission = df['commission'].sum() for result in resultList:
dailyCommission = totalCommission / totalDays if result.netPnl > 0:
profitDays += 1
elif result.netPnl < 0:
lossDays += 1
netPnlList.append(result.netPnl)
prevBalance = endBalance
endBalance += result.netPnl
balanceList.append(endBalance)
returnList.append(endBalance/prevBalance - 1)
highlevel = max(highlevel, endBalance)
highlevelList.append(highlevel)
drawdown = endBalance - highlevel
drawdownList.append(drawdown)
ddPercentList.append(drawdown/highlevel*100)
totalTurnover += result.turnover
totalCommission += result.commission
totalSlippage += result.slippage
totalTradeCount += result.tradeCount
totalNetPnl += result.netPnl
totalSlippage = df['slippage'].sum() maxDrawdown = min(drawdownList)
dailySlippage = totalSlippage / totalDays maxDdPercent = min(ddPercentList)
totalReturn = (endBalance / self.capital - 1) * 100
totalTurnover = df['turnover'].sum() dailyReturn = np.mean(returnList) * 100
dailyTurnover = totalTurnover / totalDays annualizedReturn = dailyReturn * annualDays
returnStd = np.std(returnList) * 100
totalTradeCount = df['tradeCount'].sum()
dailyTradeCount = totalTradeCount / totalDays
totalReturn = (endBalance/self.capital - 1) * 100
annualizedReturn = totalReturn / totalDays * 240
dailyReturn = df['return'].mean() * 100
returnStd = df['return'].std() * 100
if returnStd: if returnStd:
sharpeRatio = dailyReturn / returnStd * np.sqrt(240) sharpeRatio = dailyReturn / returnStd * np.sqrt(annualDays)
else: else:
sharpeRatio = 0 sharpeRatio = 0
# 返回结果 # 返回结果
result = { result = {
'startDate': startDate, 'startDate': startDate,
@ -1068,30 +1074,39 @@ class BacktestingEngine(object):
'maxDrawdown': maxDrawdown, 'maxDrawdown': maxDrawdown,
'maxDdPercent': maxDdPercent, 'maxDdPercent': maxDdPercent,
'totalNetPnl': totalNetPnl, 'totalNetPnl': totalNetPnl,
'dailyNetPnl': dailyNetPnl, 'dailyNetPnl': totalNetPnl/totalDays,
'totalCommission': totalCommission, 'totalCommission': totalCommission,
'dailyCommission': dailyCommission, 'dailyCommission': totalCommission/totalDays,
'totalSlippage': totalSlippage, 'totalSlippage': totalSlippage,
'dailySlippage': dailySlippage, 'dailySlippage': totalSlippage/totalDays,
'totalTurnover': totalTurnover, 'totalTurnover': totalTurnover,
'dailyTurnover': dailyTurnover, 'dailyTurnover': totalTurnover/totalDays,
'totalTradeCount': totalTradeCount, 'totalTradeCount': totalTradeCount,
'dailyTradeCount': dailyTradeCount, 'dailyTradeCount': totalTradeCount/totalDays,
'totalReturn': totalReturn, 'totalReturn': totalReturn,
'annualizedReturn': annualizedReturn, 'annualizedReturn': annualizedReturn,
'dailyReturn': dailyReturn, 'dailyReturn': dailyReturn,
'returnStd': returnStd, 'returnStd': returnStd,
'sharpeRatio': sharpeRatio 'sharpeRatio': sharpeRatio
} }
return df, result d = {}
d['balance'] = balanceList
d['return'] = returnList
d['highLevel'] = highlevelList
d['drawdown'] = drawdownList
d['ddPercent'] = ddPercentList
d['date'] = dateList
d['netPnl'] = netPnlList
return d, result
#---------------------------------------------------------------------- #----------------------------------------------------------------------
def showDailyResult(self, df=None, result=None): def showDailyResult(self, d=None, result=None):
"""显示按日统计的交易结果""" """显示按日统计的交易结果"""
if df is None: if d is None:
df = self.calculateDailyResult() self.calculateDailyResult()
df, result = self.calculateDailyStatistics(df) d, result = self.calculateDailyStatistics()
# 输出统计结果 # 输出统计结果
self.output('-' * 30) self.output('-' * 30)
@ -1131,23 +1146,23 @@ class BacktestingEngine(object):
pBalance = plt.subplot(4, 1, 1) pBalance = plt.subplot(4, 1, 1)
pBalance.set_title('Balance') pBalance.set_title('Balance')
df['balance'].plot(legend=True) plt.plot(d['date'], d['balance'])
pDrawdown = plt.subplot(4, 1, 2) pDrawdown = plt.subplot(4, 1, 2)
pDrawdown.set_title('Drawdown') pDrawdown.set_title('Drawdown')
pDrawdown.fill_between(range(len(df)), df['drawdown'].values) pDrawdown.fill_between(range(len(d['drawdown'])), d['drawdown'])
pPnl = plt.subplot(4, 1, 3) pPnl = plt.subplot(4, 1, 3)
pPnl.set_title('Daily Pnl') pPnl.set_title('Daily Pnl')
df['netPnl'].plot(kind='bar', legend=False, grid=False, xticks=[]) plt.bar(range(len(d['drawdown'])), d['netPnl'])
pKDE = plt.subplot(4, 1, 4) pKDE = plt.subplot(4, 1, 4)
pKDE.set_title('Daily Pnl Distribution') pKDE.set_title('Daily Pnl Distribution')
df['netPnl'].hist(bins=50) plt.hist(d['netPnl'], bins=50)
plt.show() plt.show()
######################################################################## ########################################################################
class TradingResult(object): class TradingResult(object):
"""每笔交易的结果""" """每笔交易的结果"""