Commit 7c867f41 authored by Dr.李's avatar Dr.李

update alpha mind utilities and examples

parent c6d7f90c
......@@ -90,7 +90,7 @@ def er_portfolio_analysis(er: np.ndarray,
cons_exp = constraints.risk_exp
return lbound, ubound, cons_exp, risk_lbound, risk_ubound
if benchmark is not None and method == 'risk_neutral':
if method == 'risk_neutral':
lbound, ubound, cons_exp, risk_lbound, risk_ubound = create_constraints(benchmark, **kwargs)
turn_over_target = kwargs.get('turn_over_target')
......
......@@ -7,12 +7,9 @@ Created on 2017-11-8
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
from alphamind.api import *
from PyFin.api import *
from PyFin.Math.Accumulators.StatefulAccumulators import MovingAverage
from PyFin.Math.Accumulators.StatefulAccumulators import MovingSharp
from PyFin.Math.Accumulators.StatefulAccumulators import MovingMaxDrawdown
from alphamind.api import *
from matplotlib import pyplot as plt
plt.style.use('ggplot')
......@@ -21,248 +18,220 @@ Back test parameter settings
"""
start_date = '2010-01-01'
end_date = '2018-01-29'
end_date = '2018-02-27'
frequency = '10b'
method = 'risk_neutral'
freq = '10b'
industry_lower = 1.
industry_upper = 1.
neutralize_risk = ['SIZE'] + industry_styles
constraint_risk = ['SIZE'] + industry_styles
size_risk_lower = 0
size_risk_upper = 0
turn_over_target_base = 0.30
neutralized_risk = industry_styles
industry_name = 'sw'
industry_level = 1
turn_over_target_base = 2.0
benchmark_total_lower = 0.8
benchmark_total_upper = 1.0
horizon = map_freq(frequency)
batch = 0
horizon = map_freq(freq)
weight_gap = 0.01
universe = Universe("custom", ['zz800'])
data_source = 'postgres+psycopg2://postgres:A12345678!@10.63.6.220/alpha'
benchmark_code = 905
offset = 1
executor = NaiveExecutor()
def factor_analysis(engine, factor_name, universe, benchmark_code, positive=True, neutralize_factors=None):
"""
Model phase: we need 1 constant linear model and one linear regression model
"""
alpha_name = [str(factor_name) + '_' + ('pos' if positive else 'neg')]
if neutralize_factors:
prev_factors = []
for i, f in enumerate(neutralize_factors):
pure_factor = LAST(f)
for j in range(i):
pure_factor = CSRes(pure_factor, prev_factors[j])
prev_factors.append(pure_factor)
simple_expression = LAST(factor_name)
for f in prev_factors:
simple_expression = CSRes(simple_expression, f)
ref_dates = makeSchedule(start_date, end_date, freq, 'china.sse')
engine = SqlEngine(data_source)
alpha_factors = {
'f01': LAST('ep_q'),
'f02': LAST('roe_q'),
'f03': LAST('market_confidence_25d'),
'f04': LAST('ILLIQUIDITY'),
'f05': LAST('cfinc1_q'),
'f06': LAST('CFO2EV'),
'f07': LAST('IVR'),
'f08': LAST('con_pe_rolling_order'),
'f09': LAST('con_pb_rolling_order'),
}
weights = dict(f01=1.,
f02=1.,
f03=0.25,
f04=0.25,
f05=0.25,
f06=0.25,
f07=0.25,
f08=-0.25,
f09=-0.25)
alpha_model = ConstLinearModel(features=alpha_factors, weights=weights)
def train_worker(ref_date):
data_meta = DataMeta(freq=freq,
universe=universe,
batch=batch,
neutralized_risk=neutralized_risk,
risk_model='short',
pre_process=[winsorize_normal, standardize],
post_process=[winsorize_normal, standardize, rank],
warm_start=0,
data_source=data_source)
return train_model(ref_date, alpha_model, data_meta)
def predict_worker(params):
data_meta = DataMeta(freq=freq,
universe=universe,
batch=batch,
neutralized_risk=neutralized_risk,
risk_model='short',
pre_process=[winsorize_normal, standardize],
post_process=[winsorize_normal, standardize, rank],
warm_start=0,
data_source=data_source)
ref_date, model = params
er = predict_by_model(ref_date, model, data_meta)
return er
predicts = [predict_worker((d.strftime('%Y-%m-%d'), alpha_model)) for d in ref_dates]
# rebalance
industry_names = industry_list(industry_name, industry_level)
constraint_risk = ['SIZE', 'SIZENL', 'BETA'] + industry_names
total_risk_names = constraint_risk + ['benchmark', 'total']
b_type = []
l_val = []
u_val = []
previous_pos = pd.DataFrame()
rets = []
turn_overs = []
leverags = []
for name in total_risk_names:
if name == 'benchmark':
b_type.append(BoundaryType.RELATIVE)
l_val.append(benchmark_total_lower)
u_val.append(benchmark_total_upper)
elif name in {'SIZE', 'SIZENL', 'BETA'}:
b_type.append(BoundaryType.ABSOLUTE)
l_val.append(0.0)
u_val.append(0.0)
else:
b_type.append(BoundaryType.RELATIVE)
l_val.append(industry_lower)
u_val.append(industry_upper)
bounds = create_box_bounds(total_risk_names, b_type, l_val, u_val)
industry_total = engine.fetch_industry_matrix_range(universe, dates=ref_dates, category=industry_name,
level=industry_level)
benchmark_total = engine.fetch_benchmark_range(dates=ref_dates, benchmark=benchmark_code)
risk_total = engine.fetch_risk_model_range(universe, dates=ref_dates)[1]
for i, ref_date in enumerate(ref_dates):
ref_date = ref_date.strftime('%Y-%m-%d')
industry_matrix = industry_total[industry_total.trade_date == ref_date]
benchmark_w = benchmark_total[benchmark_total.trade_date == ref_date]
risk_matrix = risk_total[risk_total.trade_date == ref_date]
res = pd.merge(industry_matrix, benchmark_w, on=['code'], how='left').fillna(0.)
res = pd.merge(res, risk_matrix, on=['code'])
res = res.dropna()
codes = res.code.values.tolist()
benchmark_w = res.weight.values
is_in_benchmark = (benchmark_w > 0.).astype(float).reshape((-1, 1))
total_risk_exp = np.concatenate([res[constraint_risk].values.astype(float),
is_in_benchmark,
np.ones_like(is_in_benchmark)],
axis=1)
total_risk_exp = pd.DataFrame(total_risk_exp, columns=total_risk_names)
constraints = LinearConstraints(bounds, total_risk_exp, benchmark_w)
lbound = np.maximum(0., benchmark_w - weight_gap) # np.zeros(len(total_data))
ubound = weight_gap + benchmark_w
if previous_pos.empty:
current_position = None
turn_over_target = None
else:
simple_expression = LAST(factor_name)
if not positive:
simple_expression = -simple_expression
const_features = {alpha_name[0]: simple_expression}
const_weights = np.array([1.])
const_model = ConstLinearModel(features=alpha_name,
weights=const_weights)
ref_dates = makeSchedule(start_date, end_date, frequency, 'china.sse')
const_model_factor_data = engine.fetch_data_range(universe,
const_features,
dates=ref_dates,
benchmark=benchmark_code)['factor'].dropna()
horizon = map_freq(frequency)
rets = []
turn_overs = []
leverags = []
previous_pos = pd.DataFrame()
index_dates = []
factor_groups = const_model_factor_data.groupby('trade_date')
for i, value in enumerate(factor_groups):
date = value[0]
data = value[1]
index_dates.append(date)
total_data = data.fillna(data[alpha_name].median())
alpha_logger.info('{0}: {1}'.format(date, len(total_data)))
risk_exp = total_data[neutralize_risk].values.astype(float)
industry = total_data.industry_code.values
benchmark_w = total_data.weight.values
constraint_exp = total_data[constraint_risk].values
risk_exp_expand = np.concatenate((constraint_exp, np.ones((len(risk_exp), 1))), axis=1).astype(float)
risk_names = constraint_risk + ['total']
risk_target = risk_exp_expand.T @ benchmark_w
lbound = np.maximum(0., benchmark_w - 0.02) # np.zeros(len(total_data))
ubound = 0.02 + benchmark_w
is_in_benchmark = (benchmark_w > 0.).astype(float)
risk_exp_expand = np.concatenate((risk_exp_expand, is_in_benchmark.reshape((-1, 1))), axis=1).astype(float)
risk_names.append('benchmark_total')
constraint = Constraints(risk_exp_expand, risk_names)
for j, name in enumerate(risk_names):
if name == 'total':
constraint.set_constraints(name,
lower_bound=risk_target[j],
upper_bound=risk_target[j])
elif name == 'SIZE':
base_target = abs(risk_target[j])
constraint.set_constraints(name,
lower_bound=risk_target[j] + base_target * size_risk_lower,
upper_bound=risk_target[j] + base_target * size_risk_upper)
elif name == 'benchmark_total':
base_target = benchmark_w.sum()
constraint.set_constraints(name,
lower_bound=benchmark_total_lower * base_target,
upper_bound=benchmark_total_upper * base_target)
else:
constraint.set_constraints(name,
lower_bound=risk_target[j] * industry_lower,
upper_bound=risk_target[j] * industry_upper)
factor_values = factor_processing(total_data[alpha_name].values,
pre_process=[winsorize_normal, standardize],
risk_factors=risk_exp,
post_process=[winsorize_normal, standardize])
# const linear model
er = const_model.predict(factor_values)
codes = total_data['code'].values
if previous_pos.empty:
current_position = None
turn_over_target = None
else:
previous_pos.set_index('code', inplace=True)
remained_pos = previous_pos.loc[codes]
remained_pos.fillna(0., inplace=True)
turn_over_target = turn_over_target_base
current_position = remained_pos.weight.values
try:
target_pos, _ = er_portfolio_analysis(er,
industry,
None,
constraint,
False,
benchmark_w,
method=method,
turn_over_target=turn_over_target,
current_position=current_position,
lbound=lbound,
ubound=ubound)
except ValueError:
alpha_logger.info('{0} full re-balance'.format(date))
target_pos, _ = er_portfolio_analysis(er,
industry,
None,
constraint,
False,
benchmark_w,
method=method,
lbound=lbound,
ubound=ubound)
target_pos['code'] = total_data['code'].values
turn_over, executed_pos = executor.execute(target_pos=target_pos)
executed_codes = executed_pos.code.tolist()
dx_returns = engine.fetch_dx_return(date, executed_codes, horizon=horizon, offset=1)
result = pd.merge(executed_pos, total_data[['code', 'weight']], on=['code'], how='inner')
result = pd.merge(result, dx_returns, on=['code'])
leverage = result.weight_x.abs().sum()
ret = result.weight_x.values @ (np.exp(result.dx.values) - 1.)
rets.append(np.log(1. + ret))
executor.set_current(executed_pos)
turn_overs.append(turn_over)
leverags.append(leverage)
previous_pos = executed_pos
alpha_logger.info('{0} is finished'.format(date))
ret_df = pd.DataFrame({'returns': rets, 'turn_over': turn_overs, 'leverage': leverags}, index=index_dates)
# index return
index_return = engine.fetch_dx_return_index_range(benchmark_code, start_date, end_date, horizon=horizon,
offset=1).set_index('trade_date')
ret_df['index'] = index_return['dx']
ret_df.loc[advanceDateByCalendar('china.sse', ref_dates[-1], frequency)] = 0.
ret_df = ret_df.shift(1)
ret_df.iloc[0] = 0.
ret_df['tc_cost'] = ret_df.turn_over * 0.002
ret_df['returns'] = ret_df['returns'] - ret_df['index'] * ret_df['leverage']
return alpha_name[0], ret_df
def worker_func_positive(factor_name):
from alphamind.api import SqlEngine, Universe
neutralize_factors = ['roe_q', 'ep_q']
engine = SqlEngine()
benchmark_code = 905
universe_name = ['zz500']
universe = Universe('custom', universe_name)
return factor_analysis(engine, factor_name, universe, benchmark_code, positive=True, neutralize_factors=neutralize_factors)
def worker_func_negative(factor_name):
from alphamind.api import SqlEngine, Universe
neutralize_factors = ['roe_q', 'ep_q']
engine = SqlEngine()
benchmark_code = 905
universe_name = ['zz500']
universe = Universe('custom', universe_name)
return factor_analysis(engine, factor_name, universe, benchmark_code, positive=False, neutralize_factors=neutralize_factors)
if __name__ == '__main__':
from dask.distributed import Client
client = Client('192.168.0.102:8786')
engine = SqlEngine()
df = engine.fetch_factor_coverage()
df = df[df.universe == 'zz800'].groupby('factor').mean()
df = df[df.coverage >= 0.98]
tasks = client.map(worker_func_positive, df.index.tolist())
res1 = client.gather(tasks)
tasks = client.map(worker_func_negative, df.index.tolist())
res2 = client.gather(tasks)
factor_df = pd.DataFrame()
for f_name, df in res1:
factor_df[f_name] = df['returns']
for f_name, df in res2:
factor_df[f_name] = df['returns']
# factor_name = LAST('EBITDA') / LAST('ev')
# f_name, ret_df = worker_func_positive(factor_name)
#
# ret_df[['returns', 'tc_cost']].cumsum().plot(figsize=(12, 6),
# title='Fixed frequency rebalanced: {0} for {1} with benchmark {2}'.format(
# frequency, factor_name, 905),
# secondary_y='tc_cost')
# plt.show()
previous_pos.set_index('code', inplace=True)
remained_pos = previous_pos.loc[codes]
remained_pos.fillna(0., inplace=True)
turn_over_target = turn_over_target_base
current_position = remained_pos.weight.values
er = predicts[i].loc[codes].values
try:
alpha_logger.info('{0} partial re-balance: {1}'.format(ref_date, len(er)))
target_pos, _ = er_portfolio_analysis(er,
industry_matrix.industry_name.values,
None,
constraints,
False,
benchmark_w,
method='risk_neutral',
turn_over_target=turn_over_target,
current_position=current_position,
lbound=lbound,
ubound=ubound)
except ValueError:
alpha_logger.info('{0} full re-balance: {1}'.format(ref_date, len(er)))
target_pos, _ = er_portfolio_analysis(er,
industry_matrix.industry_name.values,
None,
constraints,
False,
benchmark_w,
method='risk_neutral',
lbound=lbound,
ubound=ubound)
target_pos['code'] = codes
turn_over, executed_pos = executor.execute(target_pos=target_pos)
executed_codes = executed_pos.code.tolist()
dx_returns = engine.fetch_dx_return(ref_date, executed_codes, horizon=horizon, offset=offset)
result = pd.merge(executed_pos, dx_returns, on=['code'])
leverage = result.weight.abs().sum()
ret = result.weight.values @ (np.exp(result.dx.values) - 1.)
rets.append(np.log(1. + ret))
executor.set_current(executed_pos)
turn_overs.append(turn_over)
leverags.append(leverage)
previous_pos = executed_pos
alpha_logger.info('{0} is finished'.format(ref_date))
ret_df = pd.DataFrame({'returns': rets, 'turn_over': turn_overs, 'leverage': leverags}, index=ref_dates)
# index return
index_return = engine.fetch_dx_return_index_range(benchmark_code, start_date, end_date, horizon=horizon,
offset=offset).set_index('trade_date')
ret_df['index'] = index_return['dx']
ret_df.loc[advanceDateByCalendar('china.sse', ref_dates[-1], freq)] = 0.
ret_df = ret_df.shift(1)
ret_df.iloc[0] = 0.
ret_df['tc_cost'] = ret_df.turn_over * 0.002
ret_df['returns'] = ret_df['returns'] - ret_df['index'] * ret_df['leverage']
ret_df[['returns', 'tc_cost']].cumsum().plot(figsize=(12, 6),
title='Fixed freq rebalanced: {0} with benchmark {1}'.format(freq, 905),
secondary_y='tc_cost')
ret_df[['returns', 'tc_cost']][-30:].cumsum().plot(figsize=(12, 6),
title='Fixed freq rebalanced: {0} with benchmark {1}'.format(freq,
905),
secondary_y='tc_cost')
plt.show()
......@@ -94,7 +94,7 @@ def factor_analysis(f_name):
if __name__ == '__main__':
from dask.distributed import Client
client = Client('10.63.6.176:8786')
client = Client('10.63.6.13:8786')
engine = SqlEngine()
df = engine.fetch_factor_coverage()
......
......@@ -105,21 +105,28 @@ class LinearConstraints(object):
def __init__(self,
bounds: Dict[str, BoxBoundary],
cons_mat: pd.DataFrame,
backbone: np.ndarray):
backbone: np.ndarray=None):
pyFinAssert(len(bounds) == cons_mat.shape[1], "Number of bounds should be same as number of col of cons_mat")
pyFinAssert(cons_mat.shape[0] == len(backbone),
"length of back bond should be same as number of rows of cons_mat")
self.names = list(bounds.keys())
self.bounds = bounds
self.cons_mat = cons_mat
self.backbone = backbone
pyFinAssert(cons_mat.shape[0] == len(backbone) if backbone is not None else True,
"length of back bond should be same as number of rows of cons_mat")
def risk_targets(self) -> Tuple[np.ndarray, np.ndarray]:
lower_bounds = []
upper_bounds = []
if self.backbone is None:
backbone = np.zeros(len(self.cons_mat))
else:
backbone = self.backbone
for name in self.names:
center = self.backbone @ self.cons_mat[name].values
center = backbone @ self.cons_mat[name].values
l, u = self.bounds[name].bounds(center)
lower_bounds.append(l)
upper_bounds.append(u)
......
......@@ -32,7 +32,7 @@ class TestRank(unittest.TestCase):
data_rank = rank(self.x, groups=self.groups)
df = pd.DataFrame(self.x, index=self.groups)
expected_rank = df.groupby(level=0).apply(lambda x: x.values.argsort().argsort())
expected_rank = df.groupby(level=0).apply(lambda x: x.values.argsort(axis=0).argsort(axis=0))
print(expected_rank)
......@@ -229,7 +229,7 @@
"name": "stdout",
"output_type": "stream",
"text": [
"Wall time: 8.86 s\n"
"Wall time: 21.8 s\n"
]
}
],
......@@ -246,9 +246,17 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 6,
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Wall time: 1h 1min 15s\n"
]
}
],
"source": [
"%%time\n",
"\n",
......@@ -276,7 +284,7 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 7,
"metadata": {},
"outputs": [],
"source": [
......@@ -289,7 +297,7 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
......@@ -302,7 +310,7 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 9,
"metadata": {},
"outputs": [],
"source": [
......
......@@ -21,7 +21,7 @@
},
{
"cell_type": "code",
"execution_count": 28,
"execution_count": 47,
"metadata": {},
"outputs": [],
"source": [
......@@ -45,7 +45,7 @@
"horizon = map_freq(freq)\n",
"universe = Universe(\"custom\", ['zz800'])\n",
"data_source = 'postgres+psycopg2://postgres:A12345678!@10.63.6.220/alpha'\n",
"benchmark_code = 300\n",
"benchmark_code = 905\n",
"\n",
"executor = NaiveExecutor()\n",
"ref_dates = makeSchedule(start_date, end_date, freq, 'china.sse')\n",
......@@ -54,7 +54,7 @@
},
{
"cell_type": "code",
"execution_count": 29,
"execution_count": 48,
"metadata": {},
"outputs": [],
"source": [
......@@ -62,39 +62,16 @@
"Factor Model\n",
"\"\"\"\n",
"\n",
"alpha_factors = {\n",
" 'f01': LAST('ep_q'),\n",
" 'f02': LAST('roe_q'),\n",
" 'f03': LAST('market_confidence_75d'),\n",
" 'f04': LAST('DivP'),\n",
" 'f05': LAST('val_q'),\n",
" 'f06': LAST('con_np_rolling'),\n",
" 'f07': LAST('GREV'),\n",
" 'f08': LAST('con_pe_rolling_order'),\n",
" 'f09': LAST('con_pb_rolling_order')\n",
"}\n",
"\n",
"weights = dict(f01=1.,\n",
" f02=0.5,\n",
" f03=0.5,\n",
" f04=0.5,\n",
" f05=0.5,\n",
" f06=0.5,\n",
" f07=0.5,\n",
" f08=-0.5,\n",
" f09=-0.5)\n",
"\n",
"\n",
"# alpha_factors = {\n",
"# 'f01': LAST('ep_q'),\n",
"# 'f02': LAST('roe_q'),\n",
"# 'f03': LAST('market_confidence_25d'),\n",
"# 'f04': LAST('ILLIQUIDITY'),\n",
"# 'f05': LAST('cfinc1_q'),\n",
"# 'f06': LAST('CFO2EV'),\n",
"# 'f07': LAST('IVR'),\n",
"# 'f03': LAST('market_confidence_75d'),\n",
"# 'f04': LAST('DivP'),\n",
"# 'f05': LAST('val_q'),\n",
"# 'f06': LAST('con_np_rolling'),\n",
"# 'f07': LAST('GREV'),\n",
"# 'f08': LAST('con_pe_rolling_order'),\n",
"# 'f09': LAST('con_pb_rolling_order'),\n",
"# 'f09': LAST('con_pb_rolling_order')\n",
"# }\n",
"\n",
"# weights = dict(f01=1.,\n",
......@@ -107,6 +84,29 @@
"# f08=-0.5,\n",
"# f09=-0.5)\n",
"\n",
"\n",
"alpha_factors = {\n",
" 'f01': LAST('ep_q'),\n",
" 'f02': LAST('roe_q'),\n",
" 'f03': LAST('market_confidence_25d'),\n",
" 'f04': LAST('ILLIQUIDITY'),\n",
" 'f05': LAST('cfinc1_q'),\n",
" 'f06': LAST('CFO2EV'),\n",
" 'f07': LAST('IVR'),\n",
" 'f08': LAST('con_pe_rolling_order'),\n",
" 'f09': LAST('con_pb_rolling_order'),\n",
"}\n",
"\n",
"weights = dict(f01=1.,\n",
" f02=0.5,\n",
" f03=0.5,\n",
" f04=0.5,\n",
" f05=0.5,\n",
" f06=0.5,\n",
" f07=0.5,\n",
" f08=-0.5,\n",
" f09=-0.5)\n",
"\n",
"alpha_model = ConstLinearModel(features=alpha_factors, weights=weights)\n",
"\n",
"def predict_worker(params):\n",
......@@ -126,7 +126,7 @@
},
{
"cell_type": "code",
"execution_count": 30,
"execution_count": 49,
"metadata": {},
"outputs": [
{
......@@ -149,14 +149,14 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 50,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Wall time: 6.83 s\n"
"Wall time: 7.17 s\n"
]
}
],
......@@ -177,7 +177,7 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 51,
"metadata": {},
"outputs": [],
"source": [
......@@ -216,7 +216,7 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 52,
"metadata": {},
"outputs": [],
"source": [
......@@ -322,7 +322,7 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 53,
"metadata": {},
"outputs": [],
"source": [
......@@ -356,9 +356,26 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 54,
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"d:\\ProgramData\\Anaconda3\\lib\\site-packages\\ipykernel_launcher.py:39: 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-03-05 10:26:22,348 - ALPHA_MIND - INFO - 0.005 finished\n",
"2018-03-05 10:27:18,069 - ALPHA_MIND - INFO - 0.01 finished\n",
"2018-03-05 10:28:13,730 - ALPHA_MIND - INFO - 0.015 finished\n",
"2018-03-05 10:29:09,414 - ALPHA_MIND - INFO - 0.02 finished\n"
]
}
],
"source": [
"weight_gaps = [0.005, 0.010, 0.015, 0.020]\n",
"\n",
......@@ -372,18 +389,1330 @@
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 55,
"metadata": {},
"outputs": [],
"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>daily_return</th>\n",
" <th>cum_ret</th>\n",
" <th>sharp</th>\n",
" <th>drawdown</th>\n",
" <th>max_drawn</th>\n",
" <th>leverage</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>2010-01-04</th>\n",
" <td>0.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.00000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-01-18</th>\n",
" <td>-0.015930</td>\n",
" <td>-0.015930</td>\n",
" <td>0.000000</td>\n",
" <td>-0.015930</td>\n",
" <td>-0.015930</td>\n",
" <td>1.00000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-02-01</th>\n",
" <td>-0.001602</td>\n",
" <td>-0.017532</td>\n",
" <td>0.000000</td>\n",
" <td>-0.017532</td>\n",
" <td>-0.017532</td>\n",
" <td>1.00000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-02-22</th>\n",
" <td>-0.007802</td>\n",
" <td>-0.025334</td>\n",
" <td>0.000000</td>\n",
" <td>-0.025334</td>\n",
" <td>-0.025334</td>\n",
" <td>0.99839</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-03-08</th>\n",
" <td>0.008656</td>\n",
" <td>-0.016678</td>\n",
" <td>0.000000</td>\n",
" <td>-0.025334</td>\n",
" <td>-0.025334</td>\n",
" <td>0.99537</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-03-22</th>\n",
" <td>-0.008940</td>\n",
" <td>-0.025618</td>\n",
" <td>-2.506659</td>\n",
" <td>-0.025618</td>\n",
" <td>-0.025618</td>\n",
" <td>0.99846</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-04-06</th>\n",
" <td>-0.001602</td>\n",
" <td>-0.027219</td>\n",
" <td>-2.480001</td>\n",
" <td>-0.027219</td>\n",
" <td>-0.027219</td>\n",
" <td>0.99846</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-04-20</th>\n",
" <td>-0.011132</td>\n",
" <td>-0.038351</td>\n",
" <td>-3.114281</td>\n",
" <td>-0.038351</td>\n",
" <td>-0.038351</td>\n",
" <td>0.99837</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-05-05</th>\n",
" <td>0.003350</td>\n",
" <td>-0.035001</td>\n",
" <td>-2.527191</td>\n",
" <td>-0.038351</td>\n",
" <td>-0.038351</td>\n",
" <td>0.99837</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-05-19</th>\n",
" <td>0.015650</td>\n",
" <td>-0.019351</td>\n",
" <td>-1.015388</td>\n",
" <td>-0.038351</td>\n",
" <td>-0.038351</td>\n",
" <td>0.99857</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-06-02</th>\n",
" <td>-0.009471</td>\n",
" <td>-0.028822</td>\n",
" <td>-1.405507</td>\n",
" <td>-0.038351</td>\n",
" <td>-0.038351</td>\n",
" <td>0.99857</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-06-21</th>\n",
" <td>0.017837</td>\n",
" <td>-0.010985</td>\n",
" <td>-0.428957</td>\n",
" <td>-0.038351</td>\n",
" <td>-0.038351</td>\n",
" <td>0.99856</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-07-05</th>\n",
" <td>0.015338</td>\n",
" <td>0.004352</td>\n",
" <td>0.149908</td>\n",
" <td>-0.038351</td>\n",
" <td>-0.038351</td>\n",
" <td>0.99856</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-07-19</th>\n",
" <td>0.009765</td>\n",
" <td>0.014118</td>\n",
" <td>0.457505</td>\n",
" <td>-0.038351</td>\n",
" <td>-0.038351</td>\n",
" <td>0.99864</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-08-02</th>\n",
" <td>0.004413</td>\n",
" <td>0.018531</td>\n",
" <td>0.579664</td>\n",
" <td>-0.038351</td>\n",
" <td>-0.038351</td>\n",
" <td>0.99864</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-08-16</th>\n",
" <td>-0.003519</td>\n",
" <td>0.015012</td>\n",
" <td>0.452692</td>\n",
" <td>-0.038351</td>\n",
" <td>-0.038351</td>\n",
" <td>0.99857</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-08-30</th>\n",
" <td>-0.002444</td>\n",
" <td>0.012568</td>\n",
" <td>0.367160</td>\n",
" <td>-0.038351</td>\n",
" <td>-0.038351</td>\n",
" <td>0.99857</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-09-13</th>\n",
" <td>-0.004987</td>\n",
" <td>0.007581</td>\n",
" <td>0.213571</td>\n",
" <td>-0.038351</td>\n",
" <td>-0.038351</td>\n",
" <td>0.99857</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-09-30</th>\n",
" <td>0.026630</td>\n",
" <td>0.034211</td>\n",
" <td>0.795850</td>\n",
" <td>-0.038351</td>\n",
" <td>-0.038351</td>\n",
" <td>0.99870</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-10-21</th>\n",
" <td>0.043495</td>\n",
" <td>0.077706</td>\n",
" <td>1.346488</td>\n",
" <td>-0.038351</td>\n",
" <td>-0.038351</td>\n",
" <td>0.99882</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-11-04</th>\n",
" <td>-0.011799</td>\n",
" <td>0.065906</td>\n",
" <td>1.084246</td>\n",
" <td>-0.038351</td>\n",
" <td>-0.038351</td>\n",
" <td>0.99882</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-11-18</th>\n",
" <td>-0.003795</td>\n",
" <td>0.062112</td>\n",
" <td>0.994030</td>\n",
" <td>-0.038351</td>\n",
" <td>-0.038351</td>\n",
" <td>0.99871</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-12-02</th>\n",
" <td>0.006415</td>\n",
" <td>0.068527</td>\n",
" <td>1.072145</td>\n",
" <td>-0.038351</td>\n",
" <td>-0.038351</td>\n",
" <td>0.99871</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-12-16</th>\n",
" <td>0.006895</td>\n",
" <td>0.075422</td>\n",
" <td>1.154278</td>\n",
" <td>-0.038351</td>\n",
" <td>-0.038351</td>\n",
" <td>0.99889</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-12-30</th>\n",
" <td>0.007962</td>\n",
" <td>0.083384</td>\n",
" <td>1.248169</td>\n",
" <td>-0.038351</td>\n",
" <td>-0.038351</td>\n",
" <td>0.99889</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2011-01-14</th>\n",
" <td>0.036374</td>\n",
" <td>0.119758</td>\n",
" <td>1.609959</td>\n",
" <td>-0.038351</td>\n",
" <td>-0.038351</td>\n",
" <td>0.99889</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2011-01-28</th>\n",
" <td>0.011736</td>\n",
" <td>0.131494</td>\n",
" <td>2.063452</td>\n",
" <td>-0.038351</td>\n",
" <td>-0.038351</td>\n",
" <td>0.99886</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2011-02-18</th>\n",
" <td>0.002573</td>\n",
" <td>0.134067</td>\n",
" <td>2.131904</td>\n",
" <td>-0.038351</td>\n",
" <td>-0.038351</td>\n",
" <td>0.99886</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2011-03-04</th>\n",
" <td>0.011372</td>\n",
" <td>0.145440</td>\n",
" <td>2.447034</td>\n",
" <td>-0.038351</td>\n",
" <td>-0.038351</td>\n",
" <td>0.99669</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2011-03-18</th>\n",
" <td>-0.004742</td>\n",
" <td>0.140698</td>\n",
" <td>2.225872</td>\n",
" <td>-0.038351</td>\n",
" <td>-0.038351</td>\n",
" <td>0.99883</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2016-12-19</th>\n",
" <td>0.009257</td>\n",
" <td>0.971322</td>\n",
" <td>3.611241</td>\n",
" <td>-0.006885</td>\n",
" <td>-0.084831</td>\n",
" <td>0.99999</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-01-03</th>\n",
" <td>0.006450</td>\n",
" <td>0.977772</td>\n",
" <td>3.455512</td>\n",
" <td>-0.006885</td>\n",
" <td>-0.084831</td>\n",
" <td>0.99999</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-01-17</th>\n",
" <td>0.014649</td>\n",
" <td>0.992421</td>\n",
" <td>5.117561</td>\n",
" <td>-0.006885</td>\n",
" <td>-0.084831</td>\n",
" <td>1.00015</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-02-07</th>\n",
" <td>0.004827</td>\n",
" <td>0.997248</td>\n",
" <td>5.000575</td>\n",
" <td>-0.006885</td>\n",
" <td>-0.084831</td>\n",
" <td>1.00015</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-02-21</th>\n",
" <td>0.014614</td>\n",
" <td>1.011862</td>\n",
" <td>5.206648</td>\n",
" <td>-0.006885</td>\n",
" <td>-0.084831</td>\n",
" <td>0.99995</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-03-07</th>\n",
" <td>-0.003735</td>\n",
" <td>1.008127</td>\n",
" <td>4.760648</td>\n",
" <td>-0.006885</td>\n",
" <td>-0.084831</td>\n",
" <td>0.99995</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-03-21</th>\n",
" <td>0.013155</td>\n",
" <td>1.021282</td>\n",
" <td>4.760259</td>\n",
" <td>-0.006885</td>\n",
" <td>-0.084831</td>\n",
" <td>0.99992</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-04-06</th>\n",
" <td>0.007310</td>\n",
" <td>1.028592</td>\n",
" <td>5.245859</td>\n",
" <td>-0.006885</td>\n",
" <td>-0.084831</td>\n",
" <td>0.99992</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-04-20</th>\n",
" <td>0.012077</td>\n",
" <td>1.040669</td>\n",
" <td>5.299875</td>\n",
" <td>-0.006885</td>\n",
" <td>-0.084831</td>\n",
" <td>1.00001</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-05-05</th>\n",
" <td>-0.013580</td>\n",
" <td>1.027089</td>\n",
" <td>4.043663</td>\n",
" <td>-0.013580</td>\n",
" <td>-0.084831</td>\n",
" <td>1.00001</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-05-19</th>\n",
" <td>-0.007600</td>\n",
" <td>1.019489</td>\n",
" <td>3.909182</td>\n",
" <td>-0.021180</td>\n",
" <td>-0.084831</td>\n",
" <td>1.00002</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-06-06</th>\n",
" <td>0.015585</td>\n",
" <td>1.035074</td>\n",
" <td>4.321257</td>\n",
" <td>-0.021180</td>\n",
" <td>-0.084831</td>\n",
" <td>1.00002</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-06-20</th>\n",
" <td>-0.002126</td>\n",
" <td>1.032948</td>\n",
" <td>4.101910</td>\n",
" <td>-0.021180</td>\n",
" <td>-0.084831</td>\n",
" <td>1.00001</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-07-04</th>\n",
" <td>0.024380</td>\n",
" <td>1.057328</td>\n",
" <td>4.088426</td>\n",
" <td>-0.021180</td>\n",
" <td>-0.084831</td>\n",
" <td>1.00001</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-07-18</th>\n",
" <td>0.031825</td>\n",
" <td>1.089153</td>\n",
" <td>4.038232</td>\n",
" <td>-0.021180</td>\n",
" <td>-0.084831</td>\n",
" <td>1.00009</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-08-01</th>\n",
" <td>0.013961</td>\n",
" <td>1.103114</td>\n",
" <td>4.008748</td>\n",
" <td>-0.021180</td>\n",
" <td>-0.084831</td>\n",
" <td>1.00009</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-08-15</th>\n",
" <td>-0.013408</td>\n",
" <td>1.089706</td>\n",
" <td>3.188122</td>\n",
" <td>-0.021180</td>\n",
" <td>-0.084831</td>\n",
" <td>1.00001</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-08-29</th>\n",
" <td>0.009143</td>\n",
" <td>1.098850</td>\n",
" <td>3.271891</td>\n",
" <td>-0.021180</td>\n",
" <td>-0.084831</td>\n",
" <td>1.00001</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-09-12</th>\n",
" <td>-0.007417</td>\n",
" <td>1.091433</td>\n",
" <td>2.951393</td>\n",
" <td>-0.021180</td>\n",
" <td>-0.084831</td>\n",
" <td>1.00001</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-09-26</th>\n",
" <td>0.010657</td>\n",
" <td>1.102090</td>\n",
" <td>3.098674</td>\n",
" <td>-0.021180</td>\n",
" <td>-0.084831</td>\n",
" <td>1.00006</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-10-17</th>\n",
" <td>0.000377</td>\n",
" <td>1.102467</td>\n",
" <td>3.124558</td>\n",
" <td>-0.021180</td>\n",
" <td>-0.084831</td>\n",
" <td>1.00006</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-10-31</th>\n",
" <td>0.003755</td>\n",
" <td>1.106222</td>\n",
" <td>2.925562</td>\n",
" <td>-0.021180</td>\n",
" <td>-0.084831</td>\n",
" <td>1.00001</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-11-14</th>\n",
" <td>0.001778</td>\n",
" <td>1.108000</td>\n",
" <td>2.916718</td>\n",
" <td>-0.021180</td>\n",
" <td>-0.084831</td>\n",
" <td>1.00002</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-11-28</th>\n",
" <td>0.013516</td>\n",
" <td>1.121517</td>\n",
" <td>3.130178</td>\n",
" <td>-0.021180</td>\n",
" <td>-0.084831</td>\n",
" <td>1.00002</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-12-12</th>\n",
" <td>-0.001865</td>\n",
" <td>1.119652</td>\n",
" <td>2.867689</td>\n",
" <td>-0.021180</td>\n",
" <td>-0.084831</td>\n",
" <td>0.99995</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-12-26</th>\n",
" <td>0.005692</td>\n",
" <td>1.125344</td>\n",
" <td>2.807121</td>\n",
" <td>-0.021180</td>\n",
" <td>-0.084831</td>\n",
" <td>0.99995</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2018-01-10</th>\n",
" <td>0.021872</td>\n",
" <td>1.147216</td>\n",
" <td>2.968750</td>\n",
" <td>-0.021180</td>\n",
" <td>-0.084831</td>\n",
" <td>0.99999</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2018-01-24</th>\n",
" <td>0.019254</td>\n",
" <td>1.166470</td>\n",
" <td>3.005144</td>\n",
" <td>-0.021180</td>\n",
" <td>-0.084831</td>\n",
" <td>1.00011</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2018-02-07</th>\n",
" <td>0.014057</td>\n",
" <td>1.180527</td>\n",
" <td>3.143895</td>\n",
" <td>-0.021180</td>\n",
" <td>-0.084831</td>\n",
" <td>1.00004</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2018-02-28</th>\n",
" <td>-0.010978</td>\n",
" <td>1.169549</td>\n",
" <td>2.604654</td>\n",
" <td>-0.021180</td>\n",
" <td>-0.084831</td>\n",
" <td>0.99994</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>199 rows × 6 columns</p>\n",
"</div>"
],
"text/plain": [
" daily_return cum_ret sharp drawdown max_drawn leverage\n",
"2010-01-04 0.000000 0.000000 0.000000 0.000000 0.000000 0.00000\n",
"2010-01-18 -0.015930 -0.015930 0.000000 -0.015930 -0.015930 1.00000\n",
"2010-02-01 -0.001602 -0.017532 0.000000 -0.017532 -0.017532 1.00000\n",
"2010-02-22 -0.007802 -0.025334 0.000000 -0.025334 -0.025334 0.99839\n",
"2010-03-08 0.008656 -0.016678 0.000000 -0.025334 -0.025334 0.99537\n",
"2010-03-22 -0.008940 -0.025618 -2.506659 -0.025618 -0.025618 0.99846\n",
"2010-04-06 -0.001602 -0.027219 -2.480001 -0.027219 -0.027219 0.99846\n",
"2010-04-20 -0.011132 -0.038351 -3.114281 -0.038351 -0.038351 0.99837\n",
"2010-05-05 0.003350 -0.035001 -2.527191 -0.038351 -0.038351 0.99837\n",
"2010-05-19 0.015650 -0.019351 -1.015388 -0.038351 -0.038351 0.99857\n",
"2010-06-02 -0.009471 -0.028822 -1.405507 -0.038351 -0.038351 0.99857\n",
"2010-06-21 0.017837 -0.010985 -0.428957 -0.038351 -0.038351 0.99856\n",
"2010-07-05 0.015338 0.004352 0.149908 -0.038351 -0.038351 0.99856\n",
"2010-07-19 0.009765 0.014118 0.457505 -0.038351 -0.038351 0.99864\n",
"2010-08-02 0.004413 0.018531 0.579664 -0.038351 -0.038351 0.99864\n",
"2010-08-16 -0.003519 0.015012 0.452692 -0.038351 -0.038351 0.99857\n",
"2010-08-30 -0.002444 0.012568 0.367160 -0.038351 -0.038351 0.99857\n",
"2010-09-13 -0.004987 0.007581 0.213571 -0.038351 -0.038351 0.99857\n",
"2010-09-30 0.026630 0.034211 0.795850 -0.038351 -0.038351 0.99870\n",
"2010-10-21 0.043495 0.077706 1.346488 -0.038351 -0.038351 0.99882\n",
"2010-11-04 -0.011799 0.065906 1.084246 -0.038351 -0.038351 0.99882\n",
"2010-11-18 -0.003795 0.062112 0.994030 -0.038351 -0.038351 0.99871\n",
"2010-12-02 0.006415 0.068527 1.072145 -0.038351 -0.038351 0.99871\n",
"2010-12-16 0.006895 0.075422 1.154278 -0.038351 -0.038351 0.99889\n",
"2010-12-30 0.007962 0.083384 1.248169 -0.038351 -0.038351 0.99889\n",
"2011-01-14 0.036374 0.119758 1.609959 -0.038351 -0.038351 0.99889\n",
"2011-01-28 0.011736 0.131494 2.063452 -0.038351 -0.038351 0.99886\n",
"2011-02-18 0.002573 0.134067 2.131904 -0.038351 -0.038351 0.99886\n",
"2011-03-04 0.011372 0.145440 2.447034 -0.038351 -0.038351 0.99669\n",
"2011-03-18 -0.004742 0.140698 2.225872 -0.038351 -0.038351 0.99883\n",
"... ... ... ... ... ... ...\n",
"2016-12-19 0.009257 0.971322 3.611241 -0.006885 -0.084831 0.99999\n",
"2017-01-03 0.006450 0.977772 3.455512 -0.006885 -0.084831 0.99999\n",
"2017-01-17 0.014649 0.992421 5.117561 -0.006885 -0.084831 1.00015\n",
"2017-02-07 0.004827 0.997248 5.000575 -0.006885 -0.084831 1.00015\n",
"2017-02-21 0.014614 1.011862 5.206648 -0.006885 -0.084831 0.99995\n",
"2017-03-07 -0.003735 1.008127 4.760648 -0.006885 -0.084831 0.99995\n",
"2017-03-21 0.013155 1.021282 4.760259 -0.006885 -0.084831 0.99992\n",
"2017-04-06 0.007310 1.028592 5.245859 -0.006885 -0.084831 0.99992\n",
"2017-04-20 0.012077 1.040669 5.299875 -0.006885 -0.084831 1.00001\n",
"2017-05-05 -0.013580 1.027089 4.043663 -0.013580 -0.084831 1.00001\n",
"2017-05-19 -0.007600 1.019489 3.909182 -0.021180 -0.084831 1.00002\n",
"2017-06-06 0.015585 1.035074 4.321257 -0.021180 -0.084831 1.00002\n",
"2017-06-20 -0.002126 1.032948 4.101910 -0.021180 -0.084831 1.00001\n",
"2017-07-04 0.024380 1.057328 4.088426 -0.021180 -0.084831 1.00001\n",
"2017-07-18 0.031825 1.089153 4.038232 -0.021180 -0.084831 1.00009\n",
"2017-08-01 0.013961 1.103114 4.008748 -0.021180 -0.084831 1.00009\n",
"2017-08-15 -0.013408 1.089706 3.188122 -0.021180 -0.084831 1.00001\n",
"2017-08-29 0.009143 1.098850 3.271891 -0.021180 -0.084831 1.00001\n",
"2017-09-12 -0.007417 1.091433 2.951393 -0.021180 -0.084831 1.00001\n",
"2017-09-26 0.010657 1.102090 3.098674 -0.021180 -0.084831 1.00006\n",
"2017-10-17 0.000377 1.102467 3.124558 -0.021180 -0.084831 1.00006\n",
"2017-10-31 0.003755 1.106222 2.925562 -0.021180 -0.084831 1.00001\n",
"2017-11-14 0.001778 1.108000 2.916718 -0.021180 -0.084831 1.00002\n",
"2017-11-28 0.013516 1.121517 3.130178 -0.021180 -0.084831 1.00002\n",
"2017-12-12 -0.001865 1.119652 2.867689 -0.021180 -0.084831 0.99995\n",
"2017-12-26 0.005692 1.125344 2.807121 -0.021180 -0.084831 0.99995\n",
"2018-01-10 0.021872 1.147216 2.968750 -0.021180 -0.084831 0.99999\n",
"2018-01-24 0.019254 1.166470 3.005144 -0.021180 -0.084831 1.00011\n",
"2018-02-07 0.014057 1.180527 3.143895 -0.021180 -0.084831 1.00004\n",
"2018-02-28 -0.010978 1.169549 2.604654 -0.021180 -0.084831 0.99994\n",
"\n",
"[199 rows x 6 columns]"
]
},
"execution_count": 55,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"res_df"
]
},
{
"cell_type": "code",
"execution_count": null,
"execution_count": 56,
"metadata": {},
"outputs": [],
"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>leverage</th>\n",
" <th>returns</th>\n",
" <th>turn_over</th>\n",
" <th>index</th>\n",
" <th>tc_cost</th>\n",
" <th>ret_after_tc</th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>2010-01-04</th>\n",
" <td>0.00000</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000</td>\n",
" <td>0.000000</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-01-18</th>\n",
" <td>1.00000</td>\n",
" <td>0.046003</td>\n",
" <td>1.927841</td>\n",
" <td>0.058077</td>\n",
" <td>0.003856</td>\n",
" <td>-0.015930</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-02-01</th>\n",
" <td>1.00000</td>\n",
" <td>-0.116628</td>\n",
" <td>0.400000</td>\n",
" <td>-0.115825</td>\n",
" <td>0.000800</td>\n",
" <td>-0.001602</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-02-22</th>\n",
" <td>0.99839</td>\n",
" <td>0.028905</td>\n",
" <td>0.420000</td>\n",
" <td>0.035925</td>\n",
" <td>0.000840</td>\n",
" <td>-0.007802</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-03-08</th>\n",
" <td>0.99537</td>\n",
" <td>0.053336</td>\n",
" <td>0.400000</td>\n",
" <td>0.044084</td>\n",
" <td>0.000800</td>\n",
" <td>0.008656</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-03-22</th>\n",
" <td>0.99846</td>\n",
" <td>-0.008443</td>\n",
" <td>0.400000</td>\n",
" <td>-0.000303</td>\n",
" <td>0.000800</td>\n",
" <td>-0.008940</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-04-06</th>\n",
" <td>0.99846</td>\n",
" <td>0.042204</td>\n",
" <td>0.400000</td>\n",
" <td>0.043072</td>\n",
" <td>0.000800</td>\n",
" <td>-0.001602</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-04-20</th>\n",
" <td>0.99837</td>\n",
" <td>-0.004134</td>\n",
" <td>0.400000</td>\n",
" <td>0.006209</td>\n",
" <td>0.000800</td>\n",
" <td>-0.011132</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-05-05</th>\n",
" <td>0.99837</td>\n",
" <td>-0.097597</td>\n",
" <td>0.400000</td>\n",
" <td>-0.101913</td>\n",
" <td>0.000800</td>\n",
" <td>0.003350</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-05-19</th>\n",
" <td>0.99857</td>\n",
" <td>-0.108175</td>\n",
" <td>0.400000</td>\n",
" <td>-0.124804</td>\n",
" <td>0.000800</td>\n",
" <td>0.015650</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-06-02</th>\n",
" <td>0.99857</td>\n",
" <td>0.029680</td>\n",
" <td>0.400000</td>\n",
" <td>0.038406</td>\n",
" <td>0.000800</td>\n",
" <td>-0.009471</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-06-21</th>\n",
" <td>0.99856</td>\n",
" <td>0.034693</td>\n",
" <td>0.400000</td>\n",
" <td>0.016080</td>\n",
" <td>0.000800</td>\n",
" <td>0.017837</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-07-05</th>\n",
" <td>0.99856</td>\n",
" <td>-0.100566</td>\n",
" <td>0.400000</td>\n",
" <td>-0.116871</td>\n",
" <td>0.000800</td>\n",
" <td>0.015338</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-07-19</th>\n",
" <td>0.99864</td>\n",
" <td>0.085609</td>\n",
" <td>0.400000</td>\n",
" <td>0.075146</td>\n",
" <td>0.000800</td>\n",
" <td>0.009765</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-08-02</th>\n",
" <td>0.99864</td>\n",
" <td>0.064639</td>\n",
" <td>0.400000</td>\n",
" <td>0.059507</td>\n",
" <td>0.000800</td>\n",
" <td>0.004413</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-08-16</th>\n",
" <td>0.99857</td>\n",
" <td>0.058397</td>\n",
" <td>0.462835</td>\n",
" <td>0.061077</td>\n",
" <td>0.000926</td>\n",
" <td>-0.003519</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-08-30</th>\n",
" <td>0.99857</td>\n",
" <td>0.027406</td>\n",
" <td>0.400000</td>\n",
" <td>0.029092</td>\n",
" <td>0.000800</td>\n",
" <td>-0.002444</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-09-13</th>\n",
" <td>0.99857</td>\n",
" <td>0.041752</td>\n",
" <td>0.400000</td>\n",
" <td>0.046005</td>\n",
" <td>0.000800</td>\n",
" <td>-0.004987</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-09-30</th>\n",
" <td>0.99870</td>\n",
" <td>0.019627</td>\n",
" <td>0.400000</td>\n",
" <td>-0.007814</td>\n",
" <td>0.000800</td>\n",
" <td>0.026630</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-10-21</th>\n",
" <td>0.99882</td>\n",
" <td>0.067060</td>\n",
" <td>0.400000</td>\n",
" <td>0.022792</td>\n",
" <td>0.000800</td>\n",
" <td>0.043495</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-11-04</th>\n",
" <td>0.99882</td>\n",
" <td>0.074099</td>\n",
" <td>0.400000</td>\n",
" <td>0.085199</td>\n",
" <td>0.000800</td>\n",
" <td>-0.011799</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-11-18</th>\n",
" <td>0.99871</td>\n",
" <td>-0.047362</td>\n",
" <td>0.400000</td>\n",
" <td>-0.044425</td>\n",
" <td>0.000800</td>\n",
" <td>-0.003795</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-12-02</th>\n",
" <td>0.99871</td>\n",
" <td>0.011023</td>\n",
" <td>0.400000</td>\n",
" <td>0.003812</td>\n",
" <td>0.000800</td>\n",
" <td>0.006415</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-12-16</th>\n",
" <td>0.99889</td>\n",
" <td>0.032452</td>\n",
" <td>0.400000</td>\n",
" <td>0.024784</td>\n",
" <td>0.000800</td>\n",
" <td>0.006895</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2010-12-30</th>\n",
" <td>0.99889</td>\n",
" <td>-0.048569</td>\n",
" <td>0.400000</td>\n",
" <td>-0.057394</td>\n",
" <td>0.000800</td>\n",
" <td>0.007962</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2011-01-14</th>\n",
" <td>0.99889</td>\n",
" <td>-0.050939</td>\n",
" <td>0.400000</td>\n",
" <td>-0.088210</td>\n",
" <td>0.000800</td>\n",
" <td>0.036374</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2011-01-28</th>\n",
" <td>0.99886</td>\n",
" <td>0.032432</td>\n",
" <td>0.400000</td>\n",
" <td>0.019919</td>\n",
" <td>0.000800</td>\n",
" <td>0.011736</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2011-02-18</th>\n",
" <td>0.99886</td>\n",
" <td>0.092855</td>\n",
" <td>0.400000</td>\n",
" <td>0.089584</td>\n",
" <td>0.000800</td>\n",
" <td>0.002573</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2011-03-04</th>\n",
" <td>0.99669</td>\n",
" <td>0.030961</td>\n",
" <td>0.461941</td>\n",
" <td>0.018727</td>\n",
" <td>0.000924</td>\n",
" <td>0.011372</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2011-03-18</th>\n",
" <td>0.99883</td>\n",
" <td>-0.014116</td>\n",
" <td>0.400000</td>\n",
" <td>-0.010187</td>\n",
" <td>0.000800</td>\n",
" <td>-0.004742</td>\n",
" </tr>\n",
" <tr>\n",
" <th>...</th>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" <td>...</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2016-12-19</th>\n",
" <td>0.99999</td>\n",
" <td>-0.019694</td>\n",
" <td>0.400000</td>\n",
" <td>-0.029751</td>\n",
" <td>0.000800</td>\n",
" <td>0.009257</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-01-03</th>\n",
" <td>0.99999</td>\n",
" <td>0.022045</td>\n",
" <td>0.400000</td>\n",
" <td>0.014796</td>\n",
" <td>0.000800</td>\n",
" <td>0.006450</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-01-17</th>\n",
" <td>1.00015</td>\n",
" <td>-0.036656</td>\n",
" <td>0.526692</td>\n",
" <td>-0.052350</td>\n",
" <td>0.001053</td>\n",
" <td>0.014649</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-02-07</th>\n",
" <td>1.00015</td>\n",
" <td>0.041704</td>\n",
" <td>0.400000</td>\n",
" <td>0.036071</td>\n",
" <td>0.000800</td>\n",
" <td>0.004827</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-02-21</th>\n",
" <td>0.99995</td>\n",
" <td>0.044033</td>\n",
" <td>0.400000</td>\n",
" <td>0.028620</td>\n",
" <td>0.000800</td>\n",
" <td>0.014614</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-03-07</th>\n",
" <td>0.99995</td>\n",
" <td>0.000585</td>\n",
" <td>0.400000</td>\n",
" <td>0.003521</td>\n",
" <td>0.000800</td>\n",
" <td>-0.003735</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-03-21</th>\n",
" <td>0.99992</td>\n",
" <td>0.014388</td>\n",
" <td>0.400000</td>\n",
" <td>0.000433</td>\n",
" <td>0.000800</td>\n",
" <td>0.013155</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-04-06</th>\n",
" <td>0.99992</td>\n",
" <td>0.020196</td>\n",
" <td>0.400000</td>\n",
" <td>0.012087</td>\n",
" <td>0.000800</td>\n",
" <td>0.007310</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-04-20</th>\n",
" <td>1.00001</td>\n",
" <td>-0.030300</td>\n",
" <td>0.400000</td>\n",
" <td>-0.043176</td>\n",
" <td>0.000800</td>\n",
" <td>0.012077</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-05-05</th>\n",
" <td>1.00001</td>\n",
" <td>-0.065753</td>\n",
" <td>0.400000</td>\n",
" <td>-0.052973</td>\n",
" <td>0.000800</td>\n",
" <td>-0.013580</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-05-19</th>\n",
" <td>1.00002</td>\n",
" <td>-0.021411</td>\n",
" <td>0.400000</td>\n",
" <td>-0.014611</td>\n",
" <td>0.000800</td>\n",
" <td>-0.007600</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-06-06</th>\n",
" <td>1.00002</td>\n",
" <td>0.027560</td>\n",
" <td>0.400000</td>\n",
" <td>0.011175</td>\n",
" <td>0.000800</td>\n",
" <td>0.015585</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-06-20</th>\n",
" <td>1.00001</td>\n",
" <td>0.019150</td>\n",
" <td>0.400000</td>\n",
" <td>0.020476</td>\n",
" <td>0.000800</td>\n",
" <td>-0.002126</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-07-04</th>\n",
" <td>1.00001</td>\n",
" <td>0.044044</td>\n",
" <td>0.400000</td>\n",
" <td>0.018864</td>\n",
" <td>0.000800</td>\n",
" <td>0.024380</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-07-18</th>\n",
" <td>1.00009</td>\n",
" <td>0.010873</td>\n",
" <td>0.511670</td>\n",
" <td>-0.021973</td>\n",
" <td>0.001023</td>\n",
" <td>0.031825</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-08-01</th>\n",
" <td>1.00009</td>\n",
" <td>0.046041</td>\n",
" <td>0.400000</td>\n",
" <td>0.031278</td>\n",
" <td>0.000800</td>\n",
" <td>0.013961</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-08-15</th>\n",
" <td>1.00001</td>\n",
" <td>-0.001945</td>\n",
" <td>0.400000</td>\n",
" <td>0.010663</td>\n",
" <td>0.000800</td>\n",
" <td>-0.013408</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-08-29</th>\n",
" <td>1.00001</td>\n",
" <td>0.031043</td>\n",
" <td>0.400000</td>\n",
" <td>0.021099</td>\n",
" <td>0.000800</td>\n",
" <td>0.009143</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-09-12</th>\n",
" <td>1.00001</td>\n",
" <td>0.028566</td>\n",
" <td>0.400000</td>\n",
" <td>0.035183</td>\n",
" <td>0.000800</td>\n",
" <td>-0.007417</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-09-26</th>\n",
" <td>1.00006</td>\n",
" <td>-0.003795</td>\n",
" <td>0.400000</td>\n",
" <td>-0.015251</td>\n",
" <td>0.000800</td>\n",
" <td>0.010657</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-10-17</th>\n",
" <td>1.00006</td>\n",
" <td>-0.001820</td>\n",
" <td>0.400000</td>\n",
" <td>-0.002997</td>\n",
" <td>0.000800</td>\n",
" <td>0.000377</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-10-31</th>\n",
" <td>1.00001</td>\n",
" <td>0.002962</td>\n",
" <td>0.400000</td>\n",
" <td>-0.001593</td>\n",
" <td>0.000800</td>\n",
" <td>0.003755</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-11-14</th>\n",
" <td>1.00002</td>\n",
" <td>0.000244</td>\n",
" <td>0.400000</td>\n",
" <td>-0.002333</td>\n",
" <td>0.000800</td>\n",
" <td>0.001778</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-11-28</th>\n",
" <td>1.00002</td>\n",
" <td>-0.019798</td>\n",
" <td>0.400000</td>\n",
" <td>-0.034113</td>\n",
" <td>0.000800</td>\n",
" <td>0.013516</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-12-12</th>\n",
" <td>0.99995</td>\n",
" <td>-0.007562</td>\n",
" <td>0.400000</td>\n",
" <td>-0.006497</td>\n",
" <td>0.000800</td>\n",
" <td>-0.001865</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-12-26</th>\n",
" <td>0.99995</td>\n",
" <td>-0.010001</td>\n",
" <td>0.527553</td>\n",
" <td>-0.016749</td>\n",
" <td>0.001055</td>\n",
" <td>0.005692</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2018-01-10</th>\n",
" <td>0.99999</td>\n",
" <td>0.062804</td>\n",
" <td>0.400000</td>\n",
" <td>0.040133</td>\n",
" <td>0.000800</td>\n",
" <td>0.021872</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2018-01-24</th>\n",
" <td>1.00011</td>\n",
" <td>0.013303</td>\n",
" <td>0.400000</td>\n",
" <td>-0.006750</td>\n",
" <td>0.000800</td>\n",
" <td>0.019254</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2018-02-07</th>\n",
" <td>1.00004</td>\n",
" <td>-0.086680</td>\n",
" <td>0.400000</td>\n",
" <td>-0.101533</td>\n",
" <td>0.000800</td>\n",
" <td>0.014057</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2018-02-28</th>\n",
" <td>0.99994</td>\n",
" <td>0.044443</td>\n",
" <td>0.400000</td>\n",
" <td>0.054624</td>\n",
" <td>0.000800</td>\n",
" <td>-0.010978</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"<p>199 rows × 6 columns</p>\n",
"</div>"
],
"text/plain": [
" leverage returns turn_over index tc_cost ret_after_tc\n",
"2010-01-04 0.00000 0.000000 0.000000 0.000000 0.000000 0.000000\n",
"2010-01-18 1.00000 0.046003 1.927841 0.058077 0.003856 -0.015930\n",
"2010-02-01 1.00000 -0.116628 0.400000 -0.115825 0.000800 -0.001602\n",
"2010-02-22 0.99839 0.028905 0.420000 0.035925 0.000840 -0.007802\n",
"2010-03-08 0.99537 0.053336 0.400000 0.044084 0.000800 0.008656\n",
"2010-03-22 0.99846 -0.008443 0.400000 -0.000303 0.000800 -0.008940\n",
"2010-04-06 0.99846 0.042204 0.400000 0.043072 0.000800 -0.001602\n",
"2010-04-20 0.99837 -0.004134 0.400000 0.006209 0.000800 -0.011132\n",
"2010-05-05 0.99837 -0.097597 0.400000 -0.101913 0.000800 0.003350\n",
"2010-05-19 0.99857 -0.108175 0.400000 -0.124804 0.000800 0.015650\n",
"2010-06-02 0.99857 0.029680 0.400000 0.038406 0.000800 -0.009471\n",
"2010-06-21 0.99856 0.034693 0.400000 0.016080 0.000800 0.017837\n",
"2010-07-05 0.99856 -0.100566 0.400000 -0.116871 0.000800 0.015338\n",
"2010-07-19 0.99864 0.085609 0.400000 0.075146 0.000800 0.009765\n",
"2010-08-02 0.99864 0.064639 0.400000 0.059507 0.000800 0.004413\n",
"2010-08-16 0.99857 0.058397 0.462835 0.061077 0.000926 -0.003519\n",
"2010-08-30 0.99857 0.027406 0.400000 0.029092 0.000800 -0.002444\n",
"2010-09-13 0.99857 0.041752 0.400000 0.046005 0.000800 -0.004987\n",
"2010-09-30 0.99870 0.019627 0.400000 -0.007814 0.000800 0.026630\n",
"2010-10-21 0.99882 0.067060 0.400000 0.022792 0.000800 0.043495\n",
"2010-11-04 0.99882 0.074099 0.400000 0.085199 0.000800 -0.011799\n",
"2010-11-18 0.99871 -0.047362 0.400000 -0.044425 0.000800 -0.003795\n",
"2010-12-02 0.99871 0.011023 0.400000 0.003812 0.000800 0.006415\n",
"2010-12-16 0.99889 0.032452 0.400000 0.024784 0.000800 0.006895\n",
"2010-12-30 0.99889 -0.048569 0.400000 -0.057394 0.000800 0.007962\n",
"2011-01-14 0.99889 -0.050939 0.400000 -0.088210 0.000800 0.036374\n",
"2011-01-28 0.99886 0.032432 0.400000 0.019919 0.000800 0.011736\n",
"2011-02-18 0.99886 0.092855 0.400000 0.089584 0.000800 0.002573\n",
"2011-03-04 0.99669 0.030961 0.461941 0.018727 0.000924 0.011372\n",
"2011-03-18 0.99883 -0.014116 0.400000 -0.010187 0.000800 -0.004742\n",
"... ... ... ... ... ... ...\n",
"2016-12-19 0.99999 -0.019694 0.400000 -0.029751 0.000800 0.009257\n",
"2017-01-03 0.99999 0.022045 0.400000 0.014796 0.000800 0.006450\n",
"2017-01-17 1.00015 -0.036656 0.526692 -0.052350 0.001053 0.014649\n",
"2017-02-07 1.00015 0.041704 0.400000 0.036071 0.000800 0.004827\n",
"2017-02-21 0.99995 0.044033 0.400000 0.028620 0.000800 0.014614\n",
"2017-03-07 0.99995 0.000585 0.400000 0.003521 0.000800 -0.003735\n",
"2017-03-21 0.99992 0.014388 0.400000 0.000433 0.000800 0.013155\n",
"2017-04-06 0.99992 0.020196 0.400000 0.012087 0.000800 0.007310\n",
"2017-04-20 1.00001 -0.030300 0.400000 -0.043176 0.000800 0.012077\n",
"2017-05-05 1.00001 -0.065753 0.400000 -0.052973 0.000800 -0.013580\n",
"2017-05-19 1.00002 -0.021411 0.400000 -0.014611 0.000800 -0.007600\n",
"2017-06-06 1.00002 0.027560 0.400000 0.011175 0.000800 0.015585\n",
"2017-06-20 1.00001 0.019150 0.400000 0.020476 0.000800 -0.002126\n",
"2017-07-04 1.00001 0.044044 0.400000 0.018864 0.000800 0.024380\n",
"2017-07-18 1.00009 0.010873 0.511670 -0.021973 0.001023 0.031825\n",
"2017-08-01 1.00009 0.046041 0.400000 0.031278 0.000800 0.013961\n",
"2017-08-15 1.00001 -0.001945 0.400000 0.010663 0.000800 -0.013408\n",
"2017-08-29 1.00001 0.031043 0.400000 0.021099 0.000800 0.009143\n",
"2017-09-12 1.00001 0.028566 0.400000 0.035183 0.000800 -0.007417\n",
"2017-09-26 1.00006 -0.003795 0.400000 -0.015251 0.000800 0.010657\n",
"2017-10-17 1.00006 -0.001820 0.400000 -0.002997 0.000800 0.000377\n",
"2017-10-31 1.00001 0.002962 0.400000 -0.001593 0.000800 0.003755\n",
"2017-11-14 1.00002 0.000244 0.400000 -0.002333 0.000800 0.001778\n",
"2017-11-28 1.00002 -0.019798 0.400000 -0.034113 0.000800 0.013516\n",
"2017-12-12 0.99995 -0.007562 0.400000 -0.006497 0.000800 -0.001865\n",
"2017-12-26 0.99995 -0.010001 0.527553 -0.016749 0.001055 0.005692\n",
"2018-01-10 0.99999 0.062804 0.400000 0.040133 0.000800 0.021872\n",
"2018-01-24 1.00011 0.013303 0.400000 -0.006750 0.000800 0.019254\n",
"2018-02-07 1.00004 -0.086680 0.400000 -0.101533 0.000800 0.014057\n",
"2018-02-28 0.99994 0.044443 0.400000 0.054624 0.000800 -0.010978\n",
"\n",
"[199 rows x 6 columns]"
]
},
"execution_count": 56,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ret_df"
]
......
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> The methodolegy is similar to The Barra China Equity Model (CNE5)'s documentation"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"%matplotlib inline\n",
"\n",
"import numpy as np\n",
"import pandas as pd\n",
"from matplotlib import pyplot as plt\n",
"import statsmodels.api as sm\n",
"from alphamind.api import *\n",
"from PyFin.api import *\n",
"from notebook_utilities import cross_section_analysis\n",
"\n",
"plt.style.use('ggplot')"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"\"\"\"\n",
"Back test parameter settings\n",
"\"\"\"\n",
"\n",
"start_date = '2017-01-01'\n",
"end_date = '2018-02-28'\n",
"category = 'sw_adj'\n",
"level = 1\n",
"freq = '20b'\n",
"universe = Universe('custom', ['zz800'])\n",
"data_source = 'postgres+psycopg2://postgres:A12345678!@10.63.6.220/alpha'\n",
"\n",
"horizon = map_freq(freq)\n",
"ref_dates = makeSchedule(start_date, end_date, freq, 'china.sse')\n",
"engine = SqlEngine(data_source)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"\"\"\"\n",
"Factor Model\n",
"\"\"\"\n",
"factor_name = 'SIZE'"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"\"\"\"\n",
"Constraints\n",
"\"\"\"\n",
"\n",
"risk_names = list(set(risk_styles).difference({factor_name}))\n",
"industry_names = list(set(industry_styles).difference({factor_name}))\n",
"constraint_risk = risk_names + industry_names + macro_styles\n",
"\n",
"b_type = []\n",
"l_val = []\n",
"u_val = []\n",
"\n",
"for name in constraint_risk:\n",
" if name in set(risk_styles):\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(1.0)\n",
" u_val.append(1.0)\n",
" \n",
"linear_bounds = create_box_bounds(constraint_risk, b_type, l_val, u_val)"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"2018-03-05 13:28:03,536 - ALPHA_MIND - INFO - 2010-01-04 00:00:00 is finished with 798 stocks for SIZE\n",
"2018-03-05 13:28:03,926 - ALPHA_MIND - INFO - 2010-02-01 00:00:00 is finished with 799 stocks for SIZE\n",
"2018-03-05 13:28:04,321 - ALPHA_MIND - INFO - 2010-03-08 00:00:00 is finished with 799 stocks for SIZE\n",
"2018-03-05 13:28:04,714 - ALPHA_MIND - INFO - 2010-04-06 00:00:00 is finished with 799 stocks for SIZE\n",
"2018-03-05 13:28:05,111 - ALPHA_MIND - INFO - 2010-05-05 00:00:00 is finished with 799 stocks for SIZE\n",
"2018-03-05 13:28:05,592 - ALPHA_MIND - INFO - 2010-06-02 00:00:00 is finished with 799 stocks for SIZE\n",
"2018-03-05 13:28:06,005 - ALPHA_MIND - INFO - 2010-07-05 00:00:00 is finished with 799 stocks for SIZE\n",
"2018-03-05 13:28:06,436 - ALPHA_MIND - INFO - 2010-08-02 00:00:00 is finished with 799 stocks for SIZE\n",
"2018-03-05 13:28:06,836 - ALPHA_MIND - INFO - 2010-08-30 00:00:00 is finished with 799 stocks for SIZE\n",
"2018-03-05 13:28:07,244 - ALPHA_MIND - INFO - 2010-09-30 00:00:00 is finished with 799 stocks for SIZE\n",
"2018-03-05 13:28:07,646 - ALPHA_MIND - INFO - 2010-11-04 00:00:00 is finished with 799 stocks for SIZE\n",
"2018-03-05 13:28:08,073 - ALPHA_MIND - INFO - 2010-12-02 00:00:00 is finished with 799 stocks for SIZE\n",
"2018-03-05 13:28:08,492 - ALPHA_MIND - INFO - 2010-12-30 00:00:00 is finished with 799 stocks for SIZE\n",
"2018-03-05 13:28:09,006 - ALPHA_MIND - INFO - 2011-01-28 00:00:00 is finished with 799 stocks for SIZE\n",
"2018-03-05 13:28:09,434 - ALPHA_MIND - INFO - 2011-03-04 00:00:00 is finished with 798 stocks for SIZE\n",
"2018-03-05 13:28:09,857 - ALPHA_MIND - INFO - 2011-04-01 00:00:00 is finished with 798 stocks for SIZE\n",
"2018-03-05 13:28:10,275 - ALPHA_MIND - INFO - 2011-05-04 00:00:00 is finished with 798 stocks for SIZE\n",
"2018-03-05 13:28:10,696 - ALPHA_MIND - INFO - 2011-06-01 00:00:00 is finished with 798 stocks for SIZE\n",
"2018-03-05 13:28:11,098 - ALPHA_MIND - INFO - 2011-06-30 00:00:00 is finished with 798 stocks for SIZE\n",
"2018-03-05 13:28:11,511 - ALPHA_MIND - INFO - 2011-07-28 00:00:00 is finished with 798 stocks for SIZE\n",
"2018-03-05 13:28:11,908 - ALPHA_MIND - INFO - 2011-08-25 00:00:00 is finished with 796 stocks for SIZE\n",
"2018-03-05 13:28:12,408 - ALPHA_MIND - INFO - 2011-09-23 00:00:00 is finished with 797 stocks for SIZE\n",
"2018-03-05 13:28:12,819 - ALPHA_MIND - INFO - 2011-10-28 00:00:00 is finished with 798 stocks for SIZE\n",
"2018-03-05 13:28:13,269 - ALPHA_MIND - INFO - 2011-11-25 00:00:00 is finished with 798 stocks for SIZE\n",
"2018-03-05 13:28:13,699 - ALPHA_MIND - INFO - 2011-12-23 00:00:00 is finished with 798 stocks for SIZE\n",
"2018-03-05 13:28:14,144 - ALPHA_MIND - INFO - 2012-01-31 00:00:00 is finished with 798 stocks for SIZE\n",
"2018-03-05 13:28:14,574 - ALPHA_MIND - INFO - 2012-02-28 00:00:00 is finished with 796 stocks for SIZE\n",
"2018-03-05 13:28:15,006 - ALPHA_MIND - INFO - 2012-03-27 00:00:00 is finished with 796 stocks for SIZE\n",
"2018-03-05 13:28:15,443 - ALPHA_MIND - INFO - 2012-04-27 00:00:00 is finished with 798 stocks for SIZE\n",
"2018-03-05 13:28:15,962 - ALPHA_MIND - INFO - 2012-05-29 00:00:00 is finished with 798 stocks for SIZE\n",
"2018-03-05 13:28:16,383 - ALPHA_MIND - INFO - 2012-06-27 00:00:00 is finished with 798 stocks for SIZE\n",
"2018-03-05 13:28:16,824 - ALPHA_MIND - INFO - 2012-07-25 00:00:00 is finished with 798 stocks for SIZE\n",
"2018-03-05 13:28:17,233 - ALPHA_MIND - INFO - 2012-08-22 00:00:00 is finished with 799 stocks for SIZE\n",
"2018-03-05 13:28:17,663 - ALPHA_MIND - INFO - 2012-09-19 00:00:00 is finished with 799 stocks for SIZE\n",
"2018-03-05 13:28:18,076 - ALPHA_MIND - INFO - 2012-10-24 00:00:00 is finished with 799 stocks for SIZE\n",
"2018-03-05 13:28:18,497 - ALPHA_MIND - INFO - 2012-11-21 00:00:00 is finished with 799 stocks for SIZE\n",
"2018-03-05 13:28:18,925 - ALPHA_MIND - INFO - 2012-12-19 00:00:00 is finished with 799 stocks for SIZE\n",
"2018-03-05 13:28:19,346 - ALPHA_MIND - INFO - 2013-01-21 00:00:00 is finished with 799 stocks for SIZE\n",
"2018-03-05 13:28:19,869 - ALPHA_MIND - INFO - 2013-02-25 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:20,278 - ALPHA_MIND - INFO - 2013-03-25 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:20,700 - ALPHA_MIND - INFO - 2013-04-24 00:00:00 is finished with 799 stocks for SIZE\n",
"2018-03-05 13:28:21,111 - ALPHA_MIND - INFO - 2013-05-27 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:21,536 - ALPHA_MIND - INFO - 2013-06-27 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:21,967 - ALPHA_MIND - INFO - 2013-07-25 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:22,417 - ALPHA_MIND - INFO - 2013-08-22 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:22,875 - ALPHA_MIND - INFO - 2013-09-23 00:00:00 is finished with 799 stocks for SIZE\n",
"2018-03-05 13:28:23,398 - ALPHA_MIND - INFO - 2013-10-28 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:23,849 - ALPHA_MIND - INFO - 2013-11-25 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:24,274 - ALPHA_MIND - INFO - 2013-12-23 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:24,698 - ALPHA_MIND - INFO - 2014-01-21 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:25,128 - ALPHA_MIND - INFO - 2014-02-25 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:25,553 - ALPHA_MIND - INFO - 2014-03-25 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:25,976 - ALPHA_MIND - INFO - 2014-04-23 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:26,405 - ALPHA_MIND - INFO - 2014-05-23 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:26,823 - ALPHA_MIND - INFO - 2014-06-23 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:27,322 - ALPHA_MIND - INFO - 2014-07-21 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:27,748 - ALPHA_MIND - INFO - 2014-08-18 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:28,181 - ALPHA_MIND - INFO - 2014-09-16 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:28,604 - ALPHA_MIND - INFO - 2014-10-21 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:29,038 - ALPHA_MIND - INFO - 2014-11-18 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:29,478 - ALPHA_MIND - INFO - 2014-12-16 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:29,908 - ALPHA_MIND - INFO - 2015-01-15 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:30,352 - ALPHA_MIND - INFO - 2015-02-12 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:30,952 - ALPHA_MIND - INFO - 2015-03-19 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:31,386 - ALPHA_MIND - INFO - 2015-04-17 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:31,834 - ALPHA_MIND - INFO - 2015-05-18 00:00:00 is finished with 798 stocks for SIZE\n",
"2018-03-05 13:28:32,274 - ALPHA_MIND - INFO - 2015-06-15 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:32,718 - ALPHA_MIND - INFO - 2015-07-14 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:33,192 - ALPHA_MIND - INFO - 2015-08-11 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:33,635 - ALPHA_MIND - INFO - 2015-09-10 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:34,055 - ALPHA_MIND - INFO - 2015-10-15 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:34,589 - ALPHA_MIND - INFO - 2015-11-12 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:35,032 - ALPHA_MIND - INFO - 2015-12-10 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:35,464 - ALPHA_MIND - INFO - 2016-01-08 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:35,910 - ALPHA_MIND - INFO - 2016-02-05 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:36,361 - ALPHA_MIND - INFO - 2016-03-11 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:36,818 - ALPHA_MIND - INFO - 2016-04-11 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:37,272 - ALPHA_MIND - INFO - 2016-05-10 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:37,726 - ALPHA_MIND - INFO - 2016-06-07 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:38,278 - ALPHA_MIND - INFO - 2016-07-07 00:00:00 is finished with 800 stocks for SIZE\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"2018-03-05 13:28:38,747 - ALPHA_MIND - INFO - 2016-08-04 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:39,190 - ALPHA_MIND - INFO - 2016-09-01 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:39,640 - ALPHA_MIND - INFO - 2016-10-10 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:40,081 - ALPHA_MIND - INFO - 2016-11-07 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:40,536 - ALPHA_MIND - INFO - 2016-12-05 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:40,977 - ALPHA_MIND - INFO - 2017-01-03 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:41,438 - ALPHA_MIND - INFO - 2017-02-07 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:41,959 - ALPHA_MIND - INFO - 2017-03-07 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:42,403 - ALPHA_MIND - INFO - 2017-04-06 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:42,850 - ALPHA_MIND - INFO - 2017-05-05 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:43,300 - ALPHA_MIND - INFO - 2017-06-06 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:43,747 - ALPHA_MIND - INFO - 2017-07-04 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:44,197 - ALPHA_MIND - INFO - 2017-08-01 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:44,663 - ALPHA_MIND - INFO - 2017-08-29 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:45,158 - ALPHA_MIND - INFO - 2017-09-26 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:45,732 - ALPHA_MIND - INFO - 2017-10-31 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:46,201 - ALPHA_MIND - INFO - 2017-11-28 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:46,662 - ALPHA_MIND - INFO - 2017-12-26 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:47,118 - ALPHA_MIND - INFO - 2018-01-24 00:00:00 is finished with 800 stocks for SIZE\n",
"2018-03-05 13:28:47,402 - ALPHA_MIND - INFO - 2018-02-28 00:00:00 is finished with 800 stocks for SIZE\n"
]
}
],
"source": [
"df = pd.DataFrame(columns=['ret', 'ic', 't.'])\n",
"\n",
"for ref_date in ref_dates:\n",
" df.loc[ref_date, :] = cross_section_analysis(ref_date,\n",
" factor_name,\n",
" universe,\n",
" horizon,\n",
" constraint_risk,\n",
" linear_bounds,\n",
" lbound=-0.01,\n",
" ubound=0.01,\n",
" engine=engine)"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<matplotlib.axes._subplots.AxesSubplot at 0x21543a5a278>"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "iVBORw0KGgoAAAANSUhEUgAAAz4AAAGECAYAAAD3BfXiAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMS4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvNQv5yAAAIABJREFUeJzs3XecVNXdx/HP726h9112WVBUQIqgSO8gzd7DVR977KgxJkaxPbE+EmMSW9QQjTVGr72DgkpVARVFQayI9C59l+We549Zicgu7O7MZWZnv+/Xyxc7M+ee85sjCX45955jzjlERERERETSmZfsAkRERERERKKm4CMiIiIiImlPwUdERERERNKego+IiIiIiKQ9BR8REREREUl7Cj4iIiIiIpL2FHxERERERCTtKfiIiIiIiEjaU/AREREREZG0l5nsAnbDJbsAERERERFJeba7BqkefFi8eHGySyAnJ4eVK1cmu4y0pLmNluY3Oprb6Ghuo6O5jY7mNjqa2+iky9wWFBSUq51udRMRERERkbSn4CMiIiIiImlPwUdERERERNKego+IiIiIiKQ9BR8REREREUl7Cj4iIiIiIpL2FHxERERERCTtKfiIiIiIiEjaU/AREREREZG0p+AjIiIiIiJpT8FHRERERETSnoKPiIiIiIikPQWfcij6YjbhtLeTXYaIiIiIiFRSZrILqAo2vfQf3EfTcG07Yk2aJrscERERERGpIK34lEO9X/8GMMKn/pnsUkREREREpBIUfMohIzcfO/pkmPUB7pPpyS5HREREREQqSMGnnGzoMdBsL8L/jMEVFia7HBERERERqQAFn3KyzCy8Uy+CVctxrz+T7HJERERERKQCFHwqwNp2xHodghv3PG7pwmSXIyIiIiIi5aTgU0E24izIrkH45D9wziW7HBERERERKQcFnwqy+o2w40+HuZ/gZkyObBy3bi1uw7rI+hcRERERqU4UfCrBBh4KLVvjgodwmzYmvH8XbiP80yjCq88jHP8ybtu2hI8hIiIiIlKdKPhUgnkZsY0O1q3Fvfxk4geY/SEsXwyNc3FPP0h46+9w33yR+HFERERERKoJBZ9Ksn3bYAMPw739Gu7rOQntO3z7VWjYBO/6O/EuHAXr1xH+6SrCx/+O27g+oWOJiIiIiFQHCj5xsONOh4aN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\n",
"text/plain": [
"<matplotlib.figure.Figure at 0x2154239c9b0>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"df.index = pd.to_datetime(df.index)\n",
"df['ret'].cumsum().plot(figsize=(14, 7))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
},
{
"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"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
# -*- coding: utf-8 -*-
"""
Created on 2018-3-5
@author: cheng.li
"""
import numpy as np
import pandas as pd
import statsmodels.api as sm
from alphamind.api import (
SqlEngine, LinearConstraints, er_portfolio_analysis, alpha_logger
)
def cross_section_analysis(ref_date,
factor_name,
universe,
horizon,
constraint_risk,
linear_bounds,
lbound,
ubound,
engine):
codes = engine.fetch_codes(ref_date, universe)
risk_exposure = engine.fetch_risk_model(ref_date, codes)[1][['code'] + constraint_risk]
factor_data = engine.fetch_factor(ref_date, factor_name, codes)
industry_matrix = engine.fetch_industry_matrix(ref_date, codes, 'sw_adj', 1)
total_data = pd.merge(factor_data, risk_exposure, on='code')
total_data = pd.merge(total_data, industry_matrix, on='code').dropna()
total_risk_exp = total_data[constraint_risk]
constraints = LinearConstraints(linear_bounds, total_risk_exp)
er = total_data[factor_name].values
industry = total_data.industry_name.values
target_pos, _ = er_portfolio_analysis(er,
industry,
None,
constraints,
False,
None,
method='risk_neutral',
lbound=lbound*np.ones(len(er)),
ubound=ubound*np.ones(len(er)))
codes = total_data.code.tolist()
target_pos['code'] = codes
dx_returns = engine.fetch_dx_return(ref_date, codes, horizon=horizon, offset=1)
target_pos = pd.merge(target_pos, dx_returns, on=['code'])
activate_weight = target_pos.weight.values
excess_return = np.exp(target_pos.dx.values) - 1.
port_ret = np.log(activate_weight @ excess_return + 1.)
ic = np.corrcoef(excess_return, activate_weight)[0, 1]
x = sm.add_constant(activate_weight)
results = sm.OLS(excess_return, x).fit()
t_stats = results.tvalues[1]
alpha_logger.info(f"{ref_date} is finished with {len(target_pos)} stocks for {factor_name}")
return port_ret, ic, t_stats
if __name__ == '__main__':
from alphamind.api import (
Universe, map_freq, risk_styles, industry_styles, macro_styles, BoundaryType, create_box_bounds
)
"""
Back test parameter settings
"""
start_date = '2010-01-01'
end_date = '2018-02-28'
category = 'sw_adj'
level = 1
freq = '20b'
universe = Universe('custom', ['zz800'])
data_source = 'postgres+psycopg2://postgres:A12345678!@10.63.6.220/alpha'
engine = SqlEngine(data_source)
horizon = map_freq(freq)
"""
Factor Model
"""
factor_name = 'SIZE'
"""
Constraints
"""
risk_names = list(set(risk_styles).difference({factor_name}))
industry_names = list(set(industry_styles).difference({factor_name}))
constraint_risk = risk_names + industry_names + macro_styles
b_type = []
l_val = []
u_val = []
for name in constraint_risk:
if name in set(risk_styles):
b_type.append(BoundaryType.ABSOLUTE)
l_val.append(0.0)
u_val.append(0.0)
else:
b_type.append(BoundaryType.RELATIVE)
l_val.append(1.0)
u_val.append(1.0)
linear_bounds = create_box_bounds(constraint_risk, b_type, l_val, u_val)
ref_date = '2018-02-08'
df = pd.DataFrame(columns=['ret', 'ic', 't.'])
print(cross_section_analysis(ref_date,
factor_name,
universe,
horizon,
constraint_risk,
linear_bounds,
lbound=-0.01,
ubound=0.01,
engine=engine))
\ No newline at end of file
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