{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "* 请在环境变量中设置`DB_URI`指向数据库"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "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 PyFin.api import *\n",
    "from alphamind.api import *\n",
    "from alphamind.strategy.strategy import Strategy, RunningSetting\n",
    "from alphamind.portfolio.meanvariancebuilder import target_vol_builder\n",
    "\n",
    "plt.style.use('ggplot')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1. Single Day Analysis\n",
    "-----------------------"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "ref_date = '2018-01-08'\n",
    "engine = SqlEngine(os.environ['DB_URI'])\n",
    "universe = Universe('zz800')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "codes = engine.fetch_codes(ref_date, universe)\n",
    "total_data = engine.fetch_data(ref_date, 'EPS', codes, 906, industry='sw', risk_model='day')\n",
    "all_styles = risk_styles + industry_styles + ['COUNTRY']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "risk_cov = total_data['risk_cov'][all_styles].values\n",
    "factor = total_data['factor']\n",
    "risk_exposure = factor[all_styles].values\n",
    "special_risk = factor['srisk'].values"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Portfolio Construction\n",
    "\n",
    "* using `EPS` factor as alpha factor;\n",
    "* short selling is forbiden;\n",
    "* target of volatility for the activate weight is setting at 2.5% annually level."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "er = factor['EPS'].values\n",
    "bm = factor['weight'].values\n",
    "lbound = np.zeros(len(er))\n",
    "ubound = bm + 0.01\n",
    "cons_mat = np.ones((len(er), 1))\n",
    "risk_targets = (bm.sum(), bm.sum())\n",
    "target_vol = 0.025\n",
    "risk_model = dict(cov=None, factor_cov=risk_cov/10000, factor_loading=risk_exposure, idsync=special_risk ** 2 / 10000.)\n",
    "\n",
    "status, p_er, p_weight = \\\n",
    "    target_vol_builder(er, risk_model, bm, lbound, ubound, cons_mat, risk_targets, target_vol)\n",
    "    \n",
    "sec_cov = risk_exposure @ risk_cov @ risk_exposure.T / 10000. + np.diag(special_risk ** 2) / 10000"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "total weight is  1.0000\n",
      "portfolio activate weight forecasting vol is 0.0250\n",
      "portfolio er: 2.2232 comparing with benchmark er: 1.2359\n"
     ]
    }
   ],
   "source": [
    "# check the result\n",
    "print(f\"total weight is {p_weight.sum(): .4f}\")\n",
    "print(f\"portfolio activate weight forecasting vol is {np.sqrt((p_weight - bm) @ sec_cov @ (p_weight - bm)):.4f}\")\n",
    "print(f\"portfolio er: {p_weight @ er:.4f} comparing with benchmark er: {bm @ er:.4f}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. Porfolio Construction: 2016 ~ 2018\n",
    "-------------------------------"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "\"\"\"\n",
    "Back test parameter settings\n",
    "\"\"\"\n",
    "\n",
    "start_date = '2016-01-01'\n",
    "end_date = '2018-02-08'\n",
    "\n",
    "freq = '10b'\n",
    "neutralized_risk = industry_styles\n",
    "industry_name = 'sw_adj'\n",
    "industry_level = 1\n",
    "risk_model = 'short'\n",
    "batch = 0\n",
    "horizon = map_freq(freq)\n",
    "universe = Universe('zz800')\n",
    "data_source = os.environ['DB_URI']\n",
    "benchmark_code = 906\n",
    "target_vol = 0.05\n",
    "weights_bandwidth = 0.02"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [],
   "source": [
    "\"\"\"\n",
    "Factor Model\n",
    "\"\"\"\n",
    "\n",
    "alpha_factors = {'f01': CSRank(LAST('EPS'))}\n",
    "weights = dict(f01=1.)\n",
    "alpha_model = ConstLinearModel(features=alpha_factors, weights=weights)\n",
    "\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)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "\"\"\"\n",
    "Constraintes settings\n",
    "\"\"\"\n",
    "\n",
    "constraint_risk = ['SIZE', 'SIZENL', 'BETA']\n",
    "total_risk_names = constraint_risk + ['benchmark', 'total']\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)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "\"\"\"\n",
    "Running Settings\n",
    "\"\"\"\n",
    "running_setting = RunningSetting(weights_bandwidth=weights_bandwidth,\n",
    "                                 rebalance_method='tv',\n",
    "                                 bounds=bounds,\n",
    "                                 target_vol=target_vol)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\"\"\"\n",
    "Strategy run\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",
    "strategy.prepare_backtest_data()\n",
    "ret_df, positions = strategy.run(running_setting)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ret_df[['excess_return', 'turn_over']].cumsum().plot(figsize=(14, 7),\n",
    "                                                     title='Fixed freq rebalanced with target vol \\\n",
    "                                                     at {2}: {0} with benchmark {1}'.format(freq, benchmark_code, target_vol),\n",
    "                                                     secondary_y='turn_over')"
   ]
  },
  {
   "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
}
