From 346368cd2ed85b14c6b318b679a9ca9a6e07a330 Mon Sep 17 00:00:00 2001 From: "vn.py" Date: Wed, 30 Jan 2019 04:39:04 +0800 Subject: [PATCH] [Fix] bug in calculating daily backtesting pnl result --- .../turtle-checkpoint.ipynb | 82 +++++++++++++- tests/backtesting/turtle.ipynb | 104 ++++++++++++++++-- vnpy/app/cta_strategy/backtesting.py | 12 +- 3 files changed, 182 insertions(+), 16 deletions(-) diff --git a/tests/backtesting/.ipynb_checkpoints/turtle-checkpoint.ipynb b/tests/backtesting/.ipynb_checkpoints/turtle-checkpoint.ipynb index 2fd64429..43727aff 100644 --- a/tests/backtesting/.ipynb_checkpoints/turtle-checkpoint.ipynb +++ b/tests/backtesting/.ipynb_checkpoints/turtle-checkpoint.ipynb @@ -1,6 +1,84 @@ { - "cells": [], - "metadata": {}, + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#%%\n", + "from vnpy.app.cta_strategy.backtesting import BacktestingEngine\n", + "from vnpy.app.cta_strategy.strategies.turtle_signal_strategy import (\n", + " TurtleSignalStrategy,\n", + ")\n", + "from datetime import datetime" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#%%\n", + "engine = BacktestingEngine()\n", + "engine.set_parameters(\n", + " vt_symbol=\"IF88.CFFEX\",\n", + " interval=\"1m\",\n", + " start=datetime(2013, 1, 1),\n", + " end=datetime(2015, 3, 30),\n", + " rate=0,\n", + " slippage=0,\n", + " size=300,\n", + " pricetick=0.2,\n", + " capital=1_000_000,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "scrolled": false + }, + "outputs": [], + "source": [ + "#%%\n", + "engine.add_strategy(TurtleSignalStrategy, {})\n", + "engine.load_data()\n", + "engine.run_backtesting()\n", + "df = engine.calculate_result()\n", + "engine.calculate_statistics()\n", + "engine.show_chart()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.1" + } + }, "nbformat": 4, "nbformat_minor": 2 } diff --git a/tests/backtesting/turtle.ipynb b/tests/backtesting/turtle.ipynb index 5a54df76..e871bef6 100644 --- a/tests/backtesting/turtle.ipynb +++ b/tests/backtesting/turtle.ipynb @@ -4,22 +4,106 @@ "cell_type": "code", "execution_count": 1, "metadata": {}, + "outputs": [], + "source": [ + "#%%\n", + "from vnpy.app.cta_strategy.backtesting import BacktestingEngine\n", + "from vnpy.app.cta_strategy.strategies.turtle_signal_strategy import (\n", + " TurtleSignalStrategy,\n", + ")\n", + "from datetime import datetime" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "#%%\n", + "engine = BacktestingEngine()\n", + "engine.set_parameters(\n", + " vt_symbol=\"IF88.CFFEX\",\n", + " interval=\"1m\",\n", + " start=datetime(2013, 1, 1),\n", + " end=datetime(2015, 3, 30),\n", + " rate=0,\n", + " slippage=0,\n", + " size=300,\n", + " pricetick=0.2,\n", + " capital=1_000_000,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "scrolled": false + }, "outputs": [ { - "ename": "SyntaxError", - "evalue": "invalid syntax (backtesting.py, line 890)", - "output_type": "error", - "traceback": [ - "Traceback \u001b[1;36m(most recent call last)\u001b[0m:\n", - " File \u001b[0;32m\"c:\\miniconda3\\lib\\site-packages\\IPython\\core\\interactiveshell.py\"\u001b[0m, line \u001b[0;32m3267\u001b[0m, in \u001b[0;35mrun_code\u001b[0m\n exec(code_obj, self.user_global_ns, self.user_ns)\n", - "\u001b[1;36m File \u001b[1;32m\"\"\u001b[1;36m, line \u001b[1;32m1\u001b[1;36m, in \u001b[1;35m\u001b[1;36m\u001b[0m\n\u001b[1;33m from vnpy.app.cta_strategy.backtesting import BacktestingEngine\u001b[0m\n", - "\u001b[1;36m File \u001b[1;32m\"C:\\Github\\vnpy\\vnpy\\app\\cta_strategy\\backtesting.py\"\u001b[1;36m, line \u001b[1;32m890\u001b[0m\n\u001b[1;33m rate=rate,\u001b[0m\n\u001b[1;37m ^\u001b[0m\n\u001b[1;31mSyntaxError\u001b[0m\u001b[1;31m:\u001b[0m invalid syntax\n" + "name": "stdout", + "output_type": "stream", + "text": [ + "2019-01-30 04:34:46.991182\t开始加载历史数据\n", + "2019-01-30 04:34:51.884218\t历史数据加载完成,数据量:64800\n", + "2019-01-30 04:34:52.102901\t策略初始化完成\n", + "2019-01-30 04:34:52.102901\t开始回放历史数据\n", + "2013-02-01 09:48:00 1 Direction.LONG 2687.2000000000003 1\n", + "2013-02-01 09:58:00 2 Direction.SHORT 2683.8 1\n", + "2019-01-30 04:34:54.062263\t历史数据回放结束\n", + "2019-01-30 04:34:54.062263\t开始计算逐日盯市盈亏\n", + "2019-01-30 04:34:54.062263\t逐日盯市盈亏计算完成\n", + "2019-01-30 04:34:54.062263\t开始计算策略统计指标\n", + "2019-01-30 04:34:54.077883\t------------------------------\n", + "2019-01-30 04:34:54.077883\t首个交易日:\t2013-02-01\n", + "2019-01-30 04:34:54.077883\t最后交易日:\t2014-01-03\n", + "2019-01-30 04:34:54.077883\t总交易日:\t220\n", + "2019-01-30 04:34:54.077883\t盈利交易日:\t0\n", + "2019-01-30 04:34:54.077883\t亏损交易日:\t1\n", + "2019-01-30 04:34:54.077883\t起始资金:\t1,000,000.00\n", + "2019-01-30 04:34:54.077883\t结束资金:\t998,980.00\n", + "2019-01-30 04:34:54.077883\t总收益率:\t-0.10%\n", + "2019-01-30 04:34:54.077883\t年化收益:\t-0.11%\n", + "2019-01-30 04:34:54.077883\t最大回撤: \t0.00%\n", + "2019-01-30 04:34:54.077883\t百分比最大回撤: 0.00%\n", + "2019-01-30 04:34:54.077883\t总盈亏:\t-1,020.00%\n", + "2019-01-30 04:34:54.077883\t总手续费:\t0.00\n", + "2019-01-30 04:34:54.077883\t总滑点:\t0.00\n", + "2019-01-30 04:34:54.077883\t总成交金额:\t1,611,300.00\n", + "2019-01-30 04:34:54.077883\t总成交笔数:\t2\n", + "2019-01-30 04:34:54.077883\t日均盈亏:\t-4.64\n", + "2019-01-30 04:34:54.077883\t日均手续费:\t0.00\n", + "2019-01-30 04:34:54.077883\t日均滑点:\t0.00\n", + "2019-01-30 04:34:54.077883\t日均成交金额:\t7,324.09\n", + "2019-01-30 04:34:54.077883\t日均成交笔数:\t0.00909090909090909\n", + "2019-01-30 04:34:54.077883\t日均收益率:\t1,375.17%\n", + "2019-01-30 04:34:54.077883\t收益标准差:\t93.14%\n", + "2019-01-30 04:34:54.077883\tSharpe Ratio:\t228.74\n" ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" } ], "source": [ - "from vnpy.app.cta_strategy.backtesting import BacktestingEngine\n", - "from vnpy.app.cta_strategy.strategies.turtle_signal_strategy import TurtleSignalStrategy" + "#%%\n", + "engine.add_strategy(TurtleSignalStrategy, {})\n", + "engine.load_data()\n", + "engine.run_backtesting()\n", + "df = engine.calculate_result()\n", + "engine.calculate_statistics()\n", + "engine.show_chart()" ] }, { diff --git a/vnpy/app/cta_strategy/backtesting.py b/vnpy/app/cta_strategy/backtesting.py index 7f6f5acf..78ae4e7d 100644 --- a/vnpy/app/cta_strategy/backtesting.py +++ b/vnpy/app/cta_strategy/backtesting.py @@ -12,6 +12,8 @@ from pandas import DataFrame from vnpy.trader.constant import Direction, Exchange, Interval, Status from vnpy.trader.database import DbBarData, DbTickData from vnpy.trader.object import OrderData, TradeData +from vnpy.trader.utility import round_to_pricetick + from .base import ( BacktestingMode, CtaOrderType, @@ -698,6 +700,7 @@ class BacktestingEngine: stop: bool = False, ): """""" + price = round_to_pricetick(price, self.pricetick) if stop: return self.send_stop_order(order_type, price, volume) else: @@ -846,18 +849,19 @@ class DailyResult: ): """""" # Holding pnl is the pnl from holding position at day start - self.start_pos = self.end_pos = start_pos + self.start_pos = start_pos + self.end_pos = start_pos self.holding_pnl = self.start_pos * (self.close_price - self.pre_close) * size # Trading pnl is the pnl from new trade during the day self.trade_count = len(self.trades) - pos_change = 0 for trade in self.trades: if trade.direction == Direction.LONG: - pos_change += trade.volume + pos_change = trade.volume else: - pos_change -= trade.volume + pos_change = -trade.volume + turnover = trade.price * trade.volume * size self.trading_pnl += pos_change * (self.close_price - trade.price) * size