diff --git a/docs/contribution.md b/docs/contribution.md index 01a3b4ae..901115c9 100644 --- a/docs/contribution.md +++ b/docs/contribution.md @@ -1,4 +1,3 @@ - # 贡献代码 --- @@ -71,4 +70,5 @@ autopep8 --in-place --recursive . [GithubVnpy]:https://github.com/vnpy/vnpy [GithubDocForSync]:https://help.github.com/articles/syncing-a-fork/ [CreateIssue]:https://github.com/vnpy/vnpy/issues/new -[CreatePR]:https://github.com/vnpy/vnpy/compare?expand=1 \ No newline at end of file +[CreatePR]:https://github.com/vnpy/vnpy/compare?expand=1 + diff --git a/docs/cta_backtester.md b/docs/cta_backtester.md new file mode 100644 index 00000000..d1c24b08 --- /dev/null +++ b/docs/cta_backtester.md @@ -0,0 +1,46 @@ +# CTA回测模块 +CTA回测模块是基于PyQt5和pyqtgraph的图形化回测工具。启动VN Trader后,在菜单栏中点击“功能-> CTA回测”即可进入该图形化回测界面,如下图。CTA回测模块主要实现3个功能:历史行情数据的下载、策略回测、参数优化。 +![](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/cta_backtester/cta_backtester.png) + +  + + +## 1.下载数据 +数据下载功能是基于RQData的get_price()函数实现的。 +``` +get_price(order_book_ids, start_date='2013-01-04', end_date='2014-01-04', frequency='1d', fields=None, adjust_type='pre', skip_suspended =False, market='cn') +``` + + +在使用前要保证RQData初始化完毕,然后填写以下4个字段信息: +- 本地代码:格式为合约品种+交易所,如IF88.CFFEX、rb88.SHFE;然后在底层通过RqdataClient的to_rq_symbol()函数转换成符合RQData格式,对应RQData中get_price()函数的order_book_ids字段。 +- K线周期:可以填1m、60m、1d,对应get_price()函数的frequency字段。 +- 开始日期:格式为yy/mm/dd,如2017/4/21,对应get_price()函数的start_date字段。(点击窗口右侧箭头按钮可改变日期大小) +- 结束日期:格式为yy/mm/dd,如2019/4/22,对应get_price()函数的end_date字段。(点击窗口右侧箭头按钮可改变日期大小) + +填写完字段信息后,点击下方“下载数据”按钮启动下载程序,下载成功如图所示。 + +![](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/cta_backtester/data_loader.png) + + + +  + +## 2.加载启动 + + + + +## 3.策略回测 + +### 3.1统计数据 + + +### 3.2图表分析 + + + +## 4.参数优化 + + + diff --git a/docs/gateway.md b/docs/gateway.md index e69de29b..0d004e43 100644 --- a/docs/gateway.md +++ b/docs/gateway.md @@ -0,0 +1,53 @@ +# 交易接口 + +## 如何连接 + +### 加载需要用的接口 + + +### VN Trader界面操作 + + +### 修改json配置文件 + + +### 可交易的合约查看 + + +## 接口分类 + +做一个表 + + +## 接口详解 + +### CTP(ctp) + +#### 如何加载 + +#### 相关字段 + +#### 获取账号 + +#### 其他特点 + + +### 宽睿柜台(oes) + +#### 如何加载 + +#### 相关字段 + +#### 获取账号 + +#### 其他特点 + + +### 盈透证券(ib) + +### 老虎证券(tiger) + +### OKEX + + +### 火币 \ No newline at end of file diff --git a/docs/install.md b/docs/install.md index c50d1bca..76a18159 100644 --- a/docs/install.md +++ b/docs/install.md @@ -19,7 +19,7 @@ 注意事项:第4步会提示用户是否把VNConda注册成默认Python环境:若用户存在其他Python环境,则都不要勾选;反之,两个都勾选掉。 -![enter image description here](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/install.bat/install_VNConda.png "enter image title here") +![](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/install.bat/install_VNConda.png "enter image title here")   @@ -27,13 +27,13 @@ 输入账号密码或者微信扫码登陆VNConda。(社区账号通过微信扫码可得) -![enter image description here](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/install.bat/login_VNConda.png "enter image title here") +![](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/install.bat/login_VNConda.png "enter image title here")   #### 4.使用VNStation 登录后会进入到VN Station的主界面。 -![enter image description here](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/install.bat/login_VNConda_2.png "enter image title here") +![](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/install.bat/login_VNConda_2.png "enter image title here") 窗口下方有5个选项: - VN Trade Lite:直接运行VN Trader (只有CTP接口) @@ -42,6 +42,17 @@ - 提问求助:提出相关问题,管理员会每天定时回复 - 后台更新:一键更新VN Station + +  + +#### 5.更新VNStation +更新VNStation除了“一键更新”外,也可以卸载老版本,安装新版本。 + +重新启动后,有几率会遇到下面的问题:“无法定位序数4540于动态链接库 \VNConda\Lib\site-packages\PyQt5\Qt\bin\ssleay.dll上。”类似的窗口弹出了几个,无法登录VN Station。 + +原因是操作系统中安装了其他的SSL组件,同时还影响了相关的环境变量,导致PyQt载入ssl模块失败。 +解决方法是将 \VNConda\Lib\site-packages\PyQt5\Qt\bin 目录的两个动态库 libeay32.dll和 ssleay32.dll拷贝到 \VNConda\ 下。 +     @@ -94,13 +105,13 @@ $ bash Miniconda3-latest-Linux-x86_64.sh 当询问是否把Miniconda设置为Python 默认环境时,把默认的"no"改成“yes”。原因是Ubuntu 18.04已有自带的Python 3.6与Python 2.7。 -![enter image description here](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/install.bat/install_Miniconda_ubuntu.png "enter image title here") +![](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/install.bat/install_Miniconda_ubuntu.png "enter image title here") 重启Ubuntu后,打开终端直接输入"python" 然后按“Enter”键: 若出现如下图,则表示成功把Miniconda设置为Python默认环境。 -![enter image description here](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/install.bat/Conda_Python_version.png "enter image title here") +![](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/install.bat/Conda_Python_version.png "enter image title here")   diff --git a/tests/backtesting/GA_Pre_Final.ipynb b/tests/backtesting/GA_Pre_Final.ipynb new file mode 100644 index 00000000..8519ad3a --- /dev/null +++ b/tests/backtesting/GA_Pre_Final.ipynb @@ -0,0 +1,376 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import random\n", + "import multiprocessing\n", + "import numpy as np\n", + "from deap import creator, base, tools, algorithms\n", + "from backtesting import BacktestingEngine,OptimizationSetting\n", + "from boll_channel_strategy import BollChannelStrategy\n", + "from atr_rsi_strategy import AtrRsiStrategy\n", + "from datetime import datetime\n", + "import multiprocessing #多进程\n", + "from scoop import futures #多进程\n", + "from functools import lru_cache" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "数据总体: 13824\n" + ] + } + ], + "source": [ + "setting = OptimizationSetting()\n", + "#setting.add_parameter('atr_length', 10, 50, 2)\n", + "#setting.add_parameter('atr_ma_length', 10, 50, 2)\n", + "#setting.add_parameter('rsi_length', 4, 50, 2)\n", + "#setting.add_parameter('rsi_entry', 4, 30, 1)\n", + "setting.add_parameter('boll_window', 4, 50, 2)\n", + "#setting.add_parameter('boll_dev', 4, 50, 2)\n", + "setting.add_parameter('cci_window', 4, 50, 2)\n", + "setting.add_parameter('atr_window', 4, 50, 2)\n", + "\n", + "\n", + "local_setting = setting.generate_setting()\n", + "total_sample = len(local_setting)\n", + "print(\"数据总体:\",total_sample)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "dict_keys(['boll_window', 'cci_window', 'atr_window'])" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "setting_names = random.choice(local_setting).keys()\n", + "setting_names" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "def parameter_generate():\n", + " setting_param = list(random.choice(local_setting).values())\n", + " return setting_param" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[22, 28, 22]" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "parameter_generate()" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{'boll_window': 24, 'cci_window': 14, 'atr_window': 28}" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "setting=dict(zip(setting_names,parameter_generate()))\n", + "setting" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "def object_func(strategy_avg):\n", + " \"\"\"\"\"\"\n", + " return run_backtesting(tuple(strategy_avg))\n", + " #return run_backtesting(strategy_avg)\n", + " \n", + "\n", + "@lru_cache(maxsize=1000000)\n", + "def run_backtesting(strategy_avg):\n", + " # 创建回测引擎对象\n", + " engine = BacktestingEngine()\n", + " engine.set_parameters(\n", + " vt_symbol=\"IF88.CFFEX\",\n", + " interval=\"1m\",\n", + " start=datetime(2016, 1, 1),\n", + " end=datetime(2019, 1,1),\n", + " rate=0.3/10000,\n", + " slippage=0.2,\n", + " size=300,\n", + " pricetick=0.2,\n", + " capital=1_000_000,\n", + " )\n", + " \n", + " setting=dict(zip(setting_names,strategy_avg))\n", + " \n", + "\n", + " #加载策略 \n", + " #engine.initStrategy(TurtleTradingStrategy, setting)\n", + " engine.add_strategy(BollChannelStrategy, setting)\n", + " engine.load_data()\n", + " engine.run_backtesting()\n", + " engine.calculate_result()\n", + " result = engine.calculate_statistics(output=False)\n", + "\n", + " return_drawdown_ratio = round(result['return_drawdown_ratio'],2) #收益回撤比\n", + " sharpe_ratio= round(result['sharpe_ratio'],2) #夏普比率\n", + " return return_drawdown_ratio , sharpe_ratio" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "(-0.51, -0.28)" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "object_func(parameter_generate())" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [], + "source": [ + "target_names = [\"return_drawdown_ratio\" , \"sharpe_ratio\"]\n", + "def show_result(hof):\n", + " for i in range(len(hof)):\n", + " solution = hof[i] \n", + " parameter=dict(zip(setting_names,solution))\n", + " result=dict(zip(target_names,list(object_func(solution))))\n", + " print({**parameter, **result})" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "from time import time\n", + "#设置优化方向:最大化收益回撤比,最大化夏普比率\n", + "creator.create(\"FitnessMax\", base.Fitness, weights=(1.0, 1.0)) # 1.0 求最大值;-1.0 求最小值\n", + "creator.create(\"Individual\", list, fitness=creator.FitnessMax)\n", + "\n", + "def optimize(population=None):\n", + " \"\"\"\"\"\" \n", + " start = time() \n", + " toolbox = base.Toolbox() \n", + "\n", + " # 初始化 \n", + " toolbox.register(\"individual\", tools.initIterate, creator.Individual,parameter_generate) \n", + " toolbox.register(\"population\", tools.initRepeat, list, toolbox.individual) \n", + " toolbox.register(\"mate\", tools.cxTwoPoint) \n", + " toolbox.register(\"mutate\", tools.mutUniformInt,low = 4,up = 40,indpb=1) \n", + " toolbox.register(\"evaluate\", object_func) \n", + " toolbox.register(\"select\", tools.selNSGA2) \n", + " #pool = multiprocessing.Pool()\n", + " #toolbox.register(\"map\", pool.map)\n", + " #toolbox.register(\"map\", futures.map)\n", + " \n", + " \n", + " #遗传算法参数设置\n", + " MU = 80 #设置每一代选择的个体数\n", + " LAMBDA = 100 #设置每一代产生的子女数\n", + " POP=100\n", + " CXPB, MUTPB, NGEN = 0.95, 0.05,30 #分别为种群内部个体的交叉概率、变异概率、产生种群代数\n", + " \n", + " if population==None:\n", + " LAMBDA = POP = int(pow(total_sample, 1/2.7))\n", + " MU = int(0.8*POP) \n", + " \n", + " pop = toolbox.population(POP) #设置族群里面的个体数量\n", + " hof = tools.ParetoFront() #解的集合:帕累托前沿(非占优最优集)\n", + "\n", + " stats = tools.Statistics(lambda ind: ind.fitness.values)\n", + " np.set_printoptions(suppress=True) #对numpy默认输出的科学计数法转换\n", + " stats.register(\"mean\", np.mean, axis=0) #统计目标优化函数结果的平均值\n", + " stats.register(\"std\", np.std, axis=0) #统计目标优化函数结果的标准差\n", + " stats.register(\"min\", np.min, axis=0) #统计目标优化函数结果的最小值\n", + " stats.register(\"max\", np.max, axis=0) #统计目标优化函数结果的最大值\n", + " print(\"开始运行遗传算法,每代族群总数:%s, 优良品种筛选个数:%s,迭代次数:%s,交叉概率:%s,突变概率:%s\" %(POP,MU,NGEN,CXPB,MUTPB))\n", + " \n", + "\n", + " #运行算法\n", + " algorithms.eaMuPlusLambda(pop, toolbox, MU, LAMBDA, CXPB, MUTPB, NGEN, stats,\n", + " halloffame=hof) #esMuPlusLambda是一种基于(μ+λ)选择策略的多目标优化分段遗传算法\n", + "\n", + " end = time()\n", + " cost = int((end - start))\n", + "\n", + " print(\"遗传算法优化完成,耗时%s秒\"% (cost))\n", + " print(\"输出帕累托前沿解集:\")\n", + " show_result(hof)\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "开始运行遗传算法,每代族群总数:34, 优良品种筛选个数:27,迭代次数:30,交叉概率:0.95,突变概率:0.05\n", + "gen\tnevals\tmean \tstd \tmin \tmax \n", + "0 \t34 \t[0.08852941 0.00352941]\t[0.5373362 0.29107188]\t[-0.7 -0.63]\t[1.51 0.5 ]\n", + "1 \t34 \t[0.60148148 0.27518519]\t[0.31013383 0.08573734]\t[0.32 0.18] \t[1.51 0.5 ]\n", + "2 \t34 \t[0.79333333 0.33851852]\t[0.27758215 0.06742369]\t[0.47 0.25] \t[1.54 0.5 ]\n", + "3 \t34 \t[1.00888889 0.39777778]\t[0.3147525 0.06214281]\t[0.7 0.33] \t[1.54 0.5 ]\n", + "4 \t34 \t[1.41074074 0.47444444]\t[0.22881217 0.04661373]\t[0.96 0.36] \t[1.92 0.57]\n", + "5 \t34 \t[1.59666667 0.51222222]\t[0.14714568 0.0255797 ]\t[1.51 0.49] \t[1.92 0.57]\n", + "6 \t34 \t[1.66259259 0.52185185]\t[0.16585564 0.02981884]\t[1.52 0.49] \t[1.92 0.57]\n", + "7 \t34 \t[1.8737037 0.55666667]\t[0.07713135 0.01763834]\t[1.75 0.53] \t[1.95 0.57]\n", + "8 \t34 \t[1.93666667 0.57 ]\t[0.01490712 0. ]\t[1.92 0.57] \t[1.95 0.57]\n", + "9 \t34 \t[1.95 0.57] \t[0. 0.] \t[1.95 0.57] \t[1.95 0.57]\n", + "10 \t34 \t[1.95 0.57] \t[0. 0.] \t[1.95 0.57] \t[1.95 0.57]\n", + "11 \t34 \t[1.95 0.57] \t[0. 0.] \t[1.95 0.57] \t[1.95 0.57]\n", + "12 \t34 \t[1.95 0.57] \t[0. 0.] \t[1.95 0.57] \t[1.95 0.57]\n", + "13 \t34 \t[1.95 0.57] \t[0. 0.] \t[1.95 0.57] \t[1.95 0.57]\n", + "14 \t34 \t[1.95 0.57] \t[0. 0.] \t[1.95 0.57] \t[1.95 0.57]\n", + "15 \t34 \t[1.95 0.57] \t[0. 0.] \t[1.95 0.57] \t[1.95 0.57]\n", + "16 \t34 \t[1.95 0.57] \t[0. 0.] \t[1.95 0.57] \t[1.95 0.57]\n", + "17 \t34 \t[1.95 0.57] \t[0. 0.] \t[1.95 0.57] \t[1.95 0.57]\n", + "18 \t34 \t[1.95 0.57] \t[0. 0.] \t[1.95 0.57] \t[1.95 0.57]\n", + "19 \t34 \t[1.95 0.57] \t[0. 0.] \t[1.95 0.57] \t[1.95 0.57]\n", + "20 \t34 \t[1.95 0.57] \t[0. 0.] \t[1.95 0.57] \t[1.95 0.57]\n", + "21 \t34 \t[1.95 0.57] \t[0. 0.] \t[1.95 0.57] \t[1.95 0.57]\n", + "22 \t34 \t[1.95 0.57] \t[0. 0.] \t[1.95 0.57] \t[1.95 0.57]\n", + "23 \t34 \t[1.95 0.57] \t[0. 0.] \t[1.95 0.57] \t[1.95 0.57]\n", + "24 \t34 \t[1.95 0.57] \t[0. 0.] \t[1.95 0.57] \t[1.95 0.57]\n", + "25 \t34 \t[1.95 0.57] \t[0. 0.] \t[1.95 0.57] \t[1.95 0.57]\n", + "26 \t34 \t[1.95 0.57] \t[0. 0.] \t[1.95 0.57] \t[1.95 0.57]\n", + "27 \t34 \t[1.95 0.57] \t[0. 0.] \t[1.95 0.57] \t[1.95 0.57]\n", + "28 \t34 \t[1.95 0.57] \t[0. 0.] \t[1.95 0.57] \t[1.95 0.57]\n", + "29 \t34 \t[1.95 0.57] \t[0. 0.] \t[1.95 0.57] \t[1.95 0.57]\n", + "30 \t34 \t[1.95 0.57] \t[0. 0.] \t[1.95 0.57] \t[1.95 0.57]\n", + "遗传算法优化完成,耗时309秒\n", + "输出帕累托前沿解集:\n", + "{'boll_window': 48, 'cci_window': 40, 'atr_window': 22, 'return_drawdown_ratio': 1.95, 'sharpe_ratio': 0.57}\n", + "{'boll_window': 48, 'cci_window': 50, 'atr_window': 22, 'return_drawdown_ratio': 1.95, 'sharpe_ratio': 0.57}\n" + ] + } + ], + "source": [ + "optimize()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + " MU = 80 #设置每一代选择的个体数\n", + " POP = 100 #设置每一代产生的子女数\n", + " CXPB, MUTPB, NGEN = 0.95, 0.05,20 \n", + " print(\"开始运行遗传算法,每代族群总数:%s, 优良品种筛选个数:%s,迭代次数:%s,交叉概率:%s,突变概率:%s\" %(POP,MU,NGEN,CXPB,MUTPB))" + ] + }, + { + "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" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": true, + "sideBar": true, + "skip_h1_title": false, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": {}, + "toc_section_display": true, + "toc_window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}