Unverified Commit b19c2bb0 authored by Dr.李's avatar Dr.李 Committed by GitHub

Delete 2017-10-18_new_strategy.ipynb

parent 51841085
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"%matplotlib inline\n",
"import numpy as np\n",
"import pandas as pd\n",
"from matplotlib import pyplot as plt\n",
"from alphamind.api import *\n",
"from PyFin.api import *\n",
"from PyFin.Math.Accumulators import MovingMaxDrawdown\n",
"plt.style.use('fivethirtyeight')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 0. Parameter Settings\n",
"---------------------"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"engine = SqlEngine('postgres+psycopg2://postgres:A12345678!@10.63.6.220/alpha')\n",
"universe = Universe('custom', ['zz500'])\n",
"benchmark_code = 905\n",
"neutralize_risk = ['SIZE'] + industry_styles\n",
"constraint_risk = ['SIZE'] + industry_styles\n",
"start_date = '2015-01-01'\n",
"end_date = '2017-10-17'\n",
"industry_lower = 0.75\n",
"industry_upper = 1.25\n",
"\n",
"freq = '1d'\n",
"horizon = map_freq(freq)\n",
"dates = makeSchedule(start_date, end_date, tenor=freq, calendar='china.sse', dateGenerationRule=DateGeneration.Backward)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1. Current Production Strategy\n",
"-----------------------\n",
"\n",
"* **Factor Group #1**\n",
" * RVOL: 0.05\n",
" * EPS: 0.3\n",
" * DROEAfterNonRecurring: 0.35\n",
" * DivP: 0.075\n",
" * CFinc1: 0.15\n",
" * BDTO: 0.05\n",
" \n",
" \n",
"* **Factor Group #2**\n",
" * VAL: 0.034129344\n",
" * RVOL: 0.015881607\n",
" * ROEDiluted: 0.048765746\n",
" * GREV: 0.042747382\n",
" * EPS: -0.015900173\n",
" * CHV: 0.019044573\n",
" * CFinc1: -0.001792638\n",
" * BDTO: 0.014277867"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"factor_group1 = ['RVOL', 'EPS', 'DROEAfterNonRecurring', 'DivP', 'CFinc1', 'BDTO']\n",
"factor_weight1 = [0.05, 0.3, 0.35, 0.075, 0.15, 0.05]\n",
"\n",
"factor_group2 = ['VAL', 'RVOL', 'ROEDiluted', 'GREV', 'EPS', 'CHV', 'CFinc1', 'BDTO']\n",
"factor_weight2 = [0.034129344, 0.015881607, 0.048765746, 0.042747382, -0.015900173, 0.019044573, -0.001792638, 0.014277867]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"factors = list(set(factor_group1 + factor_group2))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%%time\n",
"all_data = engine.fetch_data_range(universe, factors, dates=dates, benchmark=905)\n",
"factor_all_data = all_data['factor']\n",
"factor_groups = factor_all_data.groupby('trade_date')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"rets = []\n",
"turn_overs = []\n",
"turn_over_threshold = 0.70\n",
"executor = ThresholdExecutor(turn_over_threshold=turn_over_threshold)\n",
"execution_pipeline = ExecutionPipeline(executors=[executor])\n",
"leverags = []\n",
"\n",
"for i, value in enumerate(factor_groups):\n",
" date = value[0]\n",
" data = value[1]\n",
" codes = data.code.tolist()\n",
" ref_date = date.strftime('%Y-%m-%d')\n",
" total_data = data.dropna()\n",
" dx_return = None\n",
" risk_exp = total_data[neutralize_risk].values.astype(float)\n",
" industry = total_data.industry.values\n",
" benchmark_w = total_data.weight.values\n",
" \n",
" constraint_exp = total_data[constraint_risk].values\n",
" risk_exp_expand = np.concatenate((constraint_exp, np.ones((len(risk_exp), 1))), axis=1).astype(float)\n",
" risk_names = constraint_risk + ['total']\n",
" risk_target = risk_exp_expand.T @ benchmark_w\n",
" lbound = np.zeros(len(total_data))\n",
" ubound = 0.01 + benchmark_w\n",
"\n",
" constraint = Constraints(risk_exp_expand, risk_names)\n",
" for i, name in enumerate(risk_names):\n",
" if name == 'total' or name == 'SIZE':\n",
" constraint.set_constraints(name, lower_bound=risk_target[i], upper_bound=risk_target[i])\n",
" else:\n",
" constraint.set_constraints(name, lower_bound=risk_target[i]*industry_lower, upper_bound=risk_target[i]*industry_upper)\n",
" \n",
" er1 = factor_processing(total_data[factor_group1].values,\n",
" pre_process=[winsorize_normal, standardize],\n",
" risk_factors=risk_exp,\n",
" post_process=[winsorize_normal, standardize]) @ factor_weight1\n",
" \n",
" er2 = factor_processing(total_data[factor_group2].values,\n",
" pre_process=[winsorize_normal, standardize],\n",
" risk_factors=risk_exp,\n",
" post_process=[winsorize_normal, standardize]) @ factor_weight2\n",
" \n",
" er = (er1 / er1.std() + er2 / er2.std())\n",
" \n",
" target_pos, _ = er_portfolio_analysis(er,\n",
" industry,\n",
" dx_return,\n",
" constraint,\n",
" False,\n",
" benchmark_w)\n",
" target_pos['code'] = total_data['code'].values\n",
" \n",
" turn_over, executed_pos = execution_pipeline.execute(target_pos=target_pos)\n",
" \n",
" executed_codes = executed_pos.code.tolist()\n",
" dx_retuns = engine.fetch_dx_return(advanceDateByCalendar('china.sse', date, '1b').strftime('%Y-%m-%d'),\n",
" executed_codes,\n",
" horizon=horizon)\n",
" \n",
" result = pd.merge(executed_pos, total_data, on=['code'], how='inner')\n",
" result = pd.merge(result, dx_retuns, on=['code'])\n",
" leverage = result.weight_x.abs().sum()\n",
" \n",
" ret = (result.weight_x - result.weight_y).values @ result.dx.values\n",
" rets.append(ret)\n",
" leverags.append(executed_pos.weight.abs().sum())\n",
" turn_overs.append(turn_over)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"ret_df1 = pd.DataFrame({'returns': rets, 'turn_over': turn_overs}, index=dates)\n",
"ret_df1.loc[advanceDateByCalendar('china.sse', dates[-1], freq)] = 0.\n",
"ret_df1 = ret_df1.shift(1)\n",
"ret_df1.iloc[0] = 0.\n",
"ret_df1['tc_cost'] = ret_df1.turn_over * 0.002"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"ret_df1[['returns', 'tc_cost']].cumsum().plot(figsize=(12, 6),\n",
" title='Threshold tc rebalanced: Monitored freq {0}, {1} tc'.format(freq,\n",
" turn_over_threshold),\n",
" secondary_y='tc_cost')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"ret_atfer_tc = ret_df1.returns - ret_df1.tc_cost\n",
"mmd = MovingMaxDrawdown(window=len(ret_atfer_tc))\n",
"\n",
"for ret in ret_atfer_tc:\n",
" mmd.push({'ret': ret})\n",
"\n",
"print(\"total return: \", ret_atfer_tc.mean() * 252 * 100)\n",
"print(\"sharp: \", ret_atfer_tc.mean() / ret_atfer_tc.std() * np.sqrt(252))\n",
"print(\"mmd: \", -mmd.result()[0]*100)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2. Current Production Strategy with Target Turn Over\n",
"--------------------------------------------"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"rets = []\n",
"turn_overs = []\n",
"turn_over_target_base = 0.04\n",
"executor = NaiveExecutor()\n",
"execution_pipeline = ExecutionPipeline(executors=[executor])\n",
"leverags = []\n",
"previous_pos = pd.DataFrame()\n",
"\n",
"for i, value in enumerate(factor_groups):\n",
" date = value[0]\n",
" data = value[1]\n",
" codes = data.code.tolist()\n",
" ref_date = date.strftime('%Y-%m-%d')\n",
" total_data = data.dropna()\n",
" dx_return = None\n",
" risk_exp = total_data[neutralize_risk].values.astype(float)\n",
" industry = total_data.industry.values\n",
" benchmark_w = total_data.weight.values\n",
" \n",
" constraint_exp = total_data[constraint_risk].values\n",
" risk_exp_expand = np.concatenate((constraint_exp, np.ones((len(risk_exp), 1))), axis=1).astype(float)\n",
" risk_names = constraint_risk + ['total']\n",
" risk_target = risk_exp_expand.T @ benchmark_w\n",
" lbound = np.zeros(len(total_data))\n",
" ubound = 0.01 + benchmark_w\n",
"\n",
" constraint = Constraints(risk_exp_expand, risk_names)\n",
" for i, name in enumerate(risk_names):\n",
" if name == 'total' or name == 'SIZE':\n",
" constraint.set_constraints(name, lower_bound=risk_target[i], upper_bound=risk_target[i])\n",
" else:\n",
" constraint.set_constraints(name, lower_bound=risk_target[i]*industry_lower, upper_bound=risk_target[i]*industry_upper)\n",
" \n",
" er1 = factor_processing(total_data[factor_group1].values,\n",
" pre_process=[winsorize_normal, standardize],\n",
" risk_factors=risk_exp,\n",
" post_process=[winsorize_normal, standardize]) @ factor_weight1\n",
" \n",
" er2 = factor_processing(total_data[factor_group2].values,\n",
" pre_process=[winsorize_normal, standardize],\n",
" risk_factors=risk_exp,\n",
" post_process=[winsorize_normal, standardize]) @ factor_weight2\n",
" \n",
" er = (er1 / er1.std() + er2 / er2.std())\n",
" \n",
" codes = total_data['code'].values\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",
" \n",
" current_position = remained_pos.weight.values\n",
" \n",
" try:\n",
" target_pos, _ = er_portfolio_analysis(er,\n",
" industry,\n",
" dx_return,\n",
" constraint,\n",
" False,\n",
" benchmark_w,\n",
" current_position=current_position,\n",
" turn_over_target=turn_over_target)\n",
" except ValueError:\n",
" print('{0} full rebalance'.format(date))\n",
" target_pos, _ = er_portfolio_analysis(er,\n",
" industry,\n",
" dx_return,\n",
" constraint,\n",
" False,\n",
" benchmark_w)\n",
" \n",
" target_pos['code'] = codes\n",
" \n",
" turn_over, executed_pos = execution_pipeline.execute(target_pos=target_pos)\n",
" \n",
" executed_codes = executed_pos.code.tolist()\n",
" dx_retuns = engine.fetch_dx_return(advanceDateByCalendar('china.sse', date, '1b').strftime('%Y-%m-%d'),\n",
" executed_codes,\n",
" horizon=horizon)\n",
" \n",
" result = pd.merge(executed_pos, total_data, on=['code'], how='inner')\n",
" result = pd.merge(result, dx_retuns, on=['code'])\n",
" \n",
" ret = (result.weight_x - result.weight_y ).values @ result.dx.values\n",
" rets.append(ret)\n",
" turn_overs.append(turn_over)\n",
" previous_pos = executed_pos"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"ret_df2 = pd.DataFrame({'returns': rets, 'turn_over': turn_overs}, index=dates)\n",
"ret_df2.loc[advanceDateByCalendar('china.sse', dates[-1], freq)] = 0.\n",
"ret_df2 = ret_df2.shift(1)\n",
"ret_df2.iloc[0] = 0.\n",
"ret_df2['tc_cost'] = ret_df2.turn_over * 0.002"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"ret_df2[['returns', 'tc_cost']].cumsum().plot(figsize=(12, 6),\n",
" title='Target turn over rebalanced: Rebalance freq {0}, {1} turnover_target'.format(freq, turn_over_target_base),\n",
" secondary_y='tc_cost')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"ret_atfer_tc = ret_df2.returns - ret_df2.tc_cost\n",
"mmd = MovingMaxDrawdown(window=len(ret_atfer_tc))\n",
"\n",
"for ret in ret_atfer_tc:\n",
" mmd.push({'ret': ret})\n",
"\n",
"print(\"total return: \", ret_atfer_tc.mean() * 252 * 100)\n",
"print(\"sharp: \", ret_atfer_tc.mean() / ret_atfer_tc.std() * np.sqrt(252))\n",
"print(\"mmd: \", -mmd.result()[0]*100)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 3. Candidate Strategy\n",
"---------------------\n",
"\n",
"* **Factor Group #1**\n",
" * RVOL: 0.05\n",
" * EPS: 0.3\n",
" * DROEAfterNonRecurring: 0.35\n",
" * DivP: 0.075\n",
" * CFinc1: 0.15\n",
" * BDTO: 0.05\n",
" \n",
" \n",
"* **Factor Group #2**\n",
" * VAL: 0.034129344\n",
" * IVR: 0.015881607\n",
" * ROEDiluted: 0.048765746\n",
" * GREV: 0.042747382\n",
" * EPS: -0.015900173\n",
" * CHV: 0.019044573\n",
" * CFinc1: -0.001792638\n",
" * BDTO: 0.014277867\n",
"\n",
"\n",
"* **Factor Group #3**\n",
" * con_pe_rolling: -0.6\n",
" * con_pb_rolling: -0.6\n",
" * con_eps: 0.6\n",
" * con_target_price: 1.2"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"factor_group1 = ['RVOL', 'EPS', 'DROEAfterNonRecurring', 'DivP', 'CFinc1', 'BDTO']\n",
"factor_weight1 = [0.05, 0.3, 0.35, 0.075, 0.15, 0.05]\n",
"group_weight1 = 1.\n",
"\n",
"factor_group2 = ['VAL', 'IVR', 'ROEDiluted', 'GREV', 'EPS', 'CHV', 'CFinc1', 'BDTO']\n",
"factor_weight2 = [0.034129344, 0.02, 0.048765746, 0.042747382, -0.015900173, 0.019044573, -0.001792638, 0.014277867]\n",
"group_weight2 = 1.\n",
"\n",
"factor_group3 = ['cs_pe', 'cs_pb', 'cs_eps']\n",
"factor_weight3 = [-0.6, -0.6, 0.6]\n",
"group_weight3 = 0.25"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"factors = {'RVOL': LAST('RVOL'),\n",
" 'EPS': LAST('EPS'),\n",
" 'DROEAfterNonRecurring': LAST('DROEAfterNonRecurring'),\n",
" 'DivP': LAST('DivP'),\n",
" 'CFinc1': LAST('CFinc1'),\n",
" 'BDTO': LAST('BDTO'),\n",
" 'VAL': LAST('VAL'),\n",
" 'ROEDiluted': LAST('ROEDiluted'),\n",
" 'GREV': LAST('GREV'),\n",
" 'CHV': LAST('CHV'),\n",
" 'cs_pe': LAST('con_pe_rolling'),\n",
" 'cs_pb': LAST('con_pb_rolling'),\n",
" 'cs_eps': LAST('con_eps_rolling'),\n",
" 'IVR': LAST('IVR')}"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%%time\n",
"all_data = engine.fetch_data_range(universe, factors, dates=dates, benchmark=905)\n",
"factor_all_data = all_data['factor']\n",
"factor_groups = factor_all_data.groupby('trade_date')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"rets = []\n",
"turn_overs = []\n",
"turn_over_threshold = 0.70\n",
"executor = ThresholdExecutor(turn_over_threshold=turn_over_threshold)\n",
"execution_pipeline = ExecutionPipeline(executors=[executor])\n",
"leverags = []\n",
"\n",
"for i, value in enumerate(factor_groups):\n",
" date = value[0]\n",
" data = value[1]\n",
" codes = data.code.tolist()\n",
" ref_date = date.strftime('%Y-%m-%d')\n",
" total_data = data.dropna()\n",
" dx_return = None\n",
" risk_exp = total_data[neutralize_risk].values.astype(float)\n",
" industry = total_data.industry.values\n",
" benchmark_w = total_data.weight.values\n",
" \n",
" constraint_exp = total_data[constraint_risk].values\n",
" risk_exp_expand = np.concatenate((constraint_exp, np.ones((len(risk_exp), 1))), axis=1).astype(float)\n",
" risk_names = constraint_risk + ['total']\n",
" risk_target = risk_exp_expand.T @ benchmark_w\n",
" lbound = np.zeros(len(total_data))\n",
" ubound = 0.01 + benchmark_w\n",
"\n",
" constraint = Constraints(risk_exp_expand, risk_names)\n",
" for i, name in enumerate(risk_names):\n",
" if name == 'total' or name == 'SIZE':\n",
" constraint.set_constraints(name, lower_bound=risk_target[i], upper_bound=risk_target[i])\n",
" else:\n",
" constraint.set_constraints(name, lower_bound=risk_target[i]*industry_lower, upper_bound=risk_target[i]*industry_upper)\n",
" \n",
" er1 = factor_processing(total_data[factor_group1].values,\n",
" pre_process=[winsorize_normal, standardize],\n",
" risk_factors=risk_exp,\n",
" post_process=[winsorize_normal, standardize]) @ factor_weight1\n",
" \n",
" er2 = factor_processing(total_data[factor_group2].values,\n",
" pre_process=[winsorize_normal, standardize],\n",
" risk_factors=risk_exp,\n",
" post_process=[winsorize_normal, standardize]) @ factor_weight2\n",
" \n",
" er3 = factor_processing((total_data[factor_group3].values @ factor_weight3).reshape((-1,1)),\n",
" pre_process=[winsorize_normal, standardize],\n",
" risk_factors=risk_exp,\n",
" post_process=[winsorize_normal, standardize]).flatten()\n",
" \n",
" er = (group_weight1* er1 / er1.std() + \n",
" group_weight2 * er2 / er2.std() + \n",
" group_weight3 * er3 / er3.std())\n",
" \n",
" target_pos, _ = er_portfolio_analysis(er,\n",
" industry,\n",
" dx_return,\n",
" constraint,\n",
" False,\n",
" benchmark_w)\n",
" target_pos['code'] = total_data['code'].values\n",
" \n",
" turn_over, executed_pos = execution_pipeline.execute(target_pos=target_pos)\n",
" \n",
" executed_codes = executed_pos.code.tolist()\n",
" dx_retuns = engine.fetch_dx_return(advanceDateByCalendar('china.sse', date, '1b').strftime('%Y-%m-%d'),\n",
" executed_codes,\n",
" horizon=horizon)\n",
" \n",
" result = pd.merge(executed_pos, total_data, on=['code'], how='inner')\n",
" result = pd.merge(result, dx_retuns, on=['code'])\n",
" \n",
" ret = (result.weight_x - result.weight_y).values @ result.dx.values\n",
" rets.append(ret)\n",
" leverags.append(executed_pos.weight.abs().sum())\n",
" turn_overs.append(turn_over)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"ret_df3 = pd.DataFrame({'returns': rets, 'turn_over': turn_overs}, index=dates)\n",
"ret_df3.loc[advanceDateByCalendar('china.sse', dates[-1], freq)] = 0.\n",
"ret_df3 = ret_df3.shift(1)\n",
"ret_df3.iloc[0] = 0.\n",
"ret_df3['tc_cost'] = ret_df3.turn_over * 0.002"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"ret_df3[['returns', 'tc_cost']].cumsum().plot(figsize=(12, 6),\n",
" title='Threshold tc rebalanced: Monitored freq {0}, {1} tc'.format(freq,\n",
" turn_over_threshold),\n",
" secondary_y='tc_cost')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"ret_atfer_tc = ret_df3.returns - ret_df3.tc_cost\n",
"\n",
"mmd = MovingMaxDrawdown(window=len(ret_atfer_tc))\n",
"\n",
"for ret in ret_atfer_tc:\n",
" mmd.push({'ret': ret})\n",
"\n",
"print(\"total return: \", ret_atfer_tc.mean() * 252 * 100)\n",
"print(\"sharp: \", ret_atfer_tc.mean() / ret_atfer_tc.std() * np.sqrt(252))\n",
"print(\"mmd: \", -mmd.result()[0]*100)"
]
},
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"## 4. Candidate Strategy with Target Turn Over\n",
"-----------------"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"rets = []\n",
"turn_overs = []\n",
"turn_over_target_base = 0.04\n",
"executor = NaiveExecutor()\n",
"execution_pipeline = ExecutionPipeline(executors=[executor])\n",
"leverags = []\n",
"previous_pos = pd.DataFrame()\n",
"\n",
"for i, value in enumerate(factor_groups):\n",
" date = value[0]\n",
" data = value[1]\n",
" codes = data.code.tolist()\n",
" ref_date = date.strftime('%Y-%m-%d')\n",
" total_data = data.dropna()\n",
" dx_return = None\n",
" risk_exp = total_data[neutralize_risk].values.astype(float)\n",
" industry = total_data.industry.values\n",
" benchmark_w = total_data.weight.values\n",
" \n",
" constraint_exp = total_data[constraint_risk].values\n",
" risk_exp_expand = np.concatenate((constraint_exp, np.ones((len(risk_exp), 1))), axis=1).astype(float)\n",
" risk_names = constraint_risk + ['total']\n",
" risk_target = risk_exp_expand.T @ benchmark_w\n",
" lbound = np.zeros(len(total_data))\n",
" ubound = 0.01 + benchmark_w\n",
"\n",
" constraint = Constraints(risk_exp_expand, risk_names)\n",
" for i, name in enumerate(risk_names):\n",
" if name == 'total' or name == 'SIZE':\n",
" constraint.set_constraints(name, lower_bound=risk_target[i], upper_bound=risk_target[i])\n",
" else:\n",
" constraint.set_constraints(name, lower_bound=risk_target[i]*industry_lower, upper_bound=risk_target[i]*industry_upper)\n",
" \n",
" er1 = factor_processing(total_data[factor_group1].values,\n",
" pre_process=[winsorize_normal, standardize],\n",
" risk_factors=risk_exp,\n",
" post_process=[winsorize_normal, standardize]) @ factor_weight1\n",
" \n",
" er2 = factor_processing(total_data[factor_group2].values,\n",
" pre_process=[winsorize_normal, standardize],\n",
" risk_factors=risk_exp,\n",
" post_process=[winsorize_normal, standardize]) @ factor_weight2\n",
" \n",
" er3 = factor_processing((total_data[factor_group3].values @ factor_weight3).reshape((-1,1)),\n",
" pre_process=[winsorize_normal, standardize],\n",
" risk_factors=risk_exp,\n",
" post_process=[winsorize_normal, standardize]).flatten()\n",
" \n",
" er = (group_weight1* er1 / er1.std() + \n",
" group_weight2 * er2 / er2.std() + \n",
" group_weight3 * er3 / er3.std())\n",
" \n",
" codes = total_data['code'].values\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",
" \n",
" current_position = remained_pos.weight.values\n",
" \n",
" try:\n",
" target_pos, _ = er_portfolio_analysis(er,\n",
" industry,\n",
" dx_return,\n",
" constraint,\n",
" False,\n",
" benchmark_w,\n",
" current_position=current_position,\n",
" turn_over_target=turn_over_target)\n",
" except ValueError:\n",
" print('{0} full rebalance'.format(date))\n",
" target_pos, _ = er_portfolio_analysis(er,\n",
" industry,\n",
" dx_return,\n",
" constraint,\n",
" False,\n",
" benchmark_w)\n",
" \n",
" target_pos['code'] = codes\n",
" \n",
" turn_over, executed_pos = execution_pipeline.execute(target_pos=target_pos)\n",
" \n",
" executed_codes = executed_pos.code.tolist()\n",
" dx_retuns = engine.fetch_dx_return(advanceDateByCalendar('china.sse', date, '1b').strftime('%Y-%m-%d'),\n",
" executed_codes,\n",
" horizon=horizon)\n",
" \n",
" result = pd.merge(executed_pos, total_data, on=['code'], how='inner')\n",
" result = pd.merge(result, dx_retuns, on=['code'])\n",
" ret = (result.weight_x - result.weight_y).values @ result.dx.values\n",
" rets.append(ret)\n",
" turn_overs.append(turn_over)\n",
" previous_pos = executed_pos"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"ret_df4 = pd.DataFrame({'returns': rets, 'turn_over': turn_overs}, index=dates)\n",
"ret_df4.loc[advanceDateByCalendar('china.sse', dates[-1], freq)] = 0.\n",
"ret_df4 = ret_df4.shift(1)\n",
"ret_df4.iloc[0] = 0.\n",
"ret_df4['tc_cost'] = ret_df4.turn_over * 0.002"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"ret_df4[['returns', 'tc_cost']].cumsum().plot(figsize=(12, 6),\n",
" title='Target turn over rebalanced: Rebalance freq {0}, {1} turnover_target'.format(freq, turn_over_target_base),\n",
" secondary_y='tc_cost')"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"ret_atfer_tc = ret_df4.returns - ret_df4.tc_cost\n",
"mmd = MovingMaxDrawdown(window=len(ret_atfer_tc))\n",
"\n",
"for ret in ret_atfer_tc:\n",
" mmd.push({'ret': ret})\n",
"\n",
"print(\"total return: \", ret_atfer_tc.mean() * 252 * 100)\n",
"print(\"sharp: \", ret_atfer_tc.mean() / ret_atfer_tc.std() * np.sqrt(252))\n",
"print(\"mmd: \", -mmd.result()[0]*100)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"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.3"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
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