Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
A
alpha-mind
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Dr.李
alpha-mind
Commits
e9a25f85
Commit
e9a25f85
authored
Jan 17, 2019
by
Dr.李
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
update example
parent
a9579e26
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
165 additions
and
34 deletions
+165
-34
Quick Start 4 - Step By Step Alpha Modeling.ipynb
notebooks/Quick Start 4 - Step By Step Alpha Modeling.ipynb
+165
-34
No files found.
notebooks/Quick Start 4 - Step By Step Alpha Modeling.ipynb
View file @
e9a25f85
...
...
@@ -33,9 +33,25 @@
"rc('legend', **{'frameon': False})"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1. 组合构造要求\n",
"--------------------------\n",
"\n",
"* 股票池:中证800\n",
"* 交易日:2019年1月15日\n",
"* alpha因子:EPS\n",
"* 行业分类:申万行业一级分类\n",
"* 基准指数:中证800指数\n",
"* 行业暴露:各行业保持中性\n",
"* 个股暴露:个股最大主动暴露不超过2%"
]
},
{
"cell_type": "code",
"execution_count":
95
,
"execution_count":
140
,
"metadata": {},
"outputs": [],
"source": [
...
...
@@ -49,16 +65,32 @@
"con = sa.create_engine(os.environ['DB_URI'])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2. 获取基本数据\n",
"----------------------\n",
"\n",
"获取在2019年1月15日中证800成分股的EPS因子值"
]
},
{
"cell_type": "code",
"execution_count":
96
,
"execution_count":
142
,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Wall time: 457 ms\n"
" code EPS\n",
"0 1 1.5885\n",
"1 2 1.6891\n",
"2 6 0.4970\n",
"3 8 0.0592\n",
"4 9 0.0612\n",
"Wall time: 150 ms\n"
]
}
],
...
...
@@ -73,19 +105,32 @@
" getattr(Universe, universe_name) == 1))\n",
"\n",
"factors = pd.read_sql(query, con=con)\n",
"factors.head()"
"print(factors.head())"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"获取在2019年1月15日中证800成分股的行业分类"
]
},
{
"cell_type": "code",
"execution_count":
97
,
"execution_count":
143
,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Wall time: 160 ms\n"
" code industryName1\n",
"0 1 银行\n",
"1 2 房地产\n",
"2 6 房地产\n",
"3 8 机械设备\n",
"4 9 综合\n",
"Wall time: 140 ms\n"
]
}
],
...
...
@@ -101,72 +146,123 @@
" getattr(Universe, universe_name) == 1))\n",
"\n",
"industry = pd.read_sql(query, con=con)\n",
"
industry.head(
)"
"
print(industry.head()
)"
]
},
{
"cell_type": "code",
"execution_count": 98,
"cell_type": "markdown",
"metadata": {},
"outputs": [],
"source": [
"df = pd.merge(factors, industry, on=['code'], how='inner').dropna()\n",
"industry_dummy = pd.get_dummies(df.industryName1)"
"获取在2019年1月15日中证800成分股的指数权重"
]
},
{
"cell_type": "code",
"execution_count":
99
,
"execution_count":
148
,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Wall time:
1
ms\n"
"Wall time:
413
ms\n"
]
}
],
"source": [
"%%time\n",
"\n",
"df['neutralized_factor'] = neutralize(industry_dummy.values.astype(float), df[factor].values).flatten()"
"big_table = outerjoin(IndexComponent, Universe, and_(IndexComponent.trade_date == Universe.trade_date,\n",
" IndexComponent.code == Universe.code))\n",
"\n",
"query = select([IndexComponent.code, (IndexComponent.weight / 100.).label('index_weight')]) \\\n",
" .where(and_(IndexComponent.trade_date == trade_date,\n",
" IndexComponent.indexCode == benchmark_code))\n",
"\n",
"index_components = pd.read_sql(query, con=con)\n",
"print(index_components.head())"
]
},
{
"cell_type": "code",
"execution_count": 149,
"metadata": {},
"outputs": [],
"source": [
"df = pd.merge(factors, industry, on=['code'], how='inner').dropna()\n",
"df = pd.merge(df, index_components, on=['code'], how='inner').dropna()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 3. 因子中性化\n",
"-------------------"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"将行业数据(categorical)数据转为dummy矩阵"
]
},
{
"cell_type": "code",
"execution_count": 100,
"execution_count": 98,
"metadata": {},
"outputs": [],
"source": [
"industry_dummy = pd.get_dummies(df.industryName1)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"使用行业dummy矩阵对因子做中性化,得到**行业中性化后**的因子:`neutralized_factor`"
]
},
{
"cell_type": "code",
"execution_count": 152,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Wall time: 113 ms\n"
" code neutralized_factor\n",
"0 1 0.253364\n",
"1 2 0.990502\n",
"2 6 -0.201598\n",
"3 8 -0.396290\n",
"4 9 -0.168950\n",
"Wall time: 2.96 ms\n"
]
}
],
"source": [
"%%time\n",
"\n",
"big_table = outerjoin(IndexComponent, Universe, and_(IndexComponent.trade_date == Universe.trade_date,\n",
" IndexComponent.code == Universe.code))\n",
"\n",
"query = select([IndexComponent.code, (IndexComponent.weight / 100.).label('index_weight')]) \\\n",
" .where(and_(IndexComponent.trade_date == trade_date,\n",
" IndexComponent.indexCode == benchmark_code))\n",
"\n",
"index_components = pd.read_sql(query, con=con)\n",
"index_components.head()"
"df['neutralized_factor'] = neutralize(industry_dummy.values.astype(float), df[factor].values).flatten()\n",
"print(df[['code', 'neutralized_factor']].head())"
]
},
{
"cell_type": "code",
"execution_count": 101,
"cell_type": "markdown",
"metadata": {},
"outputs": [],
"source": [
"df = pd.merge(df, index_components, on=['code'], how='inner').dropna()"
"## 4. 组合构建\n",
"-----------------------------\n",
"\n",
"使用alpha-mind中的线性优化器来做组合构建,在做组合构建的时候,我们已生成**主动权重**为目标(主动权重 = 组合权重 - 指数权重)。优化器,以最大化组合的预期收益为目标,同时达到以下的限制条件:\n",
"\n",
"* 最小主动权重-2%,同时保证不做空(所以单只股票最小主动权重为-2%与其指数权重负值中的较大值);\n",
"* 最大主动权重2%;\n",
"* 行业主动暴露为0;\n",
"* 主动权重加和为0,保证组合总权重与指数总权重一致。"
]
},
{
...
...
@@ -185,6 +281,17 @@
" np.concatenate((industry_up_bounds, [0.])),)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"输出结果中:\n",
"\n",
"* `status`:优化状态;\n",
"* `optimized_values`:组合预期收益的负值;\n",
"* `weights`:组合中股票的主动权重"
]
},
{
"cell_type": "code",
"execution_count": 112,
...
...
@@ -208,9 +315,19 @@
" risk_target)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"计算最终持仓:\n",
"\n",
"* `portfolio_weight`:组合权重\n",
"* `active_weight`:主动权重"
]
},
{
"cell_type": "code",
"execution_count": 1
29
,
"execution_count": 1
57
,
"metadata": {},
"outputs": [],
"source": [
...
...
@@ -218,18 +335,25 @@
"df['active_weight'] = weights"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"我们可以通过计算行业权重,并与指数的行业权重进行比较,验证行业暴露确实为0"
]
},
{
"cell_type": "code",
"execution_count": 1
37
,
"execution_count": 1
58
,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"<matplotlib.axes._subplots.AxesSubplot at 0x193c
2c75f
28>"
"<matplotlib.axes._subplots.AxesSubplot at 0x193c
44451
28>"
]
},
"execution_count": 1
37
,
"execution_count": 1
58
,
"metadata": {},
"output_type": "execute_result"
},
...
...
@@ -250,6 +374,13 @@
"df.groupby('industryName1').sum().plot.bar(y=['index_weight', 'portfolio_weight'], figsize=(14, 7))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"我们也可以通过观察中性化后因子值,观察个股权重与因子值的关系"
]
},
{
"cell_type": "code",
"execution_count": 139,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment