{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "* 比较不同组合组合优化器在不同规模问题上的性能；\n",
    "\n",
    "* 下面的结果主要比较``alphamind``和``python``中其他优化器的性能差别，我们将尽可能使用``cvxopt``中的优化器，其次选择``scipy``；\n",
    "\n",
    "* 由于``scipy``在``ashare_ex``上面性能太差，所以一般忽略``scipy``在这个股票池上的表现；\n",
    "\n",
    "* 时间单位都是毫秒。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import timeit\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import cvxpy\n",
    "from cvxopt import solvers\n",
    "from scipy.optimize import linprog\n",
    "from scipy.optimize import minimize\n",
    "from alphamind.api import *\n",
    "from alphamind.portfolio.linearbuilder import linear_builder\n",
    "from alphamind.portfolio.meanvariancebuilder import mean_variance_builder\n",
    "from alphamind.portfolio.meanvariancebuilder import target_vol_builder\n",
    "\n",
    "pd.options.display.float_format = '{:,.2f}'.format"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 0. 数据准备\n",
    "------------------"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "ref_date = '2018-02-08'\n",
    "u_names = ['sh50', 'hs300', 'zz500', 'zz800', 'zz1000', 'ashare_ex']\n",
    "b_codes = [16, 300, 905, 906, 852, None]\n",
    "risk_model = 'short'\n",
    "factor = 'EPS'\n",
    "lb = 0.0\n",
    "ub = 0.1\n",
    "data_source = 'postgres+psycopg2://postgres:we083826@localhost/alpha'\n",
    "engine = SqlEngine(data_source)\n",
    "\n",
    "universes = [Universe('custom', [u_name]) for u_name in u_names]\n",
    "codes_set = [engine.fetch_codes(ref_date, universe=universe) for universe in universes]\n",
    "data_set = [engine.fetch_data(ref_date, factor, codes, benchmark=b_code, risk_model=risk_model) for codes, b_code in zip(codes_set, b_codes)]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1. 线性优化（带线性限制条件）\n",
    "---------------------------------"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "2018-03-30 16:52:12,784 - ALPHA_MIND - INFO - sh50 is finished\n",
      "2018-03-30 16:52:12,796 - ALPHA_MIND - INFO - hs300 is finished\n",
      "2018-03-30 16:52:12,813 - ALPHA_MIND - INFO - zz500 is finished\n",
      "2018-03-30 16:52:12,842 - ALPHA_MIND - INFO - zz800 is finished\n",
      "2018-03-30 16:52:12,879 - ALPHA_MIND - INFO - zz1000 is finished\n",
      "2018-03-30 16:52:13,184 - ALPHA_MIND - INFO - ashare_ex is finished\n"
     ]
    }
   ],
   "source": [
    "df = pd.DataFrame(columns=u_names, index=['cvxpy', 'alphamind'])\n",
    "\n",
    "number = 1\n",
    "\n",
    "for u_name, sample_data in zip(u_names, data_set):\n",
    "    factor_data = sample_data['factor']\n",
    "    er = factor_data[factor].values\n",
    "    n = len(er)\n",
    "    lbound = np.ones(n) * lb\n",
    "    ubound = np.ones(n) * ub\n",
    "    \n",
    "    risk_constraints = np.ones((n, 1))\n",
    "    risk_target = (np.array([1.]), np.array([1.]))\n",
    "\n",
    "    status, y, x1 = linear_builder(er, lbound, ubound, risk_constraints, risk_target)\n",
    "    elasped_time1 = timeit.timeit(\"linear_builder(er, lbound, ubound, risk_constraints, risk_target)\", number=number, globals=globals()) / number * 1000\n",
    "\n",
    "    A_eq = risk_constraints.T\n",
    "    b_eq = np.array([1.])\n",
    "    \n",
    "    solvers.options['glpk'] = {'msg_lev': 'GLP_MSG_OFF'}\n",
    "    w = cvxpy.Variable(n)\n",
    "    curr_risk_exposure = risk_constraints.T @ w\n",
    "    \n",
    "    constraints = [w >= lbound,\n",
    "                   w <= ubound,\n",
    "                   curr_risk_exposure == risk_target[0]]\n",
    "    \n",
    "    objective = cvxpy.Minimize(-w.T * er)\n",
    "    prob = cvxpy.Problem(objective, constraints)\n",
    "    \n",
    "    prob.solve(solver='GLPK')\n",
    "    elasped_time2 = timeit.timeit(\"prob.solve(solver='GLPK')\",\n",
    "                                  number=number, globals=globals()) / number * 1000\n",
    "\n",
    "    np.testing.assert_almost_equal(x1 @ er, np.array(w.value).flatten() @ er, 4)\n",
    "\n",
    "    df.loc['alphamind', u_name] = elasped_time1\n",
    "    df.loc['cvxpy', u_name] = elasped_time2\n",
    "    alpha_logger.info(f\"{u_name} is finished\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>sh50</th>\n",
       "      <th>hs300</th>\n",
       "      <th>zz500</th>\n",
       "      <th>zz800</th>\n",
       "      <th>zz1000</th>\n",
       "      <th>ashare_ex</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>cvxpy</th>\n",
       "      <td>1.68</td>\n",
       "      <td>3.13</td>\n",
       "      <td>5.02</td>\n",
       "      <td>10.15</td>\n",
       "      <td>13.55</td>\n",
       "      <td>145.17</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>alphamind</th>\n",
       "      <td>0.20</td>\n",
       "      <td>0.33</td>\n",
       "      <td>0.44</td>\n",
       "      <td>0.58</td>\n",
       "      <td>0.72</td>\n",
       "      <td>2.94</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "          sh50 hs300 zz500 zz800 zz1000 ashare_ex\n",
       "cvxpy     1.68  3.13  5.02 10.15  13.55    145.17\n",
       "alphamind 0.20  0.33  0.44  0.58   0.72      2.94"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. 线性优化（带L1限制条件）\n",
    "-----------------------"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "2018-03-30 16:52:13,374 - ALPHA_MIND - INFO - sh50 is finished\n",
      "2018-03-30 16:52:13,509 - ALPHA_MIND - INFO - hs300 is finished\n",
      "2018-03-30 16:52:13,732 - ALPHA_MIND - INFO - zz500 is finished\n",
      "2018-03-30 16:52:14,220 - ALPHA_MIND - INFO - zz800 is finished\n",
      "2018-03-30 16:52:14,956 - ALPHA_MIND - INFO - zz1000 is finished\n",
      "2018-03-30 16:52:21,246 - ALPHA_MIND - INFO - ashare_ex is finished\n"
     ]
    }
   ],
   "source": [
    "from cvxpy import pnorm\n",
    "\n",
    "df = pd.DataFrame(columns=u_names, index=['cvxpy', 'alphamind (simplex)', 'alphamind (interior)'])\n",
    "turn_over_target = 0.5\n",
    "number = 1\n",
    "\n",
    "for u_name, sample_data in zip(u_names, data_set):\n",
    "    factor_data = sample_data['factor']\n",
    "    er = factor_data[factor].values\n",
    "    n = len(er)\n",
    "    lbound = np.ones(n) * lb\n",
    "    ubound = np.ones(n) * ub\n",
    "    \n",
    "    if 'weight' in factor_data:\n",
    "        current_position = factor_data.weight.values\n",
    "    else:\n",
    "        current_position = np.ones_like(er) / len(er)\n",
    "\n",
    "    risk_constraints = np.ones((len(er), 1))\n",
    "    risk_target = (np.array([1.]), np.array([1.]))\n",
    "\n",
    "    status, y, x1 = linear_builder(er,\n",
    "                                   lbound,\n",
    "                                   ubound,\n",
    "                                   risk_constraints,\n",
    "                                   risk_target,\n",
    "                                   turn_over_target=turn_over_target,\n",
    "                                   current_position=current_position,\n",
    "                                   method='interior')\n",
    "    elasped_time1 = timeit.timeit(\"\"\"linear_builder(er,\n",
    "                                                     lbound,\n",
    "                                                     ubound,\n",
    "                                                     risk_constraints,\n",
    "                                                     risk_target,\n",
    "                                                     turn_over_target=turn_over_target,\n",
    "                                                     current_position=current_position,\n",
    "                                                     method='interior')\"\"\", number=number, globals=globals()) / number * 1000\n",
    "    \n",
    "    w = cvxpy.Variable(n)\n",
    "    curr_risk_exposure = risk_constraints.T @ w\n",
    "    \n",
    "    constraints = [w >= lbound,\n",
    "                   w <= ubound,\n",
    "                   curr_risk_exposure == risk_target[0],\n",
    "                   pnorm(w - current_position, 1) <= turn_over_target]\n",
    "    \n",
    "    objective = cvxpy.Minimize(-w.T * er)\n",
    "    prob = cvxpy.Problem(objective, constraints)\n",
    "    \n",
    "    prob.solve(solver='GLPK')\n",
    "    elasped_time2 = timeit.timeit(\"prob.solve(solver='GLPK')\",\n",
    "                                  number=number, globals=globals()) / number * 1000\n",
    "    \n",
    "    elasped_time3 = timeit.timeit(\"\"\"linear_builder(er,\n",
    "                                                     lbound,\n",
    "                                                     ubound,\n",
    "                                                     risk_constraints,\n",
    "                                                     risk_target,\n",
    "                                                     turn_over_target=turn_over_target,\n",
    "                                                     current_position=current_position,\n",
    "                                                     method='simplex')\"\"\", number=number, globals=globals()) / number * 1000\n",
    "    \n",
    "    \n",
    "    np.testing.assert_almost_equal(x1 @ er, np.array(w.value).flatten() @ er, 4)\n",
    "\n",
    "    df.loc['alphamind (interior)', u_name] = elasped_time1\n",
    "    df.loc['alphamind (simplex)', u_name] = elasped_time3\n",
    "    df.loc['cvxpy', u_name] = elasped_time2\n",
    "    alpha_logger.info(f\"{u_name} is finished\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>sh50</th>\n",
       "      <th>hs300</th>\n",
       "      <th>zz500</th>\n",
       "      <th>zz800</th>\n",
       "      <th>zz1000</th>\n",
       "      <th>ashare_ex</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>cvxpy</th>\n",
       "      <td>2.49</td>\n",
       "      <td>22.19</td>\n",
       "      <td>51.62</td>\n",
       "      <td>123.42</td>\n",
       "      <td>190.62</td>\n",
       "      <td>1,946.96</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>alphamind</th>\n",
       "      <td>3.77</td>\n",
       "      <td>33.59</td>\n",
       "      <td>55.49</td>\n",
       "      <td>116.31</td>\n",
       "      <td>165.62</td>\n",
       "      <td>1,239.47</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "          sh50 hs300 zz500  zz800 zz1000 ashare_ex\n",
       "cvxpy     2.49 22.19 51.62 123.42 190.62  1,946.96\n",
       "alphamind 3.77 33.59 55.49 116.31 165.62  1,239.47"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "## 3. Mean - Variance 优化 （无约束）\n",
    "-----------------------"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "2018-03-30 16:52:21,418 - ALPHA_MIND - INFO - sh50 is finished\n",
      "2018-03-30 16:52:21,888 - ALPHA_MIND - INFO - hs300 is finished\n",
      "2018-03-30 16:52:23,360 - ALPHA_MIND - INFO - zz500 is finished\n",
      "2018-03-30 16:52:29,066 - ALPHA_MIND - INFO - zz800 is finished\n",
      "2018-03-30 16:52:37,334 - ALPHA_MIND - INFO - zz1000 is finished\n",
      "2018-03-30 16:56:15,174 - ALPHA_MIND - INFO - ashare_ex is finished\n"
     ]
    }
   ],
   "source": [
    "from cvxpy import quad_form\n",
    "\n",
    "df = pd.DataFrame(columns=u_names, index=['cvxpy', 'alphamind'])\n",
    "number = 1\n",
    "\n",
    "for u_name, sample_data in zip(u_names, data_set):\n",
    "    all_styles = risk_styles + industry_styles + ['COUNTRY']\n",
    "    factor_data = sample_data['factor']\n",
    "    risk_cov = sample_data['risk_cov'][all_styles].values\n",
    "    risk_exposure = factor_data[all_styles].values\n",
    "    special_risk = factor_data.srisk.values\n",
    "    sec_cov = risk_exposure @ risk_cov @ risk_exposure.T / 10000 + np.diag(special_risk ** 2) / 10000\n",
    "    er = factor_data[factor].values\n",
    "    n = len(er)\n",
    "\n",
    "    bm = np.zeros(n)\n",
    "    lbound = -np.ones(n) * np.inf\n",
    "    ubound = np.ones(n) * np.inf\n",
    "\n",
    "    status, y, x1 = mean_variance_builder(er, sec_cov, bm, lbound, ubound, None, None, lam=1)\n",
    "    elasped_time1 = timeit.timeit(\"mean_variance_builder(er, sec_cov, bm, lbound, ubound, None, None, lam=1)\",\n",
    "                                  number=number, globals=globals()) / number * 1000\n",
    "    \n",
    "    w = cvxpy.Variable(n)\n",
    "    risk = quad_form(w, sec_cov)\n",
    "    objective = cvxpy.Minimize(-w.T * er + 0.5 * risk)\n",
    "    prob = cvxpy.Problem(objective)\n",
    "    prob.solve(solver='CVXOPT')\n",
    "    elasped_time2 = timeit.timeit(\"prob.solve(solver='CVXOPT')\",\n",
    "                                  number=number, globals=globals()) / number * 1000\n",
    "    \n",
    "    u1 = -x1 @ er + 0.5 * x1 @ sec_cov @ x1\n",
    "    x2 = np.array(w.value).flatten()\n",
    "    u2 =  -x2 @ er + 0.5 * x2 @ sec_cov @ x2\n",
    "    \n",
    "    np.testing.assert_array_almost_equal(u1, u2, 4)\n",
    "\n",
    "    df.loc['alphamind', u_name] = elasped_time1\n",
    "    df.loc['cvxpy', u_name] = elasped_time2\n",
    "    alpha_logger.info(f\"{u_name} is finished\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>sh50</th>\n",
       "      <th>hs300</th>\n",
       "      <th>zz500</th>\n",
       "      <th>zz800</th>\n",
       "      <th>zz1000</th>\n",
       "      <th>ashare_ex</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>cvxpy</th>\n",
       "      <td>9.81</td>\n",
       "      <td>185.93</td>\n",
       "      <td>638.17</td>\n",
       "      <td>2,501.41</td>\n",
       "      <td>3,665.02</td>\n",
       "      <td>94,592.70</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>alphamind</th>\n",
       "      <td>0.33</td>\n",
       "      <td>5.66</td>\n",
       "      <td>14.24</td>\n",
       "      <td>47.29</td>\n",
       "      <td>109.08</td>\n",
       "      <td>2,515.06</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "          sh50  hs300  zz500    zz800   zz1000 ashare_ex\n",
       "cvxpy     9.81 185.93 638.17 2,501.41 3,665.02 94,592.70\n",
       "alphamind 0.33   5.66  14.24    47.29   109.08  2,515.06"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4. Mean - Variance 优化 （Box约束）\n",
    "---------------"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "2018-03-30 16:56:16,044 - ALPHA_MIND - INFO - sh50 is finished\n",
      "2018-03-30 16:56:16,705 - ALPHA_MIND - INFO - hs300 is finished\n",
      "2018-03-30 16:56:19,651 - ALPHA_MIND - INFO - zz500 is finished\n",
      "2018-03-30 16:56:30,227 - ALPHA_MIND - INFO - zz800 is finished\n",
      "2018-03-30 16:56:44,840 - ALPHA_MIND - INFO - zz1000 is finished\n",
      "2018-03-30 17:08:25,343 - ALPHA_MIND - INFO - ashare_ex is finished\n"
     ]
    }
   ],
   "source": [
    "df = pd.DataFrame(columns=u_names, index=['cvxpy', 'alphamind'])\n",
    "number = 1\n",
    "\n",
    "for u_name, sample_data in zip(u_names, data_set):\n",
    "    all_styles = risk_styles + industry_styles + ['COUNTRY']\n",
    "    factor_data = sample_data['factor']\n",
    "    risk_cov = sample_data['risk_cov'][all_styles].values\n",
    "    risk_exposure = factor_data[all_styles].values\n",
    "    special_risk = factor_data.srisk.values\n",
    "    sec_cov = risk_exposure @ risk_cov @ risk_exposure.T / 10000 + np.diag(special_risk ** 2) / 10000\n",
    "    er = factor_data[factor].values\n",
    "    n = len(er)\n",
    "\n",
    "    bm = np.zeros(n)\n",
    "    lbound = np.zeros(n)\n",
    "    ubound = np.ones(n) * 0.1\n",
    "\n",
    "    status, y, x1 = mean_variance_builder(er, sec_cov, bm, lbound, ubound, None, None, lam=1)\n",
    "    elasped_time1 = timeit.timeit(\"mean_variance_builder(er, sec_cov, bm, lbound, ubound, None, None, lam=1)\",\n",
    "                                  number=number, globals=globals()) / number * 1000\n",
    "    \n",
    "    w = cvxpy.Variable(n)\n",
    "    risk = quad_form(w, sec_cov)\n",
    "    objective = cvxpy.Minimize(-w.T * er + 0.5 * risk)\n",
    "    constraints = [w >= lbound,\n",
    "                   w <= ubound]\n",
    "    prob = cvxpy.Problem(objective, constraints)\n",
    "    prob.solve(solver='CVXOPT')\n",
    "    elasped_time2 = timeit.timeit(\"prob.solve(solver='CVXOPT')\",\n",
    "                                  number=number, globals=globals()) / number * 1000\n",
    "    \n",
    "    u1 = -x1 @ er + 0.5 * x1 @ sec_cov @ x1\n",
    "    x2 = np.array(w.value).flatten()\n",
    "    u2 =  -x2 @ er + 0.5 * x2 @ sec_cov @ x2\n",
    "    \n",
    "    np.testing.assert_array_almost_equal(u1, u2, 4)\n",
    "\n",
    "    df.loc['alphamind', u_name] = elasped_time1\n",
    "    df.loc['cvxpy', u_name] = elasped_time2\n",
    "    alpha_logger.info(f\"{u_name} is finished\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>sh50</th>\n",
       "      <th>hs300</th>\n",
       "      <th>zz500</th>\n",
       "      <th>zz800</th>\n",
       "      <th>zz1000</th>\n",
       "      <th>ashare_ex</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>cvxpy</th>\n",
       "      <td>10.78</td>\n",
       "      <td>300.36</td>\n",
       "      <td>1,377.87</td>\n",
       "      <td>5,244.64</td>\n",
       "      <td>6,758.95</td>\n",
       "      <td>334,990.46</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>alphamind</th>\n",
       "      <td>0.32</td>\n",
       "      <td>4.78</td>\n",
       "      <td>16.02</td>\n",
       "      <td>41.63</td>\n",
       "      <td>64.54</td>\n",
       "      <td>1,134.95</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "           sh50  hs300    zz500    zz800   zz1000  ashare_ex\n",
       "cvxpy     10.78 300.36 1,377.87 5,244.64 6,758.95 334,990.46\n",
       "alphamind  0.32   4.78    16.02    41.63    64.54   1,134.95"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 5. Mean - Variance 优化 （Box约束以及线性约束）\n",
    "----------------"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "2018-03-30 17:08:25,991 - ALPHA_MIND - INFO - sh50 is finished\n",
      "2018-03-30 17:08:26,763 - ALPHA_MIND - INFO - hs300 is finished\n",
      "2018-03-30 17:08:30,276 - ALPHA_MIND - INFO - zz500 is finished\n",
      "2018-03-30 17:08:41,580 - ALPHA_MIND - INFO - zz800 is finished\n",
      "2018-03-30 17:09:18,856 - ALPHA_MIND - INFO - zz1000 is finished\n"
     ]
    }
   ],
   "source": [
    "df = pd.DataFrame(columns=u_names, index=['cvxpy', 'alphamind'])\n",
    "number = 1\n",
    "\n",
    "for u_name, sample_data in zip(u_names, data_set):\n",
    "    all_styles = risk_styles + industry_styles + ['COUNTRY']\n",
    "    factor_data = sample_data['factor']\n",
    "    risk_cov = sample_data['risk_cov'][all_styles].values\n",
    "    risk_exposure = factor_data[all_styles].values\n",
    "    special_risk = factor_data.srisk.values\n",
    "    sec_cov = risk_exposure @ risk_cov @ risk_exposure.T / 10000 + np.diag(special_risk ** 2) / 10000\n",
    "    er = factor_data[factor].values\n",
    "    n = len(er)\n",
    "    \n",
    "    bm = np.zeros(n)\n",
    "    lbound = np.zeros(n)\n",
    "    ubound = np.ones(n) * 0.1\n",
    "    \n",
    "    risk_constraints = np.ones((len(er), 1))\n",
    "    risk_target = (np.array([1.]), np.array([1.]))\n",
    "\n",
    "    status, y, x1 = mean_variance_builder(er, sec_cov, bm, lbound, ubound, risk_constraints, risk_target, lam=1)\n",
    "    elasped_time1 = timeit.timeit(\"mean_variance_builder(er, sec_cov, bm, lbound, ubound, None, None, lam=1)\",\n",
    "                                  number=number, globals=globals()) / number * 1000\n",
    "    \n",
    "    w = cvxpy.Variable(n)\n",
    "    risk = quad_form(w, sec_cov)\n",
    "    objective = cvxpy.Minimize(-w.T * er + 0.5 * risk)\n",
    "    curr_risk_exposure = risk_constraints.T @ w\n",
    "    constraints = [w >= lbound,\n",
    "                   w <= ubound,\n",
    "                   curr_risk_exposure == risk_target[0]]\n",
    "    prob = cvxpy.Problem(objective, constraints)\n",
    "    prob.solve(solver='CVXOPT')\n",
    "    elasped_time2 = timeit.timeit(\"prob.solve(solver='CVXOPT')\",\n",
    "                                  number=number, globals=globals()) / number * 1000\n",
    "\n",
    "    u1 = -x1 @ er + 0.5 * x1 @ sec_cov @ x1\n",
    "    x2 = np.array(w.value).flatten()\n",
    "    u2 =  -x2 @ er + 0.5 * x2 @ sec_cov @ x2\n",
    "    \n",
    "    np.testing.assert_array_almost_equal(u1, u2, 4)\n",
    "\n",
    "    df.loc['alphamind', u_name] = elasped_time1\n",
    "    df.loc['cvxpy', u_name] = elasped_time2\n",
    "    alpha_logger.info(f\"{u_name} is finished\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 6. 线性优化（带二次限制条件）\n",
    "-------------------------"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df = pd.DataFrame(columns=u_names, index=['cvxpy', 'alphamind'])\n",
    "number = 1\n",
    "target_vol = 0.1\n",
    "\n",
    "\n",
    "for u_name, sample_data in zip(u_names, data_set):\n",
    "    all_styles = risk_styles + industry_styles + ['COUNTRY']\n",
    "    factor_data = sample_data['factor']\n",
    "    risk_cov = sample_data['risk_cov'][all_styles].values\n",
    "    risk_exposure = factor_data[all_styles].values\n",
    "    special_risk = factor_data.srisk.values\n",
    "    sec_cov = risk_exposure @ risk_cov @ risk_exposure.T / 10000 + np.diag(special_risk ** 2) / 10000\n",
    "    er = factor_data[factor].values\n",
    "    n = len(er)\n",
    "    \n",
    "    if 'weight' in factor_data:\n",
    "        bm = factor_data.weight.values\n",
    "    else:\n",
    "        bm = np.ones_like(er) / n\n",
    "    lbound = np.zeros(n)\n",
    "    ubound = np.ones(n) * 0.1\n",
    "    \n",
    "    risk_constraints = np.ones((n, 1))\n",
    "    risk_target = (np.array([bm.sum()]), np.array([bm.sum()]))\n",
    "\n",
    "    status, y, x1 = target_vol_builder(er, sec_cov, bm, lbound, ubound, risk_constraints, risk_target, vol_low=0, vol_high=target_vol)\n",
    "    elasped_time1 = timeit.timeit(\"mean_variance_builder(er, sec_cov, bm, lbound, ubound, None, None, lam=1)\",\n",
    "                                  number=number, globals=globals()) / number * 1000\n",
    "    \n",
    "    w = cvxpy.Variable(n)\n",
    "    risk = quad_form(w - bm, sec_cov)\n",
    "    objective = cvxpy.Minimize(-w.T * er)\n",
    "    curr_risk_exposure = risk_constraints.T @ w\n",
    "    constraints = [w >= lbound,\n",
    "                   w <= ubound,\n",
    "                   curr_risk_exposure == risk_target[0],\n",
    "                   risk <= target_vol * target_vol]\n",
    "    prob = cvxpy.Problem(objective, constraints)\n",
    "    prob.solve(solver='CVXOPT')\n",
    "    elasped_time2 = timeit.timeit(\"prob.solve(solver='CVXOPT')\",\n",
    "                                  number=number, globals=globals()) / number * 1000\n",
    "\n",
    "    u1 = -x1 @ er\n",
    "    x2 = np.array(w.value).flatten()\n",
    "    u2 =  -x2 @ er\n",
    "    \n",
    "    np.testing.assert_array_almost_equal(u1, u2, 4)\n",
    "\n",
    "    df.loc['alphamind', u_name] = elasped_time1\n",
    "    df.loc['cvxpy', u_name] = elasped_time2\n",
    "    alpha_logger.info(f\"{u_name} is finished\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "df"
   ]
  },
  {
   "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.4"
  },
  "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()) "
    }
   },
   "position": {
    "height": "819px",
    "left": "1947px",
    "right": "20px",
    "top": "156px",
    "width": "504px"
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
