{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "%matplotlib inline\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "from PyFin.api import *\n",
    "from alphamind.api import *\n",
    "from matplotlib import pyplot as plt\n",
    "\n",
    "plt.style.use('ggplot')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Back test parameter settings\n",
    "start_date = '2016-01-01'\n",
    "end_date = '2018-03-30'\n",
    "\n",
    "freq = '10b'\n",
    "industry_lower = 1.\n",
    "industry_upper = 1.\n",
    "neutralized_risk = industry_styles\n",
    "industry_name = 'sw_adj'\n",
    "industry_level = 1\n",
    "turn_over_target_base = 0.4\n",
    "benchmark_total_lower = 0.8\n",
    "benchmark_total_upper = 1.0\n",
    "batch = 1\n",
    "horizon = map_freq(freq)\n",
    "weight_gap = 0.01\n",
    "universe = Universe(\"custom\", ['zz800'])\n",
    "data_source = 'postgres+psycopg2://postgres:A12345678!@10.63.6.220/alpha'\n",
    "benchmark_code = 300\n",
    "offset = 1\n",
    "method = 'risk_neutral'\n",
    "target_vol = 0.05\n",
    "risk_model = 'short'\n",
    "\n",
    "executor = NaiveExecutor()\n",
    "ref_dates = makeSchedule(start_date, end_date, freq, 'china.sse')\n",
    "engine = SqlEngine(data_source)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [],
   "source": [
    "alpha_factors = {\n",
    "    'f01': LAST('ep_q'),\n",
    "    'f02': LAST('roe_q'),\n",
    "    'f03': LAST('SGRO'),\n",
    "    'f04': LAST('GREV'),\n",
    "    'f05': LAST('con_target_price'),\n",
    "    'f06': LAST('con_pe_rolling_order'),\n",
    "    'f07': LAST('IVR'),\n",
    "    'f08': LAST('ILLIQUIDITY'),\n",
    "    }\n",
    "\n",
    "weights = dict(f01=1.,\n",
    "               f02=1.,\n",
    "               f03=1.,\n",
    "               f04=1.,\n",
    "               f05=1.,\n",
    "               f06=-1.,\n",
    "               f07=0.5,\n",
    "               f08=0.5,\n",
    "              )\n",
    "\n",
    "alpha_model = ConstLinearModel(features=alpha_factors, weights=weights)\n",
    "\n",
    "def predict_worker(params):\n",
    "    data_meta = DataMeta(freq=freq,\n",
    "                         universe=universe,\n",
    "                         batch=batch,\n",
    "                         neutralized_risk=neutralized_risk,\n",
    "                         risk_model='short',\n",
    "                         pre_process=[winsorize_normal, standardize],\n",
    "                         post_process=[standardize],\n",
    "                         warm_start=0,\n",
    "                         data_source=data_source)\n",
    "    ref_date, model = params\n",
    "    er = predict_by_model(ref_date, model, data_meta)\n",
    "    return er"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Wall time: 22 s\n"
     ]
    }
   ],
   "source": [
    "%%time\n",
    "\n",
    "# training / predict\n",
    "predicts = [predict_worker((d.strftime('%Y-%m-%d'), alpha_model)) for d in ref_dates]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "2018-04-16 18:41:27,841 - ALPHA_MIND - INFO - 2016-01-04 partial re-balance: 799\n",
      "2018-04-16 18:41:28,115 - ALPHA_MIND - INFO - 2016-01-04 is finished\n",
      "d:\\ProgramData\\Anaconda3\\lib\\site-packages\\ipykernel_launcher.py:72: FutureWarning: \n",
      "Passing list-likes to .loc or [] with any missing label will raise\n",
      "KeyError in the future, you can use .reindex() as an alternative.\n",
      "\n",
      "See the documentation here:\n",
      "http://pandas.pydata.org/pandas-docs/stable/indexing.html#deprecate-loc-reindex-listlike\n",
      "2018-04-16 18:41:28,151 - ALPHA_MIND - INFO - 2016-01-18 partial re-balance: 800\n",
      "2018-04-16 18:41:28,538 - ALPHA_MIND - INFO - 2016-01-18 is finished\n",
      "2018-04-16 18:41:28,584 - ALPHA_MIND - INFO - 2016-02-01 partial re-balance: 800\n",
      "2018-04-16 18:41:29,106 - ALPHA_MIND - INFO - 2016-02-01 is finished\n",
      "2018-04-16 18:41:29,156 - ALPHA_MIND - INFO - 2016-02-22 partial re-balance: 800\n",
      "2018-04-16 18:41:29,552 - ALPHA_MIND - INFO - 2016-02-22 is finished\n",
      "2018-04-16 18:41:29,588 - ALPHA_MIND - INFO - 2016-03-07 partial re-balance: 800\n",
      "2018-04-16 18:41:29,975 - ALPHA_MIND - INFO - 2016-03-07 is finished\n",
      "2018-04-16 18:41:30,013 - ALPHA_MIND - INFO - 2016-03-21 partial re-balance: 800\n",
      "2018-04-16 18:41:30,406 - ALPHA_MIND - INFO - 2016-03-21 is finished\n",
      "2018-04-16 18:41:30,453 - ALPHA_MIND - INFO - 2016-04-05 partial re-balance: 800\n",
      "2018-04-16 18:41:30,867 - ALPHA_MIND - INFO - 2016-04-05 is finished\n",
      "2018-04-16 18:41:30,910 - ALPHA_MIND - INFO - 2016-04-19 partial re-balance: 800\n",
      "2018-04-16 18:41:31,311 - ALPHA_MIND - INFO - 2016-04-19 is finished\n",
      "2018-04-16 18:41:31,352 - ALPHA_MIND - INFO - 2016-05-04 partial re-balance: 800\n",
      "2018-04-16 18:41:31,737 - ALPHA_MIND - INFO - 2016-05-04 is finished\n",
      "2018-04-16 18:41:31,783 - ALPHA_MIND - INFO - 2016-05-18 partial re-balance: 800\n",
      "2018-04-16 18:41:32,188 - ALPHA_MIND - INFO - 2016-05-18 is finished\n",
      "2018-04-16 18:41:32,229 - ALPHA_MIND - INFO - 2016-06-01 partial re-balance: 800\n",
      "2018-04-16 18:41:32,638 - ALPHA_MIND - INFO - 2016-06-01 is finished\n",
      "2018-04-16 18:41:32,689 - ALPHA_MIND - INFO - 2016-06-17 partial re-balance: 800\n",
      "2018-04-16 18:41:33,110 - ALPHA_MIND - INFO - 2016-06-17 is finished\n",
      "2018-04-16 18:41:33,147 - ALPHA_MIND - INFO - 2016-07-01 partial re-balance: 800\n",
      "2018-04-16 18:41:33,554 - ALPHA_MIND - INFO - 2016-07-01 is finished\n",
      "2018-04-16 18:41:33,588 - ALPHA_MIND - INFO - 2016-07-15 partial re-balance: 800\n",
      "2018-04-16 18:41:33,995 - ALPHA_MIND - INFO - 2016-07-15 is finished\n",
      "2018-04-16 18:41:34,042 - ALPHA_MIND - INFO - 2016-07-29 partial re-balance: 800\n",
      "2018-04-16 18:41:34,476 - ALPHA_MIND - INFO - 2016-07-29 is finished\n",
      "2018-04-16 18:41:34,521 - ALPHA_MIND - INFO - 2016-08-12 partial re-balance: 800\n",
      "2018-04-16 18:41:34,941 - ALPHA_MIND - INFO - 2016-08-12 is finished\n",
      "2018-04-16 18:41:34,980 - ALPHA_MIND - INFO - 2016-08-26 partial re-balance: 800\n",
      "2018-04-16 18:41:35,480 - ALPHA_MIND - INFO - 2016-08-26 is finished\n",
      "2018-04-16 18:41:35,528 - ALPHA_MIND - INFO - 2016-09-09 partial re-balance: 800\n",
      "2018-04-16 18:41:35,950 - ALPHA_MIND - INFO - 2016-09-09 is finished\n",
      "2018-04-16 18:41:35,987 - ALPHA_MIND - INFO - 2016-09-27 partial re-balance: 800\n",
      "2018-04-16 18:41:36,381 - ALPHA_MIND - INFO - 2016-09-27 is finished\n",
      "2018-04-16 18:41:36,425 - ALPHA_MIND - INFO - 2016-10-18 partial re-balance: 800\n",
      "2018-04-16 18:41:36,840 - ALPHA_MIND - INFO - 2016-10-18 is finished\n",
      "2018-04-16 18:41:36,885 - ALPHA_MIND - INFO - 2016-11-01 partial re-balance: 800\n",
      "2018-04-16 18:41:37,188 - ALPHA_MIND - INFO - 2016-11-01 is finished\n",
      "2018-04-16 18:41:37,226 - ALPHA_MIND - INFO - 2016-11-15 partial re-balance: 800\n",
      "2018-04-16 18:41:37,662 - ALPHA_MIND - INFO - 2016-11-15 is finished\n",
      "2018-04-16 18:41:37,703 - ALPHA_MIND - INFO - 2016-11-29 partial re-balance: 800\n",
      "2018-04-16 18:41:38,122 - ALPHA_MIND - INFO - 2016-11-29 is finished\n",
      "2018-04-16 18:41:38,167 - ALPHA_MIND - INFO - 2016-12-13 partial re-balance: 800\n",
      "2018-04-16 18:41:38,590 - ALPHA_MIND - INFO - 2016-12-13 is finished\n",
      "2018-04-16 18:41:38,642 - ALPHA_MIND - INFO - 2016-12-27 partial re-balance: 800\n",
      "2018-04-16 18:41:39,073 - ALPHA_MIND - INFO - 2016-12-27 is finished\n",
      "2018-04-16 18:41:39,111 - ALPHA_MIND - INFO - 2017-01-11 partial re-balance: 800\n",
      "2018-04-16 18:41:39,503 - ALPHA_MIND - INFO - 2017-01-11 is finished\n",
      "2018-04-16 18:41:39,545 - ALPHA_MIND - INFO - 2017-01-25 partial re-balance: 799\n",
      "2018-04-16 18:41:39,941 - ALPHA_MIND - INFO - 2017-01-25 is finished\n",
      "2018-04-16 18:41:39,986 - ALPHA_MIND - INFO - 2017-02-15 partial re-balance: 799\n",
      "2018-04-16 18:41:40,398 - ALPHA_MIND - INFO - 2017-02-15 is finished\n",
      "2018-04-16 18:41:40,435 - ALPHA_MIND - INFO - 2017-03-01 partial re-balance: 800\n",
      "2018-04-16 18:41:40,839 - ALPHA_MIND - INFO - 2017-03-01 is finished\n",
      "2018-04-16 18:41:40,887 - ALPHA_MIND - INFO - 2017-03-15 partial re-balance: 800\n",
      "2018-04-16 18:41:41,311 - ALPHA_MIND - INFO - 2017-03-15 is finished\n",
      "2018-04-16 18:41:41,351 - ALPHA_MIND - INFO - 2017-03-29 partial re-balance: 800\n",
      "2018-04-16 18:41:41,792 - ALPHA_MIND - INFO - 2017-03-29 is finished\n",
      "2018-04-16 18:41:41,831 - ALPHA_MIND - INFO - 2017-04-14 partial re-balance: 800\n",
      "2018-04-16 18:41:42,364 - ALPHA_MIND - INFO - 2017-04-14 is finished\n",
      "2018-04-16 18:41:42,418 - ALPHA_MIND - INFO - 2017-04-28 partial re-balance: 800\n",
      "2018-04-16 18:41:42,867 - ALPHA_MIND - INFO - 2017-04-28 is finished\n",
      "2018-04-16 18:41:42,906 - ALPHA_MIND - INFO - 2017-05-15 partial re-balance: 800\n",
      "2018-04-16 18:41:43,343 - ALPHA_MIND - INFO - 2017-05-15 is finished\n",
      "2018-04-16 18:41:43,379 - ALPHA_MIND - INFO - 2017-05-31 partial re-balance: 800\n",
      "2018-04-16 18:41:43,801 - ALPHA_MIND - INFO - 2017-05-31 is finished\n",
      "2018-04-16 18:41:43,844 - ALPHA_MIND - INFO - 2017-06-14 partial re-balance: 800\n",
      "2018-04-16 18:41:44,259 - ALPHA_MIND - INFO - 2017-06-14 is finished\n",
      "2018-04-16 18:41:44,295 - ALPHA_MIND - INFO - 2017-06-28 partial re-balance: 800\n",
      "2018-04-16 18:41:44,736 - ALPHA_MIND - INFO - 2017-06-28 is finished\n",
      "2018-04-16 18:41:44,778 - ALPHA_MIND - INFO - 2017-07-12 partial re-balance: 800\n",
      "2018-04-16 18:41:45,189 - ALPHA_MIND - INFO - 2017-07-12 is finished\n",
      "2018-04-16 18:41:45,222 - ALPHA_MIND - INFO - 2017-07-26 partial re-balance: 800\n",
      "2018-04-16 18:41:45,500 - ALPHA_MIND - INFO - 2017-07-26 is finished\n",
      "2018-04-16 18:41:45,544 - ALPHA_MIND - INFO - 2017-08-09 partial re-balance: 800\n",
      "2018-04-16 18:41:45,851 - ALPHA_MIND - INFO - 2017-08-09 is finished\n",
      "2018-04-16 18:41:45,887 - ALPHA_MIND - INFO - 2017-08-23 partial re-balance: 800\n",
      "2018-04-16 18:41:46,313 - ALPHA_MIND - INFO - 2017-08-23 is finished\n",
      "2018-04-16 18:41:46,351 - ALPHA_MIND - INFO - 2017-09-06 partial re-balance: 800\n",
      "2018-04-16 18:41:46,774 - ALPHA_MIND - INFO - 2017-09-06 is finished\n",
      "2018-04-16 18:41:46,819 - ALPHA_MIND - INFO - 2017-09-20 partial re-balance: 800\n",
      "2018-04-16 18:41:47,094 - ALPHA_MIND - INFO - 2017-09-20 is finished\n",
      "2018-04-16 18:41:47,142 - ALPHA_MIND - INFO - 2017-10-11 partial re-balance: 800\n",
      "2018-04-16 18:41:47,575 - ALPHA_MIND - INFO - 2017-10-11 is finished\n",
      "2018-04-16 18:41:47,619 - ALPHA_MIND - INFO - 2017-10-25 partial re-balance: 800\n",
      "2018-04-16 18:41:48,052 - ALPHA_MIND - INFO - 2017-10-25 is finished\n",
      "2018-04-16 18:41:48,090 - ALPHA_MIND - INFO - 2017-11-08 partial re-balance: 800\n",
      "2018-04-16 18:41:48,509 - ALPHA_MIND - INFO - 2017-11-08 is finished\n",
      "2018-04-16 18:41:48,554 - ALPHA_MIND - INFO - 2017-11-22 partial re-balance: 800\n",
      "2018-04-16 18:41:49,132 - ALPHA_MIND - INFO - 2017-11-22 is finished\n",
      "2018-04-16 18:41:49,175 - ALPHA_MIND - INFO - 2017-12-06 partial re-balance: 800\n",
      "2018-04-16 18:41:49,600 - ALPHA_MIND - INFO - 2017-12-06 is finished\n",
      "2018-04-16 18:41:49,645 - ALPHA_MIND - INFO - 2017-12-20 partial re-balance: 800\n",
      "2018-04-16 18:41:50,100 - ALPHA_MIND - INFO - 2017-12-20 is finished\n",
      "2018-04-16 18:41:50,154 - ALPHA_MIND - INFO - 2018-01-04 partial re-balance: 800\n",
      "2018-04-16 18:41:50,602 - ALPHA_MIND - INFO - 2018-01-04 is finished\n",
      "2018-04-16 18:41:50,651 - ALPHA_MIND - INFO - 2018-01-18 partial re-balance: 800\n",
      "2018-04-16 18:41:51,094 - ALPHA_MIND - INFO - 2018-01-18 is finished\n",
      "2018-04-16 18:41:51,138 - ALPHA_MIND - INFO - 2018-02-01 partial re-balance: 800\n",
      "2018-04-16 18:41:51,602 - ALPHA_MIND - INFO - 2018-02-01 is finished\n",
      "2018-04-16 18:41:51,644 - ALPHA_MIND - INFO - 2018-02-22 partial re-balance: 800\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "2018-04-16 18:41:52,078 - ALPHA_MIND - INFO - 2018-02-22 is finished\n",
      "2018-04-16 18:41:52,116 - ALPHA_MIND - INFO - 2018-03-08 partial re-balance: 800\n",
      "2018-04-16 18:41:52,567 - ALPHA_MIND - INFO - 2018-03-08 is finished\n",
      "2018-04-16 18:41:52,604 - ALPHA_MIND - INFO - 2018-03-22 partial re-balance: 800\n",
      "2018-04-16 18:41:53,039 - ALPHA_MIND - INFO - 2018-03-22 is finished\n"
     ]
    }
   ],
   "source": [
    "# rebalance\n",
    "\n",
    "industry_names = industry_list(industry_name, industry_level)\n",
    "constraint_risk = ['SIZE', 'SIZENL', 'BETA']  + industry_names\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(benchmark_total_lower)\n",
    "        u_val.append(benchmark_total_upper)\n",
    "    elif name in {'SIZE', 'SIZENL', 'BETA'}:\n",
    "        b_type.append(BoundaryType.ABSOLUTE)\n",
    "        l_val.append(0.0)\n",
    "        u_val.append(0.0)\n",
    "    else:\n",
    "        b_type.append(BoundaryType.RELATIVE)\n",
    "        l_val.append(industry_lower)\n",
    "        u_val.append(industry_upper)\n",
    "\n",
    "bounds = create_box_bounds(total_risk_names, b_type, l_val, u_val)\n",
    "\n",
    "industry_total = engine.fetch_industry_matrix_range(universe, dates=ref_dates, category=industry_name, level=industry_level)\n",
    "benchmark_total = engine.fetch_benchmark_range(dates=ref_dates, benchmark=benchmark_code)\n",
    "risk_cov_total, risk_exposure_total = engine.fetch_risk_model_range(universe, dates=ref_dates, risk_model=risk_model)\n",
    "\n",
    "for i, ref_date in enumerate(ref_dates):\n",
    "    ref_date = ref_date.strftime('%Y-%m-%d')\n",
    "    industry_matrix = industry_total[industry_total.trade_date == ref_date]\n",
    "    benchmark_w = benchmark_total[benchmark_total.trade_date == ref_date]\n",
    "    risk_exposure = risk_exposure_total[risk_exposure_total.trade_date == ref_date]\n",
    "    risk_cov = risk_cov_total[risk_cov_total.trade_date == ref_date]\n",
    "    \n",
    "    res = pd.merge(industry_matrix, benchmark_w, on=['code'], how='left').fillna(0.)\n",
    "    res = pd.merge(res, risk_exposure, on=['code'])\n",
    "    res = res.dropna()\n",
    "    codes = res.code.values.tolist()\n",
    "    \n",
    "    risk_exposure = res[all_styles].values\n",
    "    risk_cov = risk_cov[all_styles].values\n",
    "    special_risk = res.srisk.values\n",
    "    sec_cov = risk_exposure @ risk_cov @ risk_exposure.T / 10000 + np.diag(special_risk ** 2) / 10000\n",
    "    \n",
    "    benchmark_w = res.weight.values\n",
    "    is_in_benchmark = (benchmark_w > 0.).astype(float).reshape((-1, 1))\n",
    "    \n",
    "    total_risk_exp = np.concatenate([res[constraint_risk].values.astype(float),\n",
    "                                     is_in_benchmark,\n",
    "                                     np.ones_like(is_in_benchmark)],\n",
    "                                    axis=1)\n",
    "    total_risk_exp = pd.DataFrame(total_risk_exp, columns=total_risk_names)\n",
    "    constraints = LinearConstraints(bounds, total_risk_exp, benchmark_w)\n",
    "    \n",
    "    lbound = np.maximum(0., benchmark_w - weight_gap)  # np.zeros(len(total_data))\n",
    "    ubound = weight_gap + benchmark_w\n",
    "    \n",
    "    if previous_pos.empty:\n",
    "        current_position = None\n",
    "        turn_over_target = None\n",
    "    else:\n",
    "        previous_pos.set_index('code', inplace=True)\n",
    "        remained_pos = previous_pos.loc[codes]\n",
    "\n",
    "        remained_pos.fillna(0., inplace=True)\n",
    "        turn_over_target = turn_over_target_base\n",
    "        current_position = remained_pos.weight.values\n",
    "        \n",
    "    er = predicts[i].loc[codes].values\n",
    "    \n",
    "    try:\n",
    "        alpha_logger.info('{0} partial re-balance: {1}'.format(ref_date, len(er)))\n",
    "        target_pos, _ = er_portfolio_analysis(er,\n",
    "                                              industry_matrix.industry_name.values,\n",
    "                                              None,\n",
    "                                              constraints,\n",
    "                                              False,\n",
    "                                              benchmark_w,\n",
    "                                              method=method,\n",
    "                                              turn_over_target=turn_over_target,\n",
    "                                              current_position=current_position,\n",
    "                                              lbound=lbound,\n",
    "                                              ubound=ubound,\n",
    "                                              target_vol=target_vol,\n",
    "                                              cov=sec_cov)\n",
    "    except ValueError:\n",
    "        alpha_logger.info('{0} full re-balance: {1}'.format(ref_date, len(er)))\n",
    "        target_pos, _ = er_portfolio_analysis(er,\n",
    "                                              industry_matrix.industry_name.values,\n",
    "                                              None,\n",
    "                                              constraints,\n",
    "                                              False,\n",
    "                                              benchmark_w,\n",
    "                                              method=method,\n",
    "                                              lbound=lbound,\n",
    "                                              ubound=ubound,\n",
    "                                              target_vol=target_vol,\n",
    "                                              cov=sec_co)\n",
    "        \n",
    "    target_pos['code'] = codes\n",
    "    turn_over, executed_pos = executor.execute(target_pos=target_pos)\n",
    "\n",
    "    executed_codes = executed_pos.code.tolist()\n",
    "    dx_returns = engine.fetch_dx_return(ref_date, executed_codes, horizon=horizon, offset=offset)\n",
    "    result = pd.merge(executed_pos, dx_returns, on=['code'])\n",
    "\n",
    "    leverage = result.weight.abs().sum()\n",
    "\n",
    "    ret = result.weight.values @ (np.exp(result.dx.values) - 1.)\n",
    "    rets.append(np.log(1. + ret))\n",
    "    executor.set_current(executed_pos)\n",
    "    turn_overs.append(turn_over)\n",
    "    leverags.append(leverage)\n",
    "\n",
    "    previous_pos = executed_pos\n",
    "    alpha_logger.info('{0} is finished'.format(ref_date))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.axes._subplots.AxesSubplot at 0x2980b3ba358>"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 43308 characters]\n",
      "text/plain": [
       "<Figure size 864x432 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "ret_df = pd.DataFrame({'returns': rets, 'turn_over': turn_overs, 'leverage': leverags}, index=ref_dates)\n",
    "\n",
    "# index return\n",
    "index_return = engine.fetch_dx_return_index_range(benchmark_code, start_date, end_date, horizon=horizon,\n",
    "                                                  offset=offset).set_index('trade_date')\n",
    "ret_df['index'] = index_return['dx']\n",
    "\n",
    "ret_df.loc[advanceDateByCalendar('china.sse', ref_dates[-1], freq)] = 0.\n",
    "ret_df = ret_df.shift(1)\n",
    "ret_df.iloc[0] = 0.\n",
    "ret_df['tc_cost'] = ret_df.turn_over * 0.002\n",
    "ret_df['returns'] = ret_df['returns'] - ret_df['index'] * ret_df['leverage']\n",
    "\n",
    "ret_df[['returns', 'tc_cost']].cumsum().plot(figsize=(12, 6),\n",
    "                                             title='Fixed freq rebalanced: {0} with benchmark {1}'.format(freq, 905),\n",
    "                                             secondary_y='tc_cost')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.axes._subplots.AxesSubplot at 0x2980568fbe0>"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "[encoded data, 43136 characters]\n",
      "text/plain": [
       "<Figure size 864x432 with 2 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "ret_df[['returns', 'tc_cost']][-30:].cumsum().plot(figsize=(12, 6),\n",
    "                                             title='Fixed freq rebalanced: {0} with benchmark {1}'.format(freq, 905),\n",
    "                                             secondary_y='tc_cost')"
   ]
  },
  {
   "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
}
