@Channelchan
2018-11-28T18:00:31.000000Z
字数 10881
阅读 64606
60分钟看长短期MA趋势, 15分钟做均线择时。
from __future__ import division
from vnpy.trader.vtConstant import *
from vnpy.trader.app.ctaStrategy import CtaTemplate
import talib as ta
########################################################################
# 策略继承CtaTemplate
class MultiFrameMaStrategy(CtaTemplate):
className = 'MultiFrameMaStrategy'
author = 'ChannelCMT'
# 策略参数
fastPeriod = 20; slowPeriod = 55
signalMaPeriod = 20
lot = 1
# 策略变量
maTrend = {} # 记录趋势状态,多头1,空头-1
transactionPrice = {} # 记录成交价格
# 参数列表,保存了参数的名称
paramList = [
'fastPeriod', 'slowPeriod',
'signalMaPeriod'
]
# 变量列表,保存了变量的名称
varList = [
'maTrend',
'transactionPrice'
]
# 同步列表,保存了需要保存到数据库的变量名称
syncList = ['posDict', 'eveningDict']
#----------------------------------------------------------------------
def __init__(self, ctaEngine, setting):
super().__init__(ctaEngine, setting)
#----------------------------------------------------------------------
def onInit(self):
"""初始化策略"""
self.writeCtaLog(u'策略初始化')
self.transactionPrice = {s:0 for s in self.symbolList} # 生成成交价格的字典
self.maTrend = {s:0 for s in self.symbolList}
self.putEvent()
#----------------------------------------------------------------------
def onStart(self):
"""启动策略"""
self.writeCtaLog(u'策略启动')
self.putEvent()
#----------------------------------------------------------------------
def onStop(self):
"""停止策略"""
self.writeCtaLog(u'策略停止')
self.putEvent()
#----------------------------------------------------------------------
def onTick(self, tick):
"""收到行情TICK推送"""
pass
#----------------------------------------------------------------------
def onBar(self, bar):
"""收到Bar推送"""
pass
#----------------------------------------------------------------------
def on60MinBar(self, bar):
"""收到60MinBar推送"""
symbol = bar.vtSymbol
am60 = self.getArrayManager(symbol, "60m")
if not am60.inited:
return
# 计算均线并判断趋势
fastMa = ta.MA(am60.close, self.fastPeriod)
slowMa = ta.MA(am60.close, self.slowPeriod)
if fastMa[-1] > slowMa[-1]:
self.maTrend[symbol] = 1
else:
self.maTrend[symbol] = -1
#----------------------------------------------------------------------
def on15MinBar(self, bar):
"""收到15MinBar推送"""
symbol = bar.vtSymbol
am15 = self.getArrayManager(symbol, "15m")
if not am15.inited:
return
signalMa = ta.EMA(am15.close, self.signalMaPeriod)
maUp = signalMa[-1]>signalMa[-3] # 均线上涨
maDn = signalMa[-1]<signalMa[-3] # 均线下跌
# 均线上涨, 趋势为多头, 多头没有持仓
if maUp and (self.maTrend[symbol]==1) and (self.posDict[symbol+'_LONG']==0):
if (self.posDict[symbol+'_SHORT']==0):
self.buy(symbol, bar.close*1.01, self.lot) # 成交价*1.01发送高价位的限价单,以最优市价买入进场
elif (self.posDict[symbol+'_SHORT'] > 0):
self.cancelAll() # 撤销挂单
self.cover(symbol, bar.close*1.01, self.posDict[symbol+'_SHORT'])
self.buy(symbol, bar.close*1.01, self.lot)
# 均线下跌, 趋势为空头, 空头没有持仓
if maDn and (self.maTrend[symbol]==-1) and (self.posDict[symbol+'_SHORT']==0):
if (self.posDict[symbol+'_LONG']==0):
# self.cancelAll() # 撤销挂单
self.short(symbol, bar.close*0.99, self.lot) # 成交价*0.99发送低价位的限价单,以最优市价卖出进场
elif (self.posDict[symbol+'_LONG'] > 0):
self.cancelAll() # 撤销挂单
self.sell(symbol, bar.close*0.99, self.posDict[symbol+'_LONG'])
self.short(symbol, bar.close*0.99, self.lot)
self.putEvent()
#----------------------------------------------------------------------
def onOrder(self, order):
"""收到委托变化推送(必须由用户继承实现)"""
# 对于无需做细粒度委托控制的策略,可以忽略onOrder
pass
#----------------------------------------------------------------------
def onTrade(self, trade):
"""收到成交推送(必须由用户继承实现)"""
# 对于无需做交易信息记录的策略,可以忽略onTrade
pass
#----------------------------------------------------------------------
def onStopOrder(self, so):
"""停止单推送"""
pass
if __name__=="__main__":
from vnpy.trader.app.ctaStrategy import BacktestingEngine
# 创建回测引擎对象
engine = BacktestingEngine()
# 设置回测使用的数据
engine.setBacktestingMode(engine.BAR_MODE) # 设置引擎的回测模式为K线
engine.setDatabase('VnTrader_1Min_Db') # 设置使用的历史数据库
engine.setStartDate('20180901 12:00',initHours=200) # 设置回测用的数据起始日期
engine.setEndDate('20181123 12:00') # 设置回测用的数据终止日期
# 配置回测引擎参数
engine.setSlippage(0.002) # 设置滑点
engine.setRate(5/10000) # 设置手续费千1
engine.setCapital(1000000) # 设置回测本金
# # 在引擎中创建策略对象
parameterDict = {'symbolList':['BTCUSDT:binance']} # 策略参数配置
engine.initStrategy(MultiFrameMaStrategy, parameterDict) # 创建策略对象
engine.runBacktesting()
import pandas as pd
tradeReport = pd.DataFrame([obj.__dict__ for obj in engine.tradeDict.values()])
tradeDf = tradeReport.set_index('dt')
tradeDf.tail()
# 显示逐日回测结果
engine.showDailyResult()
2018-11-27 16:39:28.106324 计算按日统计结果
2018-11-27 16:39:28.125304 ------------------------------
2018-11-27 16:39:28.125304 首个交易日: 2018-09-01 00:00:00
2018-11-27 16:39:28.125304 最后交易日: 2018-11-23 00:00:00
2018-11-27 16:39:28.125304 总交易日: 84
2018-11-27 16:39:28.125304 盈利交易日 54
2018-11-27 16:39:28.125304 亏损交易日: 29
2018-11-27 16:39:28.125304 起始资金: 1000000
2018-11-27 16:39:28.125304 结束资金: 1,003,343.23
2018-11-27 16:39:28.125304 总收益率: 0.33%
2018-11-27 16:39:28.125304 年化收益: 0.96%
2018-11-27 16:39:28.125304 总盈亏: 3,343.23
2018-11-27 16:39:28.125304 最大回撤: -308.75
2018-11-27 16:39:28.125304 百分比最大回撤: -0.03%
2018-11-27 16:39:28.125304 总手续费: 230.16
2018-11-27 16:39:28.125304 总滑点: 0.14
2018-11-27 16:39:28.125304 总成交金额: 460,323.2
2018-11-27 16:39:28.125304 总成交笔数: 71
2018-11-27 16:39:28.125304 日均盈亏: 39.8
2018-11-27 16:39:28.125304 日均手续费: 2.74
2018-11-27 16:39:28.125304 日均滑点: 0.0
2018-11-27 16:39:28.125304 日均成交金额: 5,480.04
2018-11-27 16:39:28.125304 日均成交笔数: 0.85
2018-11-27 16:39:28.125304 日均收益率: 0.0%
2018-11-27 16:39:28.125304 收益标准差: 0.01%
2018-11-27 16:39:28.125304 Sharpe Ratio: 4.24
# 显示逐笔回测结果
engine.showBacktestingResult()
2018-11-27 16:39:29.634764 计算回测结果
2018-11-27 16:39:29.637760 ------------------------------
2018-11-27 16:39:29.638759 第一笔交易: 2018-09-05 22:00:00
2018-11-27 16:39:29.638759 最后一笔交易: 2018-11-23 11:58:00
2018-11-27 16:39:29.638759 总交易次数: 36
2018-11-27 16:39:29.638759 总盈亏: 3,341.06
2018-11-27 16:39:29.638759 最大回撤: -254.65
2018-11-27 16:39:29.638759 平均每笔盈利: 92.81
2018-11-27 16:39:29.638759 平均每笔滑点: 0.0
2018-11-27 16:39:29.638759 平均每笔佣金: 6.45
2018-11-27 16:39:29.638759 胜率 36.11%
2018-11-27 16:39:29.638759 盈利交易平均值 339.84
2018-11-27 16:39:29.638759 亏损交易平均值 -46.82
2018-11-27 16:39:29.638759 盈亏比: 7.26
df = engine.calculateDailyResult()
df1, result = engine.calculateDailyStatistics(df)
print(pd.Series(result))
2018-11-27 16:39:30.319064 计算按日统计结果
annualizedReturn 0.955208
dailyCommission 2.74002
dailyNetPnl 39.8003
dailyReturn 0.00384366
dailySlippage 0.00169048
dailyTradeCount 0.845238
dailyTurnover 5480.04
endBalance 1.00334e+06
endDate 2018-11-23 00:00:00
lossDays 29
maxDdPercent -0.0308648
maxDrawdown -308.747
profitDays 54
returnStd 0.0140566
sharpeRatio 4.23614
startDate 2018-09-01 00:00:00
totalCommission 230.162
totalDays 84
totalNetPnl 3343.23
totalReturn 0.334323
totalSlippage 0.142
totalTradeCount 71
totalTurnover 460323
dtype: object
from vnpy.trader.app.ctaStrategy.ctaBacktesting import OptimizationSetting
# 优化配置
setting = OptimizationSetting() # 新建一个优化任务设置对象
setting.setOptimizeTarget('sharpeRatio') # 设置优化排序的目标是夏普
setting.addParameter('fastPeriod', 20, 40, 10) # 增加第一个优化参数,起始30,结束50,步进10
setting.addParameter('slowPeriod', 40, 80, 20) # 增加第二个优化参数,起始60,结束30,步进10
# setting.addParameter('signalMaPeriod', 10, 20, 5) # 增加第二个优化参数,起始10,结束30,步进5
setting.addParameter('symbolList', ['BTCUSDT:binance'])
import time
start = time.time()
# 执行单线程优化
resultList = engine.runOptimization(MultiFrameMaStrategy, setting)
# 执行多进程优化一般会改写成py文件然后用多线程运行,提高优化速度。
# resultList = engine.runParallelOptimization(MultiFrameMaStrategy, setting)
print('耗时:%s' %(time.time()-start))
2018-11-27 16:42:45.230052 计算按日统计结果
2018-11-27 16:42:45.247034 ------------------------------
2018-11-27 16:42:45.247034 优化结果:
2018-11-27 16:42:45.247034 参数:["{'fastPeriod': 20, 'slowPeriod': 40, 'symbolList': ['BTCUSDT:binance']}"],目标:3.8373178980181555
2018-11-27 16:42:45.247034 参数:["{'fastPeriod': 20, 'slowPeriod': 60, 'symbolList': ['BTCUSDT:binance']}"],目标:3.7506375116750355
2018-11-27 16:42:45.247034 参数:["{'fastPeriod': 30, 'slowPeriod': 40, 'symbolList': ['BTCUSDT:binance']}"],目标:3.6425674453940045
2018-11-27 16:42:45.247034 参数:["{'fastPeriod': 20, 'slowPeriod': 80, 'symbolList': ['BTCUSDT:binance']}"],目标:3.5332416281547103
2018-11-27 16:42:45.247034 参数:["{'fastPeriod': 40, 'slowPeriod': 40, 'symbolList': ['BTCUSDT:binance']}"],目标:3.117938276707989
2018-11-27 16:42:45.247034 参数:["{'fastPeriod': 30, 'slowPeriod': 80, 'symbolList': ['BTCUSDT:binance']}"],目标:2.9456588639684242
2018-11-27 16:42:45.247034 参数:["{'fastPeriod': 30, 'slowPeriod': 60, 'symbolList': ['BTCUSDT:binance']}"],目标:2.919579847922548
2018-11-27 16:42:45.247034 参数:["{'fastPeriod': 40, 'slowPeriod': 60, 'symbolList': ['BTCUSDT:binance']}"],目标:2.6339188082989096
2018-11-27 16:42:45.247034 参数:["{'fastPeriod': 40, 'slowPeriod': 80, 'symbolList': ['BTCUSDT:binance']}"],目标:2.458459639228935
耗时:160.99369764328003
import pandas as pd
print(pd.DataFrame(resultList).sort_values(1, ascending=False))
0 1 \
0 [{'fastPeriod': 20, 'slowPeriod': 40, 'symbolL... 3.837318
1 [{'fastPeriod': 20, 'slowPeriod': 60, 'symbolL... 3.750638
2 [{'fastPeriod': 30, 'slowPeriod': 40, 'symbolL... 3.642567
3 [{'fastPeriod': 20, 'slowPeriod': 80, 'symbolL... 3.533242
4 [{'fastPeriod': 40, 'slowPeriod': 40, 'symbolL... 3.117938
5 [{'fastPeriod': 30, 'slowPeriod': 80, 'symbolL... 2.945659
6 [{'fastPeriod': 30, 'slowPeriod': 60, 'symbolL... 2.919580
7 [{'fastPeriod': 40, 'slowPeriod': 60, 'symbolL... 2.633919
8 [{'fastPeriod': 40, 'slowPeriod': 80, 'symbolL... 2.458460
2
0 {'startDate': 2018-09-01 00:00:00, 'endDate': ...
1 {'startDate': 2018-09-01 00:00:00, 'endDate': ...
2 {'startDate': 2018-09-01 00:00:00, 'endDate': ...
3 {'startDate': 2018-09-01 00:00:00, 'endDate': ...
4 {'startDate': 2018-09-01 00:00:00, 'endDate': ...
5 {'startDate': 2018-09-01 00:00:00, 'endDate': ...
6 {'startDate': 2018-09-01 00:00:00, 'endDate': ...
7 {'startDate': 2018-09-01 00:00:00, 'endDate': ...
8 {'startDate': 2018-09-01 00:00:00, 'endDate': ...
# 显示优化的所有统计数据
for result in resultList:
print('-' * 30)
print('参数:%s,目标:%s' %(result[0], result[1]))
print('统计数据:')
for k, v in result[2].items():
print('%s:%s' %(k, v))
------------------------------
参数:["{'fastPeriod': 20, 'slowPeriod': 40, 'symbolList': ['BTCUSDT:binance']}"],目标:3.8373178980181555
统计数据:
startDate:2018-09-01 00:00:00
endDate:2018-11-23 00:00:00
totalDays:84
profitDays:43
lossDays:40
endBalance:1002162.8486499999
maxDrawdown:-800.1604799999623
maxDdPercent:-0.0802844900912358
totalNetPnl:2162.8486499999967
dailyNetPnl:25.748198214285676
totalCommission:366.11134999999996
dailyCommission:4.358468452380952
totalSlippage:0.23000000000000015
dailySlippage:0.00273809523809524
totalTurnover:732222.7000000001
dailyTurnover:8716.936904761906
totalTradeCount:115
dailyTradeCount:1.369047619047619
totalReturn:0.21628486500000488
annualizedReturn:0.617956757142871
dailyReturn:0.009231223526044257
returnStd:0.037268087692137686
sharpeRatio:3.8373178980181555
------------------------------
参数:["{'fastPeriod': 20, 'slowPeriod': 60, 'symbolList': ['BTCUSDT:binance']}"],目标:3.7506375116750355
统计数据:
startDate:2018-09-01 00:00:00
endDate:2018-11-23 00:00:00
totalDays:84
profitDays:50
lossDays:32
endBalance:1002955.52815
maxDrawdown:-312.15648999996483
maxDdPercent:-0.031176176911619793
totalNetPnl:2955.528149999998
dailyNetPnl:35.1848589285714
totalCommission:216.72784999999996
dailyCommission:2.580093452380952
totalSlippage:0.13400000000000006
dailySlippage:0.001595238095238096
totalTurnover:433455.70000000007
dailyTurnover:5160.186904761906
totalTradeCount:67
dailyTradeCount:0.7976190476190477
totalReturn:0.29555281499999975
annualizedReturn:0.8444366142857136
dailyReturn:0.0033835644182150003
returnStd:0.013975745298525763
sharpeRatio:3.7506375116750355