背景
- 本文用来快速理清常见量化思路,其官方提供的多因子此策略白皮书很适合上手。
流程
一 、 获取因子数据
# 优矿里提供了400多个因子数据,将诸如TTM类似的标准化算法工程化,可利用DataAPI直接获取
pe = DataAPI.MktStockFactorsOneDayGet(secID=set_universe('HS300'),tradeDate=u"20160922",field=u"secID,tradeDate,PE",pandas="1").set_index('secID')
pe.head()
# pe.plot(figsize=(14,5))
secID | tradeDate | PE |
---|---|---|
000001.XSHE | 2016-09-22 | 6.9680 |
000002.XSHE | 2016-09-22 | 16.0035 |
000063.XSHE | 2016-09-22 | 18.3675 |
000069.XSHE | 2016-09-22 | 11.9858 |
000100.XSHE | 2016-09-22 | 26.9261 |
二、因子分析
1、去极值
import numpy as np
# 去极值winsorize
after_winsorize = winsorize(pe['PE'].to_dict())
pe['winsorized PE'] = np.nan
pe.loc[after_winsorize.keys(),'winsorized PE'] = after_winsorize.values()
2、标准化
## 标准化standardize
after_standardize = standardize(pe['winsorized PE'].to_dict())
pe['standardized PE'] = np.nan
pe.loc[after_standardize.keys(),'standardized PE'] = after_standardize.values()
三、构建组合
选股
- 整体分位数:从所有备选股中选择因子得分大于某个分位数
- 风格分位数:以行业为例,在同一行业中选择因子得分大于某个分位数
权重
- 等权重:最常见也最通用
- 市值加权:中证指数编制时的权重考虑因素就是市值
- 风格中性权重:权重由市值和股票所属行业在指数中的权重决定
四、组合构建
# 信号合成
signal = (0.5*pd.Series(signal_pe)).add(0.5*pd.Series(signal_lcap), fill_value=0.0)
# 组合构建
wts = simple_long_only(dict(signal), yesterday)
- 相当于0.5pe与0.5lcap合成信号
- 学习下series的add方法,fill_value就是都空的时候的默认值。
>>> a = pd.Series([1, 1, 1, np.nan], index=['a', 'b', 'c', 'd'])
>>> a
a 1.0
b 1.0
c 1.0
d NaN
dtype: float64
>>> b = pd.Series([1, np.nan, 1, np.nan], index=['a', 'b', 'd', 'e'])
>>> b
a 1.0
b NaN
d 1.0
e NaN
dtype: float64
>>> a.add(b, fill_value=0)
a 2.0
b 1.0
c 1.0
d 1.0
e NaN
dtype: float64
- 这个simple_long_only返回个字典,键是股票名,value是价值权重,也就是说到时候下单按照股票和价值权重买。
# 交易部分
account = context.get_account('fantasy_account')
current_position = account.get_positions(exclude_halt=True)
target_position = wts.keys()
# 卖出当前持有,但目标持仓没有的部分
for stock in set(current_position).difference(target_position):
account.order_to(stock, 0)
# 根据目标持仓权重,逐一委托下单
for stock in target_position:
account.order_pct_to(stock, wts[stock])
思考
- 去极值中性化标准化,去极值还好,中性化标准化基本就是黑箱,不知道咋算的,可能有人写篇文章告诉咋算的也迷糊到底需要把因子这么做吗?
- 如果是快速简单写个验证用simple_long_only比较好,需要各种设参数需要用long_only,这函数也是黑箱,比较复杂。
- 实际学习时候,最好所有实现能自己完成,对比官方函数的区别。