[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])
return resultList
#----------------------------------------------------------------------
def outputOptimizeResult(self, resultList):
self.output('-' * 30)
self.output(u'优化结果:')
@ -998,62 +999,67 @@ class BacktestingEngine(object):
dailyResult.calculatePnl(openPosition, self.size, self.rate, self.slippage )
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
df['return'] = (np.log(df['balance']) - np.log(df['balance'].shift(1))).fillna(0)
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
dateList = self.dailyResultDict.keys()
resultList = self.dailyResultDict.values()
# 计算统计结果
startDate = df.index[0]
endDate = df.index[-1]
startDate = dateList[0]
endDate = dateList[-1]
totalDays = len(dateList)
totalDays = len(df)
profitDays = len(df[df['netPnl']>0])
lossDays = len(df[df['netPnl']<0])
profitDays = 0
lossDays = 0
endBalance = self.capital
highlevel = self.capital
totalNetPnl = 0
totalTurnover = 0
totalCommission = 0
totalSlippage = 0
totalTradeCount = 0
endBalance = df['balance'].iloc[-1]
maxDrawdown = df['drawdown'].min()
maxDdPercent = df['ddPercent'].min()
netPnlList = []
balanceList = []
highlevelList = []
drawdownList = []
ddPercentList = []
returnList = []
totalNetPnl = df['netPnl'].sum()
dailyNetPnl = totalNetPnl / totalDays
for result in resultList:
if result.netPnl > 0:
profitDays += 1
elif result.netPnl < 0:
lossDays += 1
netPnlList.append(result.netPnl)
totalCommission = df['commission'].sum()
dailyCommission = totalCommission / totalDays
prevBalance = endBalance
endBalance += result.netPnl
balanceList.append(endBalance)
returnList.append(endBalance/prevBalance - 1)
totalSlippage = df['slippage'].sum()
dailySlippage = totalSlippage / totalDays
highlevel = max(highlevel, endBalance)
highlevelList.append(highlevel)
totalTurnover = df['turnover'].sum()
dailyTurnover = totalTurnover / totalDays
drawdown = endBalance - highlevel
drawdownList.append(drawdown)
ddPercentList.append(drawdown/highlevel*100)
totalTradeCount = df['tradeCount'].sum()
dailyTradeCount = totalTradeCount / totalDays
totalTurnover += result.turnover
totalCommission += result.commission
totalSlippage += result.slippage
totalTradeCount += result.tradeCount
totalNetPnl += result.netPnl
maxDrawdown = min(drawdownList)
maxDdPercent = min(ddPercentList)
totalReturn = (endBalance / self.capital - 1) * 100
annualizedReturn = totalReturn / totalDays * 240
dailyReturn = df['return'].mean() * 100
returnStd = df['return'].std() * 100
dailyReturn = np.mean(returnList) * 100
annualizedReturn = dailyReturn * annualDays
returnStd = np.std(returnList) * 100
if returnStd:
sharpeRatio = dailyReturn / returnStd * np.sqrt(240)
sharpeRatio = dailyReturn / returnStd * np.sqrt(annualDays)
else:
sharpeRatio = 0
@ -1068,15 +1074,15 @@ class BacktestingEngine(object):
'maxDrawdown': maxDrawdown,
'maxDdPercent': maxDdPercent,
'totalNetPnl': totalNetPnl,
'dailyNetPnl': dailyNetPnl,
'dailyNetPnl': totalNetPnl/totalDays,
'totalCommission': totalCommission,
'dailyCommission': dailyCommission,
'dailyCommission': totalCommission/totalDays,
'totalSlippage': totalSlippage,
'dailySlippage': dailySlippage,
'dailySlippage': totalSlippage/totalDays,
'totalTurnover': totalTurnover,
'dailyTurnover': dailyTurnover,
'dailyTurnover': totalTurnover/totalDays,
'totalTradeCount': totalTradeCount,
'dailyTradeCount': dailyTradeCount,
'dailyTradeCount': totalTradeCount/totalDays,
'totalReturn': totalReturn,
'annualizedReturn': annualizedReturn,
'dailyReturn': dailyReturn,
@ -1084,14 +1090,23 @@ class BacktestingEngine(object):
'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:
df = self.calculateDailyResult()
df, result = self.calculateDailyStatistics(df)
if d is None:
self.calculateDailyResult()
d, result = self.calculateDailyStatistics()
# 输出统计结果
self.output('-' * 30)
@ -1131,19 +1146,19 @@ class BacktestingEngine(object):
pBalance = plt.subplot(4, 1, 1)
pBalance.set_title('Balance')
df['balance'].plot(legend=True)
plt.plot(d['date'], d['balance'])
pDrawdown = plt.subplot(4, 1, 2)
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.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.set_title('Daily Pnl Distribution')
df['netPnl'].hist(bins=50)
plt.hist(d['netPnl'], bins=50)
plt.show()