Commit 35776ac2 authored by Dr.李's avatar Dr.李

udpate example 7 to use cvxpy

parent 011c29b5
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
"source": [ "source": [
"* 比较不同组合组合优化器在不同规模问题上的性能;\n", "* 比较不同组合组合优化器在不同规模问题上的性能;\n",
"\n", "\n",
"* 下面的结果主要比较``alphamind``和``sicpy``中内置优化器的性能差别;\n", "* 下面的结果主要比较``alphamind``和``python``中其他优化器的性能差别,我们将尽可能使用``cvxopt``中的优化器,其次选择``scipy``;\n",
"\n", "\n",
"* 由于``scipy``在``ashare_ex``上面性能太差,所以一般忽略``scipy``在这个股票池上的表现;\n", "* 由于``scipy``在``ashare_ex``上面性能太差,所以一般忽略``scipy``在这个股票池上的表现;\n",
"\n", "\n",
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
"import timeit\n", "import timeit\n",
"import numpy as np\n", "import numpy as np\n",
"import pandas as pd\n", "import pandas as pd\n",
"import cvxpy\n",
"from cvxopt import solvers\n",
"from scipy.optimize import linprog\n", "from scipy.optimize import linprog\n",
"from scipy.optimize import minimize\n", "from scipy.optimize import minimize\n",
"from alphamind.api import *\n", "from alphamind.api import *\n",
...@@ -49,8 +51,8 @@ ...@@ -49,8 +51,8 @@
"outputs": [], "outputs": [],
"source": [ "source": [
"ref_date = '2018-02-08'\n", "ref_date = '2018-02-08'\n",
"u_names = ['sh50', 'hs300', 'zz500', 'zz800', 'ashare_ex']\n", "u_names = ['sh50', 'hs300', 'zz500', 'zz800', 'zz1000', 'ashare_ex']\n",
"b_codes = [16, 300, 905, 906, None]\n", "b_codes = [16, 300, 905, 906, 852, None]\n",
"risk_model = 'short'\n", "risk_model = 'short'\n",
"factor = 'EPS'\n", "factor = 'EPS'\n",
"lb = 0.0\n", "lb = 0.0\n",
...@@ -80,46 +82,55 @@ ...@@ -80,46 +82,55 @@
"name": "stderr", "name": "stderr",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"2018-03-26 22:21:59,192 - ALPHA_MIND - INFO - sh50 is finished\n", "2018-03-28 12:46:50,110 - ALPHA_MIND - INFO - sh50 is finished\n",
"2018-03-26 22:21:59,346 - ALPHA_MIND - INFO - hs300 is finished\n", "2018-03-28 12:46:50,131 - ALPHA_MIND - INFO - hs300 is finished\n",
"2018-03-26 22:21:59,940 - ALPHA_MIND - INFO - zz500 is finished\n", "2018-03-28 12:46:50,156 - ALPHA_MIND - INFO - zz500 is finished\n",
"2018-03-26 22:22:02,388 - ALPHA_MIND - INFO - zz800 is finished\n", "2018-03-28 12:46:50,193 - ALPHA_MIND - INFO - zz800 is finished\n",
"2018-03-26 22:22:02,396 - ALPHA_MIND - INFO - ashare_ex is finished\n" "2018-03-28 12:46:50,244 - ALPHA_MIND - INFO - zz1000 is finished\n",
"2018-03-28 12:46:50,830 - ALPHA_MIND - INFO - ashare_ex is finished\n"
] ]
} }
], ],
"source": [ "source": [
"df = pd.DataFrame(columns=u_names, index=['scipy', 'alphamind'])\n", "df = pd.DataFrame(columns=u_names, index=['cvxpy', 'alphamind'])\n",
"\n", "\n",
"number = 1\n", "number = 1\n",
"\n", "\n",
"for u_name, sample_data in zip(u_names, data_set):\n", "for u_name, sample_data in zip(u_names, data_set):\n",
" factor_data = sample_data['factor']\n", " factor_data = sample_data['factor']\n",
" er = factor_data[factor].values\n", " er = factor_data[factor].values\n",
" lbound = np.ones(len(er)) * lb\n", " n = len(er)\n",
" ubound = np.ones(len(er)) * ub\n", " lbound = np.ones(n) * lb\n",
"\n", " ubound = np.ones(n) * ub\n",
" risk_constraints = np.ones((len(er), 1))\n", " \n",
" risk_constraints = np.ones((n, 1))\n",
" risk_target = (np.array([1.]), np.array([1.]))\n", " risk_target = (np.array([1.]), np.array([1.]))\n",
"\n", "\n",
" status, y, x1 = linear_builder(er, lbound, ubound, risk_constraints, risk_target)\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", " elasped_time1 = timeit.timeit(\"linear_builder(er, lbound, ubound, risk_constraints, risk_target)\", number=number, globals=globals()) / number * 1000\n",
"\n", "\n",
" c = -er\n",
" A_eq = risk_constraints.T\n", " A_eq = risk_constraints.T\n",
" b_eq = np.array([1.])\n", " b_eq = np.array([1.])\n",
" \n", " \n",
" if u_name != 'ashare_ex':\n", " solvers.options['glpk'] = {'msg_lev': 'GLP_MSG_OFF'}\n",
" res = linprog(c, A_ub=None, b_ub=None, A_eq=A_eq, b_eq=b_eq, bounds=list(zip(lbound, ubound)))\n", " w = cvxpy.Variable(n)\n",
" elasped_time2 = timeit.timeit(\"linprog(c, A_ub=None, b_ub=None, A_eq=A_eq, b_eq=b_eq, bounds=list(zip(lbound, ubound)))\",\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", " number=number, globals=globals()) / number * 1000\n",
" x2 = res['x']\n", "\n",
" np.testing.assert_array_almost_equal(x1, x2, 4)\n", " np.testing.assert_almost_equal(x1 @ er, np.array(w.value).flatten() @ er, 4)\n",
" else:\n",
" elasped_time2 = np.nan\n",
"\n", "\n",
" df.loc['alphamind', u_name] = elasped_time1\n", " df.loc['alphamind', u_name] = elasped_time1\n",
" df.loc['scipy', u_name] = elasped_time2\n", " df.loc['cvxpy', u_name] = elasped_time2\n",
" alpha_logger.info(f\"{u_name} is finished\")" " alpha_logger.info(f\"{u_name} is finished\")"
] ]
}, },
...@@ -153,34 +164,37 @@ ...@@ -153,34 +164,37 @@
" <th>hs300</th>\n", " <th>hs300</th>\n",
" <th>zz500</th>\n", " <th>zz500</th>\n",
" <th>zz800</th>\n", " <th>zz800</th>\n",
" <th>zz1000</th>\n",
" <th>ashare_ex</th>\n", " <th>ashare_ex</th>\n",
" </tr>\n", " </tr>\n",
" </thead>\n", " </thead>\n",
" <tbody>\n", " <tbody>\n",
" <tr>\n", " <tr>\n",
" <th>scipy</th>\n", " <th>cvxpy</th>\n",
" <td>20.94</td>\n", " <td>2.69</td>\n",
" <td>73.66</td>\n", " <td>6.37</td>\n",
" <td>295.75</td>\n", " <td>7.28</td>\n",
" <td>1,207.40</td>\n", " <td>12.55</td>\n",
" <td>NaN</td>\n", " <td>20.09</td>\n",
" <td>325.88</td>\n",
" </tr>\n", " </tr>\n",
" <tr>\n", " <tr>\n",
" <th>alphamind</th>\n", " <th>alphamind</th>\n",
" <td>0.32</td>\n", " <td>0.34</td>\n",
" <td>0.31</td>\n", " <td>0.58</td>\n",
" <td>0.38</td>\n", " <td>0.70</td>\n",
" <td>0.59</td>\n", " <td>0.92</td>\n",
" <td>2.66</td>\n", " <td>1.08</td>\n",
" <td>3.08</td>\n",
" </tr>\n", " </tr>\n",
" </tbody>\n", " </tbody>\n",
"</table>\n", "</table>\n",
"</div>" "</div>"
], ],
"text/plain": [ "text/plain": [
" sh50 hs300 zz500 zz800 ashare_ex\n", " sh50 hs300 zz500 zz800 zz1000 ashare_ex\n",
"scipy 20.94 73.66 295.75 1,207.40 NaN\n", "cvxpy 2.69 6.37 7.28 12.55 20.09 325.88\n",
"alphamind 0.32 0.31 0.38 0.59 2.66" "alphamind 0.34 0.58 0.70 0.92 1.08 3.08"
] ]
}, },
"execution_count": 4, "execution_count": 4,
...@@ -209,24 +223,28 @@ ...@@ -209,24 +223,28 @@
"name": "stderr", "name": "stderr",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"2018-03-26 22:22:02,962 - ALPHA_MIND - INFO - sh50 is finished\n", "2018-03-28 12:46:51,048 - ALPHA_MIND - INFO - sh50 is finished\n",
"2018-03-26 22:22:02,986 - ALPHA_MIND - INFO - hs300 is finished\n", "2018-03-28 12:46:51,157 - ALPHA_MIND - INFO - hs300 is finished\n",
"2018-03-26 22:22:03,063 - ALPHA_MIND - INFO - zz500 is finished\n", "2018-03-28 12:46:51,442 - ALPHA_MIND - INFO - zz500 is finished\n",
"2018-03-26 22:22:03,254 - ALPHA_MIND - INFO - zz800 is finished\n", "2018-03-28 12:46:52,102 - ALPHA_MIND - INFO - zz800 is finished\n",
"2018-03-26 22:22:08,004 - ALPHA_MIND - INFO - ashare_ex is finished\n" "2018-03-28 12:46:53,172 - ALPHA_MIND - INFO - zz1000 is finished\n",
"2018-03-28 12:47:04,916 - ALPHA_MIND - INFO - ashare_ex is finished\n"
] ]
} }
], ],
"source": [ "source": [
"df = pd.DataFrame(columns=u_names, index=['alphamind'])\n", "from cvxpy import pnorm\n",
"\n",
"df = pd.DataFrame(columns=u_names, index=['cvxpy', 'alphamind'])\n",
"turn_over_target = 0.5\n", "turn_over_target = 0.5\n",
"number = 1\n", "number = 1\n",
"\n", "\n",
"for u_name, sample_data in zip(u_names, data_set):\n", "for u_name, sample_data in zip(u_names, data_set):\n",
" factor_data = sample_data['factor']\n", " factor_data = sample_data['factor']\n",
" er = factor_data[factor].values\n", " er = factor_data[factor].values\n",
" lbound = np.ones(len(er)) * lb\n", " n = len(er)\n",
" ubound = np.ones(len(er)) * ub\n", " lbound = np.ones(n) * lb\n",
" ubound = np.ones(n) * ub\n",
" \n", " \n",
" if 'weight' in factor_data:\n", " if 'weight' in factor_data:\n",
" current_position = factor_data.weight.values\n", " current_position = factor_data.weight.values\n",
...@@ -238,10 +256,25 @@ ...@@ -238,10 +256,25 @@
"\n", "\n",
" status, y, x1 = linear_builder(er, lbound, ubound, risk_constraints, risk_target, turn_over_target=turn_over_target, current_position=current_position)\n", " status, y, x1 = linear_builder(er, lbound, ubound, risk_constraints, risk_target, turn_over_target=turn_over_target, current_position=current_position)\n",
" elasped_time1 = timeit.timeit(\"linear_builder(er, lbound, ubound, risk_constraints, risk_target, turn_over_target=turn_over_target, current_position=current_position)\", number=number, globals=globals()) / number * 1000\n", " elasped_time1 = timeit.timeit(\"linear_builder(er, lbound, ubound, risk_constraints, risk_target, turn_over_target=turn_over_target, current_position=current_position)\", number=number, globals=globals()) / number * 1000\n",
"\n", " \n",
" np.testing.assert_almost_equal(np.abs(x1 - current_position).sum(), 0.5)\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",
" np.testing.assert_almost_equal(x1 @ er, np.array(w.value).flatten() @ er, 4)\n",
"\n", "\n",
" df.loc['alphamind', u_name] = elasped_time1\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\")" " alpha_logger.info(f\"{u_name} is finished\")"
] ]
}, },
...@@ -275,25 +308,37 @@ ...@@ -275,25 +308,37 @@
" <th>hs300</th>\n", " <th>hs300</th>\n",
" <th>zz500</th>\n", " <th>zz500</th>\n",
" <th>zz800</th>\n", " <th>zz800</th>\n",
" <th>zz1000</th>\n",
" <th>ashare_ex</th>\n", " <th>ashare_ex</th>\n",
" </tr>\n", " </tr>\n",
" </thead>\n", " </thead>\n",
" <tbody>\n", " <tbody>\n",
" <tr>\n", " <tr>\n",
" <th>cvxpy</th>\n",
" <td>4.26</td>\n",
" <td>28.31</td>\n",
" <td>67.48</td>\n",
" <td>164.81</td>\n",
" <td>256.14</td>\n",
" <td>2,561.17</td>\n",
" </tr>\n",
" <tr>\n",
" <th>alphamind</th>\n", " <th>alphamind</th>\n",
" <td>0.89</td>\n", " <td>1.22</td>\n",
" <td>11.30</td>\n", " <td>20.28</td>\n",
" <td>36.35</td>\n", " <td>67.10</td>\n",
" <td>93.81</td>\n", " <td>154.95</td>\n",
" <td>2,372.76</td>\n", " <td>267.17</td>\n",
" <td>3,314.10</td>\n",
" </tr>\n", " </tr>\n",
" </tbody>\n", " </tbody>\n",
"</table>\n", "</table>\n",
"</div>" "</div>"
], ],
"text/plain": [ "text/plain": [
" sh50 hs300 zz500 zz800 ashare_ex\n", " sh50 hs300 zz500 zz800 zz1000 ashare_ex\n",
"alphamind 0.89 11.30 36.35 93.81 2,372.76" "cvxpy 4.26 28.31 67.48 164.81 256.14 2,561.17\n",
"alphamind 1.22 20.28 67.10 154.95 267.17 3,314.10"
] ]
}, },
"execution_count": 6, "execution_count": 6,
...@@ -324,16 +369,19 @@ ...@@ -324,16 +369,19 @@
"name": "stderr", "name": "stderr",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"2018-03-26 22:22:14,212 - ALPHA_MIND - INFO - sh50 is finished\n", "2018-03-28 12:47:05,225 - ALPHA_MIND - INFO - sh50 is finished\n",
"2018-03-26 22:22:14,523 - ALPHA_MIND - INFO - hs300 is finished\n", "2018-03-28 12:47:06,047 - ALPHA_MIND - INFO - hs300 is finished\n",
"2018-03-26 22:22:14,973 - ALPHA_MIND - INFO - zz500 is finished\n", "2018-03-28 12:47:07,931 - ALPHA_MIND - INFO - zz500 is finished\n",
"2018-03-26 22:22:16,365 - ALPHA_MIND - INFO - zz800 is finished\n", "2018-03-28 12:47:13,124 - ALPHA_MIND - INFO - zz800 is finished\n",
"2018-03-26 22:23:11,227 - ALPHA_MIND - INFO - ashare_ex is finished\n" "2018-03-28 12:47:20,586 - ALPHA_MIND - INFO - zz1000 is finished\n",
"2018-03-28 12:50:28,528 - ALPHA_MIND - INFO - ashare_ex is finished\n"
] ]
} }
], ],
"source": [ "source": [
"df = pd.DataFrame(columns=u_names, index=['alphamind', 'direct'])\n", "from cvxpy import quad_form\n",
"\n",
"df = pd.DataFrame(columns=u_names, index=['cvxpy', 'alphamind'])\n",
"number = 1\n", "number = 1\n",
"\n", "\n",
"for u_name, sample_data in zip(u_names, data_set):\n", "for u_name, sample_data in zip(u_names, data_set):\n",
...@@ -344,22 +392,32 @@ ...@@ -344,22 +392,32 @@
" special_risk = factor_data.srisk.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", " sec_cov = risk_exposure @ risk_cov @ risk_exposure.T / 10000 + np.diag(special_risk ** 2) / 10000\n",
" er = factor_data[factor].values\n", " er = factor_data[factor].values\n",
" n = len(er)\n",
"\n", "\n",
" bm = np.zeros(len(er))\n", " bm = np.zeros(n)\n",
" lbound = -np.ones(len(er)) * np.inf\n", " lbound = -np.ones(n) * np.inf\n",
" ubound = np.ones(len(er)) * np.inf\n", " ubound = np.ones(n) * np.inf\n",
"\n", "\n",
" status, y, x1 = mean_variance_builder(er, sec_cov, bm, lbound, ubound, None, None, lam=1)\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", " 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", " number=number, globals=globals()) / number * 1000\n",
" x2 = np.linalg.inv(sec_cov) @ er\n", " \n",
" elasped_time2 = timeit.timeit(\"np.linalg.inv(sec_cov) @ er\",\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", " number=number, globals=globals()) / number * 1000\n",
"\n", " \n",
" np.testing.assert_array_almost_equal(x1, x2, 4)\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", "\n",
" df.loc['alphamind', u_name] = elasped_time1\n", " df.loc['alphamind', u_name] = elasped_time1\n",
" df.loc['direct', u_name] = elasped_time2\n", " df.loc['cvxpy', u_name] = elasped_time2\n",
" alpha_logger.info(f\"{u_name} is finished\")" " alpha_logger.info(f\"{u_name} is finished\")"
] ]
}, },
...@@ -393,34 +451,37 @@ ...@@ -393,34 +451,37 @@
" <th>hs300</th>\n", " <th>hs300</th>\n",
" <th>zz500</th>\n", " <th>zz500</th>\n",
" <th>zz800</th>\n", " <th>zz800</th>\n",
" <th>zz1000</th>\n",
" <th>ashare_ex</th>\n", " <th>ashare_ex</th>\n",
" </tr>\n", " </tr>\n",
" </thead>\n", " </thead>\n",
" <tbody>\n", " <tbody>\n",
" <tr>\n", " <tr>\n",
" <th>alphamind</th>\n", " <th>cvxpy</th>\n",
" <td>42.10</td>\n", " <td>13.26</td>\n",
" <td>114.71</td>\n", " <td>166.37</td>\n",
" <td>175.51</td>\n", " <td>493.95</td>\n",
" <td>561.04</td>\n", " <td>1,635.71</td>\n",
" <td>25,991.58</td>\n", " <td>2,359.22</td>\n",
" <td>51,708.15</td>\n",
" </tr>\n", " </tr>\n",
" <tr>\n", " <tr>\n",
" <th>direct</th>\n", " <th>alphamind</th>\n",
" <td>0.14</td>\n", " <td>68.57</td>\n",
" <td>2.63</td>\n", " <td>205.78</td>\n",
" <td>10.06</td>\n", " <td>317.68</td>\n",
" <td>37.57</td>\n", " <td>670.81</td>\n",
" <td>1,722.59</td>\n", " <td>915.77</td>\n",
" <td>32,733.73</td>\n",
" </tr>\n", " </tr>\n",
" </tbody>\n", " </tbody>\n",
"</table>\n", "</table>\n",
"</div>" "</div>"
], ],
"text/plain": [ "text/plain": [
" sh50 hs300 zz500 zz800 ashare_ex\n", " sh50 hs300 zz500 zz800 zz1000 ashare_ex\n",
"alphamind 42.10 114.71 175.51 561.04 25,991.58\n", "cvxpy 13.26 166.37 493.95 1,635.71 2,359.22 51,708.15\n",
"direct 0.14 2.63 10.06 37.57 1,722.59" "alphamind 68.57 205.78 317.68 670.81 915.77 32,733.73"
] ]
}, },
"execution_count": 8, "execution_count": 8,
...@@ -448,22 +509,17 @@ ...@@ -448,22 +509,17 @@
"name": "stderr", "name": "stderr",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"2018-03-26 22:23:11,862 - ALPHA_MIND - INFO - sh50 is finished\n", "2018-03-28 12:50:29,489 - ALPHA_MIND - INFO - sh50 is finished\n",
"2018-03-26 22:23:13,992 - ALPHA_MIND - INFO - hs300 is finished\n", "2018-03-28 12:50:30,295 - ALPHA_MIND - INFO - hs300 is finished\n",
"2018-03-26 22:25:38,790 - ALPHA_MIND - INFO - zz500 is finished\n", "2018-03-28 12:50:33,286 - ALPHA_MIND - INFO - zz500 is finished\n",
"2018-03-26 22:29:08,827 - ALPHA_MIND - INFO - zz800 is finished\n", "2018-03-28 12:50:39,842 - ALPHA_MIND - INFO - zz800 is finished\n",
"2018-03-26 22:29:10,259 - ALPHA_MIND - INFO - ashare_ex is finished\n" "2018-03-28 12:50:55,691 - ALPHA_MIND - INFO - zz1000 is finished\n",
"2018-03-28 12:57:46,604 - ALPHA_MIND - INFO - ashare_ex is finished\n"
] ]
} }
], ],
"source": [ "source": [
"def func(x):\n", "df = pd.DataFrame(columns=u_names, index=['cvxpy', 'alphamind'])\n",
" return 0.5 * x @ sec_cov @ x - er @ x\n",
"\n",
"def con_func(x):\n",
" return x.sum() - 1.\n",
"\n",
"df = pd.DataFrame(columns=u_names, index=['alphamind', 'scipy'])\n",
"number = 1\n", "number = 1\n",
"\n", "\n",
"for u_name, sample_data in zip(u_names, data_set):\n", "for u_name, sample_data in zip(u_names, data_set):\n",
...@@ -474,10 +530,11 @@ ...@@ -474,10 +530,11 @@
" special_risk = factor_data.srisk.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", " sec_cov = risk_exposure @ risk_cov @ risk_exposure.T / 10000 + np.diag(special_risk ** 2) / 10000\n",
" er = factor_data[factor].values\n", " er = factor_data[factor].values\n",
" n = len(er)\n",
" \n", " \n",
" bm = np.zeros(len(er))\n", " bm = np.zeros(n)\n",
" lbound = np.zeros(len(er))\n", " lbound = np.zeros(n)\n",
" ubound = np.ones(len(er)) * 0.1\n", " ubound = np.ones(n) * 0.1\n",
" \n", " \n",
" risk_constraints = np.ones((len(er), 1))\n", " risk_constraints = np.ones((len(er), 1))\n",
" risk_target = (np.array([1.]), np.array([1.]))\n", " risk_target = (np.array([1.]), np.array([1.]))\n",
...@@ -486,20 +543,26 @@ ...@@ -486,20 +543,26 @@
" elasped_time1 = timeit.timeit(\"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", " number=number, globals=globals()) / number * 1000\n",
" \n", " \n",
" cons = [dict(type='eq', fun=con_func)]\n", " w = cvxpy.Variable(n)\n",
" \n", " risk = quad_form(w, sec_cov)\n",
" if u_name != 'ashare_ex':\n", " objective = cvxpy.Minimize(-w.T * er + 0.5 * risk)\n",
" res = minimize(func, np.zeros(len(er)), bounds=list(zip(lbound, ubound)), constraints=cons, tol=1e-12)\n", " curr_risk_exposure = risk_constraints.T @ w\n",
" x2 = res['x']\n", " constraints = [w >= lbound,\n",
" elasped_time2 = timeit.timeit(\"minimize(func, np.zeros(len(er)), bounds=list(zip(lbound, ubound)), constraints=cons, tol=1e-12)\",\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", " number=number, globals=globals()) / number * 1000\n",
"\n", "\n",
" np.testing.assert_array_almost_equal(x1, x2, 4)\n", " u1 = -x1 @ er + 0.5 * x1 @ sec_cov @ x1\n",
" else:\n", " x2 = np.array(w.value).flatten()\n",
" elasped_time2 = np.nan\n", " u2 = -x2 @ er + 0.5 * x2 @ sec_cov @ x2\n",
" \n",
" np.testing.assert_array_almost_equal(u1, u2, 4)\n",
"\n", "\n",
" df.loc['alphamind', u_name] = elasped_time1\n", " df.loc['alphamind', u_name] = elasped_time1\n",
" df.loc['scipy', u_name] = elasped_time2\n", " df.loc['cvxpy', u_name] = elasped_time2\n",
" alpha_logger.info(f\"{u_name} is finished\")" " alpha_logger.info(f\"{u_name} is finished\")"
] ]
}, },
...@@ -533,34 +596,37 @@ ...@@ -533,34 +596,37 @@
" <th>hs300</th>\n", " <th>hs300</th>\n",
" <th>zz500</th>\n", " <th>zz500</th>\n",
" <th>zz800</th>\n", " <th>zz800</th>\n",
" <th>zz1000</th>\n",
" <th>ashare_ex</th>\n", " <th>ashare_ex</th>\n",
" </tr>\n", " </tr>\n",
" </thead>\n", " </thead>\n",
" <tbody>\n", " <tbody>\n",
" <tr>\n", " <tr>\n",
" <th>alphamind</th>\n", " <th>cvxpy</th>\n",
" <td>8.13</td>\n", " <td>20.25</td>\n",
" <td>21.83</td>\n", " <td>314.35</td>\n",
" <td>30.04</td>\n", " <td>1,306.26</td>\n",
" <td>71.48</td>\n", " <td>2,795.40</td>\n",
" <td>652.18</td>\n", " <td>7,386.27</td>\n",
" <td>195,024.34</td>\n",
" </tr>\n", " </tr>\n",
" <tr>\n", " <tr>\n",
" <th>scipy</th>\n", " <th>alphamind</th>\n",
" <td>8.33</td>\n", " <td>21.20</td>\n",
" <td>1,032.94</td>\n", " <td>41.34</td>\n",
" <td>70,803.96</td>\n", " <td>60.28</td>\n",
" <td>101,735.25</td>\n", " <td>91.30</td>\n",
" <td>NaN</td>\n", " <td>77.67</td>\n",
" <td>868.86</td>\n",
" </tr>\n", " </tr>\n",
" </tbody>\n", " </tbody>\n",
"</table>\n", "</table>\n",
"</div>" "</div>"
], ],
"text/plain": [ "text/plain": [
" sh50 hs300 zz500 zz800 ashare_ex\n", " sh50 hs300 zz500 zz800 zz1000 ashare_ex\n",
"alphamind 8.13 21.83 30.04 71.48 652.18\n", "cvxpy 20.25 314.35 1,306.26 2,795.40 7,386.27 195,024.34\n",
"scipy 8.33 1,032.94 70,803.96 101,735.25 NaN" "alphamind 21.20 41.34 60.28 91.30 77.67 868.86"
] ]
}, },
"execution_count": 10, "execution_count": 10,
...@@ -589,27 +655,20 @@ ...@@ -589,27 +655,20 @@
"name": "stderr", "name": "stderr",
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"2018-03-26 22:29:10,929 - ALPHA_MIND - INFO - sh50 is finished\n", "2018-03-28 12:57:47,308 - ALPHA_MIND - INFO - sh50 is finished\n",
"2018-03-26 22:29:13,377 - ALPHA_MIND - INFO - hs300 is finished\n", "2018-03-28 12:57:48,181 - ALPHA_MIND - INFO - hs300 is finished\n",
"2018-03-26 22:30:13,788 - ALPHA_MIND - INFO - zz500 is finished\n", "2018-03-28 12:57:51,075 - ALPHA_MIND - INFO - zz500 is finished\n",
"2018-03-26 22:34:02,088 - ALPHA_MIND - INFO - zz800 is finished\n", "2018-03-28 12:58:05,881 - ALPHA_MIND - INFO - zz800 is finished\n",
"2018-03-26 22:34:04,708 - ALPHA_MIND - INFO - ashare_ex is finished\n" "2018-03-28 12:58:19,775 - ALPHA_MIND - INFO - zz1000 is finished\n",
"2018-03-28 13:05:47,684 - ALPHA_MIND - INFO - ashare_ex is finished\n"
] ]
} }
], ],
"source": [ "source": [
"df = pd.DataFrame(columns=u_names, index=['alphamind', 'scipy'])\n", "df = pd.DataFrame(columns=u_names, index=['cvxpy', 'alphamind'])\n",
"number = 1\n", "number = 1\n",
"target_vol = 0.1\n", "target_vol = 0.1\n",
"\n", "\n",
"def func(x):\n",
" return - er @ x\n",
"\n",
"def con_func(x):\n",
" return x.sum()\n",
"\n",
"def ieq_func(x):\n",
" return target_vol * target_vol - x @ sec_cov @ x\n",
"\n", "\n",
"for u_name, sample_data in zip(u_names, data_set):\n", "for u_name, sample_data in zip(u_names, data_set):\n",
" all_styles = risk_styles + industry_styles + ['COUNTRY']\n", " all_styles = risk_styles + industry_styles + ['COUNTRY']\n",
...@@ -619,35 +678,43 @@ ...@@ -619,35 +678,43 @@
" special_risk = factor_data.srisk.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", " sec_cov = risk_exposure @ risk_cov @ risk_exposure.T / 10000 + np.diag(special_risk ** 2) / 10000\n",
" er = factor_data[factor].values\n", " er = factor_data[factor].values\n",
" n = len(er)\n",
" \n", " \n",
" if 'weight' in factor_data:\n", " if 'weight' in factor_data:\n",
" bm = factor_data.weight.values\n", " bm = factor_data.weight.values\n",
" else:\n", " else:\n",
" bm = np.ones_like(er) / len(er)\n", " bm = np.ones_like(er) / n\n",
" lbound = np.zeros(len(er))\n", " lbound = np.zeros(n)\n",
" ubound = np.ones(len(er)) * 0.1\n", " ubound = np.ones(n) * 0.1\n",
" \n", " \n",
" risk_constraints = np.ones((len(er), 1))\n", " risk_constraints = np.ones((n, 1))\n",
" risk_target = (np.array([bm.sum()]), np.array([bm.sum()]))\n", " risk_target = (np.array([bm.sum()]), np.array([bm.sum()]))\n",
"\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", " 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", " 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", " number=number, globals=globals()) / number * 1000\n",
" \n", " \n",
" cons = [dict(type='eq', fun=con_func), dict(type='ineq', fun=ieq_func)]\n", " w = cvxpy.Variable(n)\n",
" \n", " risk = quad_form(w - bm, sec_cov)\n",
" if u_name != 'ashare_ex':\n", " objective = cvxpy.Minimize(-w.T * er)\n",
" res = minimize(func, bm, bounds=list(zip(lbound - bm, ubound-bm)), constraints=cons, tol=1e-12)\n", " curr_risk_exposure = risk_constraints.T @ w\n",
" x2 = res['x'] + bm\n", " constraints = [w >= lbound,\n",
" elasped_time2 = timeit.timeit(\"minimize(func, np.zeros(len(er)), bounds=list(zip(lbound-bm, ubound-bm)), constraints=cons, tol=1e-12)\",\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", " number=number, globals=globals()) / number * 1000\n",
"\n", "\n",
" np.testing.assert_array_almost_equal(x1, x2, 4)\n", " u1 = -x1 @ er\n",
" else:\n", " x2 = np.array(w.value).flatten()\n",
" elasped_time2 = np.nan\n", " u2 = -x2 @ er\n",
" \n",
" np.testing.assert_array_almost_equal(u1, u2, 4)\n",
"\n", "\n",
" df.loc['alphamind', u_name] = elasped_time1\n", " df.loc['alphamind', u_name] = elasped_time1\n",
" df.loc['scipy', u_name] = elasped_time2\n", " df.loc['cvxpy', u_name] = elasped_time2\n",
" alpha_logger.info(f\"{u_name} is finished\")" " alpha_logger.info(f\"{u_name} is finished\")"
] ]
}, },
...@@ -681,34 +748,37 @@ ...@@ -681,34 +748,37 @@
" <th>hs300</th>\n", " <th>hs300</th>\n",
" <th>zz500</th>\n", " <th>zz500</th>\n",
" <th>zz800</th>\n", " <th>zz800</th>\n",
" <th>zz1000</th>\n",
" <th>ashare_ex</th>\n", " <th>ashare_ex</th>\n",
" </tr>\n", " </tr>\n",
" </thead>\n", " </thead>\n",
" <tbody>\n", " <tbody>\n",
" <tr>\n", " <tr>\n",
" <th>alphamind</th>\n", " <th>cvxpy</th>\n",
" <td>6.85</td>\n", " <td>23.83</td>\n",
" <td>16.36</td>\n", " <td>360.10</td>\n",
" <td>31.63</td>\n", " <td>1,261.50</td>\n",
" <td>48.64</td>\n", " <td>9,555.63</td>\n",
" <td>581.78</td>\n", " <td>6,260.97</td>\n",
" <td>212,776.88</td>\n",
" </tr>\n", " </tr>\n",
" <tr>\n", " <tr>\n",
" <th>scipy</th>\n", " <th>alphamind</th>\n",
" <td>15.86</td>\n", " <td>22.55</td>\n",
" <td>1,363.28</td>\n", " <td>32.70</td>\n",
" <td>27,494.13</td>\n", " <td>60.94</td>\n",
" <td>110,102.60</td>\n", " <td>59.65</td>\n",
" <td>NaN</td>\n", " <td>116.27</td>\n",
" <td>824.79</td>\n",
" </tr>\n", " </tr>\n",
" </tbody>\n", " </tbody>\n",
"</table>\n", "</table>\n",
"</div>" "</div>"
], ],
"text/plain": [ "text/plain": [
" sh50 hs300 zz500 zz800 ashare_ex\n", " sh50 hs300 zz500 zz800 zz1000 ashare_ex\n",
"alphamind 6.85 16.36 31.63 48.64 581.78\n", "cvxpy 23.83 360.10 1,261.50 9,555.63 6,260.97 212,776.88\n",
"scipy 15.86 1,363.28 27,494.13 110,102.60 NaN" "alphamind 22.55 32.70 60.94 59.65 116.27 824.79"
] ]
}, },
"execution_count": 12, "execution_count": 12,
...@@ -723,9 +793,7 @@ ...@@ -723,9 +793,7 @@
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": null,
"metadata": { "metadata": {},
"collapsed": true
},
"outputs": [], "outputs": [],
"source": [] "source": []
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment