[Add]增加海龟回测中的手续费和滑点计算

This commit is contained in:
vn.py 2018-11-11 14:57:51 +08:00
parent 7071af22c2
commit e5c0850956
4 changed files with 63 additions and 247 deletions

View File

@ -6,13 +6,11 @@
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
"import sys\n",
"reload(sys)\n",
"\n",
"\n",
"%matplotlib inline\n", "%matplotlib inline\n",
"\n", "\n",
"from datetime import datetime\n", "from datetime import datetime\n",
"\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n", "import matplotlib.pyplot as plt\n",
"\n", "\n",
"from turtleEngine import BacktestingEngine" "from turtleEngine import BacktestingEngine"
@ -22,28 +20,33 @@
"cell_type": "code", "cell_type": "code",
"execution_count": 2, "execution_count": 2,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [
{
"ename": "TypeError",
"evalue": "coercing to Unicode: need string or buffer, int found",
"output_type": "error",
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[1;31mTypeError\u001b[0m Traceback (most recent call last)",
"\u001b[1;32m<ipython-input-2-a69b1c674549>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[0;32m 1\u001b[0m \u001b[0mengine\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mBacktestingEngine\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 2\u001b[0m \u001b[0mengine\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msetPeriod\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mdatetime\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m2015\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m1\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mdatetime\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m2018\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m11\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m9\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 3\u001b[1;33m \u001b[0mengine\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0minitPortfolio\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m10000000\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;34m'setting.csv'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[1;32mC:\\Github\\vnpy\\examples\\TurtleStrategy\\turtleEngine.py\u001b[0m in \u001b[0;36minitPortfolio\u001b[1;34m(self, filename, portfolioValue)\u001b[0m\n\u001b[0;32m 60\u001b[0m \u001b[1;32mdef\u001b[0m \u001b[0minitPortfolio\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mself\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mfilename\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mportfolioValue\u001b[0m\u001b[1;33m=\u001b[0m\u001b[1;36m10000000\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 61\u001b[0m \u001b[1;34m\"\"\"\"\"\"\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 62\u001b[1;33m \u001b[1;32mwith\u001b[0m \u001b[0mopen\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mfilename\u001b[0m\u001b[1;33m)\u001b[0m \u001b[1;32mas\u001b[0m \u001b[0mf\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m 63\u001b[0m \u001b[0mr\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mDictReader\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mf\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 64\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0md\u001b[0m \u001b[1;32min\u001b[0m \u001b[0mr\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
"\u001b[1;31mTypeError\u001b[0m: coercing to Unicode: need string or buffer, int found"
]
}
],
"source": [ "source": [
"l = ['IF99'] #, 'CU99', 'I99', 'TA99']\n",
"engine = BacktestingEngine()\n", "engine = BacktestingEngine()\n",
"engine.setPeriod(datetime(2015, 1, 1), datetime(2018, 11, 9))\n", "engine.setPeriod(datetime(2015, 1, 1), datetime(2018, 11, 9))\n",
"engine.initPortfolio(l)" "engine.initPortfolio('setting.csv')"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 3, "execution_count": null,
"metadata": {}, "metadata": {
"outputs": [ "scrolled": false
{ },
"name": "stdout", "outputs": [],
"output_type": "stream",
"text": [
"11:39:12.298000:IF99数据加载完成总数据量940\n",
"11:39:12.299000:全部数据加载完成\n"
]
}
],
"source": [ "source": [
"engine.loadData()\n", "engine.loadData()\n",
"engine.runBacktesting()\n", "engine.runBacktesting()\n",
@ -52,34 +55,16 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 4, "execution_count": null,
"metadata": {}, "metadata": {
"outputs": [ "scrolled": false
{
"name": "stdout",
"output_type": "stream",
"text": [
"2015-06-08 00:00:00\n"
]
}, },
{ "outputs": [],
"ename": "UnicodeDecodeError",
"evalue": "'ascii' codec can't decode byte 0xe5 in position 0: ordinal not in range(128)",
"output_type": "error",
"traceback": [
"\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
"\u001b[1;31mUnicodeDecodeError\u001b[0m Traceback (most recent call last)",
"\u001b[1;32m<ipython-input-4-74c05e0f545f>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[0;32m 2\u001b[0m \u001b[1;32mprint\u001b[0m \u001b[0mdt\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 3\u001b[0m \u001b[1;32mfor\u001b[0m \u001b[0mtrade\u001b[0m \u001b[1;32min\u001b[0m \u001b[0ml\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m----> 4\u001b[1;33m \u001b[1;32mprint\u001b[0m \u001b[0mtrade\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m",
"\u001b[1;32mC:\\Github\\vnpy\\examples\\TurtleStrategy\\turtleEngine.py\u001b[0m in \u001b[0;36m__str__\u001b[1;34m(self)\u001b[0m\n\u001b[0;32m 134\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0moffset\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mencode\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;34m'UTF-8'\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 135\u001b[0m \u001b[0mself\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mvolume\u001b[0m\u001b[1;33m,\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m--> 136\u001b[1;33m self.price)\n\u001b[0m\u001b[0;32m 137\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 138\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
"\u001b[1;31mUnicodeDecodeError\u001b[0m: 'ascii' codec can't decode byte 0xe5 in position 0: ordinal not in range(128)"
]
}
],
"source": [ "source": [
"for dt, l in engine.tradeDict.items():\n", "for dt, l in engine.tradeDict.items():\n",
" print dt\n", " print dt\n",
" for trade in l:\n", " for trade in l:\n",
" print trade" " print trade.vtSymbol, trade.direction, trade.offset, trade.price, trade.volume"
] ]
}, },
{ {
@ -91,29 +76,16 @@
"outputs": [], "outputs": [],
"source": [ "source": [
"for result in engine.resultList:\n", "for result in engine.resultList:\n",
" if result.totalPnl:\n",
" print result.date, result.totalPnl" " print result.date, result.totalPnl"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"metadata": {}, "metadata": {
"outputs": [], "scrolled": true
"source": []
}, },
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
"l = [result.totalPnl for result in engine.resultList]\n", "l = [result.totalPnl for result in engine.resultList]\n",
@ -121,25 +93,6 @@
"plt.plot(equity)" "plt.plot(equity)"
] ]
}, },
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"for data in engine.dataDict.values():\n",
" print data"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print trade."
]
},
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,

