{ "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 vnpy.app.cta_strategy.backtesting import BacktestingEngine,OptimizationSetting\n", "from vnpy.app.cta_strategy.strategies.boll_channel_strategy import BollChannelStrategy\n", "from vnpy.app.cta_strategy.strategies.atr_rsi_strategy import AtrRsiStrategy\n", "from datetime import datetime\n", "import multiprocessing #多进程\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": [ "[48, 6, 26]" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "parameter_generate()" ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "{'boll_window': 16, 'cci_window': 48, 'atr_window': 6}" ] }, "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": [ { "name": "stdout", "output_type": "stream", "text": [ "2019-05-03 15:02:07.528909\t开始加载历史数据\n", "2019-05-03 15:02:34.854177\t历史数据加载完成,数据量:175440\n", "2019-05-03 15:02:34.877616\t策略初始化完成\n", "2019-05-03 15:02:34.877616\t开始回放历史数据\n", "2019-05-03 15:02:37.000744\t历史数据回放结束\n", "2019-05-03 15:02:37.000744\t开始计算逐日盯市盈亏\n", "2019-05-03 15:02:37.012463\t逐日盯市盈亏计算完成\n", "2019-05-03 15:02:37.012463\t开始计算策略统计指标\n" ] }, { "data": { "text/plain": [ "(0.96, 0.38)" ] }, "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(multiprocessing.cpu_count())\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": null, "metadata": { "scrolled": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "开始运行遗传算法,每代族群总数:34, 优良品种筛选个数:27,迭代次数:30,交叉概率:0.95,突变概率:0.05\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 }