2017-06-02 13:44:28 +00:00
|
|
|
|
{
|
|
|
|
|
"cells": [
|
|
|
|
|
{
|
|
|
|
|
"cell_type": "code",
|
2017-12-04 07:37:15 +00:00
|
|
|
|
"execution_count": 1,
|
2017-06-02 13:44:28 +00:00
|
|
|
|
"metadata": {
|
|
|
|
|
"collapsed": false
|
|
|
|
|
},
|
|
|
|
|
"outputs": [],
|
|
|
|
|
"source": [
|
|
|
|
|
"%matplotlib inline\n",
|
|
|
|
|
"\n",
|
|
|
|
|
"from vnpy.trader.app.ctaStrategy.ctaBacktesting import BacktestingEngine, OptimizationSetting, MINUTE_DB_NAME\n",
|
2017-12-15 15:05:22 +00:00
|
|
|
|
"#from vnpy.trader.app.ctaStrategy.strategy.strategyAtrRsi import AtrRsiStrategy\n",
|
|
|
|
|
"#from vnpy.trader.app.ctaStrategy.strategy.strategyMultiTimeframe import MultiTimeframeStrategy\n",
|
|
|
|
|
"from vnpy.trader.app.ctaStrategy.strategy.strategyMultiSignal import MultiSignalStrategy"
|
2017-06-02 13:44:28 +00:00
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"cell_type": "code",
|
2017-12-04 07:37:15 +00:00
|
|
|
|
"execution_count": 2,
|
2017-06-02 13:44:28 +00:00
|
|
|
|
"metadata": {
|
|
|
|
|
"collapsed": true
|
|
|
|
|
},
|
|
|
|
|
"outputs": [],
|
|
|
|
|
"source": [
|
|
|
|
|
"# 创建回测引擎对象\n",
|
|
|
|
|
"engine = BacktestingEngine()"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"cell_type": "code",
|
2017-12-04 07:37:15 +00:00
|
|
|
|
"execution_count": 3,
|
2017-06-02 13:44:28 +00:00
|
|
|
|
"metadata": {
|
|
|
|
|
"collapsed": false
|
|
|
|
|
},
|
|
|
|
|
"outputs": [],
|
|
|
|
|
"source": [
|
|
|
|
|
"# 设置回测使用的数据\n",
|
|
|
|
|
"engine.setBacktestingMode(engine.BAR_MODE) # 设置引擎的回测模式为K线\n",
|
|
|
|
|
"engine.setDatabase(MINUTE_DB_NAME, 'IF0000') # 设置使用的历史数据库\n",
|
2017-12-15 15:05:22 +00:00
|
|
|
|
"engine.setStartDate('20100101') # 设置回测用的数据起始日期"
|
2017-06-02 13:44:28 +00:00
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"cell_type": "code",
|
2017-12-04 07:37:15 +00:00
|
|
|
|
"execution_count": 4,
|
2017-06-02 13:44:28 +00:00
|
|
|
|
"metadata": {
|
|
|
|
|
"collapsed": true
|
|
|
|
|
},
|
|
|
|
|
"outputs": [],
|
|
|
|
|
"source": [
|
|
|
|
|
"# 配置回测引擎参数\n",
|
|
|
|
|
"engine.setSlippage(0.2) # 设置滑点为股指1跳\n",
|
|
|
|
|
"engine.setRate(0.3/10000) # 设置手续费万0.3\n",
|
|
|
|
|
"engine.setSize(300) # 设置股指合约大小 \n",
|
2017-07-14 12:12:42 +00:00
|
|
|
|
"engine.setPriceTick(0.2) # 设置股指最小价格变动 \n",
|
|
|
|
|
"engine.setCapital(1000000) # 设置回测本金"
|
2017-06-02 13:44:28 +00:00
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"cell_type": "code",
|
2017-12-04 07:37:15 +00:00
|
|
|
|
"execution_count": 5,
|
2017-06-02 13:44:28 +00:00
|
|
|
|
"metadata": {
|
2017-10-07 14:36:23 +00:00
|
|
|
|
"collapsed": false
|
2017-06-02 13:44:28 +00:00
|
|
|
|
},
|
|
|
|
|
"outputs": [],
|
|
|
|
|
"source": [
|
|
|
|
|
"# 在引擎中创建策略对象\n",
|
|
|
|
|
"d = {'atrLength': 11} # 策略参数配置\n",
|
2017-12-04 07:37:15 +00:00
|
|
|
|
"#engine.initStrategy(AtrRsiStrategy, d) # 创建策略对象\n",
|
2017-12-15 15:05:22 +00:00
|
|
|
|
"#ngine.initStrategy(MultiTimeframeStrategy, d) \n",
|
|
|
|
|
"engine.initStrategy(MultiSignalStrategy, {}) "
|
2017-06-02 13:44:28 +00:00
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"cell_type": "code",
|
2017-12-16 01:02:32 +00:00
|
|
|
|
"execution_count": 6,
|
2017-06-02 13:44:28 +00:00
|
|
|
|
"metadata": {
|
|
|
|
|
"collapsed": false
|
|
|
|
|
},
|
2017-12-16 01:02:32 +00:00
|
|
|
|
"outputs": [
|
|
|
|
|
{
|
|
|
|
|
"name": "stdout",
|
|
|
|
|
"output_type": "stream",
|
|
|
|
|
"text": [
|
|
|
|
|
"2017-12-15 23:03:42.343000\t开始载入数据\n",
|
|
|
|
|
"2017-12-15 23:03:42.364000\t载入完成,数据量:39389\n",
|
|
|
|
|
"2017-12-15 23:03:42.364000\t开始回测\n",
|
|
|
|
|
"2017-12-15 23:03:42.364000\t策略初始化完成\n",
|
|
|
|
|
"2017-12-15 23:03:42.364000\t策略启动完成\n",
|
|
|
|
|
"2017-12-15 23:03:42.364000\t开始回放数据\n",
|
|
|
|
|
"2017-12-15 23:03:46.010000\t数据回放结束\n"
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
],
|
2017-06-02 13:44:28 +00:00
|
|
|
|
"source": [
|
|
|
|
|
"# 运行回测\n",
|
|
|
|
|
"engine.runBacktesting() # 运行回测"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"cell_type": "code",
|
2017-12-16 01:02:32 +00:00
|
|
|
|
"execution_count": 7,
|
2017-06-02 13:44:28 +00:00
|
|
|
|
"metadata": {
|
2017-09-25 05:51:24 +00:00
|
|
|
|
"collapsed": false
|
2017-06-02 13:44:28 +00:00
|
|
|
|
},
|
2017-12-16 01:02:32 +00:00
|
|
|
|
"outputs": [
|
|
|
|
|
{
|
|
|
|
|
"name": "stdout",
|
|
|
|
|
"output_type": "stream",
|
|
|
|
|
"text": [
|
|
|
|
|
"2017-12-15 23:03:46.017000\t计算按日统计结果\n",
|
|
|
|
|
"2017-12-15 23:03:46.369000\t------------------------------\n",
|
|
|
|
|
"2017-12-15 23:03:46.369000\t首个交易日:\t2010-04-16\n",
|
|
|
|
|
"2017-12-15 23:03:46.369000\t最后交易日:\t2010-11-23\n",
|
|
|
|
|
"2017-12-15 23:03:46.370000\t总交易日:\t146\n",
|
|
|
|
|
"2017-12-15 23:03:46.370000\t盈利交易日\t63\n",
|
|
|
|
|
"2017-12-15 23:03:46.370000\t亏损交易日:\t83\n",
|
|
|
|
|
"2017-12-15 23:03:46.370000\t起始资金:\t1000000\n",
|
|
|
|
|
"2017-12-15 23:03:46.370000\t结束资金:\t988,845.07\n",
|
|
|
|
|
"2017-12-15 23:03:46.370000\t总收益率:\t-1.12\n",
|
|
|
|
|
"2017-12-15 23:03:46.371000\t总盈亏:\t-11,154.93\n",
|
|
|
|
|
"2017-12-15 23:03:46.371000\t最大回撤: \t-241,691.12\n",
|
|
|
|
|
"2017-12-15 23:03:46.371000\t总手续费:\t242,094.93\n",
|
|
|
|
|
"2017-12-15 23:03:46.371000\t总滑点:\t541,680.0\n",
|
|
|
|
|
"2017-12-15 23:03:46.371000\t总成交金额:\t8,069,830,980.0\n",
|
|
|
|
|
"2017-12-15 23:03:46.371000\t总成交笔数:\t7,039.0\n",
|
|
|
|
|
"2017-12-15 23:03:46.371000\t日均盈亏:\t-76.4\n",
|
|
|
|
|
"2017-12-15 23:03:46.371000\t日均手续费:\t1,658.18\n",
|
|
|
|
|
"2017-12-15 23:03:46.371000\t日均滑点:\t3,710.14\n",
|
|
|
|
|
"2017-12-15 23:03:46.371000\t日均成交金额:\t55,272,814.93\n",
|
|
|
|
|
"2017-12-15 23:03:46.371000\t日均成交笔数:\t48.21\n",
|
|
|
|
|
"2017-12-15 23:03:46.371000\t日均收益率:\t-0.0%\n",
|
|
|
|
|
"2017-12-15 23:03:46.371000\t收益标准差:\t3.01%\n",
|
|
|
|
|
"2017-12-15 23:03:46.371000\tSharpe Ratio:\t-0.01\n"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"data": {
|
|
|
|
|
"image/png": "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\nYsTFxdl6Ga2QSCQICwu
|
|
|
|
|
"text/plain": [
|
|
|
|
|
"<matplotlib.figure.Figure at 0xe43a3b0>"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
"metadata": {},
|
|
|
|
|
"output_type": "display_data"
|
|
|
|
|
}
|
|
|
|
|
],
|
2017-06-02 13:44:28 +00:00
|
|
|
|
"source": [
|
2017-07-14 12:12:42 +00:00
|
|
|
|
"# 显示逐日回测结果\n",
|
2017-10-07 15:25:59 +00:00
|
|
|
|
"engine.showDailyResult()"
|
2017-06-02 13:44:28 +00:00
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"cell_type": "code",
|
2017-10-07 14:36:23 +00:00
|
|
|
|
"execution_count": null,
|
2017-06-02 13:44:28 +00:00
|
|
|
|
"metadata": {
|
|
|
|
|
"collapsed": false
|
|
|
|
|
},
|
2017-10-07 14:36:23 +00:00
|
|
|
|
"outputs": [],
|
2017-07-14 12:12:42 +00:00
|
|
|
|
"source": [
|
|
|
|
|
"# 显示逐笔回测结果\n",
|
|
|
|
|
"engine.showBacktestingResult()"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"cell_type": "code",
|
2017-10-07 14:36:23 +00:00
|
|
|
|
"execution_count": null,
|
2017-07-14 12:12:42 +00:00
|
|
|
|
"metadata": {
|
|
|
|
|
"collapsed": false
|
|
|
|
|
},
|
2017-10-07 14:36:23 +00:00
|
|
|
|
"outputs": [],
|
2017-06-02 13:44:28 +00:00
|
|
|
|
"source": [
|
|
|
|
|
"# 显示前10条成交记录\n",
|
|
|
|
|
"for i in range(10):\n",
|
2017-09-25 05:51:24 +00:00
|
|
|
|
" d = engine.tradeDict[str(i+1)].__dict__\n",
|
|
|
|
|
" print 'TradeID: %s, Time: %s, Direction: %s, Price: %s, Volume: %s' %(d['tradeID'], d['dt'], d['direction'], d['price'], d['volume'])"
|
2017-06-02 13:44:28 +00:00
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"cell_type": "code",
|
2017-10-07 14:36:23 +00:00
|
|
|
|
"execution_count": null,
|
2017-06-02 13:44:28 +00:00
|
|
|
|
"metadata": {
|
|
|
|
|
"collapsed": false
|
|
|
|
|
},
|
2017-10-07 14:36:23 +00:00
|
|
|
|
"outputs": [],
|
2017-06-02 13:44:28 +00:00
|
|
|
|
"source": [
|
|
|
|
|
"# 优化配置\n",
|
|
|
|
|
"setting = OptimizationSetting() # 新建一个优化任务设置对象\n",
|
|
|
|
|
"setting.setOptimizeTarget('capital') # 设置优化排序的目标是策略净盈利\n",
|
|
|
|
|
"setting.addParameter('atrLength', 12, 20, 2) # 增加第一个优化参数atrLength,起始12,结束20,步进2\n",
|
|
|
|
|
"setting.addParameter('atrMa', 20, 30, 5) # 增加第二个优化参数atrMa,起始20,结束30,步进5\n",
|
|
|
|
|
"setting.addParameter('rsiLength', 5) # 增加一个固定数值的参数\n",
|
|
|
|
|
"\n",
|
|
|
|
|
"# 执行多进程优化\n",
|
|
|
|
|
"import time\n",
|
2017-09-25 05:51:24 +00:00
|
|
|
|
"start = time.time()\n",
|
2017-06-02 13:44:28 +00:00
|
|
|
|
"engine.runParallelOptimization(AtrRsiStrategy, setting)\n",
|
|
|
|
|
"print u'耗时:%s' %(time.time()-start)"
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"cell_type": "code",
|
|
|
|
|
"execution_count": null,
|
|
|
|
|
"metadata": {
|
|
|
|
|
"collapsed": true
|
|
|
|
|
},
|
|
|
|
|
"outputs": [],
|
|
|
|
|
"source": []
|
|
|
|
|
}
|
|
|
|
|
],
|
|
|
|
|
"metadata": {
|
|
|
|
|
"kernelspec": {
|
|
|
|
|
"display_name": "Python 2",
|
|
|
|
|
"language": "python",
|
|
|
|
|
"name": "python2"
|
|
|
|
|
},
|
|
|
|
|
"language_info": {
|
|
|
|
|
"codemirror_mode": {
|
|
|
|
|
"name": "ipython",
|
|
|
|
|
"version": 2
|
|
|
|
|
},
|
|
|
|
|
"file_extension": ".py",
|
|
|
|
|
"mimetype": "text/x-python",
|
|
|
|
|
"name": "python",
|
|
|
|
|
"nbconvert_exporter": "python",
|
|
|
|
|
"pygments_lexer": "ipython2",
|
|
|
|
|
"version": "2.7.13"
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
"nbformat": 4,
|
|
|
|
|
"nbformat_minor": 0
|
|
|
|
|
}
|