View File

@ -6,13 +6,11 @@
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
"import sys\n",
"reload(sys)\n",
"\n",
"\n",
"%matplotlib inline\n", "%matplotlib inline\n",
"\n", "\n",
"from datetime import datetime\n", "from datetime import datetime\n",
"\n",
"import numpy as np\n",
"import matplotlib.pyplot as plt\n", "import matplotlib.pyplot as plt\n",
"\n", "\n",
"from turtleEngine import BacktestingEngine" "from turtleEngine import BacktestingEngine"
@ -20,30 +18,22 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 2, "execution_count": null,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
"l = ['IF99'] #, 'CU99', 'I99', 'TA99']\n",
"engine = BacktestingEngine()\n", "engine = BacktestingEngine()\n",
"engine.setPeriod(datetime(2015, 1, 1), datetime(2018, 11, 9))\n", "engine.setPeriod(datetime(2015, 1, 1), datetime(2018, 11, 9))\n",
"engine.initPortfolio(l)" "engine.initPortfolio('setting.csv', 10000000)"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 3, "execution_count": null,
"metadata": {}, "metadata": {
"outputs": [ "scrolled": false
{ },
"name": "stdout", "outputs": [],
"output_type": "stream",
"text": [
"11:39:12.298000:IF99数据加载完成总数据量940\n",
"11:39:12.299000:全部数据加载完成\n"
]
}
],
"source": [ "source": [
"engine.loadData()\n", "engine.loadData()\n",
"engine.runBacktesting()\n", "engine.runBacktesting()\n",
@ -52,122 +42,11 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 5, "execution_count": null,
"metadata": {}, "metadata": {
"outputs": [ "scrolled": false
{ },
"name": "stdout", "outputs": [],
"output_type": "stream",
"text": [
"2015-06-08 00:00:00\n",
"IF99 多 开仓 5370.6182 1\n",
"IF99 多 开仓 5370.6182 1\n",
"2015-06-17 00:00:00\n",
"IF99 空 平仓 4994.5359289007665 1\n",
"IF99 空 平仓 4994.5359289007665 1\n",
"2015-10-12 00:00:00\n",
"IF99 多 开仓 3341.0982 1\n",
"2015-10-26 00:00:00\n",
"IF99 多 开仓 3424.5987371468213 1\n",
"2015-11-04 00:00:00\n",
"IF99 多 开仓 3508.099274293643 1\n",
"2015-11-05 00:00:00\n",
"IF99 多 开仓 3591.5998114404642 1\n",
"2015-11-23 00:00:00\n",
"IF99 空 平仓 3603.8898 4\n",
"2015-12-21 00:00:00\n",
"IF99 多 开仓 3786.5235 1\n",
"2015-12-23 00:00:00\n",
"IF99 多 开仓 3834.280588057014 1\n",
"2015-12-28 00:00:00\n",
"IF99 空 平仓 3643.2522358289566 2\n",
"2016-03-07 00:00:00\n",
"IF99 多 开仓 3027.3054 1\n",
"IF99 多 开仓 3074.3983619185256 1\n",
"2016-03-18 00:00:00\n",
"IF99 多 开仓 3121.4913238370505 1\n",
"2016-03-21 00:00:00\n",
"IF99 多 开仓 3168.584285755576 1\n",
"2016-04-20 00:00:00\n",
"IF99 空 平仓 3105.8006 4\n",
"2016-07-07 00:00:00\n",
"IF99 多 开仓 3166.5061 1\n",
"2016-07-11 00:00:00\n",
"IF99 多 开仓 3194.9341606344988 1\n",
"IF99 多 开仓 3192.2685 1\n",
"2016-07-12 00:00:00\n",
"IF99 多 开仓 3223.3622212689975 1\n",
"2016-07-27 00:00:00\n",
"IF99 空 平仓 3173.5677 4\n",
"2016-08-11 00:00:00\n",
"IF99 多 开仓 3245.6871 1\n",
"2016-08-12 00:00:00\n",
"IF99 多 开仓 3268.4782362989677 1\n",
"IF99 多 开仓 3274.5309 1\n",
"2016-08-15 00:00:00\n",
"IF99 多 开仓 3291.269372597935 1\n",
"2016-08-25 00:00:00\n",
"IF99 空 平仓 3251.8034639734847 4\n",
"2016-10-19 00:00:00\n",
"IF99 多 开仓 3294.1809 1\n",
"2016-10-24 00:00:00\n",
"IF99 多 开仓 3313.0011487826814 1\n",
"IF99 多 开仓 3331.821397565363 1\n",
"IF99 多 开仓 3350.6416463480446 1\n",
"2016-12-07 00:00:00\n",
"IF99 空 平仓 3432.9777 4\n",
"2017-03-24 00:00:00\n",
"IF99 多 开仓 3468.6291 1\n",
"2017-03-30 00:00:00\n",
"IF99 空 平仓 3406.5561141656326 1\n",
"2017-04-05 00:00:00\n",
"IF99 多 开仓 3474.3432 1\n",
"IF99 多 开仓 3491.1258202647214 1\n",
"IF99 多 开仓 3474.3432 1\n",
"IF99 多 开仓 3491.1258202647214 1\n",
"2017-04-17 00:00:00\n",
"IF99 空 平仓 3440.7779594705567 3\n",
"IF99 空 平仓 3440.7779594705567 1\n",
"2017-05-25 00:00:00\n",
"IF99 多 开仓 3433.5201 1\n",
"IF99 多 开仓 3449.826458335901 1\n",
"IF99 多 开仓 3466.1328166718017 1\n",
"2017-05-26 00:00:00\n",
"IF99 多 开仓 3482.4391750077025 1\n",
"2017-06-15 00:00:00\n",
"IF99 空 平仓 3498.115614786368 4\n",
"2017-06-22 00:00:00\n",
"IF99 多 开仓 3579.0624 1\n",
"2017-06-26 00:00:00\n",
"IF99 多 开仓 3597.53568462007 1\n",
"IF99 多 开仓 3616.0089692401393 1\n",
"IF99 多 开仓 3634.4822538602093 1\n",
"2017-08-11 00:00:00\n",
"IF99 空 平仓 3656.9743 4\n",
"2018-01-02 00:00:00\n",
"IF99 多 开仓 4105.3543 1\n",
"2018-01-03 00:00:00\n",
"IF99 多 开仓 4132.444330290369 1\n",
"2018-01-08 00:00:00\n",
"IF99 多 开仓 4159.534360580738 1\n",
"2018-01-09 00:00:00\n",
"IF99 多 开仓 4186.624390871108 1\n",
"2018-02-01 00:00:00\n",
"IF99 空 平仓 4253.1416 4\n",
"2018-07-24 00:00:00\n",
"IF99 多 开仓 3507.8183 1\n",
"IF99 多 开仓 3547.101357149508 1\n",
"2018-08-02 00:00:00\n",
"IF99 空 平仓 3389.9691285514746 2\n",
"2018-09-21 00:00:00\n",
"IF99 多 开仓 3407.2856 1\n",
"2018-09-26 00:00:00\n",
"IF99 多 开仓 3438.7157642602238 1\n",
"2018-10-08 00:00:00\n",
"IF99 空 平仓 3312.9951072193303 2\n"
]
}
],
"source": [ "source": [
"for dt, l in engine.tradeDict.items():\n", "for dt, l in engine.tradeDict.items():\n",
" print dt\n", " print dt\n",
@ -184,29 +63,16 @@
"outputs": [], "outputs": [],
"source": [ "source": [
"for result in engine.resultList:\n", "for result in engine.resultList:\n",
" if result.totalPnl:\n",
" print result.date, result.totalPnl" " print result.date, result.totalPnl"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"metadata": {}, "metadata": {
"outputs": [], "scrolled": true
"source": []
}, },
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
"l = [result.totalPnl for result in engine.resultList]\n", "l = [result.totalPnl for result in engine.resultList]\n",
@ -219,19 +85,7 @@
"execution_count": null, "execution_count": null,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": []
"for data in engine.dataDict.values():\n",
" print data"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"print trade."
]
}, },
{ {
"cell_type": "code", "cell_type": "code",

View File

@ -203,12 +203,22 @@ class DailyResult(object):
close = self.closeDict[vtSymbol] close = self.closeDict[vtSymbol]
size = SIZE_DICT[vtSymbol] size = SIZE_DICT[vtSymbol]
slippage = SLIPPAGE_DICT[vtSymbol]
variableCommission = VARIABLE_COMMISSION_DICT[vtSymbol]
fixedCommission = FIXED_COMMISSION_DICT[vtSymbol]
for trade in l: for trade in l:
if trade.direction == DIRECTION_LONG: if trade.direction == DIRECTION_LONG:
side = 1 side = 1
else: else:
side = -1 side = -1
commissionCost = (trade.volume * fixedCommission +
trade.volume * trade.price * variableCommission)
slippageCost = trade.volume * slippage
pnl = (close - trade.price) * trade.volume * side * size pnl = (close - trade.price) * trade.volume * side * size
pnl -= (commissionCost + slippageCost)
self.tradingPnl += pnl self.tradingPnl += pnl
#---------------------------------------------------------------------- #----------------------------------------------------------------------

View File

@ -255,7 +255,6 @@ class TurtleSignal(object):
return tradePrice return tradePrice
######################################################################## ########################################################################
class TurtlePortfolio(object): class TurtlePortfolio(object):
"""海龟组合""" """海龟组合"""