{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "> 请在环境变量中设置`DB_URI`指向数据库"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "import os\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "from matplotlib import pyplot as plt\n",
    "from alphamind.api import *\n",
    "from alphamind.strategy.strategy import RunningSetting\n",
    "from alphamind.strategy.strategy import Strategy\n",
    "from PyFin.api import *\n",
    "from PyFin.Math.Accumulators.StatefulAccumulators import MovingAverage\n",
    "from PyFin.Math.Accumulators.StatefulAccumulators import MovingSharp\n",
    "from PyFin.Math.Accumulators.StatefulAccumulators import MovingMaxDrawdown\n",
    "\n",
    "plt.style.use('ggplot')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\"\"\"\n",
    "Back test parameter settings\n",
    "\"\"\"\n",
    "\n",
    "benchmark_code = 905\n",
    "universe = Universe('zz800') + Universe('cyb')\n",
    "\n",
    "start_date = '2017-01-01'\n",
    "end_date = '2018-04-27'\n",
    "freq = '10b'\n",
    "neutralized_risk = None\n",
    "\n",
    "alpha_factors = {\n",
    "    'f01': CSQuantiles(LAST('EPS'), groups='sw1'),\n",
    "    'f02': CSQuantiles(LAST('ROE'), groups='sw1'),\n",
    "}\n",
    "\n",
    "weights = dict(\n",
    "               f01=1.,\n",
    "               f02=1.\n",
    "               )\n",
    "\n",
    "alpha_model = ConstLinearModel(features=alpha_factors, weights=weights)\n",
    "\n",
    "data_meta = DataMeta(freq=freq,\n",
    "                     universe=universe,\n",
    "                     batch=1,\n",
    "                     neutralized_risk=None,\n",
    "                     pre_process=None,\n",
    "                     post_process=None,\n",
    "                     data_source=os.environ['DB_URI'])\n",
    "\n",
    "strategy = Strategy(alpha_model,\n",
    "                    data_meta,\n",
    "                    universe=universe,\n",
    "                    start_date=start_date,\n",
    "                    end_date=end_date,\n",
    "                    freq=freq,\n",
    "                    benchmark=benchmark_code)\n",
    "\n",
    "strategy.prepare_backtest_data()\n",
    "\n",
    "def create_scenario(weights_bandwidth=0.02, target_vol=0.01, method='risk_neutral'):\n",
    "    industry_names = industry_list('sw', 1)\n",
    "    constraint_risk = ['SIZE', 'SIZENL', 'BETA']\n",
    "    total_risk_names = constraint_risk + ['benchmark', 'total']\n",
    "    all_styles = risk_styles + industry_styles + macro_styles\n",
    "\n",
    "    b_type = []\n",
    "    l_val = []\n",
    "    u_val = []\n",
    "\n",
    "    previous_pos = pd.DataFrame()\n",
    "    rets = []\n",
    "    turn_overs = []\n",
    "    leverags = []\n",
    "\n",
    "    for name in total_risk_names:\n",
    "        if name == 'benchmark':\n",
    "            b_type.append(BoundaryType.RELATIVE)\n",
    "            l_val.append(0.8)\n",
    "            u_val.append(1.0)\n",
    "        else:\n",
    "            b_type.append(BoundaryType.ABSOLUTE)\n",
    "            l_val.append(0.0)\n",
    "            u_val.append(0.0)\n",
    "\n",
    "    bounds = create_box_bounds(total_risk_names, b_type, l_val, u_val)\n",
    "    running_setting = RunningSetting(weights_bandwidth=weights_bandwidth,\n",
    "                                     rebalance_method=method,\n",
    "                                     bounds=bounds,\n",
    "                                     target_vol=target_vol,\n",
    "                                     turn_over_target=0.4)\n",
    "\n",
    "    ret_df, positions = strategy.run(running_setting)\n",
    "    return ret_df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def create_report(ret_df, windows):\n",
    "    sharp_calc = MovingSharp(windows, x='ret', y='riskFree')\n",
    "    drawdown_calc = MovingMaxDrawdown(windows, x='ret')\n",
    "    max_drawdown_calc = MovingMaxDrawdown(len(ret_df), x='ret')\n",
    "    \n",
    "    ret_df['ret_after_tc'] = ret_df.excess_return - 0.002 * ret_df.turn_over\n",
    "    res_df = pd.DataFrame(columns=['daily_return', 'cum_ret', 'sharp', 'drawdown', 'max_drawn', 'leverage'])\n",
    "    total_returns = 0.\n",
    "\n",
    "    for i, ret in enumerate(ret_df['ret_after_tc']):\n",
    "        date = ret_df.index[i]\n",
    "        total_returns += ret\n",
    "        sharp_calc.push({'ret': ret, 'riskFree': 0.})\n",
    "        drawdown_calc.push({'ret': ret})\n",
    "        max_drawdown_calc.push({'ret': ret})\n",
    "\n",
    "        res_df.loc[date, 'daily_return'] = ret\n",
    "        res_df.loc[date, 'cum_ret'] = total_returns\n",
    "        res_df.loc[date, 'drawdown'] = drawdown_calc.result()\n",
    "        res_df.loc[date, 'max_drawn'] = max_drawdown_calc.result()\n",
    "        res_df.loc[date, 'leverage'] = ret_df.loc[date, 'leverage']\n",
    "\n",
    "        if i < 5:\n",
    "            res_df.loc[date, 'sharp'] = 0.\n",
    "        else:\n",
    "            res_df.loc[date, 'sharp'] = sharp_calc.result() * np.sqrt(windows)\n",
    "    return res_df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%time\n",
    "weight_gaps = [0.005, 0.010, 0.015, 0.020]\n",
    "\n",
    "with pd.ExcelWriter(f'zz800_cyb_{benchmark_code}_gap.xlsx', engine='xlsxwriter') as writer:\n",
    "    for i, weight_gap in enumerate(weight_gaps):\n",
    "        ret_df = create_scenario(weight_gap, target_vol=0.01, method='risk_neutral')\n",
    "        res_df = create_report(ret_df, 25)\n",
    "        res_df.to_excel(writer, sheet_name=f'{i}')\n",
    "        alpha_logger.info(f\"weight_gap: {weight_gap} finished\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%time\n",
    "target_vols = [0.015, 0.030, 0.045, 0.060]\n",
    "\n",
    "with pd.ExcelWriter(f'zz800_cyb_{benchmark_code}_tv.xlsx', engine='xlsxwriter') as writer:\n",
    "    for i, target_vol in enumerate(target_vols):\n",
    "        ret_df = create_scenario(0.01, target_vol=target_vol, method='tv')\n",
    "        res_df = create_report(ret_df, 25)\n",
    "        res_df.to_excel(writer, sheet_name=f'{i}')\n",
    "        alpha_logger.info(f\"target_vol: {target_vol:.4f} finished\")"
   ]
  },
  {
   "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.6.5"
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
